Semtech stack for ELMO - ver. 4.1.0.

Dependencies:   SX1272lib mbed

Fork of LoRaWAN_Semtech_stack_v4.1 by Michal Leksinski

Committer:
mleksio
Date:
Wed Dec 16 14:25:16 2015 +0000
Revision:
0:c58229885f95
Child:
1:2be292bd43f9
first commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mleksio 0:c58229885f95 1 /*
mleksio 0:c58229885f95 2 / _____) _ | |
mleksio 0:c58229885f95 3 ( (____ _____ ____ _| |_ _____ ____| |__
mleksio 0:c58229885f95 4 \____ \| ___ | (_ _) ___ |/ ___) _ \
mleksio 0:c58229885f95 5 _____) ) ____| | | || |_| ____( (___| | | |
mleksio 0:c58229885f95 6 (______/|_____)_|_|_| \__)_____)\____)_| |_|
mleksio 0:c58229885f95 7 (C)2013 Semtech
mleksio 0:c58229885f95 8 Description: LoRa MAC layer implementation
mleksio 0:c58229885f95 9 License: Revised BSD License, see LICENSE.TXT file include in the project
mleksio 0:c58229885f95 10 Maintainer: Miguel Luis and Gregory Cristian
mleksio 0:c58229885f95 11 */
mleksio 0:c58229885f95 12 #include <stdlib.h>
mleksio 0:c58229885f95 13 #include <stdint.h>
mleksio 0:c58229885f95 14 #include "utilities.h"
mleksio 0:c58229885f95 15
mleksio 0:c58229885f95 16 #include "aes.h"
mleksio 0:c58229885f95 17 #include "cmac.h"
mleksio 0:c58229885f95 18
mleksio 0:c58229885f95 19 #include "LoRaMacCrypto.h"
mleksio 0:c58229885f95 20
mleksio 0:c58229885f95 21 /*!
mleksio 0:c58229885f95 22 * CMAC/AES Message Integrity Code (MIC) Block B0 size
mleksio 0:c58229885f95 23 */
mleksio 0:c58229885f95 24 #define LORAMAC_MIC_BLOCK_B0_SIZE 16
mleksio 0:c58229885f95 25
mleksio 0:c58229885f95 26 /*!
mleksio 0:c58229885f95 27 * MIC field computation initial data
mleksio 0:c58229885f95 28 */
mleksio 0:c58229885f95 29 static uint8_t MicBlockB0[] = { 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
mleksio 0:c58229885f95 30 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
mleksio 0:c58229885f95 31 };
mleksio 0:c58229885f95 32
mleksio 0:c58229885f95 33 /*!
mleksio 0:c58229885f95 34 * Contains the computed MIC field.
mleksio 0:c58229885f95 35 *
mleksio 0:c58229885f95 36 * \remark Only the 4 first bytes are used
mleksio 0:c58229885f95 37 */
mleksio 0:c58229885f95 38 static uint8_t Mic[16];
mleksio 0:c58229885f95 39
mleksio 0:c58229885f95 40 /*!
mleksio 0:c58229885f95 41 * Encryption aBlock and sBlock
mleksio 0:c58229885f95 42 */
mleksio 0:c58229885f95 43 static uint8_t aBlock[] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
mleksio 0:c58229885f95 44 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
mleksio 0:c58229885f95 45 };
mleksio 0:c58229885f95 46 static uint8_t sBlock[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
mleksio 0:c58229885f95 47 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
mleksio 0:c58229885f95 48 };
mleksio 0:c58229885f95 49
mleksio 0:c58229885f95 50 /*!
mleksio 0:c58229885f95 51 * AES computation context variable
mleksio 0:c58229885f95 52 */
mleksio 0:c58229885f95 53 static aes_context AesContext;
mleksio 0:c58229885f95 54
mleksio 0:c58229885f95 55 /*!
mleksio 0:c58229885f95 56 * CMAC computation context variable
mleksio 0:c58229885f95 57 */
mleksio 0:c58229885f95 58 static AES_CMAC_CTX AesCmacCtx[1];
mleksio 0:c58229885f95 59
mleksio 0:c58229885f95 60 /*!
mleksio 0:c58229885f95 61 * \brief Computes the LoRaMAC frame MIC field
mleksio 0:c58229885f95 62 *
mleksio 0:c58229885f95 63 * \param [IN] buffer Data buffer
mleksio 0:c58229885f95 64 * \param [IN] size Data buffer size
mleksio 0:c58229885f95 65 * \param [IN] key AES key to be used
mleksio 0:c58229885f95 66 * \param [IN] address Frame address
mleksio 0:c58229885f95 67 * \param [IN] dir Frame direction [0: uplink, 1: downlink]
mleksio 0:c58229885f95 68 * \param [IN] sequenceCounter Frame sequence counter
mleksio 0:c58229885f95 69 * \param [OUT] mic Computed MIC field
mleksio 0:c58229885f95 70 */
mleksio 0:c58229885f95 71 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 )
mleksio 0:c58229885f95 72 {
mleksio 0:c58229885f95 73 MicBlockB0[5] = dir;
mleksio 0:c58229885f95 74
mleksio 0:c58229885f95 75 MicBlockB0[6] = ( address ) & 0xFF;
mleksio 0:c58229885f95 76 MicBlockB0[7] = ( address >> 8 ) & 0xFF;
mleksio 0:c58229885f95 77 MicBlockB0[8] = ( address >> 16 ) & 0xFF;
mleksio 0:c58229885f95 78 MicBlockB0[9] = ( address >> 24 ) & 0xFF;
mleksio 0:c58229885f95 79
mleksio 0:c58229885f95 80 MicBlockB0[10] = ( sequenceCounter ) & 0xFF;
mleksio 0:c58229885f95 81 MicBlockB0[11] = ( sequenceCounter >> 8 ) & 0xFF;
mleksio 0:c58229885f95 82 MicBlockB0[12] = ( sequenceCounter >> 16 ) & 0xFF;
mleksio 0:c58229885f95 83 MicBlockB0[13] = ( sequenceCounter >> 24 ) & 0xFF;
mleksio 0:c58229885f95 84
mleksio 0:c58229885f95 85 MicBlockB0[15] = size & 0xFF;
mleksio 0:c58229885f95 86
mleksio 0:c58229885f95 87 AES_CMAC_Init( AesCmacCtx );
mleksio 0:c58229885f95 88
mleksio 0:c58229885f95 89 AES_CMAC_SetKey( AesCmacCtx, key );
mleksio 0:c58229885f95 90
mleksio 0:c58229885f95 91 AES_CMAC_Update( AesCmacCtx, MicBlockB0, LORAMAC_MIC_BLOCK_B0_SIZE );
mleksio 0:c58229885f95 92
mleksio 0:c58229885f95 93 AES_CMAC_Update( AesCmacCtx, buffer, size & 0xFF );
mleksio 0:c58229885f95 94
mleksio 0:c58229885f95 95 AES_CMAC_Final( Mic, AesCmacCtx );
mleksio 0:c58229885f95 96
mleksio 0:c58229885f95 97 *mic = ( uint32_t )( ( uint32_t )Mic[3] << 24 | ( uint32_t )Mic[2] << 16 | ( uint32_t )Mic[1] << 8 | ( uint32_t )Mic[0] );
mleksio 0:c58229885f95 98 }
mleksio 0:c58229885f95 99
mleksio 0:c58229885f95 100 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 )
mleksio 0:c58229885f95 101 {
mleksio 0:c58229885f95 102 uint16_t i;
mleksio 0:c58229885f95 103 uint8_t bufferIndex = 0;
mleksio 0:c58229885f95 104 uint16_t ctr = 1;
mleksio 0:c58229885f95 105
mleksio 0:c58229885f95 106 memset1( AesContext.ksch, '\0', 240 );
mleksio 0:c58229885f95 107 aes_set_key( key, 16, &AesContext );
mleksio 0:c58229885f95 108
mleksio 0:c58229885f95 109 aBlock[5] = dir;
mleksio 0:c58229885f95 110
mleksio 0:c58229885f95 111 aBlock[6] = ( address ) & 0xFF;
mleksio 0:c58229885f95 112 aBlock[7] = ( address >> 8 ) & 0xFF;
mleksio 0:c58229885f95 113 aBlock[8] = ( address >> 16 ) & 0xFF;
mleksio 0:c58229885f95 114 aBlock[9] = ( address >> 24 ) & 0xFF;
mleksio 0:c58229885f95 115
mleksio 0:c58229885f95 116 aBlock[10] = ( sequenceCounter ) & 0xFF;
mleksio 0:c58229885f95 117 aBlock[11] = ( sequenceCounter >> 8 ) & 0xFF;
mleksio 0:c58229885f95 118 aBlock[12] = ( sequenceCounter >> 16 ) & 0xFF;
mleksio 0:c58229885f95 119 aBlock[13] = ( sequenceCounter >> 24 ) & 0xFF;
mleksio 0:c58229885f95 120
mleksio 0:c58229885f95 121 while( size >= 16 )
mleksio 0:c58229885f95 122 {
mleksio 0:c58229885f95 123 aBlock[15] = ( ( ctr ) & 0xFF );
mleksio 0:c58229885f95 124 ctr++;
mleksio 0:c58229885f95 125 aes_encrypt( aBlock, sBlock, &AesContext );
mleksio 0:c58229885f95 126 for( i = 0; i < 16; i++ )
mleksio 0:c58229885f95 127 {
mleksio 0:c58229885f95 128 encBuffer[bufferIndex + i] = buffer[bufferIndex + i] ^ sBlock[i];
mleksio 0:c58229885f95 129 }
mleksio 0:c58229885f95 130 size -= 16;
mleksio 0:c58229885f95 131 bufferIndex += 16;
mleksio 0:c58229885f95 132 }
mleksio 0:c58229885f95 133
mleksio 0:c58229885f95 134 if( size > 0 )
mleksio 0:c58229885f95 135 {
mleksio 0:c58229885f95 136 aBlock[15] = ( ( ctr ) & 0xFF );
mleksio 0:c58229885f95 137 aes_encrypt( aBlock, sBlock, &AesContext );
mleksio 0:c58229885f95 138 for( i = 0; i < size; i++ )
mleksio 0:c58229885f95 139 {
mleksio 0:c58229885f95 140 encBuffer[bufferIndex + i] = buffer[bufferIndex + i] ^ sBlock[i];
mleksio 0:c58229885f95 141 }
mleksio 0:c58229885f95 142 }
mleksio 0:c58229885f95 143 }
mleksio 0:c58229885f95 144
mleksio 0:c58229885f95 145 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 )
mleksio 0:c58229885f95 146 {
mleksio 0:c58229885f95 147 LoRaMacPayloadEncrypt( buffer, size, key, address, dir, sequenceCounter, decBuffer );
mleksio 0:c58229885f95 148 }
mleksio 0:c58229885f95 149
mleksio 0:c58229885f95 150 void LoRaMacJoinComputeMic( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t *mic )
mleksio 0:c58229885f95 151 {
mleksio 0:c58229885f95 152 AES_CMAC_Init( AesCmacCtx );
mleksio 0:c58229885f95 153
mleksio 0:c58229885f95 154 AES_CMAC_SetKey( AesCmacCtx, key );
mleksio 0:c58229885f95 155
mleksio 0:c58229885f95 156 AES_CMAC_Update( AesCmacCtx, buffer, size & 0xFF );
mleksio 0:c58229885f95 157
mleksio 0:c58229885f95 158 AES_CMAC_Final( Mic, AesCmacCtx );
mleksio 0:c58229885f95 159
mleksio 0:c58229885f95 160 *mic = ( uint32_t )( ( uint32_t )Mic[3] << 24 | ( uint32_t )Mic[2] << 16 | ( uint32_t )Mic[1] << 8 | ( uint32_t )Mic[0] );
mleksio 0:c58229885f95 161 }
mleksio 0:c58229885f95 162
mleksio 0:c58229885f95 163 void LoRaMacJoinDecrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint8_t *decBuffer )
mleksio 0:c58229885f95 164 {
mleksio 0:c58229885f95 165 memset1( AesContext.ksch, '\0', 240 );
mleksio 0:c58229885f95 166 aes_set_key( key, 16, &AesContext );
mleksio 0:c58229885f95 167 aes_encrypt( buffer, decBuffer, &AesContext );
mleksio 0:c58229885f95 168 // Check if optional CFList is included
mleksio 0:c58229885f95 169 if( size >= 16 )
mleksio 0:c58229885f95 170 {
mleksio 0:c58229885f95 171 aes_encrypt( buffer + 16, decBuffer + 16, &AesContext );
mleksio 0:c58229885f95 172 }
mleksio 0:c58229885f95 173 }
mleksio 0:c58229885f95 174
mleksio 0:c58229885f95 175 void LoRaMacJoinComputeSKeys( const uint8_t *key, const uint8_t *appNonce, uint16_t devNonce, uint8_t *nwkSKey, uint8_t *appSKey )
mleksio 0:c58229885f95 176 {
mleksio 0:c58229885f95 177 uint8_t nonce[16];
mleksio 0:c58229885f95 178 uint8_t *pDevNonce = ( uint8_t * )&devNonce;
mleksio 0:c58229885f95 179
mleksio 0:c58229885f95 180 memset1( AesContext.ksch, '\0', 240 );
mleksio 0:c58229885f95 181 aes_set_key( key, 16, &AesContext );
mleksio 0:c58229885f95 182
mleksio 0:c58229885f95 183 memset1( nonce, 0, sizeof( nonce ) );
mleksio 0:c58229885f95 184 nonce[0] = 0x01;
mleksio 0:c58229885f95 185 LoRaMacMemCpy( appNonce, nonce + 1, 6 );
mleksio 0:c58229885f95 186 LoRaMacMemCpy( pDevNonce, nonce + 7, 2 );
mleksio 0:c58229885f95 187 aes_encrypt( nonce, nwkSKey, &AesContext );
mleksio 0:c58229885f95 188
mleksio 0:c58229885f95 189 memset1( nonce, 0, sizeof( nonce ) );
mleksio 0:c58229885f95 190 nonce[0] = 0x02;
mleksio 0:c58229885f95 191 LoRaMacMemCpy( appNonce, nonce + 1, 6 );
mleksio 0:c58229885f95 192 LoRaMacMemCpy( pDevNonce, nonce + 7, 2 );
mleksio 0:c58229885f95 193 aes_encrypt( nonce, appSKey, &AesContext );
mleksio 0:c58229885f95 194 }