aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJorge Ramirez-Ortiz2020-12-15 11:59:30 -0600
committerJérôme Forissier2021-01-05 05:31:29 -0600
commit9b5917c9e852571e99343ba83791d3c15d1431fa (patch)
tree310da22ab4d07a0ba14b74d51811ca69e02de752
parentd419b2b23d8e3ff143693519429fb528d951b276 (diff)
downloadti-optee-os-9b5917c9e852571e99343ba83791d3c15d1431fa.tar.gz
ti-optee-os-9b5917c9e852571e99343ba83791d3c15d1431fa.tar.xz
ti-optee-os-9b5917c9e852571e99343ba83791d3c15d1431fa.zip
crypto: se050: core: elliptic curve implementation
Elliptic curve driver. Signed-off-by: Jorge Ramirez-Ortiz <jorge@foundries.io> Acked-by: Jens Wiklander <jens.wiklander@linaro.org> Acked-by: Etienne Carriere <etienne.carriere@linaro.org>
-rw-r--r--core/drivers/crypto/se050/core/ecc.c628
1 files changed, 628 insertions, 0 deletions
diff --git a/core/drivers/crypto/se050/core/ecc.c b/core/drivers/crypto/se050/core/ecc.c
new file mode 100644
index 000000000..12f1b3cd8
--- /dev/null
+++ b/core/drivers/crypto/se050/core/ecc.c
@@ -0,0 +1,628 @@
1// SPDX-License-Identifier: BSD-2-Clause
2/*
3 * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved
4 * Author: Jorge Ramirez <jorge@foundries.io>
5 */
6
7#include <assert.h>
8#include <der.h>
9#include <drvcrypt.h>
10#include <drvcrypt_acipher.h>
11#include <drvcrypt_math.h>
12#include <initcall.h>
13#include <se050.h>
14#include <string.h>
15#include <tee/cache.h>
16#include <tee/tee_cryp_utl.h>
17#include <tee_api_defines_extensions.h>
18#include <utee_defines.h>
19#include <util.h>
20
21static uint32_t algo_tee2se050(uint32_t algo)
22{
23 switch (algo) {
24 case TEE_ALG_ECDSA_P192:
25 return kAlgorithm_SSS_ECDSA_SHA1;
26 case TEE_ALG_ECDSA_P224:
27 return kAlgorithm_SSS_ECDSA_SHA224;
28 case TEE_ALG_ECDSA_P256:
29 return kAlgorithm_SSS_ECDSA_SHA256;
30 case TEE_ALG_ECDSA_P384:
31 return kAlgorithm_SSS_ECDSA_SHA384;
32 case TEE_ALG_ECDSA_P521:
33 return kAlgorithm_SSS_ECDSA_SHA512;
34 default:
35 EMSG("algorithm %#"PRIx32" not enabled", algo);
36 return kAlgorithm_None;
37 }
38}
39
40static uint32_t cipher_tee2se050(uint32_t curve)
41{
42 switch (curve) {
43 case TEE_ECC_CURVE_NIST_P192:
44 case TEE_ECC_CURVE_NIST_P224:
45 case TEE_ECC_CURVE_NIST_P256:
46 case TEE_ECC_CURVE_NIST_P384:
47 case TEE_ECC_CURVE_NIST_P521:
48 return kSSS_CipherType_EC_NIST_P;
49 default:
50 EMSG("cipher %#"PRIx32" not enabled", curve);
51 return kSSS_CipherType_NONE;
52 }
53}
54
55static uint32_t curve_tee2se050(uint32_t curve)
56{
57 switch (curve) {
58 case TEE_ECC_CURVE_NIST_P192:
59 return kSE05x_ECCurve_NIST_P192;
60 case TEE_ECC_CURVE_NIST_P224:
61 return kSE05x_ECCurve_NIST_P224;
62 case TEE_ECC_CURVE_NIST_P256:
63 return kSE05x_ECCurve_NIST_P256;
64 case TEE_ECC_CURVE_NIST_P384:
65 return kSE05x_ECCurve_NIST_P384;
66 case TEE_ECC_CURVE_NIST_P521:
67 return kSE05x_ECCurve_NIST_P521;
68 default:
69 EMSG("curve %#"PRIx32" not enabled", curve);
70 return kSE05x_ECCurve_NA;
71 }
72}
73
74static uint32_t curve_se0502tee(uint32_t curve)
75{
76 switch (curve) {
77 case kSE05x_ECCurve_NIST_P192:
78 return TEE_ECC_CURVE_NIST_P192;
79 case kSE05x_ECCurve_NIST_P224:
80 return TEE_ECC_CURVE_NIST_P224;
81 case kSE05x_ECCurve_NIST_P256:
82 return TEE_ECC_CURVE_NIST_P256;
83 case kSE05x_ECCurve_NIST_P384:
84 return TEE_ECC_CURVE_NIST_P384;
85 case kSE05x_ECCurve_NIST_P521:
86 return TEE_ECC_CURVE_NIST_P521;
87 default:
88 EMSG("curve %#"PRIx32" not enabled", curve);
89 return TEE_CRYPTO_ELEMENT_NONE;
90 }
91}
92
93static bool bn_alloc_max(struct bignum **s)
94{
95 *s = crypto_bignum_allocate(4096);
96
97 return *s;
98}
99
100static TEE_Result ecc_get_key_size(uint32_t curve, uint32_t algo,
101 size_t *bytes, size_t *bits)
102{
103 /*
104 * Note GPv1.1 indicates TEE_ALG_ECDH_NIST_P192_DERIVE_SHARED_SECRET
105 * but defines TEE_ALG_ECDH_P192
106 */
107 switch (curve) {
108 case TEE_ECC_CURVE_NIST_P192:
109 *bits = 192;
110 *bytes = 24;
111 if (algo && algo != TEE_ALG_ECDSA_P192 &&
112 algo != TEE_ALG_ECDH_P192)
113 return TEE_ERROR_BAD_PARAMETERS;
114 break;
115 case TEE_ECC_CURVE_NIST_P224:
116 *bits = 224;
117 *bytes = 28;
118 if (algo && algo != TEE_ALG_ECDSA_P224 &&
119 algo != TEE_ALG_ECDH_P224)
120 return TEE_ERROR_BAD_PARAMETERS;
121 break;
122 case TEE_ECC_CURVE_NIST_P256:
123 *bits = 256;
124 *bytes = 32;
125 if (algo && algo != TEE_ALG_ECDSA_P256 &&
126 algo != TEE_ALG_ECDH_P256)
127 return TEE_ERROR_BAD_PARAMETERS;
128 break;
129 case TEE_ECC_CURVE_NIST_P384:
130 *bits = 384;
131 *bytes = 48;
132 if (algo && algo != TEE_ALG_ECDSA_P384 &&
133 algo != TEE_ALG_ECDH_P384)
134 return TEE_ERROR_BAD_PARAMETERS;
135 break;
136 case TEE_ECC_CURVE_NIST_P521:
137 *bits = 521;
138 *bytes = 66;
139 if (algo && algo != TEE_ALG_ECDSA_P521 &&
140 algo != TEE_ALG_ECDH_P521)
141 return TEE_ERROR_BAD_PARAMETERS;
142 break;
143 default:
144 return TEE_ERROR_NOT_SUPPORTED;
145 }
146
147 return TEE_SUCCESS;
148}
149
150static TEE_Result ecc_get_msg_size(uint32_t algo, size_t *len)
151{
152 switch (algo) {
153 case kAlgorithm_SSS_ECDSA_SHA1:
154 *len = MIN((size_t)TEE_SHA1_HASH_SIZE, *len);
155 break;
156 case kAlgorithm_SSS_ECDSA_SHA224:
157 *len = MIN((size_t)TEE_SHA224_HASH_SIZE, *len);
158 break;
159 case kAlgorithm_SSS_ECDSA_SHA256:
160 *len = MIN((size_t)TEE_SHA256_HASH_SIZE, *len);
161 break;
162 case kAlgorithm_SSS_ECDSA_SHA384:
163 *len = MIN((size_t)TEE_SHA384_HASH_SIZE, *len);
164 break;
165 case kAlgorithm_SSS_ECDSA_SHA512:
166 *len = MIN((size_t)TEE_SHA512_HASH_SIZE, *len);
167 break;
168 default:
169 EMSG("invalid se050 %#"PRIx32" algorithm", algo);
170 return TEE_ERROR_BAD_PARAMETERS;
171 }
172
173 return TEE_SUCCESS;
174}
175
176static TEE_Result set_binary_data(struct bignum *b, size_t key_len, uint8_t **p,
177 size_t *len)
178{
179 size_t a = crypto_bignum_num_bytes(b);
180 uint8_t leading_zeros = 0;
181 uint8_t *q = NULL;
182
183 if (!a)
184 return TEE_ERROR_GENERIC;
185
186 if (a != key_len) {
187 leading_zeros = key_len - a;
188 a = key_len;
189 }
190
191 q = calloc(1, a);
192 if (!q)
193 return TEE_ERROR_OUT_OF_MEMORY;
194
195 crypto_bignum_bn2bin(b, q + leading_zeros);
196 *len = a;
197 *p = q;
198
199 return TEE_SUCCESS;
200}
201
202static TEE_Result se050_inject_public_key(sss_se05x_object_t *k_object,
203 struct ecc_public_key *key,
204 size_t key_len)
205{
206 struct se050_ecc_keypub key_bin = { };
207 TEE_Result ret = TEE_ERROR_GENERIC;
208 sss_status_t st = kStatus_SSS_Fail;
209 uint32_t oid = 0;
210
211 st = sss_se05x_key_object_init(k_object, se050_kstore);
212 if (st != kStatus_SSS_Success)
213 return TEE_ERROR_BAD_PARAMETERS;
214
215 st = se050_get_oid(kKeyObject_Mode_Transient, &oid);
216 if (st != kStatus_SSS_Success)
217 return TEE_ERROR_GENERIC;
218
219 st = sss_se05x_key_object_allocate_handle(k_object, oid,
220 kSSS_KeyPart_Public,
221 cipher_tee2se050(key->curve),
222 0,
223 kKeyObject_Mode_Transient);
224 if (st != kStatus_SSS_Success)
225 return TEE_ERROR_BAD_PARAMETERS;
226
227 ret = set_binary_data(key->x, key_len, &key_bin.x, &key_bin.x_len);
228 if (ret != TEE_SUCCESS)
229 return ret;
230
231 ret = set_binary_data(key->y, key_len, &key_bin.y, &key_bin.y_len);
232 if (ret != TEE_SUCCESS) {
233 free(key_bin.x);
234 return ret;
235 }
236
237 key_bin.curve = curve_tee2se050(key->curve);
238 st = se050_key_store_set_ecc_key_bin(se050_kstore, k_object, NULL,
239 &key_bin);
240 free(key_bin.x);
241 free(key_bin.y);
242 if (st != kStatus_SSS_Success)
243 return TEE_ERROR_BAD_PARAMETERS;
244
245 return TEE_SUCCESS;
246}
247
248static TEE_Result se050_inject_keypair(sss_se05x_object_t *k_object,
249 struct ecc_keypair *key,
250 size_t key_len)
251{
252 struct se050_ecc_keypair key_bin = { };
253 sss_status_t st = kStatus_SSS_Fail;
254 TEE_Result ret = TEE_ERROR_GENERIC;
255 uint32_t key_id = 0;
256 uint32_t oid = 0;
257
258 st = sss_se05x_key_object_init(k_object, se050_kstore);
259 if (st != kStatus_SSS_Success)
260 return TEE_ERROR_BAD_PARAMETERS;
261
262 key_id = se050_ecc_keypair_from_nvm(key);
263 if (key_id) {
264 st = sss_se05x_key_object_get_handle(k_object, key_id);
265 if (st != kStatus_SSS_Success)
266 return TEE_ERROR_BAD_PARAMETERS;
267
268 return TEE_SUCCESS;
269 }
270
271 st = se050_get_oid(kKeyObject_Mode_Transient, &oid);
272 if (st != kStatus_SSS_Success)
273 return TEE_ERROR_GENERIC;
274
275 st = sss_se05x_key_object_allocate_handle(k_object, oid,
276 kSSS_KeyPart_Pair,
277 cipher_tee2se050(key->curve),
278 0,
279 kKeyObject_Mode_Transient);
280 if (st != kStatus_SSS_Success)
281 return TEE_ERROR_BAD_PARAMETERS;
282
283 ret = set_binary_data(key->d, key_len, &key_bin.d, &key_bin.d_len);
284 if (ret != TEE_SUCCESS)
285 return ret;
286
287 ret = set_binary_data(key->x, key_len,
288 &key_bin.pub.x, &key_bin.pub.x_len);
289 if (ret != TEE_SUCCESS) {
290 free(key_bin.d);
291 return ret;
292 }
293
294 ret = set_binary_data(key->y, key_len,
295 &key_bin.pub.y, &key_bin.pub.y_len);
296 if (ret != TEE_SUCCESS) {
297 free(key_bin.d);
298 free(key_bin.pub.x);
299 return ret;
300 }
301
302 key_bin.pub.curve = curve_tee2se050(key->curve);
303 st = se050_key_store_set_ecc_key_bin(se050_kstore, k_object, &key_bin,
304 NULL);
305 free(key_bin.d);
306 free(key_bin.pub.x);
307 free(key_bin.pub.y);
308 if (st != kStatus_SSS_Success)
309 return TEE_ERROR_BAD_PARAMETERS;
310
311 return TEE_SUCCESS;
312}
313
314static TEE_Result shared_secret(struct ecc_keypair *private_key,
315 struct ecc_public_key *public_key,
316 void *secret, size_t *secret_len)
317{
318 struct se050_ecc_keypub key = { };
319 sss_status_t st = kStatus_SSS_Fail;
320 TEE_Result ret = TEE_SUCCESS;
321 size_t key_bits = 0;
322 size_t key_bytes = 0;
323 size_t x1_len = 0;
324 size_t y1_len = 0;
325 size_t x2_len = 0;
326 uint32_t kid = 0;
327
328 if (private_key->curve != public_key->curve)
329 return TEE_ERROR_BAD_PARAMETERS;
330
331 kid = se050_ecc_keypair_from_nvm(private_key);
332 if (!kid) {
333 EMSG("private key must be stored in SE050 flash");
334 return TEE_ERROR_BAD_PARAMETERS;
335 }
336
337 /* validate input parameters */
338 x1_len = crypto_bignum_num_bytes(private_key->x);
339 y1_len = crypto_bignum_num_bytes(private_key->y);
340 x2_len = crypto_bignum_num_bytes(public_key->x);
341
342 ret = ecc_get_key_size(public_key->curve, 0, &key_bytes, &key_bits);
343 if (ret != TEE_SUCCESS)
344 return ret;
345
346 if (x1_len != y1_len || x1_len != key_bytes || x1_len != x2_len)
347 return TEE_ERROR_BAD_PARAMETERS;
348
349 /* prepare the public key (must be in raw format) */
350 ret = set_binary_data(public_key->x, x1_len, &key.x, &key.x_len);
351 if (ret != TEE_SUCCESS)
352 return ret;
353
354 ret = set_binary_data(public_key->y, y1_len, &key.y, &key.y_len);
355 if (ret != TEE_SUCCESS) {
356 free(key.x);
357 return ret;
358 }
359
360 st = se050_ecc_gen_shared_secret(&se050_session->s_ctx, kid, &key,
361 secret, secret_len);
362 free(key.x);
363 free(key.y);
364 if (st != kStatus_SSS_Success)
365 return TEE_ERROR_BAD_PARAMETERS;
366
367 return TEE_SUCCESS;
368}
369
370static TEE_Result sign(uint32_t algo, struct ecc_keypair *key,
371 const uint8_t *msg, size_t msg_len,
372 uint8_t *sig, size_t *sig_len)
373{
374 sss_status_t st = kStatus_SSS_Fail;
375 sss_se05x_asymmetric_t ctx = { };
376 sss_se05x_object_t kobject = { };
377 TEE_Result res = TEE_SUCCESS;
378 size_t key_bytes = 0;
379 size_t key_bits = 0;
380
381 res = ecc_get_key_size(key->curve, algo, &key_bytes, &key_bits);
382 if (res != TEE_SUCCESS)
383 goto exit;
384
385 /* se050 exports DER format */
386 if (*sig_len < (2 * key_bytes + DER_SIGNATURE_SZ)) {
387 *sig_len = 2 * key_bytes + DER_SIGNATURE_SZ;
388 res = TEE_ERROR_SHORT_BUFFER;
389 goto exit;
390 }
391
392 res = ecc_get_msg_size(algo_tee2se050(algo), &msg_len);
393 if (res != TEE_SUCCESS)
394 goto exit;
395
396 res = se050_inject_keypair(&kobject, key, key_bytes);
397 if (res != TEE_SUCCESS)
398 goto exit;
399
400 st = sss_se05x_asymmetric_context_init(&ctx, se050_session, &kobject,
401 algo_tee2se050(algo),
402 kMode_SSS_Sign);
403 if (st != kStatus_SSS_Success) {
404 res = TEE_ERROR_BAD_PARAMETERS;
405 goto exit;
406 }
407
408 st = sss_se05x_asymmetric_sign_digest(&ctx, (uint8_t *)msg, msg_len,
409 sig, sig_len);
410 if (st != kStatus_SSS_Success) {
411 EMSG("curve: %#"PRIx32, key->curve);
412 res = TEE_ERROR_BAD_PARAMETERS;
413 goto exit;
414 }
415
416 sss_se05x_signature_der2bin(sig, sig_len);
417exit:
418 if (!se050_ecc_keypair_from_nvm(key))
419 sss_se05x_key_store_erase_key(se050_kstore, &kobject);
420
421 sss_se05x_asymmetric_context_free(&ctx);
422
423 return res;
424}
425
426static TEE_Result verify(uint32_t algo, struct ecc_public_key *key,
427 const uint8_t *msg, size_t msg_len,
428 const uint8_t *sig, size_t sig_len)
429{
430 sss_status_t st = kStatus_SSS_Fail;
431 sss_se05x_asymmetric_t ctx = { };
432 sss_se05x_object_t kobject = { };
433 TEE_Result res = TEE_SUCCESS;
434 uint8_t signature[128];
435 size_t signature_len = sizeof(signature);
436 size_t key_bytes = 0;
437 size_t key_bits = 0;
438
439 res = ecc_get_key_size(key->curve, algo, &key_bytes, &key_bits);
440 if (res != TEE_SUCCESS)
441 goto exit;
442
443 res = ecc_get_msg_size(algo_tee2se050(algo), &msg_len);
444 if (res != TEE_SUCCESS)
445 goto exit;
446
447 res = se050_inject_public_key(&kobject, key, key_bytes);
448 if (res != TEE_SUCCESS)
449 goto exit;
450
451 st = sss_se05x_asymmetric_context_init(&ctx, se050_session, &kobject,
452 algo_tee2se050(algo),
453 kMode_SSS_Verify);
454 if (st != kStatus_SSS_Success) {
455 res = TEE_ERROR_BAD_PARAMETERS;
456 goto exit;
457 }
458
459 st = sss_se05x_signature_bin2der(signature, &signature_len,
460 (uint8_t *)sig, sig_len);
461 if (st != kStatus_SSS_Success) {
462 res = TEE_ERROR_BAD_PARAMETERS;
463 goto exit;
464 }
465
466 st = sss_se05x_asymmetric_verify_digest(&ctx, (uint8_t *)msg, msg_len,
467 (uint8_t *)signature,
468 signature_len);
469 if (st != kStatus_SSS_Success)
470 res = TEE_ERROR_SIGNATURE_INVALID;
471exit:
472 sss_se05x_key_store_erase_key(se050_kstore, &kobject);
473 sss_se05x_asymmetric_context_free(&ctx);
474
475 return res;
476}
477
478static TEE_Result gen_keypair(struct ecc_keypair *key, size_t key_size __unused)
479{
480 sss_status_t st = kStatus_SSS_Fail;
481 sss_se05x_object_t k_object = { };
482 TEE_Result ret = TEE_SUCCESS;
483 uint8_t kf[512] = { };
484 uint32_t oid = 0;
485 uint64_t kid = 0;
486 size_t bytes = 0;
487 size_t bits = 0;
488
489 ret = ecc_get_key_size(key->curve, 0, &bytes, &bits);
490 if (ret)
491 return ret;
492
493 st = sss_se05x_key_object_init(&k_object, se050_kstore);
494 if (st != kStatus_SSS_Success)
495 return TEE_ERROR_BAD_PARAMETERS;
496
497 st = se050_get_oid(kKeyObject_Mode_Persistent, &oid);
498 if (st != kStatus_SSS_Success)
499 return TEE_ERROR_GENERIC;
500
501 st = sss_se05x_key_object_allocate_handle(&k_object, oid,
502 kSSS_KeyPart_Pair,
503 cipher_tee2se050(key->curve),
504 0,
505 kKeyObject_Mode_Persistent);
506 if (st != kStatus_SSS_Success)
507 return TEE_ERROR_BAD_PARAMETERS;
508
509 st = sss_se05x_key_store_generate_key(se050_kstore, &k_object, bits,
510 &se050_asym_policy);
511 if (st != kStatus_SSS_Success)
512 return TEE_ERROR_BAD_PARAMETERS;
513
514 bytes = sizeof(kf);
515 st = se050_key_store_get_ecc_key_bin(se050_kstore, &k_object, kf,
516 &bytes);
517 if (st != kStatus_SSS_Success) {
518 sss_se05x_key_store_erase_key(se050_kstore, &k_object);
519 return TEE_ERROR_BAD_PARAMETERS;
520 }
521
522 /* skip the DER tag */
523 crypto_bignum_bin2bn(kf + 1, bytes / 2, key->x);
524 crypto_bignum_bin2bn(kf + 1 + bytes / 2, bytes / 2, key->y);
525
526 kid = se050_generate_private_key(oid);
527 crypto_bignum_bin2bn((uint8_t *)&kid, sizeof(kid), key->d);
528 key->curve = curve_se0502tee(k_object.curve_id);
529 if (key->curve != TEE_CRYPTO_ELEMENT_NONE)
530 return TEE_SUCCESS;
531
532 EMSG("ecc key generation failed");
533 sss_se05x_key_store_erase_key(se050_kstore, &k_object);
534
535 return TEE_ERROR_BAD_PARAMETERS;
536}
537
538static TEE_Result do_gen_keypair(struct ecc_keypair *key, size_t size_bytes)
539{
540 return gen_keypair(key, size_bytes);
541}
542
543static TEE_Result do_shared_secret(struct drvcrypt_secret_data *sdata)
544{
545 return shared_secret(sdata->key_priv,
546 sdata->key_pub,
547 sdata->secret.data,
548 &sdata->secret.length);
549}
550
551static TEE_Result do_sign(struct drvcrypt_sign_data *sdata)
552{
553 return sign(sdata->algo,
554 sdata->key,
555 sdata->message.data,
556 sdata->message.length,
557 sdata->signature.data,
558 &sdata->signature.length);
559}
560
561static TEE_Result do_verify(struct drvcrypt_sign_data *sdata)
562{
563 return verify(sdata->algo,
564 sdata->key,
565 sdata->message.data,
566 sdata->message.length,
567 sdata->signature.data,
568 sdata->signature.length);
569}
570
571static TEE_Result do_alloc_keypair(struct ecc_keypair *s,
572 size_t size_bits __unused)
573{
574 memset(s, 0, sizeof(*s));
575 if (!bn_alloc_max(&s->d))
576 goto err;
577 if (!bn_alloc_max(&s->x))
578 goto err;
579 if (!bn_alloc_max(&s->y))
580 goto err;
581 return TEE_SUCCESS;
582err:
583 crypto_bignum_free(s->d);
584 crypto_bignum_free(s->x);
585 crypto_bignum_free(s->y);
586 return TEE_ERROR_OUT_OF_MEMORY;
587}
588
589static TEE_Result do_alloc_publickey(struct ecc_public_key *s,
590 size_t size_bits __unused)
591{
592 memset(s, 0, sizeof(*s));
593 if (!bn_alloc_max(&s->x))
594 goto err;
595 if (!bn_alloc_max(&s->y))
596 goto err;
597 return TEE_SUCCESS;
598err:
599 crypto_bignum_free(s->x);
600 crypto_bignum_free(s->y);
601 return TEE_ERROR_OUT_OF_MEMORY;
602}
603
604static void do_free_publickey(struct ecc_public_key *s)
605{
606 if (!s)
607 return;
608
609 crypto_bignum_free(s->x);
610 crypto_bignum_free(s->y);
611}
612
613static struct drvcrypt_ecc driver_ecc = {
614 .alloc_keypair = do_alloc_keypair,
615 .alloc_publickey = do_alloc_publickey,
616 .free_publickey = do_free_publickey,
617 .gen_keypair = do_gen_keypair,
618 .sign = do_sign,
619 .verify = do_verify,
620 .shared_secret = do_shared_secret,
621};
622
623static TEE_Result ecc_init(void)
624{
625 return drvcrypt_register_ecc(&driver_ecc);
626}
627
628driver_init_late(ecc_init);