initial commit
This commit is contained in:
+136
@@ -0,0 +1,136 @@
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \file
|
||||
*
|
||||
* \brief AES and random number security service implemented using HCI.
|
||||
*
|
||||
* Copyright (c) 2010-2018 Arm Ltd.
|
||||
*
|
||||
* Copyright (c) 2019 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include "wsf_types.h"
|
||||
#include "wsf_queue.h"
|
||||
#include "wsf_msg.h"
|
||||
#include "wsf_trace.h"
|
||||
#include "sec_api.h"
|
||||
#include "sec_main.h"
|
||||
#include "hci_api.h"
|
||||
#include "util/calc128.h"
|
||||
|
||||
/**************************************************************************************************
|
||||
External Variables
|
||||
**************************************************************************************************/
|
||||
|
||||
extern secCb_t secCb;
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Returns the next token.
|
||||
*
|
||||
* \return Token value.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static uint8_t getNextToken()
|
||||
{
|
||||
uint8_t token = secCb.token++;
|
||||
|
||||
if (token == SEC_TOKEN_INVALID)
|
||||
{
|
||||
token = secCb.token++;
|
||||
}
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Execute an AES calculation. When the calculation completes, a WSF message will be
|
||||
* sent to the specified handler. This function returns a token value that
|
||||
* the client can use to match calls to this function with messages.
|
||||
*
|
||||
* \param pKey Pointer to 16 byte key.
|
||||
* \param pPlaintext Pointer to 16 byte plaintext.
|
||||
* \param handlerId WSF handler ID.
|
||||
* \param param Client-defined parameter returned in message.
|
||||
* \param event Event for client's WSF handler.
|
||||
*
|
||||
* \return Token value.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
uint8_t SecAes(uint8_t *pKey, uint8_t *pPlaintext, wsfHandlerId_t handlerId,
|
||||
uint16_t param, uint8_t event)
|
||||
{
|
||||
secQueueBuf_t *pBuf;
|
||||
|
||||
/* allocate a buffer */
|
||||
if ((pBuf = WsfMsgAlloc(sizeof(secQueueBuf_t))) != NULL)
|
||||
{
|
||||
pBuf->msg.hdr.status = getNextToken();
|
||||
pBuf->msg.hdr.param = param;
|
||||
pBuf->msg.hdr.event = event;
|
||||
|
||||
pBuf->type = SEC_TYPE_AES;
|
||||
|
||||
/* queue buffer */
|
||||
WsfMsgEnq(&secCb.aesEncQueue, handlerId, pBuf);
|
||||
|
||||
/* call HCI encrypt function */
|
||||
HciLeEncryptCmd(pKey, pPlaintext);
|
||||
|
||||
return pBuf->msg.hdr.status;
|
||||
}
|
||||
|
||||
return SEC_TOKEN_INVALID;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Callback for HCI encryption for AES operations.
|
||||
*
|
||||
* \param pBuf Pointer to sec queue element.
|
||||
* \param pEvent Pointer to HCI event.
|
||||
* \param handlerId WSF handler ID.
|
||||
*
|
||||
* \return none.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void SecAesHciCback(secQueueBuf_t *pBuf, hciEvt_t *pEvent, wsfHandlerId_t handlerId)
|
||||
{
|
||||
secAes_t *pAes = (secAes_t *) &pBuf->msg;
|
||||
|
||||
/* set encrypted data pointer and copy */
|
||||
pAes->pCiphertext = pBuf->ciphertext;
|
||||
Calc128Cpy(pAes->pCiphertext, pEvent->leEncryptCmdCmpl.data);
|
||||
|
||||
/* send message */
|
||||
WsfMsgSend(handlerId, pAes);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Called to initialize AES secuirity.
|
||||
*
|
||||
* \param none.
|
||||
*
|
||||
* \return none.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void SecAesInit()
|
||||
{
|
||||
secCb.hciCbackTbl[SEC_TYPE_AES] = SecAesHciCback;
|
||||
}
|
||||
Vendored
+137
@@ -0,0 +1,137 @@
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \file
|
||||
*
|
||||
* \brief AES and random number security service implemented using HCI.
|
||||
*
|
||||
* Copyright (c) 2010-2018 Arm Ltd.
|
||||
*
|
||||
* Copyright (c) 2019 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include "wsf_types.h"
|
||||
#include "wsf_queue.h"
|
||||
#include "wsf_msg.h"
|
||||
#include "wsf_trace.h"
|
||||
#include "sec_api.h"
|
||||
#include "sec_main.h"
|
||||
#include "hci_api.h"
|
||||
#include "util/calc128.h"
|
||||
#include "util/wstr.h"
|
||||
|
||||
/**************************************************************************************************
|
||||
External Variables
|
||||
**************************************************************************************************/
|
||||
|
||||
extern secCb_t secCb;
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Returns the next token.
|
||||
*
|
||||
* \return Token value.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static uint8_t getNextToken()
|
||||
{
|
||||
uint8_t token = secCb.token++;
|
||||
|
||||
if (token == SEC_TOKEN_INVALID)
|
||||
{
|
||||
token = secCb.token++;
|
||||
}
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Execute an AES calculation. When the calculation completes, a WSF message will be
|
||||
* sent to the specified handler. This function returns a token value that
|
||||
* the client can use to match calls to this function with messages. Note this version
|
||||
* reverses the key and plaintext bytes.
|
||||
*
|
||||
* \param pKey Pointer to 16 byte key.
|
||||
* \param pPlaintext Pointer to 16 byte plaintext.
|
||||
* \param handlerId WSF handler ID.
|
||||
* \param param Client-defined parameter returned in message.
|
||||
* \param event Event for client's WSF handler.
|
||||
*
|
||||
* \return Token value.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
uint8_t SecAesRev(uint8_t *pKey, uint8_t *pPlaintext, wsfHandlerId_t handlerId,
|
||||
uint16_t param, uint8_t event)
|
||||
{
|
||||
secQueueBuf_t *pBuf;
|
||||
|
||||
/* allocate a buffer */
|
||||
if ((pBuf = WsfMsgAlloc(sizeof(secQueueBuf_t))) != NULL)
|
||||
{
|
||||
pBuf->msg.hdr.status = getNextToken();
|
||||
pBuf->msg.hdr.param = param;
|
||||
pBuf->msg.hdr.event = event;
|
||||
|
||||
pBuf->type = SEC_TYPE_AES_REV;
|
||||
|
||||
/* call HCI encrypt function */
|
||||
SecLeEncryptCmd(pKey, pPlaintext, pBuf, handlerId);
|
||||
|
||||
return pBuf->msg.hdr.status;
|
||||
}
|
||||
|
||||
return SEC_TOKEN_INVALID;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Callback for HCI encryption for AES operations. Note this version reverses the
|
||||
* ciphertext bytes.
|
||||
*
|
||||
* \param pBuf Pointer to sec queue element.
|
||||
* \param pEvent Pointer to HCI event.
|
||||
* \param handlerId WSF handler ID.
|
||||
*
|
||||
* \return none.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void SecAesRevHciCback(secQueueBuf_t *pBuf, hciEvt_t *pEvent, wsfHandlerId_t handlerId)
|
||||
{
|
||||
secAes_t *pAes = (secAes_t *) &pBuf->msg;
|
||||
|
||||
/* set encrypted data pointer and copy */
|
||||
pAes->pCiphertext = pBuf->ciphertext;
|
||||
|
||||
Calc128Cpy(pAes->pCiphertext, pEvent->leEncryptCmdCmpl.data);
|
||||
|
||||
/* send message */
|
||||
WsfMsgSend(handlerId, pAes);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Called to initialize AES secuirity.
|
||||
*
|
||||
* \param none.
|
||||
*
|
||||
* \return none.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void SecAesRevInit()
|
||||
{
|
||||
secCb.hciCbackTbl[SEC_TYPE_AES_REV] = SecAesRevHciCback;
|
||||
}
|
||||
Vendored
+595
@@ -0,0 +1,595 @@
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \file
|
||||
*
|
||||
* \brief Counter with CBC-MAC (CCM) mode security - HCI AES.
|
||||
*
|
||||
* Copyright (c) 2018-2019 Arm Ltd.
|
||||
*
|
||||
* Copyright (c) 2019 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include "wsf_types.h"
|
||||
#include "wsf_queue.h"
|
||||
#include "wsf_msg.h"
|
||||
#include "wsf_trace.h"
|
||||
#include "wsf_assert.h"
|
||||
#include "sec_api.h"
|
||||
#include "sec_main.h"
|
||||
#include "wsf_buf.h"
|
||||
#include "hci_api.h"
|
||||
#include "util/calc128.h"
|
||||
#include "util/wstr.h"
|
||||
|
||||
#ifndef SEC_CCM_CFG
|
||||
#define SEC_CCM_CFG SEC_CCM_CFG_HCI
|
||||
#endif
|
||||
|
||||
#if SEC_CCM_CFG == SEC_CCM_CFG_HCI
|
||||
|
||||
/**************************************************************************************************
|
||||
Constants
|
||||
**************************************************************************************************/
|
||||
|
||||
/* State machine states */
|
||||
enum
|
||||
{
|
||||
SEC_CCM_STATE_XI_HDR,
|
||||
SEC_CCM_STATE_XI_MSG,
|
||||
SEC_CCM_STATE_S0,
|
||||
SEC_CCM_STATE_SI,
|
||||
SEC_CCM_STATE_MIC_COMPLETE,
|
||||
};
|
||||
|
||||
/**************************************************************************************************
|
||||
External Variables
|
||||
**************************************************************************************************/
|
||||
|
||||
/* Global security control block */
|
||||
extern secCb_t secCb;
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Exclusive-or two 128-bit integers and return the result in pDst.
|
||||
*
|
||||
* \param pDst Pointer to destination.
|
||||
* \param pSrc Pointer to source.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void secCcmCalcXor(uint8_t *pDst, uint8_t *pSrc, uint8_t size)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
*pDst++ ^= *pSrc++;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn secCcmBlockEncrypt
|
||||
*
|
||||
* \brief Perform a 16-byte block encryption (HCI AES)
|
||||
*
|
||||
* \param pBuf Security queue buffer containing CCM algorithm control block.
|
||||
* \param pText Pointer to text to encrypt (16 bytes).
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void secCcmBlockEncrypt(secQueueBuf_t *pBuf, uint8_t *pText)
|
||||
{
|
||||
secCcmSecCb_t *pCcm = (secCcmSecCb_t*) pBuf->pCb;
|
||||
SecLeEncryptCmd(pCcm->key, pText, pBuf, pCcm->handlerId);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn secCcmGenX0
|
||||
*
|
||||
* \brief Generate X_0 := E(K, B_0)
|
||||
*
|
||||
* \param pBuf Security queue buffer containing CCM algorithm control block.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void secCcmGenX0(secQueueBuf_t *pBuf)
|
||||
{
|
||||
secCcmSecCb_t *pCcm = (secCcmSecCb_t*) pBuf->pCb;
|
||||
|
||||
/* Scratch buffer contains nonce, add flags and message length */
|
||||
pCcm->scratch[0] = (SEC_CCM_L - 1) | (((pCcm->micLen - 2) / 2) << 3) | ((pCcm->clearLen > 0? 1:0) << 6);
|
||||
pCcm->scratch[SEC_BLOCK_LEN - 2] = pCcm->textLen >> 8;
|
||||
pCcm->scratch[SEC_BLOCK_LEN - 1] = pCcm->textLen & 0xFF;
|
||||
|
||||
pCcm->state = pCcm->clearLen > 0 ? SEC_CCM_STATE_XI_HDR : SEC_CCM_STATE_XI_MSG;
|
||||
pCcm->position = 0;
|
||||
|
||||
/* AES Operation */
|
||||
secCcmBlockEncrypt(pBuf, pCcm->scratch);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn secCcmGenXiHdr
|
||||
*
|
||||
* \brief Generate X_i header if clear text (additional data) is present.
|
||||
*
|
||||
* \param pBuf Security queue buffer containing CCM algorithm control block.
|
||||
* \param pPriorX 16 byte buffer containing X_i-1.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void secCcmGenXiHdr(secQueueBuf_t *pBuf, uint8_t *pPriorX)
|
||||
{
|
||||
secCcmSecCb_t *pCcm = (secCcmSecCb_t*) pBuf->pCb;
|
||||
uint8_t b_i[SEC_BLOCK_LEN];
|
||||
uint16_t remaining;
|
||||
uint16_t offset = 0;
|
||||
|
||||
if (pCcm->position == 0)
|
||||
{
|
||||
/* Copy additional data into working buffer */
|
||||
memcpy(pCcm->pWorking, pCcm->pClear, pCcm->clearLen);
|
||||
|
||||
/* First two bytes of b_0 contain length of additional data */
|
||||
b_i[0] = pCcm->clearLen >> 8;
|
||||
b_i[1] = pCcm->clearLen & 0xFF;
|
||||
pCcm->position = offset = 2;
|
||||
}
|
||||
|
||||
remaining = (int16_t) pCcm->clearLen - pCcm->position + 2;
|
||||
|
||||
/* Copy additional to b_i */
|
||||
if (remaining >= SEC_BLOCK_LEN - offset)
|
||||
{
|
||||
memcpy(b_i + offset, pCcm->pClear + pCcm->position - 2, SEC_BLOCK_LEN - offset);
|
||||
pCcm->position += SEC_BLOCK_LEN - offset;
|
||||
|
||||
if (remaining == SEC_BLOCK_LEN - offset)
|
||||
{
|
||||
pCcm->state = SEC_CCM_STATE_XI_MSG;
|
||||
pCcm->position = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(b_i + offset, pCcm->pClear + pCcm->position - 2, remaining);
|
||||
memset(b_i + offset + remaining, 0, SEC_BLOCK_LEN - remaining - offset);
|
||||
pCcm->state = SEC_CCM_STATE_XI_MSG;
|
||||
pCcm->position = 0;
|
||||
}
|
||||
|
||||
/* X_i XOR B_i */
|
||||
Calc128Xor(b_i, pPriorX);
|
||||
|
||||
/* AES Operation */
|
||||
secCcmBlockEncrypt(pBuf, b_i);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn secCcmGenXiMsg
|
||||
*
|
||||
* \brief Generate X_i for the message text.
|
||||
*
|
||||
* \param pBuf Security queue buffer containing CCM algorithm control block.
|
||||
* \param pPriorX 16 byte buffer containing X_i-1.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void secCcmGenXiMsg(secQueueBuf_t *pBuf, uint8_t *pPriorX)
|
||||
{
|
||||
secCcmSecCb_t *pCcm = (secCcmSecCb_t*) pBuf->pCb;
|
||||
uint8_t b_i[SEC_BLOCK_LEN];
|
||||
uint16_t remaining = (int16_t) pCcm->textLen - pCcm->position;
|
||||
|
||||
/* Copy data to b_i */
|
||||
if (remaining >= SEC_BLOCK_LEN)
|
||||
{
|
||||
Calc128Cpy(b_i, pCcm->pText + pCcm->position);
|
||||
pCcm->position += SEC_BLOCK_LEN;
|
||||
|
||||
if (remaining == SEC_BLOCK_LEN)
|
||||
{
|
||||
pCcm->state = SEC_CCM_STATE_S0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(b_i, pCcm->pText + pCcm->position, remaining);
|
||||
memset(b_i + remaining, 0, SEC_BLOCK_LEN - remaining);
|
||||
pCcm->state = SEC_CCM_STATE_S0;
|
||||
}
|
||||
|
||||
/* X_i XOR B_i */
|
||||
Calc128Xor(b_i, pPriorX);
|
||||
|
||||
/* AES Operation */
|
||||
secCcmBlockEncrypt(pBuf, b_i);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn secCcmGenS0
|
||||
*
|
||||
* \brief Generate S_0 := E(K, A_0)
|
||||
*
|
||||
* \param pBuf Security queue buffer containing CCM algorithm control block.
|
||||
* \param x_n 16 byte buffer containing X_n (containing T).
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void secCcmGenS0(secQueueBuf_t *pBuf, uint8_t *x_n)
|
||||
{
|
||||
secCcmSecCb_t *pCcm = (secCcmSecCb_t*) pBuf->pCb;
|
||||
uint16_t offset = pCcm->textLen + pCcm->clearLen;
|
||||
|
||||
/* Copy T to working buffer */
|
||||
memcpy(pCcm->pWorking + offset, x_n, pCcm->micLen);
|
||||
|
||||
/* Scratch buffer contains nonce, add flags and counter */
|
||||
pCcm->scratch[0] = (SEC_CCM_L - 1);
|
||||
pCcm->scratch[SEC_BLOCK_LEN - 2] = pCcm->scratch[SEC_BLOCK_LEN - 1] = 0;
|
||||
|
||||
pCcm->state = SEC_CCM_STATE_MIC_COMPLETE;
|
||||
|
||||
/* AES Operation */
|
||||
secCcmBlockEncrypt(pBuf, pCcm->scratch);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn secCcmGenS1
|
||||
*
|
||||
* \brief Generate S_1 := E(K, A_1)
|
||||
*
|
||||
* \param pBuf Security queue buffer containing CCM algorithm control block.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void secCcmGenS1(secQueueBuf_t *pBuf)
|
||||
{
|
||||
secCcmSecCb_t *pCcm = (secCcmSecCb_t*) pBuf->pCb;
|
||||
|
||||
/* Set counter. */
|
||||
pCcm->counter = 1;
|
||||
|
||||
/* Scratch buffer contains nonce, add flags and counter. */
|
||||
pCcm->scratch[0] = (SEC_CCM_L - 1);
|
||||
pCcm->scratch[SEC_BLOCK_LEN - 2] = 0;
|
||||
pCcm->scratch[SEC_BLOCK_LEN - 1] = 1;
|
||||
|
||||
/* Change state to S_i state. */
|
||||
pCcm->state = SEC_CCM_STATE_SI;
|
||||
|
||||
/* AES Operation. */
|
||||
secCcmBlockEncrypt(pBuf, pCcm->scratch);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn secCcmMicComplete
|
||||
*
|
||||
* \brief Called when MIC calculation is complete.
|
||||
*
|
||||
* \param pBuf Security queue buffer containing CCM algorithm control block.
|
||||
* \param s_0 16 byte buffer containing S_0.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void secCcmMicComplete(secQueueBuf_t *pBuf, uint8_t *s_0)
|
||||
{
|
||||
secCcmSecCb_t *pCcm = (secCcmSecCb_t*) pBuf->pCb;
|
||||
int16_t micOffset;
|
||||
|
||||
/* MIC = s_0 XOR T (store in result buffer). */
|
||||
micOffset = pCcm->textLen + pCcm->clearLen;
|
||||
secCcmCalcXor(pCcm->pWorking + micOffset, s_0, pCcm->micLen);
|
||||
|
||||
if (pCcm->operation == SEC_CCM_OP_ENCRYPT)
|
||||
{
|
||||
/* When encrypting, continue S_i calculations */
|
||||
secCcmGenS1(pBuf);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Decryption complete. Send notification. */
|
||||
secCcmDecMsg_t *pMsg = (secCcmDecMsg_t *) &pBuf->msg;
|
||||
|
||||
/* Verify MIC value */
|
||||
if (memcmp(pCcm->pRcvMic, pCcm->pWorking + micOffset, pCcm->micLen) == 0)
|
||||
{
|
||||
pMsg->pText = pCcm->pWorking + pCcm->clearLen;
|
||||
pMsg->textLen = pCcm->textLen;
|
||||
pMsg->success = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
pMsg->pText = NULL;
|
||||
pMsg->textLen = 0;
|
||||
pMsg->success = FALSE;
|
||||
}
|
||||
|
||||
WsfMsgSend(pCcm->handlerId, pMsg);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn secCcmGenSi
|
||||
*
|
||||
* \brief Generate S_i := E(K, A_i)
|
||||
*
|
||||
* \param pBuf Security queue buffer containing CCM algorithm control block.
|
||||
* \param pPriorS 16 byte buffer containing S_i-1.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void secCcmGenSi(secQueueBuf_t *pBuf, uint8_t *pPriorS)
|
||||
{
|
||||
secCcmSecCb_t *pCcm = (secCcmSecCb_t*) pBuf->pCb;
|
||||
int16_t resultOffset = 0;
|
||||
uint16_t len;
|
||||
|
||||
/* Determine length of XOR operation. */
|
||||
len = pCcm->textLen - ((pCcm->counter - 1) * SEC_BLOCK_LEN);
|
||||
len = len > SEC_BLOCK_LEN? SEC_BLOCK_LEN : len;
|
||||
|
||||
/* m_i XOR s_i+1. */
|
||||
resultOffset = (pCcm->counter - 1) * SEC_BLOCK_LEN + pCcm->clearLen;
|
||||
|
||||
secCcmCalcXor(pCcm->pWorking + resultOffset, pPriorS, (uint8_t) len);
|
||||
|
||||
if (pCcm->counter * SEC_BLOCK_LEN >= pCcm->textLen)
|
||||
{
|
||||
if (pCcm->operation == SEC_CCM_OP_ENCRYPT)
|
||||
{
|
||||
/* Encription complete. Send notification. */
|
||||
secCcmEncMsg_t *pMsg = (secCcmEncMsg_t *) &pBuf->msg;
|
||||
|
||||
pMsg->pCiphertext = pCcm->pWorking;
|
||||
pMsg->textLen = pCcm->textLen + pCcm->clearLen + pCcm->micLen;
|
||||
WsfMsgSend(pCcm->handlerId, pMsg);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set pText to point to the decrypted result in pWorking */
|
||||
pCcm->pText = pCcm->pWorking + pCcm->clearLen;
|
||||
|
||||
/* Begin calculating the MIC */
|
||||
secCcmGenX0(pBuf);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update counter. */
|
||||
pCcm->counter++;
|
||||
pCcm->scratch[SEC_BLOCK_LEN - 2] = pCcm->counter >> 8;
|
||||
pCcm->scratch[SEC_BLOCK_LEN - 1] = pCcm->counter & 0xFF;
|
||||
|
||||
/* AES Operation. */
|
||||
secCcmBlockEncrypt(pBuf, pCcm->scratch);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn SecCcmBlockEncryptCmpl
|
||||
*
|
||||
* \brief Called when a block encryption operation completes.
|
||||
*
|
||||
* \param pParam Pointer to security control block.
|
||||
* \param pCypherText Pointer to encrypt result.
|
||||
*
|
||||
* \return none.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void SecCcmHciCback(secQueueBuf_t *pBuf, hciEvt_t *pEvent, wsfHandlerId_t handlerId)
|
||||
{
|
||||
secCcmSecCb_t *pCcm = (secCcmSecCb_t *) pBuf->pCb;
|
||||
|
||||
switch (pCcm->state)
|
||||
{
|
||||
case SEC_CCM_STATE_XI_HDR:
|
||||
secCcmGenXiHdr(pBuf, pEvent->leEncryptCmdCmpl.data);
|
||||
break;
|
||||
|
||||
case SEC_CCM_STATE_XI_MSG:
|
||||
secCcmGenXiMsg(pBuf, pEvent->leEncryptCmdCmpl.data);
|
||||
break;
|
||||
|
||||
case SEC_CCM_STATE_S0:
|
||||
secCcmGenS0(pBuf, pEvent->leEncryptCmdCmpl.data);
|
||||
break;
|
||||
|
||||
case SEC_CCM_STATE_SI:
|
||||
secCcmGenSi(pBuf, pEvent->leEncryptCmdCmpl.data);
|
||||
break;
|
||||
|
||||
case SEC_CCM_STATE_MIC_COMPLETE:
|
||||
secCcmMicComplete(pBuf, pEvent->leEncryptCmdCmpl.data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn SecCcmEnc
|
||||
*
|
||||
* \brief Execute the CCM-Mode encryption algorithm.
|
||||
*
|
||||
* \param pKey Pointer to encryption key (SEC_CCM_KEY_LEN bytes).
|
||||
* \param pNonce Pointer to nonce (SEC_CCM_NONCE_LEN bytes).
|
||||
* \param pPlainText Pointer to text to encrypt.
|
||||
* \param textLen Length of pPlainText in bytes.
|
||||
* \param pClear Pointer to additional, unencrypted authentication text.
|
||||
* \param clearLen Length of pClear in bytes.
|
||||
* \param micLen Size of MIC in bytes (4, 8 or 16).
|
||||
* \param pResult Buffer to hold result (returned in complete event).
|
||||
* \param handlerId Task handler ID to receive complete event.
|
||||
* \param param Optional parameter passed in complete event.
|
||||
* \param event Event ID of complete event.
|
||||
|
||||
* \return TRUE if successful, else FALSE.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
bool_t SecCcmEnc(const uint8_t *pKey, uint8_t *pNonce, uint8_t *pPlainText, uint16_t textLen,
|
||||
uint8_t *pClear, uint16_t clearLen, uint8_t micLen, uint8_t *pResult,
|
||||
wsfHandlerId_t handlerId, uint16_t param, uint8_t event)
|
||||
{
|
||||
secQueueBuf_t *pBuf;
|
||||
uint16_t bufSize = sizeof(secQueueBuf_t) + sizeof(secCcmSecCb_t);
|
||||
|
||||
WSF_ASSERT(clearLen < SEC_CCM_MAX_ADDITIONAL_LEN);
|
||||
|
||||
if ((pBuf = WsfMsgAlloc(bufSize)) != NULL)
|
||||
{
|
||||
secCcmSecCb_t *pCcm = (secCcmSecCb_t *) (pBuf + 1);
|
||||
|
||||
/* Setup queue buffer */
|
||||
pBuf->pCb = pCcm;
|
||||
pBuf->type = SEC_TYPE_CCM;
|
||||
|
||||
pBuf->msg.hdr.status = secCb.token++;
|
||||
pBuf->msg.hdr.param = param;
|
||||
pBuf->msg.hdr.event = event;
|
||||
|
||||
pCcm->handlerId = handlerId;
|
||||
|
||||
pCcm->pText = pPlainText;
|
||||
pCcm->textLen = textLen;
|
||||
pCcm->pClear = pClear;
|
||||
pCcm->pWorking = pResult;
|
||||
pCcm->clearLen = clearLen;
|
||||
pCcm->micLen = micLen;
|
||||
pCcm->counter = 0;
|
||||
|
||||
memcpy(pCcm->pWorking + clearLen, pPlainText, textLen);
|
||||
memcpy(&pCcm->scratch[1], pNonce, SEC_CCM_NONCE_LEN);
|
||||
Calc128Cpy(pCcm->key, (uint8_t *) pKey);
|
||||
|
||||
pCcm->operation = SEC_CCM_OP_ENCRYPT;
|
||||
|
||||
/* Begin encryption of text by generation of X_0 */
|
||||
secCcmGenX0(pBuf);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn SecCcmDec
|
||||
*
|
||||
* \brief Execute the CCM-Mode verify and decrypt algorithm.
|
||||
*
|
||||
* \param pKey Pointer to encryption key (SEC_CCM_KEY_LEN bytes).
|
||||
* \param pNonce Pointer to nonce (SEC_CCM_NONCE_LEN bytes).
|
||||
* \param pCypherText Pointer to text to decrypt.
|
||||
* \param textLen Length of pCypherText in bytes.
|
||||
* \param pClear Pointer to additional, unencrypted authentication text.
|
||||
* \param clearLen Length of pClear in bytes.
|
||||
* \param pMic Pointer to authentication digest.
|
||||
* \param micLen Size of MIC in bytes (4, 8 or 16).
|
||||
* \param pResult Buffer to hold result (returned in complete event).
|
||||
* \param handlerId Task handler ID to receive complete event.
|
||||
* \param param Optional parameter passed in complete event.
|
||||
* \param event Event ID of complete event.
|
||||
*
|
||||
* \return TRUE if successful, else FALSE.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
bool_t SecCcmDec(const uint8_t *pKey, uint8_t *pNonce, uint8_t *pCypherText, uint16_t textLen,
|
||||
uint8_t *pClear, uint16_t clearLen, uint8_t *pMic, uint8_t micLen,
|
||||
uint8_t *pResult, wsfHandlerId_t handlerId, uint16_t param, uint8_t event)
|
||||
{
|
||||
secQueueBuf_t *pBuf;
|
||||
uint16_t bufSize = sizeof(secQueueBuf_t) + sizeof(secCcmSecCb_t);
|
||||
|
||||
WSF_ASSERT(clearLen < SEC_CCM_MAX_ADDITIONAL_LEN);
|
||||
|
||||
if ((pBuf = WsfMsgAlloc(bufSize)) != NULL)
|
||||
{
|
||||
secCcmSecCb_t *pCcm = (secCcmSecCb_t *) (pBuf + 1);
|
||||
|
||||
/* Setup queue buffer */
|
||||
pBuf->pCb = pCcm;
|
||||
pBuf->type = SEC_TYPE_CCM;
|
||||
|
||||
pBuf->msg.hdr.status = secCb.token++;
|
||||
pBuf->msg.hdr.param = param;
|
||||
pBuf->msg.hdr.event = event;
|
||||
|
||||
pCcm->handlerId = handlerId;
|
||||
|
||||
pCcm->pClear = pClear;
|
||||
pCcm->pRcvMic = pMic;
|
||||
pCcm->pWorking = pResult;
|
||||
pCcm->textLen = textLen;
|
||||
pCcm->clearLen = clearLen;
|
||||
pCcm->micLen = micLen;
|
||||
pCcm->counter = 0;
|
||||
|
||||
/* Prepare the working buffer */
|
||||
memcpy(pCcm->pWorking, pClear, clearLen);
|
||||
memcpy(pCcm->pWorking + clearLen, pCypherText, textLen);
|
||||
memcpy(pCcm->pWorking + clearLen + textLen, pMic, micLen);
|
||||
|
||||
memcpy(&pCcm->scratch[1], pNonce, SEC_CCM_NONCE_LEN);
|
||||
Calc128Cpy(pCcm->key, (uint8_t *) pKey);
|
||||
|
||||
pCcm->operation = SEC_CCM_OP_DECRYPT;
|
||||
|
||||
/* Begin decryption of text by generation of S_1 */
|
||||
secCcmGenS1(pBuf);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn SecCcmInit
|
||||
*
|
||||
* \brief Called to initialize CCM-Mode security.
|
||||
*
|
||||
* \param None.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void SecCcmInit(void)
|
||||
{
|
||||
secCb.hciCbackTbl[SEC_TYPE_CCM] = SecCcmHciCback;
|
||||
}
|
||||
|
||||
#endif /* SEC_CCM_CFG */
|
||||
Vendored
+323
@@ -0,0 +1,323 @@
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \file
|
||||
*
|
||||
* \brief AES and random number security service implemented using HCI.
|
||||
*
|
||||
* Copyright (c) 2010-2019 Arm Ltd.
|
||||
*
|
||||
* Copyright (c) 2019 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include "wsf_types.h"
|
||||
#include "wsf_queue.h"
|
||||
#include "wsf_msg.h"
|
||||
#include "wsf_trace.h"
|
||||
#include "sec_api.h"
|
||||
#include "sec_main.h"
|
||||
#include "wsf_buf.h"
|
||||
#include "hci_api.h"
|
||||
#include "util/calc128.h"
|
||||
#include "util/wstr.h"
|
||||
|
||||
#ifndef SEC_CMAC_CFG
|
||||
#define SEC_CMAC_CFG SEC_CMAC_CFG_HCI
|
||||
#endif
|
||||
|
||||
#if SEC_CMAC_CFG == SEC_CMAC_CFG_HCI
|
||||
|
||||
enum
|
||||
{
|
||||
SEC_CMAC_STATE_SUBKEY,
|
||||
SEC_CMAC_STATE_BLOCK,
|
||||
SEC_CMAC_STATE_COMPLETE,
|
||||
};
|
||||
|
||||
/**************************************************************************************************
|
||||
External Variables
|
||||
**************************************************************************************************/
|
||||
|
||||
extern secCb_t secCb;
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Continue the execution of the CMAC algorithm over the next message block.
|
||||
*
|
||||
* \param pBuf Security queue buffer containing CMAC algorithm control block.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void secCmacProcessBlock(secQueueBuf_t *pBuf)
|
||||
{
|
||||
secCmacSecCb_t *pCmac = (secCmacSecCb_t*) pBuf->pCb;
|
||||
uint8_t text[SEC_BLOCK_LEN];
|
||||
uint8_t *pMn = pCmac->pPlainText + pCmac->position;
|
||||
int16_t remaining = (int16_t) pCmac->len - pCmac->position;
|
||||
|
||||
/* Check for Last Block */
|
||||
if (remaining <= SEC_BLOCK_LEN)
|
||||
{
|
||||
memcpy(text, pMn, remaining);
|
||||
|
||||
/* Pad the message if necessary */
|
||||
if (remaining != SEC_BLOCK_LEN)
|
||||
{
|
||||
memset(text + remaining, 0, SEC_BLOCK_LEN - remaining);
|
||||
text[remaining] = 0x80;
|
||||
}
|
||||
|
||||
/* XOr the subkey */
|
||||
Calc128Xor(text, pCmac->subkey);
|
||||
pCmac->state = SEC_CMAC_STATE_COMPLETE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Copy the block to the buffer */
|
||||
Calc128Cpy(text, pMn);
|
||||
}
|
||||
|
||||
if (pCmac->position != 0)
|
||||
{
|
||||
/* Except for first block, XOr the previous AES calculation */
|
||||
Calc128Xor(text, pBuf->ciphertext);
|
||||
}
|
||||
|
||||
pCmac->position += SEC_BLOCK_LEN;
|
||||
|
||||
SecLeEncryptCmd(pCmac->key, text, pBuf, pCmac->handlerId);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Step 1 to generate the subkey used in the CMAC algorithm.
|
||||
*
|
||||
* \param pBuf Security queue buffer containing CMAC algorithm control block.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void secCmacGenSubkey1(secQueueBuf_t *pBuf)
|
||||
{
|
||||
secCmacSecCb_t *pCmac = (secCmacSecCb_t*) pBuf->pCb;
|
||||
uint8_t buf[SEC_BLOCK_LEN];
|
||||
|
||||
/* Perform aes on the key with a constant zero */
|
||||
memset(buf, 0, SEC_BLOCK_LEN);
|
||||
|
||||
SecLeEncryptCmd(pCmac->key, buf, pBuf, pCmac->handlerId);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Left shift a buffer of WSF_CMAC_KEY_LEN bytes by N bits.
|
||||
*
|
||||
* \param pBuf Buffer to left shift.
|
||||
* \param shift Number of bits to shift.
|
||||
*
|
||||
* \return The overflow of the operaiton.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static uint8_t secCmacKeyShift(uint8_t *pBuf, uint8_t shift)
|
||||
{
|
||||
uint8_t overflow, i;
|
||||
uint8_t finalOverflow = pBuf[0] >> (8 - shift);
|
||||
|
||||
for (i = 0; i < SEC_CMAC_KEY_LEN; i++)
|
||||
{
|
||||
/* store shifted bits for next byte */
|
||||
if (i < SEC_CMAC_KEY_LEN-1)
|
||||
{
|
||||
overflow = pBuf[i+1] >> (8 - shift);
|
||||
}
|
||||
else
|
||||
{
|
||||
overflow = 0;
|
||||
}
|
||||
|
||||
/* shift byte and OR in shifted bits from previous byte */
|
||||
pBuf[i] = (pBuf[i] << shift) | overflow;
|
||||
}
|
||||
|
||||
return finalOverflow;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Complete generation of the subkey used in the CMAC algorithm.
|
||||
*
|
||||
* \param pBuf Security queue buffer containing CMAC algorithm control block.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void secCmacGenSubkey2(secQueueBuf_t *pBuf)
|
||||
{
|
||||
secCmacSecCb_t *pCmac = (secCmacSecCb_t*) pBuf->pCb;
|
||||
uint8_t overflow;
|
||||
|
||||
/* Copy the result of the AES oepration */
|
||||
Calc128Cpy(pCmac->subkey, pBuf->ciphertext);
|
||||
|
||||
/* Calculate the K1 subkey */
|
||||
overflow = secCmacKeyShift(pCmac->subkey, 1);
|
||||
|
||||
if (overflow)
|
||||
{
|
||||
pCmac->subkey[SEC_BLOCK_LEN-1] ^= SEC_CMAC_RB;
|
||||
}
|
||||
|
||||
if (pCmac->len % SEC_BLOCK_LEN != 0)
|
||||
{
|
||||
/* If the message len is not a multiple of SEC_BLOCK_LEN */
|
||||
/* Continue with generation of the K2 subkey based on the K1 key */
|
||||
overflow = secCmacKeyShift(pCmac->subkey, 1);
|
||||
|
||||
if (overflow)
|
||||
{
|
||||
pCmac->subkey[SEC_BLOCK_LEN-1] ^= SEC_CMAC_RB;
|
||||
}
|
||||
}
|
||||
|
||||
/* Begin CMAC calculation */
|
||||
pCmac->state = SEC_CMAC_STATE_BLOCK;
|
||||
secCmacProcessBlock(pBuf);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Send a message to the handler with CMAC result.
|
||||
*
|
||||
* \param pBuf Security queue buffer containing CMAC algorithm control block.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void secCmacComplete(secQueueBuf_t *pBuf)
|
||||
{
|
||||
/* CMAC is complete, copy and send result to handler */
|
||||
secCmacMsg_t *pMsg = (secCmacMsg_t *) &pBuf->msg;
|
||||
secCmacSecCb_t *pCmac = (secCmacSecCb_t *) pBuf->pCb;
|
||||
|
||||
pMsg->pCiphertext = pBuf->ciphertext;
|
||||
pMsg->pPlainText = pCmac->pPlainText;
|
||||
|
||||
WsfMsgSend(pCmac->handlerId, pMsg);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Callback for HCI encryption for CMAC operations.
|
||||
*
|
||||
* \param pBuf Pointer to sec queue element.
|
||||
* \param pEvent Pointer to HCI event.
|
||||
* \param handlerId WSF handler ID.
|
||||
*
|
||||
* \return none.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void SecCmacHciCback(secQueueBuf_t *pBuf, hciEvt_t *pEvent, wsfHandlerId_t handlerId)
|
||||
{
|
||||
secCmacSecCb_t *pCmac = (secCmacSecCb_t *) pBuf->pCb;
|
||||
|
||||
if (pCmac)
|
||||
{
|
||||
Calc128Cpy(pBuf->ciphertext, pEvent->leEncryptCmdCmpl.data);
|
||||
|
||||
switch (pCmac->state)
|
||||
{
|
||||
case SEC_CMAC_STATE_SUBKEY:
|
||||
secCmacGenSubkey2(pBuf);
|
||||
break;
|
||||
|
||||
case SEC_CMAC_STATE_BLOCK:
|
||||
secCmacProcessBlock(pBuf);
|
||||
break;
|
||||
|
||||
case SEC_CMAC_STATE_COMPLETE:
|
||||
secCmacComplete(pBuf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Execute the CMAC algorithm.
|
||||
*
|
||||
* \param pKey Key used in CMAC operation.
|
||||
* \param pPlainText Data to perform CMAC operation over
|
||||
* \param len Size of pPlaintext in bytes.
|
||||
* \param handlerId WSF handler ID for client.
|
||||
* \param param Optional parameter sent to client's WSF handler.
|
||||
* \param event Event for client's WSF handler.
|
||||
*
|
||||
* \return TRUE if successful, else FALSE.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
bool_t SecCmac(const uint8_t *pKey, uint8_t *pPlainText, uint16_t textLen, wsfHandlerId_t handlerId,
|
||||
uint16_t param, uint8_t event)
|
||||
{
|
||||
secQueueBuf_t *pBuf;
|
||||
uint16_t bufSize = sizeof(secQueueBuf_t) + sizeof(secCmacSecCb_t);
|
||||
|
||||
if ((pBuf = WsfMsgAlloc(bufSize)) != NULL)
|
||||
{
|
||||
secCmacSecCb_t *pCmacCb = (secCmacSecCb_t *) (pBuf + 1);
|
||||
|
||||
/* Setup queue buffer */
|
||||
pBuf->pCb = pCmacCb;
|
||||
pBuf->type = SEC_TYPE_CMAC;
|
||||
|
||||
pBuf->msg.hdr.status = secCb.token++;
|
||||
pBuf->msg.hdr.param = param;
|
||||
pBuf->msg.hdr.event = event;
|
||||
|
||||
pCmacCb->pPlainText = pPlainText;
|
||||
|
||||
pCmacCb->len = textLen;
|
||||
pCmacCb->position = 0;
|
||||
pCmacCb->handlerId = handlerId;
|
||||
pCmacCb->state = SEC_CMAC_STATE_SUBKEY;
|
||||
|
||||
/* Copy key */
|
||||
Calc128Cpy(pCmacCb->key, (uint8_t *) pKey);
|
||||
|
||||
/* Start the CMAC process by calculating the subkey */
|
||||
secCmacGenSubkey1(pBuf);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Called to initialize CMAC security.
|
||||
*
|
||||
* \param None.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void SecCmacInit()
|
||||
{
|
||||
secCb.hciCbackTbl[SEC_TYPE_CMAC] = SecCmacHciCback;
|
||||
}
|
||||
|
||||
#endif /* SEC_CMAC_CFG */
|
||||
Vendored
+160
@@ -0,0 +1,160 @@
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \file
|
||||
*
|
||||
* \brief Security ECC implementation using debug keys.
|
||||
*
|
||||
* Copyright (c) 2010-2018 Arm Ltd.
|
||||
*
|
||||
* Copyright (c) 2019 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include "wsf_types.h"
|
||||
#include "wsf_queue.h"
|
||||
#include "wsf_msg.h"
|
||||
#include "wsf_trace.h"
|
||||
#include "sec_api.h"
|
||||
#include "sec_main.h"
|
||||
#include "wsf_buf.h"
|
||||
#include "hci_api.h"
|
||||
#include "util/calc128.h"
|
||||
|
||||
#ifndef SEC_ECC_CFG
|
||||
#define SEC_ECC_CFG SEC_ECC_CFG_DEBUG
|
||||
#endif
|
||||
|
||||
#if SEC_ECC_CFG == SEC_ECC_CFG_DEBUG
|
||||
|
||||
/* Debug Keys */
|
||||
static const uint8_t debugPrivateKey[] = {0x3f, 0x49, 0xf6, 0xd4, 0xa3, 0xc5, 0x5f, 0x38,
|
||||
0x74, 0xc9, 0xb3, 0xe3, 0xd2, 0x10, 0x3f, 0x50,
|
||||
0x4a, 0xff, 0x60, 0x7b, 0xeb, 0x40, 0xb7, 0x99,
|
||||
0x58, 0x99, 0xb8, 0xa6, 0xcd, 0x3c, 0x1a, 0xbd};
|
||||
|
||||
static const uint8_t debugPublicKeyX[] = {0x20, 0xb0, 0x03, 0xd2, 0xf2, 0x97, 0xbe, 0x2c,
|
||||
0x5e, 0x2c, 0x83, 0xa7, 0xe9, 0xf9, 0xa5, 0xb9,
|
||||
0xef, 0xf4, 0x91, 0x11, 0xac, 0xf4, 0xfd, 0xdb,
|
||||
0xcc, 0x03, 0x01, 0x48, 0x0e, 0x35, 0x9d, 0xe6};
|
||||
|
||||
static const uint8_t debugPublicKeyY[] = {0xdc, 0x80, 0x9c, 0x49, 0x65, 0x2a, 0xeb, 0x6d,
|
||||
0x63, 0x32, 0x9a, 0xbf, 0x5a, 0x52, 0x15, 0x5c,
|
||||
0x76, 0x63, 0x45, 0xc2, 0x8f, 0xed, 0x30, 0x24,
|
||||
0x74, 0x1c, 0x8e, 0xd0, 0x15, 0x89, 0xd2, 0x8b};
|
||||
|
||||
static const uint8_t debugSharedSecret[] = {0x49, 0x4c, 0xfd, 0x99, 0x6f, 0x40, 0x17, 0xf5,
|
||||
0xb5, 0x48, 0xba, 0x66, 0x99, 0x60, 0x64, 0x08,
|
||||
0x62, 0x75, 0xd5, 0x1f, 0xe0, 0x8e, 0x56, 0x36,
|
||||
0xb9, 0x36, 0xd1, 0xe4, 0x57, 0x46, 0x4b, 0xed};
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Callback for HCI encryption for ECC operations.
|
||||
*
|
||||
* \param pBuf Pointer to sec queue element.
|
||||
* \param pEvent Pointer to HCI event.
|
||||
* \param handlerId WSF handler ID.
|
||||
*
|
||||
* \return none.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void SecEccHciCback(secQueueBuf_t *pBuf, hciEvt_t *pEvent, wsfHandlerId_t handlerId)
|
||||
{
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Generate an ECC key.
|
||||
*
|
||||
* \param handlerId WSF handler ID for client.
|
||||
* \param param Optional parameter sent to client's WSF handler.
|
||||
* \param event Event for client's WSF handler.
|
||||
*
|
||||
* \return TRUE if successful, else FALSE.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
bool_t SecEccGenKey(wsfHandlerId_t handlerId, uint16_t param, uint8_t event)
|
||||
{
|
||||
secEccMsg_t *pMsg = WsfMsgAlloc(sizeof(secEccMsg_t));
|
||||
|
||||
if (pMsg)
|
||||
{
|
||||
/* Generate the keys */
|
||||
memcpy(pMsg->data.key.pubKey_x, debugPublicKeyX, SEC_ECC_KEY_LEN);
|
||||
memcpy(pMsg->data.key.pubKey_y, debugPublicKeyY, SEC_ECC_KEY_LEN);
|
||||
memcpy(pMsg->data.key.privKey, debugPrivateKey, SEC_ECC_KEY_LEN);
|
||||
|
||||
/* Send shared secret to handler */
|
||||
pMsg->hdr.event = event;
|
||||
pMsg->hdr.param = param;
|
||||
pMsg->hdr.status = HCI_SUCCESS;
|
||||
WsfMsgSend(handlerId, pMsg);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Generate an ECC key.
|
||||
*
|
||||
* \param pKey ECC Key structure.
|
||||
* \param handlerId WSF handler ID for client.
|
||||
* \param param Optional parameter sent to client's WSF handler.
|
||||
* \param event Event for client's WSF handler.
|
||||
*
|
||||
* \return TRUE if successful, else FALSE.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
bool_t SecEccGenSharedSecret(secEccKey_t *pKey, wsfHandlerId_t handlerId, uint16_t param, uint8_t event)
|
||||
{
|
||||
secEccMsg_t *pMsg = WsfMsgAlloc(sizeof(secEccMsg_t));
|
||||
|
||||
if (pMsg)
|
||||
{
|
||||
memcpy(pMsg->data.sharedSecret.secret, debugSharedSecret, SEC_ECC_KEY_LEN);
|
||||
|
||||
/* Send shared secret to handler */
|
||||
pMsg->hdr.event = event;
|
||||
pMsg->hdr.param = param;
|
||||
pMsg->hdr.status = HCI_SUCCESS;
|
||||
WsfMsgSend(handlerId, pMsg);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Called to initialize ECC security.
|
||||
*
|
||||
* \param None.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void SecEccInit()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#endif /* SEC_ECC_CFG */
|
||||
Vendored
+183
@@ -0,0 +1,183 @@
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \file
|
||||
*
|
||||
* \brief WSF Security ECC implementation using HCI.
|
||||
*
|
||||
* Copyright (c) 2010-2018 Arm Ltd.
|
||||
*
|
||||
* Copyright (c) 2019 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include "wsf_types.h"
|
||||
#include "wsf_queue.h"
|
||||
#include "wsf_msg.h"
|
||||
#include "wsf_trace.h"
|
||||
#include "sec_api.h"
|
||||
#include "sec_main.h"
|
||||
#include "wsf_buf.h"
|
||||
#include "hci_api.h"
|
||||
#include "util/calc128.h"
|
||||
#include "util/wstr.h"
|
||||
|
||||
#ifndef SEC_ECC_CFG
|
||||
#define SEC_ECC_CFG SEC_ECC_CFG_HCI
|
||||
#endif
|
||||
|
||||
#if SEC_ECC_CFG == SEC_ECC_CFG_HCI
|
||||
|
||||
/**************************************************************************************************
|
||||
External Variables
|
||||
**************************************************************************************************/
|
||||
|
||||
extern secCb_t secCb;
|
||||
|
||||
/**************************************************************************************************
|
||||
Local Variables
|
||||
**************************************************************************************************/
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Callback for HCI encryption for ECC operations.
|
||||
*
|
||||
* \param pBuf Pointer to sec queue element.
|
||||
* \param pEvent Pointer to HCI event.
|
||||
* \param handlerId WSF handler ID.
|
||||
*
|
||||
* \return none.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void SecEccHciCback(secQueueBuf_t *pBuf, hciEvt_t *pEvent, wsfHandlerId_t handlerId)
|
||||
{
|
||||
secEccMsg_t *pMsg = (secEccMsg_t *) &pBuf->msg;
|
||||
|
||||
if (pEvent->hdr.event == HCI_LE_READ_LOCAL_P256_PUB_KEY_CMPL_CBACK_EVT)
|
||||
{
|
||||
/* Reverse copy the public key (to big endian) */
|
||||
WStrReverseCpy(pMsg->data.key.pubKey_x, pEvent->leP256.key, SEC_ECC_KEY_LEN);
|
||||
WStrReverseCpy(pMsg->data.key.pubKey_y, pEvent->leP256.key + SEC_ECC_KEY_LEN, SEC_ECC_KEY_LEN);
|
||||
|
||||
/* Send shared secret to handler */
|
||||
pMsg->hdr.status = pEvent->leP256.status;
|
||||
WsfMsgSend(handlerId, pMsg);
|
||||
}
|
||||
else if (pEvent->hdr.event == HCI_LE_GENERATE_DHKEY_CMPL_CBACK_EVT)
|
||||
{
|
||||
/* Reverse copy the DH key (to big endian) */
|
||||
WStrReverseCpy(pMsg->data.sharedSecret.secret, pEvent->leGenDHKey.key, SEC_ECC_KEY_LEN);
|
||||
|
||||
/* Send shared secret to handler */
|
||||
pMsg->hdr.status = pEvent->leGenDHKey.status;
|
||||
WsfMsgSend(handlerId, pMsg);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Generate an ECC key.
|
||||
*
|
||||
* \param handlerId WSF handler ID for client.
|
||||
* \param param Optional parameter sent to client's WSF handler.
|
||||
* \param event Event for client's WSF handler.
|
||||
*
|
||||
* \return TRUE if successful, else FALSE.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
bool_t SecEccGenKey(wsfHandlerId_t handlerId, uint16_t param, uint8_t event)
|
||||
{
|
||||
secQueueBuf_t *pBuf;
|
||||
uint16_t bufSize = sizeof(secQueueBuf_t) + sizeof(secEccMsg_t);
|
||||
|
||||
if ((pBuf = WsfMsgAlloc(bufSize)) != NULL)
|
||||
{
|
||||
/* Record the event and parameter for use in the HCI response */
|
||||
pBuf->msg.hdr.param = param;
|
||||
pBuf->msg.hdr.event = event;
|
||||
pBuf->type = SEC_TYPE_DH;
|
||||
|
||||
/* queue buffer */
|
||||
WsfMsgEnq(&secCb.pubKeyQueue, handlerId, pBuf);
|
||||
|
||||
/* Request the local public key via HCI */
|
||||
HciLeReadLocalP256PubKey();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Generate an ECC key.
|
||||
*
|
||||
* \param pKey ECC Key structure.
|
||||
* \param handlerId WSF handler ID for client.
|
||||
* \param param Optional parameter sent to client's WSF handler.
|
||||
* \param event Event for client's WSF handler.
|
||||
*
|
||||
* \return TRUE if successful, else FALSE.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
bool_t SecEccGenSharedSecret(secEccKey_t *pKey, wsfHandlerId_t handlerId, uint16_t param, uint8_t event)
|
||||
{
|
||||
secQueueBuf_t *pBuf;
|
||||
uint16_t bufSize = sizeof(secQueueBuf_t) + sizeof(secEccMsg_t);
|
||||
|
||||
if ((pBuf = WsfMsgAlloc(bufSize)) != NULL)
|
||||
{
|
||||
uint8_t pubKeyX[SEC_ECC_KEY_LEN];
|
||||
uint8_t pubKeyY[SEC_ECC_KEY_LEN];
|
||||
|
||||
/* Record the event and parameter for use in the HCI response */
|
||||
pBuf->msg.hdr.param = param;
|
||||
pBuf->msg.hdr.event = event;
|
||||
pBuf->type = SEC_TYPE_DH;
|
||||
|
||||
/* queue buffer */
|
||||
WsfMsgEnq(&secCb.dhKeyQueue, handlerId, pBuf);
|
||||
|
||||
/* Reverse keys (to little endian) */
|
||||
WStrReverseCpy(pubKeyX, pKey->pubKey_x, SEC_ECC_KEY_LEN);
|
||||
WStrReverseCpy(pubKeyY, pKey->pubKey_y, SEC_ECC_KEY_LEN);
|
||||
|
||||
/* Request the DH Key via HCI */
|
||||
HciLeGenerateDHKey(pubKeyX, pubKeyY);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Called to initialize ECC security.
|
||||
*
|
||||
* \param None.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void SecEccInit()
|
||||
{
|
||||
secCb.hciCbackTbl[SEC_TYPE_DH] = SecEccHciCback;
|
||||
}
|
||||
|
||||
#endif /* SEC_ECC_CFG */
|
||||
Vendored
+195
@@ -0,0 +1,195 @@
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \file
|
||||
*
|
||||
* \brief Security service implemented using HCI.
|
||||
*
|
||||
* Copyright (c) 2010-2019 Arm Ltd.
|
||||
*
|
||||
* Copyright (c) 2019 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include "wsf_types.h"
|
||||
#include "wsf_queue.h"
|
||||
#include "wsf_msg.h"
|
||||
#include "wsf_trace.h"
|
||||
#include "wsf_assert.h"
|
||||
#include "sec_api.h"
|
||||
#include "sec_main.h"
|
||||
#include "hci_api.h"
|
||||
#include "util/calc128.h"
|
||||
#include "util/wstr.h"
|
||||
// #include "pal_crypto.h"
|
||||
|
||||
/**************************************************************************************************
|
||||
Global Variables
|
||||
**************************************************************************************************/
|
||||
|
||||
/* Security Control block */
|
||||
secCb_t secCb;
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Callback for HCI encryption and random number events.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void secHciCback(hciEvt_t *pEvent)
|
||||
{
|
||||
secQueueBuf_t *pBuf = NULL;
|
||||
wsfHandlerId_t handlerId = 0;
|
||||
|
||||
/* Handle random number event. */
|
||||
switch (pEvent->hdr.event)
|
||||
{
|
||||
case HCI_LE_RAND_CMD_CMPL_CBACK_EVT:
|
||||
|
||||
/* Copy new data to circular buffer of random data. */
|
||||
memcpy(&secCb.rand[HCI_RAND_LEN * secCb.randTop], pEvent->leRandCmdCmpl.randNum, HCI_RAND_LEN);
|
||||
secCb.randTop = (secCb.randTop >= SEC_HCI_RAND_MULT - 1) ? 0 : secCb.randTop + 1;
|
||||
break;
|
||||
|
||||
case HCI_LE_ENCRYPT_CMD_CMPL_CBACK_EVT:
|
||||
pBuf = WsfMsgDeq(&secCb.aesEncQueue, &handlerId);
|
||||
|
||||
WSF_ASSERT(pBuf != NULL);
|
||||
|
||||
/* note: pBuf should never be NULL and is checked by assert above. */
|
||||
/* coverity[dereference] */
|
||||
if (pBuf->type == SEC_TYPE_CCM || pBuf->type == SEC_TYPE_CMAC || pBuf->type == SEC_TYPE_AES_REV)
|
||||
{
|
||||
WStrReverse(pEvent->leEncryptCmdCmpl.data, HCI_ENCRYPT_DATA_LEN);
|
||||
}
|
||||
break;
|
||||
|
||||
case HCI_LE_READ_LOCAL_P256_PUB_KEY_CMPL_CBACK_EVT:
|
||||
pBuf = WsfMsgDeq(&secCb.pubKeyQueue, &handlerId);
|
||||
break;
|
||||
|
||||
case HCI_LE_GENERATE_DHKEY_CMPL_CBACK_EVT:
|
||||
pBuf = WsfMsgDeq(&secCb.dhKeyQueue, &handlerId);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (pBuf)
|
||||
{
|
||||
WSF_ASSERT(secCb.hciCbackTbl[pBuf->type]);
|
||||
secCb.hciCbackTbl[pBuf->type](pBuf, pEvent, handlerId);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Initialize the security service. This function should only be called once
|
||||
* upon system initialization.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void SecInit(void)
|
||||
{
|
||||
WSF_QUEUE_INIT(&secCb.aesEncQueue);
|
||||
WSF_QUEUE_INIT(&secCb.pubKeyQueue);
|
||||
WSF_QUEUE_INIT(&secCb.dhKeyQueue);
|
||||
|
||||
secCb.token = 0;
|
||||
|
||||
/* Register callback with HCI */
|
||||
HciSecRegister(secHciCback);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Initialize the random number service. This function should only be called once
|
||||
* upon system initialization.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void SecRandInit(void)
|
||||
{
|
||||
int8_t i;
|
||||
|
||||
/* get new random numbers */
|
||||
for (i=0; i<SEC_HCI_RAND_MULT; i++)
|
||||
{
|
||||
HciLeRandCmd();
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief This function returns up to HCI_RAND_LEN * SEC_HCI_RAND_MULT bytes of random data to
|
||||
* a buffer provided by the client.
|
||||
*
|
||||
* \param pRand Pointer to returned random data.
|
||||
* \param randLen Length of random data.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void SecRand(uint8_t *pRand, uint8_t randLen)
|
||||
{
|
||||
int8_t count = (randLen + HCI_RAND_LEN - 1) / HCI_RAND_LEN;
|
||||
uint8_t index = secCb.randBtm * HCI_RAND_LEN;
|
||||
|
||||
WSF_ASSERT(randLen <= SEC_RAND_DATA_LEN);
|
||||
|
||||
/* Copy from circular buffer of random data. */
|
||||
while (randLen--)
|
||||
{
|
||||
*pRand++ = secCb.rand[index];
|
||||
index = (index == SEC_RAND_DATA_LEN - 1) ? 0 : index + 1;
|
||||
}
|
||||
|
||||
while (count--)
|
||||
{
|
||||
/* Request more random data. */
|
||||
HciLeRandCmd();
|
||||
|
||||
/* Update copy index. */
|
||||
secCb.randBtm = (secCb.randBtm >= SEC_HCI_RAND_MULT - 1) ? 0 : secCb.randBtm + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Queue callback and call LE encrypt given most significant byte ordered key and data.
|
||||
*
|
||||
* \param pKey Pointer to key.
|
||||
* \param pText Pointer to text to encrypt.
|
||||
* \param pBuf Pointer to queue block.
|
||||
* \param handlerId Handler ID.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void SecLeEncryptCmd(uint8_t *pKey, uint8_t *pText, void *pBuf, wsfHandlerId_t handlerId)
|
||||
{
|
||||
uint8_t revKey[HCI_KEY_LEN];
|
||||
uint8_t revText[HCI_ENCRYPT_DATA_LEN];
|
||||
|
||||
WStrReverseCpy(revKey, pKey, HCI_KEY_LEN);
|
||||
WStrReverseCpy(revText, pText, HCI_ENCRYPT_DATA_LEN);
|
||||
|
||||
WsfMsgEnq(&secCb.aesEncQueue, handlerId, pBuf);
|
||||
HciLeEncryptCmd(revKey, revText);
|
||||
}
|
||||
Vendored
+162
@@ -0,0 +1,162 @@
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \file
|
||||
*
|
||||
* \brief Internal security service structures.
|
||||
*
|
||||
* Copyright (c) 2010-2019 Arm Ltd.
|
||||
*
|
||||
* Copyright (c) 2019 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
#ifndef SEC_MAIN_H
|
||||
#define SEC_MAIN_H
|
||||
|
||||
#include "hci_api.h"
|
||||
// #include "pal_crypto.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**************************************************************************************************
|
||||
Macros
|
||||
**************************************************************************************************/
|
||||
|
||||
|
||||
/*! AES, CMAC and HCI algorithm block length */
|
||||
#define SEC_BLOCK_LEN 16
|
||||
|
||||
/* CMAC constant Rb */
|
||||
#define SEC_CMAC_RB 0x87
|
||||
|
||||
/*! Number or random bytes to keep in the secCb_t rand data buffer */
|
||||
#define SEC_RAND_DATA_LEN 32
|
||||
|
||||
/*! Multiple of HCI_RAND_LEN kept in the secCb_t rand data buffer */
|
||||
#define SEC_HCI_RAND_MULT (SEC_RAND_DATA_LEN / HCI_RAND_LEN)
|
||||
|
||||
/*! Compile time ECC configuration */
|
||||
#define SEC_ECC_CFG_DEBUG 0
|
||||
#define SEC_ECC_CFG_UECC 1
|
||||
#define SEC_ECC_CFG_HCI 2
|
||||
|
||||
/*! Compile time CMAC configuration */
|
||||
#define SEC_CMAC_CFG_PLATFORM 0
|
||||
#define SEC_CMAC_CFG_HCI 1
|
||||
|
||||
/*! Compile time CCM configuration */
|
||||
#define SEC_CCM_CFG_PLATFORM 0
|
||||
#define SEC_CCM_CFG_HCI 1
|
||||
|
||||
/*! CCM Operation (Encryption or Decryption) */
|
||||
#define SEC_CCM_OP_ENCRYPT 0
|
||||
#define SEC_CCM_OP_DECRYPT 1
|
||||
|
||||
/**************************************************************************************************
|
||||
Data Types
|
||||
**************************************************************************************************/
|
||||
|
||||
/*! Enumeration of security operation types */
|
||||
enum
|
||||
{
|
||||
SEC_TYPE_AES,
|
||||
SEC_TYPE_CMAC,
|
||||
SEC_TYPE_DH,
|
||||
SEC_TYPE_CCM,
|
||||
SEC_TYPE_AES_REV,
|
||||
SEC_NUM_TYPES
|
||||
};
|
||||
|
||||
/*! Security queue element for CMAC operations */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t *pPlainText;
|
||||
uint8_t key[SEC_CMAC_KEY_LEN];
|
||||
uint8_t subkey[SEC_CMAC_KEY_LEN];
|
||||
uint16_t position;
|
||||
uint16_t len;
|
||||
wsfHandlerId_t handlerId;
|
||||
uint8_t state;
|
||||
} secCmacSecCb_t;
|
||||
|
||||
/*! Security queue element for CCM-Mode operations */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t operation;
|
||||
uint8_t *pText;
|
||||
uint8_t *pClear;
|
||||
uint8_t *pRcvMic;
|
||||
uint16_t textLen;
|
||||
uint16_t clearLen;
|
||||
uint8_t micLen;
|
||||
uint8_t key[SEC_CCM_KEY_LEN];
|
||||
uint8_t scratch[SEC_BLOCK_LEN];
|
||||
uint16_t counter;
|
||||
uint16_t position;
|
||||
wsfHandlerId_t handlerId;
|
||||
uint8_t state;
|
||||
uint8_t *pWorking;
|
||||
} secCcmSecCb_t;
|
||||
|
||||
/*! Security queue element */
|
||||
typedef struct
|
||||
{
|
||||
secMsg_t msg;
|
||||
uint8_t ciphertext[SEC_BLOCK_LEN];
|
||||
uint8_t reserved[SEC_BLOCK_LEN];
|
||||
void *pCb;
|
||||
uint8_t type;
|
||||
} secQueueBuf_t;
|
||||
|
||||
typedef void secHciCback_t(secQueueBuf_t *pBuf, hciEvt_t *pEvent, wsfHandlerId_t handlerId);
|
||||
typedef secHciCback_t *pSecHciCback_t;
|
||||
|
||||
/* Control block */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t rand[SEC_RAND_DATA_LEN]; /* Random data buffer */
|
||||
wsfQueue_t aesEncQueue; /* Queue for AES encrypt requests */
|
||||
wsfQueue_t pubKeyQueue; /* Queue for read p256 public key requests */
|
||||
wsfQueue_t dhKeyQueue; /* Queue for generate dh key requests */
|
||||
uint8_t token; /* Token value */
|
||||
uint8_t randTop; /* Random buffer insert point (HCI_RAND_LEN bytes) */
|
||||
uint8_t randBtm; /* Random buffer copy point (HCI_RAND_LEN bytes) */
|
||||
pSecHciCback_t hciCbackTbl[SEC_NUM_TYPES];
|
||||
} secCb_t;
|
||||
|
||||
/**************************************************************************************************
|
||||
Function Declarations
|
||||
**************************************************************************************************/
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Queue callback and call LE encrypt given most significant byte ordered key and data.
|
||||
*
|
||||
* \param pKey Pointer to key.
|
||||
* \param pText Pointer to text to encrypt.
|
||||
* \param pBuf Pointer to queue block.
|
||||
* \param handlerId Handler ID.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void SecLeEncryptCmd(uint8_t *pKey, uint8_t *pText, void *pBuf, wsfHandlerId_t handlerId);
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* SEC_MAIN_H */
|
||||
Reference in New Issue
Block a user