xref: /arm-trusted-firmware/plat/st/common/stm32mp_crypto_lib.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2022-2023, STMicroelectronics - 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 <endian.h>
9*91f16700Schasinglulu #include <errno.h>
10*91f16700Schasinglulu 
11*91f16700Schasinglulu #include <common/debug.h>
12*91f16700Schasinglulu #include <drivers/auth/crypto_mod.h>
13*91f16700Schasinglulu #include <drivers/io/io_storage.h>
14*91f16700Schasinglulu #include <drivers/st/bsec.h>
15*91f16700Schasinglulu #include <drivers/st/stm32_hash.h>
16*91f16700Schasinglulu #include <drivers/st/stm32_pka.h>
17*91f16700Schasinglulu #include <drivers/st/stm32_rng.h>
18*91f16700Schasinglulu #include <drivers/st/stm32_saes.h>
19*91f16700Schasinglulu #include <lib/utils.h>
20*91f16700Schasinglulu #include <lib/xlat_tables/xlat_tables_v2.h>
21*91f16700Schasinglulu #include <mbedtls/asn1.h>
22*91f16700Schasinglulu #include <mbedtls/md.h>
23*91f16700Schasinglulu #include <mbedtls/oid.h>
24*91f16700Schasinglulu #include <mbedtls/platform.h>
25*91f16700Schasinglulu #include <mbedtls/x509.h>
26*91f16700Schasinglulu #include <plat/common/platform.h>
27*91f16700Schasinglulu #include <tools_share/firmware_encrypted.h>
28*91f16700Schasinglulu 
29*91f16700Schasinglulu #include <platform_def.h>
30*91f16700Schasinglulu 
31*91f16700Schasinglulu #define CRYPTO_HASH_MAX_SIZE	32U
32*91f16700Schasinglulu #define CRYPTO_SIGN_MAX_SIZE	64U
33*91f16700Schasinglulu #define CRYPTO_PUBKEY_MAX_SIZE	64U
34*91f16700Schasinglulu #define CRYPTO_MAX_TAG_SIZE	16U
35*91f16700Schasinglulu 
36*91f16700Schasinglulu /* brainpoolP256t1 OID is not defined in mbedTLS */
37*91f16700Schasinglulu #define OID_EC_GRP_BP256T1          MBEDTLS_OID_EC_BRAINPOOL_V1 "\x08"
38*91f16700Schasinglulu 
39*91f16700Schasinglulu #if STM32MP_CRYPTO_ROM_LIB
40*91f16700Schasinglulu struct stm32mp_auth_ops {
41*91f16700Schasinglulu 	uint32_t (*verify_signature)(uint8_t *hash_in, uint8_t *pubkey_in,
42*91f16700Schasinglulu 				     uint8_t *signature, uint32_t ecc_algo);
43*91f16700Schasinglulu };
44*91f16700Schasinglulu 
45*91f16700Schasinglulu static struct stm32mp_auth_ops auth_ops;
46*91f16700Schasinglulu #endif
47*91f16700Schasinglulu 
48*91f16700Schasinglulu static void crypto_lib_init(void)
49*91f16700Schasinglulu {
50*91f16700Schasinglulu 	boot_api_context_t *boot_context __maybe_unused;
51*91f16700Schasinglulu 	int ret;
52*91f16700Schasinglulu 
53*91f16700Schasinglulu 	NOTICE("TRUSTED_BOARD_BOOT support enabled\n");
54*91f16700Schasinglulu 
55*91f16700Schasinglulu 	ret = stm32_hash_register();
56*91f16700Schasinglulu 	if (ret != 0) {
57*91f16700Schasinglulu 		ERROR("HASH init (%d)\n", ret);
58*91f16700Schasinglulu 		panic();
59*91f16700Schasinglulu 	}
60*91f16700Schasinglulu 
61*91f16700Schasinglulu 	if (stm32mp_is_closed_device() || stm32mp_is_auth_supported()) {
62*91f16700Schasinglulu #if STM32MP_CRYPTO_ROM_LIB
63*91f16700Schasinglulu 		boot_context = (boot_api_context_t *)stm32mp_get_boot_ctx_address();
64*91f16700Schasinglulu 		auth_ops.verify_signature = boot_context->bootrom_ecdsa_verify_signature;
65*91f16700Schasinglulu #else
66*91f16700Schasinglulu 		/* Use hardware peripherals */
67*91f16700Schasinglulu 		if (stm32_rng_init() != 0) {
68*91f16700Schasinglulu 			panic();
69*91f16700Schasinglulu 		}
70*91f16700Schasinglulu 
71*91f16700Schasinglulu 		if (stm32_saes_driver_init() != 0) {
72*91f16700Schasinglulu 			panic();
73*91f16700Schasinglulu 		}
74*91f16700Schasinglulu 
75*91f16700Schasinglulu 		if (stm32_pka_init() != 0) {
76*91f16700Schasinglulu 			panic();
77*91f16700Schasinglulu 		}
78*91f16700Schasinglulu #endif
79*91f16700Schasinglulu 	}
80*91f16700Schasinglulu }
81*91f16700Schasinglulu 
82*91f16700Schasinglulu static int get_plain_pk_from_asn1(void *pk_ptr, unsigned int pk_len, void **plain_pk,
83*91f16700Schasinglulu 				  size_t *len, int *pk_alg)
84*91f16700Schasinglulu {
85*91f16700Schasinglulu 	int ret;
86*91f16700Schasinglulu 	mbedtls_pk_context mbedtls_pk = {0};
87*91f16700Schasinglulu 	unsigned char *p, *end;
88*91f16700Schasinglulu 	mbedtls_asn1_buf alg_params = {0};
89*91f16700Schasinglulu 	mbedtls_asn1_buf alg_oid = {0};
90*91f16700Schasinglulu 
91*91f16700Schasinglulu 	*plain_pk = NULL;
92*91f16700Schasinglulu 	*len = 0U;
93*91f16700Schasinglulu 
94*91f16700Schasinglulu 	/* Parse the public key */
95*91f16700Schasinglulu 	mbedtls_pk_init(&mbedtls_pk);
96*91f16700Schasinglulu 	p = (unsigned char *)pk_ptr;
97*91f16700Schasinglulu 	end = (unsigned char *)(p + pk_len);
98*91f16700Schasinglulu 
99*91f16700Schasinglulu 	ret =  mbedtls_asn1_get_tag(&p, end, len,
100*91f16700Schasinglulu 				    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
101*91f16700Schasinglulu 	if (ret != 0) {
102*91f16700Schasinglulu 		return -EINVAL;
103*91f16700Schasinglulu 	}
104*91f16700Schasinglulu 
105*91f16700Schasinglulu 	end = p + *len;
106*91f16700Schasinglulu 	ret = mbedtls_asn1_get_alg(&p, end, &alg_oid, &alg_params);
107*91f16700Schasinglulu 	if (ret != 0) {
108*91f16700Schasinglulu 		VERBOSE("%s: mbedtls_asn1_get_alg (%d)\n", __func__, ret);
109*91f16700Schasinglulu 		return -EINVAL;
110*91f16700Schasinglulu 	}
111*91f16700Schasinglulu 
112*91f16700Schasinglulu 	if (pk_alg != NULL) {
113*91f16700Schasinglulu 		if ((strlen(MBEDTLS_OID_EC_GRP_SECP256R1) == alg_params.len) &&
114*91f16700Schasinglulu 		    (memcmp(MBEDTLS_OID_EC_GRP_SECP256R1, alg_params.p, alg_params.len) == 0)) {
115*91f16700Schasinglulu 			*pk_alg = BOOT_API_ECDSA_ALGO_TYPE_P256NIST;
116*91f16700Schasinglulu 		} else if ((strlen(OID_EC_GRP_BP256T1) == alg_params.len) &&
117*91f16700Schasinglulu 		    (memcmp(OID_EC_GRP_BP256T1, alg_params.p, alg_params.len) == 0)) {
118*91f16700Schasinglulu 			*pk_alg = BOOT_API_ECDSA_ALGO_TYPE_BRAINPOOL256;
119*91f16700Schasinglulu 		} else {
120*91f16700Schasinglulu 			ERROR("%s: Algorithm is not supported\n", __func__);
121*91f16700Schasinglulu 			return -EINVAL;
122*91f16700Schasinglulu 		}
123*91f16700Schasinglulu 	}
124*91f16700Schasinglulu 
125*91f16700Schasinglulu 	ret = mbedtls_asn1_get_bitstring_null(&p, end, len);
126*91f16700Schasinglulu 	if (ret != 0) {
127*91f16700Schasinglulu 		VERBOSE("%s: mbedtls_asn1_get_bitstring_null (%d)\n", __func__, ret);
128*91f16700Schasinglulu 		return -EINVAL;
129*91f16700Schasinglulu 	}
130*91f16700Schasinglulu 
131*91f16700Schasinglulu 	/* We remove the ident (0x04) first byte. */
132*91f16700Schasinglulu 	if ((*len < 1U) || (p[0] !=  MBEDTLS_ASN1_OCTET_STRING)) {
133*91f16700Schasinglulu 		VERBOSE("%s: not expected len or tag\n", __func__);
134*91f16700Schasinglulu 		return -EINVAL;
135*91f16700Schasinglulu 	}
136*91f16700Schasinglulu 
137*91f16700Schasinglulu 	*len = *len - 1U;
138*91f16700Schasinglulu 	*plain_pk = p + 1U;
139*91f16700Schasinglulu 
140*91f16700Schasinglulu 	return 0;
141*91f16700Schasinglulu }
142*91f16700Schasinglulu 
143*91f16700Schasinglulu #if STM32MP_CRYPTO_ROM_LIB
144*91f16700Schasinglulu uint32_t verify_signature(uint8_t *hash_in, uint8_t *pubkey_in,
145*91f16700Schasinglulu 			  uint8_t *signature, uint32_t ecc_algo)
146*91f16700Schasinglulu {
147*91f16700Schasinglulu 	int ret;
148*91f16700Schasinglulu 
149*91f16700Schasinglulu 	ret = mmap_add_dynamic_region(STM32MP_ROM_BASE, STM32MP_ROM_BASE,
150*91f16700Schasinglulu 				      STM32MP_ROM_SIZE_2MB_ALIGNED, MT_CODE | MT_SECURE);
151*91f16700Schasinglulu 	if (ret != 0) {
152*91f16700Schasinglulu 		VERBOSE("%s: mmap_add_dynamic_region (%d)\n", __func__, ret);
153*91f16700Schasinglulu 		return CRYPTO_ERR_SIGNATURE;
154*91f16700Schasinglulu 	}
155*91f16700Schasinglulu 
156*91f16700Schasinglulu 	ret = auth_ops.verify_signature(hash_in, pubkey_in, signature, ecc_algo);
157*91f16700Schasinglulu 
158*91f16700Schasinglulu 	if (ret != BOOT_API_RETURN_OK) {
159*91f16700Schasinglulu 		VERBOSE("%s: auth_ops.verify_sign (%d)\n", __func__, ret);
160*91f16700Schasinglulu 		ret = CRYPTO_ERR_SIGNATURE;
161*91f16700Schasinglulu 	} else {
162*91f16700Schasinglulu 		ret = 0;
163*91f16700Schasinglulu 	}
164*91f16700Schasinglulu 
165*91f16700Schasinglulu 	mmap_remove_dynamic_region(STM32MP_ROM_BASE, STM32MP_ROM_SIZE_2MB_ALIGNED);
166*91f16700Schasinglulu 
167*91f16700Schasinglulu 	return ret;
168*91f16700Schasinglulu }
169*91f16700Schasinglulu 
170*91f16700Schasinglulu static int crypto_convert_pk(void *full_pk_ptr, unsigned int full_pk_len,
171*91f16700Schasinglulu 			     void **hashed_pk_ptr, unsigned int *hashed_pk_len)
172*91f16700Schasinglulu {
173*91f16700Schasinglulu 	size_t len;
174*91f16700Schasinglulu 	int ret;
175*91f16700Schasinglulu 
176*91f16700Schasinglulu 	ret = get_plain_pk_from_asn1(full_pk_ptr, full_pk_len, hashed_pk_ptr, &len, NULL);
177*91f16700Schasinglulu 	if (ret == 0) {
178*91f16700Schasinglulu 		*hashed_pk_len = (unsigned int)len;
179*91f16700Schasinglulu 	}
180*91f16700Schasinglulu 
181*91f16700Schasinglulu 	return ret;
182*91f16700Schasinglulu }
183*91f16700Schasinglulu #else /* STM32MP_CRYPTO_ROM_LIB*/
184*91f16700Schasinglulu static uint32_t verify_signature(uint8_t *hash_in, uint8_t *pubkey_in,
185*91f16700Schasinglulu 				 uint8_t *signature, uint32_t ecc_algo)
186*91f16700Schasinglulu {
187*91f16700Schasinglulu 	int ret = -1;
188*91f16700Schasinglulu 	enum stm32_pka_ecdsa_curve_id cid;
189*91f16700Schasinglulu 
190*91f16700Schasinglulu 	switch (ecc_algo) {
191*91f16700Schasinglulu 	case BOOT_API_ECDSA_ALGO_TYPE_P256NIST:
192*91f16700Schasinglulu #if PKA_USE_NIST_P256
193*91f16700Schasinglulu 		cid = PKA_NIST_P256;
194*91f16700Schasinglulu 		ret = 0;
195*91f16700Schasinglulu #else
196*91f16700Schasinglulu 		WARN("%s nist_p256 requested but not included\n", __func__);
197*91f16700Schasinglulu #endif
198*91f16700Schasinglulu 		break;
199*91f16700Schasinglulu 	case BOOT_API_ECDSA_ALGO_TYPE_BRAINPOOL256:
200*91f16700Schasinglulu #if PKA_USE_BRAINPOOL_P256T1
201*91f16700Schasinglulu 		cid = PKA_BRAINPOOL_P256T1;
202*91f16700Schasinglulu 		ret = 0;
203*91f16700Schasinglulu #else
204*91f16700Schasinglulu 		WARN("%s brainpool_p256t1 requested but not included\n", __func__);
205*91f16700Schasinglulu #endif
206*91f16700Schasinglulu 		break;
207*91f16700Schasinglulu 	default:
208*91f16700Schasinglulu 		WARN("%s unexpected ecc_algo(%u)\n", __func__, ecc_algo);
209*91f16700Schasinglulu 		break;
210*91f16700Schasinglulu 	}
211*91f16700Schasinglulu 
212*91f16700Schasinglulu 	if (ret < 0) {
213*91f16700Schasinglulu 		return CRYPTO_ERR_SIGNATURE;
214*91f16700Schasinglulu 	}
215*91f16700Schasinglulu 
216*91f16700Schasinglulu 	ret = stm32_pka_ecdsa_verif(hash_in,
217*91f16700Schasinglulu 				    BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES,
218*91f16700Schasinglulu 				    signature, BOOT_API_ECDSA_SIGNATURE_LEN_IN_BYTES / 2U,
219*91f16700Schasinglulu 				    signature + BOOT_API_ECDSA_SIGNATURE_LEN_IN_BYTES / 2U,
220*91f16700Schasinglulu 				    BOOT_API_ECDSA_SIGNATURE_LEN_IN_BYTES / 2U,
221*91f16700Schasinglulu 				    pubkey_in, BOOT_API_ECDSA_PUB_KEY_LEN_IN_BYTES / 2U,
222*91f16700Schasinglulu 				    pubkey_in + BOOT_API_ECDSA_PUB_KEY_LEN_IN_BYTES / 2U,
223*91f16700Schasinglulu 				    BOOT_API_ECDSA_PUB_KEY_LEN_IN_BYTES / 2U, cid);
224*91f16700Schasinglulu 	if (ret < 0) {
225*91f16700Schasinglulu 		return CRYPTO_ERR_SIGNATURE;
226*91f16700Schasinglulu 	}
227*91f16700Schasinglulu 
228*91f16700Schasinglulu 	return 0;
229*91f16700Schasinglulu }
230*91f16700Schasinglulu 
231*91f16700Schasinglulu static int crypto_convert_pk(void *full_pk_ptr, unsigned int full_pk_len,
232*91f16700Schasinglulu 			     void **hashed_pk_ptr, unsigned int *hashed_pk_len)
233*91f16700Schasinglulu {
234*91f16700Schasinglulu 	static uint8_t st_pk[CRYPTO_PUBKEY_MAX_SIZE + sizeof(uint32_t)];
235*91f16700Schasinglulu 	int ret;
236*91f16700Schasinglulu 	void *plain_pk;
237*91f16700Schasinglulu 	size_t len;
238*91f16700Schasinglulu 	int curve_id;
239*91f16700Schasinglulu 	uint32_t cid;
240*91f16700Schasinglulu 
241*91f16700Schasinglulu 	ret = get_plain_pk_from_asn1(full_pk_ptr, full_pk_len, &plain_pk, &len, &curve_id);
242*91f16700Schasinglulu 	if ((ret != 0) || (len > CRYPTO_PUBKEY_MAX_SIZE))  {
243*91f16700Schasinglulu 		return -EINVAL;
244*91f16700Schasinglulu 	}
245*91f16700Schasinglulu 
246*91f16700Schasinglulu 	cid = curve_id; /* we want value of curve_id (1 or 2) in a uint32_t */
247*91f16700Schasinglulu 
248*91f16700Schasinglulu 	memcpy(st_pk, &cid, sizeof(cid));
249*91f16700Schasinglulu 	memcpy(st_pk + sizeof(cid), plain_pk, len);
250*91f16700Schasinglulu 
251*91f16700Schasinglulu 	*hashed_pk_ptr = st_pk;
252*91f16700Schasinglulu 	*hashed_pk_len = (unsigned int)(len + sizeof(cid));
253*91f16700Schasinglulu 
254*91f16700Schasinglulu 	return 0;
255*91f16700Schasinglulu }
256*91f16700Schasinglulu #endif /* STM32MP_CRYPTO_ROM_LIB */
257*91f16700Schasinglulu 
258*91f16700Schasinglulu static int get_plain_digest_from_asn1(void *digest_ptr, unsigned int digest_len,
259*91f16700Schasinglulu 				      uint8_t **out, size_t *out_len, mbedtls_md_type_t *md_alg)
260*91f16700Schasinglulu {
261*91f16700Schasinglulu 	int ret;
262*91f16700Schasinglulu 	mbedtls_asn1_buf hash_oid, params;
263*91f16700Schasinglulu 	size_t len;
264*91f16700Schasinglulu 	unsigned char *p, *end;
265*91f16700Schasinglulu 
266*91f16700Schasinglulu 	*out = NULL;
267*91f16700Schasinglulu 	*out_len = 0U;
268*91f16700Schasinglulu 
269*91f16700Schasinglulu 	/* Digest info should be an MBEDTLS_ASN1_SEQUENCE */
270*91f16700Schasinglulu 	p = (unsigned char *)digest_ptr;
271*91f16700Schasinglulu 	end = p + digest_len;
272*91f16700Schasinglulu 	ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
273*91f16700Schasinglulu 				   MBEDTLS_ASN1_SEQUENCE);
274*91f16700Schasinglulu 	if (ret != 0) {
275*91f16700Schasinglulu 		return ret;
276*91f16700Schasinglulu 	}
277*91f16700Schasinglulu 
278*91f16700Schasinglulu 	/* Get the hash algorithm */
279*91f16700Schasinglulu 	ret = mbedtls_asn1_get_alg(&p, end, &hash_oid, &params);
280*91f16700Schasinglulu 	if (ret != 0) {
281*91f16700Schasinglulu 		return ret;
282*91f16700Schasinglulu 	}
283*91f16700Schasinglulu 
284*91f16700Schasinglulu 	ret = mbedtls_oid_get_md_alg(&hash_oid, md_alg);
285*91f16700Schasinglulu 	if (ret != 0) {
286*91f16700Schasinglulu 		return ret;
287*91f16700Schasinglulu 	}
288*91f16700Schasinglulu 
289*91f16700Schasinglulu 	ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING);
290*91f16700Schasinglulu 	if (ret != 0) {
291*91f16700Schasinglulu 		return ret;
292*91f16700Schasinglulu 	}
293*91f16700Schasinglulu 
294*91f16700Schasinglulu 	/* Length of hash must match the algorithm's size */
295*91f16700Schasinglulu 	if (len != BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES) {
296*91f16700Schasinglulu 		return -1;
297*91f16700Schasinglulu 	}
298*91f16700Schasinglulu 
299*91f16700Schasinglulu 	*out = p;
300*91f16700Schasinglulu 	*out_len = len;
301*91f16700Schasinglulu 
302*91f16700Schasinglulu 	return 0;
303*91f16700Schasinglulu }
304*91f16700Schasinglulu 
305*91f16700Schasinglulu static int crypto_verify_signature(void *data_ptr, unsigned int data_len,
306*91f16700Schasinglulu 				   void *sig_ptr, unsigned int sig_len,
307*91f16700Schasinglulu 				   void *sig_alg, unsigned int sig_alg_len,
308*91f16700Schasinglulu 				   void *pk_ptr, unsigned int pk_len)
309*91f16700Schasinglulu {
310*91f16700Schasinglulu 	uint8_t image_hash[CRYPTO_HASH_MAX_SIZE] = {0};
311*91f16700Schasinglulu 	uint8_t sig[CRYPTO_SIGN_MAX_SIZE];
312*91f16700Schasinglulu 	uint8_t my_pk[CRYPTO_PUBKEY_MAX_SIZE];
313*91f16700Schasinglulu 	int ret;
314*91f16700Schasinglulu 	size_t len;
315*91f16700Schasinglulu 	mbedtls_asn1_sequence seq;
316*91f16700Schasinglulu 	mbedtls_asn1_sequence *cur;
317*91f16700Schasinglulu 	unsigned char *p, *end;
318*91f16700Schasinglulu 	int curve_id;
319*91f16700Schasinglulu 	mbedtls_asn1_buf sig_oid, sig_params;
320*91f16700Schasinglulu 	mbedtls_md_type_t md_alg;
321*91f16700Schasinglulu 	mbedtls_pk_type_t pk_alg;
322*91f16700Schasinglulu 	size_t bignum_len = sizeof(sig) / 2U;
323*91f16700Schasinglulu 	unsigned int seq_num = 0U;
324*91f16700Schasinglulu 
325*91f16700Schasinglulu 	if (!stm32mp_is_closed_device() && !stm32mp_is_auth_supported()) {
326*91f16700Schasinglulu 		return CRYPTO_SUCCESS;
327*91f16700Schasinglulu 	}
328*91f16700Schasinglulu 
329*91f16700Schasinglulu 	/* Get pointers to signature OID and parameters */
330*91f16700Schasinglulu 	p = (unsigned char *)sig_alg;
331*91f16700Schasinglulu 	end = (unsigned char *)(p + sig_alg_len);
332*91f16700Schasinglulu 	ret = mbedtls_asn1_get_alg(&p, end, &sig_oid, &sig_params);
333*91f16700Schasinglulu 	if (ret != 0) {
334*91f16700Schasinglulu 		VERBOSE("%s: mbedtls_asn1_get_alg (%d)\n", __func__, ret);
335*91f16700Schasinglulu 		return CRYPTO_ERR_SIGNATURE;
336*91f16700Schasinglulu 	}
337*91f16700Schasinglulu 
338*91f16700Schasinglulu 	/* Get the actual signature algorithm (MD + PK) */
339*91f16700Schasinglulu 	ret = mbedtls_oid_get_sig_alg(&sig_oid, &md_alg, &pk_alg);
340*91f16700Schasinglulu 	if (ret != 0) {
341*91f16700Schasinglulu 		VERBOSE("%s: mbedtls_oid_get_sig_alg (%d)\n", __func__, ret);
342*91f16700Schasinglulu 		return CRYPTO_ERR_SIGNATURE;
343*91f16700Schasinglulu 	}
344*91f16700Schasinglulu 
345*91f16700Schasinglulu 	if ((md_alg != MBEDTLS_MD_SHA256) || (pk_alg != MBEDTLS_PK_ECDSA)) {
346*91f16700Schasinglulu 		VERBOSE("%s: md_alg=%u pk_alg=%u\n", __func__, md_alg, pk_alg);
347*91f16700Schasinglulu 		return CRYPTO_ERR_SIGNATURE;
348*91f16700Schasinglulu 	}
349*91f16700Schasinglulu 
350*91f16700Schasinglulu 	ret = get_plain_pk_from_asn1(pk_ptr, pk_len, &pk_ptr, &len, &curve_id);
351*91f16700Schasinglulu 	if (ret != 0) {
352*91f16700Schasinglulu 		VERBOSE("%s: get_plain_pk_from_asn1 (%d)\n", __func__, ret);
353*91f16700Schasinglulu 		return CRYPTO_ERR_SIGNATURE;
354*91f16700Schasinglulu 	}
355*91f16700Schasinglulu 
356*91f16700Schasinglulu 	/* We expect a known pk_len */
357*91f16700Schasinglulu 	if (len != sizeof(my_pk)) {
358*91f16700Schasinglulu 		VERBOSE("%s: pk_len=%zu sizeof(my_pk)=%zu)\n", __func__, len, sizeof(my_pk));
359*91f16700Schasinglulu 		return CRYPTO_ERR_SIGNATURE;
360*91f16700Schasinglulu 	}
361*91f16700Schasinglulu 
362*91f16700Schasinglulu 	/* Need to copy as auth_ops.verify_signature
363*91f16700Schasinglulu 	 * expects aligned public key.
364*91f16700Schasinglulu 	 */
365*91f16700Schasinglulu 	memcpy(my_pk, pk_ptr, sizeof(my_pk));
366*91f16700Schasinglulu 
367*91f16700Schasinglulu 	/* Get the signature (bitstring) */
368*91f16700Schasinglulu 	p = (unsigned char *)sig_ptr;
369*91f16700Schasinglulu 	end = (unsigned char *)(p + sig_len);
370*91f16700Schasinglulu 	ret = mbedtls_asn1_get_bitstring_null(&p, end, &len);
371*91f16700Schasinglulu 	if (ret != 0) {
372*91f16700Schasinglulu 		VERBOSE("%s: mbedtls_asn1_get_bitstring_null (%d)\n", __func__, ret);
373*91f16700Schasinglulu 		return CRYPTO_ERR_SIGNATURE;
374*91f16700Schasinglulu 	}
375*91f16700Schasinglulu 
376*91f16700Schasinglulu 	/* Get r and s from sequence */
377*91f16700Schasinglulu 	ret = mbedtls_asn1_get_sequence_of(&p, end, &seq, MBEDTLS_ASN1_INTEGER);
378*91f16700Schasinglulu 	if (ret != 0) {
379*91f16700Schasinglulu 		VERBOSE("%s: mbedtls_asn1_get_sequence_of (%d)\n", __func__, ret);
380*91f16700Schasinglulu 		return CRYPTO_ERR_SIGNATURE;
381*91f16700Schasinglulu 	}
382*91f16700Schasinglulu 
383*91f16700Schasinglulu 	/* We expect only 2 integers (r and s) from the sequence */
384*91f16700Schasinglulu 	if (seq.next->next != NULL) {
385*91f16700Schasinglulu 		cur = seq.next;
386*91f16700Schasinglulu 		mbedtls_asn1_sequence *next;
387*91f16700Schasinglulu 
388*91f16700Schasinglulu 		VERBOSE("%s: nb seq != 2\n", __func__);
389*91f16700Schasinglulu 		/* Free all the sequences */
390*91f16700Schasinglulu 		while (cur != NULL) {
391*91f16700Schasinglulu 			next = cur->next;
392*91f16700Schasinglulu 			mbedtls_free(cur);
393*91f16700Schasinglulu 			cur = next;
394*91f16700Schasinglulu 		}
395*91f16700Schasinglulu 
396*91f16700Schasinglulu 		return CRYPTO_ERR_SIGNATURE;
397*91f16700Schasinglulu 	}
398*91f16700Schasinglulu 
399*91f16700Schasinglulu 	/*
400*91f16700Schasinglulu 	 * ECDSA signatures are composed of a tuple (R,S) where R and S are between 0 and n.
401*91f16700Schasinglulu 	 * This means that the R and S can have a maximum of 32 each, but can also be smaller.
402*91f16700Schasinglulu 	 * Also seen the integer sequence may (sometime) start with 0x00 as MSB, but we can only
403*91f16700Schasinglulu 	 * manage exactly 2*32 bytes, we remove this higher byte if there are not 00,
404*91f16700Schasinglulu 	 * we will fail either.
405*91f16700Schasinglulu 	 */
406*91f16700Schasinglulu 	cur = &seq;
407*91f16700Schasinglulu 	memset(sig, 0U, sizeof(sig));
408*91f16700Schasinglulu 
409*91f16700Schasinglulu 	while (cur != NULL) {
410*91f16700Schasinglulu 		size_t skip = 0U;
411*91f16700Schasinglulu 		size_t seek = seq_num * bignum_len;
412*91f16700Schasinglulu 
413*91f16700Schasinglulu 		if (cur->buf.len > bignum_len) {
414*91f16700Schasinglulu 			/* Remove extra 0x00 bytes */
415*91f16700Schasinglulu 			skip = cur->buf.len - bignum_len;
416*91f16700Schasinglulu 		} else if (cur->buf.len < bignum_len) {
417*91f16700Schasinglulu 			/* Add padding to match HW required size */
418*91f16700Schasinglulu 			seek += (bignum_len % cur->buf.len);
419*91f16700Schasinglulu 		}
420*91f16700Schasinglulu 
421*91f16700Schasinglulu 		if (seek + cur->buf.len > sizeof(sig) + skip) {
422*91f16700Schasinglulu 			panic();
423*91f16700Schasinglulu 		}
424*91f16700Schasinglulu 
425*91f16700Schasinglulu 		memcpy(sig + seek, cur->buf.p + skip, cur->buf.len - skip);
426*91f16700Schasinglulu 		cur = cur->next;
427*91f16700Schasinglulu 		seq_num++;
428*91f16700Schasinglulu 	}
429*91f16700Schasinglulu 
430*91f16700Schasinglulu 	/* Need to free allocated 'next' in mbedtls_asn1_get_sequence_of */
431*91f16700Schasinglulu 	mbedtls_free(seq.next);
432*91f16700Schasinglulu 
433*91f16700Schasinglulu 	/* Compute hash for the data covered by the signature */
434*91f16700Schasinglulu 	stm32_hash_init(HASH_SHA256);
435*91f16700Schasinglulu 
436*91f16700Schasinglulu 	ret = stm32_hash_final_update((uint8_t *)data_ptr, data_len, image_hash);
437*91f16700Schasinglulu 	if (ret != 0) {
438*91f16700Schasinglulu 		VERBOSE("%s: stm32_hash_final_update (%d)\n", __func__, ret);
439*91f16700Schasinglulu 		return CRYPTO_ERR_SIGNATURE;
440*91f16700Schasinglulu 	}
441*91f16700Schasinglulu 
442*91f16700Schasinglulu 	return verify_signature(image_hash, my_pk, sig, curve_id);
443*91f16700Schasinglulu }
444*91f16700Schasinglulu 
445*91f16700Schasinglulu static int crypto_verify_hash(void *data_ptr, unsigned int data_len,
446*91f16700Schasinglulu 			      void *digest_info_ptr,
447*91f16700Schasinglulu 			      unsigned int digest_info_len)
448*91f16700Schasinglulu {
449*91f16700Schasinglulu 	int ret;
450*91f16700Schasinglulu 	uint8_t calc_hash[BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES];
451*91f16700Schasinglulu 	unsigned char *p;
452*91f16700Schasinglulu 	mbedtls_md_type_t md_alg;
453*91f16700Schasinglulu 	size_t len;
454*91f16700Schasinglulu 
455*91f16700Schasinglulu 	/* we receive an asn1 encapsulated digest, we flatten it */
456*91f16700Schasinglulu 	ret = get_plain_digest_from_asn1(digest_info_ptr,
457*91f16700Schasinglulu 					 digest_info_len, &p, &len,
458*91f16700Schasinglulu 					 &md_alg);
459*91f16700Schasinglulu 	if ((ret != 0) || (md_alg != MBEDTLS_MD_SHA256) || (len != sizeof(calc_hash))) {
460*91f16700Schasinglulu 		return CRYPTO_ERR_HASH;
461*91f16700Schasinglulu 	}
462*91f16700Schasinglulu 
463*91f16700Schasinglulu 	digest_info_ptr = p;
464*91f16700Schasinglulu 	digest_info_len = len;
465*91f16700Schasinglulu 
466*91f16700Schasinglulu 	stm32_hash_init(HASH_SHA256);
467*91f16700Schasinglulu 
468*91f16700Schasinglulu 	ret = stm32_hash_final_update(data_ptr, data_len, calc_hash);
469*91f16700Schasinglulu 	if (ret != 0) {
470*91f16700Schasinglulu 		VERBOSE("%s: hash failed\n", __func__);
471*91f16700Schasinglulu 		return CRYPTO_ERR_HASH;
472*91f16700Schasinglulu 	}
473*91f16700Schasinglulu 
474*91f16700Schasinglulu 	ret = memcmp(calc_hash, digest_info_ptr, digest_info_len);
475*91f16700Schasinglulu 	if (ret != 0) {
476*91f16700Schasinglulu 		VERBOSE("%s: not expected digest\n", __func__);
477*91f16700Schasinglulu 		ret = CRYPTO_ERR_HASH;
478*91f16700Schasinglulu 	}
479*91f16700Schasinglulu 
480*91f16700Schasinglulu 	return ret;
481*91f16700Schasinglulu }
482*91f16700Schasinglulu 
483*91f16700Schasinglulu #if !defined(DECRYPTION_SUPPORT_none)
484*91f16700Schasinglulu static int derive_key(uint8_t *key, size_t *key_len, size_t len,
485*91f16700Schasinglulu 		      unsigned int *flags, const uint8_t *img_id, size_t img_id_len)
486*91f16700Schasinglulu {
487*91f16700Schasinglulu 	size_t i, j;
488*91f16700Schasinglulu 
489*91f16700Schasinglulu 	assert(*key_len >= 32U);
490*91f16700Schasinglulu 
491*91f16700Schasinglulu 	/*
492*91f16700Schasinglulu 	 * Not a real derivation yet
493*91f16700Schasinglulu 	 *
494*91f16700Schasinglulu 	 * We expect a 32 bytes key, if OTP is only 16 bytes
495*91f16700Schasinglulu 	 *   => duplicate.
496*91f16700Schasinglulu 	 */
497*91f16700Schasinglulu 	for (i = 0U, j = len; j < 32U;
498*91f16700Schasinglulu 	     i += sizeof(uint32_t), j += sizeof(uint32_t)) {
499*91f16700Schasinglulu 		memcpy(key + j, key + i, sizeof(uint32_t));
500*91f16700Schasinglulu 	}
501*91f16700Schasinglulu 
502*91f16700Schasinglulu 	*key_len = 32U;
503*91f16700Schasinglulu 	/* Variable 'key' store a real key */
504*91f16700Schasinglulu 	*flags = 0U;
505*91f16700Schasinglulu 
506*91f16700Schasinglulu 	return 0;
507*91f16700Schasinglulu }
508*91f16700Schasinglulu 
509*91f16700Schasinglulu int plat_get_enc_key_info(enum fw_enc_status_t fw_enc_status, uint8_t *key,
510*91f16700Schasinglulu 			  size_t *key_len, unsigned int *flags,
511*91f16700Schasinglulu 			  const uint8_t *img_id, size_t img_id_len)
512*91f16700Schasinglulu {
513*91f16700Schasinglulu 	uint32_t otp_idx;
514*91f16700Schasinglulu 	uint32_t otp_len;
515*91f16700Schasinglulu 	size_t read_len;
516*91f16700Schasinglulu 	size_t i;
517*91f16700Schasinglulu 
518*91f16700Schasinglulu 	if (fw_enc_status == FW_ENC_WITH_BSSK) {
519*91f16700Schasinglulu 		return -EINVAL;
520*91f16700Schasinglulu 	}
521*91f16700Schasinglulu 
522*91f16700Schasinglulu 	if (stm32_get_otp_index(ENCKEY_OTP, &otp_idx, &otp_len) != 0) {
523*91f16700Schasinglulu 		VERBOSE("%s: get %s index error\n", __func__, ENCKEY_OTP);
524*91f16700Schasinglulu 		return -EINVAL;
525*91f16700Schasinglulu 	}
526*91f16700Schasinglulu 
527*91f16700Schasinglulu 	if (otp_len > (*key_len * CHAR_BIT)) {
528*91f16700Schasinglulu 		VERBOSE("%s: length Error otp_len=%u key_len=%zu\n", __func__,
529*91f16700Schasinglulu 			otp_len, *key_len * CHAR_BIT);
530*91f16700Schasinglulu 		return -EINVAL;
531*91f16700Schasinglulu 	}
532*91f16700Schasinglulu 
533*91f16700Schasinglulu 	read_len = otp_len / CHAR_BIT;
534*91f16700Schasinglulu 	assert(read_len % sizeof(uint32_t) == 0);
535*91f16700Schasinglulu 
536*91f16700Schasinglulu 	for (i = 0U; i < read_len / sizeof(uint32_t); i++) {
537*91f16700Schasinglulu 		uint32_t tmp;
538*91f16700Schasinglulu 		uint32_t otp_val;
539*91f16700Schasinglulu 
540*91f16700Schasinglulu 		if (stm32_get_otp_value_from_idx(otp_idx + i, &otp_val) != 0) {
541*91f16700Schasinglulu 			zeromem(key, *key_len);
542*91f16700Schasinglulu 			VERBOSE("%s: unable to read from otp\n", __func__);
543*91f16700Schasinglulu 			return -EINVAL;
544*91f16700Schasinglulu 		}
545*91f16700Schasinglulu 
546*91f16700Schasinglulu 		tmp = bswap32(otp_val);
547*91f16700Schasinglulu 		memcpy(key + i * sizeof(uint32_t), &tmp, sizeof(tmp));
548*91f16700Schasinglulu 	}
549*91f16700Schasinglulu 
550*91f16700Schasinglulu 	/* Now we have the OTP values in key till read_len */
551*91f16700Schasinglulu 
552*91f16700Schasinglulu 	if (derive_key(key, key_len, read_len, flags, img_id,
553*91f16700Schasinglulu 		       img_id_len) != 0) {
554*91f16700Schasinglulu 		zeromem(key, *key_len);
555*91f16700Schasinglulu 		return -EINVAL;
556*91f16700Schasinglulu 	}
557*91f16700Schasinglulu 
558*91f16700Schasinglulu 	return 0;
559*91f16700Schasinglulu }
560*91f16700Schasinglulu 
561*91f16700Schasinglulu static enum stm32_saes_key_selection select_key(unsigned int key_flags)
562*91f16700Schasinglulu {
563*91f16700Schasinglulu 	if ((key_flags & ENC_KEY_IS_IDENTIFIER) != 0U) {
564*91f16700Schasinglulu 		panic();
565*91f16700Schasinglulu 	}
566*91f16700Schasinglulu 
567*91f16700Schasinglulu 	/* Use the provided key buffer */
568*91f16700Schasinglulu 	return STM32_SAES_KEY_SOFT;
569*91f16700Schasinglulu }
570*91f16700Schasinglulu 
571*91f16700Schasinglulu static int stm32_decrypt_aes_gcm(void *data, size_t data_len,
572*91f16700Schasinglulu 				 const void *key, unsigned int key_len,
573*91f16700Schasinglulu 				 unsigned int key_flags,
574*91f16700Schasinglulu 				 const void *iv, unsigned int iv_len,
575*91f16700Schasinglulu 				 const void *tag, unsigned int tag_len)
576*91f16700Schasinglulu {
577*91f16700Schasinglulu 	int ret;
578*91f16700Schasinglulu 	struct stm32_saes_context ctx;
579*91f16700Schasinglulu 	unsigned char tag_buf[CRYPTO_MAX_TAG_SIZE];
580*91f16700Schasinglulu 	enum stm32_saes_key_selection key_mode;
581*91f16700Schasinglulu 	unsigned int diff = 0U;
582*91f16700Schasinglulu 	unsigned int i;
583*91f16700Schasinglulu 
584*91f16700Schasinglulu 	key_mode = select_key(key_flags);
585*91f16700Schasinglulu 
586*91f16700Schasinglulu 	ret = stm32_saes_init(&ctx, true, STM32_SAES_MODE_GCM, key_mode, key,
587*91f16700Schasinglulu 			      key_len, iv, iv_len);
588*91f16700Schasinglulu 	if (ret != 0) {
589*91f16700Schasinglulu 		return CRYPTO_ERR_INIT;
590*91f16700Schasinglulu 	}
591*91f16700Schasinglulu 
592*91f16700Schasinglulu 	ret = stm32_saes_update_assodata(&ctx, true, NULL, 0U);
593*91f16700Schasinglulu 	if (ret != 0) {
594*91f16700Schasinglulu 		return CRYPTO_ERR_DECRYPTION;
595*91f16700Schasinglulu 	}
596*91f16700Schasinglulu 
597*91f16700Schasinglulu 	ret = stm32_saes_update_load(&ctx, true, data, data, data_len);
598*91f16700Schasinglulu 	if (ret != 0) {
599*91f16700Schasinglulu 		return CRYPTO_ERR_DECRYPTION;
600*91f16700Schasinglulu 	}
601*91f16700Schasinglulu 
602*91f16700Schasinglulu 	ret = stm32_saes_final(&ctx, tag_buf, sizeof(tag_buf));
603*91f16700Schasinglulu 	if (ret != 0) {
604*91f16700Schasinglulu 		return CRYPTO_ERR_DECRYPTION;
605*91f16700Schasinglulu 	}
606*91f16700Schasinglulu 
607*91f16700Schasinglulu 	/* Check tag in "constant-time" */
608*91f16700Schasinglulu 	for (i = 0U; i < tag_len; i++) {
609*91f16700Schasinglulu 		diff |= ((const unsigned char *)tag)[i] ^ tag_buf[i];
610*91f16700Schasinglulu 	}
611*91f16700Schasinglulu 
612*91f16700Schasinglulu 	if (diff != 0U) {
613*91f16700Schasinglulu 		return CRYPTO_ERR_DECRYPTION;
614*91f16700Schasinglulu 	}
615*91f16700Schasinglulu 
616*91f16700Schasinglulu 	return CRYPTO_SUCCESS;
617*91f16700Schasinglulu }
618*91f16700Schasinglulu 
619*91f16700Schasinglulu /*
620*91f16700Schasinglulu  * Authenticated decryption of an image
621*91f16700Schasinglulu  *
622*91f16700Schasinglulu  */
623*91f16700Schasinglulu static int crypto_auth_decrypt(enum crypto_dec_algo dec_algo, void *data_ptr, size_t len,
624*91f16700Schasinglulu 			       const void *key, unsigned int key_len, unsigned int key_flags,
625*91f16700Schasinglulu 			       const void *iv, unsigned int iv_len, const void *tag,
626*91f16700Schasinglulu 			       unsigned int tag_len)
627*91f16700Schasinglulu {
628*91f16700Schasinglulu 	int rc = -1;
629*91f16700Schasinglulu 	uint32_t real_iv[4];
630*91f16700Schasinglulu 
631*91f16700Schasinglulu 	switch (dec_algo) {
632*91f16700Schasinglulu 	case CRYPTO_GCM_DECRYPT:
633*91f16700Schasinglulu 		/*
634*91f16700Schasinglulu 		 * GCM expect a Nonce
635*91f16700Schasinglulu 		 * The AES IV is the nonce (a uint32_t[3])
636*91f16700Schasinglulu 		 * then a counter (a uint32_t big endian)
637*91f16700Schasinglulu 		 * The counter starts at 2.
638*91f16700Schasinglulu 		 */
639*91f16700Schasinglulu 		memcpy(real_iv, iv, iv_len);
640*91f16700Schasinglulu 		real_iv[3] = htobe32(0x2U);
641*91f16700Schasinglulu 
642*91f16700Schasinglulu 		rc = stm32_decrypt_aes_gcm(data_ptr, len, key, key_len, key_flags,
643*91f16700Schasinglulu 					   real_iv, sizeof(real_iv), tag, tag_len);
644*91f16700Schasinglulu 		break;
645*91f16700Schasinglulu 	default:
646*91f16700Schasinglulu 		rc = CRYPTO_ERR_DECRYPTION;
647*91f16700Schasinglulu 		break;
648*91f16700Schasinglulu 	}
649*91f16700Schasinglulu 
650*91f16700Schasinglulu 	if (rc != 0) {
651*91f16700Schasinglulu 		return rc;
652*91f16700Schasinglulu 	}
653*91f16700Schasinglulu 
654*91f16700Schasinglulu 	return CRYPTO_SUCCESS;
655*91f16700Schasinglulu }
656*91f16700Schasinglulu 
657*91f16700Schasinglulu REGISTER_CRYPTO_LIB("stm32_crypto_lib",
658*91f16700Schasinglulu 		    crypto_lib_init,
659*91f16700Schasinglulu 		    crypto_verify_signature,
660*91f16700Schasinglulu 		    crypto_verify_hash,
661*91f16700Schasinglulu 		    NULL,
662*91f16700Schasinglulu 		    crypto_auth_decrypt,
663*91f16700Schasinglulu 		    crypto_convert_pk);
664*91f16700Schasinglulu 
665*91f16700Schasinglulu #else /* No decryption support */
666*91f16700Schasinglulu REGISTER_CRYPTO_LIB("stm32_crypto_lib",
667*91f16700Schasinglulu 		    crypto_lib_init,
668*91f16700Schasinglulu 		    crypto_verify_signature,
669*91f16700Schasinglulu 		    crypto_verify_hash,
670*91f16700Schasinglulu 		    NULL,
671*91f16700Schasinglulu 		    NULL,
672*91f16700Schasinglulu 		    crypto_convert_pk);
673*91f16700Schasinglulu #endif
674