Ugo RENNERJérôme BeclinHervé RocheLaurent Masson
Published © GPL3+

Secure LoRaWAN Node To AWS IoT With Trusted Objects TO136 SE

From secure LoRaWAN node based on Trusted Objects-Avnet TO136 SE to AWS IoT, using STM32 Nucleo board, Kerlink gateway & Actility servers.

IntermediateProtip8 hours593
Secure LoRaWAN Node To AWS IoT With Trusted Objects TO136 SE

Things used in this project

Hardware components

STM32 Nucleo P-NUCLEO-LRWAN1
LoRaWAN device (STM32 Nucleo-L073RZ board with Semtech SX1272 shield)
×1
Avnet & Trusted Objects - TO136
Trusted Objects Secure Element
×1
Kerlink iFemtoCell
LoRaWAN gateway
×1

Software apps and online services

Eclipse Oxygen
C/C++ IDE
STMicroelectronics I-CUBE-LRWAN
LoRaWAN Software stack
Actility ThingPark
LoRaWAN Network / Application server
AWS IoT
Amazon Web Services AWS IoT
Backend

Story

Read more

Code

libto-init.patch

C/C++
Patch for STM32CubeExpansion 1.1.4 to initialize Trusted Objects library
From ef0ac1a61090cabf26197dfd676ef99d42402555 Mon Sep 17 00:00:00 2001
From: Ugo RENNER <u.renner@trusted-objects.com>
Date: Tue, 14 Nov 2017 14:04:57 +0100
Subject: [PATCH 1/2] libTO initialization

---
 Middlewares/Third_Party/Lora/Core/lora.c           | 18 ++++++++++++++
 .../Multi/Applications/LoRa/End_Node/src/main.c    | 28 ++++++++++++++++++++++
 2 files changed, 46 insertions(+)

diff --git a/Middlewares/Third_Party/Lora/Core/lora.c b/Middlewares/Third_Party/Lora/Core/lora.c
index 78a0a34..53b52aa 100644
--- a/Middlewares/Third_Party/Lora/Core/lora.c
+++ b/Middlewares/Third_Party/Lora/Core/lora.c
@@ -51,6 +51,11 @@
 #include "lora.h"
 #include "lora-test.h"
 
+#ifdef TO_SE
+#include "TO.h"
+#include "TO_defs.h"
+#endif
+
 /*!
  * Join requests trials duty cycle.
  */
@@ -266,12 +271,23 @@ void LORA_Init (LoRaMainCallback_t *callbacks, LoRaParam_t* LoRaParam )
   LoRaMainCallbacks->BoardGetUniqueId( DevEui );  
 #endif
   
+#ifdef TO_SE
+  if (TO_lora_get_app_eui(AppEui) != TORSP_SUCCESS) {
+    PRINTF("TO_lora_get_app_eui failed\n");
+  }
+  if (TO_lora_get_dev_eui(DevEui) != TORSP_SUCCESS) {
+    PRINTF("TO_lora_get_app_eui failed\n");
+  }
+#endif
+
 #if( OVER_THE_AIR_ACTIVATION != 0 )
 
   PRINTF("OTAA\n\r"); 
   PRINTF("DevEui= %02X", DevEui[0]) ;for(int i=1; i<8 ; i++) {PRINTF("-%02X", DevEui[i]); }; PRINTF("\n\r");
   PRINTF("AppEui= %02X", AppEui[0]) ;for(int i=1; i<8 ; i++) {PRINTF("-%02X", AppEui[i]); }; PRINTF("\n\r");
+#ifndef TO_SE
   PRINTF("AppKey= %02X", AppKey[0]) ;for(int i=1; i<16; i++) {PRINTF(" %02X", AppKey[i]); }; PRINTF("\n\n\r");
+#endif
 #else
 
 #if (STATIC_DEVICE_ADDRESS != 1)
@@ -283,9 +299,11 @@ void LORA_Init (LoRaMainCallback_t *callbacks, LoRaParam_t* LoRaParam )
   PRINTF("ABP\n\r"); 
   PRINTF("DevEui= %02X", DevEui[0]) ;for(int i=1; i<8 ; i++) {PRINTF("-%02X", DevEui[i]); }; PRINTF("\n\r");
   PRINTF("DevAdd=  %08X\n\r", DevAddr) ;
+#ifndef TO_SE
   PRINTF("NwkSKey= %02X", NwkSKey[0]) ;for(int i=1; i<16 ; i++) {PRINTF(" %02X", NwkSKey[i]); }; PRINTF("\n\r");
   PRINTF("AppSKey= %02X", AppSKey[0]) ;for(int i=1; i<16 ; i++) {PRINTF(" %02X", AppSKey[i]); }; PRINTF("\n\r");
 #endif
+#endif
         LoRaMacPrimitives.MacMcpsConfirm = McpsConfirm;
         LoRaMacPrimitives.MacMcpsIndication = McpsIndication;
         LoRaMacPrimitives.MacMlmeConfirm = MlmeConfirm;
diff --git a/Projects/Multi/Applications/LoRa/End_Node/src/main.c b/Projects/Multi/Applications/LoRa/End_Node/src/main.c
index 64db291..9598c9b 100644
--- a/Projects/Multi/Applications/LoRa/End_Node/src/main.c
+++ b/Projects/Multi/Applications/LoRa/End_Node/src/main.c
@@ -53,6 +53,10 @@
 #include "vcom.h"
 #include "version.h"
 
+#ifdef TO_SE
+#include <TO.h>
+#endif
+
 /* Private typedef -----------------------------------------------------------*/
 /* Private define ------------------------------------------------------------*/
 
@@ -184,6 +188,26 @@ int main( void )
   /* Configure the hardware*/
   HW_Init( );
   
+#ifdef TO_SE
+    int ret, i;
+    uint8_t sn[TO_SN_SIZE];
+    ret = TO_init();
+    if (ret == TO_OK) {
+        PRINTF("TO initialized\n");
+        ret = TO_get_serial_number(sn);
+        if (ret == TORSP_SUCCESS) {
+            PRINTF("TO serial number : ");
+            for (i = 0; i < TO_SN_SIZE; i++)
+                PRINTF("%02X ", sn[i]);
+            PRINTF("\n");
+        } else {
+            PRINTF("Error: unable to get TO serial number\n");
+        }
+    } else {
+        PRINTF("Error: unable to initialize TO\n");
+    }
+#endif
+
   /* USER CODE BEGIN 1 */
   /* USER CODE END 1 */
   
@@ -214,6 +238,10 @@ int main( void )
     /* USER CODE BEGIN 2 */
     /* USER CODE END 2 */
   }
+
+#ifdef TO_SE
+  TO_fini();
+#endif
 }
 
 static void LORA_HasJoined( void )
-- 
2.11.0

new-cryptography-layer.patch

C/C++
Patch for STM32CubeExpansion 1.1.4 to change cryptography layer to Trusted Objects'
From f68f5af50228c2be3950cf0c53662bcaa90eb08a Mon Sep 17 00:00:00 2001
From: Ugo RENNER <u.renner@trusted-objects.com>
Date: Tue, 14 Nov 2017 14:25:54 +0100
Subject: [PATCH 2/2] libTO optimized integration

---
 Middlewares/Third_Party/Lora/Mac/LoRaMac.c         | 80 +++++++++++++++++++
 Middlewares/Third_Party/Lora/Mac/LoRaMacCrypto.c   |  4 +
 .../Third_Party/Lora/Mac/LoRaMacCrypto_TO.c        | 54 +++++++++++++
 .../Third_Party/Lora/Mac/LoRaMacCrypto_TO.h        | 92 ++++++++++++++++++++++
 4 files changed, 230 insertions(+)
 create mode 100644 Middlewares/Third_Party/Lora/Mac/LoRaMacCrypto_TO.c
 create mode 100644 Middlewares/Third_Party/Lora/Mac/LoRaMacCrypto_TO.h

diff --git a/Middlewares/Third_Party/Lora/Mac/LoRaMac.c b/Middlewares/Third_Party/Lora/Mac/LoRaMac.c
index e71908b..1efab69 100644
--- a/Middlewares/Third_Party/Lora/Mac/LoRaMac.c
+++ b/Middlewares/Third_Party/Lora/Mac/LoRaMac.c
@@ -26,7 +26,11 @@ Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jae
 #include "timeServer.h"
 #include "LoRaMac.h"
 #include "region/Region.h"
+#ifndef TO_SE
 #include "LoRaMacCrypto.h"
+#else
+#include "LoRaMacCrypto_TO.h"
+#endif
 
 #include "debug.h"
 #include "LoRaMacTest.h"
@@ -68,6 +72,7 @@ static LoRaMacRegion_t LoRaMacRegion;
  */
 #define BACKOFF_DC_24_HOURS                         10000
 
+#ifndef TO_SE
 /*!
  * Device IEEE EUI
  */
@@ -106,6 +111,7 @@ static uint8_t LoRaMacAppSKey[] =
  * measurements
  */
 static uint16_t LoRaMacDevNonce;
