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