Example Tx Rx LoRa code for Multitech Conduit. Based on Semtech stack for ELMO - ver. 4.1.0.

Dependencies:   SX1272lib mbed

Committer:
Pasi
Date:
Tue Apr 19 21:48:58 2016 +0000
Revision:
6:71b489e70063
Parent:
1:2be292bd43f9
Text tweaking

Who changed what in which revision?

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