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 /* Verify first if the curve is supported */
243 curve = get_caam_curve(key->curve);
244 if (curve == CAAM_ECC_UNKNOWN)
245 return TEE_ERROR_BAD_PARAMETERS;
246
247 /* Allocate the job used to prepare the operation */
248 desc = caam_calloc_desc(MAX_DESC_KEY_GEN);
249 if (!desc) {
250 ret = TEE_ERROR_OUT_OF_MEMORY;
251 goto out;
252 }
253
254 /*
255 * Allocate secure and public keys in one buffer
256 * Secure key size = key_size align in bytes
257 * Public key size = (key_size * 2) align in bytes
258 */
259 retstatus = caam_alloc_align_buf(&d, (key_size / 8) * 3);
260 if (retstatus != CAAM_NO_ERROR) {
261 ret = caam_status_to_tee_result(retstatus);
262 goto out;
263 }
264
265 /* Build the xy buffer to simplify the code */
266 xy.data = d.data + key_size / 8;
267 xy.length = 2 * (key_size / 8);
268 xy.paddr = d.paddr + key_size / 8;
269
270 /* Build the descriptor using Predifined ECC curve */
271 caam_desc_init(desc);
272 caam_desc_add_word(desc, DESC_HEADER(0));
273 caam_desc_add_word(desc, PDB_PKGEN_PD1 | PDB_ECC_ECDSEL(curve));
274 caam_desc_add_ptr(desc, d.paddr);
275 caam_desc_add_ptr(desc, xy.paddr);
276 caam_desc_add_word(desc, PK_KEYPAIR_GEN(ECC));
277
278 desclen = caam_desc_get_len(desc);
279 caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1));
280
281 ECC_DUMPDESC(desc);
282
283 jobctx.desc = desc;
284 cache_operation(TEE_CACHEFLUSH, d.data, d.length);
285 retstatus = caam_jr_enqueue(&jobctx, NULL);
286
287 if (retstatus == CAAM_NO_ERROR) {
288 cache_operation(TEE_CACHEINVALIDATE, d.data, d.length);
289
290 /* Copy all keypair parameters */
291 ret = crypto_bignum_bin2bn(d.data, key_size / 8, key->d);
292 if (ret != TEE_SUCCESS)
293 goto out;
294
295 ret = crypto_bignum_bin2bn(xy.data, xy.length / 2, key->x);
296 if (ret != TEE_SUCCESS)
297 goto out;
298
299 ret = crypto_bignum_bin2bn(xy.data + xy.length / 2,
300 xy.length / 2, key->y);
301 if (ret != TEE_SUCCESS)
302 goto out;
303
304 ECC_DUMPBUF("D", d.data, key_size / 8);
305 ECC_DUMPBUF("X", xy.data, xy.length / 2);
306 ECC_DUMPBUF("Y", xy.data + xy.length / 2, xy.length / 2);
307 } else {
308 ECC_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status);
309 ret = job_status_to_tee_result(jobctx.status);
310 }
311
312 out:
313 caam_free_desc(&desc);
314 caam_free_buf(&d);
315
316 return ret;
317 }
318
319 /*
320 * Signature of ECC message
321 * Note the message to sign is already hashed
322 *
323 * @sdata [in/out] ECC data to sign / Signature
324 */
do_sign(struct drvcrypt_sign_data * sdata)325 static TEE_Result do_sign(struct drvcrypt_sign_data *sdata)
326 {
327 TEE_Result ret = TEE_ERROR_GENERIC;
328 enum caam_status retstatus = CAAM_FAILURE;
329 enum caam_ecc_curve curve = CAAM_ECC_UNKNOWN;
330 struct ecc_keypair *inkey = sdata->key;
331 struct caam_ecc_keypair ecckey = { };
332 struct caam_jobctx jobctx = { };
333 uint32_t *desc = NULL;
334 uint32_t desclen = 0;
335 struct caamdmaobj msg = { };
336 size_t sign_len = 0;
337 struct caamdmaobj sign_c = { };
338 struct caamdmaobj sign_d = { };
339 uint32_t pdb_sgt_flags = 0;
340
341 ECC_TRACE("ECC Signature");
342
343 /* Verify first if the curve is supported */
344 curve = get_caam_curve(inkey->curve);
345 if (curve == CAAM_ECC_UNKNOWN)
346 return TEE_ERROR_BAD_PARAMETERS;
347
348 /* Allocate the job descriptor */
349 desc = caam_calloc_desc(MAX_DESC_SIGN);
350 if (!desc) {
351 ret = TEE_ERROR_OUT_OF_MEMORY;
352 goto out;
353 }
354
355 /* Convert the private key to a local key */
356 retstatus = do_keypair_conv(&ecckey, inkey, sdata->size_sec);
357 if (retstatus != CAAM_NO_ERROR) {
358 ret = caam_status_to_tee_result(retstatus);
359 goto out;
360 }
361
362 /* Prepare the input message CAAM Descriptor entry */
363 ret = caam_dmaobj_input_sgtbuf(&msg, sdata->message.data,
364 sdata->message.length);
365 if (ret)
366 goto out;
367
368 if (msg.sgtbuf.sgt_type)
369 pdb_sgt_flags |= PDB_SGT_PKSIGN_MSG;
370
371 caam_dmaobj_cache_push(&msg);
372
373 ECC_DUMPBUF("Message", sdata->message.data, sdata->message.length);
374
375 /*
376 * ReAllocate the signature result buffer with a maximum size
377 * of the roundup to 16 bytes of the secure size in bytes if
378 * the signature buffer is not aligned or too short.
379 *
380 * - 1st Part: size_sec
381 * - 2nd Part: size_sec roundup to 16 bytes
382 */
383 sign_len = ROUNDUP(sdata->size_sec, 16) + sdata->size_sec;
384
385 ret = caam_dmaobj_output_sgtbuf(&sign_c, sdata->signature.data,
386 sdata->signature.length, sign_len);
387 if (ret)
388 goto out;
389
390 if (sign_c.sgtbuf.sgt_type)
391 pdb_sgt_flags |= PDB_SGT_PKSIGN_SIGN_C;
392
393 /* Derive sign_d from created sign_c DMA object */
394 ret = caam_dmaobj_derive_sgtbuf(&sign_d, &sign_c, sdata->size_sec,
395 ROUNDUP(sdata->size_sec, 16));
396 if (ret)
397 goto out;
398
399 if (sign_d.sgtbuf.sgt_type)
400 pdb_sgt_flags |= PDB_SGT_PKSIGN_SIGN_D;
401
402 caam_dmaobj_cache_push(&sign_c);
403
404 /* Build the descriptor using Predifined ECC curve */
405 caam_desc_init(desc);
406 caam_desc_add_word(desc, DESC_HEADER(0));
407 caam_desc_add_word(desc, PDB_PKSIGN_PD1 | PDB_ECC_ECDSEL(curve) |
408 pdb_sgt_flags);
409 /* Secret key */
410 caam_desc_add_ptr(desc, ecckey.d.paddr);
411 /* Input message */
412 caam_desc_add_ptr(desc, msg.sgtbuf.paddr);
413 /* Signature 1st part */
414 caam_desc_add_ptr(desc, sign_c.sgtbuf.paddr);
415 /* Signature 2nd part */
416 caam_desc_add_ptr(desc, sign_d.sgtbuf.paddr);
417 /* Message length */
418 caam_desc_add_word(desc, sdata->message.length);
419
420 caam_desc_add_word(desc, DSA_SIGN(ECC));
421
422 desclen = caam_desc_get_len(desc);
423 caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1));
424
425 ECC_DUMPDESC(desc);
426
427 jobctx.desc = desc;
428
429 retstatus = caam_jr_enqueue(&jobctx, NULL);
430 if (retstatus == CAAM_NO_ERROR) {
431 sign_c.orig.length = 2 * sdata->size_sec;
432 sdata->signature.length = caam_dmaobj_copy_to_orig(&sign_c);
433
434 ECC_DUMPBUF("Signature", sdata->signature.data,
435 sdata->signature.length);
436
437 ret = caam_status_to_tee_result(retstatus);
438 } else {
439 ECC_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status);
440 ret = job_status_to_tee_result(jobctx.status);
441 }
442
443 out:
444 caam_free_desc(&desc);
445 do_keypair_free(&ecckey);
446 caam_dmaobj_free(&msg);
447 caam_dmaobj_free(&sign_d);
448 caam_dmaobj_free(&sign_c);
449
450 return ret;
451 }
452
453 /*
454 * Verification of the Signature of ECC message
455 * Note the message is already hashed
456 *
457 * @sdata [in/out] ECC Signature to verify
458 */
do_verify(struct drvcrypt_sign_data * sdata)459 static TEE_Result do_verify(struct drvcrypt_sign_data *sdata)
460 {
461 TEE_Result ret = TEE_ERROR_GENERIC;
462 enum caam_status retstatus = CAAM_FAILURE;
463 enum caam_ecc_curve curve = CAAM_ECC_UNKNOWN;
464 struct ecc_public_key *inkey = sdata->key;
465 struct caam_ecc_keypair ecckey = { };
466 struct caambuf tmp = { };
467 struct caam_jobctx jobctx = { };
468 uint32_t *desc = NULL;
469 uint32_t desclen = 0;
470 struct caamdmaobj msg = { };
471 struct caamdmaobj sign_c = { };
472 struct caamdmaobj sign_d = { };
473 uint32_t pdb_sgt_flags = 0;
474
475 ECC_TRACE("ECC Verify");
476
477 /* Verify first if the curve is supported */
478 curve = get_caam_curve(inkey->curve);
479 if (curve == CAAM_ECC_UNKNOWN)
480 return TEE_ERROR_BAD_PARAMETERS;
481
482 /* Allocate the job descriptor */
483 desc = caam_calloc_desc(MAX_DESC_VERIFY);
484 if (!desc) {
485 ret = TEE_ERROR_OUT_OF_MEMORY;
486 goto out;
487 }
488
489 /* Convert the Public key to local key */
490 retstatus = do_keypub_conv(&ecckey, inkey, sdata->size_sec);
491 if (retstatus != CAAM_NO_ERROR) {
492 ret = caam_status_to_tee_result(retstatus);
493 goto out;
494 }
495
496 /* Prepare the input message CAAM Descriptor entry */
497 ret = caam_dmaobj_input_sgtbuf(&msg, sdata->message.data,
498 sdata->message.length);
499 if (ret)
500 goto out;
501
502 if (msg.sgtbuf.sgt_type)
503 pdb_sgt_flags |= PDB_SGT_PKVERIF_MSG;
504
505 caam_dmaobj_cache_push(&msg);
506
507 /*
508 * Prepare the 1st Part of the signature
509 * Handle the full signature in case signature buffer needs to
510 * be reallocated.
511 */
512 ret = caam_dmaobj_input_sgtbuf(&sign_c, sdata->signature.data,
513 sdata->signature.length);
514 if (ret)
515 goto out;
516
517 if (sign_c.sgtbuf.sgt_type)
518 pdb_sgt_flags |= PDB_SGT_PKVERIF_SIGN_C;
519
520 /* Prepare the 2nd Part of the signature, derived from sign_c */
521 ret = caam_dmaobj_derive_sgtbuf(&sign_d, &sign_c, sdata->size_sec,
522 sdata->size_sec);
523 if (ret)
524 goto out;
525
526 if (sign_d.sgtbuf.sgt_type)
527 pdb_sgt_flags |= PDB_SGT_PKVERIF_SIGN_D;
528
529 caam_dmaobj_cache_push(&sign_c);
530
531 /* Allocate a Temporary buffer used by the CAAM */
532 retstatus = caam_alloc_align_buf(&tmp, 2 * sdata->size_sec);
533 if (retstatus != CAAM_NO_ERROR) {
534 ret = caam_status_to_tee_result(retstatus);
535 goto out;
536 }
537
538 /* Build the descriptor using Predifined ECC curve */
539 caam_desc_init(desc);
540 caam_desc_add_word(desc, DESC_HEADER(0));
541 caam_desc_add_word(desc, PDB_PKVERIFY_PD1 | PDB_ECC_ECDSEL(curve) |
542 pdb_sgt_flags);
543 /* Public key */
544 caam_desc_add_ptr(desc, ecckey.xy.paddr);
545 /* Input message */
546 caam_desc_add_ptr(desc, msg.sgtbuf.paddr);
547 /* Signature 1st part */
548 caam_desc_add_ptr(desc, sign_c.sgtbuf.paddr);
549 /* Signature 2nd part */
550 caam_desc_add_ptr(desc, sign_d.sgtbuf.paddr);
551 /* Temporary buffer */
552 caam_desc_add_ptr(desc, tmp.paddr);
553 /* Message length */
554 caam_desc_add_word(desc, sdata->message.length);
555
556 caam_desc_add_word(desc, DSA_VERIFY(ECC));
557 desclen = caam_desc_get_len(desc);
558 caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1));
559
560 ECC_DUMPDESC(desc);
561
562 jobctx.desc = desc;
563
564 cache_operation(TEE_CACHEFLUSH, tmp.data, tmp.length);
565 retstatus = caam_jr_enqueue(&jobctx, NULL);
566
567 if (retstatus == CAAM_JOB_STATUS && !jobctx.status) {
568 ECC_TRACE("ECC Verify Status 0x%08" PRIx32, jobctx.status);
569 ret = TEE_ERROR_SIGNATURE_INVALID;
570 } else if (retstatus != CAAM_NO_ERROR) {
571 ECC_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status);
572 ret = job_status_to_tee_result(jobctx.status);
573 } else {
574 ret = caam_status_to_tee_result(retstatus);
575 }
576
577 out:
578 caam_free_desc(&desc);
579 do_keypair_free(&ecckey);
580 caam_free_buf(&tmp);
581 caam_dmaobj_free(&msg);
582 caam_dmaobj_free(&sign_c);
583 caam_dmaobj_free(&sign_d);
584
585 return ret;
586 }
587
588 /*
589 * Compute the shared secret data from ECC Private key and Public Key
590 *
591 * @sdata [in/out] ECC Shared Secret data
592 */
do_shared_secret(struct drvcrypt_secret_data * sdata)593 static TEE_Result do_shared_secret(struct drvcrypt_secret_data *sdata)
594 {
595 TEE_Result ret = TEE_ERROR_GENERIC;
596 enum caam_status retstatus = CAAM_FAILURE;
597 enum caam_ecc_curve curve = CAAM_ECC_UNKNOWN;
598 struct ecc_keypair *inprivkey = sdata->key_priv;
599 struct ecc_public_key *inpubkey = sdata->key_pub;
600 struct caam_ecc_keypair ecckey = { };
601 struct caam_jobctx jobctx = { };
602 uint32_t *desc = NULL;
603 uint32_t desclen = 0;
604 struct caamdmaobj secret = { };
605 uint32_t pdb_sgt_flags = 0;
606
607 ECC_TRACE("ECC Shared Secret");
608
609 /* Verify first if the curve is supported */
610 curve = get_caam_curve(inpubkey->curve);
611 if (curve == CAAM_ECC_UNKNOWN)
612 return TEE_ERROR_BAD_PARAMETERS;
613
614 /* Allocate the job descriptor */
615 desc = caam_calloc_desc(MAX_DESC_SHARED);
616 if (!desc) {
617 ret = TEE_ERROR_OUT_OF_MEMORY;
618 goto out;
619 }
620
621 /* Convert the Private key to local key */
622 retstatus = do_keypair_conv(&ecckey, inprivkey, sdata->size_sec);
623 if (retstatus != CAAM_NO_ERROR) {
624 ret = caam_status_to_tee_result(retstatus);
625 goto out;
626 }
627
628 /* Convert the Public key to local key */
629 retstatus = do_keypub_conv(&ecckey, inpubkey, sdata->size_sec);
630 if (retstatus != CAAM_NO_ERROR) {
631 ret = caam_status_to_tee_result(retstatus);
632 goto out;
633 }
634
635 /*
636 * Re-allocate the secret result buffer with a maximum size
637 * of the secret size if not cache aligned
638 */
639 ret = caam_dmaobj_output_sgtbuf(&secret, sdata->secret.data,
640 sdata->secret.length, sdata->size_sec);
641 if (ret)
642 goto out;
643
644 if (secret.sgtbuf.sgt_type)
645 pdb_sgt_flags |= PDB_SGT_PKDH_SECRET;
646
647 caam_dmaobj_cache_push(&secret);
648
649 /* Build the descriptor using Predifined ECC curve */
650 caam_desc_init(desc);
651 caam_desc_add_word(desc, DESC_HEADER(0));
652 caam_desc_add_word(desc, PDB_SHARED_SECRET_PD1 | PDB_ECC_ECDSEL(curve) |
653 pdb_sgt_flags);
654 /* Public key */
655 caam_desc_add_ptr(desc, ecckey.xy.paddr);
656 /* Private key */
657 caam_desc_add_ptr(desc, ecckey.d.paddr);
658 /* Output secret */
659 caam_desc_add_ptr(desc, secret.sgtbuf.paddr);
660
661 caam_desc_add_word(desc, SHARED_SECRET(ECC));
662 desclen = caam_desc_get_len(desc);
663 caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1));
664
665 ECC_DUMPDESC(desc);
666
667 jobctx.desc = desc;
668
669 retstatus = caam_jr_enqueue(&jobctx, NULL);
670
671 if (retstatus == CAAM_NO_ERROR) {
672 sdata->secret.length = caam_dmaobj_copy_to_orig(&secret);
673
674 ECC_DUMPBUF("Secret", sdata->secret.data, sdata->secret.length);
675
676 ret = caam_status_to_tee_result(retstatus);
677 } else {
678 ECC_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status);
679 ret = job_status_to_tee_result(jobctx.status);
680 }
681
682 out:
683 caam_free_desc(&desc);
684 do_keypair_free(&ecckey);
685 caam_dmaobj_free(&secret);
686
687 return ret;
688 }
689
690 /*
691 * Registration of the ECC Driver
692 */
693 static struct drvcrypt_ecc driver_ecc = {
694 .alloc_keypair = do_allocate_keypair,
695 .alloc_publickey = do_allocate_publickey,
696 .free_publickey = do_free_publickey,
697 .gen_keypair = do_gen_keypair,
698 .sign = do_sign,
699 .verify = do_verify,
700 .shared_secret = do_shared_secret,
701 };
702
caam_ecc_init(struct caam_jrcfg * caam_jrcfg)703 enum caam_status caam_ecc_init(struct caam_jrcfg *caam_jrcfg)
704 {
705 enum caam_status retstatus = CAAM_FAILURE;
706 vaddr_t jr_base = caam_jrcfg->base + caam_jrcfg->offset;
707
708 if (caam_hal_ctrl_pknum(jr_base))
709 if (drvcrypt_register_ecc(&driver_ecc) == TEE_SUCCESS)
710 retstatus = CAAM_NO_ERROR;
711
712 return retstatus;
713 }
714