⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hal_rf_security.c

📁 cc2x30_sw_examples: 适用于SmartRF05EB 支持CC2430、CC2530 提供Light_Switch及perTest例程。
💻 C
字号:
/*******************************************************************************

  Filename:       hal_rf_security.c

  Description:    CC2430 CCM security

*******************************************************************************/

/*******************************************************************************
* INCLUDES
*/
#include "hal_board.h"

#include "hal_rf.h"
#include "hal_rf_security.h"
#include "util.h"
#include "string.h"


/*******************************************************************************
* CONSTANTS AND DEFINES
*/


// Staring AES operation
#define AES_START()             st (ENCCS |= 0x01;)

// Setting the mode of the AES operation
#define AES_SET_MODE(mode)      st( ENCCS &= ~0x70; ENCCS |= mode; )

// Starting or stopping encryption or decryption
#define AES_SET_OPERATION(op)   st( ENCCS = (ENCCS & ~0x07) | op; )

// Poll the AES ready bit
#define AES_RDY()              ( ENCCS & 8)

// Encryption mode
#define AES_MODE_CBC            0x00
#define AES_MODE_CFB            0x10
#define AES_MODE_OFB            0x20
#define AES_MODE_CTR            0x30
#define AES_MODE_ECB            0x40
#define AES_MODE_CBCMAC         0x50

// Operations
#define AES_ENCRYPT             0x00
#define AES_DECRYPT             0x02
#define AES_LOAD_KEY            0x04
#define AES_LOAD_IV             0x06



// Convert MIC to MIC length
#define MIC_2_MICLEN(m)         ( BV((m&3)+1) & ~3 )


/*******************************************************************************
* LOCAL DATA
*/
static  uint8 nonceTx[16];
static  uint8 nonceRx[16];
static  uint8 IV[16];
static  uint8 cipherText[128];
static  uint8 buf[128];


/*******************************************************************************
* LOCAL FUNCTIONS
*/
static void halAesEncrypt(uint8 mode, uint8 *pDataIn, uint16 length, uint8 *pDataOut,
                          uint8 *pInitVector);
static void halAesDecrypt(uint8 mode, uint8 *pDataIn, uint16 length, uint8 *pDataOut,
                          uint8 *pInitVector);
static uint8 generateAuthData(uint8 c, uint8 *pIv, uint8 *pData, uint8 f, uint8 lm);




/*******************************************************************************
* GLOBAL FUNCTIONS
*/
extern void halRfAppendTxBuf(uint8* pData, uint8 length);


/*******************************************************************************
* @fn      halRfSecurityInit
*
* @brief   Security init. Write nonces and key to chip.
*
* @param   none
*
* @return  none
*/
void halRfSecurityInit(uint8* pKey, uint8* pNonceRx, uint8* pNonceTx)
{
    uint8 i;

    AES_SET_OPERATION(AES_LOAD_KEY);

    // Starting loading of key or vector.
    AES_START();

    // Store key and nonces
    for (i=0; i<NONCE_LENGTH; i++) {
        nonceRx[i]= *pNonceRx;
        nonceTx[i]= *pNonceTx;
        pNonceTx++;
        pNonceRx++;
        ENCDI = *pKey++;
    }
}



/*******************************************************************************
* @fn      halRfWriteTxBufSecure
*
* @brief   Encrypt and authenticate plaintext then fill TX buffer
*
* @param   uint8* data - data buffer. This must be allocated by caller.
*          uint8 length - number of bytes
*          uint8 c - number of bytes to encrypt
*          uint8 f - number of bytes to authenticate
*          uint8 m - integrity code (m=1,2,3 gives lenght of integrity
*                   field l(m)= 4,8,16)
*
* @return  none
*/
void halRfWriteTxBufSecure(uint8* pPkt, uint8 length, uint8 c, uint8 f, uint8 m)
{
    uint8 i,lm;

    // Generate B(i) vector
    memset(buf,0,sizeof(buf));
    lm= MIC_2_MICLEN(m);
    i= generateAuthData(c,nonceTx,pPkt+1,f,lm);

    // Calculate CBC-MAC value
    memset(IV,0,sizeof(IV));
    halAesEncrypt(AES_MODE_CBCMAC,buf, i, cipherText, IV);

    // Encrypt authentication tag
    memcpy(IV,nonceTx,16);                      // Use nonce as IV
    IV[0]= 0x01;                                // Flag for CTR
    IV[15]= 0;                                  // Counter= 0

    memcpy(buf,cipherText,16);
    halAesEncrypt(AES_MODE_CTR,buf, 16, cipherText, IV);

    // Encrypt plaintext
    memset(buf+i,0,16-(i&0xf));                 // Zero padding
    IV[15]= 1;                                  // Counter= 1
    halAesEncrypt(AES_MODE_CTR,&buf[i-c], c, &cipherText[i-c], IV);

    // Fill TX buffer
    halRfWriteTxBuf(pPkt,1);                    // Length byte
    halRfAppendTxBuf(pPkt+1,f);                 // MPDU
    halRfAppendTxBuf(&cipherText[i-c],c);       // Payload
    halRfAppendTxBuf(cipherText,lm);            // MIC
}


