Exemple #1
0
void smpSendPkt(smpCcb_t *pCcb, uint8_t *pPkt)
{
  /* if flow disabled */
  if (pCcb->flowDisabled)
  {
    /* if packet already queued discard it and replace it with this new packet */
    if (pCcb->pQueued != NULL)
    {
      SMP_TRACE_WARN1("smpSendPkt packet discarded cmd:%d", pCcb->pQueued[L2C_PAYLOAD_START]);
      WsfMsgFree(pCcb->pQueued);
    }

    /* queue packet */
    pCcb->pQueued = pPkt;
  }
  /* else send it to L2CAP */
  else
  {
    L2cDataReq(L2C_CID_SMP, pCcb->handle, smpPktLenTbl[pPkt[L2C_PAYLOAD_START]], pPkt);
  }
}
Exemple #2
0
void attcSendMsg(dmConnId_t connId, uint16_t handle, uint8_t msgId, attcPktParam_t *pPkt, bool_t continuing)
{
  attcCcb_t   *pCcb;
  uint16_t    mtu;
  bool_t      transTimedOut;

  WsfTaskLock();

  /* get CCB and verify connection still in use */
  if ((pCcb = attcCcbByConnId(connId)) != NULL)
  {
    /* get MTU size */
    mtu = pCcb->pMainCcb->mtu;
    transTimedOut = pCcb->pMainCcb->transTimedOut;
  }
  /* else connection not in use */
  else
  {
    /* MTU size unknown */
    mtu = 0;
    transTimedOut = FALSE;
  }

  WsfTaskUnlock();

  /* if MTU size known for connection */
  if (mtu > 0)
  {
    /* if no transaction's timed out */
    if (!transTimedOut)
    {
      uint16_t dataLen = 0;

      /* if packet is not null then find out its length */
      if (pPkt != NULL)
      {
        /* if not prepare write request */
        if (msgId != ATTC_MSG_API_PREP_WRITE)
        {
          dataLen = pPkt->len;
        }
        /* else prepare write request */
        else
        {
          /* if not continuing */
          if (!continuing)
          {
            /* single prepare write request */
            dataLen = ATT_PREP_WRITE_REQ_LEN + pPkt->w.len;
          }
          /* else will be sent as multiple prepare write requests */
        }
      }

      /* if packet length is less than or equal to negotiated MTU */
      if (dataLen <= mtu)
      {
        attcApiMsg_t *pMsg;

        /* allocate message buffer */
        if ((pMsg = WsfMsgAlloc(sizeof(attcApiMsg_t))) != NULL)
        {
          /* set parameters */
          pMsg->hdr.param = connId;
          pMsg->hdr.status = continuing;
          pMsg->hdr.event = msgId;
          pMsg->pPkt = pPkt;
          pMsg->handle = handle;

          /* send message */
          WsfMsgSend(attCb.handlerId, pMsg);
          return;
        }
      }
      /* else packet length exceeds MTU size */
      else
      {
        /* call callback with failure status */
        attcExecCallback(connId, msgId, handle, ATT_ERR_MTU_EXCEEDED);
      }
    }
    else
    /* transaction's timed out */
    {
      /* call callback with failure status */
      attcExecCallback(connId, msgId, handle, ATT_ERR_TIMEOUT);
    }
  }

  /* alloc failed, transaction's timed out or packet length exceeded MTU size; free packet buffer */
  if (pPkt != NULL)
  {
    WsfMsgFree(pPkt);
  }
}
Exemple #3
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;
}
Exemple #4
0
static void smpDmConnCback(dmEvt_t *pDmEvt)
{
  smpCcb_t      *pCcb;
  wsfMsgHdr_t   hdr;

  pCcb = smpCcbByConnId((dmConnId_t) pDmEvt->hdr.param);

  /* if new connection created */
  if (pDmEvt->hdr.event == DM_CONN_OPEN_IND)
  {
    /* set up state machine for master or slave */
    if (DmConnRole((dmConnId_t) pDmEvt->hdr.param) == DM_ROLE_MASTER)
    {
      pCcb->initiator = TRUE;
      pCcb->nextCmdCode = SMP_CMD_SECURITY_REQ;
    }
    else
    {
      pCcb->initiator = FALSE;
      pCcb->nextCmdCode = SMP_CMD_PAIR_REQ;
    }

    /* initialize control block */
    pCcb->handle = pDmEvt->connOpen.handle;
    pCcb->connId = (dmConnId_t) pDmEvt->hdr.param;
    pCcb->secReq = FALSE;
    pCcb->flowDisabled = FALSE;
    pCcb->attempts = SmpDbGetFailureCount((dmConnId_t) pDmEvt->hdr.param);
    pCcb->lastSentKey = 0;
    pCcb->state = 0;

    /* Resume the attempts state if necessary */
    smpResumeAttemptsState((dmConnId_t) pDmEvt->hdr.param);
  }
  /* else if connection has been opened */
  else if (pCcb->connId != DM_CONN_ID_NONE)
  {
    /* handle close */
    if (pDmEvt->hdr.event == DM_CONN_CLOSE_IND)
    {
      /* store attempts count */
      SmpDbSetFailureCount((dmConnId_t) pDmEvt->hdr.param, pCcb->attempts);

      /* send to state machine */
      hdr.param = pDmEvt->hdr.param;
      hdr.event = SMP_MSG_DM_CONN_CLOSE;
      hdr.status = pDmEvt->connClose.reason + DM_SEC_HCI_ERR_BASE;
      smpSmExecute(pCcb, (smpMsg_t *) &hdr);

      /* clear conn ID after handling event */
      pCcb->connId = DM_CONN_ID_NONE;

      /* free queued packet buffer */
      if (pCcb->pQueued != NULL)
      {
        WsfMsgFree(pCcb->pQueued);
        pCcb->pQueued = NULL;
      }
    }
  }
}