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