+#endif
 
 /*!
  * Network ID ( 3 bytes )
@@ -712,8 +718,10 @@ static void OnRadioRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t
     uint8_t appPayloadStartIndex = 0;
     uint8_t port = 0xFF;
     uint8_t frameLen = 0;
+#ifndef TO_SE
     uint32_t mic = 0;
     uint32_t micRx = 0;
+#endif
 
     uint16_t sequenceCounter = 0;
     uint16_t sequenceCounterPrev = 0;
@@ -721,8 +729,10 @@ static void OnRadioRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t
     uint32_t downLinkCounter = 0;
 
     MulticastParams_t *curMulticastParams = NULL;
+#ifndef TO_SE
     uint8_t *nwkSKey = LoRaMacNwkSKey;
     uint8_t *appSKey = LoRaMacAppSKey;
+#endif
 
     uint8_t multicast = 0;
 
@@ -756,6 +766,7 @@ static void OnRadioRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t
                 PrepareRxDoneAbort( );
                 return;
             }
+#ifndef TO_SE
             LoRaMacJoinDecrypt( payload + 1, size - 1, LoRaMacAppKey, LoRaMacRxPayload + 1 );
 
             LoRaMacRxPayload[0] = macHdr.Value;
@@ -770,6 +781,10 @@ static void OnRadioRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t
             if( micRx == mic )
             {
                 LoRaMacJoinComputeSKeys( LoRaMacAppKey, LoRaMacRxPayload + 1, LoRaMacDevNonce, LoRaMacNwkSKey, LoRaMacAppSKey );
+#else
+            if (LoRaMacHandleJoinAccept( payload, size, LoRaMacRxPayload ) == LORAMAC_CRYPTO_STATUS_OK)
+            {
+#endif
 
                 LoRaMacNetID = ( uint32_t )LoRaMacRxPayload[4];
                 LoRaMacNetID |= ( ( uint32_t )LoRaMacRxPayload[5] << 8 );
@@ -843,8 +858,10 @@ static void OnRadioRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t
                         if( address == curMulticastParams->Address )
                         {
                             multicast = 1;
+#ifndef TO_SE
                             nwkSKey = curMulticastParams->NwkSKey;
                             appSKey = curMulticastParams->AppSKey;
+#endif
                             downLinkCounter = curMulticastParams->DownLinkCounter;
                             break;
                         }
@@ -861,8 +878,10 @@ static void OnRadioRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t
                 else
                 {
                     multicast = 0;
+#ifndef TO_SE
                     nwkSKey = LoRaMacNwkSKey;
                     appSKey = LoRaMacAppSKey;
+#endif
                     downLinkCounter = DownLinkCounter;
                 }
 
@@ -873,10 +892,12 @@ static void OnRadioRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t
 
                 appPayloadStartIndex = 8 + fCtrl.Bits.FOptsLen;
 
+#ifndef TO_SE
                 micRx |= ( uint32_t )payload[size - LORAMAC_MFR_LEN];
                 micRx |= ( ( uint32_t )payload[size - LORAMAC_MFR_LEN + 1] << 8 );
                 micRx |= ( ( uint32_t )payload[size - LORAMAC_MFR_LEN + 2] << 16 );
                 micRx |= ( ( uint32_t )payload[size - LORAMAC_MFR_LEN + 3] << 24 );
+#endif
 
                 sequenceCounterPrev = ( uint16_t )downLinkCounter;
                 sequenceCounterDiff = ( sequenceCounter - sequenceCounterPrev );
@@ -884,14 +905,17 @@ static void OnRadioRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t
                 if( sequenceCounterDiff < ( 1 << 15 ) )
                 {
                     downLinkCounter += sequenceCounterDiff;
+#ifndef TO_SE
                     LoRaMacComputeMic( payload, size - LORAMAC_MFR_LEN, nwkSKey, address, DOWN_LINK, downLinkCounter, &mic );
                     if( micRx == mic )
                     {
                         isMicOk = true;
                     }
+#endif
                 }
                 else
                 {
+#ifndef TO_SE
                     // check for sequence roll-over
                     uint32_t  downLinkCounterTmp = downLinkCounter + 0x10000 + ( int16_t )sequenceCounterDiff;
                     LoRaMacComputeMic( payload, size - LORAMAC_MFR_LEN, nwkSKey, address, DOWN_LINK, downLinkCounterTmp, &mic );
@@ -900,6 +924,14 @@ static void OnRadioRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t
                         isMicOk = true;
                         downLinkCounter = downLinkCounterTmp;
                     }
+#else
+                    // assume sequence roll-over
+                    downLinkCounter += 0x10000 + ( int16_t )sequenceCounterDiff;
+                }
+                if ( LoRaMacUnsecurePHYPayload( payload, size, payload ) == LORAMAC_CRYPTO_STATUS_OK )
+                {
+                    isMicOk = true;
+#endif
                 }
 
                 // Check for a the maximum allowed counter difference
@@ -998,6 +1030,7 @@ static void OnRadioRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t
                     {
                         port = payload[appPayloadStartIndex++];
                         frameLen = ( size - 4 ) - appPayloadStartIndex;
+                        memcpy( LoRaMacRxPayload, payload + appPayloadStartIndex, frameLen );
 
                         McpsIndication.Port = port;
 
@@ -1006,6 +1039,7 @@ static void OnRadioRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t
                             // Only allow frames which do not have fOpts
                             if( fCtrl.Bits.FOptsLen == 0 )
                             {
+#ifndef TO_SE
                                 LoRaMacPayloadDecrypt( payload + appPayloadStartIndex,
                                                        frameLen,
                                                        nwkSKey,
@@ -1013,6 +1047,7 @@ static void OnRadioRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t
                                                        DOWN_LINK,
                                                        downLinkCounter,
                                                        LoRaMacRxPayload );
+#endif
 
                                 // Decode frame payload MAC commands
                                 ProcessMacCommands( LoRaMacRxPayload, 0, frameLen, snr );
@@ -1030,6 +1065,7 @@ static void OnRadioRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t
                                 ProcessMacCommands( payload, 8, appPayloadStartIndex - 1, snr );
                             }
 
+#ifndef TO_SE
                             LoRaMacPayloadDecrypt( payload + appPayloadStartIndex,
                                                    frameLen,
                                                    appSKey,
@@ -1037,6 +1073,7 @@ static void OnRadioRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t
                                                    DOWN_LINK,
                                                    downLinkCounter,
                                                    LoRaMacRxPayload );
+#endif
 
                             if( skipIndication == false )
                             {
@@ -2054,9 +2091,13 @@ static void ResetMacParameters( void )
 LoRaMacStatus_t PrepareFrame( LoRaMacHeader_t *macHdr, LoRaMacFrameCtrl_t *fCtrl, uint8_t fPort, void *fBuffer, uint16_t fBufferSize )
 {
     AdrNextParams_t adrNext;
+#ifndef TO_SE
     uint16_t i;
+#endif
     uint8_t pktHeaderLen = 0;
+#ifndef TO_SE
     uint32_t mic = 0;
+#endif
     const void* payload = fBuffer;
     uint8_t framePort = fPort;
 
@@ -2071,11 +2112,14 @@ LoRaMacStatus_t PrepareFrame( LoRaMacHeader_t *macHdr, LoRaMacFrameCtrl_t *fCtrl
 
     LoRaMacTxPayloadLen = fBufferSize;
 
+#ifndef TO_SE
     LoRaMacBuffer[pktHeaderLen++] = macHdr->Value;
+#endif
 
     switch( macHdr->Bits.MType )
     {
         case FRAME_TYPE_JOIN_REQ:
+#ifndef TO_SE
             LoRaMacBufferPktLen = pktHeaderLen;
 
             memcpyr( LoRaMacBuffer + LoRaMacBufferPktLen, LoRaMacAppEui, 8 );
@@ -2094,6 +2138,9 @@ LoRaMacStatus_t PrepareFrame( LoRaMacHeader_t *macHdr, LoRaMacFrameCtrl_t *fCtrl
             LoRaMacBuffer[LoRaMacBufferPktLen++] = ( mic >> 8 ) & 0xFF;
             LoRaMacBuffer[LoRaMacBufferPktLen++] = ( mic >> 16 ) & 0xFF;
             LoRaMacBuffer[LoRaMacBufferPktLen++] = ( mic >> 24 ) & 0xFF;
+#else
+            LoRaMacGetJoinRequest( LoRaMacBuffer, &LoRaMacBufferPktLen );
+#endif
 
             break;
         case FRAME_TYPE_DATA_CONFIRMED_UP:
@@ -2122,6 +2169,7 @@ LoRaMacStatus_t PrepareFrame( LoRaMacHeader_t *macHdr, LoRaMacFrameCtrl_t *fCtrl
                 fCtrl->Bits.Ack = 1;
             }
 
+#ifndef TO_SE
             LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr ) & 0xFF;
             LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr >> 8 ) & 0xFF;
             LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr >> 16 ) & 0xFF;
@@ -2131,6 +2179,7 @@ LoRaMacStatus_t PrepareFrame( LoRaMacHeader_t *macHdr, LoRaMacFrameCtrl_t *fCtrl
 
             LoRaMacBuffer[pktHeaderLen++] = UpLinkCounter & 0xFF;
             LoRaMacBuffer[pktHeaderLen++] = ( UpLinkCounter >> 8 ) & 0xFF;
+#endif
 
             // Copy the MAC commands which must be re-send into the MAC command buffer
             memcpy1( &MacCommandsBuffer[MacCommandsBufferIndex], MacCommandsBufferToRepeat, MacCommandsBufferToRepeatIndex );
@@ -2144,12 +2193,14 @@ LoRaMacStatus_t PrepareFrame( LoRaMacHeader_t *macHdr, LoRaMacFrameCtrl_t *fCtrl
                     {
                         fCtrl->Bits.FOptsLen += MacCommandsBufferIndex;
 
+#ifndef TO_SE
                         // Update FCtrl field with new value of OptionsLength
                         LoRaMacBuffer[0x05] = fCtrl->Value;
                         for( i = 0; i < MacCommandsBufferIndex; i++ )
                         {
                             LoRaMacBuffer[pktHeaderLen++] = MacCommandsBuffer[i];
                         }
+#endif
                     }
                     else
                     {
@@ -2176,6 +2227,7 @@ LoRaMacStatus_t PrepareFrame( LoRaMacHeader_t *macHdr, LoRaMacFrameCtrl_t *fCtrl
                 MacCommandsInNextTx = true;
             }
 
+#ifndef TO_SE
             if( ( payload != NULL ) && ( LoRaMacTxPayloadLen > 0 ) )
             {
                 LoRaMacBuffer[pktHeaderLen++] = framePort;
@@ -2201,6 +2253,16 @@ LoRaMacStatus_t PrepareFrame( LoRaMacHeader_t *macHdr, LoRaMacFrameCtrl_t *fCtrl
             LoRaMacBuffer[LoRaMacBufferPktLen + 3] = ( mic >> 24 ) & 0xFF;
 
             LoRaMacBufferPktLen += LORAMAC_MFR_LEN;
+#else
+            if( ( payload != NULL ) && ( LoRaMacTxPayloadLen > 0 ) && framePort == 0 )
+            {
+                // Reset buffer index as the mac commands are being sent on port 0
+                MacCommandsBufferIndex = 0;
+            }
+
+            LoRaMacSecurePHYPayload( macHdr->Value, fCtrl->Value, MacCommandsBuffer, framePort, payload, LoRaMacTxPayloadLen, LoRaMacBuffer );
+            LoRaMacBufferPktLen = 6 + fCtrl->Bits.FOptsLen + 2 + (LoRaMacTxPayloadLen ? LoRaMacTxPayloadLen + 1 : 0) + LORAMAC_MFR_LEN;
+#endif
 
             break;
         case FRAME_TYPE_PROPRIETARY:
@@ -2543,14 +2605,20 @@ LoRaMacStatus_t LoRaMacMibGetRequestConfirm( MibRequestConfirm_t *mibGet )
             break;
         }
         case MIB_NWK_SKEY:
+#ifndef TO_SE
         {
             mibGet->Param.NwkSKey = LoRaMacNwkSKey;
             break;
         }
+#endif
         case MIB_APP_SKEY:
         {
+#ifndef TO_SE
             mibGet->Param.AppSKey = LoRaMacAppSKey;
             break;
+#else
+            PRINTF("%s: Cannot get session key\n", __func__);
+#endif
         }
         case MIB_PUBLIC_NETWORK:
         {
@@ -2747,6 +2815,7 @@ LoRaMacStatus_t LoRaMacMibSetRequestConfirm( MibRequestConfirm_t *mibSet )
             break;
         }
         case MIB_NWK_SKEY:
+#ifndef TO_SE
         {
             if( mibSet->Param.NwkSKey != NULL )
             {
@@ -2759,8 +2828,10 @@ LoRaMacStatus_t LoRaMacMibSetRequestConfirm( MibRequestConfirm_t *mibSet )
             }
             break;
         }
+#endif
         case MIB_APP_SKEY:
         {
+#ifndef TO_SE
             if( mibSet->Param.AppSKey != NULL )
             {
                 memcpy1( LoRaMacAppSKey, mibSet->Param.AppSKey,
@@ -2770,6 +2841,9 @@ LoRaMacStatus_t LoRaMacMibSetRequestConfirm( MibRequestConfirm_t *mibSet )
             {
                 status = LORAMAC_STATUS_PARAMETER_INVALID;
             }
+#else
+            PRINTF("%s: Cannot set session key\n", __func__);
+#endif
             break;
         }
         case MIB_PUBLIC_NETWORK:
@@ -3134,10 +3208,14 @@ LoRaMacStatus_t LoRaMacMlmeRequest( MlmeReq_t *mlmeRequest )
                 return LORAMAC_STATUS_BUSY;
             }
 
+#ifndef TO_SE
             if( ( mlmeRequest->Req.Join.DevEui == NULL ) ||
                 ( mlmeRequest->Req.Join.AppEui == NULL ) ||
                 ( mlmeRequest->Req.Join.AppKey == NULL ) ||
                 ( mlmeRequest->Req.Join.NbTrials == 0 ) )
+#else
+            if( ( mlmeRequest->Req.Join.NbTrials == 0 ) )
+#endif
             {
                 return LORAMAC_STATUS_PARAMETER_INVALID;
             }
@@ -3156,9 +3234,11 @@ LoRaMacStatus_t LoRaMacMlmeRequest( MlmeReq_t *mlmeRequest )
             LoRaMacFlags.Bits.MlmeReq = 1;
             MlmeConfirm.MlmeRequest = mlmeRequest->Type;
 
+#ifndef TO_SE
             LoRaMacDevEui = mlmeRequest->Req.Join.DevEui;
             LoRaMacAppEui = mlmeRequest->Req.Join.AppEui;
             LoRaMacAppKey = mlmeRequest->Req.Join.AppKey;
+#endif
             MaxJoinRequestTrials = mlmeRequest->Req.Join.NbTrials;
 
             // Reset variable JoinRequestTrials
diff --git a/Middlewares/Third_Party/Lora/Mac/LoRaMacCrypto.c b/Middlewares/Third_Party/Lora/Mac/LoRaMacCrypto.c
index 94026c4..2bc19f8 100644
--- a/Middlewares/Third_Party/Lora/Mac/LoRaMacCrypto.c
+++ b/Middlewares/Third_Party/Lora/Mac/LoRaMacCrypto.c
@@ -1,3 +1,5 @@
+#ifndef TO_SE
+
 /*
  / _____)             _              | |
 ( (____  _____ ____ _| |_ _____  ____| |__
@@ -200,3 +202,5 @@ void LoRaMacJoinComputeSKeys( const uint8_t *key, const uint8_t *appNonce, uint1
     memcpy1( nonce + 7, pDevNonce, 2 );
     aes_encrypt( nonce, appSKey, &AesContext );
 }
+
+#endif /* TO_SE */
diff --git a/Middlewares/Third_Party/Lora/Mac/LoRaMacCrypto_TO.c b/Middlewares/Third_Party/Lora/Mac/LoRaMacCrypto_TO.c
new file mode 100644
index 0000000..d1ddfca
--- /dev/null
+++ b/Middlewares/Third_Party/Lora/Mac/LoRaMacCrypto_TO.c
@@ -0,0 +1,54 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <LoRaMacCrypto_TO.h>
+#include <TO.h>
+
+LoRaMacCryptoStatus_t LoRaMacGetJoinRequest( uint8_t *buffer, uint16_t *size )
+{
+        int ret;
+
+        ret = TO_lora_get_join_request_phypayload(buffer);
+        if (ret != TORSP_SUCCESS) {
+                fprintf(stderr, "TO get join request error, 0x%X\n", ret);
+        } else {
+            *size = TO_LORA_JOINREQUEST_SIZE;
+        }
+
+        return (ret == TORSP_SUCCESS ? LORAMAC_CRYPTO_STATUS_OK : LORAMAC_CRYPTO_STATUS_KO);
+}
+
+LoRaMacCryptoStatus_t LoRaMacHandleJoinAccept( const uint8_t *buffer, const uint16_t size, uint8_t *outBuffer )
+{
+        int ret;
+
+        ret = TO_lora_handle_join_accept_phypayload(buffer, size, outBuffer);
+        if (ret != TORSP_SUCCESS) {
+                fprintf(stderr, "TO handle join accept error, 0x%X\n", ret);
+        }
+
+        return (ret == TORSP_SUCCESS ? LORAMAC_CRYPTO_STATUS_OK : LORAMAC_CRYPTO_STATUS_KO);
+}
+
+LoRaMacCryptoStatus_t LoRaMacSecurePHYPayload( const uint8_t mhdr, const uint8_t fctrl, const uint8_t *fopts, const uint8_t fport, const uint8_t *payload, const size_t payloadSize, uint8_t *outBuffer )
+{
+        int ret;
+
+        ret = TO_lora_secure_phypayload(mhdr, fctrl, fopts, fport, payload, payloadSize, outBuffer);
+        if (ret != TORSP_SUCCESS) {
+                fprintf(stderr, "TO secure error, 0x%X\n", ret);
+        }
+
+        return (ret == TORSP_SUCCESS ? LORAMAC_CRYPTO_STATUS_OK : LORAMAC_CRYPTO_STATUS_KO);
+}
+
+LoRaMacCryptoStatus_t LoRaMacUnsecurePHYPayload( const uint8_t *buffer, const uint16_t size, uint8_t *outBuffer )
+{
+        int ret;
+
+        ret = TO_lora_unsecure_phypayload(buffer, size, outBuffer);
+        if (ret != TORSP_SUCCESS) {
+                fprintf(stderr, "TO unsecure error, 0x%X\n", ret);
+        }
+
+        return (ret == TORSP_SUCCESS ? LORAMAC_CRYPTO_STATUS_OK : LORAMAC_CRYPTO_STATUS_KO);
+}
diff --git a/Middlewares/Third_Party/Lora/Mac/LoRaMacCrypto_TO.h b/Middlewares/Third_Party/Lora/Mac/LoRaMacCrypto_TO.h
new file mode 100644
index 0000000..ea8403c
--- /dev/null
+++ b/Middlewares/Third_Party/Lora/Mac/LoRaMacCrypto_TO.h
@@ -0,0 +1,92 @@
+/*!
+ * \file      LoRaMacCrypto_TO.h
+ *
+ * \brief     LoRa MAC layer cryptography implementation
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ *                ______                              _
+ *               / _____)             _              | |
+ *              ( (____  _____ ____ _| |_ _____  ____| |__
+ *               \____ \| ___ |    (_   _) ___ |/ ___)  _ \
+ *               _____) ) ____| | | || |_| ____( (___| | | |
+ *              (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ *              (C)2013 Semtech
+ *
+ *               ___ _____ _   ___ _  _____ ___  ___  ___ ___
+ *              / __|_   _/_\ / __| |/ / __/ _ \| _ \/ __| __|
+ *              \__ \ | |/ _ \ (__| ' <| _| (_) |   / (__| _|
+ *              |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
+ *              embedded.connectivity.solutions===============
+ *
+ * \endcode
+ *
+ * \author    Miguel Luis ( Semtech )
+ *
+ * \author    Gregory Cristian ( Semtech )
+ *
+ * \author    Daniel Jckle ( STACKFORCE )
+ *
+ * \defgroup    LORAMAC_CRYPTO  LoRa MAC layer cryptography implementation
+ *              This module covers the implementation of cryptographic functions
+ *              of the LoRaMAC layer.
+ * \{
+ */
+#ifndef __LORAMAC_CRYPTO_H__
+#define __LORAMAC_CRYPTO_H__
+
+/*!
+ * LoRaMAC Crypto Status
+ */
+typedef enum eLoRaMacCryptoStatus
+{
+    /**
+     * Success
+     */
+    LORAMAC_CRYPTO_STATUS_OK,
+    /**
+     * Failure
+     */
+    LORAMAC_CRYPTO_STATUS_KO
+} LoRaMacCryptoStatus_t;
+
+/*!
+ * Get join request encrypted payload.
+ *
+ * \param [OUT]  buffer          - Encrypted payload
+ * \param [OUT]  size            - Encrypted payload size
+ */
+LoRaMacCryptoStatus_t LoRaMacGetJoinRequest( uint8_t *buffer, uint16_t *size );
+
+/*!
+ * Handle join accept payload.
+ *
+ * \param [IN]  buffer          - Encrypted join accept payload
+ * \param [IN]  size            - Encrypted join accept payload size
+ */
+LoRaMacCryptoStatus_t LoRaMacHandleJoinAccept( const uint8_t *buffer, const uint16_t size, uint8_t *outBuffer );
+
+/*!
+ * Encrypt PHYPayload.
+ *
+ * \param [IN]  mhdr            - MHDR
+ * \param [IN]  fctrl           - FCtrl
+ * \param [IN]  fopts           - FOpts (optional, depends on FCtrl)
+ * \param [IN]  fport           - FOpts (optional, depends on payload)
+ * \param [IN]  payload         - MACPayload (optional)
+ * \param [IN]  payloadSize     - MACPayload size (must be 0 if no payload)
+ */
+LoRaMacCryptoStatus_t LoRaMacSecurePHYPayload( const uint8_t mhdr, const uint8_t fctrl, const uint8_t *fopts, const uint8_t fport, const uint8_t *payload, const size_t payloadSize, uint8_t *outBuffer );
+
+/*!
+ * Decrypt PHYPayload.
+ *
+ * \param [IN]  buffer          - Payload to decrypt
+ * \param [IN]  size            - Size of payload
+ */
+LoRaMacCryptoStatus_t LoRaMacUnsecurePHYPayload( const uint8_t *buffer, const uint16_t size, uint8_t *outBuffer );
+
+/*! \} defgroup LORAMAC */
+
+#endif // __LORAMAC_CRYPTO_H__
-- 
2.11.0

main.c

C/C++
Based on STM32CubeExpansion_LRWAN_V1.1.4.
File location: Projects/Multi/Applications/LoRa/End_Node/src/main.c
No preview (download only).

lora.c

C/C++
Based on STM32CubeExpansion_LRWAN_V1.1.4.
File location: Middlewares/Third_Party/Lora/Core/lora.c
/******************************************************************************
  * @file    lora.c
  * @author  MCD Application Team
  * @version V1.1.4
  * @date    08-January-2018
  * @brief   lora API to drive the lora state Machine
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics International N.V. 
  * All rights reserved.</center></h2>
  *
  * Redistribution and use in source and binary forms, with or without 
  * modification, are permitted, provided that the following conditions are met:
  *
  * 1. Redistribution of source code must retain the above copyright notice, 
  *    this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright notice,
  *    this list of conditions and the following disclaimer in the documentation
  *    and/or other materials provided with the distribution.
  * 3. Neither the name of STMicroelectronics nor the names of other 
  *    contributors to this software may be used to endorse or promote products 
  *    derived from this software without specific written permission.
  * 4. This software, including modifications and/or derivative works of this 
  *    software, must execute solely and exclusively on microcontroller or
  *    microprocessor devices manufactured by or for STMicroelectronics.
  * 5. Redistribution and use of this software other than as permitted under 
  *    this license is void and will automatically terminate your rights under 
  *    this license. 
  *
  * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" 
  * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT 
  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 
  * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
  * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT 
  * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "hw.h"
#include "timeServer.h"
#include "LoRaMac.h"
#include "lora.h"
#include "lora-test.h"

#ifdef TO_SE
#include "TO.h"
#include "TO_defs.h"
#endif

/*!
 * Join requests trials duty cycle.
 */
#define OVER_THE_AIR_ACTIVATION_DUTYCYCLE           10000  // 10 [s] value in ms

#if defined( REGION_EU868 )

#include "LoRaMacTest.h"

/*!
 * LoRaWAN ETSI duty cycle control enable/disable
 *
 * \remark Please note that ETSI mandates duty cycled transmissions. Use only for test purposes
 */
#define LORAWAN_DUTYCYCLE_ON                        true

#define USE_SEMTECH_DEFAULT_CHANNEL_LINEUP          0

#if( USE_SEMTECH_DEFAULT_CHANNEL_LINEUP == 1 ) 

#define LC4                { 867100000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
#define LC5                { 867300000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
#define LC6                { 867500000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
#define LC7                { 867700000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
#define LC8                { 867900000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
#define LC9                { 868800000, 0, { ( ( DR_7 << 4 ) | DR_7 ) }, 2 }
#define LC10               { 868300000, 0, { ( ( DR_6 << 4 ) | DR_6 ) }, 1 }

#endif

#endif

static uint8_t DevEui[] = LORAWAN_DEVICE_EUI;
static uint8_t AppEui[] = LORAWAN_APPLICATION_EUI;
static uint8_t AppKey[] = LORAWAN_APPLICATION_KEY;

static MlmeReqJoin_t JoinParameters;

#if( OVER_THE_AIR_ACTIVATION == 0 )

static uint8_t NwkSKey[] = LORAWAN_NWKSKEY;
static uint8_t AppSKey[] = LORAWAN_APPSKEY;
static uint32_t DevAddr = LORAWAN_DEVICE_ADDRESS;
#endif

/*!
 * Defines the LoRa parameters at Init
 */
static LoRaParam_t* LoRaParamInit;
static LoRaMacPrimitives_t LoRaMacPrimitives;
static LoRaMacCallback_t LoRaMacCallbacks;
static MibRequestConfirm_t mibReq;

static LoRaMainCallback_t *LoRaMainCallbacks;
/*!
 * \brief   MCPS-Confirm event function
 *
 * \param   [IN] McpsConfirm - Pointer to the confirm structure,
 *               containing confirm attributes.
 */
static void McpsConfirm( McpsConfirm_t *mcpsConfirm )
{
    if( mcpsConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK )
    {
        switch( mcpsConfirm->McpsRequest )
        {
            case MCPS_UNCONFIRMED:
            {
                // Check Datarate
                // Check TxPower
                break;
            }
            case MCPS_CONFIRMED:
            {
                // Check Datarate
                // Check TxPower
                // Check AckReceived
                // Check NbTrials
                break;
            }
            case MCPS_PROPRIETARY:
            {
                break;
            }
            default:
                break;
        }
    }
}

