138f89369SManish V Badarkhe /* 238f89369SManish V Badarkhe * Copyright (c) 2023, Arm Limited. All rights reserved. 338f89369SManish V Badarkhe * 438f89369SManish V Badarkhe * SPDX-License-Identifier: BSD-3-Clause 538f89369SManish V Badarkhe */ 638f89369SManish V Badarkhe 738f89369SManish V Badarkhe #include <assert.h> 838f89369SManish V Badarkhe #include <stddef.h> 938f89369SManish V Badarkhe #include <string.h> 1038f89369SManish V Badarkhe 1138f89369SManish V Badarkhe /* mbed TLS headers */ 1238f89369SManish V Badarkhe #include <mbedtls/gcm.h> 1338f89369SManish V Badarkhe #include <mbedtls/md.h> 1438f89369SManish V Badarkhe #include <mbedtls/memory_buffer_alloc.h> 1538f89369SManish V Badarkhe #include <mbedtls/oid.h> 1638f89369SManish V Badarkhe #include <mbedtls/platform.h> 1738f89369SManish V Badarkhe #include <mbedtls/version.h> 1838f89369SManish V Badarkhe #include <mbedtls/x509.h> 194eaaaa19SManish V Badarkhe #include <psa/crypto.h> 204eaaaa19SManish V Badarkhe #include <psa/crypto_platform.h> 214eaaaa19SManish V Badarkhe #include <psa/crypto_types.h> 224eaaaa19SManish V Badarkhe #include <psa/crypto_values.h> 2338f89369SManish V Badarkhe 2438f89369SManish V Badarkhe #include <common/debug.h> 2538f89369SManish V Badarkhe #include <drivers/auth/crypto_mod.h> 2638f89369SManish V Badarkhe #include <drivers/auth/mbedtls/mbedtls_common.h> 2738f89369SManish V Badarkhe #include <plat/common/platform.h> 2838f89369SManish V Badarkhe 2938f89369SManish V Badarkhe #define LIB_NAME "mbed TLS PSA" 3038f89369SManish V Badarkhe 3138f89369SManish V Badarkhe #if CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \ 3238f89369SManish V Badarkhe CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC 3338f89369SManish V Badarkhe /* 3438f89369SManish V Badarkhe * CRYPTO_MD_MAX_SIZE value is as per current stronger algorithm available 3538f89369SManish V Badarkhe * so make sure that mbed TLS MD maximum size must be lesser than this. 3638f89369SManish V Badarkhe */ 3738f89369SManish V Badarkhe CASSERT(CRYPTO_MD_MAX_SIZE >= MBEDTLS_MD_MAX_SIZE, 3838f89369SManish V Badarkhe assert_mbedtls_md_size_overflow); 3938f89369SManish V Badarkhe 4038f89369SManish V Badarkhe #endif /* 4138f89369SManish V Badarkhe * CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \ 4238f89369SManish V Badarkhe * CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC 4338f89369SManish V Badarkhe */ 4438f89369SManish V Badarkhe 45*2ed061c4SManish V Badarkhe static inline psa_algorithm_t mbedtls_md_psa_alg_from_type( 46*2ed061c4SManish V Badarkhe mbedtls_md_type_t md_type) 47*2ed061c4SManish V Badarkhe { 48*2ed061c4SManish V Badarkhe assert((md_type == MBEDTLS_MD_SHA256) || 49*2ed061c4SManish V Badarkhe (md_type == MBEDTLS_MD_SHA384) || 50*2ed061c4SManish V Badarkhe (md_type == MBEDTLS_MD_SHA512)); 51*2ed061c4SManish V Badarkhe 52*2ed061c4SManish V Badarkhe return PSA_ALG_CATEGORY_HASH | (psa_algorithm_t) (md_type + 0x5); 53*2ed061c4SManish V Badarkhe } 54*2ed061c4SManish V Badarkhe 5538f89369SManish V Badarkhe /* 5638f89369SManish V Badarkhe * AlgorithmIdentifier ::= SEQUENCE { 5738f89369SManish V Badarkhe * algorithm OBJECT IDENTIFIER, 5838f89369SManish V Badarkhe * parameters ANY DEFINED BY algorithm OPTIONAL 5938f89369SManish V Badarkhe * } 6038f89369SManish V Badarkhe * 6138f89369SManish V Badarkhe * SubjectPublicKeyInfo ::= SEQUENCE { 6238f89369SManish V Badarkhe * algorithm AlgorithmIdentifier, 6338f89369SManish V Badarkhe * subjectPublicKey BIT STRING 6438f89369SManish V Badarkhe * } 6538f89369SManish V Badarkhe * 6638f89369SManish V Badarkhe * DigestInfo ::= SEQUENCE { 6738f89369SManish V Badarkhe * digestAlgorithm AlgorithmIdentifier, 6838f89369SManish V Badarkhe * digest OCTET STRING 6938f89369SManish V Badarkhe * } 7038f89369SManish V Badarkhe */ 7138f89369SManish V Badarkhe 7238f89369SManish V Badarkhe /* 734eaaaa19SManish V Badarkhe * We pretend using an external RNG (through MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG 744eaaaa19SManish V Badarkhe * mbedTLS config option) so we need to provide an implementation of 754eaaaa19SManish V Badarkhe * mbedtls_psa_external_get_random(). Provide a fake one, since we do not 764eaaaa19SManish V Badarkhe * actually have any external RNG and TF-A itself doesn't engage in 774eaaaa19SManish V Badarkhe * cryptographic operations that demands randomness. 784eaaaa19SManish V Badarkhe */ 794eaaaa19SManish V Badarkhe psa_status_t mbedtls_psa_external_get_random( 804eaaaa19SManish V Badarkhe mbedtls_psa_external_random_context_t *context, 814eaaaa19SManish V Badarkhe uint8_t *output, size_t output_size, 824eaaaa19SManish V Badarkhe size_t *output_length) 834eaaaa19SManish V Badarkhe { 844eaaaa19SManish V Badarkhe return PSA_ERROR_INSUFFICIENT_ENTROPY; 854eaaaa19SManish V Badarkhe } 864eaaaa19SManish V Badarkhe 874eaaaa19SManish V Badarkhe /* 8838f89369SManish V Badarkhe * Initialize the library and export the descriptor 8938f89369SManish V Badarkhe */ 9038f89369SManish V Badarkhe static void init(void) 9138f89369SManish V Badarkhe { 9238f89369SManish V Badarkhe /* Initialize mbed TLS */ 9338f89369SManish V Badarkhe mbedtls_init(); 944eaaaa19SManish V Badarkhe 954eaaaa19SManish V Badarkhe /* Initialise PSA mbedTLS */ 964eaaaa19SManish V Badarkhe psa_status_t status = psa_crypto_init(); 974eaaaa19SManish V Badarkhe 984eaaaa19SManish V Badarkhe if (status != PSA_SUCCESS) { 994eaaaa19SManish V Badarkhe ERROR("Failed to initialize %s crypto (%d).\n", LIB_NAME, status); 1004eaaaa19SManish V Badarkhe panic(); 1014eaaaa19SManish V Badarkhe } 1024eaaaa19SManish V Badarkhe 1034eaaaa19SManish V Badarkhe INFO("PSA crypto initialized successfully!\n"); 10438f89369SManish V Badarkhe } 10538f89369SManish V Badarkhe 10638f89369SManish V Badarkhe #if CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \ 10738f89369SManish V Badarkhe CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC 10838f89369SManish V Badarkhe /* 10938f89369SManish V Badarkhe * Verify a signature. 11038f89369SManish V Badarkhe * 11138f89369SManish V Badarkhe * Parameters are passed using the DER encoding format following the ASN.1 11238f89369SManish V Badarkhe * structures detailed above. 11338f89369SManish V Badarkhe */ 11438f89369SManish V Badarkhe static int verify_signature(void *data_ptr, unsigned int data_len, 11538f89369SManish V Badarkhe void *sig_ptr, unsigned int sig_len, 11638f89369SManish V Badarkhe void *sig_alg, unsigned int sig_alg_len, 11738f89369SManish V Badarkhe void *pk_ptr, unsigned int pk_len) 11838f89369SManish V Badarkhe { 11938f89369SManish V Badarkhe mbedtls_asn1_buf sig_oid, sig_params; 12038f89369SManish V Badarkhe mbedtls_asn1_buf signature; 12138f89369SManish V Badarkhe mbedtls_md_type_t md_alg; 12238f89369SManish V Badarkhe mbedtls_pk_type_t pk_alg; 12338f89369SManish V Badarkhe mbedtls_pk_context pk = {0}; 12438f89369SManish V Badarkhe int rc; 12538f89369SManish V Badarkhe void *sig_opts = NULL; 12638f89369SManish V Badarkhe const mbedtls_md_info_t *md_info; 12738f89369SManish V Badarkhe unsigned char *p, *end; 12838f89369SManish V Badarkhe unsigned char hash[MBEDTLS_MD_MAX_SIZE]; 12938f89369SManish V Badarkhe 13038f89369SManish V Badarkhe /* Get pointers to signature OID and parameters */ 13138f89369SManish V Badarkhe p = (unsigned char *)sig_alg; 13238f89369SManish V Badarkhe end = (unsigned char *)(p + sig_alg_len); 13338f89369SManish V Badarkhe rc = mbedtls_asn1_get_alg(&p, end, &sig_oid, &sig_params); 13438f89369SManish V Badarkhe if (rc != 0) { 13538f89369SManish V Badarkhe return CRYPTO_ERR_SIGNATURE; 13638f89369SManish V Badarkhe } 13738f89369SManish V Badarkhe 13838f89369SManish V Badarkhe /* Get the actual signature algorithm (MD + PK) */ 13938f89369SManish V Badarkhe rc = mbedtls_x509_get_sig_alg(&sig_oid, &sig_params, &md_alg, &pk_alg, &sig_opts); 14038f89369SManish V Badarkhe if (rc != 0) { 14138f89369SManish V Badarkhe return CRYPTO_ERR_SIGNATURE; 14238f89369SManish V Badarkhe } 14338f89369SManish V Badarkhe 14438f89369SManish V Badarkhe /* Parse the public key */ 14538f89369SManish V Badarkhe mbedtls_pk_init(&pk); 14638f89369SManish V Badarkhe p = (unsigned char *)pk_ptr; 14738f89369SManish V Badarkhe end = (unsigned char *)(p + pk_len); 14838f89369SManish V Badarkhe rc = mbedtls_pk_parse_subpubkey(&p, end, &pk); 14938f89369SManish V Badarkhe if (rc != 0) { 15038f89369SManish V Badarkhe rc = CRYPTO_ERR_SIGNATURE; 15138f89369SManish V Badarkhe goto end2; 15238f89369SManish V Badarkhe } 15338f89369SManish V Badarkhe 15438f89369SManish V Badarkhe /* Get the signature (bitstring) */ 15538f89369SManish V Badarkhe p = (unsigned char *)sig_ptr; 15638f89369SManish V Badarkhe end = (unsigned char *)(p + sig_len); 15738f89369SManish V Badarkhe signature.tag = *p; 15838f89369SManish V Badarkhe rc = mbedtls_asn1_get_bitstring_null(&p, end, &signature.len); 15938f89369SManish V Badarkhe if ((rc != 0) || ((size_t)(end - p) != signature.len)) { 16038f89369SManish V Badarkhe rc = CRYPTO_ERR_SIGNATURE; 16138f89369SManish V Badarkhe goto end1; 16238f89369SManish V Badarkhe } 16338f89369SManish V Badarkhe signature.p = p; 16438f89369SManish V Badarkhe 16538f89369SManish V Badarkhe /* Calculate the hash of the data */ 16638f89369SManish V Badarkhe md_info = mbedtls_md_info_from_type(md_alg); 16738f89369SManish V Badarkhe if (md_info == NULL) { 16838f89369SManish V Badarkhe rc = CRYPTO_ERR_SIGNATURE; 16938f89369SManish V Badarkhe goto end1; 17038f89369SManish V Badarkhe } 17138f89369SManish V Badarkhe p = (unsigned char *)data_ptr; 17238f89369SManish V Badarkhe rc = mbedtls_md(md_info, p, data_len, hash); 17338f89369SManish V Badarkhe if (rc != 0) { 17438f89369SManish V Badarkhe rc = CRYPTO_ERR_SIGNATURE; 17538f89369SManish V Badarkhe goto end1; 17638f89369SManish V Badarkhe } 17738f89369SManish V Badarkhe 17838f89369SManish V Badarkhe /* Verify the signature */ 17938f89369SManish V Badarkhe rc = mbedtls_pk_verify_ext(pk_alg, sig_opts, &pk, md_alg, hash, 18038f89369SManish V Badarkhe mbedtls_md_get_size(md_info), 18138f89369SManish V Badarkhe signature.p, signature.len); 18238f89369SManish V Badarkhe if (rc != 0) { 18338f89369SManish V Badarkhe rc = CRYPTO_ERR_SIGNATURE; 18438f89369SManish V Badarkhe goto end1; 18538f89369SManish V Badarkhe } 18638f89369SManish V Badarkhe 18738f89369SManish V Badarkhe /* Signature verification success */ 18838f89369SManish V Badarkhe rc = CRYPTO_SUCCESS; 18938f89369SManish V Badarkhe 19038f89369SManish V Badarkhe end1: 19138f89369SManish V Badarkhe mbedtls_pk_free(&pk); 19238f89369SManish V Badarkhe end2: 19338f89369SManish V Badarkhe mbedtls_free(sig_opts); 19438f89369SManish V Badarkhe return rc; 19538f89369SManish V Badarkhe } 19638f89369SManish V Badarkhe 19738f89369SManish V Badarkhe /* 19838f89369SManish V Badarkhe * Match a hash 19938f89369SManish V Badarkhe * 20038f89369SManish V Badarkhe * Digest info is passed in DER format following the ASN.1 structure detailed 20138f89369SManish V Badarkhe * above. 20238f89369SManish V Badarkhe */ 20338f89369SManish V Badarkhe static int verify_hash(void *data_ptr, unsigned int data_len, 20438f89369SManish V Badarkhe void *digest_info_ptr, unsigned int digest_info_len) 20538f89369SManish V Badarkhe { 20638f89369SManish V Badarkhe mbedtls_asn1_buf hash_oid, params; 20738f89369SManish V Badarkhe mbedtls_md_type_t md_alg; 20838f89369SManish V Badarkhe unsigned char *p, *end, *hash; 20938f89369SManish V Badarkhe size_t len; 21038f89369SManish V Badarkhe int rc; 211*2ed061c4SManish V Badarkhe psa_status_t status; 212*2ed061c4SManish V Badarkhe psa_algorithm_t psa_md_alg; 21338f89369SManish V Badarkhe 21438f89369SManish V Badarkhe /* 21538f89369SManish V Badarkhe * Digest info should be an MBEDTLS_ASN1_SEQUENCE, but padding after 21638f89369SManish V Badarkhe * it is allowed. This is necessary to support multiple hash 21738f89369SManish V Badarkhe * algorithms. 21838f89369SManish V Badarkhe */ 21938f89369SManish V Badarkhe p = (unsigned char *)digest_info_ptr; 22038f89369SManish V Badarkhe end = p + digest_info_len; 22138f89369SManish V Badarkhe rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | 22238f89369SManish V Badarkhe MBEDTLS_ASN1_SEQUENCE); 22338f89369SManish V Badarkhe if (rc != 0) { 22438f89369SManish V Badarkhe return CRYPTO_ERR_HASH; 22538f89369SManish V Badarkhe } 22638f89369SManish V Badarkhe 22738f89369SManish V Badarkhe end = p + len; 22838f89369SManish V Badarkhe 22938f89369SManish V Badarkhe /* Get the hash algorithm */ 23038f89369SManish V Badarkhe rc = mbedtls_asn1_get_alg(&p, end, &hash_oid, ¶ms); 23138f89369SManish V Badarkhe if (rc != 0) { 23238f89369SManish V Badarkhe return CRYPTO_ERR_HASH; 23338f89369SManish V Badarkhe } 23438f89369SManish V Badarkhe 23538f89369SManish V Badarkhe /* Hash should be octet string type and consume all bytes */ 23638f89369SManish V Badarkhe rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING); 23738f89369SManish V Badarkhe if ((rc != 0) || ((size_t)(end - p) != len)) { 23838f89369SManish V Badarkhe return CRYPTO_ERR_HASH; 23938f89369SManish V Badarkhe } 24038f89369SManish V Badarkhe hash = p; 24138f89369SManish V Badarkhe 242*2ed061c4SManish V Badarkhe rc = mbedtls_oid_get_md_alg(&hash_oid, &md_alg); 24338f89369SManish V Badarkhe if (rc != 0) { 24438f89369SManish V Badarkhe return CRYPTO_ERR_HASH; 24538f89369SManish V Badarkhe } 24638f89369SManish V Badarkhe 247*2ed061c4SManish V Badarkhe /* convert the md_alg to psa_algo */ 248*2ed061c4SManish V Badarkhe psa_md_alg = mbedtls_md_psa_alg_from_type(md_alg); 249*2ed061c4SManish V Badarkhe 250*2ed061c4SManish V Badarkhe /* Length of hash must match the algorithm's size */ 251*2ed061c4SManish V Badarkhe if (len != PSA_HASH_LENGTH(psa_md_alg)) { 252*2ed061c4SManish V Badarkhe return CRYPTO_ERR_HASH; 253*2ed061c4SManish V Badarkhe } 254*2ed061c4SManish V Badarkhe 255*2ed061c4SManish V Badarkhe /* 256*2ed061c4SManish V Badarkhe * Calculate Hash and compare it against the retrieved hash from 257*2ed061c4SManish V Badarkhe * the certificate (one shot API). 258*2ed061c4SManish V Badarkhe */ 259*2ed061c4SManish V Badarkhe status = psa_hash_compare(psa_md_alg, 260*2ed061c4SManish V Badarkhe data_ptr, (size_t)data_len, 261*2ed061c4SManish V Badarkhe (const uint8_t *)hash, len); 262*2ed061c4SManish V Badarkhe 263*2ed061c4SManish V Badarkhe if (status != PSA_SUCCESS) { 26438f89369SManish V Badarkhe return CRYPTO_ERR_HASH; 26538f89369SManish V Badarkhe } 26638f89369SManish V Badarkhe 26738f89369SManish V Badarkhe return CRYPTO_SUCCESS; 26838f89369SManish V Badarkhe } 26938f89369SManish V Badarkhe #endif /* 27038f89369SManish V Badarkhe * CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \ 27138f89369SManish V Badarkhe * CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC 27238f89369SManish V Badarkhe */ 27338f89369SManish V Badarkhe 27438f89369SManish V Badarkhe #if CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \ 27538f89369SManish V Badarkhe CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC 27638f89369SManish V Badarkhe /* 27738f89369SManish V Badarkhe * Map a generic crypto message digest algorithm to the corresponding macro used 27838f89369SManish V Badarkhe * by Mbed TLS. 27938f89369SManish V Badarkhe */ 28038f89369SManish V Badarkhe static inline mbedtls_md_type_t md_type(enum crypto_md_algo algo) 28138f89369SManish V Badarkhe { 28238f89369SManish V Badarkhe switch (algo) { 28338f89369SManish V Badarkhe case CRYPTO_MD_SHA512: 28438f89369SManish V Badarkhe return MBEDTLS_MD_SHA512; 28538f89369SManish V Badarkhe case CRYPTO_MD_SHA384: 28638f89369SManish V Badarkhe return MBEDTLS_MD_SHA384; 28738f89369SManish V Badarkhe case CRYPTO_MD_SHA256: 28838f89369SManish V Badarkhe return MBEDTLS_MD_SHA256; 28938f89369SManish V Badarkhe default: 29038f89369SManish V Badarkhe /* Invalid hash algorithm. */ 29138f89369SManish V Badarkhe return MBEDTLS_MD_NONE; 29238f89369SManish V Badarkhe } 29338f89369SManish V Badarkhe } 29438f89369SManish V Badarkhe 29538f89369SManish V Badarkhe /* 29638f89369SManish V Badarkhe * Calculate a hash 29738f89369SManish V Badarkhe * 29838f89369SManish V Badarkhe * output points to the computed hash 29938f89369SManish V Badarkhe */ 30038f89369SManish V Badarkhe static int calc_hash(enum crypto_md_algo md_algo, void *data_ptr, 30138f89369SManish V Badarkhe unsigned int data_len, 30238f89369SManish V Badarkhe unsigned char output[CRYPTO_MD_MAX_SIZE]) 30338f89369SManish V Badarkhe { 30438f89369SManish V Badarkhe const mbedtls_md_info_t *md_info; 30538f89369SManish V Badarkhe 30638f89369SManish V Badarkhe md_info = mbedtls_md_info_from_type(md_type(md_algo)); 30738f89369SManish V Badarkhe if (md_info == NULL) { 30838f89369SManish V Badarkhe return CRYPTO_ERR_HASH; 30938f89369SManish V Badarkhe } 31038f89369SManish V Badarkhe 31138f89369SManish V Badarkhe /* 31238f89369SManish V Badarkhe * Calculate the hash of the data, it is safe to pass the 31338f89369SManish V Badarkhe * 'output' hash buffer pointer considering its size is always 31438f89369SManish V Badarkhe * bigger than or equal to MBEDTLS_MD_MAX_SIZE. 31538f89369SManish V Badarkhe */ 31638f89369SManish V Badarkhe return mbedtls_md(md_info, data_ptr, data_len, output); 31738f89369SManish V Badarkhe } 31838f89369SManish V Badarkhe #endif /* 31938f89369SManish V Badarkhe * CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \ 32038f89369SManish V Badarkhe * CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC 32138f89369SManish V Badarkhe */ 32238f89369SManish V Badarkhe 32338f89369SManish V Badarkhe #if TF_MBEDTLS_USE_AES_GCM 32438f89369SManish V Badarkhe /* 32538f89369SManish V Badarkhe * Stack based buffer allocation for decryption operation. It could 32638f89369SManish V Badarkhe * be configured to balance stack usage vs execution speed. 32738f89369SManish V Badarkhe */ 32838f89369SManish V Badarkhe #define DEC_OP_BUF_SIZE 128 32938f89369SManish V Badarkhe 33038f89369SManish V Badarkhe static int aes_gcm_decrypt(void *data_ptr, size_t len, const void *key, 33138f89369SManish V Badarkhe unsigned int key_len, const void *iv, 33238f89369SManish V Badarkhe unsigned int iv_len, const void *tag, 33338f89369SManish V Badarkhe unsigned int tag_len) 33438f89369SManish V Badarkhe { 33538f89369SManish V Badarkhe mbedtls_gcm_context ctx; 33638f89369SManish V Badarkhe mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES; 33738f89369SManish V Badarkhe unsigned char buf[DEC_OP_BUF_SIZE]; 33838f89369SManish V Badarkhe unsigned char tag_buf[CRYPTO_MAX_TAG_SIZE]; 33938f89369SManish V Badarkhe unsigned char *pt = data_ptr; 34038f89369SManish V Badarkhe size_t dec_len; 34138f89369SManish V Badarkhe int diff, i, rc; 34238f89369SManish V Badarkhe size_t output_length __unused; 34338f89369SManish V Badarkhe 34438f89369SManish V Badarkhe mbedtls_gcm_init(&ctx); 34538f89369SManish V Badarkhe 34638f89369SManish V Badarkhe rc = mbedtls_gcm_setkey(&ctx, cipher, key, key_len * 8); 34738f89369SManish V Badarkhe if (rc != 0) { 34838f89369SManish V Badarkhe rc = CRYPTO_ERR_DECRYPTION; 34938f89369SManish V Badarkhe goto exit_gcm; 35038f89369SManish V Badarkhe } 35138f89369SManish V Badarkhe 35238f89369SManish V Badarkhe #if (MBEDTLS_VERSION_MAJOR < 3) 35338f89369SManish V Badarkhe rc = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT, iv, iv_len, NULL, 0); 35438f89369SManish V Badarkhe #else 35538f89369SManish V Badarkhe rc = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT, iv, iv_len); 35638f89369SManish V Badarkhe #endif 35738f89369SManish V Badarkhe if (rc != 0) { 35838f89369SManish V Badarkhe rc = CRYPTO_ERR_DECRYPTION; 35938f89369SManish V Badarkhe goto exit_gcm; 36038f89369SManish V Badarkhe } 36138f89369SManish V Badarkhe 36238f89369SManish V Badarkhe while (len > 0) { 36338f89369SManish V Badarkhe dec_len = MIN(sizeof(buf), len); 36438f89369SManish V Badarkhe 36538f89369SManish V Badarkhe #if (MBEDTLS_VERSION_MAJOR < 3) 36638f89369SManish V Badarkhe rc = mbedtls_gcm_update(&ctx, dec_len, pt, buf); 36738f89369SManish V Badarkhe #else 36838f89369SManish V Badarkhe rc = mbedtls_gcm_update(&ctx, pt, dec_len, buf, sizeof(buf), &output_length); 36938f89369SManish V Badarkhe #endif 37038f89369SManish V Badarkhe 37138f89369SManish V Badarkhe if (rc != 0) { 37238f89369SManish V Badarkhe rc = CRYPTO_ERR_DECRYPTION; 37338f89369SManish V Badarkhe goto exit_gcm; 37438f89369SManish V Badarkhe } 37538f89369SManish V Badarkhe 37638f89369SManish V Badarkhe memcpy(pt, buf, dec_len); 37738f89369SManish V Badarkhe pt += dec_len; 37838f89369SManish V Badarkhe len -= dec_len; 37938f89369SManish V Badarkhe } 38038f89369SManish V Badarkhe 38138f89369SManish V Badarkhe #if (MBEDTLS_VERSION_MAJOR < 3) 38238f89369SManish V Badarkhe rc = mbedtls_gcm_finish(&ctx, tag_buf, sizeof(tag_buf)); 38338f89369SManish V Badarkhe #else 38438f89369SManish V Badarkhe rc = mbedtls_gcm_finish(&ctx, NULL, 0, &output_length, tag_buf, sizeof(tag_buf)); 38538f89369SManish V Badarkhe #endif 38638f89369SManish V Badarkhe 38738f89369SManish V Badarkhe if (rc != 0) { 38838f89369SManish V Badarkhe rc = CRYPTO_ERR_DECRYPTION; 38938f89369SManish V Badarkhe goto exit_gcm; 39038f89369SManish V Badarkhe } 39138f89369SManish V Badarkhe 39238f89369SManish V Badarkhe /* Check tag in "constant-time" */ 39338f89369SManish V Badarkhe for (diff = 0, i = 0; i < tag_len; i++) 39438f89369SManish V Badarkhe diff |= ((const unsigned char *)tag)[i] ^ tag_buf[i]; 39538f89369SManish V Badarkhe 39638f89369SManish V Badarkhe if (diff != 0) { 39738f89369SManish V Badarkhe rc = CRYPTO_ERR_DECRYPTION; 39838f89369SManish V Badarkhe goto exit_gcm; 39938f89369SManish V Badarkhe } 40038f89369SManish V Badarkhe 40138f89369SManish V Badarkhe /* GCM decryption success */ 40238f89369SManish V Badarkhe rc = CRYPTO_SUCCESS; 40338f89369SManish V Badarkhe 40438f89369SManish V Badarkhe exit_gcm: 40538f89369SManish V Badarkhe mbedtls_gcm_free(&ctx); 40638f89369SManish V Badarkhe return rc; 40738f89369SManish V Badarkhe } 40838f89369SManish V Badarkhe 40938f89369SManish V Badarkhe /* 41038f89369SManish V Badarkhe * Authenticated decryption of an image 41138f89369SManish V Badarkhe */ 41238f89369SManish V Badarkhe static int auth_decrypt(enum crypto_dec_algo dec_algo, void *data_ptr, 41338f89369SManish V Badarkhe size_t len, const void *key, unsigned int key_len, 41438f89369SManish V Badarkhe unsigned int key_flags, const void *iv, 41538f89369SManish V Badarkhe unsigned int iv_len, const void *tag, 41638f89369SManish V Badarkhe unsigned int tag_len) 41738f89369SManish V Badarkhe { 41838f89369SManish V Badarkhe int rc; 41938f89369SManish V Badarkhe 42038f89369SManish V Badarkhe assert((key_flags & ENC_KEY_IS_IDENTIFIER) == 0); 42138f89369SManish V Badarkhe 42238f89369SManish V Badarkhe switch (dec_algo) { 42338f89369SManish V Badarkhe case CRYPTO_GCM_DECRYPT: 42438f89369SManish V Badarkhe rc = aes_gcm_decrypt(data_ptr, len, key, key_len, iv, iv_len, 42538f89369SManish V Badarkhe tag, tag_len); 42638f89369SManish V Badarkhe if (rc != 0) 42738f89369SManish V Badarkhe return rc; 42838f89369SManish V Badarkhe break; 42938f89369SManish V Badarkhe default: 43038f89369SManish V Badarkhe return CRYPTO_ERR_DECRYPTION; 43138f89369SManish V Badarkhe } 43238f89369SManish V Badarkhe 43338f89369SManish V Badarkhe return CRYPTO_SUCCESS; 43438f89369SManish V Badarkhe } 43538f89369SManish V Badarkhe #endif /* TF_MBEDTLS_USE_AES_GCM */ 43638f89369SManish V Badarkhe 43738f89369SManish V Badarkhe /* 43838f89369SManish V Badarkhe * Register crypto library descriptor 43938f89369SManish V Badarkhe */ 44038f89369SManish V Badarkhe #if CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC 44138f89369SManish V Badarkhe #if TF_MBEDTLS_USE_AES_GCM 44238f89369SManish V Badarkhe REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash, 44338f89369SManish V Badarkhe auth_decrypt, NULL); 44438f89369SManish V Badarkhe #else 44538f89369SManish V Badarkhe REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash, 44638f89369SManish V Badarkhe NULL, NULL); 44738f89369SManish V Badarkhe #endif 44838f89369SManish V Badarkhe #elif CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY 44938f89369SManish V Badarkhe #if TF_MBEDTLS_USE_AES_GCM 45038f89369SManish V Badarkhe REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL, 45138f89369SManish V Badarkhe auth_decrypt, NULL); 45238f89369SManish V Badarkhe #else 45338f89369SManish V Badarkhe REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL, 45438f89369SManish V Badarkhe NULL, NULL); 45538f89369SManish V Badarkhe #endif 45638f89369SManish V Badarkhe #elif CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY 45738f89369SManish V Badarkhe REGISTER_CRYPTO_LIB(LIB_NAME, init, NULL, NULL, calc_hash, NULL, NULL); 45838f89369SManish V Badarkhe #endif /* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */ 459