/*******************************************************************************
* @fn      halRfReadRxBufSecure
*
* @brief   Decrypts and reverse authenticates with CCM then reads out received
*          frame
*
* @param   uint8* pPkt - data buffer. This must be allocated by caller.
*          uint8 length - number of bytes
*          uint8 encrLength - number of bytes to decrypt
*          uint8 authLength - number of bytes to reverse authenticate
*          uuint8 m - ets length of integrity code (m=1,2,3 gives lenght of integrity
*                   field 4,8,16)
*
* @return  SUCCESS or FAILED
*/
uint8 halRfReadRxBufSecure(uint8* data, uint8 length, uint8 c, uint8 f, uint8 m)
{
    uint8 lm,l,i;

    // Get received packet
    halRfReadRxBuf(data,length);

    // Update RX nonce; frame counter
    nonceRx[12]= data[10];
    nonceRx[11]= data[11];
    nonceRx[10]= data[12];
    nonceRx[9]= data[13];
    // Update RX nonce; source address
    nonceRx[7]= data[8];
    nonceRx[8]= data[7];

    // Decrypt authentication tag
    memcpy(IV,nonceRx,16);
    IV[15]= 0;                        // Counter= 0
    IV[0]= 0x01;                      // Flag field for decryption
    lm=MIC_2_MICLEN(m);               // Length of authentication tag

    halAesDecrypt(AES_MODE_CTR,data+c+f, lm, buf, IV);
    memcpy(data+c+f,buf,lm);

    // Prepare payload for decryption
    memcpy(cipherText,data+f,c);

    // Zero padding
    l= (c & 0x0f )==0 ? c : (c&0xf0) + 0x10;
    for (i=c; i<l; i++)
        cipherText[i]= 0x00;

    // Decrypt payload
    IV[15]= 1;                       // Counter= 1
    halAesDecrypt(AES_MODE_CTR,cipherText, c, buf, IV);
    memcpy(data+f,buf,c);

    // Generate B(i) vector
    memset(buf,0,sizeof(buf));
    i= generateAuthData(c,nonceRx,data,f,lm);

    // Calculate CBC-MAC value
    memset(IV,0,sizeof(IV));
    halAesEncrypt(AES_MODE_CBCMAC,buf, i, cipherText, IV);

    // Check authentication data
    return memcmp(cipherText,data+c+f,lm)==0 ? SUCCESS : FAILED;
}


/*******************************************************************************
* @fn      halRfIncNonceTx
*
* @brief   Increments frame counter field of stored nonce TX
*
* @param   none
*
* @return  none
*/
void halRfIncNonceTx(void)
{
    uint32 *pCount;

    pCount= (uint32*)&nonceTx[9];
    utilReverseBuf((uint8*)pCount,4);
    (*pCount)++;
    utilReverseBuf((uint8*)pCount,4);
}




/*******************************************************************************
* LOCAL FUNCTIONS
*/


static void halAesLoadBlock(BYTE* pData, uint8 op)
{
   UINT8 i;

   // Set operation
   AES_SET_OPERATION(op);
   // Starting loading of key or vector.
   AES_START();

   // loading the data (key or vector)
   for(i = 0; i < 16; i++){
      ENCDI = pData[i];
   }

   return;
}



