LoRaWAN MAC layer implementation

Dependents:   LoRa LoRa

Fork of LoRaWAN-lib by Semtech

Committer:
olav
Date:
Mon May 09 08:06:09 2016 +0000
Revision:
4:28021ec4f3ae
Parent:
2:14a5d6ad92d5
initial commit;

Who changed what in which revision?

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