1 /*!
2  * \file      lr1110-se.c
3  *
4  * \brief     LR1110 Secure Element hardware implementation
5  *
6  * \copyright Revised BSD License, see section \ref LICENSE.
7  *
8  * \code
9  *                ______                              _
10  *               / _____)             _              | |
11  *              ( (____  _____ ____ _| |_ _____  ____| |__
12  *               \____ \| ___ |    (_   _) ___ |/ ___)  _ \
13  *               _____) ) ____| | | || |_| ____( (___| | | |
14  *              (______/|_____)_|_|_| \__)_____)\____)_| |_|
15  *              (C)2019-2019 Semtech
16  *
17  * \endcode
18  *
19  * \authors    Semtech WSP Applications Team
20  */
21 #include <stdlib.h>
22 #include <stdint.h>
23 
24 #include "lr1110.h"
25 #include "lr1110_system.h"
26 #include "lr1110_crypto_engine.h"
27 
28 #include "secure-element.h"
29 #include "secure-element-nvm.h"
30 #include "se-identity.h"
31 #include "lr1110-se-hal.h"
32 
33 /*!
34  * Number of supported crypto keys
35  */
36 #define NUM_OF_KEYS 23
37 
38 /*
39  * CMAC/AES Message Integrity Code (MIC) Block B0 size
40  */
41 #define MIC_BLOCK_BX_SIZE 16
42 
43 /*
44  * Maximum size of the message that can be handled by the crypto operations
45  */
46 #define CRYPTO_MAXMESSAGE_SIZE 256
47 
48 /*
49  * Maximum size of the buffer for crypto operations
50  */
51 #define CRYPTO_BUFFER_SIZE CRYPTO_MAXMESSAGE_SIZE + MIC_BLOCK_BX_SIZE
52 
53 static SecureElementNvmData_t* SeNvm;
54 
55 /*!
56  * LR1110 radio context
57  */
58 extern lr1110_t LR1110;
59 
60 /*!
61  * Converts key ids from SecureElement to LR1110
62  *
63  * \param [IN] key_id SecureElement key id to be converted
64  *
65  * \retval key_id Converted LR1110 key id
66  */
67 static lr1110_crypto_keys_idx_t convert_key_id_from_se_to_lr1110( KeyIdentifier_t key_id );
68 
SecureElementInit(SecureElementNvmData_t * nvm)69 SecureElementStatus_t SecureElementInit( SecureElementNvmData_t* nvm )
70 {
71     lr1110_crypto_status_t status = LR1110_CRYPTO_STATUS_ERROR;
72     SecureElementNvmData_t seNvmInit =
73     {
74         /*!
75         * end-device IEEE EUI (big endian)
76         *
77         * \remark In this application the value is automatically generated by calling
78         *         BoardGetUniqueId function
79         */
80         .DevEui = LORAWAN_DEVICE_EUI,
81         /*!
82         * App/Join server IEEE EUI (big endian)
83         */
84         .JoinEui = LORAWAN_JOIN_EUI,
85         /*!
86         * Secure-element pin (big endian)
87         */
88         .Pin = SECURE_ELEMENT_PIN,
89     };
90 
91     // Initialize nvm pointer
92     SeNvm = nvm;
93 
94     // Initialize data
95     memcpy1( ( uint8_t* )SeNvm, ( uint8_t* )&seNvmInit, sizeof( seNvmInit ) );
96 
97     lr1110_crypto_restore_from_flash( &LR1110, &status );
98 
99     if( status != LR1110_CRYPTO_STATUS_SUCCESS )
100     {
101         return ( SecureElementStatus_t ) status;
102     }
103 
104 #if defined( SECURE_ELEMENT_PRE_PROVISIONED )
105     // Read LR1110 pre-provisioned identity
106     lr1110_system_read_uid( &LR1110, SeNvm->DevEui );
107     lr1110_system_read_join_eui( &LR1110, SeNvm->JoinEui );
108     lr1110_system_read_pin( &LR1110, SeNvm->Pin );
109 #else
110 #if( STATIC_DEVICE_EUI == 0 )
111     // Get a DevEUI from MCU unique ID
112     LR1110SeHalGetUniqueId( SeNvm->DevEui );
113 #endif
114 #endif
115 
116     const lr1110_crypto_key_t zero_key = { 0 };
117     lr1110_crypto_set_key( &LR1110, &status,
118                           convert_key_id_from_se_to_lr1110( SLOT_RAND_ZERO_KEY ), zero_key );
119 
120     return ( SecureElementStatus_t ) status;
121 }
122 
SecureElementSetKey(KeyIdentifier_t keyID,uint8_t * key)123 SecureElementStatus_t SecureElementSetKey( KeyIdentifier_t keyID, uint8_t* key )
124 {
125     if( key == NULL )
126     {
127         return SECURE_ELEMENT_ERROR_NPE;
128     }
129 
130     SecureElementStatus_t status = SECURE_ELEMENT_ERROR;
131 
132     if( ( keyID == MC_KEY_0 ) || ( keyID == MC_KEY_1 ) || ( keyID == MC_KEY_2 ) || ( keyID == MC_KEY_3 ) )
133     {  // Decrypt the key if its a Mckey
134 
135         lr1110_crypto_derive_and_store_key( &LR1110, ( lr1110_crypto_status_t* ) &status,
136                                             convert_key_id_from_se_to_lr1110( MC_KE_KEY ),
137                                             convert_key_id_from_se_to_lr1110( keyID ), key );
138 
139         if( status == SECURE_ELEMENT_SUCCESS )
140         {
141             lr1110_crypto_store_to_flash( &LR1110, ( lr1110_crypto_status_t* ) &status );
142         }
143         return status;
144     }
145     else
146     {
147         lr1110_crypto_set_key( &LR1110, ( lr1110_crypto_status_t* ) &status, convert_key_id_from_se_to_lr1110( keyID ),
148                                key );
149         if( status == SECURE_ELEMENT_SUCCESS )
150         {
151             lr1110_crypto_store_to_flash( &LR1110, ( lr1110_crypto_status_t* ) &status );
152         }
153         return status;
154     }
155 }
156 
SecureElementComputeAesCmac(uint8_t * micBxBuffer,uint8_t * buffer,uint16_t size,KeyIdentifier_t keyID,uint32_t * cmac)157 SecureElementStatus_t SecureElementComputeAesCmac( uint8_t* micBxBuffer, uint8_t* buffer, uint16_t size,
158                                                    KeyIdentifier_t keyID, uint32_t* cmac )
159 {
160     SecureElementStatus_t status      = SECURE_ELEMENT_ERROR;
161     uint16_t              localSize   = size;
162     uint8_t*              localbuffer = buffer;
163 
164     if( micBxBuffer != NULL )
165     {
166         uint8_t micBuff[CRYPTO_BUFFER_SIZE];
167 
168         memset1( micBuff, 0, CRYPTO_BUFFER_SIZE );
169 
170         memcpy1( micBuff, micBxBuffer, MIC_BLOCK_BX_SIZE );
171         memcpy1( ( micBuff + MIC_BLOCK_BX_SIZE ), buffer, size );
172         localSize += MIC_BLOCK_BX_SIZE;
173         localbuffer = micBuff;
174     }
175 
176     lr1110_crypto_compute_aes_cmac( &LR1110, ( lr1110_crypto_status_t* ) &status,
177                                     convert_key_id_from_se_to_lr1110( keyID ), localbuffer, localSize,
178                                     ( uint8_t* ) cmac );
179 
180     return status;
181 }
182 
SecureElementVerifyAesCmac(uint8_t * buffer,uint16_t size,uint32_t expectedCmac,KeyIdentifier_t keyID)183 SecureElementStatus_t SecureElementVerifyAesCmac( uint8_t* buffer, uint16_t size, uint32_t expectedCmac,
184                                                   KeyIdentifier_t keyID )
185 {
186     SecureElementStatus_t status = SECURE_ELEMENT_ERROR;
187 
188     if( buffer == NULL )
189     {
190         return SECURE_ELEMENT_ERROR_NPE;
191     }
192 
193     lr1110_crypto_verify_aes_cmac( &LR1110, ( lr1110_crypto_status_t* ) &status,
194                                    convert_key_id_from_se_to_lr1110( keyID ), buffer, size,
195                                    ( uint8_t* ) &expectedCmac );
196 
197     return status;
198 }
199 
SecureElementAesEncrypt(uint8_t * buffer,uint16_t size,KeyIdentifier_t keyID,uint8_t * encBuffer)200 SecureElementStatus_t SecureElementAesEncrypt( uint8_t* buffer, uint16_t size, KeyIdentifier_t keyID,
201                                                uint8_t* encBuffer )
202 {
203     SecureElementStatus_t status = SECURE_ELEMENT_ERROR;
204 
205     if( ( buffer == NULL ) || ( encBuffer == NULL ) )
206     {
207         return SECURE_ELEMENT_ERROR_NPE;
208     }
209 
210     if( keyID < SLOT_RAND_ZERO_KEY )
211     {
212         lr1110_crypto_aes_encrypt_01( &LR1110, ( lr1110_crypto_status_t* ) &status,
213                                     convert_key_id_from_se_to_lr1110( keyID ), buffer, size, encBuffer );
214     }
215     else
216     {
217         lr1110_crypto_aes_encrypt( &LR1110, ( lr1110_crypto_status_t* ) &status,
218                                     convert_key_id_from_se_to_lr1110( keyID ), buffer, size, encBuffer );
219     }
220     return status;
221 }
222 
SecureElementDeriveAndStoreKey(uint8_t * input,KeyIdentifier_t rootKeyID,KeyIdentifier_t targetKeyID)223 SecureElementStatus_t SecureElementDeriveAndStoreKey( uint8_t* input, KeyIdentifier_t rootKeyID,
224                                                       KeyIdentifier_t targetKeyID )
225 {
226     SecureElementStatus_t status = SECURE_ELEMENT_ERROR;
227 
228     if( input == NULL )
229     {
230         return SECURE_ELEMENT_ERROR_NPE;
231     }
232 
233     lr1110_crypto_derive_and_store_key( &LR1110, ( lr1110_crypto_status_t* ) &status,
234                                         convert_key_id_from_se_to_lr1110( rootKeyID ),
235                                         convert_key_id_from_se_to_lr1110( targetKeyID ), input );
236 
237     lr1110_crypto_store_to_flash( &LR1110, ( lr1110_crypto_status_t* ) &status );
238     return status;
239 }
240 
SecureElementProcessJoinAccept(JoinReqIdentifier_t joinReqType,uint8_t * joinEui,uint16_t devNonce,uint8_t * encJoinAccept,uint8_t encJoinAcceptSize,uint8_t * decJoinAccept,uint8_t * versionMinor)241 SecureElementStatus_t SecureElementProcessJoinAccept( JoinReqIdentifier_t joinReqType, uint8_t* joinEui,
242                                                       uint16_t devNonce, uint8_t* encJoinAccept,
243                                                       uint8_t encJoinAcceptSize, uint8_t* decJoinAccept,
244                                                       uint8_t* versionMinor )
245 {
246     SecureElementStatus_t status = SECURE_ELEMENT_ERROR;
247 
248     if( ( encJoinAccept == NULL ) || ( decJoinAccept == NULL ) || ( versionMinor == NULL ) )
249     {
250         return SECURE_ELEMENT_ERROR_NPE;
251     }
252 
253     // Check that frame size isn't bigger than a JoinAccept with CFList size
254     if( encJoinAcceptSize > LORAMAC_JOIN_ACCEPT_FRAME_MAX_SIZE )
255     {
256         return SECURE_ELEMENT_ERROR_BUF_SIZE;
257     }
258 
259     // Determine decryption key
260     KeyIdentifier_t encKeyID = NWK_KEY;
261 
262     if( joinReqType != JOIN_REQ )
263     {
264         encKeyID = J_S_ENC_KEY;
265     }
266 
267     //  - Header buffer to be used for MIC computation
268     //        - LoRaWAN 1.0.x : micHeader = [MHDR(1)]
269     //        - LoRaWAN 1.1.x : micHeader = [JoinReqType(1), JoinEUI(8), DevNonce(2), MHDR(1)]
270 
271     // Try first to process LoRaWAN 1.0.x JoinAccept
272     uint8_t micHeader10[1] = { 0x20 };
273 
274     //   cmac = aes128_cmac(NwkKey, MHDR |  JoinNonce | NetID | DevAddr | DLSettings | RxDelay | CFList |
275     //   CFListType)
276     lr1110_crypto_process_join_accept(
277         &LR1110, ( lr1110_crypto_status_t* ) &status, convert_key_id_from_se_to_lr1110( encKeyID ),
278         convert_key_id_from_se_to_lr1110( NWK_KEY ), ( lr1110_crypto_lorawan_version_t ) 0, micHeader10,
279         encJoinAccept + 1, encJoinAcceptSize - 1, decJoinAccept + 1 );
280 
281     if( status == SECURE_ELEMENT_SUCCESS )
282     {
283         *versionMinor = ( ( decJoinAccept[11] & 0x80 ) == 0x80 ) ? 1 : 0;
284         if( *versionMinor == 0 )
285         {
286             // Network server is operating according to LoRaWAN 1.0.x
287             return SECURE_ELEMENT_SUCCESS;
288         }
289     }
290 
291 #if( USE_LRWAN_1_1_X_CRYPTO == 1 )
292     // 1.0.x trial failed. Trying to process LoRaWAN 1.1.x JoinAccept
293     uint8_t  micHeader11[JOIN_ACCEPT_MIC_COMPUTATION_OFFSET] = { 0 };
294     uint16_t bufItr                                     = 0;
295 
296     //   cmac = aes128_cmac(JSIntKey, JoinReqType | JoinEUI | DevNonce | MHDR | JoinNonce | NetID | DevAddr |
297     //   DLSettings | RxDelay | CFList | CFListType)
298     micHeader11[bufItr++] = ( uint8_t ) joinReqType;
299 
300     memcpyr( micHeader11 + bufItr, joinEui, LORAMAC_JOIN_EUI_FIELD_SIZE );
301     bufItr += LORAMAC_JOIN_EUI_FIELD_SIZE;
302 
303     micHeader11[bufItr++] = devNonce & 0xFF;
304     micHeader11[bufItr++] = ( devNonce >> 8 ) & 0xFF;
305 
306     micHeader11[bufItr++] = 0x20;
307 
308     lr1110_crypto_process_join_accept(
309         &LR1110, ( lr1110_crypto_status_t* ) &status, convert_key_id_from_se_to_lr1110( encKeyID ),
310         convert_key_id_from_se_to_lr1110( J_S_INT_KEY ), ( lr1110_crypto_lorawan_version_t ) 1, micHeader11,
311         encJoinAccept + 1, encJoinAcceptSize - 1, decJoinAccept + 1 );
312 
313     if( status == SECURE_ELEMENT_SUCCESS )
314     {
315         *versionMinor = ( ( decJoinAccept[11] & 0x80 ) == 0x80 ) ? 1 : 0;
316         if( *versionMinor == 1 )
317         {
318             // Network server is operating according to LoRaWAN 1.1.x
319             return SECURE_ELEMENT_SUCCESS;
320         }
321     }
322 #endif
323 
324     return status;
325 }
326 
SecureElementRandomNumber(uint32_t * randomNum)327 SecureElementStatus_t SecureElementRandomNumber( uint32_t* randomNum )
328 {
329     if( randomNum == NULL )
330     {
331         return SECURE_ELEMENT_ERROR_NPE;
332     }
333     *randomNum = LR1110SeHalGetRandomNumber( );
334     return SECURE_ELEMENT_SUCCESS;
335 }
336 
SecureElementSetDevEui(uint8_t * devEui)337 SecureElementStatus_t SecureElementSetDevEui( uint8_t* devEui )
338 {
339     if( devEui == NULL )
340     {
341         return SECURE_ELEMENT_ERROR_NPE;
342     }
343     memcpy1( SeNvm->DevEui, devEui, SE_EUI_SIZE );
344     return SECURE_ELEMENT_SUCCESS;
345 }
346 
SecureElementGetDevEui(void)347 uint8_t* SecureElementGetDevEui( void )
348 {
349     return SeNvm->DevEui;
350 }
351 
SecureElementSetJoinEui(uint8_t * joinEui)352 SecureElementStatus_t SecureElementSetJoinEui( uint8_t* joinEui )
353 {
354     if( joinEui == NULL )
355     {
356         return SECURE_ELEMENT_ERROR_NPE;
357     }
358     memcpy1( SeNvm->JoinEui, joinEui, SE_EUI_SIZE );
359     return SECURE_ELEMENT_SUCCESS;
360 }
361 
SecureElementGetJoinEui(void)362 uint8_t* SecureElementGetJoinEui( void )
363 {
364     return SeNvm->JoinEui;
365 }
366 
SecureElementSetPin(uint8_t * pin)367 SecureElementStatus_t SecureElementSetPin( uint8_t* pin )
368 {
369     if( pin == NULL )
370     {
371         return SECURE_ELEMENT_ERROR_NPE;
372     }
373 
374     memcpy1( SeNvm->Pin, pin, SE_PIN_SIZE );
375     return SECURE_ELEMENT_SUCCESS;
376 }
377 
SecureElementGetPin(void)378 uint8_t* SecureElementGetPin( void )
379 {
380     return SeNvm->Pin;
381 }
382 
convert_key_id_from_se_to_lr1110(KeyIdentifier_t key_id)383 static lr1110_crypto_keys_idx_t convert_key_id_from_se_to_lr1110( KeyIdentifier_t key_id )
384 {
385     lr1110_crypto_keys_idx_t id = LR1110_CRYPTO_KEYS_IDX_GP0;
386 
387     switch( key_id )
388     {
389         case APP_KEY:
390             id = LR1110_CRYPTO_KEYS_IDX_APP_KEY;
391             break;
392         case NWK_KEY:
393             id = LR1110_CRYPTO_KEYS_IDX_NWK_KEY;
394             break;
395         case J_S_INT_KEY:
396             id = LR1110_CRYPTO_KEYS_IDX_J_S_INT_KEY;
397             break;
398         case J_S_ENC_KEY:
399             id = LR1110_CRYPTO_KEYS_IDX_J_S_ENC_KEY;
400             break;
401         case F_NWK_S_INT_KEY:
402             id = LR1110_CRYPTO_KEYS_IDX_F_NWK_S_INT_KEY;
403             break;
404         case S_NWK_S_INT_KEY:
405             id = LR1110_CRYPTO_KEYS_IDX_S_NWK_S_INT_KEY;
406             break;
407         case NWK_S_ENC_KEY:
408             id = LR1110_CRYPTO_KEYS_IDX_NWK_S_ENC_KEY;
409             break;
410         case APP_S_KEY:
411             id = LR1110_CRYPTO_KEYS_IDX_APP_S_KEY;
412             break;
413         case MC_ROOT_KEY:
414             id = LR1110_CRYPTO_KEYS_IDX_GP_KE_KEY_5;
415             break;
416         case MC_KE_KEY:
417             id = LR1110_CRYPTO_KEYS_IDX_GP_KE_KEY_4;
418             break;
419         case MC_KEY_0:
420             id = LR1110_CRYPTO_KEYS_IDX_GP_KE_KEY_0;
421             break;
422         case MC_APP_S_KEY_0:
423             id = LR1110_CRYPTO_KEYS_IDX_MC_APP_S_KEY_0;
424             break;
425         case MC_NWK_S_KEY_0:
426             id = LR1110_CRYPTO_KEYS_IDX_MC_NWK_S_KEY_0;
427             break;
428         case MC_KEY_1:
429             id = LR1110_CRYPTO_KEYS_IDX_GP_KE_KEY_1;
430             break;
431         case MC_APP_S_KEY_1:
432             id = LR1110_CRYPTO_KEYS_IDX_MC_APP_S_KEY_1;
433             break;
434         case MC_NWK_S_KEY_1:
435             id = LR1110_CRYPTO_KEYS_IDX_MC_NWK_S_KEY_1;
436             break;
437         case MC_KEY_2:
438             id = LR1110_CRYPTO_KEYS_IDX_GP_KE_KEY_2;
439             break;
440         case MC_APP_S_KEY_2:
441             id = LR1110_CRYPTO_KEYS_IDX_MC_APP_S_KEY_2;
442             break;
443         case MC_NWK_S_KEY_2:
444             id = LR1110_CRYPTO_KEYS_IDX_MC_NWK_S_KEY_2;
445             break;
446         case MC_KEY_3:
447             id = LR1110_CRYPTO_KEYS_IDX_GP_KE_KEY_3;
448             break;
449         case MC_APP_S_KEY_3:
450             id = LR1110_CRYPTO_KEYS_IDX_MC_APP_S_KEY_3;
451             break;
452         case MC_NWK_S_KEY_3:
453             id = LR1110_CRYPTO_KEYS_IDX_MC_NWK_S_KEY_3;
454             break;
455         case SLOT_RAND_ZERO_KEY:
456             id = LR1110_CRYPTO_KEYS_IDX_GP0;
457             break;
458         default:
459             id = LR1110_CRYPTO_KEYS_IDX_GP1;
460             break;
461     }
462     return id;
463 }
464