Update LoRaMac-node to Version 4.4.4,fix Security breach found by Tencent Blade Team please refer to security advisory - CVE-2020-11068

fix Security breach found by Tencent Blade Team please refer to security advisory - CVE-2020-11068
This commit is contained in:
supowang
2020-05-29 11:59:05 +08:00
parent 5d9895cecc
commit f9bd2588a2
137 changed files with 10401 additions and 4328 deletions

View File

@@ -31,6 +31,10 @@
#ifndef AES_H
#define AES_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#if 1
@@ -159,4 +163,8 @@ void aes_decrypt_256( const uint8_t in[N_BLOCK],
uint8_t o_key[2 * N_BLOCK] );
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -4,150 +4,151 @@ Copyright (C) 2009 Lander Casado, Philippas Tsigas
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files
a copy of this software and associated documentation files
(the "Software"), to deal with the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
the following conditions:
Redistributions of source code must retain the above copyright notice,
Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimers. Redistributions in
binary form must reproduce the above copyright notice, this list of
conditions and the following disclaimers in the documentation and/or
conditions and the following disclaimers in the documentation and/or
other materials provided with the distribution.
In no event shall the authors or copyright holders be liable for any special,
incidental, indirect or consequential damages of any kind, or any damages
whatsoever resulting from loss of use, data or profits, whether or not
advised of the possibility of damage, and on any theory of liability,
incidental, indirect or consequential damages of any kind, or any damages
whatsoever resulting from loss of use, data or profits, whether or not
advised of the possibility of damage, and on any theory of liability,
arising out of or in connection with the use or performance of this software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS WITH THE SOFTWARE
*****************************************************************************/
//#include <sys/param.h>
//#include <sys/systm.h>
#include <stdint.h>
#include "aes.h"
#include "cmac.h"
#include "utilities.h"
#define LSHIFT(v, r) do { \
int32_t i; \
for (i = 0; i < 15; i++) \
(r)[i] = (v)[i] << 1 | (v)[i + 1] >> 7; \
(r)[15] = (v)[15] << 1; \
} while (0)
#define XOR(v, r) do { \
int32_t i; \
for (i = 0; i < 16; i++) \
{ \
(r)[i] = (r)[i] ^ (v)[i]; \
} \
} while (0) \
#define LSHIFT( v, r ) \
do \
{ \
int32_t i; \
for( i = 0; i < 15; i++ ) \
( r )[i] = ( v )[i] << 1 | ( v )[i + 1] >> 7; \
( r )[15] = ( v )[15] << 1; \
} while( 0 )
#define XOR( v, r ) \
do \
{ \
int32_t i; \
for( i = 0; i < 16; i++ ) \
{ \
( r )[i] = ( r )[i] ^ ( v )[i]; \
} \
} while( 0 )
void AES_CMAC_Init(AES_CMAC_CTX *ctx)
void AES_CMAC_Init( AES_CMAC_CTX* ctx )
{
memset1(ctx->X, 0, sizeof ctx->X);
ctx->M_n = 0;
memset1(ctx->rijndael.ksch, '\0', 240);
}
void AES_CMAC_SetKey(AES_CMAC_CTX *ctx, const uint8_t key[AES_CMAC_KEY_LENGTH])
{
//rijndael_set_key_enc_only(&ctx->rijndael, key, 128);
aes_set_key( key, AES_CMAC_KEY_LENGTH, &ctx->rijndael);
}
void AES_CMAC_Update(AES_CMAC_CTX *ctx, const uint8_t *data, uint32_t len)
{
uint32_t mlen;
uint8_t in[16];
if (ctx->M_n > 0) {
mlen = MIN(16 - ctx->M_n, len);
memcpy1(ctx->M_last + ctx->M_n, data, mlen);
ctx->M_n += mlen;
if (ctx->M_n < 16 || len == mlen)
return;
XOR(ctx->M_last, ctx->X);
//rijndael_encrypt(&ctx->rijndael, ctx->X, ctx->X);
aes_encrypt( ctx->X, ctx->X, &ctx->rijndael);
data += mlen;
len -= mlen;
}
while (len > 16) { /* not last block */
XOR(data, ctx->X);
//rijndael_encrypt(&ctx->rijndael, ctx->X, ctx->X);
memcpy1(in, &ctx->X[0], 16); //Bestela ez du ondo iten
aes_encrypt( in, in, &ctx->rijndael);
memcpy1(&ctx->X[0], in, 16);
data += 16;
len -= 16;
}
/* potential last block, save it */
memcpy1(ctx->M_last, data, len);
ctx->M_n = len;
}
void AES_CMAC_Final(uint8_t digest[AES_CMAC_DIGEST_LENGTH], AES_CMAC_CTX *ctx)
{
uint8_t K[16];
uint8_t in[16];
/* generate subkey K1 */
memset1(K, '\0', 16);
//rijndael_encrypt(&ctx->rijndael, K, K);
aes_encrypt( K, K, &ctx->rijndael);
if (K[0] & 0x80) {
LSHIFT(K, K);
K[15] ^= 0x87;
} else
LSHIFT(K, K);
if (ctx->M_n == 16) {
/* last block was a complete block */
XOR(K, ctx->M_last);
} else {
/* generate subkey K2 */
if (K[0] & 0x80) {
LSHIFT(K, K);
K[15] ^= 0x87;
} else
LSHIFT(K, K);
/* padding(M_last) */
ctx->M_last[ctx->M_n] = 0x80;
while (++ctx->M_n < 16)
ctx->M_last[ctx->M_n] = 0;
XOR(K, ctx->M_last);
}
XOR(ctx->M_last, ctx->X);
//rijndael_encrypt(&ctx->rijndael, ctx->X, digest);
memcpy1(in, &ctx->X[0], 16); //Bestela ez du ondo iten
aes_encrypt(in, digest, &ctx->rijndael);
memset1(K, 0, sizeof K);
memset1( ctx->X, 0, sizeof ctx->X );
ctx->M_n = 0;
memset1( ctx->rijndael.ksch, '\0', 240 );
}
void AES_CMAC_SetKey( AES_CMAC_CTX* ctx, const uint8_t key[AES_CMAC_KEY_LENGTH] )
{
aes_set_key( key, AES_CMAC_KEY_LENGTH, &ctx->rijndael );
}
void AES_CMAC_Update( AES_CMAC_CTX* ctx, const uint8_t* data, uint32_t len )
{
uint32_t mlen;
uint8_t in[16];
if( ctx->M_n > 0 )
{
mlen = MIN( 16 - ctx->M_n, len );
memcpy1( ctx->M_last + ctx->M_n, data, mlen );
ctx->M_n += mlen;
if( ctx->M_n < 16 || len == mlen )
return;
XOR( ctx->M_last, ctx->X );
memcpy1( in, &ctx->X[0], 16 ); // Otherwise it does not look good
aes_encrypt( in, in, &ctx->rijndael );
memcpy1( &ctx->X[0], in, 16 );
data += mlen;
len -= mlen;
}
while( len > 16 )
{ /* not last block */
XOR( data, ctx->X );
memcpy1( in, &ctx->X[0], 16 ); // Otherwise it does not look good
aes_encrypt( in, in, &ctx->rijndael );
memcpy1( &ctx->X[0], in, 16 );
data += 16;
len -= 16;
}
/* potential last block, save it */
memcpy1( ctx->M_last, data, len );
ctx->M_n = len;
}
void AES_CMAC_Final( uint8_t digest[AES_CMAC_DIGEST_LENGTH], AES_CMAC_CTX* ctx )
{
uint8_t K[16];
uint8_t in[16];
/* generate subkey K1 */
memset1( K, '\0', 16 );
aes_encrypt( K, K, &ctx->rijndael );
if( K[0] & 0x80 )
{
LSHIFT( K, K );
K[15] ^= 0x87;
}
else
LSHIFT( K, K );
if( ctx->M_n == 16 )
{
/* last block was a complete block */
XOR( K, ctx->M_last );
}
else
{
/* generate subkey K2 */
if( K[0] & 0x80 )
{
LSHIFT( K, K );
K[15] ^= 0x87;
}
else
LSHIFT( K, K );
/* padding(M_last) */
ctx->M_last[ctx->M_n] = 0x80;
while( ++ctx->M_n < 16 )
ctx->M_last[ctx->M_n] = 0;
XOR( K, ctx->M_last );
}
XOR( ctx->M_last, ctx->X );
memcpy1( in, &ctx->X[0], 16 ); // Otherwise it does not look good
aes_encrypt( in, digest, &ctx->rijndael );
memset1( K, 0, sizeof K );
}

