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