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