View File

@@ -36,6 +36,10 @@ DEALINGS WITH THE SOFTWARE
#ifndef _CMAC_H_
#define _CMAC_H_
#ifdef __cplusplus
extern "C"
#endif
#include "aes.h"
#define AES_CMAC_KEY_LENGTH 16
@@ -59,5 +63,9 @@ void AES_CMAC_Final(uint8_t digest[AES_CMAC_DIGEST_LENGTH], AES_CMAC_CTX *
// __attribute__((__bounded__(__minbytes__,1,AES_CMAC_DIGEST_LENGTH)));
//__END_DECLS
#ifdef __cplusplus
}
#endif
#endif /* _CMAC_H_ */

View File

@@ -0,0 +1,297 @@
/*!
* \file se-identity.h
*
* \brief Secure Element identity and keys
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2020 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
*/
#ifndef __SOFT_SE_IDENTITY_H__
#define __SOFT_SE_IDENTITY_H__
#ifdef __cplusplus
extern "C" {
#endif
/*!
******************************************************************************
********************************** WARNING ***********************************
******************************************************************************
The secure-element implementation supports both 1.0.x and 1.1.x LoRaWAN
versions of the specification.
Thus it has been decided to use the 1.1.x keys and EUI name definitions.
The below table shows the names equivalence between versions:
+---------------------+-------------------------+
| 1.0.x | 1.1.x |
+=====================+=========================+
| LORAWAN_DEVICE_EUI | LORAWAN_DEVICE_EUI |
+---------------------+-------------------------+
| LORAWAN_APP_EUI | LORAWAN_JOIN_EUI |
+---------------------+-------------------------+
| LORAWAN_GEN_APP_KEY | LORAWAN_APP_KEY |
+---------------------+-------------------------+
| LORAWAN_APP_KEY | LORAWAN_NWK_KEY |
+---------------------+-------------------------+
| LORAWAN_NWK_S_KEY | LORAWAN_F_NWK_S_INT_KEY |
+---------------------+-------------------------+
| LORAWAN_NWK_S_KEY | LORAWAN_S_NWK_S_INT_KEY |
+---------------------+-------------------------+
| LORAWAN_NWK_S_KEY | LORAWAN_NWK_S_ENC_KEY |
+---------------------+-------------------------+
| LORAWAN_APP_S_KEY | LORAWAN_APP_S_KEY |
+---------------------+-------------------------+
******************************************************************************
******************************************************************************
******************************************************************************
*/
/*!
* When set to 1 DevEui is LORAWAN_DEVICE_EUI
* When set to 0 DevEui is automatically set with a value provided by MCU platform
*/
#define STATIC_DEVICE_EUI 0
/*!
* end-device IEEE EUI (big endian)
*/
#define LORAWAN_DEVICE_EUI { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
/*!
* App/Join server IEEE EUI (big endian)
*/
#define LORAWAN_JOIN_EUI { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
/*!
* Secure-element pin
*/
#define SECURE_ELEMENT_PIN { 0x00, 0x00, 0x00, 0x00 }
/*!
* When set to 1 DevAddr is LORAWAN_DEVICE_ADDRESS
* When set to 0 DevAddr is automatically set with a value provided by a pseudo
* random generator seeded with a value provided by the MCU platform
*/
#define STATIC_DEVICE_ADDRESS 0
/*!
* Device address on the network (big endian)
*/
#define LORAWAN_DEVICE_ADDRESS ( uint32_t )0x00000000
#define SOFT_SE_KEY_LIST \
{ \
{ \
/*! \
* Application root key \
* WARNING: FOR 1.0.x DEVICES IT IS THE \ref LORAWAN_GEN_APP_KEY \
*/ \
.KeyID = APP_KEY, \
.KeyValue = { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, \
0x3C }, \
}, \
{ \
/*! \
* Network root key \
* WARNING: FOR 1.0.x DEVICES IT IS THE \ref LORAWAN_APP_KEY \
*/ \
.KeyID = NWK_KEY, \
.KeyValue = { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, \
0x3C }, \
}, \
{ \
/*! \
* Join session integrity key (Dynamically updated) \
* WARNING: NOT USED FOR 1.0.x DEVICES \
*/ \
.KeyID = J_S_INT_KEY, \
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00 }, \
}, \
{ \
/*! \
* Join session encryption key (Dynamically updated) \
* WARNING: NOT USED FOR 1.0.x DEVICES \
*/ \
.KeyID = J_S_ENC_KEY, \
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00 }, \
}, \
{ \
/*! \
* Forwarding Network session integrity key \
* WARNING: NWK_S_KEY FOR 1.0.x DEVICES \
*/ \
.KeyID = F_NWK_S_INT_KEY, \
.KeyValue = { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, \
0x3C }, \
}, \
{ \
/*! \
* Serving Network session integrity key \
* WARNING: NOT USED FOR 1.0.x DEVICES. MUST BE THE SAME AS \ref LORAWAN_F_NWK_S_INT_KEY \
*/ \
.KeyID = S_NWK_S_INT_KEY, \
.KeyValue = { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, \
0x3C }, \
}, \
{ \
/*! \
* Network session encryption key \
* WARNING: NOT USED FOR 1.0.x DEVICES. MUST BE THE SAME AS \ref LORAWAN_F_NWK_S_INT_KEY \
*/ \
.KeyID = NWK_S_ENC_KEY, \
.KeyValue = { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, \
0x3C }, \
}, \
{ \
/*! \
* Application session key \
*/ \
.KeyID = APP_S_KEY, \
.KeyValue = { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, \
0x3C }, \
}, \
{ \
/*! \
* Multicast root key (Dynamically updated) \
*/ \
.KeyID = MC_ROOT_KEY, \
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00 }, \
}, \
{ \
/*! \
* Multicast key encryption key (Dynamically updated) \
*/ \
.KeyID = MC_KE_KEY, \
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00 }, \
}, \
{ \
/*! \
* Multicast group #0 root key (Dynamically updated) \
*/ \
.KeyID = MC_KEY_0, \
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00 }, \
}, \
{ \
/*! \
* Multicast group #0 application session key (Dynamically updated) \
*/ \
.KeyID = MC_APP_S_KEY_0, \
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00 }, \
}, \
{ \
/*! \
* Multicast group #0 network session key (Dynamically updated) \
*/ \
.KeyID = MC_NWK_S_KEY_0, \
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00 }, \
}, \
{ \
/*! \
* Multicast group #1 root key (Dynamically updated) \
*/ \
.KeyID = MC_KEY_1, \
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00 }, \
}, \
{ \
/*! \
* Multicast group #1 application session key (Dynamically updated) \
*/ \
.KeyID = MC_APP_S_KEY_1, \
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00 }, \
}, \
{ \
/*! \
* Multicast group #1 network session key (Dynamically updated) \
*/ \
.KeyID = MC_NWK_S_KEY_1, \
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00 }, \
}, \
{ \
/*! \
* Multicast group #2 root key (Dynamically updated) \
*/ \
.KeyID = MC_KEY_2, \
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00 }, \
}, \
{ \
/*! \
* Multicast group #2 application session key (Dynamically updated) \
*/ \
.KeyID = MC_APP_S_KEY_2, \
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00 }, \
}, \
{ \
/*! \
* Multicast group #2 network session key (Dynamically updated) \
*/ \
.KeyID = MC_NWK_S_KEY_2, \
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00 }, \
}, \
{ \
/*! \
* Multicast group #3 root key (Dynamically updated) \
*/ \
.KeyID = MC_KEY_3, \
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00 }, \
}, \
{ \
/*! \
* Multicast group #3 application session key (Dynamically updated) \
*/ \
.KeyID = MC_APP_S_KEY_3, \
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00 }, \
}, \
{ \
/*! \
* Multicast group #3 network session key (Dynamically updated) \
*/ \
.KeyID = MC_NWK_S_KEY_3, \
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00 }, \
}, \
{ \
/*! \
* All zeros key. (ClassB usage)(constant) \
*/ \
.KeyID = SLOT_RAND_ZERO_KEY, \
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00 }, \
}, \
},
#ifdef __cplusplus
}
#endif
#endif // __SOFT_SE_IDENTITY_H__

