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
algo_to_pka_cid(uint32_t algo,enum stm32_pka_curve_id * cid)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
curve_to_pka_cid(uint32_t curve,enum stm32_pka_curve_id * cid)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
stm32_gen_keypair(struct ecc_keypair * key,size_t size_bits)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
sign(uint32_t algo,struct ecc_keypair * key,const uint8_t * msg,size_t msg_size,uint8_t * sig,size_t * sig_len)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
stm32_sign(struct drvcrypt_sign_data * sdata)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
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 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
stm32_verify(struct drvcrypt_sign_data * sdata)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
stm32_alloc_keypair(struct ecc_keypair * s,uint32_t type,size_t size_bits __unused)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
stm32_alloc_publickey(struct ecc_public_key * s,uint32_t type,size_t size_bits __unused)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
stm32_free_publickey(struct ecc_public_key * s)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
is_point_on_curve(struct stm32_pka_point * point,enum stm32_pka_curve_id cid)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
shared_secret(struct ecc_keypair * private_key,struct ecc_public_key * public_key,void * secret,size_t * secret_len)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
stm32_shared_secret(struct drvcrypt_secret_data * sdata)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
stm32_register_ecc(void)503 TEE_Result stm32_register_ecc(void)
504 {
505 return drvcrypt_register_ecc(&driver_ecc);
506 }
507