1 /**
2 * @file atecc608a-tnglora-se.c
3 *
4 * @brief ATECC608A-TNGLORA Secure Element hardware implementation
5 *
6 * @remark Current implementation supports LoRaWAN 1.0.x and 1.1
7 *
8 * @copyright Copyright (c) 2020 The Things Industries B.V.
9 *
10 * Revised BSD License
11 * Copyright The Things Industries B.V 2020. All rights reserved.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions are met:
15 * * Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * * Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * * Neither the name of the Things Industries B.V nor the
21 * names of its contributors may be used to endorse or promote products
22 * derived from this software without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE THINGS INDUSTRIES B.V BE LIABLE FOR ANY
28 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35
36 #include "atca_basic.h"
37 #include "cryptoauthlib.h"
38 #include "atca_devtypes.h"
39
40 #include "secure-element.h"
41 #include "secure-element-nvm.h"
42 #include "se-identity.h"
43 #include "atecc608a-tnglora-se-hal.h"
44
45 /*!
46 * Number of supported crypto keys
47 */
48 #define NUM_OF_KEYS 15
49
50 #define DEV_EUI_ASCII_SIZE_BYTE 16U
51
52 /*!
53 * Identifier value pair type for Keys
54 */
55 typedef struct sKey
56 {
57 /*
58 * Key identifier (used for maping the stack MAC key to the ATECC608A-TNGLoRaWAN slot)
59 */
60 KeyIdentifier_t KeyID;
61 /*
62 * Key slot number
63 */
64 uint16_t KeySlotNumber;
65 /*
66 * Key block index within slot (each block can contain two keys, so index is either 0 or 1)
67 */
68 uint8_t KeyBlockIndex;
69 } Key_t;
70
71 static SecureElementNvmData_t* SeNvm;
72
73 static Key_t KeyList[NUM_OF_KEYS] = ATECC608A_SE_KEY_LIST;
74
75 static ATCAIfaceCfg atecc608_i2c_config;
76
77 static ATCA_STATUS convert_ascii_devEUI( uint8_t* devEUI_ascii, uint8_t* devEUI );
78
atcab_read_joinEUI(uint8_t * joinEUI)79 static ATCA_STATUS atcab_read_joinEUI( uint8_t* joinEUI )
80 {
81 ATCA_STATUS status = ATCA_GEN_FAIL;
82 uint8_t read_buf[ATCA_BLOCK_SIZE];
83
84 if( joinEUI == NULL )
85 {
86 return ATCA_BAD_PARAM;
87 }
88
89 do
90 {
91 status = atcab_read_zone( ATCA_ZONE_DATA, TNGLORA_JOIN_EUI_SLOT, 0, 0, read_buf, ATCA_BLOCK_SIZE );
92 if( status != ATCA_SUCCESS )
93 {
94 break;
95 }
96 memcpy1( joinEUI, read_buf, SE_EUI_SIZE );
97 } while( 0 );
98
99 return status;
100 }
101
atcab_read_ascii_devEUI(uint8_t * devEUI_ascii)102 static ATCA_STATUS atcab_read_ascii_devEUI( uint8_t* devEUI_ascii )
103 {
104 ATCA_STATUS status = ATCA_GEN_FAIL;
105 uint8_t read_buf[ATCA_BLOCK_SIZE];
106
107 if( devEUI_ascii == NULL )
108 {
109 return ATCA_BAD_PARAM;
110 }
111
112 do
113 {
114 status = atcab_read_zone( ATCA_ZONE_DATA, TNGLORA_DEV_EUI_SLOT, 0, 0, read_buf, ATCA_BLOCK_SIZE );
115 if( status != ATCA_SUCCESS )
116 {
117 break;
118 }
119 memcpy1( devEUI_ascii, read_buf, DEV_EUI_ASCII_SIZE_BYTE );
120 } while( 0 );
121
122 return status;
123 }
124
convert_ascii_devEUI(uint8_t * devEUI_ascii,uint8_t * devEUI)125 static ATCA_STATUS convert_ascii_devEUI( uint8_t* devEUI_ascii, uint8_t* devEUI )
126 {
127 for( size_t pos = 0; pos < DEV_EUI_ASCII_SIZE_BYTE; pos += 2 )
128 {
129 uint8_t temp = 0;
130 if( ( devEUI_ascii[pos] >= '0' ) && ( devEUI_ascii[pos] <= '9' ) )
131 {
132 temp = ( devEUI_ascii[pos] - '0' ) << 4;
133 }
134 else if( ( devEUI_ascii[pos] >= 'A' ) && ( devEUI_ascii[pos] <= 'F' ) )
135 {
136 temp = ( ( devEUI_ascii[pos] - 'A' ) + 10 ) << 4;
137 }
138 else
139 {
140 return ATCA_BAD_PARAM;
141 }
142 if( ( devEUI_ascii[pos + 1] >= '0' ) && ( devEUI_ascii[pos + 1] <= '9' ) )
143 {
144 temp |= devEUI_ascii[pos + 1] - '0';
145 }
146 else if( ( devEUI_ascii[pos + 1] >= 'A' ) && ( devEUI_ascii[pos + 1] <= 'F' ) )
147 {
148 temp |= ( devEUI_ascii[pos + 1] - 'A' ) + 10;
149 }
150 else
151 {
152 return ATCA_BAD_PARAM;
153 }
154 devEUI[pos / 2] = temp;
155 }
156 return ATCA_SUCCESS;
157 }
158
atcab_read_devEUI(uint8_t * devEUI)159 static ATCA_STATUS atcab_read_devEUI( uint8_t* devEUI )
160 {
161 ATCA_STATUS status = ATCA_GEN_FAIL;
162 uint8_t devEUI_ascii[DEV_EUI_ASCII_SIZE_BYTE];
163
164 status = atcab_read_ascii_devEUI( devEUI_ascii );
165 if( status != ATCA_SUCCESS )
166 {
167 return status;
168 }
169 status = convert_ascii_devEUI( devEUI_ascii, devEUI );
170 return status;
171 }
172
173 /*
174 * Gets key item from key list.
175 *
176 * cmac = aes128_cmac(keyID, B0 | msg)
177 *
178 * \param[IN] keyID - Key identifier
179 * \param[OUT] keyItem - Key item reference
180 * \retval - Status of the operation
181 */
GetKeyByID(KeyIdentifier_t keyID,Key_t ** keyItem)182 SecureElementStatus_t GetKeyByID( KeyIdentifier_t keyID, Key_t** keyItem )
183 {
184 for( uint8_t i = 0; i < NUM_OF_KEYS; i++ )
185 {
186 if( KeyList[i].KeyID == keyID )
187 {
188 *keyItem = &( KeyList[i] );
189 return SECURE_ELEMENT_SUCCESS;
190 }
191 }
192 return SECURE_ELEMENT_ERROR_INVALID_KEY_ID;
193 }
194
195 /*
196 * Computes a CMAC of a message using provided initial Bx block
197 *
198 * cmac = aes128_cmac(keyID, blocks[i].Buffer)
199 *
200 * \param[IN] micBxBuffer - Buffer containing the initial Bx block
201 * \param[IN] buffer - Data buffer
202 * \param[IN] size - Data buffer size
203 * \param[IN] keyID - Key identifier to determine the AES key to be used
204 * \param[OUT] cmac - Computed cmac
205 * \retval - Status of the operation
206 */
ComputeCmac(uint8_t * micBxBuffer,uint8_t * buffer,uint16_t size,KeyIdentifier_t keyID,uint32_t * cmac)207 static SecureElementStatus_t ComputeCmac( uint8_t* micBxBuffer, uint8_t* buffer, uint16_t size, KeyIdentifier_t keyID,
208 uint32_t* cmac )
209 {
210 if( ( buffer == NULL ) || ( cmac == NULL ) )
211 {
212 return SECURE_ELEMENT_ERROR_NPE;
213 }
214
215 uint8_t Cmac[16] = { 0 };
216
217 Key_t* keyItem;
218 SecureElementStatus_t retval = GetKeyByID( keyID, &keyItem );
219 if( retval != SECURE_ELEMENT_SUCCESS )
220 {
221 return retval;
222 }
223
224 atca_aes_cmac_ctx_t atcaAesCmacCtx;
225 ATCA_STATUS status =
226 atcab_aes_cmac_init( &atcaAesCmacCtx, keyItem->KeySlotNumber, keyItem->KeyBlockIndex );
227
228 if( ATCA_SUCCESS == status )
229 {
230 if( micBxBuffer != NULL )
231 {
232 atcab_aes_cmac_update( &atcaAesCmacCtx, micBxBuffer, 16 );
233 }
234
235 atcab_aes_cmac_update( &atcaAesCmacCtx, buffer, size );
236
237 atcab_aes_cmac_finish( &atcaAesCmacCtx, Cmac, 16 );
238
239 *cmac = ( uint32_t )( ( uint32_t ) Cmac[3] << 24 | ( uint32_t ) Cmac[2] << 16 | ( uint32_t ) Cmac[1] << 8 |
240 ( uint32_t ) Cmac[0] );
241 return SECURE_ELEMENT_SUCCESS;
242 }
243 else
244 {
245 return SECURE_ELEMENT_ERROR;
246 }
247 }
248
SecureElementInit(SecureElementNvmData_t * nvm)249 SecureElementStatus_t SecureElementInit( SecureElementNvmData_t* nvm )
250 {
251 SecureElementNvmData_t seNvmInit =
252 {
253 /*!
254 * end-device IEEE EUI (big endian)
255 */
256 .DevEui = { 0 },
257 /*!
258 * App/Join server IEEE EUI (big endian)
259 */
260 .JoinEui = { 0 },
261 /*!
262 * Secure-element pin (big endian)
263 */
264 .Pin = SECURE_ELEMENT_PIN,
265 };
266
267 if( nvm == NULL )
268 {
269 return SECURE_ELEMENT_ERROR_NPE;
270 }
271
272 // Initialize nvm pointer
273 SeNvm = nvm;
274
275 // Initialize data
276 memcpy1( ( uint8_t* )SeNvm, ( uint8_t* )&seNvmInit, sizeof( seNvmInit ) );
277
278 #if !defined( SECURE_ELEMENT_PRE_PROVISIONED )
279 #error "ATECC608A is always pre-provisioned. Please set SECURE_ELEMENT_PRE_PROVISIONED to ON"
280 #endif
281 atecc608_i2c_config.iface_type = ATCA_I2C_IFACE;
282 atecc608_i2c_config.atcai2c.baud = ATCA_HAL_ATECC608A_I2C_FREQUENCY;
283 atecc608_i2c_config.atcai2c.bus = ATCA_HAL_ATECC608A_I2C_BUS_PINS;
284 atecc608_i2c_config.atcai2c.slave_address = ATCA_HAL_ATECC608A_I2C_ADDRESS;
285 atecc608_i2c_config.devtype = ATECC608A;
286 atecc608_i2c_config.rx_retries = ATCA_HAL_ATECC608A_I2C_RX_RETRIES;
287 atecc608_i2c_config.wake_delay = ATCA_HAL_ATECC608A_I2C_WAKEUP_DELAY;
288
289 if( atcab_init( &atecc608_i2c_config ) != ATCA_SUCCESS )
290 {
291 return SECURE_ELEMENT_ERROR;
292 }
293
294 if( atcab_read_devEUI( SeNvm->DevEui ) != ATCA_SUCCESS )
295 {
296 return SECURE_ELEMENT_ERROR;
297 }
298
299 if( atcab_read_joinEUI( SeNvm->JoinEui ) != ATCA_SUCCESS )
300 {
301 return SECURE_ELEMENT_ERROR;
302 }
303 return SECURE_ELEMENT_SUCCESS;
304 }
305
SecureElementSetKey(KeyIdentifier_t keyID,uint8_t * key)306 SecureElementStatus_t SecureElementSetKey( KeyIdentifier_t keyID, uint8_t* key )
307 {
308 // No key setting for HW SE, can only derive keys
309 return SECURE_ELEMENT_SUCCESS;
310 }
311
SecureElementComputeAesCmac(uint8_t * micBxBuffer,uint8_t * buffer,uint16_t size,KeyIdentifier_t keyID,uint32_t * cmac)312 SecureElementStatus_t SecureElementComputeAesCmac( uint8_t* micBxBuffer, uint8_t* buffer, uint16_t size,
313 KeyIdentifier_t keyID, uint32_t* cmac )
314 {
315 if( keyID >= LORAMAC_CRYPTO_MULTICAST_KEYS )
316 {
317 // Never accept multicast key identifier for cmac computation
318 return SECURE_ELEMENT_ERROR_INVALID_KEY_ID;
319 }
320 return ComputeCmac( micBxBuffer, buffer, size, keyID, cmac );
321 }
322
SecureElementVerifyAesCmac(uint8_t * buffer,uint16_t size,uint32_t expectedCmac,KeyIdentifier_t keyID)323 SecureElementStatus_t SecureElementVerifyAesCmac( uint8_t* buffer, uint16_t size, uint32_t expectedCmac,
324 KeyIdentifier_t keyID )
325 {
326 if( buffer == NULL )
327 {
328 return SECURE_ELEMENT_ERROR_NPE;
329 }
330
331 SecureElementStatus_t retval = SECURE_ELEMENT_ERROR;
332 uint32_t compCmac = 0;
333
334 retval = ComputeCmac( NULL, buffer, size, keyID, &compCmac );
335 if( retval != SECURE_ELEMENT_SUCCESS )
336 {
337 return retval;
338 }
339
340 if( expectedCmac != compCmac )
341 {
342 retval = SECURE_ELEMENT_FAIL_CMAC;
343 }
344
345 return retval;
346 }
347
SecureElementAesEncrypt(uint8_t * buffer,uint16_t size,KeyIdentifier_t keyID,uint8_t * encBuffer)348 SecureElementStatus_t SecureElementAesEncrypt( uint8_t* buffer, uint16_t size, KeyIdentifier_t keyID,
349 uint8_t* encBuffer )
350 {
351 if( buffer == NULL || encBuffer == NULL )
352 {
353 return SECURE_ELEMENT_ERROR_NPE;
354 }
355
356 // Check if the size is divisible by 16,
357 if( ( size % 16 ) != 0 )
358 {
359 return SECURE_ELEMENT_ERROR_BUF_SIZE;
360 }
361
362 Key_t* pItem;
363 SecureElementStatus_t retval = GetKeyByID( keyID, &pItem );
364
365 if( retval == SECURE_ELEMENT_SUCCESS )
366 {
367 uint8_t block = 0;
368
369 while( size != 0 )
370 {
371 atcab_aes_encrypt( pItem->KeySlotNumber, pItem->KeyBlockIndex, &buffer[block], &encBuffer[block] );
372 block = block + 16;
373 size = size - 16;
374 }
375 }
376 return retval;
377 }
378
SecureElementDeriveAndStoreKey(uint8_t * input,KeyIdentifier_t rootKeyID,KeyIdentifier_t targetKeyID)379 SecureElementStatus_t SecureElementDeriveAndStoreKey( uint8_t* input, KeyIdentifier_t rootKeyID,
380 KeyIdentifier_t targetKeyID )
381 {
382 if( input == NULL )
383 {
384 return SECURE_ELEMENT_ERROR_NPE;
385 }
386
387 // Source key slot is the LSB and target key slot is the MSB
388 uint16_t source_target_ids = 0;
389 Key_t* source_key;
390 Key_t* target_key;
391 ATCA_STATUS status = ATCA_SUCCESS;
392
393 // In case of MC_KE_KEY, only McRootKey can be used as root key
394 if( targetKeyID == MC_KE_KEY )
395 {
396 if( rootKeyID != MC_ROOT_KEY )
397 {
398 return SECURE_ELEMENT_ERROR_INVALID_KEY_ID;
399 }
400 }
401
402 if( ( rootKeyID == APP_KEY ) || ( rootKeyID == MC_ROOT_KEY ) || ( rootKeyID == MC_KE_KEY ) )
403 {
404 // Allow the stack to move forward as these rootkeys dont exist inside SE.
405 return SECURE_ELEMENT_SUCCESS;
406 }
407
408 if( GetKeyByID( rootKeyID, &source_key ) != SECURE_ELEMENT_SUCCESS )
409 {
410 return SECURE_ELEMENT_ERROR_INVALID_KEY_ID;
411 }
412
413 if( GetKeyByID( targetKeyID, &target_key ) != SECURE_ELEMENT_SUCCESS )
414 {
415 return SECURE_ELEMENT_ERROR_INVALID_KEY_ID;
416 }
417
418 source_target_ids = target_key->KeySlotNumber << 8;
419 source_target_ids += source_key->KeySlotNumber;
420
421 uint32_t detail = source_key->KeyBlockIndex;
422
423 status = atcab_kdf( KDF_MODE_ALG_AES | KDF_MODE_SOURCE_SLOT | KDF_MODE_TARGET_SLOT, source_target_ids, detail,
424 input, NULL, NULL );
425 if( status == ATCA_SUCCESS )
426 {
427 return SECURE_ELEMENT_SUCCESS;
428 }
429 else
430 {
431 return SECURE_ELEMENT_ERROR;
432 }
433 }
434
SecureElementProcessJoinAccept(JoinReqIdentifier_t joinReqType,uint8_t * joinEui,uint16_t devNonce,uint8_t * encJoinAccept,uint8_t encJoinAcceptSize,uint8_t * decJoinAccept,uint8_t * versionMinor)435 SecureElementStatus_t SecureElementProcessJoinAccept( JoinReqIdentifier_t joinReqType, uint8_t* joinEui,
436 uint16_t devNonce, uint8_t* encJoinAccept,
437 uint8_t encJoinAcceptSize, uint8_t* decJoinAccept,
438 uint8_t* versionMinor )
439 {
440 if( ( encJoinAccept == NULL ) || ( decJoinAccept == NULL ) || ( versionMinor == NULL ) )
441 {
442 return SECURE_ELEMENT_ERROR_NPE;
443 }
444
445 // Check that frame size isn't bigger than a JoinAccept with CFList size
446 if( encJoinAcceptSize > LORAMAC_JOIN_ACCEPT_FRAME_MAX_SIZE )
447 {
448 return SECURE_ELEMENT_ERROR_BUF_SIZE;
449 }
450
451 // Determine decryption key
452 KeyIdentifier_t encKeyID = NWK_KEY;
453
454 if( joinReqType != JOIN_REQ )
455 {
456 encKeyID = J_S_ENC_KEY;
457 }
458
459 memcpy1( decJoinAccept, encJoinAccept, encJoinAcceptSize );
460
461 // Decrypt JoinAccept, skip MHDR
462 if( SecureElementAesEncrypt( encJoinAccept + LORAMAC_MHDR_FIELD_SIZE, encJoinAcceptSize - LORAMAC_MHDR_FIELD_SIZE,
463 encKeyID, decJoinAccept + LORAMAC_MHDR_FIELD_SIZE ) != SECURE_ELEMENT_SUCCESS )
464 {
465 return SECURE_ELEMENT_FAIL_ENCRYPT;
466 }
467
468 *versionMinor = ( ( decJoinAccept[11] & 0x80 ) == 0x80 ) ? 1 : 0;
469
470 uint32_t mic = 0;
471
472 mic = ( ( uint32_t ) decJoinAccept[encJoinAcceptSize - LORAMAC_MIC_FIELD_SIZE] << 0 );
473 mic |= ( ( uint32_t ) decJoinAccept[encJoinAcceptSize - LORAMAC_MIC_FIELD_SIZE + 1] << 8 );
474 mic |= ( ( uint32_t ) decJoinAccept[encJoinAcceptSize - LORAMAC_MIC_FIELD_SIZE + 2] << 16 );
475 mic |= ( ( uint32_t ) decJoinAccept[encJoinAcceptSize - LORAMAC_MIC_FIELD_SIZE + 3] << 24 );
476
477 // - Header buffer to be used for MIC computation
478 // - LoRaWAN 1.0.x : micHeader = [MHDR(1)]
479 // - LoRaWAN 1.1.x : micHeader = [JoinReqType(1), JoinEUI(8), DevNonce(2), MHDR(1)]
480
481 // Verify mic
482 if( *versionMinor == 0 )
483 {
484 // For LoRaWAN 1.0.x
485 // cmac = aes128_cmac(NwkKey, MHDR | JoinNonce | NetID | DevAddr | DLSettings | RxDelay | CFList |
486 // CFListType)
487 if( SecureElementVerifyAesCmac( decJoinAccept, ( encJoinAcceptSize - LORAMAC_MIC_FIELD_SIZE ), mic, NWK_KEY ) !=
488 SECURE_ELEMENT_SUCCESS )
489 {
490 return SECURE_ELEMENT_FAIL_CMAC;
491 }
492 }
493 #if( USE_LRWAN_1_1_X_CRYPTO == 1 )
494 else if( *versionMinor == 1 )
495 {
496 uint8_t micHeader11[JOIN_ACCEPT_MIC_COMPUTATION_OFFSET] = { 0 };
497 uint16_t bufItr = 0;
498
499 micHeader11[bufItr++] = ( uint8_t ) joinReqType;
500
501 memcpyr( micHeader11 + bufItr, joinEui, LORAMAC_JOIN_EUI_FIELD_SIZE );
502 bufItr += LORAMAC_JOIN_EUI_FIELD_SIZE;
503
504 micHeader11[bufItr++] = devNonce & 0xFF;
505 micHeader11[bufItr++] = ( devNonce >> 8 ) & 0xFF;
506
507 // For LoRaWAN 1.1.x and later:
508 // cmac = aes128_cmac(JSIntKey, JoinReqType | JoinEUI | DevNonce | MHDR | JoinNonce | NetID | DevAddr |
509 // DLSettings | RxDelay | CFList | CFListType)
510 // Prepare the msg for integrity check (adding JoinReqType, JoinEUI and DevNonce)
511 uint8_t localBuffer[LORAMAC_JOIN_ACCEPT_FRAME_MAX_SIZE + JOIN_ACCEPT_MIC_COMPUTATION_OFFSET] = { 0 };
512
513 memcpy1( localBuffer, micHeader11, JOIN_ACCEPT_MIC_COMPUTATION_OFFSET );
514 memcpy1( localBuffer + JOIN_ACCEPT_MIC_COMPUTATION_OFFSET - 1, decJoinAccept, encJoinAcceptSize );
515
516 if( SecureElementVerifyAesCmac( localBuffer,
517 encJoinAcceptSize + JOIN_ACCEPT_MIC_COMPUTATION_OFFSET -
518 LORAMAC_MHDR_FIELD_SIZE - LORAMAC_MIC_FIELD_SIZE,
519 mic, J_S_INT_KEY ) != SECURE_ELEMENT_SUCCESS )
520 {
521 return SECURE_ELEMENT_FAIL_CMAC;
522 }
523 }
524 #endif
525 else
526 {
527 return SECURE_ELEMENT_ERROR_INVALID_LORAWAM_SPEC_VERSION;
528 }
529
530 return SECURE_ELEMENT_SUCCESS;
531 }
532
SecureElementRandomNumber(uint32_t * randomNum)533 SecureElementStatus_t SecureElementRandomNumber( uint32_t* randomNum )
534 {
535 if( randomNum == NULL )
536 {
537 return SECURE_ELEMENT_ERROR_NPE;
538 }
539 *randomNum = ATECC608ASeHalGetRandomNumber( );
540 return SECURE_ELEMENT_SUCCESS;
541 }
542
SecureElementSetDevEui(uint8_t * devEui)543 SecureElementStatus_t SecureElementSetDevEui( uint8_t* devEui )
544 {
545 if( devEui == NULL )
546 {
547 return SECURE_ELEMENT_ERROR_NPE;
548 }
549 memcpy1( SeNvm->DevEui, devEui, SE_EUI_SIZE );
550 return SECURE_ELEMENT_SUCCESS;
551 }
552
SecureElementGetDevEui(void)553 uint8_t* SecureElementGetDevEui( void )
554 {
555 return SeNvm->DevEui;
556 }
557
SecureElementSetJoinEui(uint8_t * joinEui)558 SecureElementStatus_t SecureElementSetJoinEui( uint8_t* joinEui )
559 {
560 if( joinEui == NULL )
561 {
562 return SECURE_ELEMENT_ERROR_NPE;
563 }
564 memcpy1( SeNvm->JoinEui, joinEui, SE_EUI_SIZE );
565 return SECURE_ELEMENT_SUCCESS;
566 }
567
SecureElementGetJoinEui(void)568 uint8_t* SecureElementGetJoinEui( void )
569 {
570 return SeNvm->JoinEui;
571 }
572
SecureElementSetPin(uint8_t * pin)573 SecureElementStatus_t SecureElementSetPin( uint8_t* pin )
574 {
575 if( pin == NULL )
576 {
577 return SECURE_ELEMENT_ERROR_NPE;
578 }
579
580 memcpy1( SeNvm->Pin, pin, SE_PIN_SIZE );
581 return SECURE_ELEMENT_SUCCESS;
582 }
583
SecureElementGetPin(void)584 uint8_t* SecureElementGetPin( void )
585 {
586 return SeNvm->Pin;
587 }
588