View File

@@ -0,0 +1,39 @@
/*!
* \file soft-se-hal.h
*
* \brief Secure Element hardware abstraction layer implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2020 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
*/
#include "board.h"
#include "radio.h"
#include "soft-se-hal.h"
void SoftSeHalGetUniqueId( uint8_t *id )
{
BoardGetUniqueId( id );
}
uint32_t SoftSeHalGetRandomNumber( void )
{
return Radio.Random( );
}

View File

@@ -0,0 +1,56 @@
/*!
* \file soft-se-hal.h
*
* \brief Secure Element hardware abstraction layer
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2020 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
*/
#ifndef __SOFT_SE_HAL_H__
#define __SOFT_SE_HAL_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stdbool.h>
/*!
* \brief Get a 64 bits unique ID
*
* \param [IN] id Pointer to an array that will contain the Unique ID
*/
void SoftSeHalGetUniqueId( uint8_t *id );
/*!
* \brief Get a random number
*
* \remark The number SHALL NOT be generated using a pseudo random number
* generator
* \retval number 32 bit random value
*/
uint32_t SoftSeHalGetRandomNumber( void );
#ifdef __cplusplus
}
#endif
#endif // __SOFT_SE_HAL_H__

View File

@@ -1,36 +1,45 @@
/*
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
___ _____ _ ___ _ _____ ___ ___ ___ ___
/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
embedded.connectivity.solutions===============
Description: Secure Element software implementation
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ),
Daniel Jaeckle ( STACKFORCE ), Johannes Bruder ( STACKFORCE )
*/
#include "secure-element.h"
/*!
* \file soft-se.c
*
* \brief Secure Element software implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2020 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
*/
#include <stdlib.h>
#include <stdint.h>
#include "LoRaMacCrypto.h"
#include "utilities.h"
#include "aes.h"
#include "cmac.h"
#include "radio.h"
#define NUM_OF_KEYS 22
#define KEY_SIZE 16
#include "LoRaMacHeaderTypes.h"
#include "secure-element.h"
#include "se-identity.h"
#include "soft-se-hal.h"
/*!
* Number of supported crypto keys
*/
#define NUM_OF_KEYS 23
/*!
* Identifier value pair type for Keys
@@ -44,7 +53,7 @@ typedef struct sKey
/*
* Key value
*/
uint8_t KeyValue[KEY_SIZE];
uint8_t KeyValue[SE_KEY_SIZE];
} Key_t;
/*
@@ -53,25 +62,49 @@ typedef struct sKey
typedef struct sSecureElementNvCtx
{
/*
* AES computation context variable
* DevEUI storage
*/
aes_context AesContext;
uint8_t DevEui[SE_EUI_SIZE];
/*
* CMAC computation context variable
* Join EUI storage
*/
AES_CMAC_CTX AesCmacCtx[1];
uint8_t JoinEui[SE_EUI_SIZE];
/*
* Pin storage
*/
uint8_t Pin[SE_PIN_SIZE];
/*
* Key List
*/
Key_t KeyList[NUM_OF_KEYS];
}SecureElementNvCtx_t;
} SecureElementNvCtx_t;
/*
* Module context
/*!
* Secure element context
*/
static SecureElementNvCtx_t SeNvmCtx;
static SecureElementNvCtx_t SeNvmCtx = {
/*!
* end-device IEEE EUI (big endian)
*
* \remark In this application the value is automatically generated by calling
* BoardGetUniqueId function
*/
.DevEui = LORAWAN_DEVICE_EUI,
/*!
* App/Join server IEEE EUI (big endian)
*/
.JoinEui = LORAWAN_JOIN_EUI,
/*!
* Secure-element pin (big endian)
*/
.Pin = SECURE_ELEMENT_PIN,
/*!
* LoRaWAN key list
*/
.KeyList = SOFT_SE_KEY_LIST
};
static EventNvmCtxChanged SeNvmCtxChanged;
static SecureElementNvmEvent SeNvmCtxChanged;
/*
* Local functions
@@ -80,13 +113,11 @@ static EventNvmCtxChanged SeNvmCtxChanged;
/*
* Gets key item from key list.
*
* cmac = aes128_cmac(keyID, B0 | msg)
*
* \param[IN] keyID - Key identifier
* \param[OUT] keyItem - Key item reference
* \retval - Status of the operation
*/
SecureElementStatus_t GetKeyByID( KeyIdentifier_t keyID, Key_t** keyItem )
static SecureElementStatus_t GetKeyByID( KeyIdentifier_t keyID, Key_t** keyItem )
{
for( uint8_t i = 0; i < NUM_OF_KEYS; i++ )
{
@@ -99,44 +130,6 @@ SecureElementStatus_t GetKeyByID( KeyIdentifier_t keyID, Key_t** keyItem )
return SECURE_ELEMENT_ERROR_INVALID_KEY_ID;
}
/*
* Computes a CMAC
*
* \param[IN] buffer - Data buffer
* \param[IN] size - Data buffer size
* \param[IN] keyID - Key identifier to determine the AES key to be used
* \param[OUT] cmac - Computed cmac
* \retval - Status of the operation
*/
SecureElementStatus_t ComputeCmac( uint8_t* buffer, uint16_t size, KeyIdentifier_t keyID, uint32_t* cmac )
{
if( buffer == NULL || cmac == NULL )
{
return SECURE_ELEMENT_ERROR_NPE;
}
uint8_t Cmac[16];
AES_CMAC_Init( SeNvmCtx.AesCmacCtx );
Key_t* keyItem;
SecureElementStatus_t retval = GetKeyByID( keyID, &keyItem );
if( retval == SECURE_ELEMENT_SUCCESS )
{
AES_CMAC_SetKey( SeNvmCtx.AesCmacCtx, keyItem->KeyValue );
AES_CMAC_Update( SeNvmCtx.AesCmacCtx, buffer, size );
AES_CMAC_Final( Cmac, SeNvmCtx.AesCmacCtx );
// Bring into the required format
*cmac = ( uint32_t )( ( uint32_t ) Cmac[3] << 24 | ( uint32_t ) Cmac[2] << 16 | ( uint32_t ) Cmac[1] << 8 | ( uint32_t ) Cmac[0] );
}
return retval;
}
/*
* Dummy callback in case if the user provides NULL function pointer
*/
@@ -145,37 +138,61 @@ static void DummyCB( void )
return;
}
/*
* Computes a CMAC of a message using provided initial Bx block
*
* cmac = aes128_cmac(keyID, blocks[i].Buffer)
*
* \param[IN] micBxBuffer - Buffer containing the initial Bx block
* \param[IN] buffer - Data buffer
* \param[IN] size - Data buffer size
* \param[IN] keyID - Key identifier to determine the AES key to be used
* \param[OUT] cmac - Computed cmac
* \retval - Status of the operation
*/
static SecureElementStatus_t ComputeCmac( uint8_t* micBxBuffer, uint8_t* buffer, uint16_t size, KeyIdentifier_t keyID,
uint32_t* cmac )
{
if( ( buffer == NULL ) || ( cmac == NULL ) )
{
return SECURE_ELEMENT_ERROR_NPE;
}
uint8_t Cmac[16];
AES_CMAC_CTX aesCmacCtx[1];
AES_CMAC_Init( aesCmacCtx );
Key_t* keyItem;
SecureElementStatus_t retval = GetKeyByID( keyID, &keyItem );
if( retval == SECURE_ELEMENT_SUCCESS )
{
AES_CMAC_SetKey( aesCmacCtx, keyItem->KeyValue );
if( micBxBuffer != NULL )
{
AES_CMAC_Update( aesCmacCtx, micBxBuffer, 16 );
}
AES_CMAC_Update( aesCmacCtx, buffer, size );
AES_CMAC_Final( Cmac, aesCmacCtx );
// Bring into the required format
*cmac = ( uint32_t )( ( uint32_t ) Cmac[3] << 24 | ( uint32_t ) Cmac[2] << 16 | ( uint32_t ) Cmac[1] << 8 |
( uint32_t ) Cmac[0] );
}
return retval;
}
/*
* API functions
*/
SecureElementStatus_t SecureElementInit( EventNvmCtxChanged seNvmCtxChanged )
SecureElementStatus_t SecureElementInit( SecureElementNvmEvent seNvmCtxChanged )
{
// Initialize with defaults
uint8_t itr = 0;
SeNvmCtx.KeyList[itr++].KeyID = APP_KEY;
SeNvmCtx.KeyList[itr++].KeyID = NWK_KEY;
SeNvmCtx.KeyList[itr++].KeyID = J_S_INT_KEY;
SeNvmCtx.KeyList[itr++].KeyID = J_S_ENC_KEY;
SeNvmCtx.KeyList[itr++].KeyID = F_NWK_S_INT_KEY;
SeNvmCtx.KeyList[itr++].KeyID = S_NWK_S_INT_KEY;
SeNvmCtx.KeyList[itr++].KeyID = NWK_S_ENC_KEY;
SeNvmCtx.KeyList[itr++].KeyID = APP_S_KEY;
SeNvmCtx.KeyList[itr++].KeyID = MC_KE_KEY;
SeNvmCtx.KeyList[itr++].KeyID = MC_KEY_0;
SeNvmCtx.KeyList[itr++].KeyID = MC_APP_S_KEY_0;
SeNvmCtx.KeyList[itr++].KeyID = MC_NWK_S_KEY_0;
SeNvmCtx.KeyList[itr++].KeyID = MC_KEY_1;
SeNvmCtx.KeyList[itr++].KeyID = MC_APP_S_KEY_1;
SeNvmCtx.KeyList[itr++].KeyID = MC_NWK_S_KEY_1;
SeNvmCtx.KeyList[itr++].KeyID = MC_KEY_2;
SeNvmCtx.KeyList[itr++].KeyID = MC_APP_S_KEY_2;
SeNvmCtx.KeyList[itr++].KeyID = MC_NWK_S_KEY_2;
SeNvmCtx.KeyList[itr++].KeyID = MC_KEY_3;
SeNvmCtx.KeyList[itr++].KeyID = MC_APP_S_KEY_3;
SeNvmCtx.KeyList[itr++].KeyID = MC_NWK_S_KEY_3;
SeNvmCtx.KeyList[itr++].KeyID = SLOT_RAND_ZERO_KEY;
// Assign callback
if( seNvmCtxChanged != 0 )
{
@@ -186,6 +203,15 @@ SecureElementStatus_t SecureElementInit( EventNvmCtxChanged seNvmCtxChanged )
SeNvmCtxChanged = DummyCB;
}
#if !defined( SECURE_ELEMENT_PRE_PROVISIONED )
#if( STATIC_DEVICE_EUI == 0 )
// Get a DevEUI from MCU unique ID
SoftSeHalGetUniqueId( SeNvmCtx.DevEui );
#endif
#endif
SeNvmCtxChanged( );
return SECURE_ELEMENT_SUCCESS;
}
@@ -215,26 +241,26 @@ SecureElementStatus_t SecureElementSetKey( KeyIdentifier_t keyID, uint8_t* key )
{
return SECURE_ELEMENT_ERROR_NPE;
}
SecureElementStatus_t retval = SECURE_ELEMENT_ERROR;
for( uint8_t i = 0; i < NUM_OF_KEYS; i++ )
{
if( SeNvmCtx.KeyList[i].KeyID == keyID )
{
if( LORAMAC_CRYPTO_MULITCAST_KEYS < SeNvmCtx.KeyList[i].KeyID )
{ // Decrypt the key if its a Mulitcast key
uint8_t decryptedKey[16] = { 0 };
if( ( keyID == MC_KEY_0 ) || ( keyID == MC_KEY_1 ) || ( keyID == MC_KEY_2 ) || ( keyID == MC_KEY_3 ) )
{ // Decrypt the key if its a Mckey
SecureElementStatus_t retval = SECURE_ELEMENT_ERROR;
uint8_t decryptedKey[16] = { 0 };
retval = SecureElementAesEncrypt( key, 16, MC_KE_KEY, decryptedKey );
if( retval != SECURE_ELEMENT_SUCCESS )
{
return retval;
}
memcpy1( SeNvmCtx.KeyList[i].KeyValue, decryptedKey, SE_KEY_SIZE );
SeNvmCtxChanged( );
return retval;
}
else
{
memcpy1( SeNvmCtx.KeyList[i].KeyValue, key, KEY_SIZE );
memcpy1( SeNvmCtx.KeyList[i].KeyValue, key, SE_KEY_SIZE );
SeNvmCtxChanged( );
return SECURE_ELEMENT_SUCCESS;
}
@@ -244,28 +270,29 @@ SecureElementStatus_t SecureElementSetKey( KeyIdentifier_t keyID, uint8_t* key )
return SECURE_ELEMENT_ERROR_INVALID_KEY_ID;
}
SecureElementStatus_t SecureElementComputeAesCmac( uint8_t* buffer, uint16_t size, KeyIdentifier_t keyID, uint32_t* cmac )
SecureElementStatus_t SecureElementComputeAesCmac( uint8_t* micBxBuffer, uint8_t* buffer, uint16_t size,
KeyIdentifier_t keyID, uint32_t* cmac )
{
if( keyID >= LORAMAC_CRYPTO_MULITCAST_KEYS )
if( keyID >= LORAMAC_CRYPTO_MULTICAST_KEYS )
{
//Never accept multicast key identifier for cmac computation
// Never accept multicast key identifier for cmac computation
return SECURE_ELEMENT_ERROR_INVALID_KEY_ID;
}
return ComputeCmac( buffer, size, keyID, cmac );
return ComputeCmac( micBxBuffer, buffer, size, keyID, cmac );
}
SecureElementStatus_t SecureElementVerifyAesCmac( uint8_t* buffer, uint16_t size, uint32_t expectedCmac, KeyIdentifier_t keyID )
SecureElementStatus_t SecureElementVerifyAesCmac( uint8_t* buffer, uint16_t size, uint32_t expectedCmac,
KeyIdentifier_t keyID )
{
if( buffer == NULL )
{
return SECURE_ELEMENT_ERROR_NPE;
}
SecureElementStatus_t retval = SECURE_ELEMENT_ERROR;
uint32_t compCmac = 0;
retval = ComputeCmac( buffer, size, keyID, &compCmac );
SecureElementStatus_t retval = SECURE_ELEMENT_ERROR;
uint32_t compCmac = 0;
retval = ComputeCmac( NULL, buffer, size, keyID, &compCmac );
if( retval != SECURE_ELEMENT_SUCCESS )
{
return retval;
@@ -279,7 +306,8 @@ SecureElementStatus_t SecureElementVerifyAesCmac( uint8_t* buffer, uint16_t size
return retval;
}
SecureElementStatus_t SecureElementAesEncrypt( uint8_t* buffer, uint16_t size, KeyIdentifier_t keyID, uint8_t* encBuffer )
SecureElementStatus_t SecureElementAesEncrypt( uint8_t* buffer, uint16_t size, KeyIdentifier_t keyID,
uint8_t* encBuffer )
{
if( buffer == NULL || encBuffer == NULL )
{
@@ -292,55 +320,48 @@ SecureElementStatus_t SecureElementAesEncrypt( uint8_t* buffer, uint16_t size, K
return SECURE_ELEMENT_ERROR_BUF_SIZE;
}
memset1( SeNvmCtx.AesContext.ksch, '\0', 240 );
aes_context aesContext;
memset1( aesContext.ksch, '\0', 240 );
Key_t* pItem;
Key_t* pItem;
SecureElementStatus_t retval = GetKeyByID( keyID, &pItem );
if( retval == SECURE_ELEMENT_SUCCESS )
{
aes_set_key( pItem->KeyValue, 16, &SeNvmCtx.AesContext );
aes_set_key( pItem->KeyValue, 16, &aesContext );
uint8_t block = 0;
while( size != 0 )
{
aes_encrypt( &buffer[block], &encBuffer[block], &SeNvmCtx.AesContext );
aes_encrypt( &buffer[block], &encBuffer[block], &aesContext );
block = block + 16;
size = size - 16;
size = size - 16;
}
}
return retval;
}
SecureElementStatus_t SecureElementDeriveAndStoreKey( Version_t version, uint8_t* input, KeyIdentifier_t rootKeyID, KeyIdentifier_t targetKeyID )
SecureElementStatus_t SecureElementDeriveAndStoreKey( Version_t version, uint8_t* input, KeyIdentifier_t rootKeyID,
KeyIdentifier_t targetKeyID )
{
if( input == NULL )
{
return SECURE_ELEMENT_ERROR_NPE;
}
SecureElementStatus_t retval = SECURE_ELEMENT_ERROR;
uint8_t key[16] = { 0 };
SecureElementStatus_t retval = SECURE_ELEMENT_ERROR;
uint8_t key[16] = { 0 };
// In case of MC_KE_KEY, prevent other keys than NwkKey or AppKey for LoRaWAN 1.1 or later
// In case of MC_KE_KEY, only McRootKey can be used as root key
if( targetKeyID == MC_KE_KEY )
{
if( ( ( rootKeyID == APP_KEY ) && ( version.Fields.Minor == 0 ) ) || ( rootKeyID == NWK_KEY ) )
if( rootKeyID != MC_ROOT_KEY )
{
return SECURE_ELEMENT_ERROR_INVALID_KEY_ID;
}
}
// In case of McKEKey derivation, the parameter input is concatenated: nonce | DevEUI | pad16
// where nonce SHALL be greater than 15
uint16_t nonce = input[0];
nonce |= ( ( uint16_t ) input[1] << 8 );
if( ( targetKeyID == MC_KE_KEY ) && ( nonce < 16 ) )
{
return retval;
}
// Derive key
retval = SecureElementAesEncrypt( input, 16, rootKeyID, key );
if( retval != SECURE_ELEMENT_SUCCESS )
@@ -358,12 +379,159 @@ SecureElementStatus_t SecureElementDeriveAndStoreKey( Version_t version, uint8_t
return SECURE_ELEMENT_SUCCESS;
}
SecureElementStatus_t SecureElementProcessJoinAccept( JoinReqIdentifier_t joinReqType, uint8_t* joinEui,
uint16_t devNonce, uint8_t* encJoinAccept,
uint8_t encJoinAcceptSize, uint8_t* decJoinAccept,
uint8_t* versionMinor )
{
if( ( encJoinAccept == NULL ) || ( decJoinAccept == NULL ) || ( versionMinor == NULL ) )
{
return SECURE_ELEMENT_ERROR_NPE;
}
// Check that frame size isn't bigger than a JoinAccept with CFList size
if( encJoinAcceptSize > LORAMAC_JOIN_ACCEPT_FRAME_MAX_SIZE )
{
return SECURE_ELEMENT_ERROR_BUF_SIZE;
}
// Determine decryption key
KeyIdentifier_t encKeyID = NWK_KEY;
if( joinReqType != JOIN_REQ )
{
encKeyID = J_S_ENC_KEY;
}
memcpy1( decJoinAccept, encJoinAccept, encJoinAcceptSize );
// Decrypt JoinAccept, skip MHDR
if( SecureElementAesEncrypt( encJoinAccept + LORAMAC_MHDR_FIELD_SIZE, encJoinAcceptSize - LORAMAC_MHDR_FIELD_SIZE,
encKeyID, decJoinAccept + LORAMAC_MHDR_FIELD_SIZE ) != SECURE_ELEMENT_SUCCESS )
{
return SECURE_ELEMENT_FAIL_ENCRYPT;
}
*versionMinor = ( ( decJoinAccept[11] & 0x80 ) == 0x80 ) ? 1 : 0;
uint32_t mic = 0;
mic = ( ( uint32_t ) decJoinAccept[encJoinAcceptSize - LORAMAC_MIC_FIELD_SIZE] << 0 );
mic |= ( ( uint32_t ) decJoinAccept[encJoinAcceptSize - LORAMAC_MIC_FIELD_SIZE + 1] << 8 );
mic |= ( ( uint32_t ) decJoinAccept[encJoinAcceptSize - LORAMAC_MIC_FIELD_SIZE + 2] << 16 );
mic |= ( ( uint32_t ) decJoinAccept[encJoinAcceptSize - LORAMAC_MIC_FIELD_SIZE + 3] << 24 );
// - Header buffer to be used for MIC computation
// - LoRaWAN 1.0.x : micHeader = [MHDR(1)]
// - LoRaWAN 1.1.x : micHeader = [JoinReqType(1), JoinEUI(8), DevNonce(2), MHDR(1)]
// Verify mic
if( *versionMinor == 0 )
{
// For LoRaWAN 1.0.x
// cmac = aes128_cmac(NwkKey, MHDR | JoinNonce | NetID | DevAddr | DLSettings | RxDelay | CFList |
// CFListType)
if( SecureElementVerifyAesCmac( decJoinAccept, ( encJoinAcceptSize - LORAMAC_MIC_FIELD_SIZE ), mic, NWK_KEY ) !=
SECURE_ELEMENT_SUCCESS )
{
return SECURE_ELEMENT_FAIL_CMAC;
}
}
#if( USE_LRWAN_1_1_X_CRYPTO == 1 )
else if( *versionMinor == 1 )
{
uint8_t micHeader11[JOIN_ACCEPT_MIC_COMPUTATION_OFFSET] = { 0 };
uint16_t bufItr = 0;
micHeader11[bufItr++] = ( uint8_t ) joinReqType;
memcpyr( micHeader11 + bufItr, joinEui, LORAMAC_JOIN_EUI_FIELD_SIZE );
bufItr += LORAMAC_JOIN_EUI_FIELD_SIZE;
micHeader11[bufItr++] = devNonce & 0xFF;
micHeader11[bufItr++] = ( devNonce >> 8 ) & 0xFF;
// For LoRaWAN 1.1.x and later:
// cmac = aes128_cmac(JSIntKey, JoinReqType | JoinEUI | DevNonce | MHDR | JoinNonce | NetID | DevAddr |
// DLSettings | RxDelay | CFList | CFListType)
// Prepare the msg for integrity check (adding JoinReqType, JoinEUI and DevNonce)
uint8_t localBuffer[LORAMAC_JOIN_ACCEPT_FRAME_MAX_SIZE + JOIN_ACCEPT_MIC_COMPUTATION_OFFSET] = { 0 };
memcpy1( localBuffer, micHeader11, JOIN_ACCEPT_MIC_COMPUTATION_OFFSET );
memcpy1( localBuffer + JOIN_ACCEPT_MIC_COMPUTATION_OFFSET - 1, decJoinAccept, encJoinAcceptSize );
if( SecureElementVerifyAesCmac( localBuffer,
encJoinAcceptSize + JOIN_ACCEPT_MIC_COMPUTATION_OFFSET -
LORAMAC_MHDR_FIELD_SIZE - LORAMAC_MIC_FIELD_SIZE,
mic, J_S_INT_KEY ) != SECURE_ELEMENT_SUCCESS )
{
return SECURE_ELEMENT_FAIL_CMAC;
}
}
#endif
else
{
return SECURE_ELEMENT_ERROR_INVALID_LORAWAM_SPEC_VERSION;
}
return SECURE_ELEMENT_SUCCESS;
}
SecureElementStatus_t SecureElementRandomNumber( uint32_t* randomNum )
{
if( randomNum == NULL )
{
return SECURE_ELEMENT_ERROR_NPE;
}
*randomNum = Radio.Random( );
*randomNum = SoftSeHalGetRandomNumber( );
return SECURE_ELEMENT_SUCCESS;
}
SecureElementStatus_t SecureElementSetDevEui( uint8_t* devEui )
{
if( devEui == NULL )
{
return SECURE_ELEMENT_ERROR_NPE;
}
memcpy1( SeNvmCtx.DevEui, devEui, SE_EUI_SIZE );
SeNvmCtxChanged( );
return SECURE_ELEMENT_SUCCESS;
}
uint8_t* SecureElementGetDevEui( void )
{
return SeNvmCtx.DevEui;
}
SecureElementStatus_t SecureElementSetJoinEui( uint8_t* joinEui )
{
if( joinEui == NULL )
{
return SECURE_ELEMENT_ERROR_NPE;
}
memcpy1( SeNvmCtx.JoinEui, joinEui, SE_EUI_SIZE );
SeNvmCtxChanged( );
return SECURE_ELEMENT_SUCCESS;
}
uint8_t* SecureElementGetJoinEui( void )
{
return SeNvmCtx.JoinEui;
}
SecureElementStatus_t SecureElementSetPin( uint8_t* pin )
{
if( pin == NULL )
{
return SECURE_ELEMENT_ERROR_NPE;
}
memcpy1( SeNvmCtx.Pin, pin, SE_PIN_SIZE );
SeNvmCtxChanged( );
return SECURE_ELEMENT_SUCCESS;
}
uint8_t* SecureElementGetPin( void )
{
return SeNvmCtx.Pin;
}