138f89369SManish V Badarkhe /* 2*8a7505b0SLauren Wehrmeister * Copyright (c) 2023-2025, 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/md.h> 1338f89369SManish V Badarkhe #include <mbedtls/memory_buffer_alloc.h> 1438f89369SManish V Badarkhe #include <mbedtls/oid.h> 1538f89369SManish V Badarkhe #include <mbedtls/platform.h> 1655aed7d7SJimmy Brisson #include <mbedtls/psa_util.h> 1738f89369SManish V Badarkhe #include <mbedtls/x509.h> 184eaaaa19SManish V Badarkhe #include <psa/crypto.h> 194eaaaa19SManish V Badarkhe #include <psa/crypto_platform.h> 204eaaaa19SManish V Badarkhe #include <psa/crypto_types.h> 214eaaaa19SManish V Badarkhe #include <psa/crypto_values.h> 2238f89369SManish V Badarkhe 2338f89369SManish V Badarkhe #include <common/debug.h> 24*8a7505b0SLauren Wehrmeister #include <drivers/auth/auth_util.h> 2538f89369SManish V Badarkhe #include <drivers/auth/crypto_mod.h> 2638f89369SManish V Badarkhe #include <drivers/auth/mbedtls/mbedtls_common.h> 27*8a7505b0SLauren Wehrmeister #include <drivers/auth/mbedtls/mbedtls_psa_crypto.h> 2838f89369SManish V Badarkhe #include <plat/common/platform.h> 2938f89369SManish V Badarkhe 3038f89369SManish V Badarkhe #define LIB_NAME "mbed TLS PSA" 3138f89369SManish V Badarkhe 3212a8e953SRyan Everett /* Minimum required size for a buffer containing a raw EC signature when using 3312a8e953SRyan Everett * a maximum curve size of 384 bits. 3412a8e953SRyan Everett * This is calculated as 2 * (384 / 8). */ 3512a8e953SRyan Everett #define ECDSA_SIG_BUFFER_SIZE 96U 36255ce97dSManish V Badarkhe 37255ce97dSManish V Badarkhe /* Size of ASN.1 length and tag in bytes*/ 38255ce97dSManish V Badarkhe #define SIZE_OF_ASN1_LEN 1U 39255ce97dSManish V Badarkhe #define SIZE_OF_ASN1_TAG 1U 40255ce97dSManish V Badarkhe 41*8a7505b0SLauren Wehrmeister /* Global cache for keys */ 42*8a7505b0SLauren Wehrmeister key_cache_t key_cache[MAX_CACHED_KEYS] = {0}; 43*8a7505b0SLauren Wehrmeister 4438f89369SManish V Badarkhe #if CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \ 4538f89369SManish V Badarkhe CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC 4638f89369SManish V Badarkhe /* 4738f89369SManish V Badarkhe * CRYPTO_MD_MAX_SIZE value is as per current stronger algorithm available 4838f89369SManish V Badarkhe * so make sure that mbed TLS MD maximum size must be lesser than this. 4938f89369SManish V Badarkhe */ 5038f89369SManish V Badarkhe CASSERT(CRYPTO_MD_MAX_SIZE >= MBEDTLS_MD_MAX_SIZE, 5138f89369SManish V Badarkhe assert_mbedtls_md_size_overflow); 5238f89369SManish V Badarkhe 5338f89369SManish V Badarkhe #endif /* 5438f89369SManish V Badarkhe * CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \ 5538f89369SManish V Badarkhe * CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC 5638f89369SManish V Badarkhe */ 5738f89369SManish V Badarkhe 5838f89369SManish V Badarkhe /* 5938f89369SManish V Badarkhe * AlgorithmIdentifier ::= SEQUENCE { 6038f89369SManish V Badarkhe * algorithm OBJECT IDENTIFIER, 6138f89369SManish V Badarkhe * parameters ANY DEFINED BY algorithm OPTIONAL 6238f89369SManish V Badarkhe * } 6338f89369SManish V Badarkhe * 6438f89369SManish V Badarkhe * SubjectPublicKeyInfo ::= SEQUENCE { 6538f89369SManish V Badarkhe * algorithm AlgorithmIdentifier, 6638f89369SManish V Badarkhe * subjectPublicKey BIT STRING 6738f89369SManish V Badarkhe * } 6838f89369SManish V Badarkhe * 6938f89369SManish V Badarkhe * DigestInfo ::= SEQUENCE { 7038f89369SManish V Badarkhe * digestAlgorithm AlgorithmIdentifier, 7138f89369SManish V Badarkhe * digest OCTET STRING 7238f89369SManish V Badarkhe * } 7338f89369SManish V Badarkhe */ 7438f89369SManish V Badarkhe 7538f89369SManish V Badarkhe /* 764eaaaa19SManish V Badarkhe * We pretend using an external RNG (through MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG 774eaaaa19SManish V Badarkhe * mbedTLS config option) so we need to provide an implementation of 784eaaaa19SManish V Badarkhe * mbedtls_psa_external_get_random(). Provide a fake one, since we do not 794eaaaa19SManish V Badarkhe * actually have any external RNG and TF-A itself doesn't engage in 804eaaaa19SManish V Badarkhe * cryptographic operations that demands randomness. 814eaaaa19SManish V Badarkhe */ 824eaaaa19SManish V Badarkhe psa_status_t mbedtls_psa_external_get_random( 834eaaaa19SManish V Badarkhe mbedtls_psa_external_random_context_t *context, 844eaaaa19SManish V Badarkhe uint8_t *output, size_t output_size, 854eaaaa19SManish V Badarkhe size_t *output_length) 864eaaaa19SManish V Badarkhe { 874eaaaa19SManish V Badarkhe return PSA_ERROR_INSUFFICIENT_ENTROPY; 884eaaaa19SManish V Badarkhe } 894eaaaa19SManish V Badarkhe 904eaaaa19SManish V Badarkhe /* 9138f89369SManish V Badarkhe * Initialize the library and export the descriptor 9238f89369SManish V Badarkhe */ 9338f89369SManish V Badarkhe static void init(void) 9438f89369SManish V Badarkhe { 9538f89369SManish V Badarkhe /* Initialize mbed TLS */ 9638f89369SManish V Badarkhe mbedtls_init(); 974eaaaa19SManish V Badarkhe 984eaaaa19SManish V Badarkhe /* Initialise PSA mbedTLS */ 994eaaaa19SManish V Badarkhe psa_status_t status = psa_crypto_init(); 1004eaaaa19SManish V Badarkhe 1014eaaaa19SManish V Badarkhe if (status != PSA_SUCCESS) { 1024eaaaa19SManish V Badarkhe ERROR("Failed to initialize %s crypto (%d).\n", LIB_NAME, status); 1034eaaaa19SManish V Badarkhe panic(); 1044eaaaa19SManish V Badarkhe } 1054eaaaa19SManish V Badarkhe 1064eaaaa19SManish V Badarkhe INFO("PSA crypto initialized successfully!\n"); 10738f89369SManish V Badarkhe } 10838f89369SManish V Badarkhe 10938f89369SManish V Badarkhe #if CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \ 11038f89369SManish V Badarkhe CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC 111*8a7505b0SLauren Wehrmeister /* Destroy all psa key ids created in a loop */ 112*8a7505b0SLauren Wehrmeister static void destroy_key_ids(void) 113*8a7505b0SLauren Wehrmeister { 114*8a7505b0SLauren Wehrmeister for (int i = 0; i < MAX_CACHED_KEYS; i++) { 115*8a7505b0SLauren Wehrmeister if (key_cache[i].valid) { 116*8a7505b0SLauren Wehrmeister psa_destroy_key(key_cache[i].key_id); 117*8a7505b0SLauren Wehrmeister } 118*8a7505b0SLauren Wehrmeister } 119*8a7505b0SLauren Wehrmeister } 120*8a7505b0SLauren Wehrmeister 121*8a7505b0SLauren Wehrmeister /* Retrieve cached key ID, algorithm, and key attributes */ 122*8a7505b0SLauren Wehrmeister static bool get_cached_psa_key_info(const char *pk_oid, psa_key_id_t *key_id, 123*8a7505b0SLauren Wehrmeister psa_algorithm_t *psa_alg, psa_key_attributes_t *psa_key_attr) 124*8a7505b0SLauren Wehrmeister { 125*8a7505b0SLauren Wehrmeister for (int i = 0; i < MAX_CACHED_KEYS; i++) { 126*8a7505b0SLauren Wehrmeister if (key_cache[i].valid && 127*8a7505b0SLauren Wehrmeister (strlen(key_cache[i].pk_oid) == strlen(pk_oid)) && 128*8a7505b0SLauren Wehrmeister (strncmp(key_cache[i].pk_oid, pk_oid, strlen(pk_oid)) == 0)) { 129*8a7505b0SLauren Wehrmeister *key_id = key_cache[i].key_id; 130*8a7505b0SLauren Wehrmeister *psa_alg = key_cache[i].psa_alg; 131*8a7505b0SLauren Wehrmeister *psa_key_attr = key_cache[i].psa_key_attr; 132*8a7505b0SLauren Wehrmeister return true; 133*8a7505b0SLauren Wehrmeister } 134*8a7505b0SLauren Wehrmeister } 135*8a7505b0SLauren Wehrmeister return false; 136*8a7505b0SLauren Wehrmeister } 137*8a7505b0SLauren Wehrmeister 138*8a7505b0SLauren Wehrmeister /* Store key ID, algorithm, and key attributes in the cache */ 139*8a7505b0SLauren Wehrmeister static int cache_psa_key_info(const char *pk_oid, psa_key_id_t key_id, psa_algorithm_t psa_alg, 140*8a7505b0SLauren Wehrmeister psa_key_attributes_t psa_key_attr) 141*8a7505b0SLauren Wehrmeister { 142*8a7505b0SLauren Wehrmeister for (int i = 0; i < MAX_CACHED_KEYS; i++) { 143*8a7505b0SLauren Wehrmeister if (!key_cache[i].valid) { 144*8a7505b0SLauren Wehrmeister key_cache[i].pk_oid = pk_oid; 145*8a7505b0SLauren Wehrmeister key_cache[i].key_id = key_id; 146*8a7505b0SLauren Wehrmeister key_cache[i].psa_alg = psa_alg; 147*8a7505b0SLauren Wehrmeister key_cache[i].psa_key_attr = psa_key_attr; 148*8a7505b0SLauren Wehrmeister key_cache[i].valid = true; 149*8a7505b0SLauren Wehrmeister return CRYPTO_SUCCESS; 150*8a7505b0SLauren Wehrmeister } 151*8a7505b0SLauren Wehrmeister } 152*8a7505b0SLauren Wehrmeister return CRYPTO_ERR_SIGNATURE; 153*8a7505b0SLauren Wehrmeister } 154eaa62e82SManish V Badarkhe 15555aed7d7SJimmy Brisson /* 15655aed7d7SJimmy Brisson * NOTE: This has been made internal in mbedtls 3.6.0 and the mbedtls team has 15755aed7d7SJimmy Brisson * advised that it's better to copy out the declaration than it would be to 15855aed7d7SJimmy Brisson * update to 3.5.2, where this function is exposed. 15955aed7d7SJimmy Brisson */ 16055aed7d7SJimmy Brisson int mbedtls_x509_get_sig_alg(const mbedtls_x509_buf *sig_oid, 16155aed7d7SJimmy Brisson const mbedtls_x509_buf *sig_params, 16255aed7d7SJimmy Brisson mbedtls_md_type_t *md_alg, 16355aed7d7SJimmy Brisson mbedtls_pk_type_t *pk_alg, 16455aed7d7SJimmy Brisson void **sig_opts); 1650bc36c83SRyan Everett 1660bc36c83SRyan Everett /* 1670bc36c83SRyan Everett * This is a helper function which parses a SignatureAlgorithm OID. 1680bc36c83SRyan Everett * It extracts the pk algorithm and constructs a psa_algorithm_t object 1690bc36c83SRyan Everett * to be used by PSA calls. 1700bc36c83SRyan Everett */ 1710bc36c83SRyan Everett static int construct_psa_alg(void *sig_alg, unsigned int sig_alg_len, 1720bc36c83SRyan Everett mbedtls_pk_type_t *pk_alg, psa_algorithm_t *psa_alg) 1730bc36c83SRyan Everett { 1740bc36c83SRyan Everett int rc; 1750bc36c83SRyan Everett mbedtls_md_type_t md_alg; 1760bc36c83SRyan Everett void *sig_opts = NULL; 1770bc36c83SRyan Everett mbedtls_asn1_buf sig_alg_oid, params; 1780bc36c83SRyan Everett unsigned char *p = (unsigned char *) sig_alg; 1790bc36c83SRyan Everett unsigned char *end = (unsigned char *) sig_alg + sig_alg_len; 1800bc36c83SRyan Everett 1810bc36c83SRyan Everett rc = mbedtls_asn1_get_alg(&p, end, &sig_alg_oid, ¶ms); 1820bc36c83SRyan Everett if (rc != 0) { 1830bc36c83SRyan Everett rc = CRYPTO_ERR_SIGNATURE; 1840bc36c83SRyan Everett goto end; 1850bc36c83SRyan Everett } 1860bc36c83SRyan Everett 1870bc36c83SRyan Everett rc = mbedtls_x509_get_sig_alg(&sig_alg_oid, ¶ms, &md_alg, pk_alg, &sig_opts); 1880bc36c83SRyan Everett if (rc != 0) { 1890bc36c83SRyan Everett rc = CRYPTO_ERR_SIGNATURE; 1900bc36c83SRyan Everett goto end; 1910bc36c83SRyan Everett } 1920bc36c83SRyan Everett 1930bc36c83SRyan Everett psa_algorithm_t psa_md_alg = mbedtls_md_psa_alg_from_type(md_alg); 1940bc36c83SRyan Everett 1950bc36c83SRyan Everett switch (*pk_alg) { 1960bc36c83SRyan Everett case MBEDTLS_PK_RSASSA_PSS: 1970bc36c83SRyan Everett *psa_alg = PSA_ALG_RSA_PSS(psa_md_alg); 1980bc36c83SRyan Everett rc = CRYPTO_SUCCESS; 1990bc36c83SRyan Everett break; 2000bc36c83SRyan Everett case MBEDTLS_PK_ECDSA: 2010bc36c83SRyan Everett *psa_alg = PSA_ALG_ECDSA(psa_md_alg); 2020bc36c83SRyan Everett rc = CRYPTO_SUCCESS; 2030bc36c83SRyan Everett break; 2040bc36c83SRyan Everett default: 2050bc36c83SRyan Everett *psa_alg = PSA_ALG_NONE; 2060bc36c83SRyan Everett rc = CRYPTO_ERR_SIGNATURE; 2070bc36c83SRyan Everett break; 2080bc36c83SRyan Everett } 2090bc36c83SRyan Everett 2100bc36c83SRyan Everett end: 2110bc36c83SRyan Everett mbedtls_free(sig_opts); 2120bc36c83SRyan Everett return rc; 2130bc36c83SRyan Everett } 2140bc36c83SRyan Everett 2150bc36c83SRyan Everett /* 2160bc36c83SRyan Everett * Helper functions for mbedtls PK contexts. 2170bc36c83SRyan Everett */ 2180bc36c83SRyan Everett static void initialize_pk_context(mbedtls_pk_context *pk, bool *pk_initialized) 2190bc36c83SRyan Everett { 2200bc36c83SRyan Everett mbedtls_pk_init(pk); 2210bc36c83SRyan Everett *pk_initialized = true; 2220bc36c83SRyan Everett } 2230bc36c83SRyan Everett 2240bc36c83SRyan Everett static void cleanup_pk_context(mbedtls_pk_context *pk, bool *pk_initialized) 2250bc36c83SRyan Everett { 2260bc36c83SRyan Everett if (*pk_initialized) { 2270bc36c83SRyan Everett mbedtls_pk_free(pk); 2280bc36c83SRyan Everett *pk_initialized = false; 2290bc36c83SRyan Everett } 2300bc36c83SRyan Everett } 2310bc36c83SRyan Everett 23255aed7d7SJimmy Brisson /* 23338f89369SManish V Badarkhe * Verify a signature. 23438f89369SManish V Badarkhe * 23538f89369SManish V Badarkhe * Parameters are passed using the DER encoding format following the ASN.1 23638f89369SManish V Badarkhe * structures detailed above. 23738f89369SManish V Badarkhe */ 23838f89369SManish V Badarkhe static int verify_signature(void *data_ptr, unsigned int data_len, 23938f89369SManish V Badarkhe void *sig_ptr, unsigned int sig_len, 24038f89369SManish V Badarkhe void *sig_alg, unsigned int sig_alg_len, 24138f89369SManish V Badarkhe void *pk_ptr, unsigned int pk_len) 24238f89369SManish V Badarkhe { 24338f89369SManish V Badarkhe unsigned char *p, *end; 2440bc36c83SRyan Everett mbedtls_pk_context pk; 2450bc36c83SRyan Everett bool pk_initialized = false; 2460bc36c83SRyan Everett int rc = CRYPTO_ERR_SIGNATURE; 2470bc36c83SRyan Everett psa_status_t psa_status = PSA_ERROR_CORRUPTION_DETECTED; 2480bc36c83SRyan Everett psa_key_attributes_t psa_key_attr = PSA_KEY_ATTRIBUTES_INIT; 2490bc36c83SRyan Everett psa_key_id_t psa_key_id; 2500bc36c83SRyan Everett mbedtls_pk_type_t pk_alg; 2510bc36c83SRyan Everett psa_algorithm_t psa_alg; 252*8a7505b0SLauren Wehrmeister const char *pk_oid = get_current_pk_oid(); 25312a8e953SRyan Everett __unused unsigned char reformatted_sig[ECDSA_SIG_BUFFER_SIZE] = {0}; 254255ce97dSManish V Badarkhe unsigned char *local_sig_ptr; 255255ce97dSManish V Badarkhe size_t local_sig_len; 256eaa62e82SManish V Badarkhe 257*8a7505b0SLauren Wehrmeister /* Check if key, algorithm, and key attributes are already cached */ 258*8a7505b0SLauren Wehrmeister if (!get_cached_psa_key_info(pk_oid, &psa_key_id, &psa_alg, &psa_key_attr)) { 2590bc36c83SRyan Everett /* Load the key into the PSA key store. */ 2600bc36c83SRyan Everett initialize_pk_context(&pk, &pk_initialized); 26138f89369SManish V Badarkhe 2620bc36c83SRyan Everett p = (unsigned char *) pk_ptr; 2630bc36c83SRyan Everett end = p + pk_len; 2640bc36c83SRyan Everett rc = mbedtls_pk_parse_subpubkey(&p, end, &pk); 26538f89369SManish V Badarkhe if (rc != 0) { 26638f89369SManish V Badarkhe rc = CRYPTO_ERR_SIGNATURE; 267eaa62e82SManish V Badarkhe goto end2; 26838f89369SManish V Badarkhe } 269255ce97dSManish V Badarkhe 270*8a7505b0SLauren Wehrmeister rc = mbedtls_pk_get_psa_attributes(&pk, PSA_KEY_USAGE_VERIFY_MESSAGE, 271*8a7505b0SLauren Wehrmeister &psa_key_attr); 2720bc36c83SRyan Everett if (rc != 0) { 2730bc36c83SRyan Everett rc = CRYPTO_ERR_SIGNATURE; 2740bc36c83SRyan Everett goto end2; 2750bc36c83SRyan Everett } 2760bc36c83SRyan Everett 2770bc36c83SRyan Everett rc = construct_psa_alg(sig_alg, sig_alg_len, &pk_alg, &psa_alg); 2780bc36c83SRyan Everett if (rc != CRYPTO_SUCCESS) { 2790bc36c83SRyan Everett goto end2; 2800bc36c83SRyan Everett } 2810bc36c83SRyan Everett psa_set_key_algorithm(&psa_key_attr, psa_alg); 2820bc36c83SRyan Everett 2830bc36c83SRyan Everett rc = mbedtls_pk_import_into_psa(&pk, &psa_key_attr, &psa_key_id); 2840bc36c83SRyan Everett if (rc != 0) { 2850bc36c83SRyan Everett rc = CRYPTO_ERR_SIGNATURE; 2860bc36c83SRyan Everett goto end2; 2870bc36c83SRyan Everett } 2880bc36c83SRyan Everett 289*8a7505b0SLauren Wehrmeister /* Cache the key, algorithm, and key attributes for future use */ 290*8a7505b0SLauren Wehrmeister rc = cache_psa_key_info(pk_oid, psa_key_id, psa_alg, psa_key_attr); 291*8a7505b0SLauren Wehrmeister if (rc != CRYPTO_SUCCESS) { 292*8a7505b0SLauren Wehrmeister goto end2; 293*8a7505b0SLauren Wehrmeister } 294*8a7505b0SLauren Wehrmeister 2950bc36c83SRyan Everett /* Optimize mbedtls heap usage by freeing the pk context now. */ 2960bc36c83SRyan Everett cleanup_pk_context(&pk, &pk_initialized); 297*8a7505b0SLauren Wehrmeister } 2980bc36c83SRyan Everett 2990bc36c83SRyan Everett /* Extract the signature from sig_ptr. */ 3000bc36c83SRyan Everett p = (unsigned char *) sig_ptr; 3010bc36c83SRyan Everett end = p + sig_len; 3020bc36c83SRyan Everett rc = mbedtls_asn1_get_bitstring_null(&p, end, &local_sig_len); 3030bc36c83SRyan Everett if (rc != 0) { 3040bc36c83SRyan Everett rc = CRYPTO_ERR_SIGNATURE; 3050bc36c83SRyan Everett goto end1; 3060bc36c83SRyan Everett } 307255ce97dSManish V Badarkhe local_sig_ptr = p; 308255ce97dSManish V Badarkhe 309255ce97dSManish V Badarkhe #if TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_ECDSA || \ 310255ce97dSManish V Badarkhe TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA_AND_ECDSA 311*8a7505b0SLauren Wehrmeister if (PSA_ALG_IS_ECDSA(psa_alg)) { 3120bc36c83SRyan Everett /* Convert the DER ASN.1 signature to raw format. */ 3130bc36c83SRyan Everett size_t key_bits = psa_get_key_bits(&psa_key_attr); 314255ce97dSManish V Badarkhe 3150bc36c83SRyan Everett rc = mbedtls_ecdsa_der_to_raw(key_bits, p, local_sig_len, 31612a8e953SRyan Everett reformatted_sig, ECDSA_SIG_BUFFER_SIZE, 3170bc36c83SRyan Everett &local_sig_len); 3180bc36c83SRyan Everett if (rc != 0) { 3190bc36c83SRyan Everett rc = CRYPTO_ERR_SIGNATURE; 3200bc36c83SRyan Everett goto end1; 3210bc36c83SRyan Everett } 322255ce97dSManish V Badarkhe local_sig_ptr = reformatted_sig; 323255ce97dSManish V Badarkhe } 324255ce97dSManish V Badarkhe #endif /* 325255ce97dSManish V Badarkhe * TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_ECDSA || \ 326255ce97dSManish V Badarkhe * TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA_AND_ECDSA 327255ce97dSManish V Badarkhe **/ 32838f89369SManish V Badarkhe 3290bc36c83SRyan Everett /* Verify the signature. */ 3300bc36c83SRyan Everett psa_status = psa_verify_message(psa_key_id, psa_alg, 331eaa62e82SManish V Badarkhe data_ptr, data_len, 332255ce97dSManish V Badarkhe local_sig_ptr, local_sig_len); 333*8a7505b0SLauren Wehrmeister 334*8a7505b0SLauren Wehrmeister rc = (psa_status == PSA_SUCCESS) ? CRYPTO_SUCCESS : CRYPTO_ERR_SIGNATURE; 33538f89369SManish V Badarkhe 33638f89369SManish V Badarkhe end1: 337*8a7505b0SLauren Wehrmeister return rc; 33838f89369SManish V Badarkhe end2: 3390bc36c83SRyan Everett /* Free the pk context, if it is initialized. */ 3400bc36c83SRyan Everett cleanup_pk_context(&pk, &pk_initialized); 3410bc36c83SRyan Everett 34238f89369SManish V Badarkhe return rc; 34338f89369SManish V Badarkhe } 34438f89369SManish V Badarkhe 34538f89369SManish V Badarkhe /* 34638f89369SManish V Badarkhe * Match a hash 34738f89369SManish V Badarkhe * 34838f89369SManish V Badarkhe * Digest info is passed in DER format following the ASN.1 structure detailed 34938f89369SManish V Badarkhe * above. 35038f89369SManish V Badarkhe */ 35138f89369SManish V Badarkhe static int verify_hash(void *data_ptr, unsigned int data_len, 35238f89369SManish V Badarkhe void *digest_info_ptr, unsigned int digest_info_len) 35338f89369SManish V Badarkhe { 35438f89369SManish V Badarkhe mbedtls_asn1_buf hash_oid, params; 35538f89369SManish V Badarkhe mbedtls_md_type_t md_alg; 35638f89369SManish V Badarkhe unsigned char *p, *end, *hash; 35738f89369SManish V Badarkhe size_t len; 35838f89369SManish V Badarkhe int rc; 3592ed061c4SManish V Badarkhe psa_status_t status; 3602ed061c4SManish V Badarkhe psa_algorithm_t psa_md_alg; 36138f89369SManish V Badarkhe 36238f89369SManish V Badarkhe /* 36338f89369SManish V Badarkhe * Digest info should be an MBEDTLS_ASN1_SEQUENCE, but padding after 36438f89369SManish V Badarkhe * it is allowed. This is necessary to support multiple hash 36538f89369SManish V Badarkhe * algorithms. 36638f89369SManish V Badarkhe */ 36738f89369SManish V Badarkhe p = (unsigned char *)digest_info_ptr; 36838f89369SManish V Badarkhe end = p + digest_info_len; 36938f89369SManish V Badarkhe rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | 37038f89369SManish V Badarkhe MBEDTLS_ASN1_SEQUENCE); 37138f89369SManish V Badarkhe if (rc != 0) { 37238f89369SManish V Badarkhe return CRYPTO_ERR_HASH; 37338f89369SManish V Badarkhe } 37438f89369SManish V Badarkhe 37538f89369SManish V Badarkhe end = p + len; 37638f89369SManish V Badarkhe 37738f89369SManish V Badarkhe /* Get the hash algorithm */ 37838f89369SManish V Badarkhe rc = mbedtls_asn1_get_alg(&p, end, &hash_oid, ¶ms); 37938f89369SManish V Badarkhe if (rc != 0) { 38038f89369SManish V Badarkhe return CRYPTO_ERR_HASH; 38138f89369SManish V Badarkhe } 38238f89369SManish V Badarkhe 38338f89369SManish V Badarkhe /* Hash should be octet string type and consume all bytes */ 38438f89369SManish V Badarkhe rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING); 38538f89369SManish V Badarkhe if ((rc != 0) || ((size_t)(end - p) != len)) { 38638f89369SManish V Badarkhe return CRYPTO_ERR_HASH; 38738f89369SManish V Badarkhe } 38838f89369SManish V Badarkhe hash = p; 38938f89369SManish V Badarkhe 3902ed061c4SManish V Badarkhe rc = mbedtls_oid_get_md_alg(&hash_oid, &md_alg); 39138f89369SManish V Badarkhe if (rc != 0) { 39238f89369SManish V Badarkhe return CRYPTO_ERR_HASH; 39338f89369SManish V Badarkhe } 39438f89369SManish V Badarkhe 3952ed061c4SManish V Badarkhe /* convert the md_alg to psa_algo */ 3962ed061c4SManish V Badarkhe psa_md_alg = mbedtls_md_psa_alg_from_type(md_alg); 3972ed061c4SManish V Badarkhe 3982ed061c4SManish V Badarkhe /* Length of hash must match the algorithm's size */ 3992ed061c4SManish V Badarkhe if (len != PSA_HASH_LENGTH(psa_md_alg)) { 4002ed061c4SManish V Badarkhe return CRYPTO_ERR_HASH; 4012ed061c4SManish V Badarkhe } 4022ed061c4SManish V Badarkhe 4032ed061c4SManish V Badarkhe /* 4042ed061c4SManish V Badarkhe * Calculate Hash and compare it against the retrieved hash from 4052ed061c4SManish V Badarkhe * the certificate (one shot API). 4062ed061c4SManish V Badarkhe */ 4072ed061c4SManish V Badarkhe status = psa_hash_compare(psa_md_alg, 4082ed061c4SManish V Badarkhe data_ptr, (size_t)data_len, 4092ed061c4SManish V Badarkhe (const uint8_t *)hash, len); 4102ed061c4SManish V Badarkhe 4112ed061c4SManish V Badarkhe if (status != PSA_SUCCESS) { 41238f89369SManish V Badarkhe return CRYPTO_ERR_HASH; 41338f89369SManish V Badarkhe } 41438f89369SManish V Badarkhe 41538f89369SManish V Badarkhe return CRYPTO_SUCCESS; 41638f89369SManish V Badarkhe } 41738f89369SManish V Badarkhe #endif /* 41838f89369SManish V Badarkhe * CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \ 41938f89369SManish V Badarkhe * CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC 42038f89369SManish V Badarkhe */ 42138f89369SManish V Badarkhe 422*8a7505b0SLauren Wehrmeister /* 423*8a7505b0SLauren Wehrmeister * Finish crypto usage by destroying the psa_key_ids 424*8a7505b0SLauren Wehrmeister */ 425*8a7505b0SLauren Wehrmeister static void finish(void) 426*8a7505b0SLauren Wehrmeister { 427*8a7505b0SLauren Wehrmeister #if CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \ 428*8a7505b0SLauren Wehrmeister CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC 429*8a7505b0SLauren Wehrmeister /* Destroy the psa_key_ids */ 430*8a7505b0SLauren Wehrmeister destroy_key_ids(); 431*8a7505b0SLauren Wehrmeister #endif 432*8a7505b0SLauren Wehrmeister } 433*8a7505b0SLauren Wehrmeister 43438f89369SManish V Badarkhe #if CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \ 43538f89369SManish V Badarkhe CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC 43638f89369SManish V Badarkhe /* 43738f89369SManish V Badarkhe * Map a generic crypto message digest algorithm to the corresponding macro used 43838f89369SManish V Badarkhe * by Mbed TLS. 43938f89369SManish V Badarkhe */ 44038f89369SManish V Badarkhe static inline mbedtls_md_type_t md_type(enum crypto_md_algo algo) 44138f89369SManish V Badarkhe { 44238f89369SManish V Badarkhe switch (algo) { 44338f89369SManish V Badarkhe case CRYPTO_MD_SHA512: 44438f89369SManish V Badarkhe return MBEDTLS_MD_SHA512; 44538f89369SManish V Badarkhe case CRYPTO_MD_SHA384: 44638f89369SManish V Badarkhe return MBEDTLS_MD_SHA384; 44738f89369SManish V Badarkhe case CRYPTO_MD_SHA256: 44838f89369SManish V Badarkhe return MBEDTLS_MD_SHA256; 44938f89369SManish V Badarkhe default: 45038f89369SManish V Badarkhe /* Invalid hash algorithm. */ 45138f89369SManish V Badarkhe return MBEDTLS_MD_NONE; 45238f89369SManish V Badarkhe } 45338f89369SManish V Badarkhe } 45438f89369SManish V Badarkhe 45538f89369SManish V Badarkhe /* 45638f89369SManish V Badarkhe * Calculate a hash 45738f89369SManish V Badarkhe * 45838f89369SManish V Badarkhe * output points to the computed hash 45938f89369SManish V Badarkhe */ 46038f89369SManish V Badarkhe static int calc_hash(enum crypto_md_algo md_algo, void *data_ptr, 46138f89369SManish V Badarkhe unsigned int data_len, 46238f89369SManish V Badarkhe unsigned char output[CRYPTO_MD_MAX_SIZE]) 46338f89369SManish V Badarkhe { 464484b5869SManish V Badarkhe size_t hash_length; 465484b5869SManish V Badarkhe psa_status_t status; 466484b5869SManish V Badarkhe psa_algorithm_t psa_md_alg; 46738f89369SManish V Badarkhe 468484b5869SManish V Badarkhe /* convert the md_alg to psa_algo */ 469484b5869SManish V Badarkhe psa_md_alg = mbedtls_md_psa_alg_from_type(md_type(md_algo)); 47038f89369SManish V Badarkhe 47138f89369SManish V Badarkhe /* 47238f89369SManish V Badarkhe * Calculate the hash of the data, it is safe to pass the 47338f89369SManish V Badarkhe * 'output' hash buffer pointer considering its size is always 47438f89369SManish V Badarkhe * bigger than or equal to MBEDTLS_MD_MAX_SIZE. 47538f89369SManish V Badarkhe */ 476484b5869SManish V Badarkhe status = psa_hash_compute(psa_md_alg, data_ptr, (size_t)data_len, 477484b5869SManish V Badarkhe (uint8_t *)output, CRYPTO_MD_MAX_SIZE, 478484b5869SManish V Badarkhe &hash_length); 479484b5869SManish V Badarkhe if (status != PSA_SUCCESS) { 480484b5869SManish V Badarkhe return CRYPTO_ERR_HASH; 481484b5869SManish V Badarkhe } 482484b5869SManish V Badarkhe 483484b5869SManish V Badarkhe return CRYPTO_SUCCESS; 48438f89369SManish V Badarkhe } 48538f89369SManish V Badarkhe #endif /* 48638f89369SManish V Badarkhe * CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \ 48738f89369SManish V Badarkhe * CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC 48838f89369SManish V Badarkhe */ 48938f89369SManish V Badarkhe 49038f89369SManish V Badarkhe #if TF_MBEDTLS_USE_AES_GCM 49138f89369SManish V Badarkhe /* 49238f89369SManish V Badarkhe * Stack based buffer allocation for decryption operation. It could 49338f89369SManish V Badarkhe * be configured to balance stack usage vs execution speed. 49438f89369SManish V Badarkhe */ 49538f89369SManish V Badarkhe #define DEC_OP_BUF_SIZE 128 49638f89369SManish V Badarkhe 49738f89369SManish V Badarkhe static int aes_gcm_decrypt(void *data_ptr, size_t len, const void *key, 49838f89369SManish V Badarkhe unsigned int key_len, const void *iv, 49938f89369SManish V Badarkhe unsigned int iv_len, const void *tag, 50038f89369SManish V Badarkhe unsigned int tag_len) 50138f89369SManish V Badarkhe { 5027079ddf9SRyan Everett mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; 5037079ddf9SRyan Everett psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT; 5047079ddf9SRyan Everett psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; 5057079ddf9SRyan Everett psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR; 50638f89369SManish V Badarkhe unsigned char buf[DEC_OP_BUF_SIZE]; 50738f89369SManish V Badarkhe unsigned char *pt = data_ptr; 50838f89369SManish V Badarkhe size_t dec_len; 5097079ddf9SRyan Everett size_t output_length; 51038f89369SManish V Badarkhe 5117079ddf9SRyan Everett /* Load the key into the PSA key store. */ 5127079ddf9SRyan Everett psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT); 5137079ddf9SRyan Everett psa_set_key_algorithm(&attributes, PSA_ALG_GCM); 5147079ddf9SRyan Everett psa_set_key_type(&attributes, PSA_KEY_TYPE_AES); 51538f89369SManish V Badarkhe 5167079ddf9SRyan Everett psa_status = psa_import_key(&attributes, key, key_len, &key_id); 5177079ddf9SRyan Everett if (psa_status != PSA_SUCCESS) { 5187079ddf9SRyan Everett return CRYPTO_ERR_DECRYPTION; 51938f89369SManish V Badarkhe } 52038f89369SManish V Badarkhe 5217079ddf9SRyan Everett /* Perform the decryption. */ 5227079ddf9SRyan Everett psa_status = psa_aead_decrypt_setup(&operation, key_id, PSA_ALG_GCM); 5237079ddf9SRyan Everett if (psa_status != PSA_SUCCESS) { 5247079ddf9SRyan Everett goto err; 5257079ddf9SRyan Everett } 5267079ddf9SRyan Everett 5277079ddf9SRyan Everett psa_status = psa_aead_set_nonce(&operation, iv, iv_len); 5287079ddf9SRyan Everett if (psa_status != PSA_SUCCESS) { 5297079ddf9SRyan Everett goto err; 53038f89369SManish V Badarkhe } 53138f89369SManish V Badarkhe 53238f89369SManish V Badarkhe while (len > 0) { 53338f89369SManish V Badarkhe dec_len = MIN(sizeof(buf), len); 53438f89369SManish V Badarkhe 5357079ddf9SRyan Everett psa_status = psa_aead_update(&operation, pt, dec_len, buf, 5367079ddf9SRyan Everett sizeof(buf), &output_length); 5377079ddf9SRyan Everett if (psa_status != PSA_SUCCESS) { 5387079ddf9SRyan Everett goto err; 53938f89369SManish V Badarkhe } 54038f89369SManish V Badarkhe 5417079ddf9SRyan Everett memcpy(pt, buf, output_length); 5427079ddf9SRyan Everett pt += output_length; 54338f89369SManish V Badarkhe len -= dec_len; 54438f89369SManish V Badarkhe } 54538f89369SManish V Badarkhe 5467079ddf9SRyan Everett /* Verify the tag. */ 5477079ddf9SRyan Everett psa_status = psa_aead_verify(&operation, NULL, 0, &output_length, tag, tag_len); 5487079ddf9SRyan Everett if (psa_status == PSA_SUCCESS) { 5497079ddf9SRyan Everett psa_destroy_key(key_id); 5507079ddf9SRyan Everett return CRYPTO_SUCCESS; 55138f89369SManish V Badarkhe } 55238f89369SManish V Badarkhe 5537079ddf9SRyan Everett err: 5547079ddf9SRyan Everett psa_aead_abort(&operation); 5557079ddf9SRyan Everett psa_destroy_key(key_id); 5567079ddf9SRyan Everett return CRYPTO_ERR_DECRYPTION; 55738f89369SManish V Badarkhe } 55838f89369SManish V Badarkhe 55938f89369SManish V Badarkhe /* 56038f89369SManish V Badarkhe * Authenticated decryption of an image 56138f89369SManish V Badarkhe */ 56238f89369SManish V Badarkhe static int auth_decrypt(enum crypto_dec_algo dec_algo, void *data_ptr, 56338f89369SManish V Badarkhe size_t len, const void *key, unsigned int key_len, 56438f89369SManish V Badarkhe unsigned int key_flags, const void *iv, 56538f89369SManish V Badarkhe unsigned int iv_len, const void *tag, 56638f89369SManish V Badarkhe unsigned int tag_len) 56738f89369SManish V Badarkhe { 56838f89369SManish V Badarkhe int rc; 56938f89369SManish V Badarkhe 57038f89369SManish V Badarkhe assert((key_flags & ENC_KEY_IS_IDENTIFIER) == 0); 57138f89369SManish V Badarkhe 57238f89369SManish V Badarkhe switch (dec_algo) { 57338f89369SManish V Badarkhe case CRYPTO_GCM_DECRYPT: 57438f89369SManish V Badarkhe rc = aes_gcm_decrypt(data_ptr, len, key, key_len, iv, iv_len, 57538f89369SManish V Badarkhe tag, tag_len); 57638f89369SManish V Badarkhe if (rc != 0) 57738f89369SManish V Badarkhe return rc; 57838f89369SManish V Badarkhe break; 57938f89369SManish V Badarkhe default: 58038f89369SManish V Badarkhe return CRYPTO_ERR_DECRYPTION; 58138f89369SManish V Badarkhe } 58238f89369SManish V Badarkhe 58338f89369SManish V Badarkhe return CRYPTO_SUCCESS; 58438f89369SManish V Badarkhe } 58538f89369SManish V Badarkhe #endif /* TF_MBEDTLS_USE_AES_GCM */ 58638f89369SManish V Badarkhe 58738f89369SManish V Badarkhe /* 58838f89369SManish V Badarkhe * Register crypto library descriptor 58938f89369SManish V Badarkhe */ 59038f89369SManish V Badarkhe #if CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC 59138f89369SManish V Badarkhe #if TF_MBEDTLS_USE_AES_GCM 59238f89369SManish V Badarkhe REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash, 593*8a7505b0SLauren Wehrmeister auth_decrypt, NULL, finish); 59438f89369SManish V Badarkhe #else 59538f89369SManish V Badarkhe REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash, 596*8a7505b0SLauren Wehrmeister NULL, NULL, finish); 59738f89369SManish V Badarkhe #endif 59838f89369SManish V Badarkhe #elif CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY 59938f89369SManish V Badarkhe #if TF_MBEDTLS_USE_AES_GCM 60038f89369SManish V Badarkhe REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL, 601*8a7505b0SLauren Wehrmeister auth_decrypt, NULL, finish); 60238f89369SManish V Badarkhe #else 60338f89369SManish V Badarkhe REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL, 604*8a7505b0SLauren Wehrmeister NULL, NULL, finish); 60538f89369SManish V Badarkhe #endif 60638f89369SManish V Badarkhe #elif CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY 607*8a7505b0SLauren Wehrmeister REGISTER_CRYPTO_LIB(LIB_NAME, init, NULL, NULL, calc_hash, NULL, NULL, finish); 60838f89369SManish V Badarkhe #endif /* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */ 609