end node on synchronous star LoRa network.

Dependencies:   SX127x sx12xx_hal TSL2561

radio chip selection

Radio chip driver is not included, allowing choice of radio device.
If you're using SX1272 or SX1276, then import sx127x driver into your program.
if you're using SX1261 or SX1262, then import sx126x driver into your program.
if you're using SX1280, then import sx1280 driver into your program.
If you're using NAmote72 or Murata discovery, then you must import only sx127x driver.

This project for use with LoRaWAN_singlechannel_gateway project.

Alternately gateway running on raspberry pi can be used as gateway.

LoRaWAN on single radio channel

Network description is at gateway project page. Synchronous star network.

Hardware Support

This project supports SX1276 and SX1272, sx126x kit, sx126x shield, and sx128x 2.4GHz. The ST board B-L072Z-LRWAN1 is also supported (TypeABZ module). When B-L072Z-LRWAN1 target is selected, TARGET_DISCO_L072CZ_LRWAN1 is defined by tools, allowing correct radio driver configuration for this platform. Alternately, any mbed board that can use LoRa radio shield board should work, but NUCLEO boards are tested.

End-node Unique ID

DevEUI is created from CPU serial number. AppEUI and AppKey are declared as software constants.

End-node Configuration

Data rate definition LORAMAC_DEFAULT_DATARATE configured in LoRaMac-definitions.h. See gateway project page for configuration of gateway.
LoRaWAN addressing is configured in Comissioning.h; only OTA mode is functional.
Header file board/lora_config.h, selects application layer options (i.e. sensors) to be compiled in.

Serial Interface

Serial port operates at 115200bps.
Application layer single_us915_main.cpp User button triggers uplink (i.e. blue button on nucleo board), or jumper enables continuously sends repeated uplink packets. The MAC layer holds each uplink request until the allocated timeslot.

commandargumentsdescription
?-print available commands
. (period)-print status (DevEUI, DevAddr, etc)
ullength integerset payload length of test uplink packets

sensor demo

Selected grove sensors may be plugged into SX1272 shield.
To enable, edit lora_config.h to define SENSORS.

Sensor connections on SX1272MB2xAS:

D8 D9: buttonRX TX: (unused)A3 A4: Rotary Angle Sensor
D6 D7: RGB LEDSCL SDA: digital light sensorA1 A2: Rotary Angle Sensor

Digital input pin, state reported via uplink: PC8
Digital output pin, controlled via downlink: PC6
PWM out: PB_10

Jumper enables auto-repeated transmit: PC10 and PC12 on NUCLEO board, located on end of morpho headers nearby JP4.

