138f89369SManish V Badarkhe /* 255aed7d7SJimmy Brisson * Copyright (c) 2023-2024, 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> 1755aed7d7SJimmy Brisson #include <mbedtls/psa_util.h> 1838f89369SManish V Badarkhe #include <mbedtls/version.h> 1938f89369SManish V Badarkhe #include <mbedtls/x509.h> 204eaaaa19SManish V Badarkhe #include <psa/crypto.h> 214eaaaa19SManish V Badarkhe #include <psa/crypto_platform.h> 224eaaaa19SManish V Badarkhe #include <psa/crypto_types.h> 234eaaaa19SManish V Badarkhe #include <psa/crypto_values.h> 2438f89369SManish V Badarkhe 2538f89369SManish V Badarkhe #include <common/debug.h> 2638f89369SManish V Badarkhe #include <drivers/auth/crypto_mod.h> 2738f89369SManish V Badarkhe #include <drivers/auth/mbedtls/mbedtls_common.h> 2838f89369SManish V Badarkhe #include <plat/common/platform.h> 2938f89369SManish V Badarkhe 3038f89369SManish V Badarkhe #define LIB_NAME "mbed TLS PSA" 3138f89369SManish V Badarkhe 32255ce97dSManish V Badarkhe /* Maximum length of R_S pair in the ECDSA signature in bytes */ 33255ce97dSManish V Badarkhe #define MAX_ECDSA_R_S_PAIR_LEN 64U 34255ce97dSManish V Badarkhe 35255ce97dSManish V Badarkhe /* Size of ASN.1 length and tag in bytes*/ 36255ce97dSManish V Badarkhe #define SIZE_OF_ASN1_LEN 1U 37255ce97dSManish V Badarkhe #define SIZE_OF_ASN1_TAG 1U 38255ce97dSManish V Badarkhe 3938f89369SManish V Badarkhe #if CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \ 4038f89369SManish V Badarkhe CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC 4138f89369SManish V Badarkhe /* 4238f89369SManish V Badarkhe * CRYPTO_MD_MAX_SIZE value is as per current stronger algorithm available 4338f89369SManish V Badarkhe * so make sure that mbed TLS MD maximum size must be lesser than this. 4438f89369SManish V Badarkhe */ 4538f89369SManish V Badarkhe CASSERT(CRYPTO_MD_MAX_SIZE >= MBEDTLS_MD_MAX_SIZE, 4638f89369SManish V Badarkhe assert_mbedtls_md_size_overflow); 4738f89369SManish V Badarkhe 4838f89369SManish V Badarkhe #endif /* 4938f89369SManish V Badarkhe * CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \ 5038f89369SManish V Badarkhe * CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC 5138f89369SManish V Badarkhe */ 5238f89369SManish V Badarkhe 5338f89369SManish V Badarkhe /* 5438f89369SManish V Badarkhe * AlgorithmIdentifier ::= SEQUENCE { 5538f89369SManish V Badarkhe * algorithm OBJECT IDENTIFIER, 5638f89369SManish V Badarkhe * parameters ANY DEFINED BY algorithm OPTIONAL 5738f89369SManish V Badarkhe * } 5838f89369SManish V Badarkhe * 5938f89369SManish V Badarkhe * SubjectPublicKeyInfo ::= SEQUENCE { 6038f89369SManish V Badarkhe * algorithm AlgorithmIdentifier, 6138f89369SManish V Badarkhe * subjectPublicKey BIT STRING 6238f89369SManish V Badarkhe * } 6338f89369SManish V Badarkhe * 6438f89369SManish V Badarkhe * DigestInfo ::= SEQUENCE { 6538f89369SManish V Badarkhe * digestAlgorithm AlgorithmIdentifier, 6638f89369SManish V Badarkhe * digest OCTET STRING 6738f89369SManish V Badarkhe * } 6838f89369SManish V Badarkhe */ 6938f89369SManish V Badarkhe 7038f89369SManish V Badarkhe /* 714eaaaa19SManish V Badarkhe * We pretend using an external RNG (through MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG 724eaaaa19SManish V Badarkhe * mbedTLS config option) so we need to provide an implementation of 734eaaaa19SManish V Badarkhe * mbedtls_psa_external_get_random(). Provide a fake one, since we do not 744eaaaa19SManish V Badarkhe * actually have any external RNG and TF-A itself doesn't engage in 754eaaaa19SManish V Badarkhe * cryptographic operations that demands randomness. 764eaaaa19SManish V Badarkhe */ 774eaaaa19SManish V Badarkhe psa_status_t mbedtls_psa_external_get_random( 784eaaaa19SManish V Badarkhe mbedtls_psa_external_random_context_t *context, 794eaaaa19SManish V Badarkhe uint8_t *output, size_t output_size, 804eaaaa19SManish V Badarkhe size_t *output_length) 814eaaaa19SManish V Badarkhe { 824eaaaa19SManish V Badarkhe return PSA_ERROR_INSUFFICIENT_ENTROPY; 834eaaaa19SManish V Badarkhe } 844eaaaa19SManish V Badarkhe 854eaaaa19SManish V Badarkhe /* 8638f89369SManish V Badarkhe * Initialize the library and export the descriptor 8738f89369SManish V Badarkhe */ 8838f89369SManish V Badarkhe static void init(void) 8938f89369SManish V Badarkhe { 9038f89369SManish V Badarkhe /* Initialize mbed TLS */ 9138f89369SManish V Badarkhe mbedtls_init(); 924eaaaa19SManish V Badarkhe 934eaaaa19SManish V Badarkhe /* Initialise PSA mbedTLS */ 944eaaaa19SManish V Badarkhe psa_status_t status = psa_crypto_init(); 954eaaaa19SManish V Badarkhe 964eaaaa19SManish V Badarkhe if (status != PSA_SUCCESS) { 974eaaaa19SManish V Badarkhe ERROR("Failed to initialize %s crypto (%d).\n", LIB_NAME, status); 984eaaaa19SManish V Badarkhe panic(); 994eaaaa19SManish V Badarkhe } 1004eaaaa19SManish V Badarkhe 1014eaaaa19SManish V Badarkhe INFO("PSA crypto initialized successfully!\n"); 10238f89369SManish V Badarkhe } 10338f89369SManish V Badarkhe 10438f89369SManish V Badarkhe #if CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \ 10538f89369SManish V Badarkhe CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC 106eaa62e82SManish V Badarkhe 10755aed7d7SJimmy Brisson /* 10855aed7d7SJimmy Brisson * NOTE: This has been made internal in mbedtls 3.6.0 and the mbedtls team has 10955aed7d7SJimmy Brisson * advised that it's better to copy out the declaration than it would be to 11055aed7d7SJimmy Brisson * update to 3.5.2, where this function is exposed. 11155aed7d7SJimmy Brisson */ 11255aed7d7SJimmy Brisson int mbedtls_x509_get_sig_alg(const mbedtls_x509_buf *sig_oid, 11355aed7d7SJimmy Brisson const mbedtls_x509_buf *sig_params, 11455aed7d7SJimmy Brisson mbedtls_md_type_t *md_alg, 11555aed7d7SJimmy Brisson mbedtls_pk_type_t *pk_alg, 11655aed7d7SJimmy Brisson void **sig_opts); 117*0bc36c83SRyan Everett 118*0bc36c83SRyan Everett /* 119*0bc36c83SRyan Everett * This is a helper function which parses a SignatureAlgorithm OID. 120*0bc36c83SRyan Everett * It extracts the pk algorithm and constructs a psa_algorithm_t object 121*0bc36c83SRyan Everett * to be used by PSA calls. 122*0bc36c83SRyan Everett */ 123*0bc36c83SRyan Everett static int construct_psa_alg(void *sig_alg, unsigned int sig_alg_len, 124*0bc36c83SRyan Everett mbedtls_pk_type_t *pk_alg, psa_algorithm_t *psa_alg) 125*0bc36c83SRyan Everett { 126*0bc36c83SRyan Everett int rc; 127*0bc36c83SRyan Everett mbedtls_md_type_t md_alg; 128*0bc36c83SRyan Everett void *sig_opts = NULL; 129*0bc36c83SRyan Everett mbedtls_asn1_buf sig_alg_oid, params; 130*0bc36c83SRyan Everett unsigned char *p = (unsigned char *) sig_alg; 131*0bc36c83SRyan Everett unsigned char *end = (unsigned char *) sig_alg + sig_alg_len; 132*0bc36c83SRyan Everett 133*0bc36c83SRyan Everett rc = mbedtls_asn1_get_alg(&p, end, &sig_alg_oid, ¶ms); 134*0bc36c83SRyan Everett if (rc != 0) { 135*0bc36c83SRyan Everett rc = CRYPTO_ERR_SIGNATURE; 136*0bc36c83SRyan Everett goto end; 137*0bc36c83SRyan Everett } 138*0bc36c83SRyan Everett 139*0bc36c83SRyan Everett rc = mbedtls_x509_get_sig_alg(&sig_alg_oid, ¶ms, &md_alg, pk_alg, &sig_opts); 140*0bc36c83SRyan Everett if (rc != 0) { 141*0bc36c83SRyan Everett rc = CRYPTO_ERR_SIGNATURE; 142*0bc36c83SRyan Everett goto end; 143*0bc36c83SRyan Everett } 144*0bc36c83SRyan Everett 145*0bc36c83SRyan Everett psa_algorithm_t psa_md_alg = mbedtls_md_psa_alg_from_type(md_alg); 146*0bc36c83SRyan Everett 147*0bc36c83SRyan Everett switch (*pk_alg) { 148*0bc36c83SRyan Everett case MBEDTLS_PK_RSASSA_PSS: 149*0bc36c83SRyan Everett *psa_alg = PSA_ALG_RSA_PSS(psa_md_alg); 150*0bc36c83SRyan Everett rc = CRYPTO_SUCCESS; 151*0bc36c83SRyan Everett break; 152*0bc36c83SRyan Everett case MBEDTLS_PK_ECDSA: 153*0bc36c83SRyan Everett *psa_alg = PSA_ALG_ECDSA(psa_md_alg); 154*0bc36c83SRyan Everett rc = CRYPTO_SUCCESS; 155*0bc36c83SRyan Everett break; 156*0bc36c83SRyan Everett default: 157*0bc36c83SRyan Everett *psa_alg = PSA_ALG_NONE; 158*0bc36c83SRyan Everett rc = CRYPTO_ERR_SIGNATURE; 159*0bc36c83SRyan Everett break; 160*0bc36c83SRyan Everett } 161*0bc36c83SRyan Everett 162*0bc36c83SRyan Everett end: 163*0bc36c83SRyan Everett mbedtls_free(sig_opts); 164*0bc36c83SRyan Everett return rc; 165*0bc36c83SRyan Everett } 166*0bc36c83SRyan Everett 167*0bc36c83SRyan Everett /* 168*0bc36c83SRyan Everett * Helper functions for mbedtls PK contexts. 169*0bc36c83SRyan Everett */ 170*0bc36c83SRyan Everett static void initialize_pk_context(mbedtls_pk_context *pk, bool *pk_initialized) 171*0bc36c83SRyan Everett { 172*0bc36c83SRyan Everett mbedtls_pk_init(pk); 173*0bc36c83SRyan Everett *pk_initialized = true; 174*0bc36c83SRyan Everett } 175*0bc36c83SRyan Everett 176*0bc36c83SRyan Everett static void cleanup_pk_context(mbedtls_pk_context *pk, bool *pk_initialized) 177*0bc36c83SRyan Everett { 178*0bc36c83SRyan Everett if (*pk_initialized) { 179*0bc36c83SRyan Everett mbedtls_pk_free(pk); 180*0bc36c83SRyan Everett *pk_initialized = false; 181*0bc36c83SRyan Everett } 182*0bc36c83SRyan Everett } 183*0bc36c83SRyan Everett 18455aed7d7SJimmy Brisson /* 18538f89369SManish V Badarkhe * Verify a signature. 18638f89369SManish V Badarkhe * 18738f89369SManish V Badarkhe * Parameters are passed using the DER encoding format following the ASN.1 18838f89369SManish V Badarkhe * structures detailed above. 18938f89369SManish V Badarkhe */ 19038f89369SManish V Badarkhe static int verify_signature(void *data_ptr, unsigned int data_len, 19138f89369SManish V Badarkhe void *sig_ptr, unsigned int sig_len, 19238f89369SManish V Badarkhe void *sig_alg, unsigned int sig_alg_len, 19338f89369SManish V Badarkhe void *pk_ptr, unsigned int pk_len) 19438f89369SManish V Badarkhe { 19538f89369SManish V Badarkhe unsigned char *p, *end; 196*0bc36c83SRyan Everett mbedtls_pk_context pk; 197*0bc36c83SRyan Everett bool pk_initialized = false; 198*0bc36c83SRyan Everett int rc = CRYPTO_ERR_SIGNATURE; 199*0bc36c83SRyan Everett psa_status_t psa_status = PSA_ERROR_CORRUPTION_DETECTED; 200*0bc36c83SRyan Everett psa_key_attributes_t psa_key_attr = PSA_KEY_ATTRIBUTES_INIT; 201*0bc36c83SRyan Everett psa_key_id_t psa_key_id; 202*0bc36c83SRyan Everett mbedtls_pk_type_t pk_alg; 203*0bc36c83SRyan Everett psa_algorithm_t psa_alg; 204*0bc36c83SRyan Everett __unused unsigned char reformatted_sig[MAX_ECDSA_R_S_PAIR_LEN] = {0}; 205255ce97dSManish V Badarkhe unsigned char *local_sig_ptr; 206255ce97dSManish V Badarkhe size_t local_sig_len; 207eaa62e82SManish V Badarkhe 208*0bc36c83SRyan Everett /* Load the key into the PSA key store. */ 209*0bc36c83SRyan Everett initialize_pk_context(&pk, &pk_initialized); 21038f89369SManish V Badarkhe 211*0bc36c83SRyan Everett p = (unsigned char *) pk_ptr; 212*0bc36c83SRyan Everett end = p + pk_len; 213*0bc36c83SRyan Everett rc = mbedtls_pk_parse_subpubkey(&p, end, &pk); 21438f89369SManish V Badarkhe if (rc != 0) { 21538f89369SManish V Badarkhe rc = CRYPTO_ERR_SIGNATURE; 216eaa62e82SManish V Badarkhe goto end2; 21738f89369SManish V Badarkhe } 218255ce97dSManish V Badarkhe 219*0bc36c83SRyan Everett rc = mbedtls_pk_get_psa_attributes(&pk, PSA_KEY_USAGE_VERIFY_MESSAGE, &psa_key_attr); 220*0bc36c83SRyan Everett if (rc != 0) { 221*0bc36c83SRyan Everett rc = CRYPTO_ERR_SIGNATURE; 222*0bc36c83SRyan Everett goto end2; 223*0bc36c83SRyan Everett } 224*0bc36c83SRyan Everett 225*0bc36c83SRyan Everett rc = construct_psa_alg(sig_alg, sig_alg_len, &pk_alg, &psa_alg); 226*0bc36c83SRyan Everett if (rc != CRYPTO_SUCCESS) { 227*0bc36c83SRyan Everett goto end2; 228*0bc36c83SRyan Everett } 229*0bc36c83SRyan Everett psa_set_key_algorithm(&psa_key_attr, psa_alg); 230*0bc36c83SRyan Everett 231*0bc36c83SRyan Everett rc = mbedtls_pk_import_into_psa(&pk, &psa_key_attr, &psa_key_id); 232*0bc36c83SRyan Everett if (rc != 0) { 233*0bc36c83SRyan Everett rc = CRYPTO_ERR_SIGNATURE; 234*0bc36c83SRyan Everett goto end2; 235*0bc36c83SRyan Everett } 236*0bc36c83SRyan Everett 237*0bc36c83SRyan Everett /* Optimize mbedtls heap usage by freeing the pk context now. */ 238*0bc36c83SRyan Everett cleanup_pk_context(&pk, &pk_initialized); 239*0bc36c83SRyan Everett 240*0bc36c83SRyan Everett /* Extract the signature from sig_ptr. */ 241*0bc36c83SRyan Everett p = (unsigned char *) sig_ptr; 242*0bc36c83SRyan Everett end = p + sig_len; 243*0bc36c83SRyan Everett rc = mbedtls_asn1_get_bitstring_null(&p, end, &local_sig_len); 244*0bc36c83SRyan Everett if (rc != 0) { 245*0bc36c83SRyan Everett rc = CRYPTO_ERR_SIGNATURE; 246*0bc36c83SRyan Everett goto end1; 247*0bc36c83SRyan Everett } 248255ce97dSManish V Badarkhe local_sig_ptr = p; 249255ce97dSManish V Badarkhe 250255ce97dSManish V Badarkhe #if TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_ECDSA || \ 251255ce97dSManish V Badarkhe TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA_AND_ECDSA 252255ce97dSManish V Badarkhe if (pk_alg == MBEDTLS_PK_ECDSA) { 253*0bc36c83SRyan Everett /* Convert the DER ASN.1 signature to raw format. */ 254*0bc36c83SRyan Everett size_t key_bits = psa_get_key_bits(&psa_key_attr); 255255ce97dSManish V Badarkhe 256*0bc36c83SRyan Everett rc = mbedtls_ecdsa_der_to_raw(key_bits, p, local_sig_len, 257*0bc36c83SRyan Everett reformatted_sig, MAX_ECDSA_R_S_PAIR_LEN, 258*0bc36c83SRyan Everett &local_sig_len); 259*0bc36c83SRyan Everett if (rc != 0) { 260*0bc36c83SRyan Everett rc = CRYPTO_ERR_SIGNATURE; 261*0bc36c83SRyan Everett goto end1; 262*0bc36c83SRyan Everett } 263255ce97dSManish V Badarkhe local_sig_ptr = reformatted_sig; 264255ce97dSManish V Badarkhe } 265255ce97dSManish V Badarkhe #endif /* 266255ce97dSManish V Badarkhe * TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_ECDSA || \ 267255ce97dSManish V Badarkhe * TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA_AND_ECDSA 268255ce97dSManish V Badarkhe **/ 26938f89369SManish V Badarkhe 270*0bc36c83SRyan Everett /* Verify the signature. */ 271*0bc36c83SRyan Everett psa_status = psa_verify_message(psa_key_id, psa_alg, 272eaa62e82SManish V Badarkhe data_ptr, data_len, 273255ce97dSManish V Badarkhe local_sig_ptr, local_sig_len); 274*0bc36c83SRyan Everett if (psa_status == PSA_SUCCESS) { 275*0bc36c83SRyan Everett /* The signature has been successfully verified. */ 276*0bc36c83SRyan Everett rc = CRYPTO_SUCCESS; 277*0bc36c83SRyan Everett } else { 27838f89369SManish V Badarkhe rc = CRYPTO_ERR_SIGNATURE; 27938f89369SManish V Badarkhe } 28038f89369SManish V Badarkhe 28138f89369SManish V Badarkhe end1: 282*0bc36c83SRyan Everett /* Destroy the key from the PSA subsystem. */ 283eaa62e82SManish V Badarkhe psa_destroy_key(psa_key_id); 28438f89369SManish V Badarkhe end2: 285*0bc36c83SRyan Everett /* Free the pk context, if it is initialized. */ 286*0bc36c83SRyan Everett cleanup_pk_context(&pk, &pk_initialized); 287*0bc36c83SRyan Everett 28838f89369SManish V Badarkhe return rc; 28938f89369SManish V Badarkhe } 29038f89369SManish V Badarkhe 29138f89369SManish V Badarkhe /* 29238f89369SManish V Badarkhe * Match a hash 29338f89369SManish V Badarkhe * 29438f89369SManish V Badarkhe * Digest info is passed in DER format following the ASN.1 structure detailed 29538f89369SManish V Badarkhe * above. 29638f89369SManish V Badarkhe */ 29738f89369SManish V Badarkhe static int verify_hash(void *data_ptr, unsigned int data_len, 29838f89369SManish V Badarkhe void *digest_info_ptr, unsigned int digest_info_len) 29938f89369SManish V Badarkhe { 30038f89369SManish V Badarkhe mbedtls_asn1_buf hash_oid, params; 30138f89369SManish V Badarkhe mbedtls_md_type_t md_alg; 30238f89369SManish V Badarkhe unsigned char *p, *end, *hash; 30338f89369SManish V Badarkhe size_t len; 30438f89369SManish V Badarkhe int rc; 3052ed061c4SManish V Badarkhe psa_status_t status; 3062ed061c4SManish V Badarkhe psa_algorithm_t psa_md_alg; 30738f89369SManish V Badarkhe 30838f89369SManish V Badarkhe /* 30938f89369SManish V Badarkhe * Digest info should be an MBEDTLS_ASN1_SEQUENCE, but padding after 31038f89369SManish V Badarkhe * it is allowed. This is necessary to support multiple hash 31138f89369SManish V Badarkhe * algorithms. 31238f89369SManish V Badarkhe */ 31338f89369SManish V Badarkhe p = (unsigned char *)digest_info_ptr; 31438f89369SManish V Badarkhe end = p + digest_info_len; 31538f89369SManish V Badarkhe rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | 31638f89369SManish V Badarkhe MBEDTLS_ASN1_SEQUENCE); 31738f89369SManish V Badarkhe if (rc != 0) { 31838f89369SManish V Badarkhe return CRYPTO_ERR_HASH; 31938f89369SManish V Badarkhe } 32038f89369SManish V Badarkhe 32138f89369SManish V Badarkhe end = p + len; 32238f89369SManish V Badarkhe 32338f89369SManish V Badarkhe /* Get the hash algorithm */ 32438f89369SManish V Badarkhe rc = mbedtls_asn1_get_alg(&p, end, &hash_oid, ¶ms); 32538f89369SManish V Badarkhe if (rc != 0) { 32638f89369SManish V Badarkhe return CRYPTO_ERR_HASH; 32738f89369SManish V Badarkhe } 32838f89369SManish V Badarkhe 32938f89369SManish V Badarkhe /* Hash should be octet string type and consume all bytes */ 33038f89369SManish V Badarkhe rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING); 33138f89369SManish V Badarkhe if ((rc != 0) || ((size_t)(end - p) != len)) { 33238f89369SManish V Badarkhe return CRYPTO_ERR_HASH; 33338f89369SManish V Badarkhe } 33438f89369SManish V Badarkhe hash = p; 33538f89369SManish V Badarkhe 3362ed061c4SManish V Badarkhe rc = mbedtls_oid_get_md_alg(&hash_oid, &md_alg); 33738f89369SManish V Badarkhe if (rc != 0) { 33838f89369SManish V Badarkhe return CRYPTO_ERR_HASH; 33938f89369SManish V Badarkhe } 34038f89369SManish V Badarkhe 3412ed061c4SManish V Badarkhe /* convert the md_alg to psa_algo */ 3422ed061c4SManish V Badarkhe psa_md_alg = mbedtls_md_psa_alg_from_type(md_alg); 3432ed061c4SManish V Badarkhe 3442ed061c4SManish V Badarkhe /* Length of hash must match the algorithm's size */ 3452ed061c4SManish V Badarkhe if (len != PSA_HASH_LENGTH(psa_md_alg)) { 3462ed061c4SManish V Badarkhe return CRYPTO_ERR_HASH; 3472ed061c4SManish V Badarkhe } 3482ed061c4SManish V Badarkhe 3492ed061c4SManish V Badarkhe /* 3502ed061c4SManish V Badarkhe * Calculate Hash and compare it against the retrieved hash from 3512ed061c4SManish V Badarkhe * the certificate (one shot API). 3522ed061c4SManish V Badarkhe */ 3532ed061c4SManish V Badarkhe status = psa_hash_compare(psa_md_alg, 3542ed061c4SManish V Badarkhe data_ptr, (size_t)data_len, 3552ed061c4SManish V Badarkhe (const uint8_t *)hash, len); 3562ed061c4SManish V Badarkhe 3572ed061c4SManish V Badarkhe if (status != PSA_SUCCESS) { 35838f89369SManish V Badarkhe return CRYPTO_ERR_HASH; 35938f89369SManish V Badarkhe } 36038f89369SManish V Badarkhe 36138f89369SManish V Badarkhe return CRYPTO_SUCCESS; 36238f89369SManish V Badarkhe } 36338f89369SManish V Badarkhe #endif /* 36438f89369SManish V Badarkhe * CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \ 36538f89369SManish V Badarkhe * CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC 36638f89369SManish V Badarkhe */ 36738f89369SManish V Badarkhe 36838f89369SManish V Badarkhe #if CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \ 36938f89369SManish V Badarkhe CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC 37038f89369SManish V Badarkhe /* 37138f89369SManish V Badarkhe * Map a generic crypto message digest algorithm to the corresponding macro used 37238f89369SManish V Badarkhe * by Mbed TLS. 37338f89369SManish V Badarkhe */ 37438f89369SManish V Badarkhe static inline mbedtls_md_type_t md_type(enum crypto_md_algo algo) 37538f89369SManish V Badarkhe { 37638f89369SManish V Badarkhe switch (algo) { 37738f89369SManish V Badarkhe case CRYPTO_MD_SHA512: 37838f89369SManish V Badarkhe return MBEDTLS_MD_SHA512; 37938f89369SManish V Badarkhe case CRYPTO_MD_SHA384: 38038f89369SManish V Badarkhe return MBEDTLS_MD_SHA384; 38138f89369SManish V Badarkhe case CRYPTO_MD_SHA256: 38238f89369SManish V Badarkhe return MBEDTLS_MD_SHA256; 38338f89369SManish V Badarkhe default: 38438f89369SManish V Badarkhe /* Invalid hash algorithm. */ 38538f89369SManish V Badarkhe return MBEDTLS_MD_NONE; 38638f89369SManish V Badarkhe } 38738f89369SManish V Badarkhe } 38838f89369SManish V Badarkhe 38938f89369SManish V Badarkhe /* 39038f89369SManish V Badarkhe * Calculate a hash 39138f89369SManish V Badarkhe * 39238f89369SManish V Badarkhe * output points to the computed hash 39338f89369SManish V Badarkhe */ 39438f89369SManish V Badarkhe static int calc_hash(enum crypto_md_algo md_algo, void *data_ptr, 39538f89369SManish V Badarkhe unsigned int data_len, 39638f89369SManish V Badarkhe unsigned char output[CRYPTO_MD_MAX_SIZE]) 39738f89369SManish V Badarkhe { 398484b5869SManish V Badarkhe size_t hash_length; 399484b5869SManish V Badarkhe psa_status_t status; 400484b5869SManish V Badarkhe psa_algorithm_t psa_md_alg; 40138f89369SManish V Badarkhe 402484b5869SManish V Badarkhe /* convert the md_alg to psa_algo */ 403484b5869SManish V Badarkhe psa_md_alg = mbedtls_md_psa_alg_from_type(md_type(md_algo)); 40438f89369SManish V Badarkhe 40538f89369SManish V Badarkhe /* 40638f89369SManish V Badarkhe * Calculate the hash of the data, it is safe to pass the 40738f89369SManish V Badarkhe * 'output' hash buffer pointer considering its size is always 40838f89369SManish V Badarkhe * bigger than or equal to MBEDTLS_MD_MAX_SIZE. 40938f89369SManish V Badarkhe */ 410484b5869SManish V Badarkhe status = psa_hash_compute(psa_md_alg, data_ptr, (size_t)data_len, 411484b5869SManish V Badarkhe (uint8_t *)output, CRYPTO_MD_MAX_SIZE, 412484b5869SManish V Badarkhe &hash_length); 413484b5869SManish V Badarkhe if (status != PSA_SUCCESS) { 414484b5869SManish V Badarkhe return CRYPTO_ERR_HASH; 415484b5869SManish V Badarkhe } 416484b5869SManish V Badarkhe 417484b5869SManish V Badarkhe return CRYPTO_SUCCESS; 41838f89369SManish V Badarkhe } 41938f89369SManish V Badarkhe #endif /* 42038f89369SManish V Badarkhe * CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \ 42138f89369SManish V Badarkhe * CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC 42238f89369SManish V Badarkhe */ 42338f89369SManish V Badarkhe 42438f89369SManish V Badarkhe #if TF_MBEDTLS_USE_AES_GCM 42538f89369SManish V Badarkhe /* 42638f89369SManish V Badarkhe * Stack based buffer allocation for decryption operation. It could 42738f89369SManish V Badarkhe * be configured to balance stack usage vs execution speed. 42838f89369SManish V Badarkhe */ 42938f89369SManish V Badarkhe #define DEC_OP_BUF_SIZE 128 43038f89369SManish V Badarkhe 43138f89369SManish V Badarkhe static int aes_gcm_decrypt(void *data_ptr, size_t len, const void *key, 43238f89369SManish V Badarkhe unsigned int key_len, const void *iv, 43338f89369SManish V Badarkhe unsigned int iv_len, const void *tag, 43438f89369SManish V Badarkhe unsigned int tag_len) 43538f89369SManish V Badarkhe { 43638f89369SManish V Badarkhe mbedtls_gcm_context ctx; 43738f89369SManish V Badarkhe mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES; 43838f89369SManish V Badarkhe unsigned char buf[DEC_OP_BUF_SIZE]; 43938f89369SManish V Badarkhe unsigned char tag_buf[CRYPTO_MAX_TAG_SIZE]; 44038f89369SManish V Badarkhe unsigned char *pt = data_ptr; 44138f89369SManish V Badarkhe size_t dec_len; 44238f89369SManish V Badarkhe int diff, i, rc; 44338f89369SManish V Badarkhe size_t output_length __unused; 44438f89369SManish V Badarkhe 44538f89369SManish V Badarkhe mbedtls_gcm_init(&ctx); 44638f89369SManish V Badarkhe 44738f89369SManish V Badarkhe rc = mbedtls_gcm_setkey(&ctx, cipher, key, key_len * 8); 44838f89369SManish V Badarkhe if (rc != 0) { 44938f89369SManish V Badarkhe rc = CRYPTO_ERR_DECRYPTION; 45038f89369SManish V Badarkhe goto exit_gcm; 45138f89369SManish V Badarkhe } 45238f89369SManish V Badarkhe 45338f89369SManish V Badarkhe #if (MBEDTLS_VERSION_MAJOR < 3) 45438f89369SManish V Badarkhe rc = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT, iv, iv_len, NULL, 0); 45538f89369SManish V Badarkhe #else 45638f89369SManish V Badarkhe rc = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT, iv, iv_len); 45738f89369SManish V Badarkhe #endif 45838f89369SManish V Badarkhe if (rc != 0) { 45938f89369SManish V Badarkhe rc = CRYPTO_ERR_DECRYPTION; 46038f89369SManish V Badarkhe goto exit_gcm; 46138f89369SManish V Badarkhe } 46238f89369SManish V Badarkhe 46338f89369SManish V Badarkhe while (len > 0) { 46438f89369SManish V Badarkhe dec_len = MIN(sizeof(buf), len); 46538f89369SManish V Badarkhe 46638f89369SManish V Badarkhe #if (MBEDTLS_VERSION_MAJOR < 3) 46738f89369SManish V Badarkhe rc = mbedtls_gcm_update(&ctx, dec_len, pt, buf); 46838f89369SManish V Badarkhe #else 46938f89369SManish V Badarkhe rc = mbedtls_gcm_update(&ctx, pt, dec_len, buf, sizeof(buf), &output_length); 47038f89369SManish V Badarkhe #endif 47138f89369SManish V Badarkhe 47238f89369SManish V Badarkhe if (rc != 0) { 47338f89369SManish V Badarkhe rc = CRYPTO_ERR_DECRYPTION; 47438f89369SManish V Badarkhe goto exit_gcm; 47538f89369SManish V Badarkhe } 47638f89369SManish V Badarkhe 47738f89369SManish V Badarkhe memcpy(pt, buf, dec_len); 47838f89369SManish V Badarkhe pt += dec_len; 47938f89369SManish V Badarkhe len -= dec_len; 48038f89369SManish V Badarkhe } 48138f89369SManish V Badarkhe 48238f89369SManish V Badarkhe #if (MBEDTLS_VERSION_MAJOR < 3) 48338f89369SManish V Badarkhe rc = mbedtls_gcm_finish(&ctx, tag_buf, sizeof(tag_buf)); 48438f89369SManish V Badarkhe #else 48538f89369SManish V Badarkhe rc = mbedtls_gcm_finish(&ctx, NULL, 0, &output_length, tag_buf, sizeof(tag_buf)); 48638f89369SManish V Badarkhe #endif 48738f89369SManish V Badarkhe 48838f89369SManish V Badarkhe if (rc != 0) { 48938f89369SManish V Badarkhe rc = CRYPTO_ERR_DECRYPTION; 49038f89369SManish V Badarkhe goto exit_gcm; 49138f89369SManish V Badarkhe } 49238f89369SManish V Badarkhe 49338f89369SManish V Badarkhe /* Check tag in "constant-time" */ 49438f89369SManish V Badarkhe for (diff = 0, i = 0; i < tag_len; i++) 49538f89369SManish V Badarkhe diff |= ((const unsigned char *)tag)[i] ^ tag_buf[i]; 49638f89369SManish V Badarkhe 49738f89369SManish V Badarkhe if (diff != 0) { 49838f89369SManish V Badarkhe rc = CRYPTO_ERR_DECRYPTION; 49938f89369SManish V Badarkhe goto exit_gcm; 50038f89369SManish V Badarkhe } 50138f89369SManish V Badarkhe 50238f89369SManish V Badarkhe /* GCM decryption success */ 50338f89369SManish V Badarkhe rc = CRYPTO_SUCCESS; 50438f89369SManish V Badarkhe 50538f89369SManish V Badarkhe exit_gcm: 50638f89369SManish V Badarkhe mbedtls_gcm_free(&ctx); 50738f89369SManish V Badarkhe return rc; 50838f89369SManish V Badarkhe } 50938f89369SManish V Badarkhe 51038f89369SManish V Badarkhe /* 51138f89369SManish V Badarkhe * Authenticated decryption of an image 51238f89369SManish V Badarkhe */ 51338f89369SManish V Badarkhe static int auth_decrypt(enum crypto_dec_algo dec_algo, void *data_ptr, 51438f89369SManish V Badarkhe size_t len, const void *key, unsigned int key_len, 51538f89369SManish V Badarkhe unsigned int key_flags, const void *iv, 51638f89369SManish V Badarkhe unsigned int iv_len, const void *tag, 51738f89369SManish V Badarkhe unsigned int tag_len) 51838f89369SManish V Badarkhe { 51938f89369SManish V Badarkhe int rc; 52038f89369SManish V Badarkhe 52138f89369SManish V Badarkhe assert((key_flags & ENC_KEY_IS_IDENTIFIER) == 0); 52238f89369SManish V Badarkhe 52338f89369SManish V Badarkhe switch (dec_algo) { 52438f89369SManish V Badarkhe case CRYPTO_GCM_DECRYPT: 52538f89369SManish V Badarkhe rc = aes_gcm_decrypt(data_ptr, len, key, key_len, iv, iv_len, 52638f89369SManish V Badarkhe tag, tag_len); 52738f89369SManish V Badarkhe if (rc != 0) 52838f89369SManish V Badarkhe return rc; 52938f89369SManish V Badarkhe break; 53038f89369SManish V Badarkhe default: 53138f89369SManish V Badarkhe return CRYPTO_ERR_DECRYPTION; 53238f89369SManish V Badarkhe } 53338f89369SManish V Badarkhe 53438f89369SManish V Badarkhe return CRYPTO_SUCCESS; 53538f89369SManish V Badarkhe } 53638f89369SManish V Badarkhe #endif /* TF_MBEDTLS_USE_AES_GCM */ 53738f89369SManish V Badarkhe 53838f89369SManish V Badarkhe /* 53938f89369SManish V Badarkhe * Register crypto library descriptor 54038f89369SManish V Badarkhe */ 54138f89369SManish V Badarkhe #if CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC 54238f89369SManish V Badarkhe #if TF_MBEDTLS_USE_AES_GCM 54338f89369SManish V Badarkhe REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash, 54438f89369SManish V Badarkhe auth_decrypt, NULL); 54538f89369SManish V Badarkhe #else 54638f89369SManish V Badarkhe REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash, 54738f89369SManish V Badarkhe NULL, NULL); 54838f89369SManish V Badarkhe #endif 54938f89369SManish V Badarkhe #elif CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY 55038f89369SManish V Badarkhe #if TF_MBEDTLS_USE_AES_GCM 55138f89369SManish V Badarkhe REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL, 55238f89369SManish V Badarkhe auth_decrypt, NULL); 55338f89369SManish V Badarkhe #else 55438f89369SManish V Badarkhe REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL, 55538f89369SManish V Badarkhe NULL, NULL); 55638f89369SManish V Badarkhe #endif 55738f89369SManish V Badarkhe #elif CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY 55838f89369SManish V Badarkhe REGISTER_CRYPTO_LIB(LIB_NAME, init, NULL, NULL, calc_hash, NULL, NULL); 55938f89369SManish V Badarkhe #endif /* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */ 560