/*!
 * \brief   MCPS-Indication event function
 *
 * \param   [IN] mcpsIndication - Pointer to the indication structure,
 *               containing indication attributes.
 */
static void McpsIndication( McpsIndication_t *mcpsIndication )
{
    lora_AppData_t AppData;
    if( mcpsIndication->Status != LORAMAC_EVENT_INFO_STATUS_OK )
    {
        return;
    }

    switch( mcpsIndication->McpsIndication )
    {
        case MCPS_UNCONFIRMED:
        {
            break;
        }
        case MCPS_CONFIRMED:
        {
            break;
        }
        case MCPS_PROPRIETARY:
        {
            break;
        }
        case MCPS_MULTICAST:
        {
            break;
        }
        default:
            break;
    }

    // Check Multicast
    // Check Port
    // Check Datarate
    // Check FramePending
    // Check Buffer
    // Check BufferSize
    // Check Rssi
    // Check Snr
    // Check RxSlot
    if (certif_running() == true )
    {
      certif_DownLinkIncrement( );
    }

    if( mcpsIndication->RxData == true )
    {
      switch( mcpsIndication->Port )
      {
        case CERTIF_PORT:
          certif_rx( mcpsIndication, &JoinParameters );
          break;
        default:
          
          AppData.Port = mcpsIndication->Port;
          AppData.BuffSize = mcpsIndication->BufferSize;
          AppData.Buff = mcpsIndication->Buffer;
        
          LoRaMainCallbacks->LORA_RxData( &AppData );
          break;
      }
    }
}

/*!
 * \brief   MLME-Confirm event function
 *
 * \param   [IN] MlmeConfirm - Pointer to the confirm structure,
 *               containing confirm attributes.
 */
static void MlmeConfirm( MlmeConfirm_t *mlmeConfirm )
{
    switch( mlmeConfirm->MlmeRequest )
    {
        case MLME_JOIN:
        {
            if( mlmeConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK )
            {
                // Status is OK, node has joined the network
              LoRaMainCallbacks->LORA_HasJoined();
            }
            else
            {
                // Join was not successful. Try to join again
                LORA_Join();
            }
            break;
        }
        case MLME_LINK_CHECK:
        {
            if( mlmeConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK )
            {
                // Check DemodMargin
                // Check NbGateways
                if (certif_running() == true )
                {
                     certif_linkCheck( mlmeConfirm);
                }
            }
            break;
        }
        default:
            break;
    }
}
/**
 *  lora Init
 */
void LORA_Init (LoRaMainCallback_t *callbacks, LoRaParam_t* LoRaParam )
{
  /* init the Tx Duty Cycle*/
  LoRaParamInit = LoRaParam;
  
  /* init the main call backs*/
  LoRaMainCallbacks = callbacks;
  
#if (STATIC_DEVICE_EUI != 1)
  LoRaMainCallbacks->BoardGetUniqueId( DevEui );  
#endif
  
#ifdef TO_SE
  if (TO_lora_get_app_eui(AppEui) != TORSP_SUCCESS) {
    PRINTF("TO_lora_get_app_eui failed\n");
  }
  if (TO_lora_get_dev_eui(DevEui) != TORSP_SUCCESS) {
    PRINTF("TO_lora_get_app_eui failed\n");
  }
#endif

#if( OVER_THE_AIR_ACTIVATION != 0 )

  PRINTF("OTAA\n\r"); 
  PRINTF("DevEui= %02X", DevEui[0]) ;for(int i=1; i<8 ; i++) {PRINTF("-%02X", DevEui[i]); }; PRINTF("\n\r");
  PRINTF("AppEui= %02X", AppEui[0]) ;for(int i=1; i<8 ; i++) {PRINTF("-%02X", AppEui[i]); }; PRINTF("\n\r");
#ifndef TO_SE
  PRINTF("AppKey= %02X", AppKey[0]) ;for(int i=1; i<16; i++) {PRINTF(" %02X", AppKey[i]); }; PRINTF("\n\n\r");
#endif
#else

#if (STATIC_DEVICE_ADDRESS != 1)
  // Random seed initialization
  srand1( LoRaMainCallbacks->BoardGetRandomSeed( ) );
  // Choose a random device address
  DevAddr = randr( 0, 0x01FFFFFF );
#endif
  PRINTF("ABP\n\r"); 
  PRINTF("DevEui= %02X", DevEui[0]) ;for(int i=1; i<8 ; i++) {PRINTF("-%02X", DevEui[i]); }; PRINTF("\n\r");
  PRINTF("DevAdd=  %08X\n\r", DevAddr) ;
#ifndef TO_SE
  PRINTF("NwkSKey= %02X", NwkSKey[0]) ;for(int i=1; i<16 ; i++) {PRINTF(" %02X", NwkSKey[i]); }; PRINTF("\n\r");
  PRINTF("AppSKey= %02X", AppSKey[0]) ;for(int i=1; i<16 ; i++) {PRINTF(" %02X", AppSKey[i]); }; PRINTF("\n\r");
#endif
#endif
        LoRaMacPrimitives.MacMcpsConfirm = McpsConfirm;
        LoRaMacPrimitives.MacMcpsIndication = McpsIndication;
        LoRaMacPrimitives.MacMlmeConfirm = MlmeConfirm;
        LoRaMacCallbacks.GetBatteryLevel = LoRaMainCallbacks->BoardGetBatteryLevel;
#if defined( REGION_AS923 )
        LoRaMacInitialization( &LoRaMacPrimitives, &LoRaMacCallbacks, LORAMAC_REGION_AS923 );
#elif defined( REGION_AU915 )
        LoRaMacInitialization( &LoRaMacPrimitives, &LoRaMacCallbacks, LORAMAC_REGION_AU915 );
#elif defined( REGION_CN470 )
        LoRaMacInitialization( &LoRaMacPrimitives, &LoRaMacCallbacks, LORAMAC_REGION_CN470 );
#elif defined( REGION_CN779 )
        LoRaMacInitialization( &LoRaMacPrimitives, &LoRaMacCallbacks, LORAMAC_REGION_CN779 );
#elif defined( REGION_EU433 )
        LoRaMacInitialization( &LoRaMacPrimitives, &LoRaMacCallbacks, LORAMAC_REGION_EU433 );
 #elif defined( REGION_IN865 )
        LoRaMacInitialization( &LoRaMacPrimitives, &LoRaMacCallbacks, LORAMAC_REGION_IN865 );
#elif defined( REGION_EU868 )
        LoRaMacInitialization( &LoRaMacPrimitives, &LoRaMacCallbacks, LORAMAC_REGION_EU868 );
#elif defined( REGION_KR920 )
        LoRaMacInitialization( &LoRaMacPrimitives, &LoRaMacCallbacks, LORAMAC_REGION_KR920 );
#elif defined( REGION_US915 )
        LoRaMacInitialization( &LoRaMacPrimitives, &LoRaMacCallbacks, LORAMAC_REGION_US915 );
#elif defined( REGION_US915_HYBRID )
        LoRaMacInitialization( &LoRaMacPrimitives, &LoRaMacCallbacks, LORAMAC_REGION_US915_HYBRID );
#else
    #error "Please define a region in the compiler options."
#endif
      
      mibReq.Type = MIB_ADR;
      mibReq.Param.AdrEnable = LoRaParamInit->AdrEnable;
      LoRaMacMibSetRequestConfirm( &mibReq );

      mibReq.Type = MIB_PUBLIC_NETWORK;
      mibReq.Param.EnablePublicNetwork = LoRaParamInit->EnablePublicNetwork;
      LoRaMacMibSetRequestConfirm( &mibReq );
                      
      mibReq.Type = MIB_DEVICE_CLASS;
      mibReq.Param.Class= CLASS_A;
      LoRaMacMibSetRequestConfirm( &mibReq );

#if defined( REGION_EU868 )
      LoRaMacTestSetDutyCycleOn( LORAWAN_DUTYCYCLE_ON );

#if( USE_SEMTECH_DEFAULT_CHANNEL_LINEUP == 1 )
      LoRaMacChannelAdd( 3, ( ChannelParams_t )LC4 );
      LoRaMacChannelAdd( 4, ( ChannelParams_t )LC5 );
      LoRaMacChannelAdd( 5, ( ChannelParams_t )LC6 );
      LoRaMacChannelAdd( 6, ( ChannelParams_t )LC7 );
      LoRaMacChannelAdd( 7, ( ChannelParams_t )LC8 );
      LoRaMacChannelAdd( 8, ( ChannelParams_t )LC9 );
      LoRaMacChannelAdd( 9, ( ChannelParams_t )LC10 );

      mibReq.Type = MIB_RX2_DEFAULT_CHANNEL;
      mibReq.Param.Rx2DefaultChannel = ( Rx2ChannelParams_t ){ 869525000, DR_3 };
      LoRaMacMibSetRequestConfirm( &mibReq );

      mibReq.Type = MIB_RX2_CHANNEL;
      mibReq.Param.Rx2Channel = ( Rx2ChannelParams_t ){ 869525000, DR_3 };
      LoRaMacMibSetRequestConfirm( &mibReq );
#endif

#endif
}


void LORA_Join( void)
{
    MlmeReq_t mlmeReq;
  
    mlmeReq.Type = MLME_JOIN;
    mlmeReq.Req.Join.DevEui = DevEui;
    mlmeReq.Req.Join.AppEui = AppEui;
    mlmeReq.Req.Join.AppKey = AppKey;
    mlmeReq.Req.Join.NbTrials = LoRaParamInit->NbTrials;
  
    JoinParameters = mlmeReq.Req.Join;

#if( OVER_THE_AIR_ACTIVATION != 0 )
    LoRaMacMlmeRequest( &mlmeReq );
#else
    mibReq.Type = MIB_NET_ID;
    mibReq.Param.NetID = LORAWAN_NETWORK_ID;
    LoRaMacMibSetRequestConfirm( &mibReq );

    mibReq.Type = MIB_DEV_ADDR;
    mibReq.Param.DevAddr = DevAddr;
    LoRaMacMibSetRequestConfirm( &mibReq );

    mibReq.Type = MIB_NWK_SKEY;
    mibReq.Param.NwkSKey = NwkSKey;
    LoRaMacMibSetRequestConfirm( &mibReq );

    mibReq.Type = MIB_APP_SKEY;
    mibReq.Param.AppSKey = AppSKey;
    LoRaMacMibSetRequestConfirm( &mibReq );

    mibReq.Type = MIB_NETWORK_JOINED;
    mibReq.Param.IsNetworkJoined = true;
    LoRaMacMibSetRequestConfirm( &mibReq );

    LoRaMainCallbacks->LORA_HasJoined();
#endif
}

LoraFlagStatus LORA_JoinStatus( void)
{
  MibRequestConfirm_t mibReq;

  mibReq.Type = MIB_NETWORK_JOINED;
  
  LoRaMacMibGetRequestConfirm( &mibReq );

  if( mibReq.Param.IsNetworkJoined == true )
  {
    return LORA_SET;
  }
  else
  {
    return LORA_RESET;
  }
}



bool LORA_send(lora_AppData_t* AppData, LoraConfirm_t IsTxConfirmed)
{
    McpsReq_t mcpsReq;
    LoRaMacTxInfo_t txInfo;
  
    /*if certification test are on going, application data is not sent*/
    if (certif_running() == true)
    {
      return false;
    }
    
    if( LoRaMacQueryTxPossible( AppData->BuffSize, &txInfo ) != LORAMAC_STATUS_OK )
    {
        // Send empty frame in order to flush MAC commands
        mcpsReq.Type = MCPS_UNCONFIRMED;
        mcpsReq.Req.Unconfirmed.fBuffer = NULL;
        mcpsReq.Req.Unconfirmed.fBufferSize = 0;
        mcpsReq.Req.Unconfirmed.Datarate = LoRaParamInit->TxDatarate;
    }
    else
    {
        if( IsTxConfirmed == LORAWAN_UNCONFIRMED_MSG )
        {
            mcpsReq.Type = MCPS_UNCONFIRMED;
            mcpsReq.Req.Unconfirmed.fPort = AppData->Port;
            mcpsReq.Req.Unconfirmed.fBufferSize = AppData->BuffSize;
            mcpsReq.Req.Unconfirmed.fBuffer = AppData->Buff;
            mcpsReq.Req.Unconfirmed.Datarate = LoRaParamInit->TxDatarate;
        }
        else
        {
            mcpsReq.Type = MCPS_CONFIRMED;
            mcpsReq.Req.Confirmed.fPort = AppData->Port;
            mcpsReq.Req.Confirmed.fBufferSize = AppData->BuffSize;
            mcpsReq.Req.Confirmed.fBuffer = AppData->Buff;
            mcpsReq.Req.Confirmed.NbTrials = 8;
            mcpsReq.Req.Confirmed.Datarate = LoRaParamInit->TxDatarate;
        }
    }
    if( LoRaMacMcpsRequest( &mcpsReq ) == LORAMAC_STATUS_OK )
    {
        return false;
    }
    return true;
}  

