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