20171208

Fork of LoRaWAN-lib by Semtech

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