LoraErrorStatus LORA_RequestClass( DeviceClass_t newClass )
{
  LoraErrorStatus Errorstatus = LORA_SUCCESS;
  MibRequestConfirm_t mibReq;
  DeviceClass_t currentClass;
  
  mibReq.Type = MIB_DEVICE_CLASS;
  LoRaMacMibGetRequestConfirm( &mibReq );
  
  currentClass = mibReq.Param.Class;
  /*attempt to swicth only if class update*/
  if (currentClass != newClass)
  {
    switch (newClass)
    {
      case CLASS_A:
      {
        if (currentClass == CLASS_A)
        {
          mibReq.Param.Class = CLASS_A;
          if( LoRaMacMibSetRequestConfirm( &mibReq ) == LORAMAC_STATUS_OK )
          {
          /*switch is instantanuous*/
            LoRaMainCallbacks->LORA_ConfirmClass(CLASS_A);
          }
          else
          {
            Errorstatus = LORA_ERROR;
          }
        }
        break;
      }
      case CLASS_C:
      {
        if (currentClass != CLASS_A)
        {
          Errorstatus = LORA_ERROR;
        }
        /*switch is instantanuous*/
        mibReq.Param.Class = CLASS_C;
        if( LoRaMacMibSetRequestConfirm( &mibReq ) == LORAMAC_STATUS_OK )
        {
          LoRaMainCallbacks->LORA_ConfirmClass(CLASS_C);
        }
        else
        {
            Errorstatus = LORA_ERROR;
        }
        break;
      }
      default:
        break;
    } 
  }
  return Errorstatus;
}

void LORA_GetCurrentClass( DeviceClass_t *currentClass )
{
  MibRequestConfirm_t mibReq;
  
  mibReq.Type = MIB_DEVICE_CLASS;
  LoRaMacMibGetRequestConfirm( &mibReq );
  
  *currentClass = mibReq.Param.Class;
}

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

LoRaMac.c

C/C++
Based on STM32CubeExpansion_LRWAN_V1.1.4.
File location: Middlewares/Third_Party/Lora/Mac/LoRaMac.c
/*
 / _____)             _              | |
( (____  _____ ____ _| |_ _____  ____| |__
 \____ \| ___ |    (_   _) ___ |/ ___)  _ \
 _____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
    (C)2013 Semtech
 ___ _____ _   ___ _  _____ ___  ___  ___ ___
/ __|_   _/_\ / __| |/ / __/ _ \| _ \/ __| __|
\__ \ | |/ _ \ (__| ' <| _| (_) |   / (__| _|
|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
embedded.connectivity.solutions===============

Description: LoRa MAC layer implementation

License: Revised BSD License, see LICENSE.TXT file include in the project

Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
*/


#include <stdbool.h>
#include <string.h>
#include <stdint.h>
#include "radio.h"
#include "timeServer.h"
#include "LoRaMac.h"
#include "region/Region.h"
#ifndef TO_SE
#include "LoRaMacCrypto.h"
#else
#include "LoRaMacCrypto_TO.h"
#endif

#include "debug.h"
#include "LoRaMacTest.h"



/*!
 * Maximum PHY layer payload size
 */
#define LORAMAC_PHY_MAXPAYLOAD                      255

/*!
 * Maximum MAC commands buffer size
 */
#define LORA_MAC_COMMAND_MAX_LENGTH                 128

/*!
 * Maximum length of the fOpts field
 */
#define LORA_MAC_COMMAND_MAX_FOPTS_LENGTH           15

/*!
 * LoRaMac region.
 */
static LoRaMacRegion_t LoRaMacRegion;

/*!
 * LoRaMac duty cycle for the back-off procedure during the first hour.
 */
#define BACKOFF_DC_1_HOUR                           100

/*!
 * LoRaMac duty cycle for the back-off procedure during the next 10 hours.
 */
#define BACKOFF_DC_10_HOURS                         1000

/*!
 * LoRaMac duty cycle for the back-off procedure during the next 24 hours.
 */
#define BACKOFF_DC_24_HOURS                         10000

#ifndef TO_SE
/*!
 * Device IEEE EUI
 */
static uint8_t *LoRaMacDevEui;

/*!
 * Application IEEE EUI
 */
static uint8_t *LoRaMacAppEui;

/*!
 * AES encryption/decryption cipher application key
 */
static uint8_t *LoRaMacAppKey;

/*!
 * AES encryption/decryption cipher network session key
 */
