diff options
author | Jorge Ramirez-Ortiz | 2020-12-15 11:59:30 -0600 |
---|---|---|
committer | Jérôme Forissier | 2021-01-05 05:31:29 -0600 |
commit | 9b5917c9e852571e99343ba83791d3c15d1431fa (patch) | |
tree | 310da22ab4d07a0ba14b74d51811ca69e02de752 | |
parent | d419b2b23d8e3ff143693519429fb528d951b276 (diff) | |
download | ti-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.c | 628 |
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 | |||
21 | static 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 | |||
40 | static 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 | |||
55 | static 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 | |||
74 | static 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 | |||
93 | static bool bn_alloc_max(struct bignum **s) | ||
94 | { | ||
95 | *s = crypto_bignum_allocate(4096); | ||
96 | |||
97 | return *s; | ||
98 | } | ||
99 | |||
100 | static 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 | |||
150 | static 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 | |||
176 | static 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 | |||
202 | static 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 | |||
248 | static 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 | |||
314 | static 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 | |||
370 | static 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); | ||
417 | exit: | ||
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 | |||
426 | static 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; | ||
471 | exit: | ||
472 | sss_se05x_key_store_erase_key(se050_kstore, &kobject); | ||
473 | sss_se05x_asymmetric_context_free(&ctx); | ||
474 | |||
475 | return res; | ||
476 | } | ||
477 | |||
478 | static 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 | |||
538 | static TEE_Result do_gen_keypair(struct ecc_keypair *key, size_t size_bytes) | ||
539 | { | ||
540 | return gen_keypair(key, size_bytes); | ||
541 | } | ||
542 | |||
543 | static 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 | |||
551 | static 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 | |||
561 | static 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 | |||
571 | static 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; | ||
582 | err: | ||
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 | |||
589 | static 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; | ||
598 | err: | ||
599 | crypto_bignum_free(s->x); | ||
600 | crypto_bignum_free(s->y); | ||
601 | return TEE_ERROR_OUT_OF_MEMORY; | ||
602 | } | ||
603 | |||
604 | static 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 | |||
613 | static 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 | |||
623 | static TEE_Result ecc_init(void) | ||
624 | { | ||
625 | return drvcrypt_register_ecc(&driver_ecc); | ||
626 | } | ||
627 | |||
628 | driver_init_late(ecc_init); | ||