1 /* 2 * Copyright (c) 2023-2025, Arm Limited. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 #include <stddef.h> 9 #include <string.h> 10 11 /* mbed TLS headers */ 12 #include <mbedtls/md.h> 13 #include <mbedtls/memory_buffer_alloc.h> 14 #include <mbedtls/oid.h> 15 #include <mbedtls/platform.h> 16 #include <mbedtls/psa_util.h> 17 #include <mbedtls/x509.h> 18 #include <psa/crypto.h> 19 #include <psa/crypto_platform.h> 20 #include <psa/crypto_types.h> 21 #include <psa/crypto_values.h> 22 23 #include <common/debug.h> 24 #include <drivers/auth/auth_util.h> 25 #include <drivers/auth/crypto_mod.h> 26 #include <drivers/auth/mbedtls/mbedtls_common.h> 27 #include <drivers/auth/mbedtls/mbedtls_psa_crypto.h> 28 #include <plat/common/platform.h> 29 30 #define LIB_NAME "mbed TLS PSA" 31 32 /* Minimum required size for a buffer containing a raw EC signature when using 33 * a maximum curve size of 384 bits. 34 * This is calculated as 2 * (384 / 8). */ 35 #define ECDSA_SIG_BUFFER_SIZE 96U 36 37 /* Size of ASN.1 length and tag in bytes*/ 38 #define SIZE_OF_ASN1_LEN 1U 39 #define SIZE_OF_ASN1_TAG 1U 40 41 /* Global cache for keys */ 42 key_cache_t key_cache[MAX_CACHED_KEYS] = {0}; 43 44 #if CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \ 45 CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC 46 /* 47 * CRYPTO_MD_MAX_SIZE value is as per current stronger algorithm available 48 * so make sure that mbed TLS MD maximum size must be lesser than this. 49 */ 50 CASSERT(CRYPTO_MD_MAX_SIZE >= MBEDTLS_MD_MAX_SIZE, 51 assert_mbedtls_md_size_overflow); 52 53 #endif /* 54 * CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \ 55 * CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC 56 */ 57 58 /* 59 * AlgorithmIdentifier ::= SEQUENCE { 60 * algorithm OBJECT IDENTIFIER, 61 * parameters ANY DEFINED BY algorithm OPTIONAL 62 * } 63 * 64 * SubjectPublicKeyInfo ::= SEQUENCE { 65 * algorithm AlgorithmIdentifier, 66 * subjectPublicKey BIT STRING 67 * } 68 * 69 * DigestInfo ::= SEQUENCE { 70 * digestAlgorithm AlgorithmIdentifier, 71 * digest OCTET STRING 72 * } 73 */ 74 75 /* 76 * We pretend using an external RNG (through MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG 77 * mbedTLS config option) so we need to provide an implementation of 78 * mbedtls_psa_external_get_random(). Provide a fake one, since we do not 79 * actually have any external RNG and TF-A itself doesn't engage in 80 * cryptographic operations that demands randomness. 81 */ 82 psa_status_t mbedtls_psa_external_get_random( 83 mbedtls_psa_external_random_context_t *context, 84 uint8_t *output, size_t output_size, 85 size_t *output_length) 86 { 87 return PSA_ERROR_INSUFFICIENT_ENTROPY; 88 } 89 90 /* 91 * Initialize the library and export the descriptor 92 */ 93 static void init(void) 94 { 95 /* Initialize mbed TLS */ 96 mbedtls_init(); 97 98 /* Initialise PSA mbedTLS */ 99 psa_status_t status = psa_crypto_init(); 100 101 if (status != PSA_SUCCESS) { 102 ERROR("Failed to initialize %s crypto (%d).\n", LIB_NAME, status); 103 panic(); 104 } 105 106 INFO("PSA crypto initialized successfully!\n"); 107 } 108 109 #if CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \ 110 CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC 111 /* Destroy all psa key ids created in a loop */ 112 static void destroy_key_ids(void) 113 { 114 for (int i = 0; i < MAX_CACHED_KEYS; i++) { 115 if (key_cache[i].valid) { 116 psa_destroy_key(key_cache[i].key_id); 117 } 118 } 119 } 120 121 /* Retrieve cached key ID, algorithm, and key attributes */ 122 static bool get_cached_psa_key_info(const char *pk_oid, psa_key_id_t *key_id, 123 psa_algorithm_t *psa_alg, psa_key_attributes_t *psa_key_attr) 124 { 125 for (int i = 0; i < MAX_CACHED_KEYS; i++) { 126 if (key_cache[i].valid && 127 (strlen(key_cache[i].pk_oid) == strlen(pk_oid)) && 128 (strncmp(key_cache[i].pk_oid, pk_oid, strlen(pk_oid)) == 0)) { 129 *key_id = key_cache[i].key_id; 130 *psa_alg = key_cache[i].psa_alg; 131 *psa_key_attr = key_cache[i].psa_key_attr; 132 return true; 133 } 134 } 135 return false; 136 } 137 138 /* Store key ID, algorithm, and key attributes in the cache */ 139 static int cache_psa_key_info(const char *pk_oid, psa_key_id_t key_id, psa_algorithm_t psa_alg, 140 psa_key_attributes_t psa_key_attr) 141 { 142 for (int i = 0; i < MAX_CACHED_KEYS; i++) { 143 if (!key_cache[i].valid) { 144 key_cache[i].pk_oid = pk_oid; 145 key_cache[i].key_id = key_id; 146 key_cache[i].psa_alg = psa_alg; 147 key_cache[i].psa_key_attr = psa_key_attr; 148 key_cache[i].valid = true; 149 return CRYPTO_SUCCESS; 150 } 151 } 152 return CRYPTO_ERR_SIGNATURE; 153 } 154 155 /* 156 * NOTE: This has been made internal in mbedtls 3.6.0 and the mbedtls team has 157 * advised that it's better to copy out the declaration than it would be to 158 * update to 3.5.2, where this function is exposed. 159 */ 160 int mbedtls_x509_get_sig_alg(const mbedtls_x509_buf *sig_oid, 161 const mbedtls_x509_buf *sig_params, 162 mbedtls_md_type_t *md_alg, 163 mbedtls_pk_type_t *pk_alg, 164 void **sig_opts); 165 166 /* 167 * This is a helper function which parses a SignatureAlgorithm OID. 168 * It extracts the pk algorithm and constructs a psa_algorithm_t object 169 * to be used by PSA calls. 170 */ 171 static int construct_psa_alg(void *sig_alg, unsigned int sig_alg_len, 172 mbedtls_pk_type_t *pk_alg, psa_algorithm_t *psa_alg) 173 { 174 int rc; 175 mbedtls_md_type_t md_alg; 176 void *sig_opts = NULL; 177 mbedtls_asn1_buf sig_alg_oid, params; 178 unsigned char *p = (unsigned char *) sig_alg; 179 unsigned char *end = (unsigned char *) sig_alg + sig_alg_len; 180 181 rc = mbedtls_asn1_get_alg(&p, end, &sig_alg_oid, ¶ms); 182 if (rc != 0) { 183 rc = CRYPTO_ERR_SIGNATURE; 184 goto end; 185 } 186 187 rc = mbedtls_x509_get_sig_alg(&sig_alg_oid, ¶ms, &md_alg, pk_alg, &sig_opts); 188 if (rc != 0) { 189 rc = CRYPTO_ERR_SIGNATURE; 190 goto end; 191 } 192 193 psa_algorithm_t psa_md_alg = mbedtls_md_psa_alg_from_type(md_alg); 194 195 switch (*pk_alg) { 196 case MBEDTLS_PK_RSASSA_PSS: 197 *psa_alg = PSA_ALG_RSA_PSS(psa_md_alg); 198 rc = CRYPTO_SUCCESS; 199 break; 200 case MBEDTLS_PK_ECDSA: 201 *psa_alg = PSA_ALG_ECDSA(psa_md_alg); 202 rc = CRYPTO_SUCCESS; 203 break; 204 default: 205 *psa_alg = PSA_ALG_NONE; 206 rc = CRYPTO_ERR_SIGNATURE; 207 break; 208 } 209 210 end: 211 mbedtls_free(sig_opts); 212 return rc; 213 } 214 215 /* 216 * Helper functions for mbedtls PK contexts. 217 */ 218 static void initialize_pk_context(mbedtls_pk_context *pk, bool *pk_initialized) 219 { 220 mbedtls_pk_init(pk); 221 *pk_initialized = true; 222 } 223 224 static void cleanup_pk_context(mbedtls_pk_context *pk, bool *pk_initialized) 225 { 226 if (*pk_initialized) { 227 mbedtls_pk_free(pk); 228 *pk_initialized = false; 229 } 230 } 231 232 /* 233 * Verify a signature. 234 * 235 * Parameters are passed using the DER encoding format following the ASN.1 236 * structures detailed above. 237 */ 238 static int verify_signature(void *data_ptr, unsigned int data_len, 239 void *sig_ptr, unsigned int sig_len, 240 void *sig_alg, unsigned int sig_alg_len, 241 void *pk_ptr, unsigned int pk_len) 242 { 243 unsigned char *p, *end; 244 mbedtls_pk_context pk; 245 bool pk_initialized = false; 246 int rc = CRYPTO_ERR_SIGNATURE; 247 psa_status_t psa_status = PSA_ERROR_CORRUPTION_DETECTED; 248 psa_key_attributes_t psa_key_attr = PSA_KEY_ATTRIBUTES_INIT; 249 psa_key_id_t psa_key_id; 250 mbedtls_pk_type_t pk_alg; 251 psa_algorithm_t psa_alg; 252 const char *pk_oid = get_current_pk_oid(); 253 __unused unsigned char reformatted_sig[ECDSA_SIG_BUFFER_SIZE] = {0}; 254 unsigned char *local_sig_ptr; 255 size_t local_sig_len; 256 257 /* Check if key, algorithm, and key attributes are already cached */ 258 if (!get_cached_psa_key_info(pk_oid, &psa_key_id, &psa_alg, &psa_key_attr)) { 259 /* Load the key into the PSA key store. */ 260 initialize_pk_context(&pk, &pk_initialized); 261 262 p = (unsigned char *) pk_ptr; 263 end = p + pk_len; 264 rc = mbedtls_pk_parse_subpubkey(&p, end, &pk); 265 if (rc != 0) { 266 rc = CRYPTO_ERR_SIGNATURE; 267 goto end2; 268 } 269 270 rc = mbedtls_pk_get_psa_attributes(&pk, PSA_KEY_USAGE_VERIFY_MESSAGE, 271 &psa_key_attr); 272 if (rc != 0) { 273 rc = CRYPTO_ERR_SIGNATURE; 274 goto end2; 275 } 276 277 rc = construct_psa_alg(sig_alg, sig_alg_len, &pk_alg, &psa_alg); 278 if (rc != CRYPTO_SUCCESS) { 279 goto end2; 280 } 281 psa_set_key_algorithm(&psa_key_attr, psa_alg); 282 283 rc = mbedtls_pk_import_into_psa(&pk, &psa_key_attr, &psa_key_id); 284 if (rc != 0) { 285 rc = CRYPTO_ERR_SIGNATURE; 286 goto end2; 287 } 288 289 /* Cache the key, algorithm, and key attributes for future use */ 290 rc = cache_psa_key_info(pk_oid, psa_key_id, psa_alg, psa_key_attr); 291 if (rc != CRYPTO_SUCCESS) { 292 goto end2; 293 } 294 295 /* Optimize mbedtls heap usage by freeing the pk context now. */ 296 cleanup_pk_context(&pk, &pk_initialized); 297 } 298 299 /* Extract the signature from sig_ptr. */ 300 p = (unsigned char *) sig_ptr; 301 end = p + sig_len; 302 rc = mbedtls_asn1_get_bitstring_null(&p, end, &local_sig_len); 303 if (rc != 0) { 304 rc = CRYPTO_ERR_SIGNATURE; 305 goto end1; 306 } 307 local_sig_ptr = p; 308 309 #if TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_ECDSA || \ 310 TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA_AND_ECDSA 311 if (PSA_ALG_IS_ECDSA(psa_alg)) { 312 /* Convert the DER ASN.1 signature to raw format. */ 313 size_t key_bits = psa_get_key_bits(&psa_key_attr); 314 315 rc = mbedtls_ecdsa_der_to_raw(key_bits, p, local_sig_len, 316 reformatted_sig, ECDSA_SIG_BUFFER_SIZE, 317 &local_sig_len); 318 if (rc != 0) { 319 rc = CRYPTO_ERR_SIGNATURE; 320 goto end1; 321 } 322 local_sig_ptr = reformatted_sig; 323 } 324 #endif /* 325 * TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_ECDSA || \ 326 * TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA_AND_ECDSA 327 **/ 328 329 /* Verify the signature. */ 330 psa_status = psa_verify_message(psa_key_id, psa_alg, 331 data_ptr, data_len, 332 local_sig_ptr, local_sig_len); 333 334 rc = (psa_status == PSA_SUCCESS) ? CRYPTO_SUCCESS : CRYPTO_ERR_SIGNATURE; 335 336 end1: 337 return rc; 338 end2: 339 /* Free the pk context, if it is initialized. */ 340 cleanup_pk_context(&pk, &pk_initialized); 341 342 return rc; 343 } 344 345 /* 346 * Match a hash 347 * 348 * Digest info is passed in DER format following the ASN.1 structure detailed 349 * above. 350 */ 351 static int verify_hash(void *data_ptr, unsigned int data_len, 352 void *digest_info_ptr, unsigned int digest_info_len) 353 { 354 mbedtls_asn1_buf hash_oid, params; 355 mbedtls_md_type_t md_alg; 356 unsigned char *p, *end, *hash; 357 size_t len; 358 int rc; 359 psa_status_t status; 360 psa_algorithm_t psa_md_alg; 361 362 /* 363 * Digest info should be an MBEDTLS_ASN1_SEQUENCE, but padding after 364 * it is allowed. This is necessary to support multiple hash 365 * algorithms. 366 */ 367 p = (unsigned char *)digest_info_ptr; 368 end = p + digest_info_len; 369 rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | 370 MBEDTLS_ASN1_SEQUENCE); 371 if (rc != 0) { 372 return CRYPTO_ERR_HASH; 373 } 374 375 end = p + len; 376 377 /* Get the hash algorithm */ 378 rc = mbedtls_asn1_get_alg(&p, end, &hash_oid, ¶ms); 379 if (rc != 0) { 380 return CRYPTO_ERR_HASH; 381 } 382 383 /* Hash should be octet string type and consume all bytes */ 384 rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING); 385 if ((rc != 0) || ((size_t)(end - p) != len)) { 386 return CRYPTO_ERR_HASH; 387 } 388 hash = p; 389 390 rc = mbedtls_oid_get_md_alg(&hash_oid, &md_alg); 391 if (rc != 0) { 392 return CRYPTO_ERR_HASH; 393 } 394 395 /* convert the md_alg to psa_algo */ 396 psa_md_alg = mbedtls_md_psa_alg_from_type(md_alg); 397 398 /* Length of hash must match the algorithm's size */ 399 if (len != PSA_HASH_LENGTH(psa_md_alg)) { 400 return CRYPTO_ERR_HASH; 401 } 402 403 /* 404 * Calculate Hash and compare it against the retrieved hash from 405 * the certificate (one shot API). 406 */ 407 status = psa_hash_compare(psa_md_alg, 408 data_ptr, (size_t)data_len, 409 (const uint8_t *)hash, len); 410 411 if (status != PSA_SUCCESS) { 412 return CRYPTO_ERR_HASH; 413 } 414 415 return CRYPTO_SUCCESS; 416 } 417 #endif /* 418 * CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \ 419 * CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC 420 */ 421 422 /* 423 * Finish crypto usage by destroying the psa_key_ids 424 */ 425 static void finish(void) 426 { 427 #if CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \ 428 CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC 429 /* Destroy the psa_key_ids */ 430 destroy_key_ids(); 431 #endif 432 } 433 434 #if CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \ 435 CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC 436 /* 437 * Map a generic crypto message digest algorithm to the corresponding macro used 438 * by Mbed TLS. 439 */ 440 static inline mbedtls_md_type_t md_type(enum crypto_md_algo algo) 441 { 442 switch (algo) { 443 case CRYPTO_MD_SHA512: 444 return MBEDTLS_MD_SHA512; 445 case CRYPTO_MD_SHA384: 446 return MBEDTLS_MD_SHA384; 447 case CRYPTO_MD_SHA256: 448 return MBEDTLS_MD_SHA256; 449 default: 450 /* Invalid hash algorithm. */ 451 return MBEDTLS_MD_NONE; 452 } 453 } 454 455 /* 456 * Calculate a hash 457 * 458 * output points to the computed hash 459 */ 460 static int calc_hash(enum crypto_md_algo md_algo, void *data_ptr, 461 unsigned int data_len, 462 unsigned char output[CRYPTO_MD_MAX_SIZE]) 463 { 464 size_t hash_length; 465 psa_status_t status; 466 psa_algorithm_t psa_md_alg; 467 468 /* convert the md_alg to psa_algo */ 469 psa_md_alg = mbedtls_md_psa_alg_from_type(md_type(md_algo)); 470 471 /* 472 * Calculate the hash of the data, it is safe to pass the 473 * 'output' hash buffer pointer considering its size is always 474 * bigger than or equal to MBEDTLS_MD_MAX_SIZE. 475 */ 476 status = psa_hash_compute(psa_md_alg, data_ptr, (size_t)data_len, 477 (uint8_t *)output, CRYPTO_MD_MAX_SIZE, 478 &hash_length); 479 if (status != PSA_SUCCESS) { 480 return CRYPTO_ERR_HASH; 481 } 482 483 return CRYPTO_SUCCESS; 484 } 485 #endif /* 486 * CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \ 487 * CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC 488 */ 489 490 #if TF_MBEDTLS_USE_AES_GCM 491 /* 492 * Stack based buffer allocation for decryption operation. It could 493 * be configured to balance stack usage vs execution speed. 494 */ 495 #define DEC_OP_BUF_SIZE 128 496 497 static int aes_gcm_decrypt(void *data_ptr, size_t len, const void *key, 498 unsigned int key_len, const void *iv, 499 unsigned int iv_len, const void *tag, 500 unsigned int tag_len) 501 { 502 mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; 503 psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT; 504 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; 505 psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR; 506 unsigned char buf[DEC_OP_BUF_SIZE]; 507 unsigned char *pt = data_ptr; 508 size_t dec_len; 509 size_t output_length; 510 511 /* Load the key into the PSA key store. */ 512 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT); 513 psa_set_key_algorithm(&attributes, PSA_ALG_GCM); 514 psa_set_key_type(&attributes, PSA_KEY_TYPE_AES); 515 516 psa_status = psa_import_key(&attributes, key, key_len, &key_id); 517 if (psa_status != PSA_SUCCESS) { 518 return CRYPTO_ERR_DECRYPTION; 519 } 520 521 /* Perform the decryption. */ 522 psa_status = psa_aead_decrypt_setup(&operation, key_id, PSA_ALG_GCM); 523 if (psa_status != PSA_SUCCESS) { 524 goto err; 525 } 526 527 psa_status = psa_aead_set_nonce(&operation, iv, iv_len); 528 if (psa_status != PSA_SUCCESS) { 529 goto err; 530 } 531 532 while (len > 0) { 533 dec_len = MIN(sizeof(buf), len); 534 535 psa_status = psa_aead_update(&operation, pt, dec_len, buf, 536 sizeof(buf), &output_length); 537 if (psa_status != PSA_SUCCESS) { 538 goto err; 539 } 540 541 memcpy(pt, buf, output_length); 542 pt += output_length; 543 len -= dec_len; 544 } 545 546 /* Verify the tag. */ 547 psa_status = psa_aead_verify(&operation, NULL, 0, &output_length, tag, tag_len); 548 if (psa_status == PSA_SUCCESS) { 549 psa_destroy_key(key_id); 550 return CRYPTO_SUCCESS; 551 } 552 553 err: 554 psa_aead_abort(&operation); 555 psa_destroy_key(key_id); 556 return CRYPTO_ERR_DECRYPTION; 557 } 558 559 /* 560 * Authenticated decryption of an image 561 */ 562 static int auth_decrypt(enum crypto_dec_algo dec_algo, void *data_ptr, 563 size_t len, const void *key, unsigned int key_len, 564 unsigned int key_flags, const void *iv, 565 unsigned int iv_len, const void *tag, 566 unsigned int tag_len) 567 { 568 int rc; 569 570 assert((key_flags & ENC_KEY_IS_IDENTIFIER) == 0); 571 572 switch (dec_algo) { 573 case CRYPTO_GCM_DECRYPT: 574 rc = aes_gcm_decrypt(data_ptr, len, key, key_len, iv, iv_len, 575 tag, tag_len); 576 if (rc != 0) 577 return rc; 578 break; 579 default: 580 return CRYPTO_ERR_DECRYPTION; 581 } 582 583 return CRYPTO_SUCCESS; 584 } 585 #endif /* TF_MBEDTLS_USE_AES_GCM */ 586 587 /* 588 * Register crypto library descriptor 589 */ 590 #if CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC 591 #if TF_MBEDTLS_USE_AES_GCM 592 REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash, 593 auth_decrypt, NULL, finish); 594 #else 595 REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash, 596 NULL, NULL, finish); 597 #endif 598 #elif CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY 599 #if TF_MBEDTLS_USE_AES_GCM 600 REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL, 601 auth_decrypt, NULL, finish); 602 #else 603 REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL, 604 NULL, NULL, finish); 605 #endif 606 #elif CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY 607 REGISTER_CRYPTO_LIB(LIB_NAME, init, NULL, NULL, calc_hash, NULL, NULL, finish); 608 #endif /* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */ 609