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