LoRaWAN end device MAC layer for SX1272 and SX1276. Supports LoRaWAN-1.0 and LoRaWAN-1.1

Dependencies:   sx12xx_hal

Dependents:   LoRaWAN-SanJose_Bootcamp LoRaWAN-grove-cayenne LoRaWAN-classC-demo LoRaWAN-grove-cayenne ... more

radio chip selection

Radio chip driver is not included, because two options are available.
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 NAmote72 or Murata discovery, then you must import only sx127x driver.

application project requirements

This library requires mbed TLS to be enabled.
The file mbed_app.json must be present in the project using this library:

{
    "macros": [ "MBEDTLS_CMAC_C" ]
}

regional PHY selection

All end device configuration is done in Commissioning.h, define desired radio frequency band of operation in this header file.
Commissioning.h is located in the application using this library.

end device provisioning

End device is provisioned by editing Commissioning.h in the application which is using this library
To use LoRaWAN-1.0 OTA: make sure LORAWAN_ROOT_APPKEY is undefined.
To use LoRaWAN-1.1 OTA, define LORAWAN_ROOT_APPKEY.
To select OTA operation, define LORAWAN_JOIN_EUI, then LORAWAN_DEVICE_EUI must be defined, along with root key(s).
To select ABP operation, undefine LORAWAN_JOIN_EUI: then define session keys

LoRaWAN 1.0 nameLoRaWAN 1.1 nameComissioning.h defnedescription
OTADevEUIDevEUILORAWAN_DEVICE_EUIuniquely identifies end device
OTAAppEUIJoinEUILORAWAN_JOIN_EUI
OTAAppKeyNwkKeyLORAWAN_ROOT_NWKKEYroot key for network server
OTA(note 1)AppKeyLORAWAN_ROOT_APPKEYroot key for application server
ABPNwkSKey(note 3)LORAWAN_FNwkSIntKeynetwork session key
ABP(note 2)SNwkSIntKeyLORAWAN_SNwkSIntKeymac layer network integrity key
ABP(note 2)NwkSEncKeyLORAWAN_NwkSEncKeynetwork session encryption key
ABP(note 2)FNwkSIntKeyLORAWAN_FNwkSIntKeyforwarding network session integrity key
ABPAppSKeyAppSKeyLORAWAN_APPSKEYapplication session encryption key

(note 1): LoRaWAN-1.0 OTA uses a single root key for both network server and application server.

In LoRaWAN-1.0 OTA: the single root AppKey is used to generate NwkSkey and AppSKey.
(note 2): In LoRaWAN-1.0 (both OTA and ABP) SNwkSIntKey, NwkSEncKey. FNwkSIntKey are of same value and are collectively known as NwkSKey.
(note 3): LoRaWAN-1.0 uses single network session key, LoRaWAN-1.1 uses 3 network session keys. Both use a unique application session key.


In LoRaWAN-1.1 OTA: the root NwkKey is used to generate SNwkSIntKey, NwkSEncKey, FNwkSIntKey
In LoRaWAN-1.1 OTA: the root AppKey is used to generate AppSKey


in ABP mode, the DevAddr, and session keys are fixed (never change), and frame counters never reset to zero.
ABP operation has no concept of: root keys, or DevEUI or JoinEUI/AppEUI.
in OTA mode, the DevAddr and session keys are assigned at join procedure, and frame counters reset at join.

eeprom

This library includes eeprom driver to support non-volatile storage required by LoRaWAN specification.
Currently eeprom is implemented for STM32L1 family and STM32L0 family.
Writing of values are wear-leveled to increase endurance; each write operation circulates across several memory locations. A read operation returns the highest value found. This simple method is used for sequence numbers which only increase.

value nameused in
DevNonceOTAfor Join request (note 1)
RJcount1OTAfor ReJoin Type 1 request
FCntUpABPuplink frame counter
NFCntDownABPdownlink frame counter
AFCntDownABPdownlink frame counter

AFCntDown is only used in LoRaWAN-1.1 when application payload is present in downlink and FPort > 0.
NFCntDown is used in LoRaWAN-1.1 when FPort is zero in downlink or application payload not present.
NFCntDown is the only downlink frame counter used in LoRaWAN-1.0
(note 1) OTA DevNonce is random number in LoRaWAN-1.0, therefore not stored in eeprom. DevNonce in LoRaWAN-1.1 is forever increasing (non-volatile) number upon each join request,.
RJcount0 is only stored in RAM because the value resets upon new session from JoinAccept, therefore not stored in eeprom.
Frame counters in OTA mode reset upon new session in join request, therefore are stored in RAM instead of eeprom for OTA.

