1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright 2018-2021 NXP
4 *
5 * Implementation of ECC functions
6 */
7 #include <caam_acipher.h>
8 #include <caam_common.h>
9 #include <caam_hal_ctrl.h>
10 #include <caam_jr.h>
11 #include <caam_utils_mem.h>
12 #include <caam_utils_status.h>
13 #include <drvcrypt.h>
14 #include <drvcrypt_acipher.h>
15 #include <mm/core_memprot.h>
16 #include <string.h>
17 #include <tee/cache.h>
18
19 #ifdef CFG_CAAM_64BIT
20 #define MAX_DESC_KEY_GEN 8
21 #define MAX_DESC_SIGN 13
22 #define MAX_DESC_VERIFY 15
23 #define MAX_DESC_SHARED 10
24 #else
25 #define MAX_DESC_KEY_GEN 6
26 #define MAX_DESC_SIGN 9
27 #define MAX_DESC_VERIFY 10
28 #define MAX_DESC_SHARED 7
29 #endif
30
31 /*
32 * Definition of the local ECC Keypair
33 * Public Key format (x, y)
34 * Private Key format (d)
35 */
36 struct caam_ecc_keypair {
37 struct caambuf xy;
38 struct caambuf d;
39 };
40
41 /*
42 * Free local ECC keypair
43 *
44 * @key ECC keypair
45 */
do_keypair_free(struct caam_ecc_keypair * key)46 static void do_keypair_free(struct caam_ecc_keypair *key)
47 {
48 caam_free_buf(&key->xy);
49 caam_free_buf(&key->d);
50 }
51
52 /*
53 * Convert Crypto ECC Key to local ECC Public Key
54 *
55 * @outkey [out] Output keypair in local format
56 * @inkey Input key in TEE Crypto format
57 * @size_sec Security size in bytes
58 */
do_keypub_conv(struct caam_ecc_keypair * outkey,const struct ecc_public_key * inkey,size_t size_sec)59 static enum caam_status do_keypub_conv(struct caam_ecc_keypair *outkey,
60 const struct ecc_public_key *inkey,
61 size_t size_sec)
62 {
63 enum caam_status retstatus = CAAM_OUT_MEMORY;
64 size_t x_size = 0;
65 size_t y_size = 0;
66
67 ECC_TRACE("ECC Convert Public Key size %zu bytes", size_sec);
68
69 /* Point (x y) is twice security key size */
70 retstatus = caam_calloc_buf(&outkey->xy, 2 * size_sec);
71 if (retstatus != CAAM_NO_ERROR)
72 return retstatus;
73
74 /* Copy x and y and get the number of bytes to pad with 0's */
75 x_size = crypto_bignum_num_bytes(inkey->x);
76 crypto_bignum_bn2bin(inkey->x, outkey->xy.data + size_sec - x_size);
77
78 y_size = crypto_bignum_num_bytes(inkey->y);
79 crypto_bignum_bn2bin(inkey->y, outkey->xy.data + 2 * size_sec - y_size);
80
81 cache_operation(TEE_CACHECLEAN, outkey->xy.data, outkey->xy.length);
82
83 return CAAM_NO_ERROR;
84 }
85
86 /*
87 * Convert Crypto ECC Key to local ECC Keypair Key
88 * Don't convert the exponent e not used in decrytion
89 *
90 * @outkey [out] Output keypair in local format
91 * @inkey Input key in TEE Crypto format
92 * @size_sec Security size in bytes
93 */
do_keypair_conv(struct caam_ecc_keypair * outkey,const struct ecc_keypair * inkey,size_t size_sec)94 static enum caam_status do_keypair_conv(struct caam_ecc_keypair *outkey,
95 const struct ecc_keypair *inkey,
96 size_t size_sec)
97 {
98 enum caam_status retstatus = CAAM_OUT_MEMORY;
99 size_t d_size = 0;
100
101 ECC_TRACE("ECC Convert Keypair size %zu bytes", size_sec);
102
103 /* Private key is only scalar d of sec_size bytes */
104 retstatus = caam_calloc_buf(&outkey->d, size_sec);
105 if (retstatus != CAAM_NO_ERROR)
106 return retstatus;
107
108 /* Get the number of bytes of d to pad with 0's */
109 d_size = crypto_bignum_num_bytes(inkey->d);
110 crypto_bignum_bn2bin(inkey->d, outkey->d.data + size_sec - d_size);
111
112 cache_operation(TEE_CACHECLEAN, outkey->d.data, outkey->d.length);
113
114 return CAAM_NO_ERROR;
115 }
116
117 /*
118 * Convert TEE ECC Curve to CAAM ECC Curve
119 *
120 * @tee_curve TEE ECC Curve
121 */
get_caam_curve(uint32_t tee_curve)122 static enum caam_ecc_curve get_caam_curve(uint32_t tee_curve)
123 {
124 enum caam_ecc_curve caam_curve = CAAM_ECC_UNKNOWN;
125
126 if (tee_curve > 0 &&
127 tee_curve < CAAM_ECC_MAX + TEE_ECC_CURVE_NIST_P192) {
128 /*
129 * Realign TEE Curve assuming NIST_P192 is the first entry in
130 * the list of supported ECC curves.
131 */
132 caam_curve = tee_curve - TEE_ECC_CURVE_NIST_P192
133 + CAAM_ECC_P192;
134 }
135
136 return caam_curve;
137 }
138
139 /*
140 * Allocate a ECC keypair
141 *
142 * @key Keypair
143 * @size_bits Key size in bits
144 */
do_allocate_keypair(struct ecc_keypair * key,size_t size_bits)145 static TEE_Result do_allocate_keypair(struct ecc_keypair *key, size_t size_bits)
146 {
147 ECC_TRACE("Allocate Keypair of %zu bits", size_bits);
148
149 /* Initialize the key fields to NULL */
150 memset(key, 0, sizeof(*key));
151
152 /* Allocate Secure Scalar */
153 key->d = crypto_bignum_allocate(size_bits);
154 if (!key->d)
155 goto err;
156
157 /* Allocate Public coordinate X */
158 key->x = crypto_bignum_allocate(size_bits);
159 if (!key->x)
160 goto err;
161
162 /* Allocate Public coordinate Y */
163 key->y = crypto_bignum_allocate(size_bits);
164 if (!key->y)
165 goto err;
166
167 return TEE_SUCCESS;
168
169 err:
170 ECC_TRACE("Allocation error");
171
172 crypto_bignum_free(key->d);
173 crypto_bignum_free(key->x);
174
175 return TEE_ERROR_OUT_OF_MEMORY;
176 }
177
178 /*
179 * Allocate an ECC Public Key
180 *
181 * @key Public Key
182 * @size_bits Key size in bits
183 */
do_allocate_publickey(struct ecc_public_key * key,size_t size_bits)184 static TEE_Result do_allocate_publickey(struct ecc_public_key *key,
185 size_t size_bits)
186 {
187 ECC_TRACE("Allocate Public Key of %zu bits", size_bits);
188
189 /* Initialize the key fields to NULL */
190 memset(key, 0, sizeof(*key));
191
192 /* Allocate Public coordinate X */
193 key->x = crypto_bignum_allocate(size_bits);
194 if (!key->x)
195 goto err;
196
197 /* Allocate Public coordinate Y */
198 key->y = crypto_bignum_allocate(size_bits);
199 if (!key->y)
200 goto err;
201
202 return TEE_SUCCESS;
203
204 err:
205 ECC_TRACE("Allocation error");
206
207 crypto_bignum_free(key->x);
208
209 return TEE_ERROR_OUT_OF_MEMORY;
210 }
211
212 /*
213 * Free an ECC public key
214 *
215 * @key Public Key
216 */
do_free_publickey(struct ecc_public_key * key)217 static void do_free_publickey(struct ecc_public_key *key)
218 {
219 crypto_bignum_free(key->x);
220 crypto_bignum_free(key->y);
221 }
222
223 /*
224 * Generate ECC keypair
225 *
226 * @key [out] Keypair
227 * @key_size Key size in bits multiple of 8 bits
228 */
do_gen_keypair(struct ecc_keypair * key,size_t key_size)229 static TEE_Result do_gen_keypair(struct ecc_keypair *key, size_t key_size)
230 {
231 TEE_Result ret = TEE_ERROR_GENERIC;
232 enum caam_status retstatus = CAAM_FAILURE;
233 enum caam_ecc_curve curve = CAAM_ECC_UNKNOWN;
234 struct caambuf d = { };
235 struct caambuf xy = { };
236 struct caam_jobctx jobctx = { };
237 uint32_t *desc = NULL;
238 uint32_t desclen = 0;
239
240 ECC_TRACE("Generate Keypair of %zu bits", key_size);
241
242 /* The key size must be a multiple of 8 bits */
243 key_size = ROUNDUP(key_size, 8);
244
245 /* Verify first if the curve is supported */
246 curve = get_caam_curve(key->curve);
247 if (curve == CAAM_ECC_UNKNOWN)
248 return TEE_ERROR_BAD_PARAMETERS;
249
250 /* Allocate the job used to prepare the operation */
251 desc = caam_calloc_desc(MAX_DESC_KEY_GEN);
252 if (!desc) {
253 ret = TEE_ERROR_OUT_OF_MEMORY;
254 goto out;
255 }
256
257 /*
258 * Allocate secure and public keys in one buffer
259 * Secure key size = key_size align in bytes
260 * Public key size = (key_size * 2) align in bytes
261 */
262 retstatus = caam_alloc_align_buf(&d, (key_size / 8) * 3);
263 if (retstatus != CAAM_NO_ERROR) {
264 ret = caam_status_to_tee_result(retstatus);
265 goto out;
266 }
267
268 /* Build the xy buffer to simplify the code */
269 xy.data = d.data + key_size / 8;
270 xy.length = 2 * (key_size / 8);
271 xy.paddr = d.paddr + key_size / 8;
272
273 /* Build the descriptor using Predifined ECC curve */
274 caam_desc_init(desc);
275 caam_desc_add_word(desc, DESC_HEADER(0));
276 caam_desc_add_word(desc, PDB_PKGEN_PD1 | PDB_ECC_ECDSEL(curve));
277 caam_desc_add_ptr(desc, d.paddr);
278 caam_desc_add_ptr(desc, xy.paddr);
279 caam_desc_add_word(desc, PK_KEYPAIR_GEN(ECC));
280
281 desclen = caam_desc_get_len(desc);
282 caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1));
283
284 ECC_DUMPDESC(desc);
285
286 jobctx.desc = desc;
287 cache_operation(TEE_CACHEFLUSH, d.data, d.length);
288 retstatus = caam_jr_enqueue(&jobctx, NULL);
289
290 if (retstatus == CAAM_NO_ERROR) {
291 cache_operation(TEE_CACHEINVALIDATE, d.data, d.length);
292
293 /* Copy all keypair parameters */
294 ret = crypto_bignum_bin2bn(d.data, key_size / 8, key->d);
295 if (ret != TEE_SUCCESS)
296 goto out;
297
298 ret = crypto_bignum_bin2bn(xy.data, xy.length / 2, key->x);
299 if (ret != TEE_SUCCESS)
300 goto out;
301
302 ret = crypto_bignum_bin2bn(xy.data + xy.length / 2,
303 xy.length / 2, key->y);
304 if (ret != TEE_SUCCESS)
305 goto out;
306
307 ECC_DUMPBUF("D", d.data, key_size / 8);
308 ECC_DUMPBUF("X", xy.data, xy.length / 2);
309 ECC_DUMPBUF("Y", xy.data + xy.length / 2, xy.length / 2);
310 } else {
311 ECC_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status);
312 ret = job_status_to_tee_result(jobctx.status);
313 }
314
315 out:
316 caam_free_desc(&desc);
317 caam_free_buf(&d);
318
319 return ret;
320 }
321
322 /*
323 * Signature of ECC message
324 * Note the message to sign is already hashed
325 *
326 * @sdata [in/out] ECC data to sign / Signature
327 */
do_sign(struct drvcrypt_sign_data * sdata)328 static TEE_Result do_sign(struct drvcrypt_sign_data *sdata)
329 {
330 TEE_Result ret = TEE_ERROR_GENERIC;
331 enum caam_status retstatus = CAAM_FAILURE;
332 enum caam_ecc_curve curve = CAAM_ECC_UNKNOWN;
333 struct ecc_keypair *inkey = sdata->key;
334 struct caam_ecc_keypair ecckey = { };
335 struct caam_jobctx jobctx = { };
336 uint32_t *desc = NULL;
337 uint32_t desclen = 0;
338 struct caamdmaobj msg = { };
339 size_t sign_len = 0;
340 struct caamdmaobj sign_c = { };
341 struct caamdmaobj sign_d = { };
342 uint32_t pdb_sgt_flags = 0;
343
344 ECC_TRACE("ECC Signature");
345
346 /* Verify first if the curve is supported */
347 curve = get_caam_curve(inkey->curve);
348 if (curve == CAAM_ECC_UNKNOWN)
349 return TEE_ERROR_BAD_PARAMETERS;
350
351 /* Allocate the job descriptor */
352 desc = caam_calloc_desc(MAX_DESC_SIGN);
353 if (!desc) {
354 ret = TEE_ERROR_OUT_OF_MEMORY;
355 goto out;
356 }
357
358 /* Convert the private key to a local key */
359 retstatus = do_keypair_conv(&ecckey, inkey, sdata->size_sec);
360 if (retstatus != CAAM_NO_ERROR) {
361 ret = caam_status_to_tee_result(retstatus);
362 goto out;
363 }
364
365 /* Prepare the input message CAAM Descriptor entry */
366 ret = caam_dmaobj_input_sgtbuf(&msg, sdata->message.data,
367 sdata->message.length);
368 if (ret)
369 goto out;
370
371 if (msg.sgtbuf.sgt_type)
372 pdb_sgt_flags |= PDB_SGT_PKSIGN_MSG;
373
374 caam_dmaobj_cache_push(&msg);
375
376 ECC_DUMPBUF("Message", sdata->message.data, sdata->message.length);
377
378 /*
379 * ReAllocate the signature result buffer with a maximum size
380 * of the roundup to 16 bytes of the secure size in bytes if
381 * the signature buffer is not aligned or too short.
382 *
383 * - 1st Part: size_sec
384 * - 2nd Part: size_sec roundup to 16 bytes
385 */
386 sign_len = ROUNDUP(sdata->size_sec, 16) + sdata->size_sec;
387
388 ret = caam_dmaobj_output_sgtbuf(&sign_c, sdata->signature.data,
389 sdata->signature.length, sign_len);
390 if (ret)
391 goto out;
392
393 if (sign_c.sgtbuf.sgt_type)
394 pdb_sgt_flags |= PDB_SGT_PKSIGN_SIGN_C;
395
396 /* Derive sign_d from created sign_c DMA object */
397 ret = caam_dmaobj_derive_sgtbuf(&sign_d, &sign_c, sdata->size_sec,
398 ROUNDUP(sdata->size_sec, 16));
399 if (ret)
400 goto out;
401
402 if (sign_d.sgtbuf.sgt_type)
403 pdb_sgt_flags |= PDB_SGT_PKSIGN_SIGN_D;
404
405 caam_dmaobj_cache_push(&sign_c);
406
407 /* Build the descriptor using Predifined ECC curve */
408 caam_desc_init(desc);
409 caam_desc_add_word(desc, DESC_HEADER(0));
410 caam_desc_add_word(desc, PDB_PKSIGN_PD1 | PDB_ECC_ECDSEL(curve) |
411 pdb_sgt_flags);
412 /* Secret key */
413 caam_desc_add_ptr(desc, ecckey.d.paddr);
414 /* Input message */
415 caam_desc_add_ptr(desc, msg.sgtbuf.paddr);
416 /* Signature 1st part */
417 caam_desc_add_ptr(desc, sign_c.sgtbuf.paddr);
418 /* Signature 2nd part */
419 caam_desc_add_ptr(desc, sign_d.sgtbuf.paddr);
420 /* Message length */
421 caam_desc_add_word(desc, sdata->message.length);
422
423 caam_desc_add_word(desc, DSA_SIGN(ECC));
424
425 desclen = caam_desc_get_len(desc);
426 caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1));
427
428 ECC_DUMPDESC(desc);
429
430 jobctx.desc = desc;
431
432 retstatus = caam_jr_enqueue(&jobctx, NULL);
433 if (retstatus == CAAM_NO_ERROR) {
434 sign_c.orig.length = 2 * sdata->size_sec;
435 sdata->signature.length = caam_dmaobj_copy_to_orig(&sign_c);
436
437 ECC_DUMPBUF("Signature", sdata->signature.data,
438 sdata->signature.length);
439
440 ret = caam_status_to_tee_result(retstatus);
441 } else {
442 ECC_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status);
443 ret = job_status_to_tee_result(jobctx.status);
444 }
445
446 out:
447 caam_free_desc(&desc);
448 do_keypair_free(&ecckey);
449 caam_dmaobj_free(&msg);
450 caam_dmaobj_free(&sign_d);
451 caam_dmaobj_free(&sign_c);
452
453 return ret;
454 }
455
456 /*
457 * Verification of the Signature of ECC message
458 * Note the message is already hashed
459 *
460 * @sdata [in/out] ECC Signature to verify
461 */
do_verify(struct drvcrypt_sign_data * sdata)462 static TEE_Result do_verify(struct drvcrypt_sign_data *sdata)
463 {
464 TEE_Result ret = TEE_ERROR_GENERIC;
465 enum caam_status retstatus = CAAM_FAILURE;
466 enum caam_ecc_curve curve = CAAM_ECC_UNKNOWN;
467 struct ecc_public_key *inkey = sdata->key;
468 struct caam_ecc_keypair ecckey = { };
469 struct caambuf tmp = { };
470 struct caam_jobctx jobctx = { };
471 uint32_t *desc = NULL;
472 uint32_t desclen = 0;
473 struct caamdmaobj msg = { };
474 struct caamdmaobj sign_c = { };
475 struct caamdmaobj sign_d = { };
476 uint32_t pdb_sgt_flags = 0;
477
478 ECC_TRACE("ECC Verify");
479
480 /* Verify first if the curve is supported */
481 curve = get_caam_curve(inkey->curve);
482 if (curve == CAAM_ECC_UNKNOWN)
483 return TEE_ERROR_BAD_PARAMETERS;
484
485 /* Allocate the job descriptor */
486 desc = caam_calloc_desc(MAX_DESC_VERIFY);
487 if (!desc) {
488 ret = TEE_ERROR_OUT_OF_MEMORY;
489 goto out;
490 }
491
492 /* Convert the Public key to local key */
493 retstatus = do_keypub_conv(&ecckey, inkey, sdata->size_sec);
494 if (retstatus != CAAM_NO_ERROR) {
495 ret = caam_status_to_tee_result(retstatus);
496 goto out;
497 }
498
499 /* Prepare the input message CAAM Descriptor entry */
500 ret = caam_dmaobj_input_sgtbuf(&msg, sdata->message.data,
501 sdata->message.length);
502 if (ret)
503 goto out;
504
505 if (msg.sgtbuf.sgt_type)
506 pdb_sgt_flags |= PDB_SGT_PKVERIF_MSG;
507
508 caam_dmaobj_cache_push(&msg);
509
510 /*
511 * Prepare the 1st Part of the signature
512 * Handle the full signature in case signature buffer needs to
513 * be reallocated.
514 */
515 ret = caam_dmaobj_input_sgtbuf(&sign_c, sdata->signature.data,
516 sdata->signature.length);
517 if (ret)
518 goto out;
519
520 if (sign_c.sgtbuf.sgt_type)
521 pdb_sgt_flags |= PDB_SGT_PKVERIF_SIGN_C;
522
523 /* Prepare the 2nd Part of the signature, derived from sign_c */
524 ret = caam_dmaobj_derive_sgtbuf(&sign_d, &sign_c, sdata->size_sec,
525 sdata->size_sec);
526 if (ret)
527 goto out;
528
529 if (sign_d.sgtbuf.sgt_type)
530 pdb_sgt_flags |= PDB_SGT_PKVERIF_SIGN_D;
531
532 caam_dmaobj_cache_push(&sign_c);
533
534 /* Allocate a Temporary buffer used by the CAAM */
535 retstatus = caam_alloc_align_buf(&tmp, 2 * sdata->size_sec);
536 if (retstatus != CAAM_NO_ERROR) {
537 ret = caam_status_to_tee_result(retstatus);
538 goto out;
539 }
540
541 /* Build the descriptor using Predifined ECC curve */
542 caam_desc_init(desc);
543 caam_desc_add_word(desc, DESC_HEADER(0));
544 caam_desc_add_word(desc, PDB_PKVERIFY_PD1 | PDB_ECC_ECDSEL(curve) |
545 pdb_sgt_flags);
546 /* Public key */
547 caam_desc_add_ptr(desc, ecckey.xy.paddr);
548 /* Input message */
549 caam_desc_add_ptr(desc, msg.sgtbuf.paddr);
550 /* Signature 1st part */
551 caam_desc_add_ptr(desc, sign_c.sgtbuf.paddr);
552 /* Signature 2nd part */
553 caam_desc_add_ptr(desc, sign_d.sgtbuf.paddr);
554 /* Temporary buffer */
555 caam_desc_add_ptr(desc, tmp.paddr);
556 /* Message length */
557 caam_desc_add_word(desc, sdata->message.length);
558
559 caam_desc_add_word(desc, DSA_VERIFY(ECC));
560 desclen = caam_desc_get_len(desc);
561 caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1));
562
563 ECC_DUMPDESC(desc);
564
565 jobctx.desc = desc;
566
567 cache_operation(TEE_CACHEFLUSH, tmp.data, tmp.length);
568 retstatus = caam_jr_enqueue(&jobctx, NULL);
569
570 if (retstatus == CAAM_JOB_STATUS && !jobctx.status) {
571 ECC_TRACE("ECC Verify Status 0x%08" PRIx32, jobctx.status);
572 ret = TEE_ERROR_SIGNATURE_INVALID;
573 } else if (retstatus != CAAM_NO_ERROR) {
574 ECC_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status);
575 ret = job_status_to_tee_result(jobctx.status);
576 } else {
577 ret = caam_status_to_tee_result(retstatus);
578 }
579
580 out:
581 caam_free_desc(&desc);
582 do_keypair_free(&ecckey);
583 caam_free_buf(&tmp);
584 caam_dmaobj_free(&msg);
585 caam_dmaobj_free(&sign_c);
586 caam_dmaobj_free(&sign_d);
587
588 return ret;
589 }
590
591 /*
592 * Compute the shared secret data from ECC Private key and Public Key
593 *
594 * @sdata [in/out] ECC Shared Secret data
595 */
do_shared_secret(struct drvcrypt_secret_data * sdata)596 static TEE_Result do_shared_secret(struct drvcrypt_secret_data *sdata)
597 {
598 TEE_Result ret = TEE_ERROR_GENERIC;
599 enum caam_status retstatus = CAAM_FAILURE;
600 enum caam_ecc_curve curve = CAAM_ECC_UNKNOWN;
601 struct ecc_keypair *inprivkey = sdata->key_priv;
602 struct ecc_public_key *inpubkey = sdata->key_pub;
603 struct caam_ecc_keypair ecckey = { };
604 struct caam_jobctx jobctx = { };
605 uint32_t *desc = NULL;
606 uint32_t desclen = 0;
607 struct caamdmaobj secret = { };
608 uint32_t pdb_sgt_flags = 0;
609
610 ECC_TRACE("ECC Shared Secret");
611
612 /* Verify first if the curve is supported */
613 curve = get_caam_curve(inpubkey->curve);
614 if (curve == CAAM_ECC_UNKNOWN)
615 return TEE_ERROR_BAD_PARAMETERS;
616
617 /* Allocate the job descriptor */
618 desc = caam_calloc_desc(MAX_DESC_SHARED);
619 if (!desc) {
620 ret = TEE_ERROR_OUT_OF_MEMORY;
621 goto out;
622 }
623
624 /* Convert the Private key to local key */
625 retstatus = do_keypair_conv(&ecckey, inprivkey, sdata->size_sec);
626 if (retstatus != CAAM_NO_ERROR) {
627 ret = caam_status_to_tee_result(retstatus);
628 goto out;
629 }
630
631 /* Convert the Public key to local key */
632 retstatus = do_keypub_conv(&ecckey, inpubkey, sdata->size_sec);
633 if (retstatus != CAAM_NO_ERROR) {
634 ret = caam_status_to_tee_result(retstatus);
635 goto out;
636 }
637
638 /*
639 * Re-allocate the secret result buffer with a maximum size
640 * of the secret size if not cache aligned
641 */
642 ret = caam_dmaobj_output_sgtbuf(&secret, sdata->secret.data,
643 sdata->secret.length, sdata->size_sec);
644 if (ret)
645 goto out;
646
647 if (secret.sgtbuf.sgt_type)
648 pdb_sgt_flags |= PDB_SGT_PKDH_SECRET;
649
650 caam_dmaobj_cache_push(&secret);
651
652 /* Build the descriptor using Predifined ECC curve */
653 caam_desc_init(desc);
654 caam_desc_add_word(desc, DESC_HEADER(0));
655 caam_desc_add_word(desc, PDB_SHARED_SECRET_PD1 | PDB_ECC_ECDSEL(curve) |
656 pdb_sgt_flags);
657 /* Public key */
658 caam_desc_add_ptr(desc, ecckey.xy.paddr);
659 /* Private key */
660 caam_desc_add_ptr(desc, ecckey.d.paddr);
661 /* Output secret */
662 caam_desc_add_ptr(desc, secret.sgtbuf.paddr);
663
664 caam_desc_add_word(desc, SHARED_SECRET(ECC));
665 desclen = caam_desc_get_len(desc);
666 caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1));
667
668 ECC_DUMPDESC(desc);
669
670 jobctx.desc = desc;
671
672 retstatus = caam_jr_enqueue(&jobctx, NULL);
673
674 if (retstatus == CAAM_NO_ERROR) {
675 sdata->secret.length = caam_dmaobj_copy_to_orig(&secret);
676
677 ECC_DUMPBUF("Secret", sdata->secret.data, sdata->secret.length);
678
679 ret = caam_status_to_tee_result(retstatus);
680 } else {
681 ECC_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status);
682 ret = job_status_to_tee_result(jobctx.status);
683 }
684
685 out:
686 caam_free_desc(&desc);
687 do_keypair_free(&ecckey);
688 caam_dmaobj_free(&secret);
689
690 return ret;
691 }
692
693 /*
694 * Registration of the ECC Driver
695 */
696 static struct drvcrypt_ecc driver_ecc = {
697 .alloc_keypair = do_allocate_keypair,
698 .alloc_publickey = do_allocate_publickey,
699 .free_publickey = do_free_publickey,
700 .gen_keypair = do_gen_keypair,
701 .sign = do_sign,
702 .verify = do_verify,
703 .shared_secret = do_shared_secret,
704 };
705
caam_ecc_init(struct caam_jrcfg * caam_jrcfg)706 enum caam_status caam_ecc_init(struct caam_jrcfg *caam_jrcfg)
707 {
708 enum caam_status retstatus = CAAM_FAILURE;
709 vaddr_t jr_base = caam_jrcfg->base + caam_jrcfg->offset;
710
711 if (caam_hal_ctrl_pknum(jr_base))
712 if (drvcrypt_register_ecc(&driver_ecc) == TEE_SUCCESS)
713 retstatus = CAAM_NO_ERROR;
714
715 return retstatus;
716 }
717