static uint8_t LoRaMacNwkSKey[] =
{
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

/*!
 * AES encryption/decryption cipher application session key
 */
static uint8_t LoRaMacAppSKey[] =
{
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

/*!
 * Device nonce is a random value extracted by issuing a sequence of RSSI
 * measurements
 */
static uint16_t LoRaMacDevNonce;
#endif

/*!
 * Network ID ( 3 bytes )
 */
static uint32_t LoRaMacNetID;

/*!
 * Mote Address
 */
static uint32_t LoRaMacDevAddr;

/*!
 * Multicast channels linked list
 */
static MulticastParams_t *MulticastChannels = NULL;

/*!
 * Actual device class
 */
static DeviceClass_t LoRaMacDeviceClass;

/*!
 * Indicates if the node is connected to a private or public network
 */
static bool PublicNetwork;

/*!
 * Indicates if the node supports repeaters
 */
static bool RepeaterSupport;

/*!
 * Buffer containing the data to be sent or received.
 */
static uint8_t LoRaMacBuffer[LORAMAC_PHY_MAXPAYLOAD];

/*!
 * Length of packet in LoRaMacBuffer
 */
static uint16_t LoRaMacBufferPktLen = 0;

/*!
 * Length of the payload in LoRaMacBuffer
 */
static uint8_t LoRaMacTxPayloadLen = 0;

/*!
 * Buffer containing the upper layer data.
 */
static uint8_t LoRaMacRxPayload[LORAMAC_PHY_MAXPAYLOAD];

/*!
 * LoRaMAC frame counter. Each time a packet is sent the counter is incremented.
 * Only the 16 LSB bits are sent
 */
static uint32_t UpLinkCounter = 0;

/*!
 * LoRaMAC frame counter. Each time a packet is received the counter is incremented.
 * Only the 16 LSB bits are received
 */
static uint32_t DownLinkCounter = 0;

/*!
 * IsPacketCounterFixed enables the MIC field tests by fixing the
 * UpLinkCounter value
 */
static bool IsUpLinkCounterFixed = false;

/*!
 * Used for test purposes. Disables the opening of the reception windows.
 */
static bool IsRxWindowsEnabled = true;

/*!
 * Indicates if the MAC layer has already joined a network.
 */
static bool IsLoRaMacNetworkJoined = false;

/*!
 * LoRaMac ADR control status
 */
static bool AdrCtrlOn = false;

/*!
 * Counts the number of missed ADR acknowledgements
 */
static uint32_t AdrAckCounter = 0;

/*!
 * If the node has sent a FRAME_TYPE_DATA_CONFIRMED_UP this variable indicates
 * if the nodes needs to manage the server acknowledgement.
 */
static bool NodeAckRequested = false;

/*!
 * If the server has sent a FRAME_TYPE_DATA_CONFIRMED_DOWN this variable indicates
 * if the ACK bit must be set for the next transmission
 */
static bool SrvAckRequested = false;

/*!
 * Indicates if the MAC layer wants to send MAC commands
 */
static bool MacCommandsInNextTx = false;

/*!
 * Contains the current MacCommandsBuffer index
 */
static uint8_t MacCommandsBufferIndex = 0;

/*!
 * Contains the current MacCommandsBuffer index for MAC commands to repeat
 */
static uint8_t MacCommandsBufferToRepeatIndex = 0;

/*!
 * Buffer containing the MAC layer commands
 */
static uint8_t MacCommandsBuffer[LORA_MAC_COMMAND_MAX_LENGTH];

/*!
 * Buffer containing the MAC layer commands which must be repeated
 */
static uint8_t MacCommandsBufferToRepeat[LORA_MAC_COMMAND_MAX_LENGTH];

/*!
 * LoRaMac parameters
 */
LoRaMacParams_t LoRaMacParams;

/*!
 * LoRaMac default parameters
 */
LoRaMacParams_t LoRaMacParamsDefaults;

/*!
 * Uplink messages repetitions counter
 */
static uint8_t ChannelsNbRepCounter = 0;

/*!
 * Maximum duty cycle
 * \remark Possibility to shutdown the device.
 */
static uint8_t MaxDCycle = 0;

/*!
 * Aggregated duty cycle management
 */
static uint16_t AggregatedDCycle;
static TimerTime_t AggregatedLastTxDoneTime;
static TimerTime_t AggregatedTimeOff;

/*!
 * Enables/Disables duty cycle management (Test only)
 */
static bool DutyCycleOn;

/*!
 * Current channel index
 */
static uint8_t Channel;

/*!
 * Current channel index
 */
static uint8_t LastTxChannel;

/*!
 * Set to true, if the last uplink was a join request
 */
static bool LastTxIsJoinRequest;

/*!
 * Stores the time at LoRaMac initialization.
 *
 * \remark Used for the BACKOFF_DC computation.
 */
static TimerTime_t LoRaMacInitializationTime = 0;

/*!
 * LoRaMac internal states
 */
enum eLoRaMacState
{
    LORAMAC_IDLE          = 0x00000000,
    LORAMAC_TX_RUNNING    = 0x00000001,
    LORAMAC_RX            = 0x00000002,
    LORAMAC_ACK_REQ       = 0x00000004,
    LORAMAC_ACK_RETRY     = 0x00000008,
    LORAMAC_TX_DELAYED    = 0x00000010,
    LORAMAC_TX_CONFIG     = 0x00000020,
    LORAMAC_RX_ABORT      = 0x00000040,
};

/*!
 * LoRaMac internal state
 */
uint32_t LoRaMacState = LORAMAC_IDLE;

/*!
 * LoRaMac timer used to check the LoRaMacState (runs every second)
 */
static TimerEvent_t MacStateCheckTimer;

/*!
 * LoRaMac upper layer event functions
 */
static LoRaMacPrimitives_t *LoRaMacPrimitives;

/*!
 * LoRaMac upper layer callback functions
 */
static LoRaMacCallback_t *LoRaMacCallbacks;

/*!
 * Radio events function pointer
 */
static RadioEvents_t RadioEvents;

/*!
 * LoRaMac duty cycle delayed Tx timer
 */
static TimerEvent_t TxDelayedTimer;

/*!
 * LoRaMac reception windows timers
 */
static TimerEvent_t RxWindowTimer1;
static TimerEvent_t RxWindowTimer2;

/*!
 * LoRaMac reception windows delay
 * \remark normal frame: RxWindowXDelay = ReceiveDelayX - RADIO_WAKEUP_TIME
 *         join frame  : RxWindowXDelay = JoinAcceptDelayX - RADIO_WAKEUP_TIME
 */
static uint32_t RxWindow1Delay;
static uint32_t RxWindow2Delay;

/*!
 * LoRaMac Rx windows configuration
 */
static RxConfigParams_t RxWindow1Config;
static RxConfigParams_t RxWindow2Config;

/*!
 * Acknowledge timeout timer. Used for packet retransmissions.
 */
static TimerEvent_t AckTimeoutTimer;

/*!
 * Number of trials to get a frame acknowledged
 */
static uint8_t AckTimeoutRetries = 1;

/*!
 * Number of trials to get a frame acknowledged
 */
static uint8_t AckTimeoutRetriesCounter = 1;

/*!
 * Indicates if the AckTimeout timer has expired or not
 */
static bool AckTimeoutRetry = false;

/*!
 * Last transmission time on air
 */
TimerTime_t TxTimeOnAir = 0;

/*!
 * Number of trials for the Join Request
 */
static uint8_t JoinRequestTrials;

/*!
 * Maximum number of trials for the Join Request
 */
static uint8_t MaxJoinRequestTrials;

/*!
 * Structure to hold an MCPS indication data.
 */
static McpsIndication_t McpsIndication;

/*!
 * Structure to hold MCPS confirm data.
 */
static McpsConfirm_t McpsConfirm;

/*!
 * Structure to hold MLME confirm data.
 */
static MlmeConfirm_t MlmeConfirm;

/*!
 * Holds the current rx window slot
 */
static uint8_t RxSlot = 0;

/*!
 * LoRaMac tx/rx operation state
 */
LoRaMacFlags_t LoRaMacFlags;

/*!
 * \brief Function to be executed on Radio Tx Done event
 */
static void OnRadioTxDone( void );

/*!
 * \brief This function prepares the MAC to abort the execution of function
 *        OnRadioRxDone in case of a reception error.
 */
static void PrepareRxDoneAbort( void );

/*!
 * \brief Function to be executed on Radio Rx Done event
 */
static void OnRadioRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr );

/*!
 * \brief Function executed on Radio Tx Timeout event
 */
static void OnRadioTxTimeout( void );

/*!
 * \brief Function executed on Radio Rx error event
 */
static void OnRadioRxError( void );

/*!
 * \brief Function executed on Radio Rx Timeout event
 */
static void OnRadioRxTimeout( void );

/*!
 * \brief Function executed on Resend Frame timer event.
 */
static void OnMacStateCheckTimerEvent( void );

/*!
 * \brief Function executed on duty cycle delayed Tx  timer event
 */
static void OnTxDelayedTimerEvent( void );

/*!
 * \brief Function executed on first Rx window timer event
 */
static void OnRxWindow1TimerEvent( void );

/*!
 * \brief Function executed on second Rx window timer event
 */
static void OnRxWindow2TimerEvent( void );

/*!
 * \brief Function executed on AckTimeout timer event
 */
static void OnAckTimeoutTimerEvent( void );

/*!
 * \brief Initializes and opens the reception window
 *
 * \param [IN] rxContinuous Set to true, if the RX is in continuous mode
 * \param [IN] maxRxWindow Maximum RX window timeout
 */
static void RxWindowSetup( bool rxContinuous, uint32_t maxRxWindow );

/*!
 * \brief Adds a new MAC command to be sent.
 *
 * \Remark MAC layer internal function
 *
 * \param [in] cmd MAC command to be added
 *                 [MOTE_MAC_LINK_CHECK_REQ,
 *                  MOTE_MAC_LINK_ADR_ANS,
 *                  MOTE_MAC_DUTY_CYCLE_ANS,
 *                  MOTE_MAC_RX2_PARAM_SET_ANS,
 *                  MOTE_MAC_DEV_STATUS_ANS
 *                  MOTE_MAC_NEW_CHANNEL_ANS]
 * \param [in] p1  1st parameter ( optional depends on the command )
 * \param [in] p2  2nd parameter ( optional depends on the command )
 *
 * \retval status  Function status [0: OK, 1: Unknown command, 2: Buffer full]
 */
static LoRaMacStatus_t AddMacCommand( uint8_t cmd, uint8_t p1, uint8_t p2 );

/*!
 * \brief Parses the MAC commands which must be repeated.
 *
 * \Remark MAC layer internal function
 *
 * \param [IN] cmdBufIn  Buffer which stores the MAC commands to send
 * \param [IN] length  Length of the input buffer to parse
 * \param [OUT] cmdBufOut  Buffer which stores the MAC commands which must be
 *                         repeated.
 *
 * \retval Size of the MAC commands to repeat.
 */
static uint8_t ParseMacCommandsToRepeat( uint8_t* cmdBufIn, uint8_t length, uint8_t* cmdBufOut );

/*!
 * \brief Validates if the payload fits into the frame, taking the datarate
 *        into account.
 *
 * \details Refer to chapter 4.3.2 of the LoRaWAN specification, v1.0
 *
 * \param lenN Length of the application payload. The length depends on the
 *             datarate and is region specific
 *
 * \param datarate Current datarate
 *
 * \param fOptsLen Length of the fOpts field
 *
 * \retval [false: payload does not fit into the frame, true: payload fits into
 *          the frame]
 */
static bool ValidatePayloadLength( uint8_t lenN, int8_t datarate, uint8_t fOptsLen );

/*!
 * \brief Decodes MAC commands in the fOpts field and in the payload
 */
static void ProcessMacCommands( uint8_t *payload, uint8_t macIndex, uint8_t commandsSize, uint8_t snr );

/*!
 * \brief LoRaMAC layer generic send frame
 *
 * \param [IN] macHdr      MAC header field
 * \param [IN] fPort       MAC payload port
 * \param [IN] fBuffer     MAC data buffer to be sent
 * \param [IN] fBufferSize MAC data buffer size
 * \retval status          Status of the operation.
 */
LoRaMacStatus_t Send( LoRaMacHeader_t *macHdr, uint8_t fPort, void *fBuffer, uint16_t fBufferSize );

/*!
 * \brief LoRaMAC layer frame buffer initialization
 *
 * \param [IN] macHdr      MAC header field
 * \param [IN] fCtrl       MAC frame control field
 * \param [IN] fOpts       MAC commands buffer
 * \param [IN] fPort       MAC payload port
 * \param [IN] fBuffer     MAC data buffer to be sent
 * \param [IN] fBufferSize MAC data buffer size
 * \retval status          Status of the operation.
 */
LoRaMacStatus_t PrepareFrame( LoRaMacHeader_t *macHdr, LoRaMacFrameCtrl_t *fCtrl, uint8_t fPort, void *fBuffer, uint16_t fBufferSize );

/*
 * \brief Schedules the frame according to the duty cycle
 *
 * \retval Status of the operation
 */
static LoRaMacStatus_t ScheduleTx( void );

/*
 * \brief Calculates the back-off time for the band of a channel.
 *
 * \param [IN] channel     The last Tx channel index
 */
static void CalculateBackOff( uint8_t channel );

/*!
 * \brief LoRaMAC layer prepared frame buffer transmission with channel specification
 *
 * \remark PrepareFrame must be called at least once before calling this
 *         function.
 *
 * \param [IN] channel     Channel to transmit on
 * \retval status          Status of the operation.
 */
LoRaMacStatus_t SendFrameOnChannel( uint8_t channel );

/*!
 * \brief Sets the radio in continuous transmission mode
 *
 * \remark Uses the radio parameters set on the previous transmission.
 *
 * \param [IN] timeout     Time in seconds while the radio is kept in continuous wave mode
 * \retval status          Status of the operation.
 */
LoRaMacStatus_t SetTxContinuousWave( uint16_t timeout );

/*!
 * \brief Sets the radio in continuous transmission mode
 *
 * \remark Uses the radio parameters set on the previous transmission.
 *
 * \param [IN] timeout     Time in seconds while the radio is kept in continuous wave mode
 * \param [IN] frequency   RF frequency to be set.
 * \param [IN] power       RF output power to be set.
 * \retval status          Status of the operation.
 */
LoRaMacStatus_t SetTxContinuousWave1( uint16_t timeout, uint32_t frequency, uint8_t power );

/*!
 * \brief Resets MAC specific parameters to default
 */
static void ResetMacParameters( void );

static void OnRadioTxDone( void )
{
    GetPhyParams_t getPhy;
    PhyParam_t phyParam;
    SetBandTxDoneParams_t txDone;
    TimerTime_t curTime = TimerGetCurrentTime( );

    if( LoRaMacDeviceClass != CLASS_C )
    {
        Radio.Sleep( );
    }
    else
    {
        OnRxWindow2TimerEvent( );
    }

    // Setup timers
    if( IsRxWindowsEnabled == true )
    {
        TimerSetValue( &RxWindowTimer1, RxWindow1Delay );
        TimerStart( &RxWindowTimer1 );
        if( LoRaMacDeviceClass != CLASS_C )
        {
            TimerSetValue( &RxWindowTimer2, RxWindow2Delay );
            TimerStart( &RxWindowTimer2 );
        }
        if( ( LoRaMacDeviceClass == CLASS_C ) || ( NodeAckRequested == true ) )
        {
            getPhy.Attribute = PHY_ACK_TIMEOUT;
            phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
            TimerSetValue( &AckTimeoutTimer, RxWindow2Delay + phyParam.Value );
            TimerStart( &AckTimeoutTimer );
        }
    }
    else
    {
        McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK;
        MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT;

        if( LoRaMacFlags.Value == 0 )
        {
            LoRaMacFlags.Bits.McpsReq = 1;
        }
        LoRaMacFlags.Bits.MacDone = 1;
    }

    // Verify if the last uplink was a join request
    if( ( LoRaMacFlags.Bits.MlmeReq == 1 ) && ( MlmeConfirm.MlmeRequest == MLME_JOIN ) )
    {
        LastTxIsJoinRequest = true;
    }
    else
    {
        LastTxIsJoinRequest = false;
    }

    // Store last Tx channel
    LastTxChannel = Channel;
    // Update last tx done time for the current channel
    txDone.Channel = Channel;
    txDone.Joined = IsLoRaMacNetworkJoined;
    txDone.LastTxDoneTime = curTime;
    RegionSetBandTxDone( LoRaMacRegion, &txDone );
    // Update Aggregated last tx done time
    AggregatedLastTxDoneTime = curTime;

    if( NodeAckRequested == false )
    {
        McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK;
        ChannelsNbRepCounter++;
    }
}

static void PrepareRxDoneAbort( void )
{
    LoRaMacState |= LORAMAC_RX_ABORT;

    if( NodeAckRequested )
    {
        OnAckTimeoutTimerEvent( );
    }

    LoRaMacFlags.Bits.McpsInd = 1;
    LoRaMacFlags.Bits.MacDone = 1;

    // Trig OnMacCheckTimerEvent call as soon as possible
    TimerSetValue( &MacStateCheckTimer, 1 );
    TimerStart( &MacStateCheckTimer );
}

static void OnRadioRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr )
{
    LoRaMacHeader_t macHdr;
    LoRaMacFrameCtrl_t fCtrl;
    ApplyCFListParams_t applyCFList;
    GetPhyParams_t getPhy;
    PhyParam_t phyParam;
    bool skipIndication = false;

    uint8_t pktHeaderLen = 0;
    uint32_t address = 0;
    uint8_t appPayloadStartIndex = 0;
    uint8_t port = 0xFF;
    uint8_t frameLen = 0;
#ifndef TO_SE
    uint32_t mic = 0;
    uint32_t micRx = 0;
#endif

    uint16_t sequenceCounter = 0;
    uint16_t sequenceCounterPrev = 0;
    uint16_t sequenceCounterDiff = 0;
    uint32_t downLinkCounter = 0;

    MulticastParams_t *curMulticastParams = NULL;
#ifndef TO_SE
    uint8_t *nwkSKey = LoRaMacNwkSKey;
    uint8_t *appSKey = LoRaMacAppSKey;
#endif

    uint8_t multicast = 0;

    bool isMicOk = false;

    McpsConfirm.AckReceived = false;
    McpsIndication.Rssi = rssi;
    McpsIndication.Snr = snr;
    McpsIndication.RxSlot = RxSlot;
    McpsIndication.Port = 0;
    McpsIndication.Multicast = 0;
    McpsIndication.FramePending = 0;
    McpsIndication.Buffer = NULL;
    McpsIndication.BufferSize = 0;
    McpsIndication.RxData = false;
    McpsIndication.AckReceived = false;
    McpsIndication.DownLinkCounter = 0;
    McpsIndication.McpsIndication = MCPS_UNCONFIRMED;

    Radio.Sleep( );
    TimerStop( &RxWindowTimer2 );

    macHdr.Value = payload[pktHeaderLen++];

    switch( macHdr.Bits.MType )
    {
        case FRAME_TYPE_JOIN_ACCEPT:
            if( IsLoRaMacNetworkJoined == true )
            {
                McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
                PrepareRxDoneAbort( );
                return;
            }
#ifndef TO_SE
            LoRaMacJoinDecrypt( payload + 1, size - 1, LoRaMacAppKey, LoRaMacRxPayload + 1 );

            LoRaMacRxPayload[0] = macHdr.Value;

            LoRaMacJoinComputeMic( LoRaMacRxPayload, size - LORAMAC_MFR_LEN, LoRaMacAppKey, &mic );

            micRx |= ( uint32_t )LoRaMacRxPayload[size - LORAMAC_MFR_LEN];
            micRx |= ( ( uint32_t )LoRaMacRxPayload[size - LORAMAC_MFR_LEN + 1] << 8 );
            micRx |= ( ( uint32_t )LoRaMacRxPayload[size - LORAMAC_MFR_LEN + 2] << 16 );
            micRx |= ( ( uint32_t )LoRaMacRxPayload[size - LORAMAC_MFR_LEN + 3] << 24 );

            if( micRx == mic )
            {
                LoRaMacJoinComputeSKeys( LoRaMacAppKey, LoRaMacRxPayload + 1, LoRaMacDevNonce, LoRaMacNwkSKey, LoRaMacAppSKey );
#else
            if (LoRaMacHandleJoinAccept( payload, size, LoRaMacRxPayload ) == LORAMAC_CRYPTO_STATUS_OK)
            {
#endif

                LoRaMacNetID = ( uint32_t )LoRaMacRxPayload[4];
                LoRaMacNetID |= ( ( uint32_t )LoRaMacRxPayload[5] << 8 );
                LoRaMacNetID |= ( ( uint32_t )LoRaMacRxPayload[6] << 16 );

                LoRaMacDevAddr = ( uint32_t )LoRaMacRxPayload[7];
                LoRaMacDevAddr |= ( ( uint32_t )LoRaMacRxPayload[8] << 8 );
                LoRaMacDevAddr |= ( ( uint32_t )LoRaMacRxPayload[9] << 16 );
                LoRaMacDevAddr |= ( ( uint32_t )LoRaMacRxPayload[10] << 24 );

                // DLSettings
                LoRaMacParams.Rx1DrOffset = ( LoRaMacRxPayload[11] >> 4 ) & 0x07;
                LoRaMacParams.Rx2Channel.Datarate = LoRaMacRxPayload[11] & 0x0F;

                // RxDelay
                LoRaMacParams.ReceiveDelay1 = ( LoRaMacRxPayload[12] & 0x0F );
                if( LoRaMacParams.ReceiveDelay1 == 0 )
                {
                    LoRaMacParams.ReceiveDelay1 = 1;
                }
                LoRaMacParams.ReceiveDelay1 *= 1000;
                LoRaMacParams.ReceiveDelay2 = LoRaMacParams.ReceiveDelay1 + 1000;

                // Apply CF list
                applyCFList.Payload = &LoRaMacRxPayload[13];
                // Size of the regular payload is 12. Plus 1 byte MHDR and 4 bytes MIC
                applyCFList.Size = size - 17;

                RegionApplyCFList( LoRaMacRegion, &applyCFList );

                MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK;
                IsLoRaMacNetworkJoined = true;
                LoRaMacParams.ChannelsDatarate = LoRaMacParamsDefaults.ChannelsDatarate;
            }
            else
            {
                MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL;
            }
            break;
        case FRAME_TYPE_DATA_CONFIRMED_DOWN:
        case FRAME_TYPE_DATA_UNCONFIRMED_DOWN:
            {
                // Check if the received payload size is valid
                getPhy.UplinkDwellTime = LoRaMacParams.DownlinkDwellTime;
                getPhy.Datarate = McpsIndication.RxDatarate;
                getPhy.Attribute = PHY_MAX_PAYLOAD;

                // Get the maximum payload length
                if( RepeaterSupport == true )
                {
                    getPhy.Attribute = PHY_MAX_PAYLOAD_REPEATER;
                }
                phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
                if( MAX( 0, ( int16_t )( ( int16_t )size - ( int16_t )LORA_MAC_FRMPAYLOAD_OVERHEAD ) ) > phyParam.Value )
                {
                    McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
                    PrepareRxDoneAbort( );
                    return;
                }

                address = payload[pktHeaderLen++];
                address |= ( (uint32_t)payload[pktHeaderLen++] << 8 );
                address |= ( (uint32_t)payload[pktHeaderLen++] << 16 );
                address |= ( (uint32_t)payload[pktHeaderLen++] << 24 );

                if( address != LoRaMacDevAddr )
                {
                    curMulticastParams = MulticastChannels;
                    while( curMulticastParams != NULL )
                    {
                        if( address == curMulticastParams->Address )
                        {
                            multicast = 1;
#ifndef TO_SE
                            nwkSKey = curMulticastParams->NwkSKey;
                            appSKey = curMulticastParams->AppSKey;
#endif
                            downLinkCounter = curMulticastParams->DownLinkCounter;
                            break;
                        }
                        curMulticastParams = curMulticastParams->Next;
                    }
                    if( multicast == 0 )
                    {
                        // We are not the destination of this frame.
                        McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_ADDRESS_FAIL;
                        PrepareRxDoneAbort( );
                        return;
                    }
                }
                else
                {
                    multicast = 0;
#ifndef TO_SE
                    nwkSKey = LoRaMacNwkSKey;
                    appSKey = LoRaMacAppSKey;
#endif
                    downLinkCounter = DownLinkCounter;
                }

                fCtrl.Value = payload[pktHeaderLen++];

                sequenceCounter = ( uint16_t )payload[pktHeaderLen++];
                sequenceCounter |= ( uint16_t )payload[pktHeaderLen++] << 8;

                appPayloadStartIndex = 8 + fCtrl.Bits.FOptsLen;

#ifndef TO_SE
                micRx |= ( uint32_t )payload[size - LORAMAC_MFR_LEN];
                micRx |= ( ( uint32_t )payload[size - LORAMAC_MFR_LEN + 1] << 8 );
                micRx |= ( ( uint32_t )payload[size - LORAMAC_MFR_LEN + 2] << 16 );
                micRx |= ( ( uint32_t )payload[size - LORAMAC_MFR_LEN + 3] << 24 );
#endif

                sequenceCounterPrev = ( uint16_t )downLinkCounter;
                sequenceCounterDiff = ( sequenceCounter - sequenceCounterPrev );

                if( sequenceCounterDiff < ( 1 << 15 ) )
                {
                    downLinkCounter += sequenceCounterDiff;
#ifndef TO_SE
                    LoRaMacComputeMic( payload, size - LORAMAC_MFR_LEN, nwkSKey, address, DOWN_LINK, downLinkCounter, &mic );
                    if( micRx == mic )
                    {
                        isMicOk = true;
                    }
#endif
                }
                else
                {
#ifndef TO_SE
                    // check for sequence roll-over
                    uint32_t  downLinkCounterTmp = downLinkCounter + 0x10000 + ( int16_t )sequenceCounterDiff;
                    LoRaMacComputeMic( payload, size - LORAMAC_MFR_LEN, nwkSKey, address, DOWN_LINK, downLinkCounterTmp, &mic );
                    if( micRx == mic )
                    {
                        isMicOk = true;
                        downLinkCounter = downLinkCounterTmp;
                    }
#else
                    // assume sequence roll-over
                    downLinkCounter += 0x10000 + ( int16_t )sequenceCounterDiff;
                }
                if ( LoRaMacUnsecurePHYPayload( payload, size, payload ) == LORAMAC_CRYPTO_STATUS_OK )
                {
                    isMicOk = true;
#endif
                }

                // Check for a the maximum allowed counter difference
                getPhy.Attribute = PHY_MAX_FCNT_GAP;
                phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
                if( sequenceCounterDiff >= phyParam.Value )
                {
                    McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_TOO_MANY_FRAMES_LOSS;
                    McpsIndication.DownLinkCounter = downLinkCounter;
                    PrepareRxDoneAbort( );
                    return;
                }

                if( isMicOk == true )
                {
                    McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_OK;
                    McpsIndication.Multicast = multicast;
                    McpsIndication.FramePending = fCtrl.Bits.FPending;
                    McpsIndication.Buffer = NULL;
                    McpsIndication.BufferSize = 0;
                    McpsIndication.DownLinkCounter = downLinkCounter;

                    McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK;

                    AdrAckCounter = 0;
                    MacCommandsBufferToRepeatIndex = 0;

                    // Update 32 bits downlink counter
                    if( multicast == 1 )
                    {
                        McpsIndication.McpsIndication = MCPS_MULTICAST;

                        if( ( curMulticastParams->DownLinkCounter == downLinkCounter ) &&
                            ( curMulticastParams->DownLinkCounter != 0 ) )
                        {
                            McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_REPEATED;
                            McpsIndication.DownLinkCounter = downLinkCounter;
                            PrepareRxDoneAbort( );
                            return;
                        }
                        curMulticastParams->DownLinkCounter = downLinkCounter;
                    }
                    else
                    {
                        if( macHdr.Bits.MType == FRAME_TYPE_DATA_CONFIRMED_DOWN )
                        {
                            SrvAckRequested = true;
                            McpsIndication.McpsIndication = MCPS_CONFIRMED;

                            if( ( DownLinkCounter == downLinkCounter ) &&
                                ( DownLinkCounter != 0 ) )
                            {
                                // Duplicated confirmed downlink. Skip indication.
                                // In this case, the MAC layer shall accept the MAC commands
                                // which are included in the downlink retransmission.
                                // It should not provide the same frame to the application
                                // layer again.
                                skipIndication = true;
                            }
                        }
                        else
                        {
                            SrvAckRequested = false;
                            McpsIndication.McpsIndication = MCPS_UNCONFIRMED;

                            if( ( DownLinkCounter == downLinkCounter ) &&
...

This file has been truncated, please download it to see its full contents.

LoRaMacCrypto.c

C/C++
Based on STM32CubeExpansion_LRWAN_V1.1.4.
File location: Middlewares/Third_Party/Lora/Mac/LoRaMacCrypto.c
#ifndef TO_SE

/*
 / _____)             _              | |
( (____  _____ ____ _| |_ _____  ____| |__
 \____ \| ___ |    (_   _) ___ |/ ___)  _ \
 _____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
    (C)2013 Semtech
 ___ _____ _   ___ _  _____ ___  ___  ___ ___
/ __|_   _/_\ / __| |/ / __/ _ \| _ \/ __| __|
\__ \ | |/ _ \ (__| ' <| _| (_) |   / (__| _|
|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
embedded.connectivity.solutions===============

Description: LoRa MAC layer implementation

License: Revised BSD License, see LICENSE.TXT file include in the project

Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
*/
#include <stdlib.h>
#include <stdint.h>
#include "utilities.h"

#include "aes.h"
#include "cmac.h"

#include "LoRaMacCrypto.h"

/*!
 * CMAC/AES Message Integrity Code (MIC) Block B0 size
 */
#define LORAMAC_MIC_BLOCK_B0_SIZE                   16

/*!
 * MIC field computation initial data
 */
static uint8_t MicBlockB0[] = { 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
                              };

/*!
 * Contains the computed MIC field.
 *
 * \remark Only the 4 first bytes are used
 */
static uint8_t Mic[16];

/*!
 * Encryption aBlock and sBlock
 */
static uint8_t aBlock[] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
                          };
static uint8_t sBlock[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
                          };

/*!
 * AES computation context variable
 */
static aes_context AesContext;

/*!
 * CMAC computation context variable
 */
static AES_CMAC_CTX AesCmacCtx[1];

/*!
 * \brief Computes the LoRaMAC frame MIC field  
 *
 * \param [IN]  buffer          Data buffer
 * \param [IN]  size            Data buffer size
 * \param [IN]  key             AES key to be used
 * \param [IN]  address         Frame address
 * \param [IN]  dir             Frame direction [0: uplink, 1: downlink]
 * \param [IN]  sequenceCounter Frame sequence counter
 * \param [OUT] mic Computed MIC field
 */
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 )
{
    MicBlockB0[5] = dir;
    
    MicBlockB0[6] = ( address ) & 0xFF;
    MicBlockB0[7] = ( address >> 8 ) & 0xFF;
    MicBlockB0[8] = ( address >> 16 ) & 0xFF;
    MicBlockB0[9] = ( address >> 24 ) & 0xFF;

    MicBlockB0[10] = ( sequenceCounter ) & 0xFF;
    MicBlockB0[11] = ( sequenceCounter >> 8 ) & 0xFF;
    MicBlockB0[12] = ( sequenceCounter >> 16 ) & 0xFF;
    MicBlockB0[13] = ( sequenceCounter >> 24 ) & 0xFF;

    MicBlockB0[15] = size & 0xFF;

    AES_CMAC_Init( AesCmacCtx );

    AES_CMAC_SetKey( AesCmacCtx, key );

    AES_CMAC_Update( AesCmacCtx, MicBlockB0, LORAMAC_MIC_BLOCK_B0_SIZE );
    
    AES_CMAC_Update( AesCmacCtx, buffer, size & 0xFF );
    
    AES_CMAC_Final( Mic, AesCmacCtx );
    
    *mic = ( uint32_t )( ( uint32_t )Mic[3] << 24 | ( uint32_t )Mic[2] << 16 | ( uint32_t )Mic[1] << 8 | ( uint32_t )Mic[0] );
}

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 )
{
    uint16_t i;
    uint8_t bufferIndex = 0;
    uint16_t ctr = 1;

    memset1( AesContext.ksch, '\0', 240 );
    aes_set_key( key, 16, &AesContext );

    aBlock[5] = dir;

    aBlock[6] = ( address ) & 0xFF;
    aBlock[7] = ( address >> 8 ) & 0xFF;
    aBlock[8] = ( address >> 16 ) & 0xFF;
    aBlock[9] = ( address >> 24 ) & 0xFF;

    aBlock[10] = ( sequenceCounter ) & 0xFF;
    aBlock[11] = ( sequenceCounter >> 8 ) & 0xFF;
    aBlock[12] = ( sequenceCounter >> 16 ) & 0xFF;
    aBlock[13] = ( sequenceCounter >> 24 ) & 0xFF;

    while( size >= 16 )
    {
        aBlock[15] = ( ( ctr ) & 0xFF );
        ctr++;
        aes_encrypt( aBlock, sBlock, &AesContext );
        for( i = 0; i < 16; i++ )
        {
            encBuffer[bufferIndex + i] = buffer[bufferIndex + i] ^ sBlock[i];
        }
        size -= 16;
        bufferIndex += 16;
    }

    if( size > 0 )
    {
        aBlock[15] = ( ( ctr ) & 0xFF );
        aes_encrypt( aBlock, sBlock, &AesContext );
        for( i = 0; i < size; i++ )
        {
            encBuffer[bufferIndex + i] = buffer[bufferIndex + i] ^ sBlock[i];
        }
    }
}

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 )
{
    LoRaMacPayloadEncrypt( buffer, size, key, address, dir, sequenceCounter, decBuffer );
}

void LoRaMacJoinComputeMic( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t *mic )
{
    AES_CMAC_Init( AesCmacCtx );

    AES_CMAC_SetKey( AesCmacCtx, key );

    AES_CMAC_Update( AesCmacCtx, buffer, size & 0xFF );

    AES_CMAC_Final( Mic, AesCmacCtx );

    *mic = ( uint32_t )( ( uint32_t )Mic[3] << 24 | ( uint32_t )Mic[2] << 16 | ( uint32_t )Mic[1] << 8 | ( uint32_t )Mic[0] );
}

void LoRaMacJoinDecrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint8_t *decBuffer )
{
    memset1( AesContext.ksch, '\0', 240 );
    aes_set_key( key, 16, &AesContext );
    aes_encrypt( buffer, decBuffer, &AesContext );
    // Check if optional CFList is included
    if( size >= 16 )
    {
        aes_encrypt( buffer + 16, decBuffer + 16, &AesContext );
    }
}

void LoRaMacJoinComputeSKeys( const uint8_t *key, const uint8_t *appNonce, uint16_t devNonce, uint8_t *nwkSKey, uint8_t *appSKey )
{
    uint8_t nonce[16];
    uint8_t *pDevNonce = ( uint8_t * )&devNonce;
    
    memset1( AesContext.ksch, '\0', 240 );
    aes_set_key( key, 16, &AesContext );

    memset1( nonce, 0, sizeof( nonce ) );
    nonce[0] = 0x01;
    memcpy1( nonce + 1, appNonce, 6 );
    memcpy1( nonce + 7, pDevNonce, 2 );
    aes_encrypt( nonce, nwkSKey, &AesContext );

    memset1( nonce, 0, sizeof( nonce ) );
    nonce[0] = 0x02;
    memcpy1( nonce + 1, appNonce, 6 );
    memcpy1( nonce + 7, pDevNonce, 2 );
    aes_encrypt( nonce, appSKey, &AesContext );
}

#endif /* TO_SE */

LoRaMacCrypto_TO.c

C/C++
New cryptography layer implementation.
File location: Middlewares/Third_Party/Lora/Mac/LoRaMacCrypto_TO.c
#include <stdio.h>
#include <stdint.h>
#include <LoRaMacCrypto_TO.h>
#include <TO.h>

LoRaMacCryptoStatus_t LoRaMacGetJoinRequest( uint8_t *buffer, uint16_t *size )
{
        int ret;

        ret = TO_lora_get_join_request_phypayload(buffer);
        if (ret != TORSP_SUCCESS) {
                fprintf(stderr, "TO get join request error, 0x%X\n", ret);
        } else {
            *size = TO_LORA_JOINREQUEST_SIZE;
        }

        return (ret == TORSP_SUCCESS ? LORAMAC_CRYPTO_STATUS_OK : LORAMAC_CRYPTO_STATUS_KO);
}

LoRaMacCryptoStatus_t LoRaMacHandleJoinAccept( const uint8_t *buffer, const uint16_t size, uint8_t *outBuffer )
{
        int ret;

        ret = TO_lora_handle_join_accept_phypayload(buffer, size, outBuffer);
        if (ret != TORSP_SUCCESS) {
                fprintf(stderr, "TO handle join accept error, 0x%X\n", ret);
        }

        return (ret == TORSP_SUCCESS ? LORAMAC_CRYPTO_STATUS_OK : LORAMAC_CRYPTO_STATUS_KO);
}

LoRaMacCryptoStatus_t LoRaMacSecurePHYPayload( const uint8_t mhdr, const uint8_t fctrl, const uint8_t *fopts, const uint8_t fport, const uint8_t *payload, const size_t payloadSize, uint8_t *outBuffer )
{
        int ret;

        ret = TO_lora_secure_phypayload(mhdr, fctrl, fopts, fport, payload, payloadSize, outBuffer);
        if (ret != TORSP_SUCCESS) {
                fprintf(stderr, "TO secure error, 0x%X\n", ret);
        }

        return (ret == TORSP_SUCCESS ? LORAMAC_CRYPTO_STATUS_OK : LORAMAC_CRYPTO_STATUS_KO);
}

LoRaMacCryptoStatus_t LoRaMacUnsecurePHYPayload( const uint8_t *buffer, const uint16_t size, uint8_t *outBuffer )
{
        int ret;

        ret = TO_lora_unsecure_phypayload(buffer, size, outBuffer);
        if (ret != TORSP_SUCCESS) {
                fprintf(stderr, "TO unsecure error, 0x%X\n", ret);
        }

        return (ret == TORSP_SUCCESS ? LORAMAC_CRYPTO_STATUS_OK : LORAMAC_CRYPTO_STATUS_KO);
}

LoRaMacCrypto_TO.h

C Header File
New cryptography layer header.
File location: Middlewares/Third_Party/Lora/Mac/LoRaMacCrypto_TO.h
/*!
 * \file      LoRaMacCrypto_TO.h
 *
 * \brief     LoRa MAC layer cryptography implementation
 *
 * \copyright Revised BSD License, see section \ref LICENSE.
 *
 * \code
 *                ______                              _
 *               / _____)             _              | |
 *              ( (____  _____ ____ _| |_ _____  ____| |__
 *               \____ \| ___ |    (_   _) ___ |/ ___)  _ \
 *               _____) ) ____| | | || |_| ____( (___| | | |
 *              (______/|_____)_|_|_| \__)_____)\____)_| |_|
 *              (C)2013 Semtech
 *
 *               ___ _____ _   ___ _  _____ ___  ___  ___ ___
 *              / __|_   _/_\ / __| |/ / __/ _ \| _ \/ __| __|
 *              \__ \ | |/ _ \ (__| ' <| _| (_) |   / (__| _|
 *              |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
 *              embedded.connectivity.solutions===============
 *
 * \endcode
 *
 * \author    Miguel Luis ( Semtech )
 *
 * \author    Gregory Cristian ( Semtech )
 *
 * \author    Daniel Jckle ( STACKFORCE )
 *
 * \defgroup    LORAMAC_CRYPTO  LoRa MAC layer cryptography implementation
 *              This module covers the implementation of cryptographic functions
 *              of the LoRaMAC layer.
 * \{
 */
#ifndef __LORAMAC_CRYPTO_H__
#define __LORAMAC_CRYPTO_H__

/*!
 * LoRaMAC Crypto Status
 */
typedef enum eLoRaMacCryptoStatus
{
    /**
     * Success
     */
    LORAMAC_CRYPTO_STATUS_OK,
    /**
     * Failure
     */
    LORAMAC_CRYPTO_STATUS_KO
} LoRaMacCryptoStatus_t;

/*!
 * Get join request encrypted payload.
 *
 * \param [OUT]  buffer          - Encrypted payload
 * \param [OUT]  size            - Encrypted payload size
 */
LoRaMacCryptoStatus_t LoRaMacGetJoinRequest( uint8_t *buffer, uint16_t *size );

/*!
 * Handle join accept payload.
 *
 * \param [IN]  buffer          - Encrypted join accept payload
 * \param [IN]  size            - Encrypted join accept payload size
 */
LoRaMacCryptoStatus_t LoRaMacHandleJoinAccept( const uint8_t *buffer, const uint16_t size, uint8_t *outBuffer );

/*!
 * Encrypt PHYPayload.
 *
 * \param [IN]  mhdr            - MHDR
 * \param [IN]  fctrl           - FCtrl
 * \param [IN]  fopts           - FOpts (optional, depends on FCtrl)
 * \param [IN]  fport           - FOpts (optional, depends on payload)
 * \param [IN]  payload         - MACPayload (optional)
 * \param [IN]  payloadSize     - MACPayload size (must be 0 if no payload)
 */
LoRaMacCryptoStatus_t LoRaMacSecurePHYPayload( const uint8_t mhdr, const uint8_t fctrl, const uint8_t *fopts, const uint8_t fport, const uint8_t *payload, const size_t payloadSize, uint8_t *outBuffer );

/*!
 * Decrypt PHYPayload.
 *
 * \param [IN]  buffer          - Payload to decrypt
 * \param [IN]  size            - Size of payload
 */
LoRaMacCryptoStatus_t LoRaMacUnsecurePHYPayload( const uint8_t *buffer, const uint16_t size, uint8_t *outBuffer );

/*! \} defgroup LORAMAC */

#endif // __LORAMAC_CRYPTO_H__

Credits

Ugo RENNER

Ugo RENNER

2 projects • 0 followers
Security Software R&D Engineer
Jérôme Beclin

Jérôme Beclin

2 projects • 0 followers
Sales engineer, Trusted Objects
Hervé Roche

Hervé Roche

2 projects • 0 followers
Marketing & Business Development
Laurent Masson

Laurent Masson

2 projects • 0 followers

Comments

Add projectSign up / Login