LoRaWAN MAC layer implementation

Dependents:   LoRaWAN-demo-72_tjm LoRaWAN-demo-72_jlc LoRaWAN-demo-elmo frdm_LoRa_Connect_Woodstream_Demo_tjm ... more

LoRAWAN-lib is a port of the GitHub LoRaMac-node LoRaWAN MAC layer implementation.

This library depends on the SX1276Lib or SX1272Lib radio drivers depending on the used mbed component shield.

This library depends also on some cryptographic helper functions as well as helper functions for the timers management. These can be found on the example projects under the system directory.

The example projects are:

  1. LoRaWAN-demo-72
  2. LoRaWAN-demo-76
  3. LoRaWAN-demo-NAMote72

The LoRaWAN specification specifies different ISM bands operating parameters. These are all implemented under the LoRaMac-board.h file.

In order to select which band to use, please change line 24 of board.h file provided on the examples projects as follows:


EU868

board.h

#define USE_BAND_868


US915

board.h

#define USE_BAND_915


US915 - Hybrid

board.h

#define USE_BAND_915_HYBRID


CN780

board.h

#define USE_BAND_780


EU433

board.h

#define USE_BAND_433
Committer:
mluis
Date:
Mon Nov 23 10:09:43 2015 +0000
Revision:
1:91e4e6c60d1e
Parent:
0:91d1a7783bb9
Child:
2:14a5d6ad92d5
Keep LoRaMac only related files in the library.; Updated files according to latest GitHub version

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