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