radio driver support

When SX127x driver is used, both SX1272 and SX1276 are supported without defining at compile time. The chip is detected at start-up.
Supported radio platforms:


Alternately, when SX126x driver is imported, the SX126xDVK1xAS board is used.

low-speed clock oscillator selection

LoRaWAN uses 32768Hz crystal to permit low-power operation.
However, some mbed targets might revert to low-speed internal oscillator, which is not accurate enough for LoRaWAN operation.
An oscillator check is performed at initialization; program will not start if internal oscillator is used.
To force LSE watch crystal, add to mbed_app.json

{
    "macros": [ "MBEDTLS_CMAC_C" ],
    "target_overrides": {
        "<your-target>": {
            "target.lse_available": true
        }
    }
}
Committer:
Wayne Roberts
Date:
Mon Aug 20 14:09:49 2018 -0700
Revision:
12:0f28f2e7c35e
Parent:
11:ce1317758488
add 8 hybrid channel sets for us915 band

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Wayne Roberts 11:ce1317758488 1 #include "lorawan_board.h"
Wayne Roberts 0:6b3ac9c5a042 2 #include "LoRaMacCrypto.h"
Wayne Roberts 0:6b3ac9c5a042 3 #include "cmac.h"
Wayne Roberts 0:6b3ac9c5a042 4 #include "aes.h"
Wayne Roberts 0:6b3ac9c5a042 5
Wayne Roberts 0:6b3ac9c5a042 6 #define LORAMAC_MIC_BLOCK_B0_SIZE 16
Wayne Roberts 0:6b3ac9c5a042 7 mbedtls_cipher_context_t ctx;
Wayne Roberts 0:6b3ac9c5a042 8
Wayne Roberts 0:6b3ac9c5a042 9 uint32_t LoRaMacComputeMic(
Wayne Roberts 0:6b3ac9c5a042 10 const block_t* block,
Wayne Roberts 0:6b3ac9c5a042 11 const uint8_t* pktPayload,
Wayne Roberts 0:6b3ac9c5a042 12 const uint8_t* key)
Wayne Roberts 0:6b3ac9c5a042 13 {
Wayne Roberts 0:6b3ac9c5a042 14 uint8_t Mic[16];
Wayne Roberts 0:6b3ac9c5a042 15
Wayne Roberts 0:6b3ac9c5a042 16 if (block->b.dir == DOWN_LINK) {
Wayne Roberts 0:6b3ac9c5a042 17 DEBUG_MIC_DOWN("down ");
Wayne Roberts 0:6b3ac9c5a042 18 DEBUG_MIC_BUF_DOWN(block->octets, LORAMAC_MIC_BLOCK_B0_SIZE, "b0", ROW_MIC+1);
Wayne Roberts 0:6b3ac9c5a042 19 DEBUG_MIC_BUF_DOWN(key, 16, "b0-key", ROW_MIC+2);
Wayne Roberts 0:6b3ac9c5a042 20 } else if (block->b.dir == UP_LINK) {
Wayne Roberts 0:6b3ac9c5a042 21 DEBUG_MIC_UP(" up ");
Wayne Roberts 0:6b3ac9c5a042 22 DEBUG_MIC_BUF_UP(block->octets, LORAMAC_MIC_BLOCK_B0_SIZE, "b0", ROW_MIC+1);
Wayne Roberts 0:6b3ac9c5a042 23 DEBUG_MIC_BUF_UP(key, 16, "b0-key", ROW_MIC+2);
Wayne Roberts 0:6b3ac9c5a042 24 }
Wayne Roberts 0:6b3ac9c5a042 25
Wayne Roberts 0:6b3ac9c5a042 26 mbedtls_cipher_cmac_starts(&ctx, key, 128);
Wayne Roberts 0:6b3ac9c5a042 27
Wayne Roberts 0:6b3ac9c5a042 28 mbedtls_cipher_cmac_update(&ctx, block->octets, LORAMAC_MIC_BLOCK_B0_SIZE);
Wayne Roberts 0:6b3ac9c5a042 29
Wayne Roberts 0:6b3ac9c5a042 30 mbedtls_cipher_cmac_update(&ctx, pktPayload, block->b.lenMsg);
Wayne Roberts 0:6b3ac9c5a042 31
Wayne Roberts 0:6b3ac9c5a042 32 mbedtls_cipher_cmac_finish(&ctx, Mic);
Wayne Roberts 0:6b3ac9c5a042 33
Wayne Roberts 0:6b3ac9c5a042 34 return ( uint32_t )( ( uint32_t )Mic[3] << 24 | ( uint32_t )Mic[2] << 16 | ( uint32_t )Mic[1] << 8 | ( uint32_t )Mic[0] );
Wayne Roberts 0:6b3ac9c5a042 35 }
Wayne Roberts 0:6b3ac9c5a042 36
Wayne Roberts 0:6b3ac9c5a042 37 void LoRaMacEncrypt( uint8_t ctr, const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint8_t *encBuffer )
Wayne Roberts 0:6b3ac9c5a042 38 {
Wayne Roberts 0:6b3ac9c5a042 39 uint8_t aBlock[16];
Wayne Roberts 0:6b3ac9c5a042 40 uint8_t sBlock[16];
Wayne Roberts 0:6b3ac9c5a042 41 uint16_t i;
Wayne Roberts 0:6b3ac9c5a042 42 uint8_t bufferIndex = 0;
Wayne Roberts 0:6b3ac9c5a042 43 mbedtls_aes_context actx;
Wayne Roberts 0:6b3ac9c5a042 44
Wayne Roberts 0:6b3ac9c5a042 45 //memset( AesContext.ksch, '\0', 240 );
Wayne Roberts 0:6b3ac9c5a042 46 mbedtls_aes_init(&actx);
Wayne Roberts 0:6b3ac9c5a042 47 //aes_set_key( key, 16, &AesContext );
Wayne Roberts 0:6b3ac9c5a042 48 mbedtls_aes_setkey_enc(&actx, key, 128);
Wayne Roberts 0:6b3ac9c5a042 49
Wayne Roberts 0:6b3ac9c5a042 50 aBlock[0] = 0x01;
Wayne Roberts 0:6b3ac9c5a042 51
Wayne Roberts 0:6b3ac9c5a042 52 aBlock[1] = 0x00;
Wayne Roberts 0:6b3ac9c5a042 53 aBlock[2] = 0x00;
Wayne Roberts 0:6b3ac9c5a042 54 aBlock[3] = 0x00;
Wayne Roberts 0:6b3ac9c5a042 55 aBlock[4] = 0x00;
Wayne Roberts 0:6b3ac9c5a042 56
Wayne Roberts 0:6b3ac9c5a042 57 aBlock[5] = dir;
Wayne Roberts 0:6b3ac9c5a042 58
Wayne Roberts 0:6b3ac9c5a042 59 aBlock[6] = ( address ) & 0xFF;
Wayne Roberts 0:6b3ac9c5a042 60 aBlock[7] = ( address >> 8 ) & 0xFF;
Wayne Roberts 0:6b3ac9c5a042 61 aBlock[8] = ( address >> 16 ) & 0xFF;
Wayne Roberts 0:6b3ac9c5a042 62 aBlock[9] = ( address >> 24 ) & 0xFF;
Wayne Roberts 0:6b3ac9c5a042 63
Wayne Roberts 0:6b3ac9c5a042 64 aBlock[10] = ( sequenceCounter ) & 0xFF;
Wayne Roberts 0:6b3ac9c5a042 65 aBlock[11] = ( sequenceCounter >> 8 ) & 0xFF;
Wayne Roberts 0:6b3ac9c5a042 66 aBlock[12] = ( sequenceCounter >> 16 ) & 0xFF;
Wayne Roberts 0:6b3ac9c5a042 67 aBlock[13] = ( sequenceCounter >> 24 ) & 0xFF;
Wayne Roberts 0:6b3ac9c5a042 68
Wayne Roberts 0:6b3ac9c5a042 69 aBlock[14] = 0;
Wayne Roberts 0:6b3ac9c5a042 70
Wayne Roberts 0:6b3ac9c5a042 71 while( size >= 16 )
Wayne Roberts 0:6b3ac9c5a042 72 {
Wayne Roberts 0:6b3ac9c5a042 73 aBlock[15] = ( ( ctr ) & 0xFF );
Wayne Roberts 0:6b3ac9c5a042 74 ctr++;
Wayne Roberts 0:6b3ac9c5a042 75 //aes_encrypt( aBlock, sBlock, &AesContext );
Wayne Roberts 0:6b3ac9c5a042 76 mbedtls_aes_encrypt(&actx, aBlock, sBlock);
Wayne Roberts 0:6b3ac9c5a042 77 for( i = 0; i < 16; i++ )
Wayne Roberts 0:6b3ac9c5a042 78 {
Wayne Roberts 0:6b3ac9c5a042 79 encBuffer[bufferIndex + i] = buffer[bufferIndex + i] ^ sBlock[i];
Wayne Roberts 0:6b3ac9c5a042 80 }
Wayne Roberts 0:6b3ac9c5a042 81 size -= 16;
Wayne Roberts 0:6b3ac9c5a042 82 bufferIndex += 16;
Wayne Roberts 0:6b3ac9c5a042 83 }
Wayne Roberts 0:6b3ac9c5a042 84
Wayne Roberts 0:6b3ac9c5a042 85 if( size > 0 )
Wayne Roberts 0:6b3ac9c5a042 86 {
Wayne Roberts 0:6b3ac9c5a042 87 aBlock[15] = ( ( ctr ) & 0xFF );
Wayne Roberts 0:6b3ac9c5a042 88 //aes_encrypt( aBlock, sBlock, &AesContext );
Wayne Roberts 0:6b3ac9c5a042 89 mbedtls_aes_encrypt(&actx, aBlock, sBlock);
Wayne Roberts 0:6b3ac9c5a042 90 for( i = 0; i < size; i++ )
Wayne Roberts 0:6b3ac9c5a042 91 {
Wayne Roberts 0:6b3ac9c5a042 92 encBuffer[bufferIndex + i] = buffer[bufferIndex + i] ^ sBlock[i];
Wayne Roberts 0:6b3ac9c5a042 93 }
Wayne Roberts 0:6b3ac9c5a042 94 }
Wayne Roberts 0:6b3ac9c5a042 95
Wayne Roberts 0:6b3ac9c5a042 96 mbedtls_aes_free(&actx);
Wayne Roberts 0:6b3ac9c5a042 97 }
Wayne Roberts 0:6b3ac9c5a042 98
Wayne Roberts 0:6b3ac9c5a042 99 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 )
Wayne Roberts 0:6b3ac9c5a042 100 {
Wayne Roberts 0:6b3ac9c5a042 101 LoRaMacEncrypt(1, buffer, size, key, address, dir, sequenceCounter, decBuffer );
Wayne Roberts 0:6b3ac9c5a042 102 }
Wayne Roberts 0:6b3ac9c5a042 103
Wayne Roberts 0:6b3ac9c5a042 104 void
Wayne Roberts 0:6b3ac9c5a042 105 LoRaMacCryptoInit()
Wayne Roberts 0:6b3ac9c5a042 106 {
Wayne Roberts 0:6b3ac9c5a042 107 //int ret;
Wayne Roberts 0:6b3ac9c5a042 108 const mbedtls_cipher_info_t *cipher_info = mbedtls_cipher_info_from_type( MBEDTLS_CIPHER_AES_128_ECB );
Wayne Roberts 0:6b3ac9c5a042 109 if (cipher_info == NULL) {
Wayne Roberts 0:6b3ac9c5a042 110 MAC_PRINTF("mbedtls_cipher_info_from_type() failed\n");
Wayne Roberts 0:6b3ac9c5a042 111 return;
Wayne Roberts 0:6b3ac9c5a042 112 }
Wayne Roberts 0:6b3ac9c5a042 113 mbedtls_cipher_init(&ctx);
Wayne Roberts 0:6b3ac9c5a042 114 /*ret = */mbedtls_cipher_setup(&ctx, cipher_info);
Wayne Roberts 0:6b3ac9c5a042 115 //MAC_PRINTF("mbedtls_cipher_setup returned %d, type %d\r\n", ret, ctx.cipher_info->type);
Wayne Roberts 0:6b3ac9c5a042 116 /* always using same ctx --- mbedtls_cipher_free(&ctx) */
Wayne Roberts 0:6b3ac9c5a042 117 }
Wayne Roberts 0:6b3ac9c5a042 118
Wayne Roberts 0:6b3ac9c5a042 119 #ifdef LORAWAN_JOIN_EUI
Wayne Roberts 0:6b3ac9c5a042 120 void LoRaMacJoinComputeSKeys_1v1( const uint8_t *nwk_root_key, const uint8_t *app_root_key, const uint8_t *joinNonce, const uint8_t *joinEUI, uint16_t devNonce, skey_t* keys)
Wayne Roberts 0:6b3ac9c5a042 121 {
Wayne Roberts 0:6b3ac9c5a042 122 uint8_t buff[16];
Wayne Roberts 0:6b3ac9c5a042 123 uint8_t *pDevNonce = ( uint8_t * )&devNonce;
Wayne Roberts 0:6b3ac9c5a042 124 uint8_t* bufPtr;
Wayne Roberts 0:6b3ac9c5a042 125 mbedtls_aes_context actx;
Wayne Roberts 0:6b3ac9c5a042 126
Wayne Roberts 0:6b3ac9c5a042 127 mbedtls_aes_init(&actx);
Wayne Roberts 0:6b3ac9c5a042 128 //memset( AesContext.ksch, '\0', 240 );
Wayne Roberts 0:6b3ac9c5a042 129 DEBUG_CRYPT_BUF(app_root_key, 16, "AppSKey-root", 0);
Wayne Roberts 0:6b3ac9c5a042 130 //aes_set_key( app_root_key, 16, &AesContext );
Wayne Roberts 0:6b3ac9c5a042 131 mbedtls_aes_setkey_enc(&actx, app_root_key, 128);
Wayne Roberts 0:6b3ac9c5a042 132
Wayne Roberts 0:6b3ac9c5a042 133 memset(buff, 0, sizeof(buff));
Wayne Roberts 0:6b3ac9c5a042 134 bufPtr = buff + 1;
Wayne Roberts 0:6b3ac9c5a042 135 memcpy(bufPtr, joinNonce, 3);
Wayne Roberts 0:6b3ac9c5a042 136 bufPtr += 3;
Wayne Roberts 0:6b3ac9c5a042 137 memcpyr(bufPtr, joinEUI, 8);
Wayne Roberts 0:6b3ac9c5a042 138 bufPtr += 8;
Wayne Roberts 0:6b3ac9c5a042 139 memcpy(bufPtr, pDevNonce, 2);
Wayne Roberts 0:6b3ac9c5a042 140 bufPtr += 2;
Wayne Roberts 0:6b3ac9c5a042 141
Wayne Roberts 0:6b3ac9c5a042 142 /* generate AppSKey */
Wayne Roberts 0:6b3ac9c5a042 143 buff[0] = 0x02;
Wayne Roberts 0:6b3ac9c5a042 144 DEBUG_CRYPT_BUF(buff, 16, "AppSKey-in", 0);
Wayne Roberts 0:6b3ac9c5a042 145 //aes_encrypt(buff, keys->AppSKey, &AesContext );
Wayne Roberts 0:6b3ac9c5a042 146 mbedtls_aes_encrypt(&actx, buff, keys->AppSKey);
Wayne Roberts 0:6b3ac9c5a042 147 DEBUG_CRYPT_BUF(keys->AppSKey, 16, "AppSKey", 0);
Wayne Roberts 0:6b3ac9c5a042 148
Wayne Roberts 0:6b3ac9c5a042 149 //memset( AesContext.ksch, '\0', 240 );
Wayne Roberts 0:6b3ac9c5a042 150 //aes_set_key( nwk_root_key, 16, &AesContext );
Wayne Roberts 0:6b3ac9c5a042 151 mbedtls_aes_setkey_enc(&actx, nwk_root_key, 128);
Wayne Roberts 0:6b3ac9c5a042 152
Wayne Roberts 0:6b3ac9c5a042 153 /* generate FNwkSIntKey */
Wayne Roberts 0:6b3ac9c5a042 154 buff[0] = 0x01;
Wayne Roberts 0:6b3ac9c5a042 155 DEBUG_CRYPT_BUF(buff, sizeof(buff), "in-FNwkSIntKey", 0);
Wayne Roberts 0:6b3ac9c5a042 156 //aes_encrypt(buff, keys->FNwkSIntKey, &AesContext );
Wayne Roberts 0:6b3ac9c5a042 157 mbedtls_aes_encrypt(&actx, buff, keys->FNwkSIntKey);
Wayne Roberts 0:6b3ac9c5a042 158 DEBUG_CRYPT_BUF(keys->FNwkSIntKey, 16, "FNwkSIntKey", 0);
Wayne Roberts 0:6b3ac9c5a042 159
Wayne Roberts 0:6b3ac9c5a042 160 /* generate SNwkSIntKey */
Wayne Roberts 0:6b3ac9c5a042 161 buff[0] = 0x03;
Wayne Roberts 0:6b3ac9c5a042 162 //aes_encrypt(buff, keys->SNwkSIntKey, &AesContext );
Wayne Roberts 0:6b3ac9c5a042 163 mbedtls_aes_encrypt(&actx, buff, keys->SNwkSIntKey);
Wayne Roberts 0:6b3ac9c5a042 164 DEBUG_CRYPT_BUF(keys->SNwkSIntKey, 16, "SNwkSIntKey", 0);
Wayne Roberts 0:6b3ac9c5a042 165
Wayne Roberts 0:6b3ac9c5a042 166 /* generate NwkSEncKey */
Wayne Roberts 0:6b3ac9c5a042 167 buff[0] = 0x04;
Wayne Roberts 0:6b3ac9c5a042 168 //aes_encrypt(buff, keys->NwkSEncKey, &AesContext );
Wayne Roberts 0:6b3ac9c5a042 169 mbedtls_aes_encrypt(&actx, buff, keys->NwkSEncKey);
Wayne Roberts 0:6b3ac9c5a042 170 DEBUG_CRYPT_BUF(keys->NwkSEncKey, 16, "NwkSEncKey", 0);
Wayne Roberts 0:6b3ac9c5a042 171
Wayne Roberts 0:6b3ac9c5a042 172 mbedtls_aes_free(&actx);
Wayne Roberts 0:6b3ac9c5a042 173 }
Wayne Roberts 0:6b3ac9c5a042 174
Wayne Roberts 0:6b3ac9c5a042 175 void LoRaMacJoinComputeSKeys_1v0(const uint8_t *nwk_root_key, const uint8_t *ja_rx, uint16_t devNonce, skey_t* keys)
Wayne Roberts 0:6b3ac9c5a042 176 {
Wayne Roberts 0:6b3ac9c5a042 177 /* ja_rx: joinNonce + NetID, 6bytes */
Wayne Roberts 0:6b3ac9c5a042 178 uint8_t nonce[16];
Wayne Roberts 0:6b3ac9c5a042 179 uint8_t *pDevNonce = ( uint8_t * )&devNonce;
Wayne Roberts 0:6b3ac9c5a042 180 mbedtls_aes_context actx;
Wayne Roberts 0:6b3ac9c5a042 181
Wayne Roberts 0:6b3ac9c5a042 182 mbedtls_aes_init(&actx);
Wayne Roberts 0:6b3ac9c5a042 183 //memset( AesContext.ksch, '\0', 240 );
Wayne Roberts 0:6b3ac9c5a042 184 //aes_set_key( nwk_root_key, 16, &AesContext );
Wayne Roberts 0:6b3ac9c5a042 185 mbedtls_aes_setkey_enc(&actx, nwk_root_key, 128);
Wayne Roberts 0:6b3ac9c5a042 186
Wayne Roberts 0:6b3ac9c5a042 187 memset( nonce, 0, sizeof( nonce ) );
Wayne Roberts 0:6b3ac9c5a042 188 nonce[0] = 0x01;
Wayne Roberts 0:6b3ac9c5a042 189 memcpy( nonce + 1, ja_rx, 6 );
Wayne Roberts 0:6b3ac9c5a042 190 memcpy( nonce + 7, pDevNonce, 2 );
Wayne Roberts 0:6b3ac9c5a042 191 //aes_encrypt( nonce, keys->FNwkSIntKey, &AesContext );
Wayne Roberts 0:6b3ac9c5a042 192 mbedtls_aes_encrypt(&actx, nonce, keys->FNwkSIntKey);
Wayne Roberts 0:6b3ac9c5a042 193
Wayne Roberts 0:6b3ac9c5a042 194 memcpy(keys->SNwkSIntKey, keys->FNwkSIntKey, 16);
Wayne Roberts 0:6b3ac9c5a042 195 memcpy(keys->NwkSEncKey, keys->FNwkSIntKey, 16);
Wayne Roberts 0:6b3ac9c5a042 196
Wayne Roberts 0:6b3ac9c5a042 197 memset( nonce, 0, sizeof( nonce ) );
Wayne Roberts 0:6b3ac9c5a042 198 nonce[0] = 0x02;
Wayne Roberts 0:6b3ac9c5a042 199 memcpy( nonce + 1, ja_rx, 6 );
Wayne Roberts 0:6b3ac9c5a042 200 memcpy( nonce + 7, pDevNonce, 2 );
Wayne Roberts 0:6b3ac9c5a042 201 //aes_encrypt( nonce, keys->AppSKey, &AesContext );
Wayne Roberts 0:6b3ac9c5a042 202 mbedtls_aes_encrypt(&actx, nonce, keys->AppSKey);
Wayne Roberts 0:6b3ac9c5a042 203
Wayne Roberts 0:6b3ac9c5a042 204 mbedtls_aes_free(&actx);
Wayne Roberts 0:6b3ac9c5a042 205 }
Wayne Roberts 0:6b3ac9c5a042 206
Wayne Roberts 0:6b3ac9c5a042 207 int LoRaMacJoinComputeMic(bool verbose, const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t *mic )
Wayne Roberts 0:6b3ac9c5a042 208 {
Wayne Roberts 0:6b3ac9c5a042 209 int ret;
Wayne Roberts 0:6b3ac9c5a042 210 uint8_t Mic[LORAMAC_MIC_BLOCK_B0_SIZE];
Wayne Roberts 0:6b3ac9c5a042 211
Wayne Roberts 0:6b3ac9c5a042 212 #ifndef ENABLE_VT100
Wayne Roberts 0:6b3ac9c5a042 213 if (verbose) {
Wayne Roberts 5:4e9d41359897 214 print_buf(key, 16, "mic-key");
Wayne Roberts 5:4e9d41359897 215 print_buf(buffer, size, "mic-in-buf");
Wayne Roberts 0:6b3ac9c5a042 216 }
Wayne Roberts 0:6b3ac9c5a042 217 #endif /* ENABLE_VT100 */
Wayne Roberts 0:6b3ac9c5a042 218
Wayne Roberts 0:6b3ac9c5a042 219 ret = mbedtls_cipher_cmac_starts(&ctx, key, 128);
Wayne Roberts 0:6b3ac9c5a042 220 if (ret != 0) {
Wayne Roberts 0:6b3ac9c5a042 221 MAC_PRINTF("0x%x = mbedtls_cipher_cmac_starts()\r\n", ret);
Wayne Roberts 0:6b3ac9c5a042 222 return ret;
Wayne Roberts 0:6b3ac9c5a042 223 }
Wayne Roberts 0:6b3ac9c5a042 224
Wayne Roberts 0:6b3ac9c5a042 225 ret = mbedtls_cipher_cmac_update(&ctx, buffer, size & 0xff);
Wayne Roberts 0:6b3ac9c5a042 226 if (ret != 0) {
Wayne Roberts 0:6b3ac9c5a042 227 MAC_PRINTF("%d = mbedtls_cipher_cmac_update()\r\n", ret);
Wayne Roberts 0:6b3ac9c5a042 228 return ret;
Wayne Roberts 0:6b3ac9c5a042 229 }
Wayne Roberts 0:6b3ac9c5a042 230
Wayne Roberts 0:6b3ac9c5a042 231 ret = mbedtls_cipher_cmac_finish(&ctx, Mic);
Wayne Roberts 0:6b3ac9c5a042 232 if (ret != 0) {
Wayne Roberts 0:6b3ac9c5a042 233 MAC_PRINTF("%d = mbedtls_cipher_cmac_finish()\r\n", ret);
Wayne Roberts 0:6b3ac9c5a042 234 return ret;
Wayne Roberts 0:6b3ac9c5a042 235 }
Wayne Roberts 0:6b3ac9c5a042 236
Wayne Roberts 0:6b3ac9c5a042 237 *mic = ( uint32_t )( ( uint32_t )Mic[3] << 24 | ( uint32_t )Mic[2] << 16 | ( uint32_t )Mic[1] << 8 | ( uint32_t )Mic[0] );
Wayne Roberts 0:6b3ac9c5a042 238 return 0;
Wayne Roberts 0:6b3ac9c5a042 239 }
Wayne Roberts 0:6b3ac9c5a042 240
Wayne Roberts 0:6b3ac9c5a042 241 void LoRaMacJoinDecrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint8_t *decBuffer )
Wayne Roberts 0:6b3ac9c5a042 242 {
Wayne Roberts 0:6b3ac9c5a042 243 mbedtls_aes_context actx;
Wayne Roberts 0:6b3ac9c5a042 244 mbedtls_aes_init(&actx);
Wayne Roberts 0:6b3ac9c5a042 245 if (mbedtls_aes_setkey_enc(&actx, key, 128) < 0) {
Wayne Roberts 0:6b3ac9c5a042 246 MAC_PRINTF("%d = mbedtls_aes_setkey_enc()\r\n");
Wayne Roberts 0:6b3ac9c5a042 247 }
Wayne Roberts 0:6b3ac9c5a042 248 mbedtls_aes_encrypt(&actx, buffer, decBuffer);
Wayne Roberts 0:6b3ac9c5a042 249 // Check if optional CFList is included
Wayne Roberts 0:6b3ac9c5a042 250 if (size >= 16)
Wayne Roberts 0:6b3ac9c5a042 251 {
Wayne Roberts 0:6b3ac9c5a042 252 mbedtls_aes_encrypt(&actx, buffer + 16, decBuffer + 16);
Wayne Roberts 0:6b3ac9c5a042 253 }
Wayne Roberts 0:6b3ac9c5a042 254
Wayne Roberts 0:6b3ac9c5a042 255 mbedtls_aes_free(&actx);
Wayne Roberts 0:6b3ac9c5a042 256 }
Wayne Roberts 0:6b3ac9c5a042 257
Wayne Roberts 0:6b3ac9c5a042 258 void LoRaMacGenerateJoinKey(uint8_t token, const uint8_t* root_key, const uint8_t* devEui, uint8_t* output)
Wayne Roberts 0:6b3ac9c5a042 259 {
Wayne Roberts 0:6b3ac9c5a042 260 int i;
Wayne Roberts 0:6b3ac9c5a042 261 uint8_t input[16];
Wayne Roberts 0:6b3ac9c5a042 262 uint8_t* ptr = input;
Wayne Roberts 0:6b3ac9c5a042 263 mbedtls_aes_context actx;
Wayne Roberts 0:6b3ac9c5a042 264
Wayne Roberts 0:6b3ac9c5a042 265 mbedtls_aes_init(&actx);
Wayne Roberts 0:6b3ac9c5a042 266
Wayne Roberts 0:6b3ac9c5a042 267 memset(ptr, 0, sizeof(input));
Wayne Roberts 0:6b3ac9c5a042 268
Wayne Roberts 0:6b3ac9c5a042 269 *ptr++ = token;
Wayne Roberts 0:6b3ac9c5a042 270
Wayne Roberts 0:6b3ac9c5a042 271 /* EUI put into buffer in same order that it appears over-the-air */
Wayne Roberts 0:6b3ac9c5a042 272 for (i = LORA_EUI_LENGTH - 1; i >= 0; i--)
Wayne Roberts 0:6b3ac9c5a042 273 *ptr++ = devEui[i];
Wayne Roberts 0:6b3ac9c5a042 274
Wayne Roberts 0:6b3ac9c5a042 275 DEBUG_CRYPT_BUF(root_key, 16, "generate-join-key-root_key", 0);
Wayne Roberts 0:6b3ac9c5a042 276 DEBUG_CRYPT_BUF(input, 16, "generate-join-key-input", 0);
Wayne Roberts 0:6b3ac9c5a042 277
Wayne Roberts 0:6b3ac9c5a042 278 mbedtls_aes_setkey_enc(&actx, root_key, 128);
Wayne Roberts 0:6b3ac9c5a042 279 mbedtls_aes_encrypt(&actx, input, output);
Wayne Roberts 0:6b3ac9c5a042 280
Wayne Roberts 0:6b3ac9c5a042 281 mbedtls_aes_free(&actx);
Wayne Roberts 0:6b3ac9c5a042 282 }
Wayne Roberts 0:6b3ac9c5a042 283 #endif /* LORAWAN_JOIN_EUI */