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:
ubhat
Date:
Tue Jul 17 22:48:35 2018 +0000
Revision:
11:2426a05fe29e
Parent:
2:14a5d6ad92d5
Fix bug where FCnt get incremented twice in the case of ADRACKReq with D/L ACK

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