void smpAuthReq(smpCcb_t *pCcb, uint8_t oob, uint8_t display) { /* use a union to save a bit of memory on the stack */ union { smpDmAuthRsp_t authRsp; dmSecAuthReqIndEvt_t authReq; } buf; /* if authenticated pairing */ if (pCcb->auth & SMP_AUTH_MITM_FLAG) { /* request pin or oob from user */ buf.authReq.hdr.param = pCcb->connId; buf.authReq.hdr.event = DM_SEC_AUTH_REQ_IND; buf.authReq.oob = oob; buf.authReq.display = display; DmSmpCbackExec((dmEvt_t *) &buf.authReq); } else { /* else use just works; send ourselves a auth rsp with all zero pin */ buf.authRsp.hdr.param = pCcb->connId; buf.authRsp.hdr.event = SMP_MSG_API_AUTH_RSP; buf.authRsp.authData[0] = 0; buf.authRsp.authData[1] = 0; buf.authRsp.authData[2] = 0; buf.authRsp.authDataLen = SMP_PIN_LEN; smpSmExecute(pCcb, (smpMsg_t *) &buf.authRsp); } }
void smpGenerateLtk(smpCcb_t *pCcb) { uint8_t *p; smpScratch_t *pScr = pCcb->pScr; /* generated results are stored in scratch buffer */ p = pScr->keyInd.keyData.ltk.key; /* generate LTK from random number */ SecRand(p, pScr->keyInd.encKeyLen); p += pScr->keyInd.encKeyLen; /* set remaining key bytes to zero */ memset(p, 0, (SMP_KEY_LEN - pScr->keyInd.encKeyLen)); /* use existing random number stored in scratch buf b4 for EDIV and RAND */ BYTES_TO_UINT16(pScr->keyInd.keyData.ltk.ediv, pScr->buf.b4); memcpy(pScr->keyInd.keyData.ltk.rand, &pScr->buf.b4[2], SMP_RAND8_LEN); /* pass key to app via DM */ pScr->keyInd.type = DM_KEY_LOCAL_LTK; pScr->keyInd.secLevel = (pCcb->auth & SMP_AUTH_MITM_FLAG) ? DM_SEC_LEVEL_ENC_AUTH : DM_SEC_LEVEL_ENC; pScr->keyInd.hdr.event = DM_SEC_KEY_IND; DmSmpCbackExec((dmEvt_t *) &pScr->keyInd); }
void smpActPairingFailed(smpCcb_t *pCcb, smpMsg_t *pMsg) { /* clean up */ smpCleanup(pCcb); /* set connection idle */ DmConnSetIdle(pCcb->connId, DM_IDLE_SMP_PAIR, DM_CONN_IDLE); /* notify DM of pairing failure */ pMsg->hdr.event = DM_SEC_PAIR_FAIL_IND; DmSmpCbackExec((dmEvt_t *) pMsg); }
void smpActPairingCmpl(smpCcb_t *pCcb, smpMsg_t *pMsg) { dmSecPairCmplIndEvt_t pairCmpl; smpCleanup(pCcb); /* set connection idle */ DmConnSetIdle(pCcb->connId, DM_IDLE_SMP_PAIR, DM_CONN_IDLE); pairCmpl.auth = pCcb->auth; pairCmpl.hdr.param = pCcb->connId; pairCmpl.hdr.event = DM_SEC_PAIR_CMPL_IND; DmSmpCbackExec((dmEvt_t *) &pairCmpl); }
void smpActCheckAttempts(smpCcb_t *pCcb, smpMsg_t *pMsg) { /* check if attempt was received */ if (pCcb->attempts) { pCcb->attempts = 0; smpSendPairingFailed(pCcb, SMP_ERR_ATTEMPTS); /* notify DM of pairing failure */ pMsg->hdr.status = SMP_ERR_ATTEMPTS; pMsg->hdr.event = DM_SEC_PAIR_FAIL_IND; DmSmpCbackExec((dmEvt_t *) pMsg); smpCleanup(pCcb); } }
void smprActProcPairReq(smpCcb_t *pCcb, smpMsg_t *pMsg) { dmSecPairIndEvt_t pairInd; uint8_t *p; /* allocate scratch buffer */ if (pCcb->pScr == NULL) { if ((pCcb->pScr = WsfBufAlloc(sizeof(smpScratch_t))) == NULL) { /* alloc failed; cancel pairing */ pMsg->hdr.status = SMP_ERR_UNSPECIFIED; pMsg->hdr.event = SMP_MSG_API_CANCEL_REQ; smpSmExecute(pCcb, pMsg); return; } } else { /* should not happen */ SMP_TRACE_ERR0("pScr already allocated"); } /* set connection busy */ DmConnSetIdle(pCcb->connId, DM_IDLE_SMP_PAIR, DM_CONN_BUSY); p = pMsg->data.pPacket + L2C_PAYLOAD_START; /* store packet for later */ memcpy(pCcb->pairReq, p, SMP_PAIR_REQ_LEN); /* parse packet to callback event structure */ p++; /* skip command code */ p++; /* skip IO capabilities */ BSTREAM_TO_UINT8(pairInd.oob, p); BSTREAM_TO_UINT8(pairInd.auth, p); p++; /* skip max key len */ BSTREAM_TO_UINT8(pairInd.iKeyDist, p); BSTREAM_TO_UINT8(pairInd.rKeyDist, p); /* call app callback */ pairInd.hdr.param = pCcb->connId; pairInd.hdr.event = DM_SEC_PAIR_IND; DmSmpCbackExec((dmEvt_t *) &pairInd); }
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; }