xref: /optee_os/core/drivers/crypto/stm32/ecc.c (revision 81f5b20c1e8ca69355a2ca31a61c2990a03c60df)
1*81f5b20cSNicolas Toromanoff // SPDX-License-Identifier: BSD-2-Clause
2*81f5b20cSNicolas Toromanoff /*
3*81f5b20cSNicolas Toromanoff  * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
4*81f5b20cSNicolas Toromanoff  */
5*81f5b20cSNicolas Toromanoff 
6*81f5b20cSNicolas Toromanoff #include <drvcrypt.h>
7*81f5b20cSNicolas Toromanoff #include <drvcrypt_acipher.h>
8*81f5b20cSNicolas Toromanoff #include <initcall.h>
9*81f5b20cSNicolas Toromanoff #include <stdlib_ext.h>
10*81f5b20cSNicolas Toromanoff #include <string.h>
11*81f5b20cSNicolas Toromanoff #include <tee_api_types.h>
12*81f5b20cSNicolas Toromanoff 
13*81f5b20cSNicolas Toromanoff #include "common.h"
14*81f5b20cSNicolas Toromanoff #include "stm32_pka.h"
15*81f5b20cSNicolas Toromanoff 
algo_to_pka_cid(uint32_t algo,enum stm32_pka_curve_id * cid)16*81f5b20cSNicolas Toromanoff static TEE_Result algo_to_pka_cid(uint32_t algo,
17*81f5b20cSNicolas Toromanoff 				  enum stm32_pka_curve_id *cid)
18*81f5b20cSNicolas Toromanoff {
19*81f5b20cSNicolas Toromanoff 	switch (algo) {
20*81f5b20cSNicolas Toromanoff 	case TEE_ALG_ECDSA_P192:
21*81f5b20cSNicolas Toromanoff 		*cid = PKA_NIST_P192;
22*81f5b20cSNicolas Toromanoff 		break;
23*81f5b20cSNicolas Toromanoff 	case TEE_ALG_ECDSA_P224:
24*81f5b20cSNicolas Toromanoff 		*cid = PKA_NIST_P224;
25*81f5b20cSNicolas Toromanoff 		break;
26*81f5b20cSNicolas Toromanoff 	case TEE_ALG_ECDSA_P256:
27*81f5b20cSNicolas Toromanoff 		*cid = PKA_NIST_P256;
28*81f5b20cSNicolas Toromanoff 		break;
29*81f5b20cSNicolas Toromanoff 	case TEE_ALG_ECDSA_P384:
30*81f5b20cSNicolas Toromanoff 		*cid = PKA_NIST_P384;
31*81f5b20cSNicolas Toromanoff 		break;
32*81f5b20cSNicolas Toromanoff 	case TEE_ALG_ECDSA_P521:
33*81f5b20cSNicolas Toromanoff 		*cid = PKA_NIST_P521;
34*81f5b20cSNicolas Toromanoff 		break;
35*81f5b20cSNicolas Toromanoff 	default:
36*81f5b20cSNicolas Toromanoff 		EMSG("algorithm %#"PRIx32" not enabled", algo);
37*81f5b20cSNicolas Toromanoff 		return TEE_ERROR_NOT_SUPPORTED;
38*81f5b20cSNicolas Toromanoff 	}
39*81f5b20cSNicolas Toromanoff 
40*81f5b20cSNicolas Toromanoff 	return TEE_SUCCESS;
41*81f5b20cSNicolas Toromanoff }
42*81f5b20cSNicolas Toromanoff 
curve_to_pka_cid(uint32_t curve,enum stm32_pka_curve_id * cid)43*81f5b20cSNicolas Toromanoff static TEE_Result curve_to_pka_cid(uint32_t curve,
44*81f5b20cSNicolas Toromanoff 				   enum stm32_pka_curve_id *cid)
45*81f5b20cSNicolas Toromanoff {
46*81f5b20cSNicolas Toromanoff 	switch (curve) {
47*81f5b20cSNicolas Toromanoff 	case TEE_ECC_CURVE_NIST_P192:
48*81f5b20cSNicolas Toromanoff 		*cid = PKA_NIST_P192;
49*81f5b20cSNicolas Toromanoff 		break;
50*81f5b20cSNicolas Toromanoff 	case TEE_ECC_CURVE_NIST_P224:
51*81f5b20cSNicolas Toromanoff 		*cid = PKA_NIST_P224;
52*81f5b20cSNicolas Toromanoff 		break;
53*81f5b20cSNicolas Toromanoff 	case TEE_ECC_CURVE_NIST_P256:
54*81f5b20cSNicolas Toromanoff 		*cid = PKA_NIST_P256;
55*81f5b20cSNicolas Toromanoff 		break;
56*81f5b20cSNicolas Toromanoff 	case TEE_ECC_CURVE_NIST_P384:
57*81f5b20cSNicolas Toromanoff 		*cid = PKA_NIST_P384;
58*81f5b20cSNicolas Toromanoff 		break;
59*81f5b20cSNicolas Toromanoff 	case TEE_ECC_CURVE_NIST_P521:
60*81f5b20cSNicolas Toromanoff 		*cid = PKA_NIST_P521;
61*81f5b20cSNicolas Toromanoff 		break;
62*81f5b20cSNicolas Toromanoff 	default:
63*81f5b20cSNicolas Toromanoff 		EMSG("curve %#"PRIx32" not enabled", curve);
64*81f5b20cSNicolas Toromanoff 		return TEE_ERROR_NOT_SUPPORTED;
65*81f5b20cSNicolas Toromanoff 	}
66*81f5b20cSNicolas Toromanoff 
67*81f5b20cSNicolas Toromanoff 	return TEE_SUCCESS;
68*81f5b20cSNicolas Toromanoff }
69*81f5b20cSNicolas Toromanoff 
stm32_gen_keypair(struct ecc_keypair * key,size_t size_bits)70*81f5b20cSNicolas Toromanoff static TEE_Result stm32_gen_keypair(struct ecc_keypair *key, size_t size_bits)
71*81f5b20cSNicolas Toromanoff {
72*81f5b20cSNicolas Toromanoff 	TEE_Result res = TEE_ERROR_GENERIC;
73*81f5b20cSNicolas Toromanoff 	struct stm32_pka_bn d = { };
74*81f5b20cSNicolas Toromanoff 	struct stm32_pka_point pk = { };
75*81f5b20cSNicolas Toromanoff 	enum stm32_pka_curve_id cid = PKA_LAST_CID;
76*81f5b20cSNicolas Toromanoff 	size_t bytes = 0;
77*81f5b20cSNicolas Toromanoff 
78*81f5b20cSNicolas Toromanoff 	if (!key)
79*81f5b20cSNicolas Toromanoff 		return TEE_ERROR_BAD_PARAMETERS;
80*81f5b20cSNicolas Toromanoff 
81*81f5b20cSNicolas Toromanoff 	FMSG("Using PKA");
82*81f5b20cSNicolas Toromanoff 	res = curve_to_pka_cid(key->curve, &cid);
83*81f5b20cSNicolas Toromanoff 	if (res)
84*81f5b20cSNicolas Toromanoff 		return res;
85*81f5b20cSNicolas Toromanoff 
86*81f5b20cSNicolas Toromanoff 	res = stm32_pka_get_max_size(&bytes, NULL, cid);
87*81f5b20cSNicolas Toromanoff 	if (res)
88*81f5b20cSNicolas Toromanoff 		return res;
89*81f5b20cSNicolas Toromanoff 
90*81f5b20cSNicolas Toromanoff 	if (size_bits > bytes * 8 ||
91*81f5b20cSNicolas Toromanoff 	    crypto_bignum_num_bytes(key->d) > bytes ||
92*81f5b20cSNicolas Toromanoff 	    crypto_bignum_num_bytes(key->x) > bytes ||
93*81f5b20cSNicolas Toromanoff 	    crypto_bignum_num_bytes(key->y) > bytes)
94*81f5b20cSNicolas Toromanoff 		return TEE_ERROR_BAD_PARAMETERS;
95*81f5b20cSNicolas Toromanoff 
96*81f5b20cSNicolas Toromanoff 	d.val = calloc(1, bytes);
97*81f5b20cSNicolas Toromanoff 	d.size = bytes;
98*81f5b20cSNicolas Toromanoff 	if (!d.val)
99*81f5b20cSNicolas Toromanoff 		return TEE_ERROR_OUT_OF_MEMORY;
100*81f5b20cSNicolas Toromanoff 
101*81f5b20cSNicolas Toromanoff 	/* Private key is a random vector */
102*81f5b20cSNicolas Toromanoff 	res = crypto_rng_read(d.val, d.size);
103*81f5b20cSNicolas Toromanoff 	if (res) {
104*81f5b20cSNicolas Toromanoff 		free(d.val);
105*81f5b20cSNicolas Toromanoff 		return res;
106*81f5b20cSNicolas Toromanoff 	}
107*81f5b20cSNicolas Toromanoff 
108*81f5b20cSNicolas Toromanoff 	pk.x.val = calloc(1, bytes);
109*81f5b20cSNicolas Toromanoff 	pk.x.size = bytes;
110*81f5b20cSNicolas Toromanoff 	if (!pk.x.val) {
111*81f5b20cSNicolas Toromanoff 		free(d.val);
112*81f5b20cSNicolas Toromanoff 		return TEE_ERROR_OUT_OF_MEMORY;
113*81f5b20cSNicolas Toromanoff 	}
114*81f5b20cSNicolas Toromanoff 
115*81f5b20cSNicolas Toromanoff 	pk.y.val = calloc(1, bytes);
116*81f5b20cSNicolas Toromanoff 	pk.y.size = bytes;
117*81f5b20cSNicolas Toromanoff 	if (!pk.y.val) {
118*81f5b20cSNicolas Toromanoff 		free(pk.x.val);
119*81f5b20cSNicolas Toromanoff 		free(d.val);
120*81f5b20cSNicolas Toromanoff 		return TEE_ERROR_OUT_OF_MEMORY;
121*81f5b20cSNicolas Toromanoff 	}
122*81f5b20cSNicolas Toromanoff 
123*81f5b20cSNicolas Toromanoff 	res = stm32_pka_edac_gen_pubkey(&d, &pk, cid);
124*81f5b20cSNicolas Toromanoff 	if (res)
125*81f5b20cSNicolas Toromanoff 		goto out;
126*81f5b20cSNicolas Toromanoff 
127*81f5b20cSNicolas Toromanoff 	res = crypto_bignum_bin2bn(d.val, d.size, key->d);
128*81f5b20cSNicolas Toromanoff 	if (res)
129*81f5b20cSNicolas Toromanoff 		goto out;
130*81f5b20cSNicolas Toromanoff 
131*81f5b20cSNicolas Toromanoff 	res = crypto_bignum_bin2bn(pk.x.val, pk.x.size, key->x);
132*81f5b20cSNicolas Toromanoff 	if (res)
133*81f5b20cSNicolas Toromanoff 		goto out;
134*81f5b20cSNicolas Toromanoff 
135*81f5b20cSNicolas Toromanoff 	res = crypto_bignum_bin2bn(pk.y.val, pk.y.size, key->y);
136*81f5b20cSNicolas Toromanoff 
137*81f5b20cSNicolas Toromanoff out:
138*81f5b20cSNicolas Toromanoff 	free(pk.y.val);
139*81f5b20cSNicolas Toromanoff 	free(pk.x.val);
140*81f5b20cSNicolas Toromanoff 	free_wipe(d.val);
141*81f5b20cSNicolas Toromanoff 
142*81f5b20cSNicolas Toromanoff 	return res;
143*81f5b20cSNicolas Toromanoff }
144*81f5b20cSNicolas Toromanoff 
sign(uint32_t algo,struct ecc_keypair * key,const uint8_t * msg,size_t msg_size,uint8_t * sig,size_t * sig_len)145*81f5b20cSNicolas Toromanoff static TEE_Result sign(uint32_t algo, struct ecc_keypair *key,
146*81f5b20cSNicolas Toromanoff 		       const uint8_t *msg, size_t msg_size,
147*81f5b20cSNicolas Toromanoff 		       uint8_t *sig, size_t *sig_len)
148*81f5b20cSNicolas Toromanoff {
149*81f5b20cSNicolas Toromanoff 	TEE_Result res = TEE_ERROR_GENERIC;
150*81f5b20cSNicolas Toromanoff 	enum stm32_pka_curve_id cid_from_algo = PKA_LAST_CID;
151*81f5b20cSNicolas Toromanoff 	enum stm32_pka_curve_id cid = PKA_LAST_CID;
152*81f5b20cSNicolas Toromanoff 	struct stm32_pka_bn d = { };
153*81f5b20cSNicolas Toromanoff 	struct stm32_pka_bn k = { };
154*81f5b20cSNicolas Toromanoff 	struct stm32_pka_bn sig_r = { };
155*81f5b20cSNicolas Toromanoff 	struct stm32_pka_bn sig_s = { };
156*81f5b20cSNicolas Toromanoff 	size_t bytes = 0;
157*81f5b20cSNicolas Toromanoff 
158*81f5b20cSNicolas Toromanoff 	if (!key || !msg || !sig || !sig_len)
159*81f5b20cSNicolas Toromanoff 		return TEE_ERROR_BAD_PARAMETERS;
160*81f5b20cSNicolas Toromanoff 
161*81f5b20cSNicolas Toromanoff 	if (curve_to_pka_cid(key->curve, &cid) ||
162*81f5b20cSNicolas Toromanoff 	    algo_to_pka_cid(algo, &cid_from_algo) ||
163*81f5b20cSNicolas Toromanoff 	    cid_from_algo != cid)
164*81f5b20cSNicolas Toromanoff 		return TEE_ERROR_BAD_PARAMETERS;
165*81f5b20cSNicolas Toromanoff 
166*81f5b20cSNicolas Toromanoff 	res = stm32_pka_get_max_size(&bytes, NULL, cid);
167*81f5b20cSNicolas Toromanoff 	if (res)
168*81f5b20cSNicolas Toromanoff 		return res;
169*81f5b20cSNicolas Toromanoff 
170*81f5b20cSNicolas Toromanoff 	if (crypto_bignum_num_bytes(key->d) > bytes || *sig_len < 2 * bytes)
171*81f5b20cSNicolas Toromanoff 		return TEE_ERROR_BAD_PARAMETERS;
172*81f5b20cSNicolas Toromanoff 
173*81f5b20cSNicolas Toromanoff 	*sig_len = 2 * bytes;
174*81f5b20cSNicolas Toromanoff 
175*81f5b20cSNicolas Toromanoff 	d.size = crypto_bignum_num_bytes(key->d);
176*81f5b20cSNicolas Toromanoff 	d.val = calloc(1, d.size);
177*81f5b20cSNicolas Toromanoff 	if (!d.val)
178*81f5b20cSNicolas Toromanoff 		return TEE_ERROR_OUT_OF_MEMORY;
179*81f5b20cSNicolas Toromanoff 
180*81f5b20cSNicolas Toromanoff 	crypto_bignum_bn2bin(key->d, d.val);
181*81f5b20cSNicolas Toromanoff 
182*81f5b20cSNicolas Toromanoff 	k.val = calloc(1, bytes);
183*81f5b20cSNicolas Toromanoff 	k.size = bytes;
184*81f5b20cSNicolas Toromanoff 	if (!k.val) {
185*81f5b20cSNicolas Toromanoff 		free_wipe(d.val);
186*81f5b20cSNicolas Toromanoff 		return TEE_ERROR_OUT_OF_MEMORY;
187*81f5b20cSNicolas Toromanoff 	}
188*81f5b20cSNicolas Toromanoff 
189*81f5b20cSNicolas Toromanoff 	res = crypto_rng_read(k.val, k.size);
190*81f5b20cSNicolas Toromanoff 	if (res)
191*81f5b20cSNicolas Toromanoff 		goto out;
192*81f5b20cSNicolas Toromanoff 
193*81f5b20cSNicolas Toromanoff 	sig_r.val = (void *)sig;
194*81f5b20cSNicolas Toromanoff 	sig_r.size = bytes;
195*81f5b20cSNicolas Toromanoff 	sig_s.val = (void *)(sig + bytes);
196*81f5b20cSNicolas Toromanoff 	sig_s.size = bytes;
197*81f5b20cSNicolas Toromanoff 
198*81f5b20cSNicolas Toromanoff 	res = stm32_pka_ecdsa_sign(msg, msg_size, &sig_r, &sig_s, &d, &k, cid);
199*81f5b20cSNicolas Toromanoff 
200*81f5b20cSNicolas Toromanoff out:
201*81f5b20cSNicolas Toromanoff 	free_wipe(k.val);
202*81f5b20cSNicolas Toromanoff 	free_wipe(d.val);
203*81f5b20cSNicolas Toromanoff 
204*81f5b20cSNicolas Toromanoff 	return res;
205*81f5b20cSNicolas Toromanoff }
206*81f5b20cSNicolas Toromanoff 
stm32_sign(struct drvcrypt_sign_data * sdata)207*81f5b20cSNicolas Toromanoff static TEE_Result stm32_sign(struct drvcrypt_sign_data *sdata)
208*81f5b20cSNicolas Toromanoff {
209*81f5b20cSNicolas Toromanoff 	if (!sdata)
210*81f5b20cSNicolas Toromanoff 		return TEE_ERROR_BAD_PARAMETERS;
211*81f5b20cSNicolas Toromanoff 
212*81f5b20cSNicolas Toromanoff 	FMSG("Using PKA");
213*81f5b20cSNicolas Toromanoff 	return sign(sdata->algo,
214*81f5b20cSNicolas Toromanoff 		    sdata->key,
215*81f5b20cSNicolas Toromanoff 		    sdata->message.data,
216*81f5b20cSNicolas Toromanoff 		    sdata->message.length,
217*81f5b20cSNicolas Toromanoff 		    sdata->signature.data,
218*81f5b20cSNicolas Toromanoff 		    &sdata->signature.length);
219*81f5b20cSNicolas Toromanoff }
220*81f5b20cSNicolas Toromanoff 
verify(uint32_t algo,struct ecc_public_key * key,const uint8_t * msg,size_t msg_size,const uint8_t * sig,size_t sig_size)221*81f5b20cSNicolas Toromanoff static TEE_Result verify(uint32_t algo, struct ecc_public_key *key,
222*81f5b20cSNicolas Toromanoff 			 const uint8_t *msg, size_t msg_size,
223*81f5b20cSNicolas Toromanoff 			 const uint8_t *sig, size_t sig_size)
224*81f5b20cSNicolas Toromanoff {
225*81f5b20cSNicolas Toromanoff 	TEE_Result res = TEE_ERROR_GENERIC;
226*81f5b20cSNicolas Toromanoff 	struct stm32_pka_bn sig_r = { };
227*81f5b20cSNicolas Toromanoff 	struct stm32_pka_bn sig_s = { };
228*81f5b20cSNicolas Toromanoff 	struct stm32_pka_point pk = { };
229*81f5b20cSNicolas Toromanoff 	enum stm32_pka_curve_id cid_from_algo = PKA_LAST_CID;
230*81f5b20cSNicolas Toromanoff 	enum stm32_pka_curve_id cid = PKA_LAST_CID;
231*81f5b20cSNicolas Toromanoff 	size_t bytes = 0;
232*81f5b20cSNicolas Toromanoff 
233*81f5b20cSNicolas Toromanoff 	if (!key || !msg || !sig)
234*81f5b20cSNicolas Toromanoff 		return TEE_ERROR_BAD_PARAMETERS;
235*81f5b20cSNicolas Toromanoff 
236*81f5b20cSNicolas Toromanoff 	if (curve_to_pka_cid(key->curve, &cid) ||
237*81f5b20cSNicolas Toromanoff 	    algo_to_pka_cid(algo, &cid_from_algo) ||
238*81f5b20cSNicolas Toromanoff 	    cid_from_algo != cid)
239*81f5b20cSNicolas Toromanoff 		return TEE_ERROR_BAD_PARAMETERS;
240*81f5b20cSNicolas Toromanoff 
241*81f5b20cSNicolas Toromanoff 	res = stm32_pka_get_max_size(&bytes, NULL, cid);
242*81f5b20cSNicolas Toromanoff 	if (res)
243*81f5b20cSNicolas Toromanoff 		return res;
244*81f5b20cSNicolas Toromanoff 
245*81f5b20cSNicolas Toromanoff 	if (sig_size % 2)
246*81f5b20cSNicolas Toromanoff 		return TEE_ERROR_BAD_PARAMETERS;
247*81f5b20cSNicolas Toromanoff 
248*81f5b20cSNicolas Toromanoff 	sig_r.val = (void *)sig;
249*81f5b20cSNicolas Toromanoff 	sig_r.size = sig_size / 2;
250*81f5b20cSNicolas Toromanoff 	sig_s.val = (void *)(sig + sig_size / 2);
251*81f5b20cSNicolas Toromanoff 	sig_s.size = sig_size / 2;
252*81f5b20cSNicolas Toromanoff 
253*81f5b20cSNicolas Toromanoff 	pk.x.size = crypto_bignum_num_bytes(key->x);
254*81f5b20cSNicolas Toromanoff 	pk.x.val = calloc(1, pk.x.size);
255*81f5b20cSNicolas Toromanoff 	if (!pk.x.val)
256*81f5b20cSNicolas Toromanoff 		return TEE_ERROR_OUT_OF_MEMORY;
257*81f5b20cSNicolas Toromanoff 
258*81f5b20cSNicolas Toromanoff 	crypto_bignum_bn2bin(key->x, pk.x.val);
259*81f5b20cSNicolas Toromanoff 
260*81f5b20cSNicolas Toromanoff 	pk.y.size = crypto_bignum_num_bytes(key->y);
261*81f5b20cSNicolas Toromanoff 	pk.y.val = calloc(1, pk.y.size);
262*81f5b20cSNicolas Toromanoff 	if (!pk.y.val) {
263*81f5b20cSNicolas Toromanoff 		free(pk.x.val);
264*81f5b20cSNicolas Toromanoff 		return TEE_ERROR_OUT_OF_MEMORY;
265*81f5b20cSNicolas Toromanoff 	}
266*81f5b20cSNicolas Toromanoff 
267*81f5b20cSNicolas Toromanoff 	crypto_bignum_bn2bin(key->y, pk.y.val);
268*81f5b20cSNicolas Toromanoff 
269*81f5b20cSNicolas Toromanoff 	res = stm32_pka_ecdsa_verif(msg, msg_size, &sig_r, &sig_s, &pk, cid);
270*81f5b20cSNicolas Toromanoff 
271*81f5b20cSNicolas Toromanoff 	free(pk.y.val);
272*81f5b20cSNicolas Toromanoff 	free(pk.x.val);
273*81f5b20cSNicolas Toromanoff 
274*81f5b20cSNicolas Toromanoff 	return res;
275*81f5b20cSNicolas Toromanoff }
276*81f5b20cSNicolas Toromanoff 
stm32_verify(struct drvcrypt_sign_data * sdata)277*81f5b20cSNicolas Toromanoff static TEE_Result stm32_verify(struct drvcrypt_sign_data *sdata)
278*81f5b20cSNicolas Toromanoff {
279*81f5b20cSNicolas Toromanoff 	if (!sdata)
280*81f5b20cSNicolas Toromanoff 		return TEE_ERROR_BAD_PARAMETERS;
281*81f5b20cSNicolas Toromanoff 
282*81f5b20cSNicolas Toromanoff 	FMSG("Using PKA");
283*81f5b20cSNicolas Toromanoff 	return verify(sdata->algo,
284*81f5b20cSNicolas Toromanoff 		      sdata->key,
285*81f5b20cSNicolas Toromanoff 		      sdata->message.data,
286*81f5b20cSNicolas Toromanoff 		      sdata->message.length,
287*81f5b20cSNicolas Toromanoff 		      sdata->signature.data,
288*81f5b20cSNicolas Toromanoff 		      sdata->signature.length);
289*81f5b20cSNicolas Toromanoff }
290*81f5b20cSNicolas Toromanoff 
stm32_alloc_keypair(struct ecc_keypair * s,uint32_t type,size_t size_bits __unused)291*81f5b20cSNicolas Toromanoff static TEE_Result stm32_alloc_keypair(struct ecc_keypair *s, uint32_t type,
292*81f5b20cSNicolas Toromanoff 				      size_t size_bits __unused)
293*81f5b20cSNicolas Toromanoff {
294*81f5b20cSNicolas Toromanoff 	if (!s)
295*81f5b20cSNicolas Toromanoff 		return TEE_ERROR_BAD_PARAMETERS;
296*81f5b20cSNicolas Toromanoff 
297*81f5b20cSNicolas Toromanoff 	/* This driver only supports ECDH/ECDSA */
298*81f5b20cSNicolas Toromanoff 	if (type != TEE_TYPE_ECDSA_KEYPAIR &&
299*81f5b20cSNicolas Toromanoff 	    type != TEE_TYPE_ECDH_KEYPAIR)
300*81f5b20cSNicolas Toromanoff 		return TEE_ERROR_NOT_IMPLEMENTED;
301*81f5b20cSNicolas Toromanoff 
302*81f5b20cSNicolas Toromanoff 	FMSG("Using PKA");
303*81f5b20cSNicolas Toromanoff 	memset(s, 0, sizeof(*s));
304*81f5b20cSNicolas Toromanoff 
305*81f5b20cSNicolas Toromanoff 	s->d = crypto_bignum_allocate(PKA_MAX_ECC_LEN);
306*81f5b20cSNicolas Toromanoff 	if (!s->d)
307*81f5b20cSNicolas Toromanoff 		return TEE_ERROR_OUT_OF_MEMORY;
308*81f5b20cSNicolas Toromanoff 
309*81f5b20cSNicolas Toromanoff 	s->x = crypto_bignum_allocate(PKA_MAX_ECC_LEN);
310*81f5b20cSNicolas Toromanoff 	if (!s->x) {
311*81f5b20cSNicolas Toromanoff 		crypto_bignum_free(&s->d);
312*81f5b20cSNicolas Toromanoff 		return TEE_ERROR_OUT_OF_MEMORY;
313*81f5b20cSNicolas Toromanoff 	}
314*81f5b20cSNicolas Toromanoff 
315*81f5b20cSNicolas Toromanoff 	s->y = crypto_bignum_allocate(PKA_MAX_ECC_LEN);
316*81f5b20cSNicolas Toromanoff 	if (!s->y) {
317*81f5b20cSNicolas Toromanoff 		crypto_bignum_free(&s->d);
318*81f5b20cSNicolas Toromanoff 		crypto_bignum_free(&s->x);
319*81f5b20cSNicolas Toromanoff 		return TEE_ERROR_OUT_OF_MEMORY;
320*81f5b20cSNicolas Toromanoff 	}
321*81f5b20cSNicolas Toromanoff 
322*81f5b20cSNicolas Toromanoff 	return TEE_SUCCESS;
323*81f5b20cSNicolas Toromanoff }
324*81f5b20cSNicolas Toromanoff 
stm32_alloc_publickey(struct ecc_public_key * s,uint32_t type,size_t size_bits __unused)325*81f5b20cSNicolas Toromanoff static TEE_Result stm32_alloc_publickey(struct ecc_public_key *s, uint32_t type,
326*81f5b20cSNicolas Toromanoff 					size_t size_bits __unused)
327*81f5b20cSNicolas Toromanoff {
328*81f5b20cSNicolas Toromanoff 	if (!s)
329*81f5b20cSNicolas Toromanoff 		return TEE_ERROR_BAD_PARAMETERS;
330*81f5b20cSNicolas Toromanoff 
331*81f5b20cSNicolas Toromanoff 	/* This driver only supports ECDH/ECDSA */
332*81f5b20cSNicolas Toromanoff 	if (type != TEE_TYPE_ECDSA_PUBLIC_KEY &&
333*81f5b20cSNicolas Toromanoff 	    type != TEE_TYPE_ECDH_PUBLIC_KEY)
334*81f5b20cSNicolas Toromanoff 		return TEE_ERROR_NOT_IMPLEMENTED;
335*81f5b20cSNicolas Toromanoff 
336*81f5b20cSNicolas Toromanoff 	memset(s, 0, sizeof(*s));
337*81f5b20cSNicolas Toromanoff 
338*81f5b20cSNicolas Toromanoff 	s->x = crypto_bignum_allocate(PKA_MAX_ECC_LEN);
339*81f5b20cSNicolas Toromanoff 	if (!s->x)
340*81f5b20cSNicolas Toromanoff 		return TEE_ERROR_OUT_OF_MEMORY;
341*81f5b20cSNicolas Toromanoff 
342*81f5b20cSNicolas Toromanoff 	s->y = crypto_bignum_allocate(PKA_MAX_ECC_LEN);
343*81f5b20cSNicolas Toromanoff 	if (!s->y) {
344*81f5b20cSNicolas Toromanoff 		crypto_bignum_free(&s->x);
345*81f5b20cSNicolas Toromanoff 		return TEE_ERROR_OUT_OF_MEMORY;
346*81f5b20cSNicolas Toromanoff 	}
347*81f5b20cSNicolas Toromanoff 
348*81f5b20cSNicolas Toromanoff 	return TEE_SUCCESS;
349*81f5b20cSNicolas Toromanoff }
350*81f5b20cSNicolas Toromanoff 
stm32_free_publickey(struct ecc_public_key * s)351*81f5b20cSNicolas Toromanoff static void stm32_free_publickey(struct ecc_public_key *s)
352*81f5b20cSNicolas Toromanoff {
353*81f5b20cSNicolas Toromanoff 	if (!s)
354*81f5b20cSNicolas Toromanoff 		return;
355*81f5b20cSNicolas Toromanoff 
356*81f5b20cSNicolas Toromanoff 	FMSG("Using PKA");
357*81f5b20cSNicolas Toromanoff 	crypto_bignum_free(&s->x);
358*81f5b20cSNicolas Toromanoff 	crypto_bignum_free(&s->y);
359*81f5b20cSNicolas Toromanoff }
360*81f5b20cSNicolas Toromanoff 
is_point_on_curve(struct stm32_pka_point * point,enum stm32_pka_curve_id cid)361*81f5b20cSNicolas Toromanoff static TEE_Result is_point_on_curve(struct stm32_pka_point *point,
362*81f5b20cSNicolas Toromanoff 				    enum stm32_pka_curve_id cid)
363*81f5b20cSNicolas Toromanoff {
364*81f5b20cSNicolas Toromanoff 	TEE_Result res = TEE_ERROR_GENERIC;
365*81f5b20cSNicolas Toromanoff 	struct stm32_pka_bn r2modn = { };
366*81f5b20cSNicolas Toromanoff 
367*81f5b20cSNicolas Toromanoff 	res = stm32_pka_get_max_size(&r2modn.size, NULL, cid);
368*81f5b20cSNicolas Toromanoff 	if (res)
369*81f5b20cSNicolas Toromanoff 		return res;
370*81f5b20cSNicolas Toromanoff 
371*81f5b20cSNicolas Toromanoff 	r2modn.val = calloc(1, r2modn.size);
372*81f5b20cSNicolas Toromanoff 	if (!r2modn.val)
373*81f5b20cSNicolas Toromanoff 		return TEE_ERROR_OUT_OF_MEMORY;
374*81f5b20cSNicolas Toromanoff 
375*81f5b20cSNicolas Toromanoff 	res = stm32_pka_ecc_compute_montgomery(&r2modn, cid);
376*81f5b20cSNicolas Toromanoff 	if (res)
377*81f5b20cSNicolas Toromanoff 		goto out;
378*81f5b20cSNicolas Toromanoff 
379*81f5b20cSNicolas Toromanoff 	res = stm32_pka_is_point_on_curve(point, &r2modn, cid);
380*81f5b20cSNicolas Toromanoff out:
381*81f5b20cSNicolas Toromanoff 	free(r2modn.val);
382*81f5b20cSNicolas Toromanoff 
383*81f5b20cSNicolas Toromanoff 	return res;
384*81f5b20cSNicolas Toromanoff }
385*81f5b20cSNicolas Toromanoff 
shared_secret(struct ecc_keypair * private_key,struct ecc_public_key * public_key,void * secret,size_t * secret_len)386*81f5b20cSNicolas Toromanoff static TEE_Result shared_secret(struct ecc_keypair *private_key,
387*81f5b20cSNicolas Toromanoff 				struct ecc_public_key *public_key,
388*81f5b20cSNicolas Toromanoff 				void *secret, size_t *secret_len)
389*81f5b20cSNicolas Toromanoff {
390*81f5b20cSNicolas Toromanoff 	TEE_Result res = TEE_ERROR_GENERIC;
391*81f5b20cSNicolas Toromanoff 	enum stm32_pka_curve_id cid = PKA_LAST_CID;
392*81f5b20cSNicolas Toromanoff 	struct stm32_pka_bn d = { };
393*81f5b20cSNicolas Toromanoff 	struct stm32_pka_point pk = { };
394*81f5b20cSNicolas Toromanoff 	struct stm32_pka_point result = { };
395*81f5b20cSNicolas Toromanoff 	size_t bytes = 0;
396*81f5b20cSNicolas Toromanoff 
397*81f5b20cSNicolas Toromanoff 	if (!private_key || !public_key || !secret || !secret_len)
398*81f5b20cSNicolas Toromanoff 		return TEE_ERROR_BAD_PARAMETERS;
399*81f5b20cSNicolas Toromanoff 
400*81f5b20cSNicolas Toromanoff 	if (private_key->curve != public_key->curve ||
401*81f5b20cSNicolas Toromanoff 	    curve_to_pka_cid(public_key->curve, &cid))
402*81f5b20cSNicolas Toromanoff 		return TEE_ERROR_BAD_PARAMETERS;
403*81f5b20cSNicolas Toromanoff 
404*81f5b20cSNicolas Toromanoff 	res = stm32_pka_get_max_size(&bytes, NULL, cid);
405*81f5b20cSNicolas Toromanoff 	if (res)
406*81f5b20cSNicolas Toromanoff 		return res;
407*81f5b20cSNicolas Toromanoff 
408*81f5b20cSNicolas Toromanoff 	/* Convert provided value to PKA format */
409*81f5b20cSNicolas Toromanoff 	pk.x.size = crypto_bignum_num_bytes(public_key->x);
410*81f5b20cSNicolas Toromanoff 	pk.x.val = calloc(1, pk.x.size);
411*81f5b20cSNicolas Toromanoff 	if (!pk.x.val)
412*81f5b20cSNicolas Toromanoff 		return TEE_ERROR_OUT_OF_MEMORY;
413*81f5b20cSNicolas Toromanoff 
414*81f5b20cSNicolas Toromanoff 	crypto_bignum_bn2bin(public_key->x, pk.x.val);
415*81f5b20cSNicolas Toromanoff 
416*81f5b20cSNicolas Toromanoff 	pk.y.size = crypto_bignum_num_bytes(public_key->y);
417*81f5b20cSNicolas Toromanoff 	pk.y.val = calloc(1, pk.y.size);
418*81f5b20cSNicolas Toromanoff 	if (!pk.y.val) {
419*81f5b20cSNicolas Toromanoff 		res = TEE_ERROR_OUT_OF_MEMORY;
420*81f5b20cSNicolas Toromanoff 		goto out;
421*81f5b20cSNicolas Toromanoff 	}
422*81f5b20cSNicolas Toromanoff 
423*81f5b20cSNicolas Toromanoff 	crypto_bignum_bn2bin(public_key->y, pk.y.val);
424*81f5b20cSNicolas Toromanoff 
425*81f5b20cSNicolas Toromanoff 	d.size = crypto_bignum_num_bytes(private_key->d);
426*81f5b20cSNicolas Toromanoff 	d.val = calloc(1, d.size);
427*81f5b20cSNicolas Toromanoff 	if (!d.val) {
428*81f5b20cSNicolas Toromanoff 		res = TEE_ERROR_OUT_OF_MEMORY;
429*81f5b20cSNicolas Toromanoff 		goto out;
430*81f5b20cSNicolas Toromanoff 	}
431*81f5b20cSNicolas Toromanoff 
432*81f5b20cSNicolas Toromanoff 	crypto_bignum_bn2bin(private_key->d, d.val);
433*81f5b20cSNicolas Toromanoff 
434*81f5b20cSNicolas Toromanoff 	/* Allocate intermediate point */
435*81f5b20cSNicolas Toromanoff 	result.x.size = bytes;
436*81f5b20cSNicolas Toromanoff 	result.x.val = calloc(1, result.x.size);
437*81f5b20cSNicolas Toromanoff 	if (!result.x.val) {
438*81f5b20cSNicolas Toromanoff 		res = TEE_ERROR_OUT_OF_MEMORY;
439*81f5b20cSNicolas Toromanoff 		goto out;
440*81f5b20cSNicolas Toromanoff 	}
441*81f5b20cSNicolas Toromanoff 
442*81f5b20cSNicolas Toromanoff 	result.y.size = bytes;
443*81f5b20cSNicolas Toromanoff 	result.y.val = calloc(1, result.y.size);
444*81f5b20cSNicolas Toromanoff 	if (!result.y.val) {
445*81f5b20cSNicolas Toromanoff 		res = TEE_ERROR_OUT_OF_MEMORY;
446*81f5b20cSNicolas Toromanoff 		goto out;
447*81f5b20cSNicolas Toromanoff 	}
448*81f5b20cSNicolas Toromanoff 
449*81f5b20cSNicolas Toromanoff 	/*
450*81f5b20cSNicolas Toromanoff 	 * We should check that provided public_key point is on the selected
451*81f5b20cSNicolas Toromanoff 	 * curve.
452*81f5b20cSNicolas Toromanoff 	 */
453*81f5b20cSNicolas Toromanoff 	res = is_point_on_curve(&pk, cid);
454*81f5b20cSNicolas Toromanoff 	if (res)
455*81f5b20cSNicolas Toromanoff 		goto out;
456*81f5b20cSNicolas Toromanoff 
457*81f5b20cSNicolas Toromanoff 	res = stm32_pka_ecc_scalar_mul(&d, &pk, &result, cid);
458*81f5b20cSNicolas Toromanoff 	if (res)
459*81f5b20cSNicolas Toromanoff 		goto out;
460*81f5b20cSNicolas Toromanoff 
461*81f5b20cSNicolas Toromanoff 	if (*secret_len < result.x.size) {
462*81f5b20cSNicolas Toromanoff 		res = TEE_ERROR_BAD_PARAMETERS;
463*81f5b20cSNicolas Toromanoff 		goto out;
464*81f5b20cSNicolas Toromanoff 	}
465*81f5b20cSNicolas Toromanoff 
466*81f5b20cSNicolas Toromanoff 	memcpy(secret, result.x.val, result.x.size);
467*81f5b20cSNicolas Toromanoff 	*secret_len = result.x.size;
468*81f5b20cSNicolas Toromanoff out:
469*81f5b20cSNicolas Toromanoff 	free_wipe(result.y.val);
470*81f5b20cSNicolas Toromanoff 	free_wipe(result.x.val);
471*81f5b20cSNicolas Toromanoff 	free_wipe(d.val);
472*81f5b20cSNicolas Toromanoff 	free(pk.y.val);
473*81f5b20cSNicolas Toromanoff 	free(pk.x.val);
474*81f5b20cSNicolas Toromanoff 
475*81f5b20cSNicolas Toromanoff 	return res;
476*81f5b20cSNicolas Toromanoff }
477*81f5b20cSNicolas Toromanoff 
stm32_shared_secret(struct drvcrypt_secret_data * sdata)478*81f5b20cSNicolas Toromanoff static TEE_Result stm32_shared_secret(struct drvcrypt_secret_data *sdata)
479*81f5b20cSNicolas Toromanoff {
480*81f5b20cSNicolas Toromanoff 	if (!sdata)
481*81f5b20cSNicolas Toromanoff 		return TEE_ERROR_BAD_PARAMETERS;
482*81f5b20cSNicolas Toromanoff 
483*81f5b20cSNicolas Toromanoff 	FMSG("Using PKA");
484*81f5b20cSNicolas Toromanoff 	return shared_secret(sdata->key_priv,
485*81f5b20cSNicolas Toromanoff 			     sdata->key_pub,
486*81f5b20cSNicolas Toromanoff 			     sdata->secret.data,
487*81f5b20cSNicolas Toromanoff 			     &sdata->secret.length);
488*81f5b20cSNicolas Toromanoff }
489*81f5b20cSNicolas Toromanoff 
490*81f5b20cSNicolas Toromanoff /*
491*81f5b20cSNicolas Toromanoff  * Registration of the ECC Driver.
492*81f5b20cSNicolas Toromanoff  */
493*81f5b20cSNicolas Toromanoff static struct drvcrypt_ecc driver_ecc = {
494*81f5b20cSNicolas Toromanoff 	.alloc_keypair = stm32_alloc_keypair,
495*81f5b20cSNicolas Toromanoff 	.alloc_publickey = stm32_alloc_publickey,
496*81f5b20cSNicolas Toromanoff 	.free_publickey = stm32_free_publickey,
497*81f5b20cSNicolas Toromanoff 	.gen_keypair = stm32_gen_keypair,
498*81f5b20cSNicolas Toromanoff 	.sign = stm32_sign,
499*81f5b20cSNicolas Toromanoff 	.verify = stm32_verify,
500*81f5b20cSNicolas Toromanoff 	.shared_secret = stm32_shared_secret,
501*81f5b20cSNicolas Toromanoff };
502*81f5b20cSNicolas Toromanoff 
stm32_register_ecc(void)503*81f5b20cSNicolas Toromanoff TEE_Result stm32_register_ecc(void)
504*81f5b20cSNicolas Toromanoff {
505*81f5b20cSNicolas Toromanoff 	return drvcrypt_register_ecc(&driver_ecc);
506*81f5b20cSNicolas Toromanoff }
507