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 */
mbedtls_psa_external_get_random(mbedtls_psa_external_random_context_t * context,uint8_t * output,size_t output_size,size_t * output_length)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 */
init(void)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 */
destroy_key_ids(void)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 */
get_cached_psa_key_info(const char * pk_oid,psa_key_id_t * key_id,psa_algorithm_t * psa_alg,psa_key_attributes_t * psa_key_attr)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 */
cache_psa_key_info(const char * pk_oid,psa_key_id_t key_id,psa_algorithm_t psa_alg,psa_key_attributes_t psa_key_attr)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 */
construct_psa_alg(void * sig_alg,unsigned int sig_alg_len,mbedtls_pk_type_t * pk_alg,psa_algorithm_t * psa_alg)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 */
initialize_pk_context(mbedtls_pk_context * pk,bool * pk_initialized)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
cleanup_pk_context(mbedtls_pk_context * pk,bool * pk_initialized)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 */
verify_signature(void * data_ptr,unsigned int data_len,void * sig_ptr,unsigned int sig_len,void * sig_alg,unsigned int sig_alg_len,void * pk_ptr,unsigned int pk_len)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 */
verify_hash(void * data_ptr,unsigned int data_len,void * digest_info_ptr,unsigned int digest_info_len)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 */
finish(void)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 */
md_type(enum crypto_md_algo algo)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 */
calc_hash(enum crypto_md_algo md_algo,void * data_ptr,unsigned int data_len,unsigned char output[CRYPTO_MD_MAX_SIZE])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
aes_gcm_decrypt(void * data_ptr,size_t len,const void * key,unsigned int key_len,const void * iv,unsigned int iv_len,const void * tag,unsigned int tag_len)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 */
auth_decrypt(enum crypto_dec_algo dec_algo,void * data_ptr,size_t len,const void * key,unsigned int key_len,unsigned int key_flags,const void * iv,unsigned int iv_len,const void * tag,unsigned int tag_len)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