| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- /*
- / _____) _ | |
- ( (____ _____ ____ _| |_ _____ ____| |__
- \____ \| ___ | (_ _) ___ |/ ___) _ \
- _____) ) ____| | | || |_| ____( (___| | | |
- (______/|_____)_|_|_| \__)_____)\____)_| |_|
- (C)2013 Semtech
- ___ _____ _ ___ _ _____ ___ ___ ___ ___
- / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
- \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
- |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
- embedded.connectivity.solutions===============
- Description: LoRa MAC layer implementation
- License: Revised BSD License, see LICENSE.TXT file include in the project
- Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jäckle ( STACKFORCE )
- */
- #include <stdlib.h>
- #include <stdint.h>
- #include "utilities.h"
- #include "aes.h"
- #include "cmac.h"
- #include "LoRaMacCrypto.h"
- #if defined(__CC_ARM) || defined(__GNUC__)
- #define ALIGNED4 __attribute__((aligned(4)))
- #elif defined( __ICCARM__ )
- #define ALIGNED4
- #else
- #warning Not supported compiler type
- #endif
- /*!
- * CMAC/AES Message Integrity Code (MIC) Block B0 size
- */
- #define LORAMAC_MIC_BLOCK_B0_SIZE 16
- /*!
- * MIC field computation initial data
- */
- static uint8_t MicBlockB0[] ALIGNED4 = { 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
- /*!
- * Contains the computed MIC field.
- *
- * \remark Only the 4 first bytes are used
- */
- static uint8_t Mic[16];
- /*!
- * Encryption aBlock and sBlock
- */
- static uint8_t aBlock[] ALIGNED4 = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
- static uint8_t sBlock[] ALIGNED4 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
- /*!
- * AES computation context variable
- */
- static aes_context AesContext ALIGNED4;
- /*!
- * CMAC computation context variable
- */
- static AES_CMAC_CTX AesCmacCtx[1] ALIGNED4;
- /*!
- * \brief Computes the LoRaMAC frame MIC field
- *
- * \param [IN] buffer Data buffer
- * \param [IN] size Data buffer size
- * \param [IN] key AES key to be used
- * \param [IN] address Frame address
- * \param [IN] dir Frame direction [0: uplink, 1: downlink]
- * \param [IN] sequenceCounter Frame sequence counter
- * \param [OUT] mic Computed MIC field
- */
- 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 )
- {
- MicBlockB0[5] = dir;
-
- MicBlockB0[6] = ( address ) & 0xFF;
- MicBlockB0[7] = ( address >> 8 ) & 0xFF;
- MicBlockB0[8] = ( address >> 16 ) & 0xFF;
- MicBlockB0[9] = ( address >> 24 ) & 0xFF;
- MicBlockB0[10] = ( sequenceCounter ) & 0xFF;
- MicBlockB0[11] = ( sequenceCounter >> 8 ) & 0xFF;
- MicBlockB0[12] = ( sequenceCounter >> 16 ) & 0xFF;
- MicBlockB0[13] = ( sequenceCounter >> 24 ) & 0xFF;
- MicBlockB0[15] = size & 0xFF;
- AES_CMAC_Init( AesCmacCtx );
- AES_CMAC_SetKey( AesCmacCtx, key );
- AES_CMAC_Update( AesCmacCtx, MicBlockB0, LORAMAC_MIC_BLOCK_B0_SIZE );
-
- AES_CMAC_Update( AesCmacCtx, buffer, size & 0xFF );
-
- AES_CMAC_Final( Mic, AesCmacCtx );
-
- *mic = ( uint32_t )( ( uint32_t )Mic[3] << 24 | ( uint32_t )Mic[2] << 16 | ( uint32_t )Mic[1] << 8 | ( uint32_t )Mic[0] );
- }
- 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 )
- {
- uint16_t i;
- uint8_t bufferIndex = 0;
- uint16_t ctr = 1;
- memset1( AesContext.ksch, '\0', 240 );
- aes_set_key( key, 16, &AesContext );
- aBlock[5] = dir;
- aBlock[6] = ( address ) & 0xFF;
- aBlock[7] = ( address >> 8 ) & 0xFF;
- aBlock[8] = ( address >> 16 ) & 0xFF;
- aBlock[9] = ( address >> 24 ) & 0xFF;
- aBlock[10] = ( sequenceCounter ) & 0xFF;
- aBlock[11] = ( sequenceCounter >> 8 ) & 0xFF;
- aBlock[12] = ( sequenceCounter >> 16 ) & 0xFF;
- aBlock[13] = ( sequenceCounter >> 24 ) & 0xFF;
- while( size >= 16 )
- {
- aBlock[15] = ( ( ctr ) & 0xFF );
- ctr++;
- aes_encrypt( aBlock, sBlock, &AesContext );
- for( i = 0; i < 16; i++ )
- {
- encBuffer[bufferIndex + i] = buffer[bufferIndex + i] ^ sBlock[i];
- }
- size -= 16;
- bufferIndex += 16;
- }
- if( size > 0 )
- {
- aBlock[15] = ( ( ctr ) & 0xFF );
- aes_encrypt( aBlock, sBlock, &AesContext );
- for( i = 0; i < size; i++ )
- {
- encBuffer[bufferIndex + i] = buffer[bufferIndex + i] ^ sBlock[i];
- }
- }
- }
- 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 )
- {
- LoRaMacPayloadEncrypt( buffer, size, key, address, dir, sequenceCounter, decBuffer );
- }
- void LoRaMacJoinComputeMic( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t *mic )
- {
- AES_CMAC_Init( AesCmacCtx );
- AES_CMAC_SetKey( AesCmacCtx, key );
- AES_CMAC_Update( AesCmacCtx, buffer, size & 0xFF );
- AES_CMAC_Final( Mic, AesCmacCtx );
- *mic = ( uint32_t )( ( uint32_t )Mic[3] << 24 | ( uint32_t )Mic[2] << 16 | ( uint32_t )Mic[1] << 8 | ( uint32_t )Mic[0] );
- }
- void LoRaMacJoinDecrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint8_t *decBuffer )
- {
- memset1( AesContext.ksch, '\0', 240 );
- aes_set_key( key, 16, &AesContext );
- aes_encrypt( buffer, decBuffer, &AesContext );
- // Check if optional CFList is included
- if( size >= 16 )
- {
- aes_encrypt( buffer + 16, decBuffer + 16, &AesContext );
- }
- }
- void LoRaMacJoinComputeSKeys( const uint8_t *key, const uint8_t *appNonce, uint16_t devNonce, uint8_t *nwkSKey, uint8_t *appSKey )
- {
- uint8_t nonce[16];
- uint8_t *pDevNonce = ( uint8_t * )&devNonce;
-
- memset1( AesContext.ksch, '\0', 240 );
- aes_set_key( key, 16, &AesContext );
- memset1( nonce, 0, sizeof( nonce ) );
- nonce[0] = 0x01;
- memcpy1( nonce + 1, appNonce, 6 );
- memcpy1( nonce + 7, pDevNonce, 2 );
- aes_encrypt( nonce, nwkSKey, &AesContext );
- memset1( nonce, 0, sizeof( nonce ) );
- nonce[0] = 0x02;
- memcpy1( nonce + 1, appNonce, 6 );
- memcpy1( nonce + 7, pDevNonce, 2 );
- aes_encrypt( nonce, appSKey, &AesContext );
- }
|