Simplified LoRaWAN library.
Fork of LoRaWAN-lib-v1_0_1 by
LoRaMacCrypto.cpp@12:54937781831b, 2018-04-03 (annotated)
- Committer:
- dgabino
- Date:
- Tue Apr 03 17:01:27 2018 +0000
- Revision:
- 12:54937781831b
- Parent:
- 2:14a5d6ad92d5
Substituted api-v3 with MAC layer service
Who changed what in which revision?
User | Revision | Line number | New 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 | } |