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