Forked LoRaWAN-lib for Legacy Gateway testing
Fork of LoRaWAN-lib by
LoRaMacCrypto.cpp@1:91e4e6c60d1e, 2015-11-23 (annotated)
- 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?
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 | 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 | } |