xref: /rk3399_ARM-atf/drivers/auth/mbedtls/mbedtls_psa_crypto.c (revision 12a8e95303c051dc5671441a6419741db3b0964e)
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/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>
2438f89369SManish V Badarkhe #include <drivers/auth/crypto_mod.h>
2538f89369SManish V Badarkhe #include <drivers/auth/mbedtls/mbedtls_common.h>
2638f89369SManish V Badarkhe #include <plat/common/platform.h>
2738f89369SManish V Badarkhe 
2838f89369SManish V Badarkhe #define LIB_NAME		"mbed TLS PSA"
2938f89369SManish V Badarkhe 
30*12a8e953SRyan Everett /* Minimum required size for a buffer containing a raw EC signature when using
31*12a8e953SRyan Everett  * a maximum curve size of 384 bits.
32*12a8e953SRyan Everett  * This is calculated as 2 * (384 / 8). */
33*12a8e953SRyan Everett #define ECDSA_SIG_BUFFER_SIZE	96U
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);
1170bc36c83SRyan Everett 
1180bc36c83SRyan Everett /*
1190bc36c83SRyan Everett  * This is a helper function which parses a SignatureAlgorithm OID.
1200bc36c83SRyan Everett  * It extracts the pk algorithm and constructs a psa_algorithm_t object
1210bc36c83SRyan Everett  * to be used by PSA calls.
1220bc36c83SRyan Everett  */
1230bc36c83SRyan Everett static int construct_psa_alg(void *sig_alg, unsigned int sig_alg_len,
1240bc36c83SRyan Everett 			     mbedtls_pk_type_t *pk_alg, psa_algorithm_t *psa_alg)
1250bc36c83SRyan Everett {
1260bc36c83SRyan Everett 	int rc;
1270bc36c83SRyan Everett 	mbedtls_md_type_t md_alg;
1280bc36c83SRyan Everett 	void *sig_opts = NULL;
1290bc36c83SRyan Everett 	mbedtls_asn1_buf sig_alg_oid, params;
1300bc36c83SRyan Everett 	unsigned char *p = (unsigned char *) sig_alg;
1310bc36c83SRyan Everett 	unsigned char *end = (unsigned char *) sig_alg + sig_alg_len;
1320bc36c83SRyan Everett 
1330bc36c83SRyan Everett 	rc = mbedtls_asn1_get_alg(&p, end, &sig_alg_oid, &params);
1340bc36c83SRyan Everett 	if (rc != 0) {
1350bc36c83SRyan Everett 		rc = CRYPTO_ERR_SIGNATURE;
1360bc36c83SRyan Everett 		goto end;
1370bc36c83SRyan Everett 	}
1380bc36c83SRyan Everett 
1390bc36c83SRyan Everett 	rc = mbedtls_x509_get_sig_alg(&sig_alg_oid, &params, &md_alg, pk_alg, &sig_opts);
1400bc36c83SRyan Everett 	if (rc != 0) {
1410bc36c83SRyan Everett 		rc = CRYPTO_ERR_SIGNATURE;
1420bc36c83SRyan Everett 		goto end;
1430bc36c83SRyan Everett 	}
1440bc36c83SRyan Everett 
1450bc36c83SRyan Everett 	psa_algorithm_t psa_md_alg = mbedtls_md_psa_alg_from_type(md_alg);
1460bc36c83SRyan Everett 
1470bc36c83SRyan Everett 	switch (*pk_alg) {
1480bc36c83SRyan Everett 	case MBEDTLS_PK_RSASSA_PSS:
1490bc36c83SRyan Everett 		*psa_alg = PSA_ALG_RSA_PSS(psa_md_alg);
1500bc36c83SRyan Everett 		rc = CRYPTO_SUCCESS;
1510bc36c83SRyan Everett 		break;
1520bc36c83SRyan Everett 	case MBEDTLS_PK_ECDSA:
1530bc36c83SRyan Everett 		*psa_alg = PSA_ALG_ECDSA(psa_md_alg);
1540bc36c83SRyan Everett 		rc = CRYPTO_SUCCESS;
1550bc36c83SRyan Everett 		break;
1560bc36c83SRyan Everett 	default:
1570bc36c83SRyan Everett 		*psa_alg = PSA_ALG_NONE;
1580bc36c83SRyan Everett 		rc = CRYPTO_ERR_SIGNATURE;
1590bc36c83SRyan Everett 		break;
1600bc36c83SRyan Everett 	}
1610bc36c83SRyan Everett 
1620bc36c83SRyan Everett end:
1630bc36c83SRyan Everett 	mbedtls_free(sig_opts);
1640bc36c83SRyan Everett 	return rc;
1650bc36c83SRyan Everett }
1660bc36c83SRyan Everett 
1670bc36c83SRyan Everett /*
1680bc36c83SRyan Everett  * Helper functions for mbedtls PK contexts.
1690bc36c83SRyan Everett  */
1700bc36c83SRyan Everett static void initialize_pk_context(mbedtls_pk_context *pk, bool *pk_initialized)
1710bc36c83SRyan Everett {
1720bc36c83SRyan Everett 	mbedtls_pk_init(pk);
1730bc36c83SRyan Everett 	*pk_initialized = true;
1740bc36c83SRyan Everett }
1750bc36c83SRyan Everett 
1760bc36c83SRyan Everett static void cleanup_pk_context(mbedtls_pk_context *pk, bool *pk_initialized)
1770bc36c83SRyan Everett {
1780bc36c83SRyan Everett 	if (*pk_initialized) {
1790bc36c83SRyan Everett 		mbedtls_pk_free(pk);
1800bc36c83SRyan Everett 		*pk_initialized = false;
1810bc36c83SRyan Everett 	}
1820bc36c83SRyan Everett }
1830bc36c83SRyan 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;
1960bc36c83SRyan Everett 	mbedtls_pk_context pk;
1970bc36c83SRyan Everett 	bool pk_initialized = false;
1980bc36c83SRyan Everett 	int rc = CRYPTO_ERR_SIGNATURE;
1990bc36c83SRyan Everett 	psa_status_t psa_status = PSA_ERROR_CORRUPTION_DETECTED;
2000bc36c83SRyan Everett 	psa_key_attributes_t psa_key_attr = PSA_KEY_ATTRIBUTES_INIT;
2010bc36c83SRyan Everett 	psa_key_id_t psa_key_id;
2020bc36c83SRyan Everett 	mbedtls_pk_type_t pk_alg;
2030bc36c83SRyan Everett 	psa_algorithm_t psa_alg;
204*12a8e953SRyan Everett 	__unused unsigned char reformatted_sig[ECDSA_SIG_BUFFER_SIZE] = {0};
205255ce97dSManish V Badarkhe 	unsigned char *local_sig_ptr;
206255ce97dSManish V Badarkhe 	size_t local_sig_len;
207eaa62e82SManish V Badarkhe 
2080bc36c83SRyan Everett 	/* Load the key into the PSA key store. */
2090bc36c83SRyan Everett 	initialize_pk_context(&pk, &pk_initialized);
21038f89369SManish V Badarkhe 
2110bc36c83SRyan Everett 	p = (unsigned char *) pk_ptr;
2120bc36c83SRyan Everett 	end = p + pk_len;
2130bc36c83SRyan 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 
2190bc36c83SRyan Everett 	rc = mbedtls_pk_get_psa_attributes(&pk, PSA_KEY_USAGE_VERIFY_MESSAGE, &psa_key_attr);
2200bc36c83SRyan Everett 	if (rc != 0) {
2210bc36c83SRyan Everett 		rc = CRYPTO_ERR_SIGNATURE;
2220bc36c83SRyan Everett 		goto end2;
2230bc36c83SRyan Everett 	}
2240bc36c83SRyan Everett 
2250bc36c83SRyan Everett 	rc = construct_psa_alg(sig_alg, sig_alg_len, &pk_alg, &psa_alg);
2260bc36c83SRyan Everett 	if (rc != CRYPTO_SUCCESS) {
2270bc36c83SRyan Everett 		goto end2;
2280bc36c83SRyan Everett 	}
2290bc36c83SRyan Everett 	psa_set_key_algorithm(&psa_key_attr, psa_alg);
2300bc36c83SRyan Everett 
2310bc36c83SRyan Everett 	rc = mbedtls_pk_import_into_psa(&pk, &psa_key_attr, &psa_key_id);
2320bc36c83SRyan Everett 	if (rc != 0) {
2330bc36c83SRyan Everett 		rc = CRYPTO_ERR_SIGNATURE;
2340bc36c83SRyan Everett 		goto end2;
2350bc36c83SRyan Everett 	}
2360bc36c83SRyan Everett 
2370bc36c83SRyan Everett 	/* Optimize mbedtls heap usage by freeing the pk context now.  */
2380bc36c83SRyan Everett 	cleanup_pk_context(&pk, &pk_initialized);
2390bc36c83SRyan Everett 
2400bc36c83SRyan Everett 	/* Extract the signature from sig_ptr. */
2410bc36c83SRyan Everett 	p = (unsigned char *) sig_ptr;
2420bc36c83SRyan Everett 	end = p + sig_len;
2430bc36c83SRyan Everett 	rc = mbedtls_asn1_get_bitstring_null(&p, end, &local_sig_len);
2440bc36c83SRyan Everett 	if (rc != 0) {
2450bc36c83SRyan Everett 		rc = CRYPTO_ERR_SIGNATURE;
2460bc36c83SRyan Everett 		goto end1;
2470bc36c83SRyan 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) {
2530bc36c83SRyan Everett 		/* Convert the DER ASN.1 signature to raw format. */
2540bc36c83SRyan Everett 		size_t key_bits = psa_get_key_bits(&psa_key_attr);
255255ce97dSManish V Badarkhe 
2560bc36c83SRyan Everett 		rc = mbedtls_ecdsa_der_to_raw(key_bits, p, local_sig_len,
257*12a8e953SRyan Everett 					      reformatted_sig, ECDSA_SIG_BUFFER_SIZE,
2580bc36c83SRyan Everett 					      &local_sig_len);
2590bc36c83SRyan Everett 		if (rc != 0) {
2600bc36c83SRyan Everett 			rc = CRYPTO_ERR_SIGNATURE;
2610bc36c83SRyan Everett 			goto end1;
2620bc36c83SRyan 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 
2700bc36c83SRyan Everett 	/* Verify the signature. */
2710bc36c83SRyan 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);
2740bc36c83SRyan Everett 	if (psa_status == PSA_SUCCESS) {
2750bc36c83SRyan Everett 		/* The signature has been successfully verified. */
2760bc36c83SRyan Everett 		rc = CRYPTO_SUCCESS;
2770bc36c83SRyan Everett 	} else {
27838f89369SManish V Badarkhe 		rc = CRYPTO_ERR_SIGNATURE;
27938f89369SManish V Badarkhe 	}
28038f89369SManish V Badarkhe 
28138f89369SManish V Badarkhe end1:
2820bc36c83SRyan Everett 	/* Destroy the key from the PSA subsystem. */
283eaa62e82SManish V Badarkhe 	psa_destroy_key(psa_key_id);
28438f89369SManish V Badarkhe end2:
2850bc36c83SRyan Everett 	/* Free the pk context, if it is initialized. */
2860bc36c83SRyan Everett 	cleanup_pk_context(&pk, &pk_initialized);
2870bc36c83SRyan 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, &params);
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 {
4367079ddf9SRyan Everett 	mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
4377079ddf9SRyan Everett 	psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT;
4387079ddf9SRyan Everett 	psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
4397079ddf9SRyan Everett 	psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
44038f89369SManish V Badarkhe 	unsigned char buf[DEC_OP_BUF_SIZE];
44138f89369SManish V Badarkhe 	unsigned char *pt = data_ptr;
44238f89369SManish V Badarkhe 	size_t dec_len;
4437079ddf9SRyan Everett 	size_t output_length;
44438f89369SManish V Badarkhe 
4457079ddf9SRyan Everett 	/* Load the key into the PSA key store. */
4467079ddf9SRyan Everett 	psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT);
4477079ddf9SRyan Everett 	psa_set_key_algorithm(&attributes, PSA_ALG_GCM);
4487079ddf9SRyan Everett 	psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
44938f89369SManish V Badarkhe 
4507079ddf9SRyan Everett 	psa_status = psa_import_key(&attributes, key, key_len, &key_id);
4517079ddf9SRyan Everett 	if (psa_status != PSA_SUCCESS) {
4527079ddf9SRyan Everett 		return CRYPTO_ERR_DECRYPTION;
45338f89369SManish V Badarkhe 	}
45438f89369SManish V Badarkhe 
4557079ddf9SRyan Everett 	/* Perform the decryption. */
4567079ddf9SRyan Everett 	psa_status = psa_aead_decrypt_setup(&operation, key_id, PSA_ALG_GCM);
4577079ddf9SRyan Everett 	if (psa_status != PSA_SUCCESS) {
4587079ddf9SRyan Everett 		goto err;
4597079ddf9SRyan Everett 	}
4607079ddf9SRyan Everett 
4617079ddf9SRyan Everett 	psa_status = psa_aead_set_nonce(&operation, iv, iv_len);
4627079ddf9SRyan Everett 	if (psa_status != PSA_SUCCESS) {
4637079ddf9SRyan Everett 		goto err;
46438f89369SManish V Badarkhe 	}
46538f89369SManish V Badarkhe 
46638f89369SManish V Badarkhe 	while (len > 0) {
46738f89369SManish V Badarkhe 		dec_len = MIN(sizeof(buf), len);
46838f89369SManish V Badarkhe 
4697079ddf9SRyan Everett 		psa_status = psa_aead_update(&operation, pt, dec_len, buf,
4707079ddf9SRyan Everett 					     sizeof(buf), &output_length);
4717079ddf9SRyan Everett 		if (psa_status != PSA_SUCCESS) {
4727079ddf9SRyan Everett 			goto err;
47338f89369SManish V Badarkhe 		}
47438f89369SManish V Badarkhe 
4757079ddf9SRyan Everett 		memcpy(pt, buf, output_length);
4767079ddf9SRyan Everett 		pt += output_length;
47738f89369SManish V Badarkhe 		len -= dec_len;
47838f89369SManish V Badarkhe 	}
47938f89369SManish V Badarkhe 
4807079ddf9SRyan Everett 	/* Verify the tag. */
4817079ddf9SRyan Everett 	psa_status = psa_aead_verify(&operation, NULL, 0, &output_length, tag, tag_len);
4827079ddf9SRyan Everett 	if (psa_status == PSA_SUCCESS) {
4837079ddf9SRyan Everett 		psa_destroy_key(key_id);
4847079ddf9SRyan Everett 		return CRYPTO_SUCCESS;
48538f89369SManish V Badarkhe 	}
48638f89369SManish V Badarkhe 
4877079ddf9SRyan Everett err:
4887079ddf9SRyan Everett 	psa_aead_abort(&operation);
4897079ddf9SRyan Everett 	psa_destroy_key(key_id);
4907079ddf9SRyan Everett 	return CRYPTO_ERR_DECRYPTION;
49138f89369SManish V Badarkhe }
49238f89369SManish V Badarkhe 
49338f89369SManish V Badarkhe /*
49438f89369SManish V Badarkhe  * Authenticated decryption of an image
49538f89369SManish V Badarkhe  */
49638f89369SManish V Badarkhe static int auth_decrypt(enum crypto_dec_algo dec_algo, void *data_ptr,
49738f89369SManish V Badarkhe 			size_t len, const void *key, unsigned int key_len,
49838f89369SManish V Badarkhe 			unsigned int key_flags, const void *iv,
49938f89369SManish V Badarkhe 			unsigned int iv_len, const void *tag,
50038f89369SManish V Badarkhe 			unsigned int tag_len)
50138f89369SManish V Badarkhe {
50238f89369SManish V Badarkhe 	int rc;
50338f89369SManish V Badarkhe 
50438f89369SManish V Badarkhe 	assert((key_flags & ENC_KEY_IS_IDENTIFIER) == 0);
50538f89369SManish V Badarkhe 
50638f89369SManish V Badarkhe 	switch (dec_algo) {
50738f89369SManish V Badarkhe 	case CRYPTO_GCM_DECRYPT:
50838f89369SManish V Badarkhe 		rc = aes_gcm_decrypt(data_ptr, len, key, key_len, iv, iv_len,
50938f89369SManish V Badarkhe 				     tag, tag_len);
51038f89369SManish V Badarkhe 		if (rc != 0)
51138f89369SManish V Badarkhe 			return rc;
51238f89369SManish V Badarkhe 		break;
51338f89369SManish V Badarkhe 	default:
51438f89369SManish V Badarkhe 		return CRYPTO_ERR_DECRYPTION;
51538f89369SManish V Badarkhe 	}
51638f89369SManish V Badarkhe 
51738f89369SManish V Badarkhe 	return CRYPTO_SUCCESS;
51838f89369SManish V Badarkhe }
51938f89369SManish V Badarkhe #endif /* TF_MBEDTLS_USE_AES_GCM */
52038f89369SManish V Badarkhe 
52138f89369SManish V Badarkhe /*
52238f89369SManish V Badarkhe  * Register crypto library descriptor
52338f89369SManish V Badarkhe  */
52438f89369SManish V Badarkhe #if CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
52538f89369SManish V Badarkhe #if TF_MBEDTLS_USE_AES_GCM
52638f89369SManish V Badarkhe REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash,
52738f89369SManish V Badarkhe 		    auth_decrypt, NULL);
52838f89369SManish V Badarkhe #else
52938f89369SManish V Badarkhe REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash,
53038f89369SManish V Badarkhe 		    NULL, NULL);
53138f89369SManish V Badarkhe #endif
53238f89369SManish V Badarkhe #elif CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY
53338f89369SManish V Badarkhe #if TF_MBEDTLS_USE_AES_GCM
53438f89369SManish V Badarkhe REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL,
53538f89369SManish V Badarkhe 		    auth_decrypt, NULL);
53638f89369SManish V Badarkhe #else
53738f89369SManish V Badarkhe REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL,
53838f89369SManish V Badarkhe 		    NULL, NULL);
53938f89369SManish V Badarkhe #endif
54038f89369SManish V Badarkhe #elif CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY
54138f89369SManish V Badarkhe REGISTER_CRYPTO_LIB(LIB_NAME, init, NULL, NULL, calc_hash, NULL, NULL);
54238f89369SManish V Badarkhe #endif /* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */
543