1 /**
2 ******************************************************************************
3 * @file se_psa.c
4 * @author MCD Application Team
5 * @version V1.0.0
6 * @brief Implementation file of psa_drv_se interface.
7 ******************************************************************************
8 * @attention
9 *
10 * Copyright (c) 2021 STMicroelectronics.
11 * All rights reserved.
12 *
13 * This software is licensed under terms that can be found in the LICENSE file
14 * in the root directory of this software component.
15 * If no LICENSE file comes with this software, it is provided AS-IS.
16 *
17 ******************************************************************************
18 */
19
20 #if defined(PSA_USE_SE_ST)
21
22 /* Includes ------------------------------------------------------------------*/
23 #include "tfm_mbedcrypto_include.h"
24 #include "se_psa.h"
25 #include "stsafea_service_stub.h"
26 #include "stdarg.h"
27 #include "stdio.h"
28 #include "string.h"
29 #include "psa_manifest/pid.h"
30 #include "tfm_nspm.h"
31 #include "tfm_spm_log.h"
32 #include "tfm_plat_defs.h"
33 #include "tfm_plat_crypto_keys.h"
34
35 /* Private typedef -----------------------------------------------------------*/
36 typedef struct
37 {
38 uint32_t map_size;
39 } SE_psa_drv_se_persistent_t;
40
41
42 #define SE_ST_MAX_INPUT_SIZE 488 /* data to be shared by user is */
43
44 /* Transient context command status */
45 #define SE_ST_CMD_NOT_INIT 0
46 #define SE_ST_CMD_READY 1
47 #define SE_ST_CMD_EXECUTED 2
48
49 typedef struct
50 {
51 uint8_t cmd;
52 uint16_t size;
53 uint8_t buffer[SE_ST_MAX_INPUT_SIZE];
54 uint8_t status;
55 } psa_se_st_transient_ctx_t;
56
57 psa_se_st_transient_ctx_t se_st_t_ctx;
58
59 /* Private define ------------------------------------------------------------*/
60 /* Private macro -------------------------------------------------------------*/
61 #define SE_ST_PSA_PRINT debug_print
62 /* Private struct ------------------------------------------------------------*/
63 /* Private variables ---------------------------------------------------------*/
64 /* Private function prototypes -----------------------------------------------*/
65 static psa_status_t register_se_keys(void);
66 //#define TOP_CHECK_KEY
67 int32_t debug_print(char const *fmt, ...);
68 psa_status_t se_st_to_psa_error(int32_t ret);
69 /**
70 * @brief debug_print
71 * psa trace function for SE PSA traces.
72 *
73 * @param fmt : char string to format output
74 * @retval return value from tfm_hal_output_spm_log
75 */
debug_print(char const * fmt,...)76 int32_t debug_print(char const *fmt, ...)
77 {
78 int32_t len;
79 va_list args;
80 va_start(args, fmt);
81 char trace_buf[500];
82
83 len = vsnprintf(trace_buf, sizeof(trace_buf), fmt, args);
84 SPMLOG_DBGMSG(trace_buf);
85 return 0;
86 }
87
88 /**
89 * @brief se_st_to_psa_error
90 * translate error code to psa_status_t
91 *
92 * @param ret[in] : int32_t error code
93 * @retval psa_status_t translation
94 */
se_st_to_psa_error(int32_t ret)95 psa_status_t se_st_to_psa_error(int32_t ret)
96 {
97 switch (ret)
98 {
99 case 0:
100 return PSA_SUCCESS;
101 default:
102 return PSA_ERROR_HARDWARE_FAILURE;
103 }
104 }
105
106
107 /**
108 * @brief register a key in its operational domain(s)
109 *
110 * @param key[in] : Identifier of the key to use for the operation.
111 * @param attr[in] : The attributes for the key.
112 *
113 * @retval #PSA_SUCCESS
114 * A key slot is created.
115 */
register_key_in_all_domain(mbedtls_svc_key_id_t key,psa_key_attributes_t * attr)116 static psa_status_t register_key_in_all_domain(mbedtls_svc_key_id_t key,
117 psa_key_attributes_t *attr) {
118 psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
119
120
121 psa_key_handle_t key_handle;
122
123
124 /* check if keys are present */
125 SE_ST_PSA_PRINT("checking key existance %x\n", key.MBEDTLS_PRIVATE(key_id));
126 psa_status = psa_open_key(key, &key_handle);
127 if (psa_status != PSA_SUCCESS)
128 {
129 psa_set_key_id(attr, key);
130 SE_ST_PSA_PRINT("Registering key : ");
131 psa_status = mbedtls_psa_register_se_key(attr);
132 if (psa_status != PSA_SUCCESS) {
133 SE_ST_PSA_PRINT("KO %d\n", psa_status);
134 goto exit;
135 }
136 SE_ST_PSA_PRINT("OK\n");
137 }
138 else
139 {
140 psa_close_key(key_handle);
141 psa_status = PSA_SUCCESS;
142 }
143
144 exit:
145
146 return psa_status;
147 }
148
149 /**
150 * @brief register a function key with its corresponding attributes.
151 * This type of key is not physically in the Secure Element but
152 * represents the structure of physical element(s).
153 *
154 * @param key[in] : Identifier of the key to use for the operation.
155 * @param attr[in] : The attributes for the key.
156 *
157 * @retval #PSA_SUCCESS
158 * Key is imported and usable.
159 * Its usage can be from all applications but also extended to
160 * specific partition(s).
161 */
register_function_key(psa_key_id_t key_id,psa_key_attributes_t * attr)162 static psa_status_t register_function_key(psa_key_id_t key_id,
163 psa_key_attributes_t *attr)
164 {
165 mbedtls_svc_key_id_t mbedtls_id = {0,tfm_nspm_get_current_client_id()};
166 /* attribute for function keys */
167 psa_set_key_bits(attr, 8); /* logical asset */
168 psa_set_key_lifetime(attr, PSA_SE_ST_LIFETIME_READ_ONLY);
169 psa_set_key_usage_flags(attr, PSA_KEY_USAGE_EXPORT);
170 psa_set_key_type(attr, PSA_KEY_TYPE_RAW_DATA);
171
172 mbedtls_id.MBEDTLS_PRIVATE(key_id) = key_id,
173
174 psa_set_key_slot_number(attr, PSA_ID_TO_SE_ST_ID(key_id));
175
176 return register_key_in_all_domain(mbedtls_id, attr);
177 }
178
179 /**
180 * @brief register a function key to deal with the unique serial number
181 * identifier of in the Secure Element.
182 *
183 * @retval #PSA_SUCCESS
184 * Key is created.
185 */
register_se_serial_number_key(void)186 static psa_status_t register_se_serial_number_key(void)
187 {
188 psa_key_attributes_t attributes = psa_key_attributes_init();
189
190 return register_function_key( SE_ST_ID_TO_PSA_ID(SE_ST_SERIAL_NUMBER),
191 &attributes);
192 }
193
194 /**
195 * @brief register a key set of the Secure Element
196 *
197 * @retval #PSA_SUCCESS
198 * Key set is created and subcribed in the TFM.
199 */
register_se_keys(void)200 static psa_status_t register_se_keys(void)
201 {
202 psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
203
204 /* check if keys are present */
205 #ifdef TOP_CHECK_KEY
206 mbedtls_svc_key_id_t key_id = {0,tfm_nspm_get_current_client_id()};
207 psa_key_handle_t key_handle;
208
209 key_id.MBEDTLS_PRIVATE(key_id) = SE_ST_ID_TO_PSA_ID(SE_ST_SERIAL_NUMBER);
210 psa_status = psa_open_key(key_id, &key_handle);
211 if (psa_status != PSA_SUCCESS)
212 {
213 #endif
214 if ((psa_status = register_se_serial_number_key()) != PSA_SUCCESS)
215 return psa_status;
216 #ifdef TOP_CHECK_KEY
217 }
218 #endif
219 return psa_status;
220 }
221
222 /**
223 * @brief psa_se_st_init
224 * Init of PSA drv SE
225 * @note Start Low Level HW for SE
226 *
227 * @param drv_context : psa_drv_se_context_t structure to keep persistent data and transient data
228 * @param persistent_data : init data provided by psa drv se mechanism.
229 * @param location : location of the init call
230 * @retval PSA_SUCCESS if success, an error code otherwise
231 */
232
psa_se_st_init(psa_drv_se_context_t * drv_context,void * persistent_data,psa_key_location_t location)233 static psa_status_t psa_se_st_init(psa_drv_se_context_t *drv_context,
234 void *persistent_data,
235 psa_key_location_t location)
236 {
237 /* Not used by SE_API */
238 if (drv_context == NULL)
239 {
240
241 return PSA_ERROR_INVALID_ARGUMENT;
242 }
243 memset(&se_st_t_ctx, 0, sizeof(se_st_t_ctx));
244 drv_context->MBEDTLS_PRIVATE(transient_data) = (uintptr_t)&se_st_t_ctx;
245
246 BSP_I2C_Init();
247 HW_IO_Init();
248 /* check PSA key location */
249 if (location != PSA_SE_ST_LOCATION)
250 {
251 SE_ST_PSA_PRINT("Invalid driver\n");
252
253 return PSA_ERROR_GENERIC_ERROR;
254 }
255
256 SE_ST_PSA_PRINT("Secure Element driver initialized\n");
257 /* register keys */
258 return register_se_keys();
259 }
260
261 /**
262 * @brief psa_se_st_validate_slot_number_fct
263 * Validate slot number for psa drv se according to key attributes
264 *
265 * @param drv_context : psa_drv_se_context_t structure to keep persistent data and transient data
266 * @param persistent_data : init data provided by psa drv se mechanism.
267 * @param attributes : key attributes to map on SE ressources
268 * @param method : key creation context supported values
269 * PSA_KEY_CREATION_REGISTER : persistent key declaration
270 * @param key_slot : internal key index
271 * @retval PSA_SUCCESS if success, an error code otherwise
272 */
psa_se_st_validate_slot_number_fct(psa_drv_se_context_t * drv_context,void * persistent_data,const psa_key_attributes_t * attributes,psa_key_creation_method_t method,psa_key_slot_number_t key_slot)273 static psa_status_t psa_se_st_validate_slot_number_fct(
274 psa_drv_se_context_t *drv_context,
275 void *persistent_data,
276 const psa_key_attributes_t *attributes,
277 psa_key_creation_method_t method,
278 psa_key_slot_number_t key_slot)
279 {
280 psa_key_type_t type = psa_get_key_type(attributes);
281
282 /* support registration and import only for memory region */
283 if (method != PSA_KEY_CREATION_REGISTER)
284 {
285 SE_ST_PSA_PRINT("Key slot validation cannot operate with method : %x\n", method);
286
287 return PSA_ERROR_NOT_SUPPORTED;
288 }
289 /* if type = PSA_KEY_TYPE_RAW_DATA check if SE_ST_SERIAL_NUMBER */
290 if (type == PSA_KEY_TYPE_RAW_DATA)
291 {
292 if (key_slot != SE_ST_SERIAL_NUMBER)
293 {
294 return PSA_ERROR_INVALID_ARGUMENT;
295 }
296 }
297 else
298 {
299 return PSA_ERROR_INVALID_ARGUMENT;
300 }
301
302 /* if already exists do not return error */
303
304 return PSA_SUCCESS;
305 }
306
307 /**
308 * @brief psa_se_st_export_public_fct
309 *
310 * @note Not implemented
311 *
312 * @param drv_context
313 * @param key
314 * @param p_data
315 * @param data_size
316 * @param p_data_length
317 * @retval PSA_ERROR_NOT_SUPPORTED
318 */
psa_se_st_export_public_fct(psa_drv_se_context_t * drv_context,psa_key_slot_number_t key,uint8_t * p_data,size_t data_size,size_t * p_data_length)319 static psa_status_t psa_se_st_export_public_fct(psa_drv_se_context_t *drv_context,
320 psa_key_slot_number_t key,
321 uint8_t *p_data,
322 size_t data_size,
323 size_t *p_data_length)
324 {
325 return PSA_ERROR_NOT_SUPPORTED;
326 }
327
328
329 /**
330 * @brief psa_se_st_gen_key_fct
331 *
332 * @note Not implemented
333 *
334 * @param drv_context
335 * @param key_slot
336 * @param attributes
337 * @param pubkey
338 * @param pubkey_size
339 * @param pubkey_length
340 * @retval PSA_ERROR_NOT_SUPPORTED
341 */
psa_se_st_gen_key_fct(psa_drv_se_context_t * drv_context,psa_key_slot_number_t key_slot,const psa_key_attributes_t * attributes,uint8_t * pubkey,size_t pubkey_size,size_t * pubkey_length)342 static psa_status_t psa_se_st_gen_key_fct(
343 psa_drv_se_context_t *drv_context,
344 psa_key_slot_number_t key_slot,
345 const psa_key_attributes_t *attributes,
346 uint8_t *pubkey, size_t pubkey_size, size_t *pubkey_length)
347 {
348 return PSA_ERROR_NOT_SUPPORTED;
349 }
350
351 /**
352 * @brief psa_se_st_import_fct
353 *
354 * @note PSA_ERROR_NOT_SUPPORTED
355 *
356 * @param drv_context
357 * @param key_slot
358 * @param attributes
359 * @param data
360 * @param data_length
361 * @param bits
362 * @retval PSA_ERROR_NOT_SUPPORTED
363 */
psa_se_st_import(psa_drv_se_context_t * drv_context,psa_key_slot_number_t key_slot,const psa_key_attributes_t * attributes,const uint8_t * data,size_t data_length,size_t * bits)364 static psa_status_t psa_se_st_import(
365 psa_drv_se_context_t *drv_context,
366 psa_key_slot_number_t key_slot,
367 const psa_key_attributes_t *attributes,
368 const uint8_t *data,
369 size_t data_length,
370 size_t *bits)
371 {
372 return PSA_ERROR_NOT_SUPPORTED;
373 }
374
byte2char(uint8_t b,uint8_t * c)375 static void byte2char(uint8_t b, uint8_t *c)
376 {
377 uint8_t d = b >> 4;
378 if (d < 10)
379 *c = '0' + d;
380 else
381 *c = 'A' + d - 10;
382 c++;
383 d = b & 0xF;
384 if (d < 10)
385 *c = '0' + d;
386 else
387 *c = 'A' + d - 10;
388 }
389
psa_se_st_get_serial(uint8_t * data,size_t data_size,size_t * p_data_length)390 static psa_status_t psa_se_st_get_serial(uint8_t *data, size_t data_size, size_t *p_data_length)
391 {
392 uint8_t sn_data[] = { 0x14, 0x11, 0xFC, 0xBE };
393 uint8_t r_data[100];
394 uint8_t *sn = &r_data[10];
395 int32_t ret = 0;
396 if (data_size < 9)
397 {
398 SE_ST_PSA_PRINT("Serial Number cannot be set in a buffer of size : %d\n", data_size);
399
400 return PSA_ERROR_BUFFER_TOO_SMALL;
401 }
402
403 ret = BSP_I2C_Send(0x40, sn_data, 4);
404 if (ret == 0)
405 {
406 BSP_TimeDelay(5);
407 ret = BSP_I2C_Recv(0x40, r_data, 69);
408 }
409 if (ret != 0)
410 {
411 return PSA_ERROR_HARDWARE_FAILURE;
412 }
413
414 if (data_size >= 19)
415 {
416 for (int i = 0; i < 9; i++)
417 {
418 byte2char(sn[i], &data[2*i]);
419 }
420 data[18] = '\0';
421 if (p_data_length != NULL)
422 {
423 *p_data_length = 19;
424 }
425 }
426 else
427 {
428 for (int i = 0; i < 9; i++)
429 data[i] = sn[i];
430 if (p_data_length != NULL)
431 {
432 *p_data_length = 9;
433 }
434 }
435 if (ret != 0)
436 {
437 SE_ST_PSA_PRINT("Serial Number cannot be recovered\n");
438
439 return PSA_ERROR_HARDWARE_FAILURE;
440 }
441
442 return PSA_SUCCESS;
443 }
444
445 /**
446 * @brief psa_se_st_export_fct
447 * export serial number from SE
448 * @note
449 *
450 * @param drv_context : psa_drv_se_context_t structure to keep persistent data and transient data
451 * @param key_slot : internal key index
452 * @param attributes : key attributes for the memory region
453 * @param data : data buffer to write SE Serial Number
454 * @param data_size : requested size of data to export
455 * @param p_data_length : actual size of exported data
456 * @retval PSA_SUCCESS if success, an error code otherwise
457 */
psa_se_st_export(psa_drv_se_context_t * drv_context,psa_key_slot_number_t key,uint8_t * data,size_t data_size,size_t * p_data_length)458 static psa_status_t psa_se_st_export(psa_drv_se_context_t *drv_context,
459 psa_key_slot_number_t key,
460 uint8_t *data,
461 size_t data_size,
462 size_t *p_data_length)
463 {
464 const uint16_t slot = key;
465
466 switch (slot)
467 {
468 case SE_ST_SERIAL_NUMBER :
469 {
470 return psa_se_st_get_serial(data, data_size, p_data_length);
471 }
472 default:
473 return PSA_ERROR_NOT_SUPPORTED;
474 }
475
476 }
477
478 /**
479 * @brief psa_se_st_allocate_key
480 *
481 *
482 * @param drv_context
483 * @param persistent_data
484 * @param attributes
485 * @param method
486 * @param key_slot
487 * @retval PSA_ERROR_NOT_SUPPORTED
488 */
psa_se_st_allocate_key(psa_drv_se_context_t * drv_context,void * persistent_data,const psa_key_attributes_t * attributes,psa_key_creation_method_t method,psa_key_slot_number_t * key_slot)489 static psa_status_t psa_se_st_allocate_key(
490 psa_drv_se_context_t *drv_context,
491 void *persistent_data,
492 const psa_key_attributes_t *attributes,
493 psa_key_creation_method_t method,
494 psa_key_slot_number_t *key_slot)
495 {
496 return PSA_ERROR_NOT_SUPPORTED;
497 }
498
499
500 /**
501 * @brief psa_se_st_destroy_key
502 * key deallocation of SE ressources
503 *
504 * @param drv_context : psa_drv_se_context_t structure to keep persistent data and transient data
505 * @param persistent_data : updatable persistent data for psa drv se
506 * @param key_slot : internal key slot to free
507 * @retval PSA_SUCCESS if success, an error code otherwise
508 */
psa_se_st_destroy_key(psa_drv_se_context_t * drv_context,void * persistent_data,psa_key_slot_number_t key_slot)509 static psa_status_t psa_se_st_destroy_key(
510 psa_drv_se_context_t *drv_context,
511 void *persistent_data,
512 psa_key_slot_number_t key_slot)
513 {
514 return PSA_SUCCESS;
515 }
516
517
518
519 /**
520 * @brief psa_se_st_sign_fct
521 *
522 * @param drv_context
523 * @param key_slot
524 * @param alg
525 * @param p_hash
526 * @param hash_length
527 * @param p_signature
528 * @param signature_size
529 * @param p_signature_length
530 * @retval PSA_ERROR_NOT_SUPPORTED
531 */
psa_se_st_sign_fct(psa_drv_se_context_t * drv_context,psa_key_slot_number_t key_slot,psa_algorithm_t alg,const uint8_t * p_hash,size_t hash_length,uint8_t * p_signature,size_t signature_size,size_t * p_signature_length)532 static psa_status_t psa_se_st_sign_fct(psa_drv_se_context_t *drv_context,
533 psa_key_slot_number_t key_slot,
534 psa_algorithm_t alg,
535 const uint8_t *p_hash,
536 size_t hash_length,
537 uint8_t *p_signature,
538 size_t signature_size,
539 size_t *p_signature_length)
540 {
541 return PSA_ERROR_NOT_SUPPORTED;
542 }
543
544 /**
545 * @brief psa_se_st_verify_fct
546 * Asymmetric signature verification
547 * @note not implemented yet
548 *
549 * @param drv_context : psa_drv_se_context_t structure to keep persistent data and transient data
550 * @param key_slot : internal key slot
551 * @param alg : expected signature scheme (only PSA_ALG_ECDSA() supported)
552 * @param p_hash : hash buffer
553 * @param hash_length : size of hash buffer
554 * @param p_signature : signature buffer for RAW R and S output
555 * @param signature_size : size of signature buffer
556 * @param p_signature_length : actual size of outputed signature
557 * @retval PSA_SUCCESS if success, an error code otherwise
558 */
psa_se_st_verify_fct(psa_drv_se_context_t * drv_context,psa_key_slot_number_t key_slot,psa_algorithm_t alg,const uint8_t * p_hash,size_t hash_length,const uint8_t * p_signature,size_t signature_length)559 static psa_status_t psa_se_st_verify_fct(psa_drv_se_context_t *drv_context,
560 psa_key_slot_number_t key_slot,
561 psa_algorithm_t alg,
562 const uint8_t *p_hash,
563 size_t hash_length,
564 const uint8_t *p_signature,
565 size_t signature_length)
566 {
567 return PSA_SUCCESS;
568 }
569
570
571
572 psa_drv_se_key_management_t psa_se_st_key_management_fct =
573 {
574 /* first step to allocate a new private key */
575 .MBEDTLS_PRIVATE(p_allocate) = psa_se_st_allocate_key,
576 .MBEDTLS_PRIVATE(p_destroy) = psa_se_st_destroy_key,
577 /* use to address memory region read */
578 .MBEDTLS_PRIVATE(p_export) = psa_se_st_export,
579 /* export public key for the 3 first sectors */
580 .MBEDTLS_PRIVATE(p_export_public) = psa_se_st_export_public_fct,
581 /* not use for ECDHE as not implemented yet by MbedCrypto */
582 .MBEDTLS_PRIVATE(p_generate) = psa_se_st_gen_key_fct,
583 /* use to address memory region update */
584 .MBEDTLS_PRIVATE(p_import) = psa_se_st_import,
585 /* use to validate the pre provisionned key */
586 .MBEDTLS_PRIVATE(p_validate_slot_number) = psa_se_st_validate_slot_number_fct,
587 };
588
589
590 psa_drv_se_key_derivation_t psa_se_st_derivation_fct =
591 {
592 .MBEDTLS_PRIVATE(p_derive) = NULL,
593 .MBEDTLS_PRIVATE(context_size) = 0,
594 .MBEDTLS_PRIVATE(p_collateral) = NULL,
595 .MBEDTLS_PRIVATE(p_export) = NULL,
596 .MBEDTLS_PRIVATE(p_setup) = NULL,
597 };
598
599 psa_drv_se_asymmetric_t psa_se_st_asymmetric_fct =
600 {
601 .MBEDTLS_PRIVATE(p_decrypt) = NULL,
602 .MBEDTLS_PRIVATE(p_encrypt) = NULL,
603 .MBEDTLS_PRIVATE(p_sign) = psa_se_st_sign_fct,
604 .MBEDTLS_PRIVATE(p_verify) = psa_se_st_verify_fct,
605 };
606
607 const psa_drv_se_t psa_se_st =
608 {
609 .MBEDTLS_PRIVATE(hal_version) = PSA_DRV_SE_HAL_VERSION,
610 .MBEDTLS_PRIVATE(aead) = NULL,
611 .MBEDTLS_PRIVATE(asymmetric) = &psa_se_st_asymmetric_fct,
612 .MBEDTLS_PRIVATE(cipher) = NULL,
613 .MBEDTLS_PRIVATE(derivation) = &psa_se_st_derivation_fct,
614 .MBEDTLS_PRIVATE(key_management) = &psa_se_st_key_management_fct,
615 .MBEDTLS_PRIVATE(mac) = NULL,
616 .MBEDTLS_PRIVATE(persistent_data_size) = sizeof(SE_psa_drv_se_persistent_t),
617 .MBEDTLS_PRIVATE(p_init) = psa_se_st_init,
618 };
se_st_engine_init(void)619 int se_st_engine_init(void)
620 {
621 if (psa_register_se_driver(PSA_SE_ST_LOCATION, &psa_se_st) !=PSA_SUCCESS)
622 {
623 return -1;
624 }
625 return 0;
626 }
627 #endif /* PSA_USE_SE_ST */
628
629