1 /*
2  * Copyright (c) 2024, Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 /**
8  * \note This source file is derivative work of psa_crypto.c from the Mbed TLS project
9  */
10 #include <assert.h>
11 #include <string.h>
12 #include <stdbool.h>
13 
14 #include "common.h"
15 #include "psa/crypto.h"
16 #include "psa_crypto_driver_wrappers.h"
17 #include "psa_crypto_driver_wrappers_no_static.h"
18 #ifdef MCUBOOT_BUILTIN_KEY
19 #include "tfm_plat_crypto_keys.h"
20 #include "tfm_plat_otp.h"
21 #endif /* MCUBOOT_BUILTIN_KEY */
22 
23 /* For mbedtls_psa_ecdsa_verify_hash() */
24 #include "psa_crypto_ecp.h"
25 
26 /* A few Mbed TLS definitions */
27 #include "mbedtls/entropy.h"
28 #include "mbedtls/ecp.h"
29 
30 /* Definitions required for the MCUBOOT_BUILTIN_KEY case */
31 #if defined(MCUBOOT_BUILTIN_KEY)
32 #define MCUBOOT_BUILTIN_KEY_ID_MIN   (0x1)
33 #define MCUBOOT_BUILTIN_KEY_ID_MAX   (MCUBOOT_IMAGE_NUMBER)
34 #if defined(MCUBOOT_SIGN_EC256)
35 #define PUBKEY_DATA_SIZE             (65)
36 #define PUBKEY_BUF_SIZE              (68) /* Must be aligned to 4 Bytes */
37 #elif defined(MCUBOOT_SIGN_EC384)
38 #define PUBKEY_DATA_SIZE             (97)
39 #define PUBKEY_BUF_SIZE              (100) /* Must be aligned to 4 Bytes */
40 #endif /* MCUBOOT_SIGN_EC256 */
41 #endif /* MCUBOOT_BUILTIN_KEY */
42 
43 /**
44  * @note MCUboot uses the keys by importing them after parsing and then using
45  *       them right away in the following call, so it makes sense to avoid a copy
46  *       of data and just directly use the pointer to key material from the
47  *       caller. The psa_import_key() call does not cross any security boundary.
48  */
49 
50 /**
51  * @brief A structure describing the contents of a thin key slot, which
52  *        holds key material and metadata following a psa_import_key() call
53  */
54 struct thin_key_slot_s {
55     const uint8_t *buf;        /*!< Pointer to the buffer holding the key material */
56     size_t len;                /*!< Size in bytes of the \a buf buffer */
57     psa_key_attributes_t attr; /*!< Attributes of the key */
58     psa_key_id_t key_id;       /*!< Key ID assigned to the key */
59     bool is_valid;             /*!< Boolean value, true if the key material is valid */
60 };
61 
62 #if defined(MCUBOOT_BUILTIN_KEY)
63 /**
64  * @brief Static local buffer that holds enough data for the key material
65  *        provisioned bundle to be retrieved from the platform
66  */
67 static uint8_t g_pubkey_data[PUBKEY_BUF_SIZE];
68 #endif /* MCUBOOT_BUILTIN_KEY */
69 
70 /**
71  * @brief This static global variable holds the key slot. The thin PSA Crypto core
72  *        supports only a single key to be imported at any given time. Importing a
73  *        new key will just cause the existing key to be forgotten
74  */
75 static struct thin_key_slot_s g_key_slot =  {
76 #if !defined(MCUBOOT_BUILTIN_KEY)
77     .buf = NULL,
78     .len = 0,
79     .attr = PSA_KEY_ATTRIBUTES_INIT,
80     .key_id = PSA_KEY_ID_NULL,
81     .is_valid = false,
82 #else
83     .buf  = g_pubkey_data,
84     .len  = sizeof(g_pubkey_data),
85     .attr = PSA_KEY_ATTRIBUTES_INIT,
86     /* .key_id   - not used
87      * .is_valid - not used
88      */
89 #endif /* !MCUBOOT_BUILTIN_KEY */
90 };
91 
92 /**
93  * @brief Context required by the RNG function, mocked
94  *
95  */
96 static mbedtls_psa_external_random_context_t *g_ctx = NULL;
97 
98 #if defined(MCUBOOT_BUILTIN_KEY)
get_builtin_public_key(psa_key_id_t key_id,psa_algorithm_t alg)99 static psa_status_t get_builtin_public_key(psa_key_id_t key_id,
100                                            psa_algorithm_t alg)
101 {
102     enum tfm_plat_err_t plat_err;
103 
104     /* Decrease key ID by MCUBOOT_BUILTIN_KEY_ID_MIN as zero (PSA_KEY_ID_NULL)
105      * is reserved and considered invalid.
106      */
107     plat_err = tfm_plat_otp_read(
108             (PLAT_OTP_ID_BL2_ROTPK_0 + (key_id - MCUBOOT_BUILTIN_KEY_ID_MIN)),
109             PUBKEY_BUF_SIZE,
110             g_pubkey_data);
111     if (plat_err == TFM_PLAT_ERR_SUCCESS) {
112         g_key_slot.len = PUBKEY_DATA_SIZE;
113     } else {
114         return PSA_ERROR_GENERIC_ERROR;
115     }
116 
117     psa_set_key_usage_flags(&g_key_slot.attr, PSA_KEY_USAGE_VERIFY_HASH);
118     psa_set_key_algorithm(&g_key_slot.attr, alg);
119     psa_set_key_type(&g_key_slot.attr,
120                      PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1));
121     psa_set_key_bits(&g_key_slot.attr,
122                      PSA_BYTES_TO_BITS((g_key_slot.len - 1)/2));
123 
124     return PSA_SUCCESS;
125 }
126 #endif /* MCUBOOT_BUILTIN_KEY */
127 
psa_crypto_init(void)128 psa_status_t psa_crypto_init(void)
129 {
130     psa_status_t status = psa_driver_wrapper_init();
131 
132     /* This will have to perform RNG/DRBG init in case that will be ever required by
133      * any API
134      */
135     return status;
136 }
137 
psa_hash_abort(psa_hash_operation_t * operation)138 psa_status_t psa_hash_abort(psa_hash_operation_t *operation)
139 {
140     /* Aborting a non-active operation is allowed */
141     if (operation->id == 0) {
142         return PSA_SUCCESS;
143     }
144 
145     psa_status_t status = psa_driver_wrapper_hash_abort(operation);
146 
147     operation->id = 0;
148 
149     return status;
150 }
151 
psa_hash_setup(psa_hash_operation_t * operation,psa_algorithm_t alg)152 psa_status_t psa_hash_setup(psa_hash_operation_t *operation,
153                             psa_algorithm_t alg)
154 {
155     psa_status_t status;
156 
157     /* A context must be freshly initialized before it can be set up. */
158     assert(operation->id == 0);
159     assert(PSA_ALG_IS_HASH(alg));
160 
161     /* Ensure all of the context is zeroized, since PSA_HASH_OPERATION_INIT only
162      * directly zeroes the int-sized dummy member of the context union.
163      */
164     memset(&operation->ctx, 0, sizeof(operation->ctx));
165 
166     status = psa_driver_wrapper_hash_setup(operation, alg);
167 
168     if (status != PSA_SUCCESS) {
169         psa_hash_abort(operation);
170     }
171 
172     return status;
173 }
174 
psa_hash_update(psa_hash_operation_t * operation,const uint8_t * input,size_t input_length)175 psa_status_t psa_hash_update(psa_hash_operation_t *operation,
176                              const uint8_t *input,
177                              size_t input_length)
178 {
179     psa_status_t status;
180 
181     assert(operation->id != 0);
182 
183     /* Don't require hash implementations to behave correctly on a
184      * zero-length input, which may have an invalid pointer.
185      */
186     if (input_length == 0) {
187         return PSA_SUCCESS;
188     }
189 
190     status = psa_driver_wrapper_hash_update(operation, input, input_length);
191 
192     if (status != PSA_SUCCESS) {
193         psa_hash_abort(operation);
194     }
195 
196     return status;
197 }
198 
psa_hash_finish(psa_hash_operation_t * operation,uint8_t * hash,size_t hash_size,size_t * hash_length)199 psa_status_t psa_hash_finish(psa_hash_operation_t *operation,
200                              uint8_t *hash,
201                              size_t hash_size,
202                              size_t *hash_length)
203 {
204     *hash_length = 0;
205     assert(operation->id != 0);
206 
207     psa_status_t status = psa_driver_wrapper_hash_finish(
208         operation, hash, hash_size, hash_length);
209     psa_hash_abort(operation);
210     return status;
211 }
212 
213 #if !defined(MCUBOOT_BUILTIN_KEY)
214 /**
215  * The key management subsystem is simplified to support only the BL2 required
216  * use case for signature verification either with RSA or ECDSA. MCUboot key
217  * bundles can be encoded in the SubjectPublicKeyInfo format (RFC 5480):
218  *
219  * SubjectPublicKeyInfo  ::= SEQUENCE  {
220  *     algorithm            AlgorithmIdentifier,
221  *     subjectPublicKey     BIT STRING
222  * }
223  *
224  * where, for RSA, the subjectPublicKey is either specified in RFC 3447 (PKCS#1v2.1)
225  * or the newest RFC 8017 (PKCS#1v2.2) using RSAPublicKey:
226  *
227  * RSAPublicKey ::= SEQUENCE {
228  *     modulus           INTEGER,  -- n
229  *     publicExponent    INTEGER   -- e
230  * }
231  *
232  * or for ECDSA is specified in RFC 5480 itself as ECPoint ::= OCTET STRING
233  *
234  * For ECDSA, MCUboot passes the uncompressed format (i.e. 0x04 X Y), i.e. the
235  * key encoding is parsed by MCUboot itself before being imported. For RSA, the
236  * AlgorithmIdentifier is instead specified in RFC 3279 as the value of the OID
237  * rsaEncryption: 1.2.840.113549.1.1.1, but MCUboot chooses in this case to
238  * pass already the RSAPublicKey structure to the APIs, hence the code below just
239  * understands the length of n by inspecting the fields of the ASN.1 encoding
240  *
241  */
psa_import_key(const psa_key_attributes_t * attributes,const uint8_t * data,size_t data_length,psa_key_id_t * key)242 psa_status_t psa_import_key(const psa_key_attributes_t *attributes,
243                             const uint8_t *data,
244                             size_t data_length,
245                             psa_key_id_t *key)
246 {
247 #if defined(MCUBOOT_SIGN_RSA)
248     /* This is either a 2048, 3072 or 4096 bit RSA key, hence the TLV must place
249      * the length at index (6,7) with a leading 0x00. The leading 0x00 is due to
250      * the fact that the MSB will always be set for RSA keys where the length is
251      * a multiple of 8 bits.
252      */
253     const size_t bits =
254         PSA_BYTES_TO_BITS((((uint16_t)data[6]) << 8) | (uint16_t)data[7]) - 8;
255 
256 #elif defined(MCUBOOT_SIGN_EC256) || defined(MCUBOOT_SIGN_EC384)
257     /* The public key is expected in uncompressed format, i.e. 0x04 X Y
258      * for 256 or 384 bit lengths, and the driver wrappers expect to receive
259      * it in that format
260      */
261     assert(data[0] == 0x04);
262     const size_t bits = PSA_BYTES_TO_BITS((data_length - 1)/2);
263 #endif
264 
265     g_key_slot.buf = data;
266     g_key_slot.len = data_length;
267 
268     memcpy(&g_key_slot.attr, attributes, sizeof(psa_key_attributes_t));
269     g_key_slot.attr.bits = (psa_key_bits_t)bits;
270 
271     /* This signals that a new key has been imported */
272     *key = (++g_key_slot.key_id);
273 
274     g_key_slot.is_valid = true;
275 
276     return PSA_SUCCESS;
277 }
278 
psa_get_key_attributes(psa_key_id_t key,psa_key_attributes_t * attributes)279 psa_status_t psa_get_key_attributes(psa_key_id_t key,
280                                     psa_key_attributes_t *attributes)
281 {
282     assert(g_key_slot.is_valid && (g_key_slot.key_id == key));
283     memcpy(attributes, &g_key_slot.attr, sizeof(psa_key_attributes_t));
284     return PSA_SUCCESS;
285 }
286 #endif /* !MCUBOOT_BUILTIN_KEY */
287 
psa_destroy_key(psa_key_id_t key)288 psa_status_t psa_destroy_key(psa_key_id_t key)
289 {
290 #if !defined(MCUBOOT_BUILTIN_KEY)
291     assert(g_key_slot.is_valid && (g_key_slot.key_id == key));
292 
293     g_key_slot.buf = NULL;
294     g_key_slot.len = 0;
295     g_key_slot.attr = psa_key_attributes_init();
296     g_key_slot.is_valid = false;
297 
298     /* This will keep the value of the key_id so that a new import will
299      * just use the next key_id. This allows to keep track of potential
300      * clients trying to reuse a deleted key ID
301      */
302 #else /* !MCUBOOT_BUILTIN_KEY */
303     memset(g_pubkey_data, 0, sizeof(g_pubkey_data));
304     g_key_slot.len = 0;
305     g_key_slot.attr = psa_key_attributes_init();
306 #endif /* !MCUBOOT_BUILTIN_KEY */
307 
308     return PSA_SUCCESS;
309 }
310 
311 /* Signature verification supports only RSA or ECDSA with P256 or P384 */
psa_verify_hash(psa_key_id_t key,psa_algorithm_t alg,const uint8_t * hash,size_t hash_length,const uint8_t * signature,size_t signature_length)312 psa_status_t psa_verify_hash(psa_key_id_t key,
313                              psa_algorithm_t alg,
314                              const uint8_t *hash,
315                              size_t hash_length,
316                              const uint8_t *signature,
317                              size_t signature_length)
318 {
319     psa_status_t status;
320 
321 #if !defined(MCUBOOT_BUILTIN_KEY)
322     assert(g_key_slot.is_valid && (g_key_slot.key_id == key));
323 #else
324     assert((key >= MCUBOOT_BUILTIN_KEY_ID_MIN) &&
325            (key <= MCUBOOT_BUILTIN_KEY_ID_MAX));
326 
327     status = get_builtin_public_key(key, alg);
328     if (status != PSA_SUCCESS) {
329         return status;
330     }
331 #endif /* !MCUBOOT_BUILTIN_KEY */
332 
333     status = psa_driver_wrapper_verify_hash(
334                 &g_key_slot.attr,
335                 g_key_slot.buf, g_key_slot.len,
336                 alg, hash, hash_length,
337                 signature, signature_length);
338 
339     return status;
340 }
341 
mbedtls_to_psa_error(int ret)342 psa_status_t mbedtls_to_psa_error(int ret)
343 {
344     /* We don't require precise error translation */
345     if (!ret) {
346         return PSA_SUCCESS;
347     } else {
348         return PSA_ERROR_GENERIC_ERROR;
349     }
350 }
351 
352 #if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
mbedtls_psa_get_random(void * p_rng,unsigned char * output,size_t output_size)353 int mbedtls_psa_get_random(void *p_rng,
354                            unsigned char *output,
355                            size_t output_size)
356 {
357     /* This function takes a pointer to the RNG state because that's what
358      * classic mbedtls functions using an RNG expect. The PSA RNG manages
359      * its own state internally and doesn't let the caller access that state.
360      * So we just ignore the state parameter, and in practice we'll pass
361      * NULL.
362      */
363     (void) p_rng;
364     psa_status_t status = psa_generate_random(output, output_size);
365 
366     if (status == PSA_SUCCESS) {
367         return 0;
368     } else {
369         return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
370     }
371 }
372 #endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
373 
psa_generate_random(uint8_t * output,size_t output_size)374 psa_status_t psa_generate_random(uint8_t *output,
375                                  size_t output_size)
376 {
377 #if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
378 
379     size_t output_length = 0;
380     psa_status_t status = mbedtls_psa_external_get_random(g_ctx,
381                                                           output, output_size,
382                                                           &output_length);
383     if (status != PSA_SUCCESS) {
384         return status;
385     }
386     /* Breaking up a request into smaller chunks is currently not supported
387      * for the external RNG interface.
388      */
389     if (output_length != output_size) {
390         return PSA_ERROR_INSUFFICIENT_ENTROPY;
391     }
392     return PSA_SUCCESS;
393 
394 #endif
395     return PSA_ERROR_NOT_SUPPORTED;
396 }
397 
398 /* This gets linked by the driver wrapper if no driver is present */
psa_verify_hash_builtin(const psa_key_attributes_t * attributes,const uint8_t * key_buffer,size_t key_buffer_size,psa_algorithm_t alg,const uint8_t * hash,size_t hash_length,const uint8_t * signature,size_t signature_length)399 psa_status_t psa_verify_hash_builtin(
400     const psa_key_attributes_t *attributes,
401     const uint8_t *key_buffer, size_t key_buffer_size,
402     psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
403     const uint8_t *signature, size_t signature_length)
404 {
405 #if defined(MCUBOOT_SIGN_RSA)
406     if (PSA_KEY_TYPE_IS_RSA(psa_get_key_type(attributes))) {
407         if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) ||
408             PSA_ALG_IS_RSA_PSS(alg)) {
409 #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)
410             return mbedtls_psa_rsa_verify_hash(
411                 attributes,
412                 key_buffer, key_buffer_size,
413                 alg, hash, hash_length,
414                 signature, signature_length);
415 #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) */
416         } else {
417             return PSA_ERROR_INVALID_ARGUMENT;
418         }
419     }
420 #elif defined(MCUBOOT_SIGN_EC256) || defined(MCUBOOT_SIGN_EC384)
421     if (PSA_KEY_TYPE_IS_ECC(psa_get_key_type(attributes))) {
422         if (PSA_ALG_IS_ECDSA(alg)) {
423 #if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
424             defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
425             return mbedtls_psa_ecdsa_verify_hash(
426                 attributes,
427                 key_buffer, key_buffer_size,
428                 alg, hash, hash_length,
429                 signature, signature_length);
430 #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
431         * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
432         */
433         } else {
434             return PSA_ERROR_INVALID_ARGUMENT;
435         }
436     }
437 #endif
438 
439     (void) key_buffer;
440     (void) key_buffer_size;
441     (void) hash;
442     (void) hash_length;
443     (void) signature;
444     (void) signature_length;
445 
446     return PSA_ERROR_NOT_SUPPORTED;
447 }
448 
449 /* Required when Mbed TLS backend converts from PSA to Mbed TLS native */
mbedtls_ecc_group_from_psa(psa_ecc_family_t family,size_t bits)450 mbedtls_ecp_group_id mbedtls_ecc_group_from_psa(psa_ecc_family_t family,
451                                                 size_t bits)
452 {
453     switch (family) {
454     case PSA_ECC_FAMILY_SECP_R1:
455         switch (bits) {
456 #if defined(PSA_WANT_ECC_SECP_R1_192)
457         case 192:
458             return MBEDTLS_ECP_DP_SECP192R1;
459 #endif
460 #if defined(PSA_WANT_ECC_SECP_R1_224)
461         case 224:
462             return MBEDTLS_ECP_DP_SECP224R1;
463 #endif
464 #if defined(PSA_WANT_ECC_SECP_R1_256)
465         case 256:
466             return MBEDTLS_ECP_DP_SECP256R1;
467 #endif
468 #if defined(PSA_WANT_ECC_SECP_R1_384)
469         case 384:
470             return MBEDTLS_ECP_DP_SECP384R1;
471 #endif
472 #if defined(PSA_WANT_ECC_SECP_R1_521)
473         case 521:
474             return MBEDTLS_ECP_DP_SECP521R1;
475 #endif
476         }
477         break;
478 
479     case PSA_ECC_FAMILY_BRAINPOOL_P_R1:
480         switch (bits) {
481 #if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256)
482         case 256:
483             return MBEDTLS_ECP_DP_BP256R1;
484 #endif
485 #if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384)
486         case 384:
487             return MBEDTLS_ECP_DP_BP384R1;
488 #endif
489 #if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512)
490         case 512:
491             return MBEDTLS_ECP_DP_BP512R1;
492 #endif
493         }
494         break;
495 
496     case PSA_ECC_FAMILY_MONTGOMERY:
497         switch (bits) {
498 #if defined(PSA_WANT_ECC_MONTGOMERY_255)
499         case 255:
500             return MBEDTLS_ECP_DP_CURVE25519;
501 #endif
502 #if defined(PSA_WANT_ECC_MONTGOMERY_448)
503         case 448:
504             return MBEDTLS_ECP_DP_CURVE448;
505 #endif
506         }
507         break;
508 
509     case PSA_ECC_FAMILY_SECP_K1:
510         switch (bits) {
511 #if defined(PSA_WANT_ECC_SECP_K1_192)
512         case 192:
513             return MBEDTLS_ECP_DP_SECP192K1;
514 #endif
515 #if defined(PSA_WANT_ECC_SECP_K1_224)
516             /* secp224k1 is not and will not be supported in PSA (#3541). */
517 #endif
518 #if defined(PSA_WANT_ECC_SECP_K1_256)
519         case 256:
520             return MBEDTLS_ECP_DP_SECP256K1;
521 #endif
522         }
523         break;
524     }
525 
526     return MBEDTLS_ECP_DP_NONE;
527 }
528 
529 /* We don't need the full driver wrapper, we know the key is already a public key */
psa_driver_wrapper_export_public_key(const psa_key_attributes_t * attributes,const uint8_t * key_buffer,size_t key_buffer_size,uint8_t * data,size_t data_size,size_t * data_length)530 psa_status_t psa_driver_wrapper_export_public_key(
531     const psa_key_attributes_t *attributes,
532     const uint8_t *key_buffer, size_t key_buffer_size,
533     uint8_t *data, size_t data_size, size_t *data_length)
534 {
535     assert(PSA_KEY_TYPE_IS_PUBLIC_KEY(psa_get_key_type(attributes)));
536     assert(key_buffer_size <= data_size);
537 
538     memcpy(data, key_buffer, key_buffer_size);
539     *data_length = key_buffer_size;
540 
541     return PSA_SUCCESS;
542 }
543