static void wsfSecHciCback(hciEvt_t *pEvent) { wsfSecQueueBuf_t *pBuf; wsfHandlerId_t handlerId; /* handle random number event */ if (pEvent->hdr.event == HCI_LE_RAND_CMD_CMPL_CBACK_EVT) { /* move up data by eight bytes */ memcpy(&wsfSecCb.rand[HCI_RAND_LEN], wsfSecCb.rand, HCI_RAND_LEN); /* copy new data to random data buffer */ memcpy(wsfSecCb.rand, pEvent->leRandCmdCmpl.randNum, HCI_RAND_LEN); } /* handle encryption event */ else if (pEvent->hdr.event == HCI_LE_ENCRYPT_CMD_CMPL_CBACK_EVT) { /* dequeue parameter buffer */ if ((pBuf = WsfMsgDeq(&wsfSecCb.aesQueue, &handlerId)) != NULL) { /* set encrypted data pointer and copy */ pBuf->aes.pCiphertext = pBuf->ciphertext; Calc128Cpy(pBuf->aes.pCiphertext, pEvent->leEncryptCmdCmpl.data); /* send message */ WsfMsgSend(handlerId, pBuf); } else { WSF_TRACE_WARN0("WSF sec queue empty!"); } } }
bool_t smpProcRcvKey(smpCcb_t *pCcb, dmSecKeyIndEvt_t *pKeyInd, uint8_t *pBuf, uint8_t keyDist) { bool_t keyIndReady = FALSE; bool_t done = FALSE; uint8_t cmdCode; /* go to start of packet */ pBuf += L2C_PAYLOAD_START; cmdCode = *pBuf++; if (cmdCode == SMP_CMD_ENC_INFO) { /* parse encryption information packet */ Calc128Cpy(pKeyInd->keyData.ltk.key, pBuf); } else if (cmdCode == SMP_CMD_MASTER_ID) { /* parse master identification packet */ BSTREAM_TO_UINT16(pKeyInd->keyData.ltk.ediv, pBuf); memcpy(pKeyInd->keyData.ltk.rand, pBuf, SMP_RAND8_LEN); pKeyInd->secLevel = (pCcb->auth & SMP_AUTH_MITM_FLAG) ? DM_SEC_LEVEL_ENC_AUTH : DM_SEC_LEVEL_ENC; pKeyInd->type = DM_KEY_PEER_LTK; keyIndReady = TRUE; } else if (cmdCode == SMP_CMD_ID_INFO) { /* parse identity information packet */ Calc128Cpy(pKeyInd->keyData.irk.key, pBuf); } else if (cmdCode == SMP_CMD_ID_ADDR_INFO) { /* parse identity address information packet */ BSTREAM_TO_UINT8(pKeyInd->keyData.irk.addrType, pBuf); BSTREAM_TO_BDA(pKeyInd->keyData.irk.bdAddr, pBuf); pKeyInd->type = DM_KEY_IRK; keyIndReady = TRUE; } else if (cmdCode == SMP_CMD_SIGN_INFO) { /* parse signing information packet */ Calc128Cpy(pKeyInd->keyData.csrk.key, pBuf); pKeyInd->type = DM_KEY_CSRK; keyIndReady = TRUE; } /* set up to receive next key */ /* if just got first part of LTK or IRK */ if (pCcb->nextCmdCode == SMP_CMD_ENC_INFO || pCcb->nextCmdCode == SMP_CMD_ID_INFO) { /* wait for second part of LTK or IRK info */ pCcb->nextCmdCode++; } /* else if got LTK and need IRK */ else if ((keyDist & SMP_KEY_DIST_ID) && (pCcb->nextCmdCode == SMP_CMD_MASTER_ID)) { /* wait for first part of IRK */ pCcb->nextCmdCode = SMP_CMD_ID_INFO; } /* else if got LTK or IRK and need SRK */ else if ((keyDist & SMP_KEY_DIST_SIGN) && (pCcb->nextCmdCode == SMP_CMD_MASTER_ID || pCcb->nextCmdCode == SMP_CMD_ID_ADDR_INFO)) { /* wait for SRK */ pCcb->nextCmdCode = SMP_CMD_SIGN_INFO; } else { /* done receiving keys */ done = TRUE; } /* call callback if key ready */ if (keyIndReady) { pKeyInd->hdr.event = DM_SEC_KEY_IND; DmSmpCbackExec((dmEvt_t *) pKeyInd); } return done; }
bool_t smpSendKey(smpCcb_t *pCcb, uint8_t keyDist) { uint8_t *pPkt; uint8_t *p; wsfMsgHdr_t *pHdr; if (smpCb.lescSupported && pCcb->pScCcb->lescEnabled && pCcb->lastSentKey == 0) { dmSecKeyIndEvt_t keyInd; /* pass LTK to app via DM */ if (DmConnRole(pCcb->connId) == DM_ROLE_MASTER) { keyInd.type = DM_KEY_PEER_LTK; } else { keyInd.type = DM_KEY_LOCAL_LTK; } keyInd.hdr.event = DM_SEC_KEY_IND; keyInd.hdr.param = pCcb->connId; keyInd.secLevel = smpGetScSecLevel(pCcb); keyInd.keyData.ltk.ediv = 0; memset(keyInd.keyData.ltk.rand, 0, SMP_RAND8_LEN); Calc128Cpy(keyInd.keyData.ltk.key, pCcb->pScCcb->pLtk->ltk_t); DmSmpCbackExec((dmEvt_t *)&keyInd); pCcb->lastSentKey = SMP_CMD_MASTER_ID; } /* check if we're done sending keys */ if ((keyDist == 0) || (keyDist == SMP_KEY_DIST_ENC && pCcb->lastSentKey == SMP_CMD_MASTER_ID) || (keyDist <= (SMP_KEY_DIST_ENC | SMP_KEY_DIST_ID) && pCcb->lastSentKey == SMP_CMD_ID_ADDR_INFO) || (pCcb->lastSentKey == SMP_CMD_SIGN_INFO)) { return TRUE; } /* if flow disabled return */ if (pCcb->flowDisabled) { return FALSE; } /* allocate packet buffer for largest packet size */ if ((pPkt = smpMsgAlloc(SMP_ENC_INFO_LEN + L2C_PAYLOAD_START)) != NULL) { p = pPkt + L2C_PAYLOAD_START; /* determine next key to send */ if (pCcb->lastSentKey == 0 && (keyDist & SMP_KEY_DIST_ENC)) { /* generate LTK, EDIV, and RAND */ smpGenerateLtk(pCcb); /* send first part of LTK */ UINT8_TO_BSTREAM(p, SMP_CMD_ENC_INFO); Calc128Cpy(p, pCcb->pScr->keyInd.keyData.ltk.key); } else if (pCcb->lastSentKey == SMP_CMD_ENC_INFO) { /* send second part of LTK */ UINT8_TO_BSTREAM(p, SMP_CMD_MASTER_ID); UINT16_TO_BSTREAM(p, pCcb->pScr->keyInd.keyData.ltk.ediv); memcpy(p, pCcb->pScr->keyInd.keyData.ltk.rand, SMP_RAND8_LEN); } else if ((keyDist & SMP_KEY_DIST_ID) && (pCcb->lastSentKey == 0 || pCcb->lastSentKey == SMP_CMD_MASTER_ID)) { /* send first part of IRK */ UINT8_TO_BSTREAM(p, SMP_CMD_ID_INFO); Calc128Cpy(p, DmSecGetLocalIrk()); } else if (pCcb->lastSentKey == SMP_CMD_ID_INFO) { /* send second part of IRK */ UINT8_TO_BSTREAM(p, SMP_CMD_ID_ADDR_INFO); UINT8_TO_BSTREAM(p, DM_ADDR_PUBLIC); BDA_TO_BSTREAM(p, HciGetBdAddr()); } else if ((keyDist & SMP_KEY_DIST_SIGN) && (pCcb->lastSentKey == 0 || pCcb->lastSentKey == SMP_CMD_ID_ADDR_INFO || pCcb->lastSentKey == SMP_CMD_MASTER_ID)) { /* send SRK */ UINT8_TO_BSTREAM(p, SMP_CMD_SIGN_INFO); Calc128Cpy(p, DmSecGetLocalCsrk()); } else { /* should never get here */ WsfMsgFree(pPkt); SMP_TRACE_WARN2("smpSendKey unexpected state keyDist:%d lastSentKey:%d", keyDist, pCcb->lastSentKey); return TRUE; } /* set last sent key to command code */ pCcb->lastSentKey = pPkt[L2C_PAYLOAD_START]; /* send command packet */ smpSendPkt(pCcb, pPkt); /* if flow not disabled set up to send next key */ if (!pCcb->flowDisabled) { if ((pHdr = WsfMsgAlloc(sizeof(wsfMsgHdr_t))) != NULL) { pHdr->event = SMP_MSG_INT_SEND_NEXT_KEY; pHdr->param = pCcb->connId; WsfMsgSend(smpCb.handlerId, pHdr); } } } return FALSE; }