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