예제 #1
0
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);
  }
}
예제 #2
0
파일: smp_main.c 프로젝트: 0xc0170/mbed
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);
}
예제 #3
0
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);
}
예제 #4
0
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);
}
예제 #5
0
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);
  }
}
예제 #6
0
파일: smpr_act.c 프로젝트: 0xc0170/mbed
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);
}
예제 #7
0
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;
}
예제 #8
0
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;
}