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