1 /* 2 * Copyright (c) 2023, 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/gcm.h> 13 #include <mbedtls/md.h> 14 #include <mbedtls/memory_buffer_alloc.h> 15 #include <mbedtls/oid.h> 16 #include <mbedtls/platform.h> 17 #include <mbedtls/version.h> 18 #include <mbedtls/x509.h> 19 #include <psa/crypto.h> 20 #include <psa/crypto_platform.h> 21 #include <psa/crypto_types.h> 22 #include <psa/crypto_values.h> 23 24 #include <common/debug.h> 25 #include <drivers/auth/crypto_mod.h> 26 #include <drivers/auth/mbedtls/mbedtls_common.h> 27 #include <plat/common/platform.h> 28 29 #define LIB_NAME "mbed TLS PSA" 30 31 /* Maximum length of R_S pair in the ECDSA signature in bytes */ 32 #define MAX_ECDSA_R_S_PAIR_LEN 64U 33 34 /* Size of ASN.1 length and tag in bytes*/ 35 #define SIZE_OF_ASN1_LEN 1U 36 #define SIZE_OF_ASN1_TAG 1U 37 38 #if CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \ 39 CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC 40 /* 41 * CRYPTO_MD_MAX_SIZE value is as per current stronger algorithm available 42 * so make sure that mbed TLS MD maximum size must be lesser than this. 43 */ 44 CASSERT(CRYPTO_MD_MAX_SIZE >= MBEDTLS_MD_MAX_SIZE, 45 assert_mbedtls_md_size_overflow); 46 47 #endif /* 48 * CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \ 49 * CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC 50 */ 51 52 static inline psa_algorithm_t mbedtls_md_psa_alg_from_type( 53 mbedtls_md_type_t md_type) 54 { 55 assert((md_type == MBEDTLS_MD_SHA256) || 56 (md_type == MBEDTLS_MD_SHA384) || 57 (md_type == MBEDTLS_MD_SHA512)); 58 59 return PSA_ALG_CATEGORY_HASH | (psa_algorithm_t) (md_type + 0x5); 60 } 61 62 /* 63 * AlgorithmIdentifier ::= SEQUENCE { 64 * algorithm OBJECT IDENTIFIER, 65 * parameters ANY DEFINED BY algorithm OPTIONAL 66 * } 67 * 68 * SubjectPublicKeyInfo ::= SEQUENCE { 69 * algorithm AlgorithmIdentifier, 70 * subjectPublicKey BIT STRING 71 * } 72 * 73 * DigestInfo ::= SEQUENCE { 74 * digestAlgorithm AlgorithmIdentifier, 75 * digest OCTET STRING 76 * } 77 */ 78 79 /* 80 * We pretend using an external RNG (through MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG 81 * mbedTLS config option) so we need to provide an implementation of 82 * mbedtls_psa_external_get_random(). Provide a fake one, since we do not 83 * actually have any external RNG and TF-A itself doesn't engage in 84 * cryptographic operations that demands randomness. 85 */ 86 psa_status_t mbedtls_psa_external_get_random( 87 mbedtls_psa_external_random_context_t *context, 88 uint8_t *output, size_t output_size, 89 size_t *output_length) 90 { 91 return PSA_ERROR_INSUFFICIENT_ENTROPY; 92 } 93 94 /* 95 * Initialize the library and export the descriptor 96 */ 97 static void init(void) 98 { 99 /* Initialize mbed TLS */ 100 mbedtls_init(); 101 102 /* Initialise PSA mbedTLS */ 103 psa_status_t status = psa_crypto_init(); 104 105 if (status != PSA_SUCCESS) { 106 ERROR("Failed to initialize %s crypto (%d).\n", LIB_NAME, status); 107 panic(); 108 } 109 110 INFO("PSA crypto initialized successfully!\n"); 111 } 112 113 #if CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \ 114 CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC 115 116 static void construct_psa_key_alg_and_type(mbedtls_pk_type_t pk_alg, 117 mbedtls_md_type_t md_alg, 118 psa_ecc_family_t psa_ecc_family, 119 psa_algorithm_t *psa_alg, 120 psa_key_type_t *psa_key_type) 121 { 122 psa_algorithm_t psa_md_alg = mbedtls_md_psa_alg_from_type(md_alg); 123 124 switch (pk_alg) { 125 case MBEDTLS_PK_RSASSA_PSS: 126 *psa_alg = PSA_ALG_RSA_PSS(psa_md_alg); 127 *psa_key_type = PSA_KEY_TYPE_RSA_PUBLIC_KEY; 128 break; 129 case MBEDTLS_PK_ECDSA: 130 *psa_alg = PSA_ALG_ECDSA(psa_md_alg); 131 *psa_key_type = PSA_KEY_TYPE_ECC_PUBLIC_KEY(psa_ecc_family); 132 break; 133 default: 134 *psa_alg = PSA_ALG_NONE; 135 *psa_key_type = PSA_KEY_TYPE_NONE; 136 break; 137 } 138 } 139 140 141 #if TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_ECDSA || \ 142 TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA_AND_ECDSA 143 144 /* 145 * This is a helper function to detect padding byte (if the MSB bit of the 146 * first data byte is set to 1, for example 0x80) and on detection, ignore the 147 * padded byte(0x00) and increase the buffer pointer beyond padded byte and 148 * decrease the length of the buffer by 1. 149 * 150 * On Success returns 0, error otherwise. 151 **/ 152 static inline int ignore_asn1_int_padding_byte(unsigned char **buf_start, 153 size_t *buf_len) 154 { 155 unsigned char *local_buf = *buf_start; 156 157 /* Check for negative number */ 158 if ((local_buf[0] & 0x80U) != 0U) { 159 return -1; 160 } 161 162 if ((local_buf[0] == 0U) && (local_buf[1] > 0x7FU) && 163 (*buf_len > 1U)) { 164 *buf_start = &local_buf[1]; 165 (*buf_len)--; 166 } 167 168 return 0; 169 } 170 171 /* 172 * This is a helper function that gets a pointer to the encoded ECDSA publicKey 173 * and its length (as per RFC5280) and returns corresponding decoded publicKey 174 * and its length. As well, it retrieves the family of ECC key in the PSA 175 * format. 176 * 177 * This function returns error(CRYPTO_ERR_SIGNATURE) on ASN.1 parsing failure, 178 * otherwise success(0). 179 **/ 180 static int get_ecdsa_pkinfo_from_asn1(unsigned char **pk_start, 181 unsigned int *pk_len, 182 psa_ecc_family_t *psa_ecc_family) 183 { 184 mbedtls_asn1_buf alg_oid, alg_params; 185 mbedtls_ecp_group_id grp_id; 186 int rc; 187 unsigned char *pk_end; 188 size_t len; 189 size_t curve_bits; 190 unsigned char *pk_ptr = *pk_start; 191 192 pk_end = pk_ptr + *pk_len; 193 rc = mbedtls_asn1_get_tag(&pk_ptr, pk_end, &len, 194 MBEDTLS_ASN1_CONSTRUCTED | 195 MBEDTLS_ASN1_SEQUENCE); 196 if (rc != 0) { 197 return CRYPTO_ERR_SIGNATURE; 198 } 199 200 pk_end = pk_ptr + len; 201 rc = mbedtls_asn1_get_alg(&pk_ptr, pk_end, &alg_oid, &alg_params); 202 if (rc != 0) { 203 return CRYPTO_ERR_SIGNATURE; 204 } 205 206 if (alg_params.tag == MBEDTLS_ASN1_OID) { 207 if (mbedtls_oid_get_ec_grp(&alg_params, &grp_id) != 0) { 208 return CRYPTO_ERR_SIGNATURE; 209 } 210 *psa_ecc_family = mbedtls_ecc_group_to_psa(grp_id, 211 &curve_bits); 212 } else { 213 return CRYPTO_ERR_SIGNATURE; 214 } 215 216 pk_end = pk_ptr + len - (alg_oid.len + alg_params.len + 217 2 * (SIZE_OF_ASN1_LEN + SIZE_OF_ASN1_TAG)); 218 rc = mbedtls_asn1_get_bitstring_null(&pk_ptr, pk_end, &len); 219 if (rc != 0) { 220 return CRYPTO_ERR_SIGNATURE; 221 } 222 223 *pk_start = pk_ptr; 224 *pk_len = len; 225 226 return rc; 227 } 228 229 /* 230 * Ecdsa-Sig-Value ::= SEQUENCE { 231 * r INTEGER, 232 * s INTEGER 233 * } 234 * 235 * This helper function that gets a pointer to the encoded ECDSA signature and 236 * its length (as per RFC5280) and returns corresponding decoded signature 237 * (R_S pair) and its size. 238 * 239 * This function returns error(CRYPTO_ERR_SIGNATURE) on ASN.1 parsing failure, 240 * otherwise success(0). 241 **/ 242 static int get_ecdsa_signature_from_asn1(unsigned char *sig_ptr, 243 size_t *sig_len, 244 unsigned char *r_s_pair) 245 { 246 int rc; 247 unsigned char *sig_end; 248 size_t len, r_len, s_len; 249 250 sig_end = sig_ptr + *sig_len; 251 rc = mbedtls_asn1_get_tag(&sig_ptr, sig_end, &len, 252 MBEDTLS_ASN1_CONSTRUCTED | 253 MBEDTLS_ASN1_SEQUENCE); 254 if (rc != 0) { 255 return CRYPTO_ERR_SIGNATURE; 256 } 257 258 sig_end = sig_ptr + len; 259 rc = mbedtls_asn1_get_tag(&sig_ptr, sig_end, &r_len, 260 MBEDTLS_ASN1_INTEGER); 261 if (rc != 0) { 262 return CRYPTO_ERR_SIGNATURE; 263 } 264 265 if (ignore_asn1_int_padding_byte(&sig_ptr, &r_len) != 0) { 266 return CRYPTO_ERR_SIGNATURE; 267 } 268 269 (void)memcpy((void *)&r_s_pair[0], (const void *)sig_ptr, r_len); 270 271 sig_ptr = sig_ptr + r_len; 272 sig_end = sig_ptr + len - (r_len + (SIZE_OF_ASN1_LEN + 273 SIZE_OF_ASN1_TAG)); 274 rc = mbedtls_asn1_get_tag(&sig_ptr, sig_end, &s_len, 275 MBEDTLS_ASN1_INTEGER); 276 if (rc != 0) { 277 return CRYPTO_ERR_SIGNATURE; 278 } 279 280 if (ignore_asn1_int_padding_byte(&sig_ptr, &s_len) != 0) { 281 return CRYPTO_ERR_SIGNATURE; 282 } 283 284 (void)memcpy((void *)&r_s_pair[r_len], (const void *)sig_ptr, s_len); 285 286 *sig_len = s_len + r_len; 287 288 return 0; 289 } 290 #endif /* 291 * TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_ECDSA || \ 292 * TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA_AND_ECDSA 293 **/ 294 295 /* 296 * Verify a signature. 297 * 298 * Parameters are passed using the DER encoding format following the ASN.1 299 * structures detailed above. 300 */ 301 static int verify_signature(void *data_ptr, unsigned int data_len, 302 void *sig_ptr, unsigned int sig_len, 303 void *sig_alg, unsigned int sig_alg_len, 304 void *pk_ptr, unsigned int pk_len) 305 { 306 mbedtls_asn1_buf sig_oid, sig_params; 307 mbedtls_asn1_buf signature; 308 mbedtls_md_type_t md_alg; 309 mbedtls_pk_type_t pk_alg; 310 int rc; 311 void *sig_opts = NULL; 312 unsigned char *p, *end; 313 unsigned char *local_sig_ptr; 314 size_t local_sig_len; 315 psa_ecc_family_t psa_ecc_family = 0U; 316 __unused unsigned char reformatted_sig[MAX_ECDSA_R_S_PAIR_LEN] = {0}; 317 318 /* construct PSA key algo and type */ 319 psa_status_t status = PSA_SUCCESS; 320 psa_key_attributes_t psa_key_attr = PSA_KEY_ATTRIBUTES_INIT; 321 psa_key_id_t psa_key_id = PSA_KEY_ID_NULL; 322 psa_key_type_t psa_key_type; 323 psa_algorithm_t psa_alg; 324 325 /* Get pointers to signature OID and parameters */ 326 p = (unsigned char *)sig_alg; 327 end = (unsigned char *)(p + sig_alg_len); 328 rc = mbedtls_asn1_get_alg(&p, end, &sig_oid, &sig_params); 329 if (rc != 0) { 330 return CRYPTO_ERR_SIGNATURE; 331 } 332 333 /* Get the actual signature algorithm (MD + PK) */ 334 rc = mbedtls_x509_get_sig_alg(&sig_oid, &sig_params, &md_alg, &pk_alg, &sig_opts); 335 if (rc != 0) { 336 return CRYPTO_ERR_SIGNATURE; 337 } 338 339 /* Get the signature (bitstring) */ 340 p = (unsigned char *)sig_ptr; 341 end = (unsigned char *)(p + sig_len); 342 signature.tag = *p; 343 rc = mbedtls_asn1_get_bitstring_null(&p, end, &signature.len); 344 if ((rc != 0) || ((size_t)(end - p) != signature.len)) { 345 rc = CRYPTO_ERR_SIGNATURE; 346 goto end2; 347 } 348 349 local_sig_ptr = p; 350 local_sig_len = signature.len; 351 352 #if TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_ECDSA || \ 353 TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA_AND_ECDSA 354 if (pk_alg == MBEDTLS_PK_ECDSA) { 355 rc = get_ecdsa_signature_from_asn1(local_sig_ptr, 356 &local_sig_len, 357 reformatted_sig); 358 if (rc != 0) { 359 goto end2; 360 } 361 362 local_sig_ptr = reformatted_sig; 363 364 rc = get_ecdsa_pkinfo_from_asn1((unsigned char **)&pk_ptr, 365 &pk_len, 366 &psa_ecc_family); 367 if (rc != 0) { 368 goto end2; 369 } 370 } 371 #endif /* 372 * TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_ECDSA || \ 373 * TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA_AND_ECDSA 374 **/ 375 376 /* Convert this pk_alg and md_alg to PSA key type and key algorithm */ 377 construct_psa_key_alg_and_type(pk_alg, md_alg, psa_ecc_family, 378 &psa_alg, &psa_key_type); 379 380 381 if ((psa_alg == PSA_ALG_NONE) || (psa_key_type == PSA_KEY_TYPE_NONE)) { 382 rc = CRYPTO_ERR_SIGNATURE; 383 goto end2; 384 } 385 386 /* filled-in key_attributes */ 387 psa_set_key_algorithm(&psa_key_attr, psa_alg); 388 psa_set_key_type(&psa_key_attr, psa_key_type); 389 psa_set_key_usage_flags(&psa_key_attr, PSA_KEY_USAGE_VERIFY_MESSAGE); 390 391 /* Get the key_id using import API */ 392 status = psa_import_key(&psa_key_attr, 393 pk_ptr, 394 (size_t)pk_len, 395 &psa_key_id); 396 397 if (status != PSA_SUCCESS) { 398 rc = CRYPTO_ERR_SIGNATURE; 399 goto end2; 400 } 401 402 /* 403 * Hash calculation and Signature verification of the given data payload 404 * is wrapped under the psa_verify_message function. 405 */ 406 status = psa_verify_message(psa_key_id, psa_alg, 407 data_ptr, data_len, 408 local_sig_ptr, local_sig_len); 409 410 if (status != PSA_SUCCESS) { 411 rc = CRYPTO_ERR_SIGNATURE; 412 goto end1; 413 } 414 415 /* Signature verification success */ 416 rc = CRYPTO_SUCCESS; 417 418 end1: 419 /* 420 * Destroy the key if it is created successfully 421 */ 422 psa_destroy_key(psa_key_id); 423 end2: 424 mbedtls_free(sig_opts); 425 return rc; 426 } 427 428 /* 429 * Match a hash 430 * 431 * Digest info is passed in DER format following the ASN.1 structure detailed 432 * above. 433 */ 434 static int verify_hash(void *data_ptr, unsigned int data_len, 435 void *digest_info_ptr, unsigned int digest_info_len) 436 { 437 mbedtls_asn1_buf hash_oid, params; 438 mbedtls_md_type_t md_alg; 439 unsigned char *p, *end, *hash; 440 size_t len; 441 int rc; 442 psa_status_t status; 443 psa_algorithm_t psa_md_alg; 444 445 /* 446 * Digest info should be an MBEDTLS_ASN1_SEQUENCE, but padding after 447 * it is allowed. This is necessary to support multiple hash 448 * algorithms. 449 */ 450 p = (unsigned char *)digest_info_ptr; 451 end = p + digest_info_len; 452 rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | 453 MBEDTLS_ASN1_SEQUENCE); 454 if (rc != 0) { 455 return CRYPTO_ERR_HASH; 456 } 457 458 end = p + len; 459 460 /* Get the hash algorithm */ 461 rc = mbedtls_asn1_get_alg(&p, end, &hash_oid, ¶ms); 462 if (rc != 0) { 463 return CRYPTO_ERR_HASH; 464 } 465 466 /* Hash should be octet string type and consume all bytes */ 467 rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING); 468 if ((rc != 0) || ((size_t)(end - p) != len)) { 469 return CRYPTO_ERR_HASH; 470 } 471 hash = p; 472 473 rc = mbedtls_oid_get_md_alg(&hash_oid, &md_alg); 474 if (rc != 0) { 475 return CRYPTO_ERR_HASH; 476 } 477 478 /* convert the md_alg to psa_algo */ 479 psa_md_alg = mbedtls_md_psa_alg_from_type(md_alg); 480 481 /* Length of hash must match the algorithm's size */ 482 if (len != PSA_HASH_LENGTH(psa_md_alg)) { 483 return CRYPTO_ERR_HASH; 484 } 485 486 /* 487 * Calculate Hash and compare it against the retrieved hash from 488 * the certificate (one shot API). 489 */ 490 status = psa_hash_compare(psa_md_alg, 491 data_ptr, (size_t)data_len, 492 (const uint8_t *)hash, len); 493 494 if (status != PSA_SUCCESS) { 495 return CRYPTO_ERR_HASH; 496 } 497 498 return CRYPTO_SUCCESS; 499 } 500 #endif /* 501 * CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \ 502 * CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC 503 */ 504 505 #if CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \ 506 CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC 507 /* 508 * Map a generic crypto message digest algorithm to the corresponding macro used 509 * by Mbed TLS. 510 */ 511 static inline mbedtls_md_type_t md_type(enum crypto_md_algo algo) 512 { 513 switch (algo) { 514 case CRYPTO_MD_SHA512: 515 return MBEDTLS_MD_SHA512; 516 case CRYPTO_MD_SHA384: 517 return MBEDTLS_MD_SHA384; 518 case CRYPTO_MD_SHA256: 519 return MBEDTLS_MD_SHA256; 520 default: 521 /* Invalid hash algorithm. */ 522 return MBEDTLS_MD_NONE; 523 } 524 } 525 526 /* 527 * Calculate a hash 528 * 529 * output points to the computed hash 530 */ 531 static int calc_hash(enum crypto_md_algo md_algo, void *data_ptr, 532 unsigned int data_len, 533 unsigned char output[CRYPTO_MD_MAX_SIZE]) 534 { 535 size_t hash_length; 536 psa_status_t status; 537 psa_algorithm_t psa_md_alg; 538 539 /* convert the md_alg to psa_algo */ 540 psa_md_alg = mbedtls_md_psa_alg_from_type(md_type(md_algo)); 541 542 /* 543 * Calculate the hash of the data, it is safe to pass the 544 * 'output' hash buffer pointer considering its size is always 545 * bigger than or equal to MBEDTLS_MD_MAX_SIZE. 546 */ 547 status = psa_hash_compute(psa_md_alg, data_ptr, (size_t)data_len, 548 (uint8_t *)output, CRYPTO_MD_MAX_SIZE, 549 &hash_length); 550 if (status != PSA_SUCCESS) { 551 return CRYPTO_ERR_HASH; 552 } 553 554 return CRYPTO_SUCCESS; 555 } 556 #endif /* 557 * CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \ 558 * CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC 559 */ 560 561 #if TF_MBEDTLS_USE_AES_GCM 562 /* 563 * Stack based buffer allocation for decryption operation. It could 564 * be configured to balance stack usage vs execution speed. 565 */ 566 #define DEC_OP_BUF_SIZE 128 567 568 static int aes_gcm_decrypt(void *data_ptr, size_t len, const void *key, 569 unsigned int key_len, const void *iv, 570 unsigned int iv_len, const void *tag, 571 unsigned int tag_len) 572 { 573 mbedtls_gcm_context ctx; 574 mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES; 575 unsigned char buf[DEC_OP_BUF_SIZE]; 576 unsigned char tag_buf[CRYPTO_MAX_TAG_SIZE]; 577 unsigned char *pt = data_ptr; 578 size_t dec_len; 579 int diff, i, rc; 580 size_t output_length __unused; 581 582 mbedtls_gcm_init(&ctx); 583 584 rc = mbedtls_gcm_setkey(&ctx, cipher, key, key_len * 8); 585 if (rc != 0) { 586 rc = CRYPTO_ERR_DECRYPTION; 587 goto exit_gcm; 588 } 589 590 #if (MBEDTLS_VERSION_MAJOR < 3) 591 rc = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT, iv, iv_len, NULL, 0); 592 #else 593 rc = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT, iv, iv_len); 594 #endif 595 if (rc != 0) { 596 rc = CRYPTO_ERR_DECRYPTION; 597 goto exit_gcm; 598 } 599 600 while (len > 0) { 601 dec_len = MIN(sizeof(buf), len); 602 603 #if (MBEDTLS_VERSION_MAJOR < 3) 604 rc = mbedtls_gcm_update(&ctx, dec_len, pt, buf); 605 #else 606 rc = mbedtls_gcm_update(&ctx, pt, dec_len, buf, sizeof(buf), &output_length); 607 #endif 608 609 if (rc != 0) { 610 rc = CRYPTO_ERR_DECRYPTION; 611 goto exit_gcm; 612 } 613 614 memcpy(pt, buf, dec_len); 615 pt += dec_len; 616 len -= dec_len; 617 } 618 619 #if (MBEDTLS_VERSION_MAJOR < 3) 620 rc = mbedtls_gcm_finish(&ctx, tag_buf, sizeof(tag_buf)); 621 #else 622 rc = mbedtls_gcm_finish(&ctx, NULL, 0, &output_length, tag_buf, sizeof(tag_buf)); 623 #endif 624 625 if (rc != 0) { 626 rc = CRYPTO_ERR_DECRYPTION; 627 goto exit_gcm; 628 } 629 630 /* Check tag in "constant-time" */ 631 for (diff = 0, i = 0; i < tag_len; i++) 632 diff |= ((const unsigned char *)tag)[i] ^ tag_buf[i]; 633 634 if (diff != 0) { 635 rc = CRYPTO_ERR_DECRYPTION; 636 goto exit_gcm; 637 } 638 639 /* GCM decryption success */ 640 rc = CRYPTO_SUCCESS; 641 642 exit_gcm: 643 mbedtls_gcm_free(&ctx); 644 return rc; 645 } 646 647 /* 648 * Authenticated decryption of an image 649 */ 650 static int auth_decrypt(enum crypto_dec_algo dec_algo, void *data_ptr, 651 size_t len, const void *key, unsigned int key_len, 652 unsigned int key_flags, const void *iv, 653 unsigned int iv_len, const void *tag, 654 unsigned int tag_len) 655 { 656 int rc; 657 658 assert((key_flags & ENC_KEY_IS_IDENTIFIER) == 0); 659 660 switch (dec_algo) { 661 case CRYPTO_GCM_DECRYPT: 662 rc = aes_gcm_decrypt(data_ptr, len, key, key_len, iv, iv_len, 663 tag, tag_len); 664 if (rc != 0) 665 return rc; 666 break; 667 default: 668 return CRYPTO_ERR_DECRYPTION; 669 } 670 671 return CRYPTO_SUCCESS; 672 } 673 #endif /* TF_MBEDTLS_USE_AES_GCM */ 674 675 /* 676 * Register crypto library descriptor 677 */ 678 #if CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC 679 #if TF_MBEDTLS_USE_AES_GCM 680 REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash, 681 auth_decrypt, NULL); 682 #else 683 REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash, 684 NULL, NULL); 685 #endif 686 #elif CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY 687 #if TF_MBEDTLS_USE_AES_GCM 688 REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL, 689 auth_decrypt, NULL); 690 #else 691 REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL, 692 NULL, NULL); 693 #endif 694 #elif CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY 695 REGISTER_CRYPTO_LIB(LIB_NAME, init, NULL, NULL, calc_hash, NULL, NULL); 696 #endif /* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */ 697