/*====================================================================* Copyright (c) 2013,2021 Qualcomm Technologies, Inc. All Rights Reserved. Confidential and Proprietary - Qualcomm Technologies, Inc. ****************************************************************** 2013 Qualcomm Atheros, Inc. *--------------------------------------------------------------------*/ /*====================================================================* * * signed pev_cm_set_key (struct session * session, struct channel * channel, struct message * message); * * slac.h * * PEV-HLE sets the NMK and NID on PEV-PLC using CM_SET_KEY.REQ; * the NMK and NID must match those provided by EVSE-HLE using * CM_SLAC_MATCH.CNF; * * Contributor(s): * Charles Maier * *--------------------------------------------------------------------*/ #ifndef PEV_CM_SET_KEY_SOURCE #define PEV_CM_SET_KEY_SOURCE #include #include "../ether/channel.h" #include "../tools/memory.h" #include "../tools/error.h" #include "../tools/flags.h" #include "../mme/qualcomm.h" #include "../mme/homeplug.h" #include "../slac/slac.h" #include "../plc/plc.h" signed pev_cm_set_key (struct session * session, struct channel * channel, struct message * message) { #ifndef __GNUC__ #pragma pack(push,1) #endif struct __packed cm_set_key_request { struct ethernet_hdr ethernet; struct homeplug_fmi homeplug; uint8_t KEYTYPE; uint32_t MYNONCE; uint32_t YOURNONCE; uint8_t PID; uint16_t PRN; uint8_t PMN; uint8_t CCOCAP; uint8_t NID [SLAC_NID_LEN]; uint8_t NEWEKS; uint8_t NEWKEY [SLAC_NMK_LEN]; uint8_t RSVD [3]; } * request = (struct cm_set_key_request *) (message); struct __packed cm_set_key_confirm { struct ethernet_hdr ethernet; struct homeplug_fmi homeplug; uint8_t RESULT; uint32_t MYNONCE; uint32_t YOURNONCE; uint8_t PID; uint16_t PRN; uint8_t PMN; uint8_t CCOCAP; uint8_t RSVD [27]; } * confirm = (struct cm_set_key_confirm *) (message); #ifndef __GNUC__ #pragma pack (pop) #endif memset (message, 0, sizeof (* message)); debug (0, __func__, "--> CM_SET_KEY.REQ"); EthernetHeader (& request->ethernet, channel->peer, channel->host, channel->type); HomePlugHeader1 (& request->homeplug, HOMEPLUG_MMV, (CM_SET_KEY | MMTYPE_REQ)); request->KEYTYPE = SLAC_CM_SETKEY_KEYTYPE; memset (& request->MYNONCE, 0xAA, sizeof (request->MYNONCE)); memset (& request->YOURNONCE, 0x00, sizeof (request->YOURNONCE)); request->PID = SLAC_CM_SETKEY_PID; request->PRN = HTOLE16 (SLAC_CM_SETKEY_PRN); request->PMN = SLAC_CM_SETKEY_PMN; request->CCOCAP = SLAC_CM_SETKEY_CCO; memcpy (request->NID, session->NID, sizeof (request->NID)); request->NEWEKS = SLAC_CM_SETKEY_EKS; memcpy (request->NEWKEY, session->NMK, sizeof (request->NEWKEY)); #if SLAC_DEBUG if (_anyset (session->flags, SLAC_VERBOSE)) { char string [1024]; debug (0, __func__, "CM_SET_KEY.KEYTYPE %d", request->KEYTYPE); debug (0, __func__, "CM_SET_KEY.MYNONCE %s", hexstring (string, sizeof (string), & request->MYNONCE, sizeof (request->MYNONCE))); debug (0, __func__, "CM_SET_KEY.YOURNONCE %s", hexstring (string, sizeof (string), & request->YOURNONCE, sizeof (request->MYNONCE))); debug (0, __func__, "CM_SET_KEY.PID %d", request->PID); debug (0, __func__, "CM_SET_KEY.PRN %d", LE32TOH (request->PRN)); debug (0, __func__, "CM_SET_KEY.PMN %d", request->PMN); debug (0, __func__, "CM_SET_KEY.CCoCAP %d", request->CCOCAP); debug (0, __func__, "CM_SET_KEY.NID %s", HEXSTRING (string, request->NID)); debug (0, __func__, "CM_SET_KEY.NEWEKS %d", request->NEWEKS); debug (0, __func__, "CM_SET_KEY.NEWKEY %s", HEXSTRING (string, request->NEWKEY)); } #endif if (sendpacket (channel, request, sizeof (* request)) <= 0) { return (debug (1, __func__, CHANNEL_CANTSEND)); } while (readpacket (channel, confirm, sizeof (* confirm)) > 0) { if (ntohs (confirm->ethernet.MTYPE) != ETH_P_HPAV) { debug (session->exit, __func__, "Ignore MTYPE 0x%04X", htons (confirm->ethernet.MTYPE)); continue; } if (confirm->homeplug.MMV != HOMEPLUG_MMV) { debug (session->exit, __func__, "Ignore MMV 0x%02X", confirm->homeplug.MMV); continue; } if (LE32TOH (confirm->homeplug.MMTYPE) != (CM_SET_KEY | MMTYPE_CNF)) { debug (session->exit, __func__, "Ignore MMTYPE 0x%04X", LE32TOH (confirm->homeplug.MMTYPE)); continue; } debug (0, __func__, "<-- CM_SET_KEY.CNF"); if (! confirm->RESULT) { return (debug (session->exit, __func__, "Can't set keys")); } #if SLAC_DEBUG if (_anyset (session->flags, SLAC_VERBOSE)) { char string [1024]; debug (0, __func__, "CM_SET_KEY.RESULT %d", confirm->RESULT); debug (0, __func__, "CM_SET_KEY.MYNONCE %s", hexstring (string, sizeof (string), & confirm->MYNONCE, sizeof (confirm->MYNONCE))); debug (0, __func__, "CM_SET_KEY.YOURNONCE %s", hexstring (string, sizeof (string), & confirm->YOURNONCE, sizeof (confirm->MYNONCE))); debug (0, __func__, "CM_SET_KEY.PID %d", confirm->PID); debug (0, __func__, "CM_SET_KEY.PRN %d", LE32TOH (confirm->PRN)); debug (0, __func__, "CM_SET_KEY.PMN %d", confirm->PMN); debug (0, __func__, "CM_SET_KEY.CCoCAP %d", confirm->CCOCAP); } #endif return (0); } return (debug (session->exit, __func__, "<-- CM_SET_KEY.CNF ?")); } signed pev_cm_set_key_req(struct session* session, struct channel* channel, struct message* message) { #ifndef __GNUC__ #pragma pack(push,1) #endif struct __packed cm_set_key_request { struct ethernet_hdr ethernet; struct homeplug_fmi homeplug; uint8_t KEYTYPE; uint32_t MYNONCE; uint32_t YOURNONCE; uint8_t PID; uint16_t PRN; uint8_t PMN; uint8_t CCOCAP; uint8_t NID[SLAC_NID_LEN]; uint8_t NEWEKS; uint8_t NEWKEY[SLAC_NMK_LEN]; uint8_t RSVD[3]; } *request = (struct cm_set_key_request*)(message); #ifndef __GNUC__ #pragma pack (pop) #endif memset(message, 0, sizeof(*message)); debug(0, __func__, "--> CM_SET_KEY.REQ"); EthernetHeader(&request->ethernet, channel->peer, channel->host, channel->type); HomePlugHeader1(&request->homeplug, HOMEPLUG_MMV, (CM_SET_KEY | MMTYPE_REQ)); request->KEYTYPE = SLAC_CM_SETKEY_KEYTYPE; memset(&request->MYNONCE, 0xAA, sizeof(request->MYNONCE)); memset(&request->YOURNONCE, 0x00, sizeof(request->YOURNONCE)); request->PID = SLAC_CM_SETKEY_PID; request->PRN = HTOLE16(SLAC_CM_SETKEY_PRN); request->PMN = SLAC_CM_SETKEY_PMN; request->CCOCAP = SLAC_CM_SETKEY_CCO; memcpy(request->NID, session->NID, sizeof(request->NID)); request->NEWEKS = SLAC_CM_SETKEY_EKS; memcpy(request->NEWKEY, session->NMK, sizeof(request->NEWKEY)); #if SLAC_DEBUG if (_anyset(session->flags, SLAC_VERBOSE)) { char string[1024]; debug(0, __func__, "CM_SET_KEY.KEYTYPE %d", request->KEYTYPE); debug(0, __func__, "CM_SET_KEY.MYNONCE %s", hexstring(string, sizeof(string), &request->MYNONCE, sizeof(request->MYNONCE))); debug(0, __func__, "CM_SET_KEY.YOURNONCE %s", hexstring(string, sizeof(string), &request->YOURNONCE, sizeof(request->MYNONCE))); debug(0, __func__, "CM_SET_KEY.PID %d", request->PID); debug(0, __func__, "CM_SET_KEY.PRN %d", LE32TOH(request->PRN)); debug(0, __func__, "CM_SET_KEY.PMN %d", request->PMN); debug(0, __func__, "CM_SET_KEY.CCoCAP %d", request->CCOCAP); debug(0, __func__, "CM_SET_KEY.NID %s", HEXSTRING(string, request->NID)); debug(0, __func__, "CM_SET_KEY.NEWEKS %d", request->NEWEKS); debug(0, __func__, "CM_SET_KEY.NEWKEY %s", HEXSTRING(string, request->NEWKEY)); } #endif if (sendpacket(channel, request, sizeof(*request)) <= 0) { return (debug(1, __func__, CHANNEL_CANTSEND)); } return 0; } signed pev_cm_set_key_cnf(struct session* session, struct channel* channel, struct message* message) { #ifndef __GNUC__ #pragma pack(push,1) #endif struct __packed cm_set_key_confirm { struct ethernet_hdr ethernet; struct homeplug_fmi homeplug; uint8_t RESULT; uint32_t MYNONCE; uint32_t YOURNONCE; uint8_t PID; uint16_t PRN; uint8_t PMN; uint8_t CCOCAP; uint8_t RSVD[27]; } *confirm = (struct cm_set_key_confirm*)(message); #ifndef __GNUC__ #pragma pack (pop) #endif debug(0, __func__, "<-- CM_SET_KEY.CNF"); if (!confirm->RESULT) { return (debug(session->exit, __func__, "Can't set keys")); } #if SLAC_DEBUG if (_anyset(session->flags, SLAC_VERBOSE)) { char string[1024]; debug(0, __func__, "CM_SET_KEY.RESULT %d", confirm->RESULT); debug(0, __func__, "CM_SET_KEY.MYNOUNCE %s", hexstring(string, sizeof(string), &confirm->MYNONCE, sizeof(confirm->MYNONCE))); debug(0, __func__, "CM_SET_KEY.YOURNOUNCE %s", hexstring(string, sizeof(string), &confirm->YOURNONCE, sizeof(confirm->MYNONCE))); debug(0, __func__, "CM_SET_KEY.PID %d", confirm->PID); debug(0, __func__, "CM_SET_KEY.PRN %d", LE32TOH(confirm->PRN)); debug(0, __func__, "CM_SET_KEY.PMN %d", confirm->PMN); debug(0, __func__, "CM_SET_KEY.CCoCAP %d", confirm->CCOCAP); } #endif return (0); } signed pev_cm_get_key_req(struct plc* plc, void* NID) { struct channel* channel = (struct channel*)(plc->channel); struct message* message = (struct message*)(plc->message); #ifndef __GNUC__ #pragma pack(push,1) #endif struct __packed cm_get_key_request { struct ethernet_hdr ethernet; struct homeplug_fmi homeplug; uint8_t REQTYPE; uint8_t KEYTYPE; uint8_t NID[SLAC_NID_LEN]; uint32_t MYNONCE; uint8_t PID; uint16_t PRN; uint8_t PMN; uint8_t HASHKEY[384]; } *request = (struct cm_get_key_request*)(message); #ifndef __GNUC__ #pragma pack (pop) #endif memset(message, 0, sizeof(*message)); debug(0, __func__, "--> CM_GET_KEY.REQ"); EthernetHeader(&request->ethernet, channel->peer, channel->host, channel->type); HomePlugHeader1(&request->homeplug, HOMEPLUG_MMV, (CM_GET_KEY | MMTYPE_REQ)); request->REQTYPE = 0x00; //0x00 - Direct request->KEYTYPE = SLAC_CM_SETKEY_KEYTYPE; // keytype is 0x01 for NMK memcpy(request->NID, (uint8_t*)NID, sizeof(request->NID)); memset(&request->MYNONCE, 0xAA, sizeof(request->MYNONCE)); request->PID = SLAC_CM_SETKEY_PID; request->PRN = HTOLE16(SLAC_CM_SETKEY_PRN); request->PMN = SLAC_CM_SETKEY_PMN; if (sendpacket(channel, request, sizeof(*request)) <= 0) { return (debug(1, __func__, CHANNEL_CANTSEND)); } return 0; } signed process_pev_cm_get_key_cnf(struct plc* plc, uint8_t* NMK, uint8_t* NID) { struct message* message = (struct message*)(plc->message); #ifndef __GNUC__ #pragma pack(push,1) #endif struct __packed cm_get_key_confirm { struct ethernet_hdr ethernet; struct homeplug_fmi homeplug; uint8_t RESULT; uint8_t KEYTYPE; uint32_t MYNONCE; uint32_t YOURNONCE; uint8_t NID[SLAC_NID_LEN]; uint8_t EKS; uint8_t PID; uint16_t PRN; uint8_t PMN; uint8_t NMK[SLAC_NMK_LEN]; } *confirm = (struct cm_get_key_confirm*)(message); #ifndef __GNUC__ #pragma pack (pop) #endif debug(0, __func__, "<-- CM_GET_KEY.CNF"); if (!confirm->RESULT) { return (debug(1, __func__, "Can't get keys")); } if(!memcmp(confirm->NID, NID, SLAC_NID_LEN)) { return (debug(1, __func__, "NID not matching")); } if((confirm->KEYTYPE != SLAC_CM_SETKEY_KEYTYPE) || (confirm->EKS != SLAC_CM_SETKEY_EKS)) { printf("key type %0x , eks %0x", confirm->KEYTYPE, confirm->EKS); return (debug(1, __func__, "keytype or eks don't match")); } memcpy(confirm->NMK, NMK, SLAC_NMK_LEN); return 0; } #endif