Espotel / Mbed 2 deprecated LoRaWAN_Semtech_stack

Dependencies:   SX1272lib mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers LoRaMacCrypto.cpp Source File

LoRaMacCrypto.cpp

00001 /*
00002  / _____)             _              | |
00003 ( (____  _____ ____ _| |_ _____  ____| |__
00004  \____ \| ___ |    (_   _) ___ |/ ___)  _ \
00005  _____) ) ____| | | || |_| ____( (___| | | |
00006 (______/|_____)_|_|_| \__)_____)\____)_| |_|
00007     (C)2013 Semtech
00008 Description: LoRa MAC layer implementation
00009 License: Revised BSD License, see LICENSE.TXT file include in the project
00010 Maintainer: Miguel Luis and Gregory Cristian
00011 */
00012 #include <stdlib.h>
00013 #include <stdint.h>
00014 #include "utilities.h"
00015 
00016 #include "aes.h"
00017 #include "cmac.h"
00018 
00019 #include "LoRaMacCrypto.h"
00020 
00021 /*!
00022  * CMAC/AES Message Integrity Code (MIC) Block B0 size
00023  */
00024 #define LORAMAC_MIC_BLOCK_B0_SIZE                   16
00025 
00026 /*!
00027  * MIC field computation initial data
00028  */
00029 static uint8_t MicBlockB0[] = { 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00030                                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
00031                               };
00032 
00033 /*!
00034  * Contains the computed MIC field.
00035  *
00036  * \remark Only the 4 first bytes are used
00037  */
00038 static uint8_t Mic[16];
00039 
00040 /*!
00041  * Encryption aBlock and sBlock
00042  */
00043 static uint8_t aBlock[] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00044                             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
00045                           };
00046 static uint8_t sBlock[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00047                             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
00048                           };
00049 
00050 /*!
00051  * AES computation context variable
00052  */
00053 static aes_context AesContext;
00054 
00055 /*!
00056  * CMAC computation context variable
00057  */
00058 static AES_CMAC_CTX AesCmacCtx[1];
00059 
00060 /*!
00061  * \brief Computes the LoRaMAC frame MIC field  
00062  *
00063  * \param [IN]  buffer          Data buffer
00064  * \param [IN]  size            Data buffer size
00065  * \param [IN]  key             AES key to be used
00066  * \param [IN]  address         Frame address
00067  * \param [IN]  dir             Frame direction [0: uplink, 1: downlink]
00068  * \param [IN]  sequenceCounter Frame sequence counter
00069  * \param [OUT] mic Computed MIC field
00070  */
00071 void LoRaMacComputeMic( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint32_t *mic )
00072 {
00073     MicBlockB0[5] = dir;
00074     
00075     MicBlockB0[6] = ( address ) & 0xFF;
00076     MicBlockB0[7] = ( address >> 8 ) & 0xFF;
00077     MicBlockB0[8] = ( address >> 16 ) & 0xFF;
00078     MicBlockB0[9] = ( address >> 24 ) & 0xFF;
00079 
00080     MicBlockB0[10] = ( sequenceCounter ) & 0xFF;
00081     MicBlockB0[11] = ( sequenceCounter >> 8 ) & 0xFF;
00082     MicBlockB0[12] = ( sequenceCounter >> 16 ) & 0xFF;
00083     MicBlockB0[13] = ( sequenceCounter >> 24 ) & 0xFF;
00084 
00085     MicBlockB0[15] = size & 0xFF;
00086 
00087     AES_CMAC_Init( AesCmacCtx );
00088 
00089     AES_CMAC_SetKey( AesCmacCtx, key );
00090 
00091     AES_CMAC_Update( AesCmacCtx, MicBlockB0, LORAMAC_MIC_BLOCK_B0_SIZE );
00092     
00093     AES_CMAC_Update( AesCmacCtx, buffer, size & 0xFF );
00094     
00095     AES_CMAC_Final( Mic, AesCmacCtx );
00096     
00097     *mic = ( uint32_t )( ( uint32_t )Mic[3] << 24 | ( uint32_t )Mic[2] << 16 | ( uint32_t )Mic[1] << 8 | ( uint32_t )Mic[0] );
00098 }
00099 
00100 void LoRaMacPayloadEncrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint8_t *encBuffer )
00101 {
00102     uint16_t i;
00103     uint8_t bufferIndex = 0;
00104     uint16_t ctr = 1;
00105 
00106     memset1( AesContext.ksch, '\0', 240 );
00107     aes_set_key( key, 16, &AesContext );
00108 
00109     aBlock[5] = dir;
00110 
00111     aBlock[6] = ( address ) & 0xFF;
00112     aBlock[7] = ( address >> 8 ) & 0xFF;
00113     aBlock[8] = ( address >> 16 ) & 0xFF;
00114     aBlock[9] = ( address >> 24 ) & 0xFF;
00115 
00116     aBlock[10] = ( sequenceCounter ) & 0xFF;
00117     aBlock[11] = ( sequenceCounter >> 8 ) & 0xFF;
00118     aBlock[12] = ( sequenceCounter >> 16 ) & 0xFF;
00119     aBlock[13] = ( sequenceCounter >> 24 ) & 0xFF;
00120 
00121     while( size >= 16 )
00122     {
00123         aBlock[15] = ( ( ctr ) & 0xFF );
00124         ctr++;
00125         aes_encrypt( aBlock, sBlock, &AesContext );
00126         for( i = 0; i < 16; i++ )
00127         {
00128             encBuffer[bufferIndex + i] = buffer[bufferIndex + i] ^ sBlock[i];
00129         }
00130         size -= 16;
00131         bufferIndex += 16;
00132     }
00133 
00134     if( size > 0 )
00135     {
00136         aBlock[15] = ( ( ctr ) & 0xFF );
00137         aes_encrypt( aBlock, sBlock, &AesContext );
00138         for( i = 0; i < size; i++ )
00139         {
00140             encBuffer[bufferIndex + i] = buffer[bufferIndex + i] ^ sBlock[i];
00141         }
00142     }
00143 }
00144 
00145 void LoRaMacPayloadDecrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint8_t *decBuffer )
00146 {
00147     LoRaMacPayloadEncrypt( buffer, size, key, address, dir, sequenceCounter, decBuffer );
00148 }
00149 
00150 void LoRaMacJoinComputeMic( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t *mic )
00151 {
00152     AES_CMAC_Init( AesCmacCtx );
00153 
00154     AES_CMAC_SetKey( AesCmacCtx, key );
00155 
00156     AES_CMAC_Update( AesCmacCtx, buffer, size & 0xFF );
00157 
00158     AES_CMAC_Final( Mic, AesCmacCtx );
00159 
00160     *mic = ( uint32_t )( ( uint32_t )Mic[3] << 24 | ( uint32_t )Mic[2] << 16 | ( uint32_t )Mic[1] << 8 | ( uint32_t )Mic[0] );
00161 }
00162 
00163 void LoRaMacJoinDecrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint8_t *decBuffer )
00164 {
00165     memset1( AesContext.ksch, '\0', 240 );
00166     aes_set_key( key, 16, &AesContext );
00167     aes_encrypt( buffer, decBuffer, &AesContext );
00168     // Check if optional CFList is included
00169     if( size >= 16 )
00170     {
00171         aes_encrypt( buffer + 16, decBuffer + 16, &AesContext );
00172     }
00173 }
00174 
00175 void LoRaMacJoinComputeSKeys( const uint8_t *key, const uint8_t *appNonce, uint16_t devNonce, uint8_t *nwkSKey, uint8_t *appSKey )
00176 {
00177     uint8_t nonce[16];
00178     uint8_t *pDevNonce = ( uint8_t * )&devNonce;
00179     
00180     memset1( AesContext.ksch, '\0', 240 );
00181     aes_set_key( key, 16, &AesContext );
00182 
00183     memset1( nonce, 0, sizeof( nonce ) );
00184     nonce[0] = 0x01;
00185     LoRaMacMemCpy( appNonce, nonce + 1, 6 );
00186     LoRaMacMemCpy( pDevNonce, nonce + 7, 2 );
00187     aes_encrypt( nonce, nwkSKey, &AesContext );
00188 
00189     memset1( nonce, 0, sizeof( nonce ) );
00190     nonce[0] = 0x02;
00191     LoRaMacMemCpy( appNonce, nonce + 1, 6 );
00192     LoRaMacMemCpy( pDevNonce, nonce + 7, 2 );
00193     aes_encrypt( nonce, appSKey, &AesContext );
00194 }