Committer:
Wayne Roberts
Date:
Mon Jul 13 09:15:59 2020 -0700
Revision:
35:be452a242876
Parent:
34:9c8966cd66a2
remove old crypto

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Wayne Roberts 34:9c8966cd66a2 1 /* */
dudmuck 0:8f0d0ae0a077 2
dudmuck 0:8f0d0ae0a077 3 #include <stdlib.h>
dudmuck 0:8f0d0ae0a077 4 #include <stdint.h>
dudmuck 0:8f0d0ae0a077 5 #include "utilities.h"
dudmuck 0:8f0d0ae0a077 6
Wayne Roberts 34:9c8966cd66a2 7 #include "cmac.h"
Wayne Roberts 34:9c8966cd66a2 8 #include "aes.h"
dudmuck 0:8f0d0ae0a077 9
dudmuck 0:8f0d0ae0a077 10 #include "LoRaMacCrypto.h"
dudmuck 0:8f0d0ae0a077 11
dudmuck 0:8f0d0ae0a077 12 /*!
dudmuck 0:8f0d0ae0a077 13 * CMAC/AES Message Integrity Code (MIC) Block B0 size
dudmuck 0:8f0d0ae0a077 14 */
dudmuck 0:8f0d0ae0a077 15 #define LORAMAC_MIC_BLOCK_B0_SIZE 16
dudmuck 0:8f0d0ae0a077 16
dudmuck 0:8f0d0ae0a077 17 /*!
dudmuck 0:8f0d0ae0a077 18 * MIC field computation initial data
dudmuck 0:8f0d0ae0a077 19 */
dudmuck 0:8f0d0ae0a077 20 static uint8_t MicBlockB0[] = { 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
dudmuck 0:8f0d0ae0a077 21 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
dudmuck 0:8f0d0ae0a077 22 };
dudmuck 0:8f0d0ae0a077 23
dudmuck 0:8f0d0ae0a077 24 /*!
dudmuck 0:8f0d0ae0a077 25 * Contains the computed MIC field.
dudmuck 0:8f0d0ae0a077 26 *
dudmuck 0:8f0d0ae0a077 27 * \remark Only the 4 first bytes are used
dudmuck 0:8f0d0ae0a077 28 */
dudmuck 0:8f0d0ae0a077 29 static uint8_t Mic[16];
dudmuck 0:8f0d0ae0a077 30
dudmuck 0:8f0d0ae0a077 31 /*!
dudmuck 0:8f0d0ae0a077 32 * Encryption aBlock and sBlock
dudmuck 0:8f0d0ae0a077 33 */
dudmuck 0:8f0d0ae0a077 34 static uint8_t aBlock[] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
dudmuck 0:8f0d0ae0a077 35 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
dudmuck 0:8f0d0ae0a077 36 };
dudmuck 0:8f0d0ae0a077 37 static uint8_t sBlock[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
dudmuck 0:8f0d0ae0a077 38 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
dudmuck 0:8f0d0ae0a077 39 };
dudmuck 0:8f0d0ae0a077 40
Wayne Roberts 34:9c8966cd66a2 41 static mbedtls_cipher_context_t ctx;
dudmuck 0:8f0d0ae0a077 42
dudmuck 0:8f0d0ae0a077 43 /*!
dudmuck 0:8f0d0ae0a077 44 * \brief Computes the LoRaMAC frame MIC field
dudmuck 0:8f0d0ae0a077 45 *
dudmuck 0:8f0d0ae0a077 46 * \param [IN] buffer Data buffer
dudmuck 0:8f0d0ae0a077 47 * \param [IN] size Data buffer size
dudmuck 0:8f0d0ae0a077 48 * \param [IN] key AES key to be used
dudmuck 0:8f0d0ae0a077 49 * \param [IN] address Frame address
dudmuck 0:8f0d0ae0a077 50 * \param [IN] dir Frame direction [0: uplink, 1: downlink]
dudmuck 0:8f0d0ae0a077 51 * \param [IN] sequenceCounter Frame sequence counter
dudmuck 0:8f0d0ae0a077 52 * \param [OUT] mic Computed MIC field
dudmuck 0:8f0d0ae0a077 53 */
Wayne Roberts 34:9c8966cd66a2 54 int LoRaMacComputeMic( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint32_t *mic )
dudmuck 0:8f0d0ae0a077 55 {
Wayne Roberts 34:9c8966cd66a2 56 //tls_printf("LoRaMacComputeMic:\r\n");
dudmuck 0:8f0d0ae0a077 57 MicBlockB0[5] = dir;
dudmuck 0:8f0d0ae0a077 58
dudmuck 0:8f0d0ae0a077 59 MicBlockB0[6] = ( address ) & 0xFF;
dudmuck 0:8f0d0ae0a077 60 MicBlockB0[7] = ( address >> 8 ) & 0xFF;
dudmuck 0:8f0d0ae0a077 61 MicBlockB0[8] = ( address >> 16 ) & 0xFF;
dudmuck 0:8f0d0ae0a077 62 MicBlockB0[9] = ( address >> 24 ) & 0xFF;
dudmuck 0:8f0d0ae0a077 63
dudmuck 0:8f0d0ae0a077 64 MicBlockB0[10] = ( sequenceCounter ) & 0xFF;
dudmuck 0:8f0d0ae0a077 65 MicBlockB0[11] = ( sequenceCounter >> 8 ) & 0xFF;
dudmuck 0:8f0d0ae0a077 66 MicBlockB0[12] = ( sequenceCounter >> 16 ) & 0xFF;
dudmuck 0:8f0d0ae0a077 67 MicBlockB0[13] = ( sequenceCounter >> 24 ) & 0xFF;
dudmuck 0:8f0d0ae0a077 68
dudmuck 0:8f0d0ae0a077 69 MicBlockB0[15] = size & 0xFF;
dudmuck 0:8f0d0ae0a077 70
Wayne Roberts 34:9c8966cd66a2 71 if (mbedtls_cipher_cmac_starts(&ctx, key, 128))
Wayne Roberts 34:9c8966cd66a2 72 return -1;
Wayne Roberts 34:9c8966cd66a2 73
Wayne Roberts 34:9c8966cd66a2 74 mbedtls_cipher_cmac_update(&ctx, MicBlockB0, LORAMAC_MIC_BLOCK_B0_SIZE);
Wayne Roberts 34:9c8966cd66a2 75
Wayne Roberts 34:9c8966cd66a2 76 mbedtls_cipher_cmac_update(&ctx, buffer, size & 0xff);
Wayne Roberts 34:9c8966cd66a2 77
Wayne Roberts 34:9c8966cd66a2 78 mbedtls_cipher_cmac_finish(&ctx, Mic);
dudmuck 0:8f0d0ae0a077 79 *mic = ( uint32_t )( ( uint32_t )Mic[3] << 24 | ( uint32_t )Mic[2] << 16 | ( uint32_t )Mic[1] << 8 | ( uint32_t )Mic[0] );
Wayne Roberts 34:9c8966cd66a2 80 return 0;
dudmuck 0:8f0d0ae0a077 81 }
dudmuck 0:8f0d0ae0a077 82
dudmuck 0:8f0d0ae0a077 83 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 )
dudmuck 0:8f0d0ae0a077 84 {
Wayne Roberts 34:9c8966cd66a2 85 mbedtls_aes_context actx;
dudmuck 0:8f0d0ae0a077 86 uint16_t i;
dudmuck 0:8f0d0ae0a077 87 uint8_t bufferIndex = 0;
dudmuck 0:8f0d0ae0a077 88 uint16_t ctr = 1;
dudmuck 0:8f0d0ae0a077 89
Wayne Roberts 34:9c8966cd66a2 90 mbedtls_aes_init(&actx);
Wayne Roberts 34:9c8966cd66a2 91 mbedtls_aes_setkey_enc(&actx, key, 128);
dudmuck 0:8f0d0ae0a077 92
dudmuck 0:8f0d0ae0a077 93 aBlock[5] = dir;
dudmuck 0:8f0d0ae0a077 94
dudmuck 0:8f0d0ae0a077 95 aBlock[6] = ( address ) & 0xFF;
dudmuck 0:8f0d0ae0a077 96 aBlock[7] = ( address >> 8 ) & 0xFF;
dudmuck 0:8f0d0ae0a077 97 aBlock[8] = ( address >> 16 ) & 0xFF;
dudmuck 0:8f0d0ae0a077 98 aBlock[9] = ( address >> 24 ) & 0xFF;
dudmuck 0:8f0d0ae0a077 99
dudmuck 0:8f0d0ae0a077 100 aBlock[10] = ( sequenceCounter ) & 0xFF;
dudmuck 0:8f0d0ae0a077 101 aBlock[11] = ( sequenceCounter >> 8 ) & 0xFF;
dudmuck 0:8f0d0ae0a077 102 aBlock[12] = ( sequenceCounter >> 16 ) & 0xFF;
dudmuck 0:8f0d0ae0a077 103 aBlock[13] = ( sequenceCounter >> 24 ) & 0xFF;
dudmuck 0:8f0d0ae0a077 104
dudmuck 0:8f0d0ae0a077 105 while( size >= 16 )
dudmuck 0:8f0d0ae0a077 106 {
dudmuck 0:8f0d0ae0a077 107 aBlock[15] = ( ( ctr ) & 0xFF );
dudmuck 0:8f0d0ae0a077 108 ctr++;
Wayne Roberts 34:9c8966cd66a2 109 mbedtls_aes_encrypt(&actx, aBlock, sBlock);
dudmuck 0:8f0d0ae0a077 110 for( i = 0; i < 16; i++ )
dudmuck 0:8f0d0ae0a077 111 {
dudmuck 0:8f0d0ae0a077 112 encBuffer[bufferIndex + i] = buffer[bufferIndex + i] ^ sBlock[i];
dudmuck 0:8f0d0ae0a077 113 }
dudmuck 0:8f0d0ae0a077 114 size -= 16;
dudmuck 0:8f0d0ae0a077 115 bufferIndex += 16;
dudmuck 0:8f0d0ae0a077 116 }
dudmuck 0:8f0d0ae0a077 117
Wayne Roberts 34:9c8966cd66a2 118 if (size > 0)
dudmuck 0:8f0d0ae0a077 119 {
dudmuck 0:8f0d0ae0a077 120 aBlock[15] = ( ( ctr ) & 0xFF );
Wayne Roberts 34:9c8966cd66a2 121 mbedtls_aes_encrypt(&actx, aBlock, sBlock);
dudmuck 0:8f0d0ae0a077 122 for( i = 0; i < size; i++ )
dudmuck 0:8f0d0ae0a077 123 {
dudmuck 0:8f0d0ae0a077 124 encBuffer[bufferIndex + i] = buffer[bufferIndex + i] ^ sBlock[i];
dudmuck 0:8f0d0ae0a077 125 }
dudmuck 0:8f0d0ae0a077 126 }
Wayne Roberts 34:9c8966cd66a2 127
Wayne Roberts 34:9c8966cd66a2 128 mbedtls_aes_free(&actx);
dudmuck 0:8f0d0ae0a077 129 }
dudmuck 0:8f0d0ae0a077 130
Wayne Roberts 34:9c8966cd66a2 131 void LoRaMacPayloadDecrypt(
Wayne Roberts 34:9c8966cd66a2 132 const uint8_t *buffer,
Wayne Roberts 34:9c8966cd66a2 133 uint16_t size,
Wayne Roberts 34:9c8966cd66a2 134 const uint8_t *key,
Wayne Roberts 34:9c8966cd66a2 135 uint32_t address,
Wayne Roberts 34:9c8966cd66a2 136 uint8_t dir,
Wayne Roberts 34:9c8966cd66a2 137 uint32_t sequenceCounter,
Wayne Roberts 34:9c8966cd66a2 138 uint8_t *decBuffer )
dudmuck 0:8f0d0ae0a077 139 {
dudmuck 0:8f0d0ae0a077 140 LoRaMacPayloadEncrypt( buffer, size, key, address, dir, sequenceCounter, decBuffer );
dudmuck 0:8f0d0ae0a077 141 }
dudmuck 0:8f0d0ae0a077 142
Wayne Roberts 34:9c8966cd66a2 143 int LoRaMacJoinComputeMic( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t *mic )
dudmuck 0:8f0d0ae0a077 144 {
Wayne Roberts 34:9c8966cd66a2 145 int ret;
Wayne Roberts 34:9c8966cd66a2 146 uint8_t Mic[16];
Wayne Roberts 34:9c8966cd66a2 147 ret = mbedtls_cipher_cmac_starts(&ctx, key, 128);
Wayne Roberts 34:9c8966cd66a2 148 if (ret < 0)
Wayne Roberts 34:9c8966cd66a2 149 return ret;
Wayne Roberts 34:9c8966cd66a2 150 ret = mbedtls_cipher_cmac_update(&ctx, buffer, size & 0xff);
Wayne Roberts 34:9c8966cd66a2 151 if (ret < 0)
Wayne Roberts 34:9c8966cd66a2 152 return ret;
Wayne Roberts 34:9c8966cd66a2 153 ret = mbedtls_cipher_cmac_finish(&ctx, Mic);
Wayne Roberts 34:9c8966cd66a2 154 if (ret < 0)
Wayne Roberts 34:9c8966cd66a2 155 return ret;
dudmuck 0:8f0d0ae0a077 156 *mic = ( uint32_t )( ( uint32_t )Mic[3] << 24 | ( uint32_t )Mic[2] << 16 | ( uint32_t )Mic[1] << 8 | ( uint32_t )Mic[0] );
Wayne Roberts 34:9c8966cd66a2 157 return 0;
dudmuck 0:8f0d0ae0a077 158 }
dudmuck 0:8f0d0ae0a077 159
Wayne Roberts 34:9c8966cd66a2 160 int LoRaMacJoinDecrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint8_t *decBuffer )
dudmuck 0:8f0d0ae0a077 161 {
Wayne Roberts 34:9c8966cd66a2 162 int ret;
Wayne Roberts 34:9c8966cd66a2 163 mbedtls_aes_context actx;
Wayne Roberts 34:9c8966cd66a2 164
Wayne Roberts 34:9c8966cd66a2 165 mbedtls_aes_init(&actx);
Wayne Roberts 34:9c8966cd66a2 166 ret = mbedtls_aes_setkey_enc(&actx, key, 128);
Wayne Roberts 34:9c8966cd66a2 167 if (ret < 0)
Wayne Roberts 34:9c8966cd66a2 168 return -1;
Wayne Roberts 34:9c8966cd66a2 169
Wayne Roberts 34:9c8966cd66a2 170 mbedtls_aes_encrypt(&actx, buffer, decBuffer);
Wayne Roberts 34:9c8966cd66a2 171
Wayne Roberts 34:9c8966cd66a2 172 if (size >= 16) {
Wayne Roberts 34:9c8966cd66a2 173 mbedtls_aes_encrypt(&actx, buffer + 16, decBuffer + 16);
dudmuck 0:8f0d0ae0a077 174 }
Wayne Roberts 34:9c8966cd66a2 175
Wayne Roberts 34:9c8966cd66a2 176 mbedtls_aes_free(&actx);
Wayne Roberts 34:9c8966cd66a2 177
Wayne Roberts 34:9c8966cd66a2 178 return 0;
dudmuck 0:8f0d0ae0a077 179 }
dudmuck 0:8f0d0ae0a077 180
Wayne Roberts 34:9c8966cd66a2 181 int LoRaMacJoinComputeSKeys( const uint8_t *key, const uint8_t *appNonce, uint16_t devNonce, uint8_t *nwkSKey, uint8_t *appSKey )
dudmuck 0:8f0d0ae0a077 182 {
Wayne Roberts 34:9c8966cd66a2 183 mbedtls_aes_context actx;
dudmuck 0:8f0d0ae0a077 184 uint8_t nonce[16];
dudmuck 0:8f0d0ae0a077 185 uint8_t *pDevNonce = ( uint8_t * )&devNonce;
Wayne Roberts 34:9c8966cd66a2 186
Wayne Roberts 34:9c8966cd66a2 187 mbedtls_aes_init(&actx);
Wayne Roberts 34:9c8966cd66a2 188 if (mbedtls_aes_setkey_enc(&actx, key, 128) < 0)
Wayne Roberts 34:9c8966cd66a2 189 return -1;
dudmuck 0:8f0d0ae0a077 190
dudmuck 0:8f0d0ae0a077 191 memset1( nonce, 0, sizeof( nonce ) );
dudmuck 0:8f0d0ae0a077 192 nonce[0] = 0x01;
dudmuck 0:8f0d0ae0a077 193 memcpy1( nonce + 1, appNonce, 6 );
dudmuck 0:8f0d0ae0a077 194 memcpy1( nonce + 7, pDevNonce, 2 );
Wayne Roberts 34:9c8966cd66a2 195 mbedtls_aes_encrypt(&actx, nonce, nwkSKey);
dudmuck 0:8f0d0ae0a077 196
dudmuck 0:8f0d0ae0a077 197 memset1( nonce, 0, sizeof( nonce ) );
dudmuck 0:8f0d0ae0a077 198 nonce[0] = 0x02;
dudmuck 0:8f0d0ae0a077 199 memcpy1( nonce + 1, appNonce, 6 );
dudmuck 0:8f0d0ae0a077 200 memcpy1( nonce + 7, pDevNonce, 2 );
Wayne Roberts 34:9c8966cd66a2 201 mbedtls_aes_encrypt(&actx, nonce, appSKey);
Wayne Roberts 34:9c8966cd66a2 202
Wayne Roberts 34:9c8966cd66a2 203 mbedtls_aes_free(&actx);
Wayne Roberts 34:9c8966cd66a2 204
Wayne Roberts 34:9c8966cd66a2 205 return 0;
dudmuck 0:8f0d0ae0a077 206 }
Wayne Roberts 34:9c8966cd66a2 207
Wayne Roberts 34:9c8966cd66a2 208 int LoRaMacCryptoInit()
Wayne Roberts 34:9c8966cd66a2 209 {
Wayne Roberts 34:9c8966cd66a2 210 int ret;
Wayne Roberts 34:9c8966cd66a2 211 const mbedtls_cipher_info_t *cipher_info;
Wayne Roberts 34:9c8966cd66a2 212 mbedtls_cipher_init(&ctx);
Wayne Roberts 34:9c8966cd66a2 213 cipher_info = mbedtls_cipher_info_from_type( MBEDTLS_CIPHER_AES_128_ECB );
Wayne Roberts 34:9c8966cd66a2 214 if (cipher_info == NULL) {
Wayne Roberts 34:9c8966cd66a2 215 return -1;
Wayne Roberts 34:9c8966cd66a2 216 }
Wayne Roberts 34:9c8966cd66a2 217 ret = mbedtls_cipher_setup(&ctx, cipher_info);
Wayne Roberts 34:9c8966cd66a2 218 return ret;
Wayne Roberts 34:9c8966cd66a2 219 }
Wayne Roberts 34:9c8966cd66a2 220