static void halAesOperation(uint8 oper,uint8 *pDataIn, uint16 length, uint8 *pDataOut, uint8 *pInitVector)
{
   uint16 i;
   uint8 j, k;
   uint8 mode;
   uint16 nbrOfBlocks;
   uint16 convertedBlock;

   nbrOfBlocks = length / 0x10;

   if((length % 0x10) != 0){
      // length not multiplum of 16, convert one block extra with zeropadding
      nbrOfBlocks++;
   }

   // Loading the IV.
   halAesLoadBlock(pInitVector, AES_LOAD_IV);

   // Start the operation
   AES_SET_OPERATION(oper);

   // Getting the operation mode.
   mode = ENCCS & 0x70;

   for(convertedBlock = 0; convertedBlock < nbrOfBlocks; convertedBlock++){
      // Starting the conversion.
      AES_START();

      i = convertedBlock * 16;
      // Counter, Output Feedback and Cipher Feedback operates on 4 bytes and not 16 bytes.
      if((mode == AES_MODE_CFB) || (mode == AES_MODE_OFB) || (mode == AES_MODE_CTR)) {

         for(j = 0; j < 4; j++){
            // Writing the input data with zero-padding
            for(k = 0; k < 4; k++){
               ENCDI = ((i + 4*j + k < length) ? pDataIn[i + 4*j + k] : 0x00 );
            }

            // Read out data for every 4th byte
            for(k = 0; k < 4; k++){
               pDataOut[i + 4*j + k] = ENCDO;
            }

         }
      }
      else if (mode == AES_MODE_CBCMAC){
         // Writing the input data with zero-padding
         for(j = 0; j < 16; j++){
            ENCDI = ((i + j < length) ? pDataIn[i + j] : 0x00 );
         }
         // The last block of the CBC-MAC is computed by using CBC mode.
         if(convertedBlock == nbrOfBlocks - 2){
            AES_SET_MODE(AES_MODE_CBC);
            // wait for data ready
            halMcuWaitUs(1);
         }
         // The CBC-MAC does not produce an output on the n-1 first blocks
         // only the last block is read out
         else if(convertedBlock == nbrOfBlocks - 1){

             // wait for data ready
             halMcuWaitUs(1);
            for(j = 0; j < 16; j++){
               pDataOut[j] = ENCDO;
            }
         }
      } // ECB or CBC
      else{
         // Writing the input data with zero-padding
         for(j = 0; j < 16; j++){
            ENCDI = ((i+j < length) ? pDataIn[i+j] : 0x00 );
         }

         // wait for data ready
         halMcuWaitUs(1);

         // Read out data
         for(j = 0; j < 16; j++){
            pDataOut[i+j] = ENCDO;
         }
      }
   }
}

static void halAesEncrypt(uint8 mode, uint8 *pDataIn, uint16 length, uint8 *pDataOut, uint8 *pInitVector)
{
    AES_SET_MODE(mode);
    halAesOperation(AES_ENCRYPT,pDataIn,length,pDataOut,pInitVector);
}


static void halAesDecrypt(uint8 mode, uint8 *pDataIn, uint16 length, uint8 *pDataOut, uint8 *pInitVector)
{
    AES_SET_MODE(mode);
    halAesOperation(AES_DECRYPT,pDataIn,length,pDataOut,pInitVector);
}



static uint8 generateAuthData(uint8 c, uint8 *pIv, uint8 *pData, uint8 f, uint8 lm)
{
    uint8 i,j,l;

    // Prepare input for CBC-MAC, B0, Bi.... Bn
    memcpy(buf,pIv,16);             // B0

    // Create flag
    buf[0]=  0x01;                  // L'= L - 1 (L=2)
    if (f>0)
        buf[0]|= 0x40;              // Adata= f > 0
    buf[0]|=  ( (lm-2) / 2 ) <<3;   // M'= (lm-2) / 2;

    buf[14]= 0x00;
    buf[15]= c;

    // Add authentication data
    buf[16]= 0;
    buf[17]= f;
    memcpy(&buf[18],pData,f);

    // .... zero padding
    i= 18 + f;
	l= (i & 0x0f )==0 ? i : (i&0xf0) + 0x10;
    while(i<l)
        buf[i++]= 0x00;

    // Add command payload
    j= 0;
    while(i<l+c) {
        buf[i++]= pData[f+j];
        j++;
    }

    return i;
}

/*------------------------------------------------------------------------------
										  0ooo                                     
								ooo0	 (	 )                                     
								(	)	  ) /                                      
								 \ (	 (_/                                       
								  \_)		 Modify By:cuiqingwei [gary]                  
------------------------------------------------------------------------------*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -