xref: /rk3399_ARM-atf/drivers/auth/mbedtls/mbedtls_psa_crypto.c (revision 38f893692ad9b8edb5413f4b2b9cd15a9b485685)
1*38f89369SManish V Badarkhe /*
2*38f89369SManish V Badarkhe  * Copyright (c) 2023, Arm Limited. All rights reserved.
3*38f89369SManish V Badarkhe  *
4*38f89369SManish V Badarkhe  * SPDX-License-Identifier: BSD-3-Clause
5*38f89369SManish V Badarkhe  */
6*38f89369SManish V Badarkhe 
7*38f89369SManish V Badarkhe #include <assert.h>
8*38f89369SManish V Badarkhe #include <stddef.h>
9*38f89369SManish V Badarkhe #include <string.h>
10*38f89369SManish V Badarkhe 
11*38f89369SManish V Badarkhe /* mbed TLS headers */
12*38f89369SManish V Badarkhe #include <mbedtls/gcm.h>
13*38f89369SManish V Badarkhe #include <mbedtls/md.h>
14*38f89369SManish V Badarkhe #include <mbedtls/memory_buffer_alloc.h>
15*38f89369SManish V Badarkhe #include <mbedtls/oid.h>
16*38f89369SManish V Badarkhe #include <mbedtls/platform.h>
17*38f89369SManish V Badarkhe #include <mbedtls/version.h>
18*38f89369SManish V Badarkhe #include <mbedtls/x509.h>
19*38f89369SManish V Badarkhe 
20*38f89369SManish V Badarkhe #include <common/debug.h>
21*38f89369SManish V Badarkhe #include <drivers/auth/crypto_mod.h>
22*38f89369SManish V Badarkhe #include <drivers/auth/mbedtls/mbedtls_common.h>
23*38f89369SManish V Badarkhe 
24*38f89369SManish V Badarkhe #include <plat/common/platform.h>
25*38f89369SManish V Badarkhe 
26*38f89369SManish V Badarkhe #define LIB_NAME		"mbed TLS PSA"
27*38f89369SManish V Badarkhe 
28*38f89369SManish V Badarkhe #if CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \
29*38f89369SManish V Badarkhe CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
30*38f89369SManish V Badarkhe /*
31*38f89369SManish V Badarkhe  * CRYPTO_MD_MAX_SIZE value is as per current stronger algorithm available
32*38f89369SManish V Badarkhe  * so make sure that mbed TLS MD maximum size must be lesser than this.
33*38f89369SManish V Badarkhe  */
34*38f89369SManish V Badarkhe CASSERT(CRYPTO_MD_MAX_SIZE >= MBEDTLS_MD_MAX_SIZE,
35*38f89369SManish V Badarkhe 	assert_mbedtls_md_size_overflow);
36*38f89369SManish V Badarkhe 
37*38f89369SManish V Badarkhe #endif /*
38*38f89369SManish V Badarkhe 	* CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \
39*38f89369SManish V Badarkhe 	* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
40*38f89369SManish V Badarkhe 	*/
41*38f89369SManish V Badarkhe 
42*38f89369SManish V Badarkhe /*
43*38f89369SManish V Badarkhe  * AlgorithmIdentifier  ::=  SEQUENCE  {
44*38f89369SManish V Badarkhe  *     algorithm               OBJECT IDENTIFIER,
45*38f89369SManish V Badarkhe  *     parameters              ANY DEFINED BY algorithm OPTIONAL
46*38f89369SManish V Badarkhe  * }
47*38f89369SManish V Badarkhe  *
48*38f89369SManish V Badarkhe  * SubjectPublicKeyInfo  ::=  SEQUENCE  {
49*38f89369SManish V Badarkhe  *     algorithm            AlgorithmIdentifier,
50*38f89369SManish V Badarkhe  *     subjectPublicKey     BIT STRING
51*38f89369SManish V Badarkhe  * }
52*38f89369SManish V Badarkhe  *
53*38f89369SManish V Badarkhe  * DigestInfo ::= SEQUENCE {
54*38f89369SManish V Badarkhe  *     digestAlgorithm AlgorithmIdentifier,
55*38f89369SManish V Badarkhe  *     digest OCTET STRING
56*38f89369SManish V Badarkhe  * }
57*38f89369SManish V Badarkhe  */
58*38f89369SManish V Badarkhe 
59*38f89369SManish V Badarkhe /*
60*38f89369SManish V Badarkhe  * Initialize the library and export the descriptor
61*38f89369SManish V Badarkhe  */
62*38f89369SManish V Badarkhe static void init(void)
63*38f89369SManish V Badarkhe {
64*38f89369SManish V Badarkhe 	/* Initialize mbed TLS */
65*38f89369SManish V Badarkhe 	mbedtls_init();
66*38f89369SManish V Badarkhe }
67*38f89369SManish V Badarkhe 
68*38f89369SManish V Badarkhe #if CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \
69*38f89369SManish V Badarkhe CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
70*38f89369SManish V Badarkhe /*
71*38f89369SManish V Badarkhe  * Verify a signature.
72*38f89369SManish V Badarkhe  *
73*38f89369SManish V Badarkhe  * Parameters are passed using the DER encoding format following the ASN.1
74*38f89369SManish V Badarkhe  * structures detailed above.
75*38f89369SManish V Badarkhe  */
76*38f89369SManish V Badarkhe static int verify_signature(void *data_ptr, unsigned int data_len,
77*38f89369SManish V Badarkhe 			    void *sig_ptr, unsigned int sig_len,
78*38f89369SManish V Badarkhe 			    void *sig_alg, unsigned int sig_alg_len,
79*38f89369SManish V Badarkhe 			    void *pk_ptr, unsigned int pk_len)
80*38f89369SManish V Badarkhe {
81*38f89369SManish V Badarkhe 	mbedtls_asn1_buf sig_oid, sig_params;
82*38f89369SManish V Badarkhe 	mbedtls_asn1_buf signature;
83*38f89369SManish V Badarkhe 	mbedtls_md_type_t md_alg;
84*38f89369SManish V Badarkhe 	mbedtls_pk_type_t pk_alg;
85*38f89369SManish V Badarkhe 	mbedtls_pk_context pk = {0};
86*38f89369SManish V Badarkhe 	int rc;
87*38f89369SManish V Badarkhe 	void *sig_opts = NULL;
88*38f89369SManish V Badarkhe 	const mbedtls_md_info_t *md_info;
89*38f89369SManish V Badarkhe 	unsigned char *p, *end;
90*38f89369SManish V Badarkhe 	unsigned char hash[MBEDTLS_MD_MAX_SIZE];
91*38f89369SManish V Badarkhe 
92*38f89369SManish V Badarkhe 	/* Get pointers to signature OID and parameters */
93*38f89369SManish V Badarkhe 	p = (unsigned char *)sig_alg;
94*38f89369SManish V Badarkhe 	end = (unsigned char *)(p + sig_alg_len);
95*38f89369SManish V Badarkhe 	rc = mbedtls_asn1_get_alg(&p, end, &sig_oid, &sig_params);
96*38f89369SManish V Badarkhe 	if (rc != 0) {
97*38f89369SManish V Badarkhe 		return CRYPTO_ERR_SIGNATURE;
98*38f89369SManish V Badarkhe 	}
99*38f89369SManish V Badarkhe 
100*38f89369SManish V Badarkhe 	/* Get the actual signature algorithm (MD + PK) */
101*38f89369SManish V Badarkhe 	rc = mbedtls_x509_get_sig_alg(&sig_oid, &sig_params, &md_alg, &pk_alg, &sig_opts);
102*38f89369SManish V Badarkhe 	if (rc != 0) {
103*38f89369SManish V Badarkhe 		return CRYPTO_ERR_SIGNATURE;
104*38f89369SManish V Badarkhe 	}
105*38f89369SManish V Badarkhe 
106*38f89369SManish V Badarkhe 	/* Parse the public key */
107*38f89369SManish V Badarkhe 	mbedtls_pk_init(&pk);
108*38f89369SManish V Badarkhe 	p = (unsigned char *)pk_ptr;
109*38f89369SManish V Badarkhe 	end = (unsigned char *)(p + pk_len);
110*38f89369SManish V Badarkhe 	rc = mbedtls_pk_parse_subpubkey(&p, end, &pk);
111*38f89369SManish V Badarkhe 	if (rc != 0) {
112*38f89369SManish V Badarkhe 		rc = CRYPTO_ERR_SIGNATURE;
113*38f89369SManish V Badarkhe 		goto end2;
114*38f89369SManish V Badarkhe 	}
115*38f89369SManish V Badarkhe 
116*38f89369SManish V Badarkhe 	/* Get the signature (bitstring) */
117*38f89369SManish V Badarkhe 	p = (unsigned char *)sig_ptr;
118*38f89369SManish V Badarkhe 	end = (unsigned char *)(p + sig_len);
119*38f89369SManish V Badarkhe 	signature.tag = *p;
120*38f89369SManish V Badarkhe 	rc = mbedtls_asn1_get_bitstring_null(&p, end, &signature.len);
121*38f89369SManish V Badarkhe 	if ((rc != 0) || ((size_t)(end - p) != signature.len)) {
122*38f89369SManish V Badarkhe 		rc = CRYPTO_ERR_SIGNATURE;
123*38f89369SManish V Badarkhe 		goto end1;
124*38f89369SManish V Badarkhe 	}
125*38f89369SManish V Badarkhe 	signature.p = p;
126*38f89369SManish V Badarkhe 
127*38f89369SManish V Badarkhe 	/* Calculate the hash of the data */
128*38f89369SManish V Badarkhe 	md_info = mbedtls_md_info_from_type(md_alg);
129*38f89369SManish V Badarkhe 	if (md_info == NULL) {
130*38f89369SManish V Badarkhe 		rc = CRYPTO_ERR_SIGNATURE;
131*38f89369SManish V Badarkhe 		goto end1;
132*38f89369SManish V Badarkhe 	}
133*38f89369SManish V Badarkhe 	p = (unsigned char *)data_ptr;
134*38f89369SManish V Badarkhe 	rc = mbedtls_md(md_info, p, data_len, hash);
135*38f89369SManish V Badarkhe 	if (rc != 0) {
136*38f89369SManish V Badarkhe 		rc = CRYPTO_ERR_SIGNATURE;
137*38f89369SManish V Badarkhe 		goto end1;
138*38f89369SManish V Badarkhe 	}
139*38f89369SManish V Badarkhe 
140*38f89369SManish V Badarkhe 	/* Verify the signature */
141*38f89369SManish V Badarkhe 	rc = mbedtls_pk_verify_ext(pk_alg, sig_opts, &pk, md_alg, hash,
142*38f89369SManish V Badarkhe 			mbedtls_md_get_size(md_info),
143*38f89369SManish V Badarkhe 			signature.p, signature.len);
144*38f89369SManish V Badarkhe 	if (rc != 0) {
145*38f89369SManish V Badarkhe 		rc = CRYPTO_ERR_SIGNATURE;
146*38f89369SManish V Badarkhe 		goto end1;
147*38f89369SManish V Badarkhe 	}
148*38f89369SManish V Badarkhe 
149*38f89369SManish V Badarkhe 	/* Signature verification success */
150*38f89369SManish V Badarkhe 	rc = CRYPTO_SUCCESS;
151*38f89369SManish V Badarkhe 
152*38f89369SManish V Badarkhe end1:
153*38f89369SManish V Badarkhe 	mbedtls_pk_free(&pk);
154*38f89369SManish V Badarkhe end2:
155*38f89369SManish V Badarkhe 	mbedtls_free(sig_opts);
156*38f89369SManish V Badarkhe 	return rc;
157*38f89369SManish V Badarkhe }
158*38f89369SManish V Badarkhe 
159*38f89369SManish V Badarkhe /*
160*38f89369SManish V Badarkhe  * Match a hash
161*38f89369SManish V Badarkhe  *
162*38f89369SManish V Badarkhe  * Digest info is passed in DER format following the ASN.1 structure detailed
163*38f89369SManish V Badarkhe  * above.
164*38f89369SManish V Badarkhe  */
165*38f89369SManish V Badarkhe static int verify_hash(void *data_ptr, unsigned int data_len,
166*38f89369SManish V Badarkhe 		       void *digest_info_ptr, unsigned int digest_info_len)
167*38f89369SManish V Badarkhe {
168*38f89369SManish V Badarkhe 	mbedtls_asn1_buf hash_oid, params;
169*38f89369SManish V Badarkhe 	mbedtls_md_type_t md_alg;
170*38f89369SManish V Badarkhe 	const mbedtls_md_info_t *md_info;
171*38f89369SManish V Badarkhe 	unsigned char *p, *end, *hash;
172*38f89369SManish V Badarkhe 	unsigned char data_hash[MBEDTLS_MD_MAX_SIZE];
173*38f89369SManish V Badarkhe 	size_t len;
174*38f89369SManish V Badarkhe 	int rc;
175*38f89369SManish V Badarkhe 
176*38f89369SManish V Badarkhe 	/*
177*38f89369SManish V Badarkhe 	 * Digest info should be an MBEDTLS_ASN1_SEQUENCE, but padding after
178*38f89369SManish V Badarkhe 	 * it is allowed.  This is necessary to support multiple hash
179*38f89369SManish V Badarkhe 	 * algorithms.
180*38f89369SManish V Badarkhe 	 */
181*38f89369SManish V Badarkhe 	p = (unsigned char *)digest_info_ptr;
182*38f89369SManish V Badarkhe 	end = p + digest_info_len;
183*38f89369SManish V Badarkhe 	rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
184*38f89369SManish V Badarkhe 				  MBEDTLS_ASN1_SEQUENCE);
185*38f89369SManish V Badarkhe 	if (rc != 0) {
186*38f89369SManish V Badarkhe 		return CRYPTO_ERR_HASH;
187*38f89369SManish V Badarkhe 	}
188*38f89369SManish V Badarkhe 
189*38f89369SManish V Badarkhe 	end = p + len;
190*38f89369SManish V Badarkhe 
191*38f89369SManish V Badarkhe 	/* Get the hash algorithm */
192*38f89369SManish V Badarkhe 	rc = mbedtls_asn1_get_alg(&p, end, &hash_oid, &params);
193*38f89369SManish V Badarkhe 	if (rc != 0) {
194*38f89369SManish V Badarkhe 		return CRYPTO_ERR_HASH;
195*38f89369SManish V Badarkhe 	}
196*38f89369SManish V Badarkhe 
197*38f89369SManish V Badarkhe 	rc = mbedtls_oid_get_md_alg(&hash_oid, &md_alg);
198*38f89369SManish V Badarkhe 	if (rc != 0) {
199*38f89369SManish V Badarkhe 		return CRYPTO_ERR_HASH;
200*38f89369SManish V Badarkhe 	}
201*38f89369SManish V Badarkhe 
202*38f89369SManish V Badarkhe 	md_info = mbedtls_md_info_from_type(md_alg);
203*38f89369SManish V Badarkhe 	if (md_info == NULL) {
204*38f89369SManish V Badarkhe 		return CRYPTO_ERR_HASH;
205*38f89369SManish V Badarkhe 	}
206*38f89369SManish V Badarkhe 
207*38f89369SManish V Badarkhe 	/* Hash should be octet string type and consume all bytes */
208*38f89369SManish V Badarkhe 	rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING);
209*38f89369SManish V Badarkhe 	if ((rc != 0) || ((size_t)(end - p) != len)) {
210*38f89369SManish V Badarkhe 		return CRYPTO_ERR_HASH;
211*38f89369SManish V Badarkhe 	}
212*38f89369SManish V Badarkhe 
213*38f89369SManish V Badarkhe 	/* Length of hash must match the algorithm's size */
214*38f89369SManish V Badarkhe 	if (len != mbedtls_md_get_size(md_info)) {
215*38f89369SManish V Badarkhe 		return CRYPTO_ERR_HASH;
216*38f89369SManish V Badarkhe 	}
217*38f89369SManish V Badarkhe 	hash = p;
218*38f89369SManish V Badarkhe 
219*38f89369SManish V Badarkhe 	/* Calculate the hash of the data */
220*38f89369SManish V Badarkhe 	p = (unsigned char *)data_ptr;
221*38f89369SManish V Badarkhe 	rc = mbedtls_md(md_info, p, data_len, data_hash);
222*38f89369SManish V Badarkhe 	if (rc != 0) {
223*38f89369SManish V Badarkhe 		return CRYPTO_ERR_HASH;
224*38f89369SManish V Badarkhe 	}
225*38f89369SManish V Badarkhe 
226*38f89369SManish V Badarkhe 	/* Compare values */
227*38f89369SManish V Badarkhe 	rc = memcmp(data_hash, hash, mbedtls_md_get_size(md_info));
228*38f89369SManish V Badarkhe 	if (rc != 0) {
229*38f89369SManish V Badarkhe 		return CRYPTO_ERR_HASH;
230*38f89369SManish V Badarkhe 	}
231*38f89369SManish V Badarkhe 
232*38f89369SManish V Badarkhe 	return CRYPTO_SUCCESS;
233*38f89369SManish V Badarkhe }
234*38f89369SManish V Badarkhe #endif /*
235*38f89369SManish V Badarkhe 	* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \
236*38f89369SManish V Badarkhe 	* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
237*38f89369SManish V Badarkhe 	*/
238*38f89369SManish V Badarkhe 
239*38f89369SManish V Badarkhe #if CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \
240*38f89369SManish V Badarkhe CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
241*38f89369SManish V Badarkhe /*
242*38f89369SManish V Badarkhe  * Map a generic crypto message digest algorithm to the corresponding macro used
243*38f89369SManish V Badarkhe  * by Mbed TLS.
244*38f89369SManish V Badarkhe  */
245*38f89369SManish V Badarkhe static inline mbedtls_md_type_t md_type(enum crypto_md_algo algo)
246*38f89369SManish V Badarkhe {
247*38f89369SManish V Badarkhe 	switch (algo) {
248*38f89369SManish V Badarkhe 	case CRYPTO_MD_SHA512:
249*38f89369SManish V Badarkhe 		return MBEDTLS_MD_SHA512;
250*38f89369SManish V Badarkhe 	case CRYPTO_MD_SHA384:
251*38f89369SManish V Badarkhe 		return MBEDTLS_MD_SHA384;
252*38f89369SManish V Badarkhe 	case CRYPTO_MD_SHA256:
253*38f89369SManish V Badarkhe 		return MBEDTLS_MD_SHA256;
254*38f89369SManish V Badarkhe 	default:
255*38f89369SManish V Badarkhe 		/* Invalid hash algorithm. */
256*38f89369SManish V Badarkhe 		return MBEDTLS_MD_NONE;
257*38f89369SManish V Badarkhe 	}
258*38f89369SManish V Badarkhe }
259*38f89369SManish V Badarkhe 
260*38f89369SManish V Badarkhe /*
261*38f89369SManish V Badarkhe  * Calculate a hash
262*38f89369SManish V Badarkhe  *
263*38f89369SManish V Badarkhe  * output points to the computed hash
264*38f89369SManish V Badarkhe  */
265*38f89369SManish V Badarkhe static int calc_hash(enum crypto_md_algo md_algo, void *data_ptr,
266*38f89369SManish V Badarkhe 		     unsigned int data_len,
267*38f89369SManish V Badarkhe 		     unsigned char output[CRYPTO_MD_MAX_SIZE])
268*38f89369SManish V Badarkhe {
269*38f89369SManish V Badarkhe 	const mbedtls_md_info_t *md_info;
270*38f89369SManish V Badarkhe 
271*38f89369SManish V Badarkhe 	md_info = mbedtls_md_info_from_type(md_type(md_algo));
272*38f89369SManish V Badarkhe 	if (md_info == NULL) {
273*38f89369SManish V Badarkhe 		return CRYPTO_ERR_HASH;
274*38f89369SManish V Badarkhe 	}
275*38f89369SManish V Badarkhe 
276*38f89369SManish V Badarkhe 	/*
277*38f89369SManish V Badarkhe 	 * Calculate the hash of the data, it is safe to pass the
278*38f89369SManish V Badarkhe 	 * 'output' hash buffer pointer considering its size is always
279*38f89369SManish V Badarkhe 	 * bigger than or equal to MBEDTLS_MD_MAX_SIZE.
280*38f89369SManish V Badarkhe 	 */
281*38f89369SManish V Badarkhe 	return mbedtls_md(md_info, data_ptr, data_len, output);
282*38f89369SManish V Badarkhe }
283*38f89369SManish V Badarkhe #endif /*
284*38f89369SManish V Badarkhe 	* CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \
285*38f89369SManish V Badarkhe 	* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
286*38f89369SManish V Badarkhe 	*/
287*38f89369SManish V Badarkhe 
288*38f89369SManish V Badarkhe #if TF_MBEDTLS_USE_AES_GCM
289*38f89369SManish V Badarkhe /*
290*38f89369SManish V Badarkhe  * Stack based buffer allocation for decryption operation. It could
291*38f89369SManish V Badarkhe  * be configured to balance stack usage vs execution speed.
292*38f89369SManish V Badarkhe  */
293*38f89369SManish V Badarkhe #define DEC_OP_BUF_SIZE		128
294*38f89369SManish V Badarkhe 
295*38f89369SManish V Badarkhe static int aes_gcm_decrypt(void *data_ptr, size_t len, const void *key,
296*38f89369SManish V Badarkhe 			   unsigned int key_len, const void *iv,
297*38f89369SManish V Badarkhe 			   unsigned int iv_len, const void *tag,
298*38f89369SManish V Badarkhe 			   unsigned int tag_len)
299*38f89369SManish V Badarkhe {
300*38f89369SManish V Badarkhe 	mbedtls_gcm_context ctx;
301*38f89369SManish V Badarkhe 	mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
302*38f89369SManish V Badarkhe 	unsigned char buf[DEC_OP_BUF_SIZE];
303*38f89369SManish V Badarkhe 	unsigned char tag_buf[CRYPTO_MAX_TAG_SIZE];
304*38f89369SManish V Badarkhe 	unsigned char *pt = data_ptr;
305*38f89369SManish V Badarkhe 	size_t dec_len;
306*38f89369SManish V Badarkhe 	int diff, i, rc;
307*38f89369SManish V Badarkhe 	size_t output_length __unused;
308*38f89369SManish V Badarkhe 
309*38f89369SManish V Badarkhe 	mbedtls_gcm_init(&ctx);
310*38f89369SManish V Badarkhe 
311*38f89369SManish V Badarkhe 	rc = mbedtls_gcm_setkey(&ctx, cipher, key, key_len * 8);
312*38f89369SManish V Badarkhe 	if (rc != 0) {
313*38f89369SManish V Badarkhe 		rc = CRYPTO_ERR_DECRYPTION;
314*38f89369SManish V Badarkhe 		goto exit_gcm;
315*38f89369SManish V Badarkhe 	}
316*38f89369SManish V Badarkhe 
317*38f89369SManish V Badarkhe #if (MBEDTLS_VERSION_MAJOR < 3)
318*38f89369SManish V Badarkhe 	rc = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT, iv, iv_len, NULL, 0);
319*38f89369SManish V Badarkhe #else
320*38f89369SManish V Badarkhe 	rc = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT, iv, iv_len);
321*38f89369SManish V Badarkhe #endif
322*38f89369SManish V Badarkhe 	if (rc != 0) {
323*38f89369SManish V Badarkhe 		rc = CRYPTO_ERR_DECRYPTION;
324*38f89369SManish V Badarkhe 		goto exit_gcm;
325*38f89369SManish V Badarkhe 	}
326*38f89369SManish V Badarkhe 
327*38f89369SManish V Badarkhe 	while (len > 0) {
328*38f89369SManish V Badarkhe 		dec_len = MIN(sizeof(buf), len);
329*38f89369SManish V Badarkhe 
330*38f89369SManish V Badarkhe #if (MBEDTLS_VERSION_MAJOR < 3)
331*38f89369SManish V Badarkhe 		rc = mbedtls_gcm_update(&ctx, dec_len, pt, buf);
332*38f89369SManish V Badarkhe #else
333*38f89369SManish V Badarkhe 		rc = mbedtls_gcm_update(&ctx, pt, dec_len, buf, sizeof(buf), &output_length);
334*38f89369SManish V Badarkhe #endif
335*38f89369SManish V Badarkhe 
336*38f89369SManish V Badarkhe 		if (rc != 0) {
337*38f89369SManish V Badarkhe 			rc = CRYPTO_ERR_DECRYPTION;
338*38f89369SManish V Badarkhe 			goto exit_gcm;
339*38f89369SManish V Badarkhe 		}
340*38f89369SManish V Badarkhe 
341*38f89369SManish V Badarkhe 		memcpy(pt, buf, dec_len);
342*38f89369SManish V Badarkhe 		pt += dec_len;
343*38f89369SManish V Badarkhe 		len -= dec_len;
344*38f89369SManish V Badarkhe 	}
345*38f89369SManish V Badarkhe 
346*38f89369SManish V Badarkhe #if (MBEDTLS_VERSION_MAJOR < 3)
347*38f89369SManish V Badarkhe 	rc = mbedtls_gcm_finish(&ctx, tag_buf, sizeof(tag_buf));
348*38f89369SManish V Badarkhe #else
349*38f89369SManish V Badarkhe 	rc = mbedtls_gcm_finish(&ctx, NULL, 0, &output_length, tag_buf, sizeof(tag_buf));
350*38f89369SManish V Badarkhe #endif
351*38f89369SManish V Badarkhe 
352*38f89369SManish V Badarkhe 	if (rc != 0) {
353*38f89369SManish V Badarkhe 		rc = CRYPTO_ERR_DECRYPTION;
354*38f89369SManish V Badarkhe 		goto exit_gcm;
355*38f89369SManish V Badarkhe 	}
356*38f89369SManish V Badarkhe 
357*38f89369SManish V Badarkhe 	/* Check tag in "constant-time" */
358*38f89369SManish V Badarkhe 	for (diff = 0, i = 0; i < tag_len; i++)
359*38f89369SManish V Badarkhe 		diff |= ((const unsigned char *)tag)[i] ^ tag_buf[i];
360*38f89369SManish V Badarkhe 
361*38f89369SManish V Badarkhe 	if (diff != 0) {
362*38f89369SManish V Badarkhe 		rc = CRYPTO_ERR_DECRYPTION;
363*38f89369SManish V Badarkhe 		goto exit_gcm;
364*38f89369SManish V Badarkhe 	}
365*38f89369SManish V Badarkhe 
366*38f89369SManish V Badarkhe 	/* GCM decryption success */
367*38f89369SManish V Badarkhe 	rc = CRYPTO_SUCCESS;
368*38f89369SManish V Badarkhe 
369*38f89369SManish V Badarkhe exit_gcm:
370*38f89369SManish V Badarkhe 	mbedtls_gcm_free(&ctx);
371*38f89369SManish V Badarkhe 	return rc;
372*38f89369SManish V Badarkhe }
373*38f89369SManish V Badarkhe 
374*38f89369SManish V Badarkhe /*
375*38f89369SManish V Badarkhe  * Authenticated decryption of an image
376*38f89369SManish V Badarkhe  */
377*38f89369SManish V Badarkhe static int auth_decrypt(enum crypto_dec_algo dec_algo, void *data_ptr,
378*38f89369SManish V Badarkhe 			size_t len, const void *key, unsigned int key_len,
379*38f89369SManish V Badarkhe 			unsigned int key_flags, const void *iv,
380*38f89369SManish V Badarkhe 			unsigned int iv_len, const void *tag,
381*38f89369SManish V Badarkhe 			unsigned int tag_len)
382*38f89369SManish V Badarkhe {
383*38f89369SManish V Badarkhe 	int rc;
384*38f89369SManish V Badarkhe 
385*38f89369SManish V Badarkhe 	assert((key_flags & ENC_KEY_IS_IDENTIFIER) == 0);
386*38f89369SManish V Badarkhe 
387*38f89369SManish V Badarkhe 	switch (dec_algo) {
388*38f89369SManish V Badarkhe 	case CRYPTO_GCM_DECRYPT:
389*38f89369SManish V Badarkhe 		rc = aes_gcm_decrypt(data_ptr, len, key, key_len, iv, iv_len,
390*38f89369SManish V Badarkhe 				     tag, tag_len);
391*38f89369SManish V Badarkhe 		if (rc != 0)
392*38f89369SManish V Badarkhe 			return rc;
393*38f89369SManish V Badarkhe 		break;
394*38f89369SManish V Badarkhe 	default:
395*38f89369SManish V Badarkhe 		return CRYPTO_ERR_DECRYPTION;
396*38f89369SManish V Badarkhe 	}
397*38f89369SManish V Badarkhe 
398*38f89369SManish V Badarkhe 	return CRYPTO_SUCCESS;
399*38f89369SManish V Badarkhe }
400*38f89369SManish V Badarkhe #endif /* TF_MBEDTLS_USE_AES_GCM */
401*38f89369SManish V Badarkhe 
402*38f89369SManish V Badarkhe /*
403*38f89369SManish V Badarkhe  * Register crypto library descriptor
404*38f89369SManish V Badarkhe  */
405*38f89369SManish V Badarkhe #if CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
406*38f89369SManish V Badarkhe #if TF_MBEDTLS_USE_AES_GCM
407*38f89369SManish V Badarkhe REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash,
408*38f89369SManish V Badarkhe 		    auth_decrypt, NULL);
409*38f89369SManish V Badarkhe #else
410*38f89369SManish V Badarkhe REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash,
411*38f89369SManish V Badarkhe 		    NULL, NULL);
412*38f89369SManish V Badarkhe #endif
413*38f89369SManish V Badarkhe #elif CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY
414*38f89369SManish V Badarkhe #if TF_MBEDTLS_USE_AES_GCM
415*38f89369SManish V Badarkhe REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL,
416*38f89369SManish V Badarkhe 		    auth_decrypt, NULL);
417*38f89369SManish V Badarkhe #else
418*38f89369SManish V Badarkhe REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL,
419*38f89369SManish V Badarkhe 		    NULL, NULL);
420*38f89369SManish V Badarkhe #endif
421*38f89369SManish V Badarkhe #elif CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY
422*38f89369SManish V Badarkhe REGISTER_CRYPTO_LIB(LIB_NAME, init, NULL, NULL, calc_hash, NULL, NULL);
423*38f89369SManish V Badarkhe #endif /* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */
424