1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright 2018-2021 NXP
4 *
5 * Crypto ECC interface implementation to enable HW driver.
6 */
7 #include <crypto/crypto_impl.h>
8 #include <drvcrypt.h>
9 #include <drvcrypt_acipher.h>
10 #include <utee_defines.h>
11
12 /*
13 * Returns the key size in bytes for the given ECC curve
14 *
15 * @curve ECC Curve ID
16 */
get_ecc_key_size_bytes(uint32_t curve)17 static size_t get_ecc_key_size_bytes(uint32_t curve)
18 {
19 switch (curve) {
20 case TEE_ECC_CURVE_NIST_P192:
21 return 24;
22
23 case TEE_ECC_CURVE_NIST_P224:
24 return 28;
25
26 case TEE_ECC_CURVE_NIST_P256:
27 case TEE_ECC_CURVE_SM2:
28 return 32;
29
30 case TEE_ECC_CURVE_NIST_P384:
31 return 48;
32
33 case TEE_ECC_CURVE_NIST_P521:
34 return 66;
35
36 default:
37 return 0;
38 }
39 }
40
41 /*
42 * Returns the key size in bits for the given ECC curve
43 *
44 * @curve ECC Curve ID
45 */
46
get_ecc_key_size_bits(uint32_t curve)47 static size_t get_ecc_key_size_bits(uint32_t curve)
48 {
49 switch (curve) {
50 case TEE_ECC_CURVE_NIST_P192:
51 case TEE_ECC_CURVE_NIST_P224:
52 case TEE_ECC_CURVE_NIST_P256:
53 case TEE_ECC_CURVE_NIST_P384:
54 case TEE_ECC_CURVE_SM2:
55 return get_ecc_key_size_bytes(curve) * 8;
56
57 case TEE_ECC_CURVE_NIST_P521:
58 return 521;
59
60 default:
61 return 0;
62 }
63 }
64
65 /*
66 * Verify if the cryptographic algorithm @algo is valid for
67 * the ECC curve
68 *
69 * @curve ECC curve
70 * @algo Cryptographic algorithm
71 */
algo_is_valid(uint32_t curve,uint32_t algo)72 static bool algo_is_valid(uint32_t curve, uint32_t algo)
73 {
74 unsigned int algo_op = TEE_ALG_GET_CLASS(algo);
75 unsigned int algo_id = TEE_ALG_GET_MAIN_ALG(algo);
76 unsigned int algo_curve = TEE_ALG_GET_DIGEST_HASH(algo);
77
78 /* Check first the algo operation and id */
79 if ((algo_op == TEE_OPERATION_ASYMMETRIC_SIGNATURE &&
80 algo_id == TEE_MAIN_ALGO_ECDSA) ||
81 (algo_op == TEE_OPERATION_KEY_DERIVATION &&
82 algo_id == TEE_MAIN_ALGO_ECDH)) {
83 if (curve == algo_curve) {
84 CRYPTO_TRACE("Algo 0x%" PRIx32 " curve 0x%" PRIx32
85 " is valid", algo, curve);
86 return true;
87 }
88 }
89
90 if (algo_op == TEE_OPERATION_ASYMMETRIC_SIGNATURE &&
91 algo_id == TEE_MAIN_ALGO_SM2_DSA_SM3) {
92 if (curve == TEE_ECC_CURVE_SM2)
93 return true;
94 }
95
96 CRYPTO_TRACE("Algo 0x%" PRIx32 " curve 0x%" PRIx32 " is not valid",
97 algo, curve);
98
99 return false;
100 }
101
102 /*
103 * Free an ECC public key
104 *
105 * @key Public Key
106 */
ecc_free_public_key(struct ecc_public_key * key)107 static void ecc_free_public_key(struct ecc_public_key *key)
108 {
109 struct drvcrypt_ecc *ecc = NULL;
110
111 if (key) {
112 ecc = drvcrypt_get_ops(CRYPTO_ECC);
113 if (ecc) {
114 CRYPTO_TRACE("ECC Public Key free");
115 ecc->free_publickey(key);
116 }
117 }
118 }
119
120 /*
121 * Generates an ECC keypair
122 *
123 * @key Keypair
124 * @size_bits Key size in bits
125 */
ecc_generate_keypair(struct ecc_keypair * key,size_t size_bits __maybe_unused)126 static TEE_Result ecc_generate_keypair(struct ecc_keypair *key,
127 size_t size_bits __maybe_unused)
128 {
129 TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED;
130 struct drvcrypt_ecc *ecc = NULL;
131 size_t key_size_bits = 0;
132
133 /* Check input parameters */
134 if (!key) {
135 CRYPTO_TRACE("Parameters error key is NULL");
136 return TEE_ERROR_BAD_PARAMETERS;
137 }
138
139 key_size_bits = get_ecc_key_size_bits(key->curve);
140
141 ecc = drvcrypt_get_ops(CRYPTO_ECC);
142 if (ecc)
143 ret = ecc->gen_keypair(key, key_size_bits);
144
145 CRYPTO_TRACE("ECC Keypair (%zu bits) generate ret = 0x%" PRIx32,
146 key_size_bits, ret);
147
148 return ret;
149 }
150
151 /*
152 * Sign the message with the ECC Key given by the Keypair
153 *
154 * @algo ECC algorithm
155 * @key ECC Keypair
156 * @msg Message to sign
157 * @msg_len Length of the message (bytes)
158 * @sig Signature
159 * @sig_len [in/out] Length of the signature (bytes)
160 */
ecc_sign(uint32_t algo,struct ecc_keypair * key,const uint8_t * msg,size_t msg_len,uint8_t * sig,size_t * sig_len)161 static TEE_Result ecc_sign(uint32_t algo, struct ecc_keypair *key,
162 const uint8_t *msg, size_t msg_len, uint8_t *sig,
163 size_t *sig_len)
164 {
165 TEE_Result ret = TEE_ERROR_BAD_PARAMETERS;
166 struct drvcrypt_ecc *ecc = NULL;
167 struct drvcrypt_sign_data sdata = { };
168 size_t size_bytes = 0;
169
170 /* Verify first the input parameters */
171 if (!key || !msg || !sig_len) {
172 CRYPTO_TRACE("Input parameters reference error");
173 return ret;
174 }
175
176 if (!algo_is_valid(key->curve, algo))
177 return ret;
178
179 size_bytes = get_ecc_key_size_bytes(key->curve);
180 if (!size_bytes)
181 return TEE_ERROR_BAD_PARAMETERS;
182
183 /* Verify the signature length function of the key size */
184 if (*sig_len < 2 * size_bytes) {
185 CRYPTO_TRACE("Length (%zu) too short expected %zu bytes",
186 *sig_len, 2 * size_bytes);
187 *sig_len = 2 * size_bytes;
188 return TEE_ERROR_SHORT_BUFFER;
189 }
190
191 if (!sig) {
192 CRYPTO_TRACE("Parameter \"sig\" reference error");
193 return TEE_ERROR_BAD_PARAMETERS;
194 }
195
196 ecc = drvcrypt_get_ops(CRYPTO_ECC);
197 if (ecc) {
198 /*
199 * Prepare the Signature structure data
200 */
201 sdata.algo = algo;
202 sdata.key = key;
203 sdata.size_sec = size_bytes;
204 sdata.message.data = (uint8_t *)msg;
205 sdata.message.length = msg_len;
206 sdata.signature.data = (uint8_t *)sig;
207 sdata.signature.length = *sig_len;
208
209 ret = ecc->sign(&sdata);
210
211 /* Set the signature length */
212 *sig_len = sdata.signature.length;
213 } else {
214 ret = TEE_ERROR_NOT_IMPLEMENTED;
215 }
216
217 CRYPTO_TRACE("Sign algo (0x%" PRIx32 ") returned 0x%" PRIx32, algo,
218 ret);
219
220 return ret;
221 }
222
223 /*
224 * Verify if signature is signed with the given public key.
225 *
226 * @algo ECC algorithm
227 * @key ECC Public key
228 * @msg Message to sign
229 * @msg_len Length of the message (bytes)
230 * @sig Signature
231 * @sig_len Length of the signature (bytes)
232 */
ecc_verify(uint32_t algo,struct ecc_public_key * key,const uint8_t * msg,size_t msg_len,const uint8_t * sig,size_t sig_len)233 static TEE_Result ecc_verify(uint32_t algo, struct ecc_public_key *key,
234 const uint8_t *msg, size_t msg_len,
235 const uint8_t *sig, size_t sig_len)
236 {
237 TEE_Result ret = TEE_ERROR_BAD_PARAMETERS;
238 struct drvcrypt_ecc *ecc = NULL;
239 struct drvcrypt_sign_data sdata = { };
240 size_t size_bytes = 0;
241
242 /* Verify first the input parameters */
243 if (!key || !msg || !sig) {
244 CRYPTO_TRACE("Input parameters reference error");
245 return ret;
246 }
247
248 if (!algo_is_valid(key->curve, algo))
249 return ret;
250
251 size_bytes = get_ecc_key_size_bytes(key->curve);
252 if (!size_bytes)
253 return TEE_ERROR_BAD_PARAMETERS;
254
255 /* Verify the signature length against key size */
256 if (sig_len != 2 * size_bytes) {
257 CRYPTO_TRACE("Length (%zu) is invalid expected %zu bytes",
258 sig_len, 2 * size_bytes);
259 return TEE_ERROR_SIGNATURE_INVALID;
260 }
261
262 ecc = drvcrypt_get_ops(CRYPTO_ECC);
263 if (ecc) {
264 sdata.algo = algo;
265 sdata.key = key;
266 sdata.size_sec = size_bytes;
267 sdata.message.data = (uint8_t *)msg;
268 sdata.message.length = msg_len;
269 sdata.signature.data = (uint8_t *)sig;
270 sdata.signature.length = sig_len;
271
272 ret = ecc->verify(&sdata);
273 } else {
274 ret = TEE_ERROR_NOT_IMPLEMENTED;
275 }
276
277 CRYPTO_TRACE("Verify algo (0x%" PRIx32 ") returned 0x%" PRIx32, algo,
278 ret);
279
280 return ret;
281 }
282
283 /*
284 * Compute the shared secret data from ECC Private key and Public Key
285 *
286 * @private_key ECC Private key
287 * @public_key ECC Public key
288 * @secret Secret
289 * @secret_len Length of the secret (bytes)
290 */
ecc_shared_secret(struct ecc_keypair * private_key,struct ecc_public_key * public_key,void * secret,unsigned long * secret_len)291 static TEE_Result ecc_shared_secret(struct ecc_keypair *private_key,
292 struct ecc_public_key *public_key,
293 void *secret, unsigned long *secret_len)
294 {
295 TEE_Result ret = TEE_ERROR_BAD_PARAMETERS;
296 struct drvcrypt_ecc *ecc = NULL;
297 struct drvcrypt_secret_data sdata = { };
298 size_t size_bytes = 0;
299
300 /* Verify first the input parameters */
301 if (!private_key || !public_key || !secret_len) {
302 CRYPTO_TRACE("Input parameters reference error");
303 return ret;
304 }
305
306 if (private_key->curve != public_key->curve) {
307 CRYPTO_TRACE("Private Key curve (%d) != Public Key curve (%d)",
308 private_key->curve, public_key->curve);
309 return ret;
310 }
311
312 size_bytes = get_ecc_key_size_bytes(public_key->curve);
313 if (!size_bytes)
314 return ret;
315
316 if (*secret_len < size_bytes) {
317 *secret_len = size_bytes;
318 return TEE_ERROR_SHORT_BUFFER;
319 }
320
321 if (!secret) {
322 CRYPTO_TRACE("Parameter \"secret\" reference error");
323 return ret;
324 }
325
326 ecc = drvcrypt_get_ops(CRYPTO_ECC);
327 if (ecc) {
328 /*
329 * Prepare the Secret structure data
330 */
331 sdata.key_priv = private_key;
332 sdata.key_pub = public_key;
333 sdata.size_sec = size_bytes;
334 sdata.secret.data = secret;
335 sdata.secret.length = *secret_len;
336
337 ret = ecc->shared_secret(&sdata);
338
339 /* Set the secret length */
340 *secret_len = sdata.secret.length;
341 } else {
342 ret = TEE_ERROR_NOT_IMPLEMENTED;
343 }
344
345 CRYPTO_TRACE("Shared Secret returned 0x%" PRIx32, ret);
346
347 return ret;
348 }
349
ecc_sm2_encrypt(struct ecc_public_key * key,const uint8_t * src,size_t src_len,uint8_t * dst,size_t * dst_len)350 static TEE_Result ecc_sm2_encrypt(struct ecc_public_key *key,
351 const uint8_t *src, size_t src_len,
352 uint8_t *dst, size_t *dst_len)
353 {
354 TEE_Result ret = TEE_ERROR_BAD_PARAMETERS;
355 struct drvcrypt_ecc_ed cdata = { };
356 struct drvcrypt_ecc *ecc = NULL;
357 size_t ciphertext_len = 0;
358 size_t size_bytes = 0;
359
360 ecc = drvcrypt_get_ops(CRYPTO_ECC);
361
362 size_bytes = get_ecc_key_size_bytes(key->curve);
363 if (!size_bytes) {
364 CRYPTO_TRACE("Curve 0x%08"PRIx32" not supported", key->curve);
365 return TEE_ERROR_BAD_PARAMETERS;
366 }
367
368 /* Uncompressed form indicator */
369 dst[0] = 0x04;
370
371 ciphertext_len = 2 * size_bytes + src_len + TEE_SM3_HASH_SIZE;
372
373 cdata.key = key;
374 cdata.size_sec = size_bytes;
375 cdata.plaintext.data = (uint8_t *)src;
376 cdata.plaintext.length = src_len;
377 cdata.ciphertext.data = dst + 1;
378 cdata.ciphertext.length = ciphertext_len;
379
380 ret = ecc->encrypt(&cdata);
381
382 if (!ret || ret == TEE_ERROR_SHORT_BUFFER)
383 *dst_len = cdata.ciphertext.length + 1;
384
385 return ret;
386 }
387
ecc_encrypt(struct ecc_public_key * key,const uint8_t * src,size_t src_len,uint8_t * dst,size_t * dst_len)388 static TEE_Result ecc_encrypt(struct ecc_public_key *key,
389 const uint8_t *src, size_t src_len,
390 uint8_t *dst, size_t *dst_len)
391 {
392 struct drvcrypt_ecc *ecc = NULL;
393
394 if (!key || !src || !dst) {
395 CRYPTO_TRACE("Input parameters reference error");
396 return TEE_ERROR_BAD_PARAMETERS;
397 }
398
399 ecc = drvcrypt_get_ops(CRYPTO_ECC);
400 if (!ecc || !ecc->encrypt)
401 return TEE_ERROR_NOT_IMPLEMENTED;
402
403 switch (key->curve) {
404 case TEE_ECC_CURVE_SM2:
405 return ecc_sm2_encrypt(key, src, src_len, dst, dst_len);
406 default:
407 return TEE_ERROR_NOT_IMPLEMENTED;
408 }
409 }
410
ecc_sm2_decrypt(struct ecc_keypair * key,const uint8_t * src,size_t src_len,uint8_t * dst,size_t * dst_len)411 static TEE_Result ecc_sm2_decrypt(struct ecc_keypair *key,
412 const uint8_t *src, size_t src_len,
413 uint8_t *dst, size_t *dst_len)
414 {
415 TEE_Result ret = TEE_ERROR_BAD_PARAMETERS;
416 struct drvcrypt_ecc_ed cdata = { };
417 struct drvcrypt_ecc *ecc = NULL;
418 uint8_t *ciphertext = NULL;
419 size_t ciphertext_len = 0;
420 size_t size_bytes = 0;
421 size_t plaintext_len = 0;
422 /* Point Compression */
423 uint8_t pc = 0;
424
425 ecc = drvcrypt_get_ops(CRYPTO_ECC);
426
427 size_bytes = get_ecc_key_size_bytes(key->curve);
428 if (!size_bytes) {
429 CRYPTO_TRACE("Curve 0x%08"PRIx32" not supported", key->curve);
430 return TEE_ERROR_BAD_PARAMETERS;
431 }
432
433 pc = src[0];
434 switch (pc) {
435 case 0x02:
436 case 0x03:
437 /* Compressed form */
438 return TEE_ERROR_NOT_SUPPORTED;
439 case 0x04:
440 /* Uncompressed form */
441 ciphertext = (uint8_t *)src + 1;
442 ciphertext_len = src_len - 1;
443 break;
444 case 0x06:
445 case 0x07:
446 /* Hybrid form */
447 return TEE_ERROR_NOT_SUPPORTED;
448 default:
449 return TEE_ERROR_BAD_PARAMETERS;
450 }
451
452 if (SUB_OVERFLOW(ciphertext_len, 2 * size_bytes + TEE_SM3_HASH_SIZE,
453 &plaintext_len))
454 return TEE_ERROR_BAD_PARAMETERS;
455
456 cdata.key = key;
457 cdata.size_sec = size_bytes;
458 cdata.ciphertext.data = ciphertext;
459 cdata.ciphertext.length = ciphertext_len;
460 cdata.plaintext.data = dst;
461 cdata.plaintext.length = plaintext_len;
462
463 ret = ecc->decrypt(&cdata);
464
465 /* Set the plaintext length */
466 if (!ret || ret == TEE_ERROR_SHORT_BUFFER)
467 *dst_len = cdata.plaintext.length;
468
469 return ret;
470 }
471
ecc_decrypt(struct ecc_keypair * key,const uint8_t * src,size_t src_len,uint8_t * dst,size_t * dst_len)472 static TEE_Result ecc_decrypt(struct ecc_keypair *key,
473 const uint8_t *src, size_t src_len,
474 uint8_t *dst, size_t *dst_len)
475 {
476 struct drvcrypt_ecc *ecc = NULL;
477
478 if (!key || !src || !dst) {
479 CRYPTO_TRACE("Input parameters reference error");
480 return TEE_ERROR_BAD_PARAMETERS;
481 }
482
483 ecc = drvcrypt_get_ops(CRYPTO_ECC);
484 if (!ecc || !ecc->decrypt)
485 return TEE_ERROR_NOT_IMPLEMENTED;
486
487 switch (key->curve) {
488 case TEE_ECC_CURVE_SM2:
489 return ecc_sm2_decrypt(key, src, src_len, dst, dst_len);
490 default:
491 return TEE_ERROR_NOT_IMPLEMENTED;
492 }
493 }
494
495 static const struct crypto_ecc_keypair_ops ecc_keypair_ops = {
496 .generate = ecc_generate_keypair,
497 .sign = ecc_sign,
498 .shared_secret = ecc_shared_secret,
499 .decrypt = ecc_decrypt,
500 };
501
drvcrypt_asym_alloc_ecc_keypair(struct ecc_keypair * key,uint32_t type,size_t size_bits)502 TEE_Result drvcrypt_asym_alloc_ecc_keypair(struct ecc_keypair *key,
503 uint32_t type, size_t size_bits)
504 {
505 TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED;
506 struct drvcrypt_ecc *ecc = NULL;
507
508 if (!key || !size_bits) {
509 CRYPTO_TRACE("Bad parameters (key @%p)(size %zu bits)", key,
510 size_bits);
511 return TEE_ERROR_BAD_PARAMETERS;
512 }
513
514 switch (type) {
515 case TEE_TYPE_ECDSA_KEYPAIR:
516 case TEE_TYPE_ECDH_KEYPAIR:
517 case TEE_TYPE_SM2_PKE_KEYPAIR:
518 case TEE_TYPE_SM2_DSA_KEYPAIR:
519 ecc = drvcrypt_get_ops(CRYPTO_ECC);
520 break;
521 default:
522 break;
523 }
524
525 if (ecc)
526 ret = ecc->alloc_keypair(key, type, size_bits);
527
528 if (!ret) {
529 key->ops = &ecc_keypair_ops;
530
531 /* ecc->alloc_keypair() can not get type to set curve */
532 switch (type) {
533 case TEE_TYPE_SM2_PKE_KEYPAIR:
534 case TEE_TYPE_SM2_DSA_KEYPAIR:
535 key->curve = TEE_ECC_CURVE_SM2;
536 break;
537 default:
538 break;
539 }
540 }
541
542 CRYPTO_TRACE("ECC Keypair (%zu bits) alloc ret = 0x%" PRIx32, size_bits,
543 ret);
544 return ret;
545 }
546
547 static const struct crypto_ecc_public_ops ecc_public_key_ops = {
548 .free = ecc_free_public_key,
549 .verify = ecc_verify,
550 .encrypt = ecc_encrypt,
551 };
552
drvcrypt_asym_alloc_ecc_public_key(struct ecc_public_key * key,uint32_t type,size_t size_bits)553 TEE_Result drvcrypt_asym_alloc_ecc_public_key(struct ecc_public_key *key,
554 uint32_t type, size_t size_bits)
555 {
556 TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED;
557 struct drvcrypt_ecc *ecc = NULL;
558
559 if (!key || !size_bits) {
560 CRYPTO_TRACE("Bad parameters (key @%p)(size %zu bits)", key,
561 size_bits);
562 return TEE_ERROR_BAD_PARAMETERS;
563 }
564
565 switch (type) {
566 case TEE_TYPE_ECDSA_PUBLIC_KEY:
567 case TEE_TYPE_ECDH_PUBLIC_KEY:
568 case TEE_TYPE_SM2_PKE_PUBLIC_KEY:
569 case TEE_TYPE_SM2_DSA_PUBLIC_KEY:
570 ecc = drvcrypt_get_ops(CRYPTO_ECC);
571 break;
572 default:
573 break;
574 }
575
576 if (ecc)
577 ret = ecc->alloc_publickey(key, type, size_bits);
578
579 if (!ret) {
580 key->ops = &ecc_public_key_ops;
581
582 /* ecc->alloc_publickey() can not get type to set curve */
583 switch (type) {
584 case TEE_TYPE_SM2_PKE_PUBLIC_KEY:
585 case TEE_TYPE_SM2_DSA_PUBLIC_KEY:
586 key->curve = TEE_ECC_CURVE_SM2;
587 break;
588 default:
589 break;
590 }
591 }
592
593 CRYPTO_TRACE("ECC Public Key (%zu bits) alloc ret = 0x%" PRIx32,
594 size_bits, ret);
595 return ret;
596 }
597