xref: /arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_psa_crypto.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2023, Arm Limited. All rights reserved.
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu  */
6*91f16700Schasinglulu 
7*91f16700Schasinglulu #include <assert.h>
8*91f16700Schasinglulu #include <stddef.h>
9*91f16700Schasinglulu #include <string.h>
10*91f16700Schasinglulu 
11*91f16700Schasinglulu /* mbed TLS headers */
12*91f16700Schasinglulu #include <mbedtls/gcm.h>
13*91f16700Schasinglulu #include <mbedtls/md.h>
14*91f16700Schasinglulu #include <mbedtls/memory_buffer_alloc.h>
15*91f16700Schasinglulu #include <mbedtls/oid.h>
16*91f16700Schasinglulu #include <mbedtls/platform.h>
17*91f16700Schasinglulu #include <mbedtls/version.h>
18*91f16700Schasinglulu #include <mbedtls/x509.h>
19*91f16700Schasinglulu #include <psa/crypto.h>
20*91f16700Schasinglulu #include <psa/crypto_platform.h>
21*91f16700Schasinglulu #include <psa/crypto_types.h>
22*91f16700Schasinglulu #include <psa/crypto_values.h>
23*91f16700Schasinglulu 
24*91f16700Schasinglulu #include <common/debug.h>
25*91f16700Schasinglulu #include <drivers/auth/crypto_mod.h>
26*91f16700Schasinglulu #include <drivers/auth/mbedtls/mbedtls_common.h>
27*91f16700Schasinglulu #include <plat/common/platform.h>
28*91f16700Schasinglulu 
29*91f16700Schasinglulu #define LIB_NAME		"mbed TLS PSA"
30*91f16700Schasinglulu 
31*91f16700Schasinglulu /* Maximum length of R_S pair in the ECDSA signature in bytes */
32*91f16700Schasinglulu #define MAX_ECDSA_R_S_PAIR_LEN	64U
33*91f16700Schasinglulu 
34*91f16700Schasinglulu /* Size of ASN.1 length and tag in bytes*/
35*91f16700Schasinglulu #define SIZE_OF_ASN1_LEN	1U
36*91f16700Schasinglulu #define SIZE_OF_ASN1_TAG	1U
37*91f16700Schasinglulu 
38*91f16700Schasinglulu #if CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \
39*91f16700Schasinglulu CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
40*91f16700Schasinglulu /*
41*91f16700Schasinglulu  * CRYPTO_MD_MAX_SIZE value is as per current stronger algorithm available
42*91f16700Schasinglulu  * so make sure that mbed TLS MD maximum size must be lesser than this.
43*91f16700Schasinglulu  */
44*91f16700Schasinglulu CASSERT(CRYPTO_MD_MAX_SIZE >= MBEDTLS_MD_MAX_SIZE,
45*91f16700Schasinglulu 	assert_mbedtls_md_size_overflow);
46*91f16700Schasinglulu 
47*91f16700Schasinglulu #endif /*
48*91f16700Schasinglulu 	* CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \
49*91f16700Schasinglulu 	* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
50*91f16700Schasinglulu 	*/
51*91f16700Schasinglulu 
52*91f16700Schasinglulu static inline psa_algorithm_t mbedtls_md_psa_alg_from_type(
53*91f16700Schasinglulu 						mbedtls_md_type_t md_type)
54*91f16700Schasinglulu {
55*91f16700Schasinglulu 	assert((md_type == MBEDTLS_MD_SHA256) ||
56*91f16700Schasinglulu 	       (md_type == MBEDTLS_MD_SHA384) ||
57*91f16700Schasinglulu 	       (md_type == MBEDTLS_MD_SHA512));
58*91f16700Schasinglulu 
59*91f16700Schasinglulu 	return PSA_ALG_CATEGORY_HASH | (psa_algorithm_t) (md_type + 0x5);
60*91f16700Schasinglulu }
61*91f16700Schasinglulu 
62*91f16700Schasinglulu /*
63*91f16700Schasinglulu  * AlgorithmIdentifier  ::=  SEQUENCE  {
64*91f16700Schasinglulu  *     algorithm               OBJECT IDENTIFIER,
65*91f16700Schasinglulu  *     parameters              ANY DEFINED BY algorithm OPTIONAL
66*91f16700Schasinglulu  * }
67*91f16700Schasinglulu  *
68*91f16700Schasinglulu  * SubjectPublicKeyInfo  ::=  SEQUENCE  {
69*91f16700Schasinglulu  *     algorithm            AlgorithmIdentifier,
70*91f16700Schasinglulu  *     subjectPublicKey     BIT STRING
71*91f16700Schasinglulu  * }
72*91f16700Schasinglulu  *
73*91f16700Schasinglulu  * DigestInfo ::= SEQUENCE {
74*91f16700Schasinglulu  *     digestAlgorithm AlgorithmIdentifier,
75*91f16700Schasinglulu  *     digest OCTET STRING
76*91f16700Schasinglulu  * }
77*91f16700Schasinglulu  */
78*91f16700Schasinglulu 
79*91f16700Schasinglulu /*
80*91f16700Schasinglulu  * We pretend using an external RNG (through MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG
81*91f16700Schasinglulu  * mbedTLS config option) so we need to provide an implementation of
82*91f16700Schasinglulu  * mbedtls_psa_external_get_random(). Provide a fake one, since we do not
83*91f16700Schasinglulu  * actually have any external RNG and TF-A itself doesn't engage in
84*91f16700Schasinglulu  * cryptographic operations that demands randomness.
85*91f16700Schasinglulu  */
86*91f16700Schasinglulu psa_status_t mbedtls_psa_external_get_random(
87*91f16700Schasinglulu 			mbedtls_psa_external_random_context_t *context,
88*91f16700Schasinglulu 			uint8_t *output, size_t output_size,
89*91f16700Schasinglulu 			size_t *output_length)
90*91f16700Schasinglulu {
91*91f16700Schasinglulu 	return PSA_ERROR_INSUFFICIENT_ENTROPY;
92*91f16700Schasinglulu }
93*91f16700Schasinglulu 
94*91f16700Schasinglulu /*
95*91f16700Schasinglulu  * Initialize the library and export the descriptor
96*91f16700Schasinglulu  */
97*91f16700Schasinglulu static void init(void)
98*91f16700Schasinglulu {
99*91f16700Schasinglulu 	/* Initialize mbed TLS */
100*91f16700Schasinglulu 	mbedtls_init();
101*91f16700Schasinglulu 
102*91f16700Schasinglulu 	/* Initialise PSA mbedTLS */
103*91f16700Schasinglulu 	psa_status_t status = psa_crypto_init();
104*91f16700Schasinglulu 
105*91f16700Schasinglulu 	if (status != PSA_SUCCESS) {
106*91f16700Schasinglulu 		ERROR("Failed to initialize %s crypto (%d).\n", LIB_NAME, status);
107*91f16700Schasinglulu 		panic();
108*91f16700Schasinglulu 	}
109*91f16700Schasinglulu 
110*91f16700Schasinglulu 	INFO("PSA crypto initialized successfully!\n");
111*91f16700Schasinglulu }
112*91f16700Schasinglulu 
113*91f16700Schasinglulu #if CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \
114*91f16700Schasinglulu CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
115*91f16700Schasinglulu 
116*91f16700Schasinglulu static void construct_psa_key_alg_and_type(mbedtls_pk_type_t pk_alg,
117*91f16700Schasinglulu 					   mbedtls_md_type_t md_alg,
118*91f16700Schasinglulu 					   psa_ecc_family_t psa_ecc_family,
119*91f16700Schasinglulu 					   psa_algorithm_t *psa_alg,
120*91f16700Schasinglulu 					   psa_key_type_t *psa_key_type)
121*91f16700Schasinglulu {
122*91f16700Schasinglulu 	psa_algorithm_t psa_md_alg = mbedtls_md_psa_alg_from_type(md_alg);
123*91f16700Schasinglulu 
124*91f16700Schasinglulu 	switch (pk_alg) {
125*91f16700Schasinglulu 	case MBEDTLS_PK_RSASSA_PSS:
126*91f16700Schasinglulu 		*psa_alg = PSA_ALG_RSA_PSS(psa_md_alg);
127*91f16700Schasinglulu 		*psa_key_type = PSA_KEY_TYPE_RSA_PUBLIC_KEY;
128*91f16700Schasinglulu 		break;
129*91f16700Schasinglulu 	case MBEDTLS_PK_ECDSA:
130*91f16700Schasinglulu 		*psa_alg = PSA_ALG_ECDSA(psa_md_alg);
131*91f16700Schasinglulu 		*psa_key_type = PSA_KEY_TYPE_ECC_PUBLIC_KEY(psa_ecc_family);
132*91f16700Schasinglulu 		break;
133*91f16700Schasinglulu 	default:
134*91f16700Schasinglulu 		*psa_alg = PSA_ALG_NONE;
135*91f16700Schasinglulu 		*psa_key_type = PSA_KEY_TYPE_NONE;
136*91f16700Schasinglulu 		break;
137*91f16700Schasinglulu 	}
138*91f16700Schasinglulu }
139*91f16700Schasinglulu 
140*91f16700Schasinglulu 
141*91f16700Schasinglulu #if TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_ECDSA || \
142*91f16700Schasinglulu TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA_AND_ECDSA
143*91f16700Schasinglulu 
144*91f16700Schasinglulu /*
145*91f16700Schasinglulu  * This is a helper function to detect padding byte (if the MSB bit of the
146*91f16700Schasinglulu  * first data byte is set to 1, for example 0x80) and on detection, ignore the
147*91f16700Schasinglulu  * padded byte(0x00) and increase the buffer pointer beyond padded byte and
148*91f16700Schasinglulu  * decrease the length of the buffer by 1.
149*91f16700Schasinglulu  *
150*91f16700Schasinglulu  * On Success returns 0, error otherwise.
151*91f16700Schasinglulu  **/
152*91f16700Schasinglulu static inline int ignore_asn1_int_padding_byte(unsigned char **buf_start,
153*91f16700Schasinglulu 					       size_t *buf_len)
154*91f16700Schasinglulu {
155*91f16700Schasinglulu 	unsigned char *local_buf = *buf_start;
156*91f16700Schasinglulu 
157*91f16700Schasinglulu 	/* Check for negative number */
158*91f16700Schasinglulu 	if ((local_buf[0] & 0x80U) != 0U) {
159*91f16700Schasinglulu 		return -1;
160*91f16700Schasinglulu 	}
161*91f16700Schasinglulu 
162*91f16700Schasinglulu 	if ((local_buf[0] == 0U) && (local_buf[1] > 0x7FU) &&
163*91f16700Schasinglulu 	    (*buf_len > 1U)) {
164*91f16700Schasinglulu 		*buf_start = &local_buf[1];
165*91f16700Schasinglulu 		(*buf_len)--;
166*91f16700Schasinglulu 	}
167*91f16700Schasinglulu 
168*91f16700Schasinglulu 	return 0;
169*91f16700Schasinglulu }
170*91f16700Schasinglulu 
171*91f16700Schasinglulu /*
172*91f16700Schasinglulu  * This is a helper function that gets a pointer to the encoded ECDSA publicKey
173*91f16700Schasinglulu  * and its length (as per RFC5280) and returns corresponding decoded publicKey
174*91f16700Schasinglulu  * and its length. As well, it retrieves the family of ECC key in the PSA
175*91f16700Schasinglulu  * format.
176*91f16700Schasinglulu  *
177*91f16700Schasinglulu  * This function returns error(CRYPTO_ERR_SIGNATURE) on ASN.1 parsing failure,
178*91f16700Schasinglulu  * otherwise success(0).
179*91f16700Schasinglulu  **/
180*91f16700Schasinglulu static int get_ecdsa_pkinfo_from_asn1(unsigned char **pk_start,
181*91f16700Schasinglulu 				      unsigned int *pk_len,
182*91f16700Schasinglulu 				      psa_ecc_family_t *psa_ecc_family)
183*91f16700Schasinglulu {
184*91f16700Schasinglulu 	mbedtls_asn1_buf alg_oid, alg_params;
185*91f16700Schasinglulu 	mbedtls_ecp_group_id grp_id;
186*91f16700Schasinglulu 	int rc;
187*91f16700Schasinglulu 	unsigned char *pk_end;
188*91f16700Schasinglulu 	size_t len;
189*91f16700Schasinglulu 	size_t curve_bits;
190*91f16700Schasinglulu 	unsigned char *pk_ptr = *pk_start;
191*91f16700Schasinglulu 
192*91f16700Schasinglulu 	pk_end = pk_ptr + *pk_len;
193*91f16700Schasinglulu 	rc = mbedtls_asn1_get_tag(&pk_ptr, pk_end, &len,
194*91f16700Schasinglulu 				  MBEDTLS_ASN1_CONSTRUCTED |
195*91f16700Schasinglulu 				  MBEDTLS_ASN1_SEQUENCE);
196*91f16700Schasinglulu 	if (rc != 0) {
197*91f16700Schasinglulu 		return CRYPTO_ERR_SIGNATURE;
198*91f16700Schasinglulu 	}
199*91f16700Schasinglulu 
200*91f16700Schasinglulu 	pk_end = pk_ptr + len;
201*91f16700Schasinglulu 	rc = mbedtls_asn1_get_alg(&pk_ptr, pk_end, &alg_oid, &alg_params);
202*91f16700Schasinglulu 	if (rc != 0) {
203*91f16700Schasinglulu 		return CRYPTO_ERR_SIGNATURE;
204*91f16700Schasinglulu 	}
205*91f16700Schasinglulu 
206*91f16700Schasinglulu 	if (alg_params.tag == MBEDTLS_ASN1_OID) {
207*91f16700Schasinglulu 		if (mbedtls_oid_get_ec_grp(&alg_params, &grp_id) != 0) {
208*91f16700Schasinglulu 			return CRYPTO_ERR_SIGNATURE;
209*91f16700Schasinglulu 		}
210*91f16700Schasinglulu 		*psa_ecc_family = mbedtls_ecc_group_to_psa(grp_id,
211*91f16700Schasinglulu 							   &curve_bits);
212*91f16700Schasinglulu 	} else {
213*91f16700Schasinglulu 		return CRYPTO_ERR_SIGNATURE;
214*91f16700Schasinglulu 	}
215*91f16700Schasinglulu 
216*91f16700Schasinglulu 	pk_end = pk_ptr + len - (alg_oid.len + alg_params.len +
217*91f16700Schasinglulu 		 2 * (SIZE_OF_ASN1_LEN + SIZE_OF_ASN1_TAG));
218*91f16700Schasinglulu 	rc = mbedtls_asn1_get_bitstring_null(&pk_ptr, pk_end, &len);
219*91f16700Schasinglulu 	if (rc != 0) {
220*91f16700Schasinglulu 		return CRYPTO_ERR_SIGNATURE;
221*91f16700Schasinglulu 	}
222*91f16700Schasinglulu 
223*91f16700Schasinglulu 	*pk_start = pk_ptr;
224*91f16700Schasinglulu 	*pk_len = len;
225*91f16700Schasinglulu 
226*91f16700Schasinglulu 	return rc;
227*91f16700Schasinglulu }
228*91f16700Schasinglulu 
229*91f16700Schasinglulu /*
230*91f16700Schasinglulu  * Ecdsa-Sig-Value  ::=  SEQUENCE  {
231*91f16700Schasinglulu  *   r     INTEGER,
232*91f16700Schasinglulu  *   s     INTEGER
233*91f16700Schasinglulu  * }
234*91f16700Schasinglulu  *
235*91f16700Schasinglulu  * This helper function that gets a pointer to the encoded ECDSA signature and
236*91f16700Schasinglulu  * its length (as per RFC5280) and returns corresponding decoded signature
237*91f16700Schasinglulu  * (R_S pair) and its size.
238*91f16700Schasinglulu  *
239*91f16700Schasinglulu  * This function returns error(CRYPTO_ERR_SIGNATURE) on ASN.1 parsing failure,
240*91f16700Schasinglulu  * otherwise success(0).
241*91f16700Schasinglulu  **/
242*91f16700Schasinglulu static int get_ecdsa_signature_from_asn1(unsigned char *sig_ptr,
243*91f16700Schasinglulu 					 size_t *sig_len,
244*91f16700Schasinglulu 					 unsigned char *r_s_pair)
245*91f16700Schasinglulu {
246*91f16700Schasinglulu 	int rc;
247*91f16700Schasinglulu 	unsigned char *sig_end;
248*91f16700Schasinglulu 	size_t len, r_len, s_len;
249*91f16700Schasinglulu 
250*91f16700Schasinglulu 	sig_end = sig_ptr + *sig_len;
251*91f16700Schasinglulu 	rc = mbedtls_asn1_get_tag(&sig_ptr, sig_end, &len,
252*91f16700Schasinglulu 				  MBEDTLS_ASN1_CONSTRUCTED |
253*91f16700Schasinglulu 				  MBEDTLS_ASN1_SEQUENCE);
254*91f16700Schasinglulu 	if (rc != 0) {
255*91f16700Schasinglulu 		return CRYPTO_ERR_SIGNATURE;
256*91f16700Schasinglulu 	}
257*91f16700Schasinglulu 
258*91f16700Schasinglulu 	sig_end = sig_ptr + len;
259*91f16700Schasinglulu 	rc = mbedtls_asn1_get_tag(&sig_ptr, sig_end, &r_len,
260*91f16700Schasinglulu 				  MBEDTLS_ASN1_INTEGER);
261*91f16700Schasinglulu 	if (rc != 0) {
262*91f16700Schasinglulu 		return CRYPTO_ERR_SIGNATURE;
263*91f16700Schasinglulu 	}
264*91f16700Schasinglulu 
265*91f16700Schasinglulu 	if (ignore_asn1_int_padding_byte(&sig_ptr, &r_len) != 0) {
266*91f16700Schasinglulu 		return CRYPTO_ERR_SIGNATURE;
267*91f16700Schasinglulu 	}
268*91f16700Schasinglulu 
269*91f16700Schasinglulu 	(void)memcpy((void *)&r_s_pair[0], (const void *)sig_ptr, r_len);
270*91f16700Schasinglulu 
271*91f16700Schasinglulu 	sig_ptr = sig_ptr + r_len;
272*91f16700Schasinglulu 	sig_end = sig_ptr + len - (r_len + (SIZE_OF_ASN1_LEN +
273*91f16700Schasinglulu 		  SIZE_OF_ASN1_TAG));
274*91f16700Schasinglulu 	rc = mbedtls_asn1_get_tag(&sig_ptr, sig_end, &s_len,
275*91f16700Schasinglulu 				  MBEDTLS_ASN1_INTEGER);
276*91f16700Schasinglulu 	if (rc != 0) {
277*91f16700Schasinglulu 		return CRYPTO_ERR_SIGNATURE;
278*91f16700Schasinglulu 	}
279*91f16700Schasinglulu 
280*91f16700Schasinglulu 	if (ignore_asn1_int_padding_byte(&sig_ptr, &s_len) != 0) {
281*91f16700Schasinglulu 		return CRYPTO_ERR_SIGNATURE;
282*91f16700Schasinglulu 	}
283*91f16700Schasinglulu 
284*91f16700Schasinglulu 	(void)memcpy((void *)&r_s_pair[r_len], (const void *)sig_ptr, s_len);
285*91f16700Schasinglulu 
286*91f16700Schasinglulu 	*sig_len = s_len + r_len;
287*91f16700Schasinglulu 
288*91f16700Schasinglulu 	return 0;
289*91f16700Schasinglulu }
290*91f16700Schasinglulu #endif /*
291*91f16700Schasinglulu 	* TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_ECDSA || \
292*91f16700Schasinglulu 	* TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA_AND_ECDSA
293*91f16700Schasinglulu 	**/
294*91f16700Schasinglulu 
295*91f16700Schasinglulu /*
296*91f16700Schasinglulu  * Verify a signature.
297*91f16700Schasinglulu  *
298*91f16700Schasinglulu  * Parameters are passed using the DER encoding format following the ASN.1
299*91f16700Schasinglulu  * structures detailed above.
300*91f16700Schasinglulu  */
301*91f16700Schasinglulu static int verify_signature(void *data_ptr, unsigned int data_len,
302*91f16700Schasinglulu 			    void *sig_ptr, unsigned int sig_len,
303*91f16700Schasinglulu 			    void *sig_alg, unsigned int sig_alg_len,
304*91f16700Schasinglulu 			    void *pk_ptr, unsigned int pk_len)
305*91f16700Schasinglulu {
306*91f16700Schasinglulu 	mbedtls_asn1_buf sig_oid, sig_params;
307*91f16700Schasinglulu 	mbedtls_asn1_buf signature;
308*91f16700Schasinglulu 	mbedtls_md_type_t md_alg;
309*91f16700Schasinglulu 	mbedtls_pk_type_t pk_alg;
310*91f16700Schasinglulu 	int rc;
311*91f16700Schasinglulu 	void *sig_opts = NULL;
312*91f16700Schasinglulu 	unsigned char *p, *end;
313*91f16700Schasinglulu 	unsigned char *local_sig_ptr;
314*91f16700Schasinglulu 	size_t local_sig_len;
315*91f16700Schasinglulu 	psa_ecc_family_t psa_ecc_family = 0U;
316*91f16700Schasinglulu 	__unused unsigned char reformatted_sig[MAX_ECDSA_R_S_PAIR_LEN] = {0};
317*91f16700Schasinglulu 
318*91f16700Schasinglulu 	/* construct PSA key algo and type */
319*91f16700Schasinglulu 	psa_status_t status = PSA_SUCCESS;
320*91f16700Schasinglulu 	psa_key_attributes_t psa_key_attr = PSA_KEY_ATTRIBUTES_INIT;
321*91f16700Schasinglulu 	psa_key_id_t psa_key_id = PSA_KEY_ID_NULL;
322*91f16700Schasinglulu 	psa_key_type_t psa_key_type;
323*91f16700Schasinglulu 	psa_algorithm_t psa_alg;
324*91f16700Schasinglulu 
325*91f16700Schasinglulu 	/* Get pointers to signature OID and parameters */
326*91f16700Schasinglulu 	p = (unsigned char *)sig_alg;
327*91f16700Schasinglulu 	end = (unsigned char *)(p + sig_alg_len);
328*91f16700Schasinglulu 	rc = mbedtls_asn1_get_alg(&p, end, &sig_oid, &sig_params);
329*91f16700Schasinglulu 	if (rc != 0) {
330*91f16700Schasinglulu 		return CRYPTO_ERR_SIGNATURE;
331*91f16700Schasinglulu 	}
332*91f16700Schasinglulu 
333*91f16700Schasinglulu 	/* Get the actual signature algorithm (MD + PK) */
334*91f16700Schasinglulu 	rc = mbedtls_x509_get_sig_alg(&sig_oid, &sig_params, &md_alg, &pk_alg, &sig_opts);
335*91f16700Schasinglulu 	if (rc != 0) {
336*91f16700Schasinglulu 		return CRYPTO_ERR_SIGNATURE;
337*91f16700Schasinglulu 	}
338*91f16700Schasinglulu 
339*91f16700Schasinglulu 	/* Get the signature (bitstring) */
340*91f16700Schasinglulu 	p = (unsigned char *)sig_ptr;
341*91f16700Schasinglulu 	end = (unsigned char *)(p + sig_len);
342*91f16700Schasinglulu 	signature.tag = *p;
343*91f16700Schasinglulu 	rc = mbedtls_asn1_get_bitstring_null(&p, end, &signature.len);
344*91f16700Schasinglulu 	if ((rc != 0) || ((size_t)(end - p) != signature.len)) {
345*91f16700Schasinglulu 		rc = CRYPTO_ERR_SIGNATURE;
346*91f16700Schasinglulu 		goto end2;
347*91f16700Schasinglulu 	}
348*91f16700Schasinglulu 
349*91f16700Schasinglulu 	local_sig_ptr = p;
350*91f16700Schasinglulu 	local_sig_len = signature.len;
351*91f16700Schasinglulu 
352*91f16700Schasinglulu #if TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_ECDSA || \
353*91f16700Schasinglulu TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA_AND_ECDSA
354*91f16700Schasinglulu 	if (pk_alg == MBEDTLS_PK_ECDSA) {
355*91f16700Schasinglulu 		rc = get_ecdsa_signature_from_asn1(local_sig_ptr,
356*91f16700Schasinglulu 						   &local_sig_len,
357*91f16700Schasinglulu 						   reformatted_sig);
358*91f16700Schasinglulu 		if (rc != 0) {
359*91f16700Schasinglulu 			goto end2;
360*91f16700Schasinglulu 		}
361*91f16700Schasinglulu 
362*91f16700Schasinglulu 		local_sig_ptr = reformatted_sig;
363*91f16700Schasinglulu 
364*91f16700Schasinglulu 		rc = get_ecdsa_pkinfo_from_asn1((unsigned char **)&pk_ptr,
365*91f16700Schasinglulu 						&pk_len,
366*91f16700Schasinglulu 						&psa_ecc_family);
367*91f16700Schasinglulu 		if (rc != 0) {
368*91f16700Schasinglulu 			goto end2;
369*91f16700Schasinglulu 		}
370*91f16700Schasinglulu 	}
371*91f16700Schasinglulu #endif /*
372*91f16700Schasinglulu 	* TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_ECDSA || \
373*91f16700Schasinglulu 	* TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA_AND_ECDSA
374*91f16700Schasinglulu 	**/
375*91f16700Schasinglulu 
376*91f16700Schasinglulu 	/* Convert this pk_alg and md_alg to PSA key type and key algorithm */
377*91f16700Schasinglulu 	construct_psa_key_alg_and_type(pk_alg, md_alg, psa_ecc_family,
378*91f16700Schasinglulu 				       &psa_alg, &psa_key_type);
379*91f16700Schasinglulu 
380*91f16700Schasinglulu 
381*91f16700Schasinglulu 	if ((psa_alg == PSA_ALG_NONE) || (psa_key_type == PSA_KEY_TYPE_NONE)) {
382*91f16700Schasinglulu 		rc = CRYPTO_ERR_SIGNATURE;
383*91f16700Schasinglulu 		goto end2;
384*91f16700Schasinglulu 	}
385*91f16700Schasinglulu 
386*91f16700Schasinglulu 	/* filled-in key_attributes */
387*91f16700Schasinglulu 	psa_set_key_algorithm(&psa_key_attr, psa_alg);
388*91f16700Schasinglulu 	psa_set_key_type(&psa_key_attr, psa_key_type);
389*91f16700Schasinglulu 	psa_set_key_usage_flags(&psa_key_attr, PSA_KEY_USAGE_VERIFY_MESSAGE);
390*91f16700Schasinglulu 
391*91f16700Schasinglulu 	/* Get the key_id using import API */
392*91f16700Schasinglulu 	status = psa_import_key(&psa_key_attr,
393*91f16700Schasinglulu 				pk_ptr,
394*91f16700Schasinglulu 				(size_t)pk_len,
395*91f16700Schasinglulu 				&psa_key_id);
396*91f16700Schasinglulu 
397*91f16700Schasinglulu 	if (status != PSA_SUCCESS) {
398*91f16700Schasinglulu 		rc = CRYPTO_ERR_SIGNATURE;
399*91f16700Schasinglulu 		goto end2;
400*91f16700Schasinglulu 	}
401*91f16700Schasinglulu 
402*91f16700Schasinglulu 	/*
403*91f16700Schasinglulu 	 * Hash calculation and Signature verification of the given data payload
404*91f16700Schasinglulu 	 * is wrapped under the psa_verify_message function.
405*91f16700Schasinglulu 	 */
406*91f16700Schasinglulu 	status = psa_verify_message(psa_key_id, psa_alg,
407*91f16700Schasinglulu 				    data_ptr, data_len,
408*91f16700Schasinglulu 				    local_sig_ptr, local_sig_len);
409*91f16700Schasinglulu 
410*91f16700Schasinglulu 	if (status != PSA_SUCCESS) {
411*91f16700Schasinglulu 		rc = CRYPTO_ERR_SIGNATURE;
412*91f16700Schasinglulu 		goto end1;
413*91f16700Schasinglulu 	}
414*91f16700Schasinglulu 
415*91f16700Schasinglulu 	/* Signature verification success */
416*91f16700Schasinglulu 	rc = CRYPTO_SUCCESS;
417*91f16700Schasinglulu 
418*91f16700Schasinglulu end1:
419*91f16700Schasinglulu 	/*
420*91f16700Schasinglulu 	 * Destroy the key if it is created successfully
421*91f16700Schasinglulu 	 */
422*91f16700Schasinglulu 	psa_destroy_key(psa_key_id);
423*91f16700Schasinglulu end2:
424*91f16700Schasinglulu 	mbedtls_free(sig_opts);
425*91f16700Schasinglulu 	return rc;
426*91f16700Schasinglulu }
427*91f16700Schasinglulu 
428*91f16700Schasinglulu /*
429*91f16700Schasinglulu  * Match a hash
430*91f16700Schasinglulu  *
431*91f16700Schasinglulu  * Digest info is passed in DER format following the ASN.1 structure detailed
432*91f16700Schasinglulu  * above.
433*91f16700Schasinglulu  */
434*91f16700Schasinglulu static int verify_hash(void *data_ptr, unsigned int data_len,
435*91f16700Schasinglulu 		       void *digest_info_ptr, unsigned int digest_info_len)
436*91f16700Schasinglulu {
437*91f16700Schasinglulu 	mbedtls_asn1_buf hash_oid, params;
438*91f16700Schasinglulu 	mbedtls_md_type_t md_alg;
439*91f16700Schasinglulu 	unsigned char *p, *end, *hash;
440*91f16700Schasinglulu 	size_t len;
441*91f16700Schasinglulu 	int rc;
442*91f16700Schasinglulu 	psa_status_t status;
443*91f16700Schasinglulu 	psa_algorithm_t psa_md_alg;
444*91f16700Schasinglulu 
445*91f16700Schasinglulu 	/*
446*91f16700Schasinglulu 	 * Digest info should be an MBEDTLS_ASN1_SEQUENCE, but padding after
447*91f16700Schasinglulu 	 * it is allowed.  This is necessary to support multiple hash
448*91f16700Schasinglulu 	 * algorithms.
449*91f16700Schasinglulu 	 */
450*91f16700Schasinglulu 	p = (unsigned char *)digest_info_ptr;
451*91f16700Schasinglulu 	end = p + digest_info_len;
452*91f16700Schasinglulu 	rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
453*91f16700Schasinglulu 				  MBEDTLS_ASN1_SEQUENCE);
454*91f16700Schasinglulu 	if (rc != 0) {
455*91f16700Schasinglulu 		return CRYPTO_ERR_HASH;
456*91f16700Schasinglulu 	}
457*91f16700Schasinglulu 
458*91f16700Schasinglulu 	end = p + len;
459*91f16700Schasinglulu 
460*91f16700Schasinglulu 	/* Get the hash algorithm */
461*91f16700Schasinglulu 	rc = mbedtls_asn1_get_alg(&p, end, &hash_oid, &params);
462*91f16700Schasinglulu 	if (rc != 0) {
463*91f16700Schasinglulu 		return CRYPTO_ERR_HASH;
464*91f16700Schasinglulu 	}
465*91f16700Schasinglulu 
466*91f16700Schasinglulu 	/* Hash should be octet string type and consume all bytes */
467*91f16700Schasinglulu 	rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING);
468*91f16700Schasinglulu 	if ((rc != 0) || ((size_t)(end - p) != len)) {
469*91f16700Schasinglulu 		return CRYPTO_ERR_HASH;
470*91f16700Schasinglulu 	}
471*91f16700Schasinglulu 	hash = p;
472*91f16700Schasinglulu 
473*91f16700Schasinglulu 	rc = mbedtls_oid_get_md_alg(&hash_oid, &md_alg);
474*91f16700Schasinglulu 	if (rc != 0) {
475*91f16700Schasinglulu 		return CRYPTO_ERR_HASH;
476*91f16700Schasinglulu 	}
477*91f16700Schasinglulu 
478*91f16700Schasinglulu 	/* convert the md_alg to psa_algo */
479*91f16700Schasinglulu 	psa_md_alg = mbedtls_md_psa_alg_from_type(md_alg);
480*91f16700Schasinglulu 
481*91f16700Schasinglulu 	/* Length of hash must match the algorithm's size */
482*91f16700Schasinglulu 	if (len != PSA_HASH_LENGTH(psa_md_alg)) {
483*91f16700Schasinglulu 		return CRYPTO_ERR_HASH;
484*91f16700Schasinglulu 	}
485*91f16700Schasinglulu 
486*91f16700Schasinglulu 	/*
487*91f16700Schasinglulu 	 * Calculate Hash and compare it against the retrieved hash from
488*91f16700Schasinglulu 	 * the certificate (one shot API).
489*91f16700Schasinglulu 	 */
490*91f16700Schasinglulu 	status = psa_hash_compare(psa_md_alg,
491*91f16700Schasinglulu 				  data_ptr, (size_t)data_len,
492*91f16700Schasinglulu 				  (const uint8_t *)hash, len);
493*91f16700Schasinglulu 
494*91f16700Schasinglulu 	if (status != PSA_SUCCESS) {
495*91f16700Schasinglulu 		return CRYPTO_ERR_HASH;
496*91f16700Schasinglulu 	}
497*91f16700Schasinglulu 
498*91f16700Schasinglulu 	return CRYPTO_SUCCESS;
499*91f16700Schasinglulu }
500*91f16700Schasinglulu #endif /*
501*91f16700Schasinglulu 	* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \
502*91f16700Schasinglulu 	* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
503*91f16700Schasinglulu 	*/
504*91f16700Schasinglulu 
505*91f16700Schasinglulu #if CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \
506*91f16700Schasinglulu CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
507*91f16700Schasinglulu /*
508*91f16700Schasinglulu  * Map a generic crypto message digest algorithm to the corresponding macro used
509*91f16700Schasinglulu  * by Mbed TLS.
510*91f16700Schasinglulu  */
511*91f16700Schasinglulu static inline mbedtls_md_type_t md_type(enum crypto_md_algo algo)
512*91f16700Schasinglulu {
513*91f16700Schasinglulu 	switch (algo) {
514*91f16700Schasinglulu 	case CRYPTO_MD_SHA512:
515*91f16700Schasinglulu 		return MBEDTLS_MD_SHA512;
516*91f16700Schasinglulu 	case CRYPTO_MD_SHA384:
517*91f16700Schasinglulu 		return MBEDTLS_MD_SHA384;
518*91f16700Schasinglulu 	case CRYPTO_MD_SHA256:
519*91f16700Schasinglulu 		return MBEDTLS_MD_SHA256;
520*91f16700Schasinglulu 	default:
521*91f16700Schasinglulu 		/* Invalid hash algorithm. */
522*91f16700Schasinglulu 		return MBEDTLS_MD_NONE;
523*91f16700Schasinglulu 	}
524*91f16700Schasinglulu }
525*91f16700Schasinglulu 
526*91f16700Schasinglulu /*
527*91f16700Schasinglulu  * Calculate a hash
528*91f16700Schasinglulu  *
529*91f16700Schasinglulu  * output points to the computed hash
530*91f16700Schasinglulu  */
531*91f16700Schasinglulu static int calc_hash(enum crypto_md_algo md_algo, void *data_ptr,
532*91f16700Schasinglulu 		     unsigned int data_len,
533*91f16700Schasinglulu 		     unsigned char output[CRYPTO_MD_MAX_SIZE])
534*91f16700Schasinglulu {
535*91f16700Schasinglulu 	size_t hash_length;
536*91f16700Schasinglulu 	psa_status_t status;
537*91f16700Schasinglulu 	psa_algorithm_t psa_md_alg;
538*91f16700Schasinglulu 
539*91f16700Schasinglulu 	/* convert the md_alg to psa_algo */
540*91f16700Schasinglulu 	psa_md_alg = mbedtls_md_psa_alg_from_type(md_type(md_algo));
541*91f16700Schasinglulu 
542*91f16700Schasinglulu 	/*
543*91f16700Schasinglulu 	 * Calculate the hash of the data, it is safe to pass the
544*91f16700Schasinglulu 	 * 'output' hash buffer pointer considering its size is always
545*91f16700Schasinglulu 	 * bigger than or equal to MBEDTLS_MD_MAX_SIZE.
546*91f16700Schasinglulu 	 */
547*91f16700Schasinglulu 	status = psa_hash_compute(psa_md_alg, data_ptr, (size_t)data_len,
548*91f16700Schasinglulu 				  (uint8_t *)output, CRYPTO_MD_MAX_SIZE,
549*91f16700Schasinglulu 				  &hash_length);
550*91f16700Schasinglulu 	if (status != PSA_SUCCESS) {
551*91f16700Schasinglulu 		return CRYPTO_ERR_HASH;
552*91f16700Schasinglulu 	}
553*91f16700Schasinglulu 
554*91f16700Schasinglulu 	return CRYPTO_SUCCESS;
555*91f16700Schasinglulu }
556*91f16700Schasinglulu #endif /*
557*91f16700Schasinglulu 	* CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \
558*91f16700Schasinglulu 	* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
559*91f16700Schasinglulu 	*/
560*91f16700Schasinglulu 
561*91f16700Schasinglulu #if TF_MBEDTLS_USE_AES_GCM
562*91f16700Schasinglulu /*
563*91f16700Schasinglulu  * Stack based buffer allocation for decryption operation. It could
564*91f16700Schasinglulu  * be configured to balance stack usage vs execution speed.
565*91f16700Schasinglulu  */
566*91f16700Schasinglulu #define DEC_OP_BUF_SIZE		128
567*91f16700Schasinglulu 
568*91f16700Schasinglulu static int aes_gcm_decrypt(void *data_ptr, size_t len, const void *key,
569*91f16700Schasinglulu 			   unsigned int key_len, const void *iv,
570*91f16700Schasinglulu 			   unsigned int iv_len, const void *tag,
571*91f16700Schasinglulu 			   unsigned int tag_len)
572*91f16700Schasinglulu {
573*91f16700Schasinglulu 	mbedtls_gcm_context ctx;
574*91f16700Schasinglulu 	mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
575*91f16700Schasinglulu 	unsigned char buf[DEC_OP_BUF_SIZE];
576*91f16700Schasinglulu 	unsigned char tag_buf[CRYPTO_MAX_TAG_SIZE];
577*91f16700Schasinglulu 	unsigned char *pt = data_ptr;
578*91f16700Schasinglulu 	size_t dec_len;
579*91f16700Schasinglulu 	int diff, i, rc;
580*91f16700Schasinglulu 	size_t output_length __unused;
581*91f16700Schasinglulu 
582*91f16700Schasinglulu 	mbedtls_gcm_init(&ctx);
583*91f16700Schasinglulu 
584*91f16700Schasinglulu 	rc = mbedtls_gcm_setkey(&ctx, cipher, key, key_len * 8);
585*91f16700Schasinglulu 	if (rc != 0) {
586*91f16700Schasinglulu 		rc = CRYPTO_ERR_DECRYPTION;
587*91f16700Schasinglulu 		goto exit_gcm;
588*91f16700Schasinglulu 	}
589*91f16700Schasinglulu 
590*91f16700Schasinglulu #if (MBEDTLS_VERSION_MAJOR < 3)
591*91f16700Schasinglulu 	rc = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT, iv, iv_len, NULL, 0);
592*91f16700Schasinglulu #else
593*91f16700Schasinglulu 	rc = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT, iv, iv_len);
594*91f16700Schasinglulu #endif
595*91f16700Schasinglulu 	if (rc != 0) {
596*91f16700Schasinglulu 		rc = CRYPTO_ERR_DECRYPTION;
597*91f16700Schasinglulu 		goto exit_gcm;
598*91f16700Schasinglulu 	}
599*91f16700Schasinglulu 
600*91f16700Schasinglulu 	while (len > 0) {
601*91f16700Schasinglulu 		dec_len = MIN(sizeof(buf), len);
602*91f16700Schasinglulu 
603*91f16700Schasinglulu #if (MBEDTLS_VERSION_MAJOR < 3)
604*91f16700Schasinglulu 		rc = mbedtls_gcm_update(&ctx, dec_len, pt, buf);
605*91f16700Schasinglulu #else
606*91f16700Schasinglulu 		rc = mbedtls_gcm_update(&ctx, pt, dec_len, buf, sizeof(buf), &output_length);
607*91f16700Schasinglulu #endif
608*91f16700Schasinglulu 
609*91f16700Schasinglulu 		if (rc != 0) {
610*91f16700Schasinglulu 			rc = CRYPTO_ERR_DECRYPTION;
611*91f16700Schasinglulu 			goto exit_gcm;
612*91f16700Schasinglulu 		}
613*91f16700Schasinglulu 
614*91f16700Schasinglulu 		memcpy(pt, buf, dec_len);
615*91f16700Schasinglulu 		pt += dec_len;
616*91f16700Schasinglulu 		len -= dec_len;
617*91f16700Schasinglulu 	}
618*91f16700Schasinglulu 
619*91f16700Schasinglulu #if (MBEDTLS_VERSION_MAJOR < 3)
620*91f16700Schasinglulu 	rc = mbedtls_gcm_finish(&ctx, tag_buf, sizeof(tag_buf));
621*91f16700Schasinglulu #else
622*91f16700Schasinglulu 	rc = mbedtls_gcm_finish(&ctx, NULL, 0, &output_length, tag_buf, sizeof(tag_buf));
623*91f16700Schasinglulu #endif
624*91f16700Schasinglulu 
625*91f16700Schasinglulu 	if (rc != 0) {
626*91f16700Schasinglulu 		rc = CRYPTO_ERR_DECRYPTION;
627*91f16700Schasinglulu 		goto exit_gcm;
628*91f16700Schasinglulu 	}
629*91f16700Schasinglulu 
630*91f16700Schasinglulu 	/* Check tag in "constant-time" */
631*91f16700Schasinglulu 	for (diff = 0, i = 0; i < tag_len; i++)
632*91f16700Schasinglulu 		diff |= ((const unsigned char *)tag)[i] ^ tag_buf[i];
633*91f16700Schasinglulu 
634*91f16700Schasinglulu 	if (diff != 0) {
635*91f16700Schasinglulu 		rc = CRYPTO_ERR_DECRYPTION;
636*91f16700Schasinglulu 		goto exit_gcm;
637*91f16700Schasinglulu 	}
638*91f16700Schasinglulu 
639*91f16700Schasinglulu 	/* GCM decryption success */
640*91f16700Schasinglulu 	rc = CRYPTO_SUCCESS;
641*91f16700Schasinglulu 
642*91f16700Schasinglulu exit_gcm:
643*91f16700Schasinglulu 	mbedtls_gcm_free(&ctx);
644*91f16700Schasinglulu 	return rc;
645*91f16700Schasinglulu }
646*91f16700Schasinglulu 
647*91f16700Schasinglulu /*
648*91f16700Schasinglulu  * Authenticated decryption of an image
649*91f16700Schasinglulu  */
650*91f16700Schasinglulu static int auth_decrypt(enum crypto_dec_algo dec_algo, void *data_ptr,
651*91f16700Schasinglulu 			size_t len, const void *key, unsigned int key_len,
652*91f16700Schasinglulu 			unsigned int key_flags, const void *iv,
653*91f16700Schasinglulu 			unsigned int iv_len, const void *tag,
654*91f16700Schasinglulu 			unsigned int tag_len)
655*91f16700Schasinglulu {
656*91f16700Schasinglulu 	int rc;
657*91f16700Schasinglulu 
658*91f16700Schasinglulu 	assert((key_flags & ENC_KEY_IS_IDENTIFIER) == 0);
659*91f16700Schasinglulu 
660*91f16700Schasinglulu 	switch (dec_algo) {
661*91f16700Schasinglulu 	case CRYPTO_GCM_DECRYPT:
662*91f16700Schasinglulu 		rc = aes_gcm_decrypt(data_ptr, len, key, key_len, iv, iv_len,
663*91f16700Schasinglulu 				     tag, tag_len);
664*91f16700Schasinglulu 		if (rc != 0)
665*91f16700Schasinglulu 			return rc;
666*91f16700Schasinglulu 		break;
667*91f16700Schasinglulu 	default:
668*91f16700Schasinglulu 		return CRYPTO_ERR_DECRYPTION;
669*91f16700Schasinglulu 	}
670*91f16700Schasinglulu 
671*91f16700Schasinglulu 	return CRYPTO_SUCCESS;
672*91f16700Schasinglulu }
673*91f16700Schasinglulu #endif /* TF_MBEDTLS_USE_AES_GCM */
674*91f16700Schasinglulu 
675*91f16700Schasinglulu /*
676*91f16700Schasinglulu  * Register crypto library descriptor
677*91f16700Schasinglulu  */
678*91f16700Schasinglulu #if CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
679*91f16700Schasinglulu #if TF_MBEDTLS_USE_AES_GCM
680*91f16700Schasinglulu REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash,
681*91f16700Schasinglulu 		    auth_decrypt, NULL);
682*91f16700Schasinglulu #else
683*91f16700Schasinglulu REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash,
684*91f16700Schasinglulu 		    NULL, NULL);
685*91f16700Schasinglulu #endif
686*91f16700Schasinglulu #elif CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY
687*91f16700Schasinglulu #if TF_MBEDTLS_USE_AES_GCM
688*91f16700Schasinglulu REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL,
689*91f16700Schasinglulu 		    auth_decrypt, NULL);
690*91f16700Schasinglulu #else
691*91f16700Schasinglulu REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL,
692*91f16700Schasinglulu 		    NULL, NULL);
693*91f16700Schasinglulu #endif
694*91f16700Schasinglulu #elif CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY
695*91f16700Schasinglulu REGISTER_CRYPTO_LIB(LIB_NAME, init, NULL, NULL, calc_hash, NULL, NULL);
696*91f16700Schasinglulu #endif /* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */
697