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