xref: /optee_os/core/drivers/crypto/caam/acipher/caam_dsa.c (revision 014494479f9d6c334b4494235a68c1bb1dff902a)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright 2019-2021, 2023 NXP
4  *
5  * Implementation of DSA 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_key.h>
12 #include <caam_utils_mem.h>
13 #include <caam_utils_status.h>
14 #include <drvcrypt.h>
15 #include <drvcrypt_acipher.h>
16 #include <mm/core_memprot.h>
17 #include <tee/cache.h>
18 #include <string.h>
19 
20 #include "local.h"
21 #include "utee_types.h"
22 
23 #ifdef CFG_CAAM_64BIT
24 #define MAX_DESC_KEY_GEN 14
25 #define MAX_DESC_SIGN    19
26 #define MAX_DESC_VERIFY  21
27 #else
28 #define MAX_DESC_KEY_GEN 9
29 #define MAX_DESC_SIGN    12
30 #define MAX_DESC_VERIFY  13
31 #endif
32 
33 /*
34  * Definition of the local DSA Keypair
35  *   Domain Parameters (p, q, g)
36  *   Private Key format (x)
37  *   Public Key format (y)
38  */
39 struct caam_dsa_keypair {
40 	struct caambuf g; /* Generator */
41 	struct caambuf p; /* Prime Number (L bits) */
42 	struct caambuf q; /* Subprime Number (N bits) */
43 	struct caamkey x; /* Private key */
44 	struct caambuf y; /* Public key */
45 };
46 
47 /*
48  * Free local DSA keypair
49  *
50  * @key  DSA keypair
51  */
do_keypair_free(struct caam_dsa_keypair * key)52 static void do_keypair_free(struct caam_dsa_keypair *key)
53 {
54 	caam_free_buf(&key->g);
55 	caam_free_buf(&key->p);
56 	caam_free_buf(&key->q);
57 	caam_key_free(&key->x);
58 	caam_free_buf(&key->y);
59 }
60 
61 /*
62  * If all DSA parameters p, q and g are present, convert them from bignumbers
63  * to local buffers (via keypair object). Otherwise generate them.
64  *
65  * @outkey    [out] Output keypair in local format
66  * @key       Input key in TEE Crypto format
67  * @l_bytes   Prime p size in bytes
68  * @n_bytes   Subprime q size in bytes
69  */
get_keypair_domain_params(struct caam_dsa_keypair * outkey,const struct dsa_keypair * key,size_t l_bytes,size_t n_bytes)70 static TEE_Result get_keypair_domain_params(struct caam_dsa_keypair *outkey,
71 					    const struct dsa_keypair *key,
72 					    size_t l_bytes, size_t n_bytes)
73 {
74 	enum caam_status retstatus = CAAM_OUT_MEMORY;
75 	size_t in_q_size = 0;
76 	size_t in_p_size = 0;
77 	size_t in_g_size = 0;
78 	struct prime_data_dsa prime = { };
79 
80 	DSA_TRACE("DSA conv key param (p, g) of %zu bytes and (q) of %zu bytes",
81 		  l_bytes, n_bytes);
82 
83 	retstatus = caam_calloc_buf(&outkey->q, n_bytes);
84 	if (retstatus != CAAM_NO_ERROR)
85 		return caam_status_to_tee_result(retstatus);
86 
87 	retstatus = caam_calloc_buf(&outkey->g, l_bytes);
88 	if (retstatus != CAAM_NO_ERROR)
89 		return caam_status_to_tee_result(retstatus);
90 
91 	retstatus = caam_calloc_buf(&outkey->p, l_bytes);
92 	if (retstatus != CAAM_NO_ERROR)
93 		return caam_status_to_tee_result(retstatus);
94 
95 	/*
96 	 * Get all inputs parameters size, if one of them is not
97 	 * define generate new parameters
98 	 */
99 	in_g_size = crypto_bignum_num_bytes(key->g);
100 	in_p_size = crypto_bignum_num_bytes(key->p);
101 	in_q_size = crypto_bignum_num_bytes(key->q);
102 
103 	if (!in_q_size || !in_g_size || !in_p_size) {
104 		/* Generate DSA parameters: Generator G and Primes P/Q */
105 		prime.g = &outkey->g;
106 		prime.p = &outkey->p;
107 		prime.q = &outkey->q;
108 
109 		retstatus = caam_prime_dsa_gen(&prime);
110 		DSA_TRACE("Generate G and Primes P/Q returned %#x", retstatus);
111 
112 		if (retstatus != CAAM_NO_ERROR)
113 			return caam_status_to_tee_result(retstatus);
114 
115 		/* Copy Generated DSA Parameter */
116 		crypto_bignum_bin2bn(outkey->q.data, outkey->q.length, key->q);
117 		crypto_bignum_bin2bn(outkey->g.data, outkey->g.length, key->g);
118 		crypto_bignum_bin2bn(outkey->p.data, outkey->p.length, key->p);
119 
120 	} else {
121 		DSA_TRACE("Prime Q is defined");
122 
123 		crypto_bignum_bn2bin(key->q,
124 				     outkey->q.data + n_bytes - in_q_size);
125 		cache_operation(TEE_CACHECLEAN, outkey->q.data,
126 				outkey->q.length);
127 
128 		DSA_TRACE("Prime G is defined");
129 		crypto_bignum_bn2bin(key->g,
130 				     outkey->g.data + l_bytes - in_g_size);
131 		cache_operation(TEE_CACHECLEAN, outkey->g.data,
132 				outkey->g.length);
133 
134 		DSA_TRACE("Prime P is defined");
135 		crypto_bignum_bn2bin(key->p,
136 				     outkey->p.data + l_bytes - in_p_size);
137 		cache_operation(TEE_CACHECLEAN, outkey->p.data,
138 				outkey->p.length);
139 	}
140 
141 	return TEE_SUCCESS;
142 }
143 
144 /*
145  * Convert Crypto DSA Private Key to local Keypair Key
146  *
147  * @outkey    [out] Output keypair in local format
148  * @inkey     Input key in TEE Crypto format
149  * @l_bytes   Prime p size in bytes
150  * @n_bytes   Subprime q size in bytes
151  */
do_keypriv_conv(struct caam_dsa_keypair * outkey,const struct dsa_keypair * inkey,size_t l_bytes,size_t n_bytes)152 static enum caam_status do_keypriv_conv(struct caam_dsa_keypair *outkey,
153 					const struct dsa_keypair *inkey,
154 					size_t l_bytes, size_t n_bytes)
155 {
156 	enum caam_status retstatus = CAAM_OUT_MEMORY;
157 	size_t field_size = 0;
158 
159 	DSA_TRACE("DSA Convert Key Private size l=%zu bytes, n=%zu bytes",
160 		  l_bytes, n_bytes);
161 
162 	/* Generator */
163 	retstatus = caam_calloc_buf(&outkey->g, l_bytes);
164 	if (retstatus != CAAM_NO_ERROR)
165 		return retstatus;
166 
167 	/* Get the number of bytes of g to pad with 0's */
168 	field_size = crypto_bignum_num_bytes(inkey->g);
169 	crypto_bignum_bn2bin(inkey->g, outkey->g.data + l_bytes - field_size);
170 
171 	/* Prime Number Modulus */
172 	retstatus = caam_calloc_buf(&outkey->p, l_bytes);
173 	if (retstatus != CAAM_NO_ERROR)
174 		return retstatus;
175 
176 	/* Get the number of bytes of p to pad with 0's */
177 	field_size = crypto_bignum_num_bytes(inkey->p);
178 	crypto_bignum_bn2bin(inkey->p, outkey->p.data + l_bytes - field_size);
179 
180 	/* Subprime Number Modulus */
181 	retstatus = caam_calloc_buf(&outkey->q, n_bytes);
182 	if (retstatus != CAAM_NO_ERROR)
183 		return retstatus;
184 
185 	/* Get the number of bytes of q to pad with 0's */
186 	field_size = crypto_bignum_num_bytes(inkey->q);
187 	crypto_bignum_bn2bin(inkey->q, outkey->q.data + n_bytes - field_size);
188 
189 	retstatus = caam_key_deserialize_from_bn(inkey->x, &outkey->x, n_bytes);
190 	if (retstatus != CAAM_NO_ERROR)
191 		return retstatus;
192 
193 	cache_operation(TEE_CACHECLEAN, outkey->g.data, outkey->g.length);
194 	cache_operation(TEE_CACHECLEAN, outkey->p.data, outkey->p.length);
195 	cache_operation(TEE_CACHECLEAN, outkey->q.data, outkey->q.length);
196 	caam_key_cache_op(TEE_CACHECLEAN, &outkey->x);
197 
198 	return CAAM_NO_ERROR;
199 }
200 
201 /*
202  * Convert Crypto DSA Public Key to local DSA Keypair Key
203  *
204  * @outkey    [out] Output keypair in local format
205  * @inkey     Input key in TEE Crypto format
206  * @l_bytes   Prime p size in bytes
207  * @n_bytes   Subprime q size in bytes
208  */
do_keypub_conv(struct caam_dsa_keypair * outkey,const struct dsa_public_key * inkey,size_t l_bytes,size_t n_bytes)209 static enum caam_status do_keypub_conv(struct caam_dsa_keypair *outkey,
210 				       const struct dsa_public_key *inkey,
211 				       size_t l_bytes, size_t n_bytes)
212 {
213 	enum caam_status retstatus = CAAM_OUT_MEMORY;
214 	size_t field_size = 0;
215 
216 	DSA_TRACE("DSA Convert Public Key size l=%zu bytes, n=%zu bytes",
217 		  l_bytes, n_bytes);
218 
219 	/* Generator */
220 	retstatus = caam_calloc_buf(&outkey->g, l_bytes);
221 	if (retstatus != CAAM_NO_ERROR)
222 		return retstatus;
223 
224 	/* Get the number of bytes of g to pad with 0's */
225 	field_size = crypto_bignum_num_bytes(inkey->g);
226 	crypto_bignum_bn2bin(inkey->g, outkey->g.data + l_bytes - field_size);
227 
228 	/* Prime Number Modulus */
229 	retstatus = caam_calloc_buf(&outkey->p, l_bytes);
230 	if (retstatus != CAAM_NO_ERROR)
231 		return retstatus;
232 
233 	/* Get the number of bytes of p to pad with 0's */
234 	field_size = crypto_bignum_num_bytes(inkey->p);
235 	crypto_bignum_bn2bin(inkey->p, outkey->p.data + l_bytes - field_size);
236 
237 	/* Subprime Number Modulus */
238 	retstatus = caam_calloc_buf(&outkey->q, n_bytes);
239 	if (retstatus != CAAM_NO_ERROR)
240 		return retstatus;
241 
242 	/* Get the number of bytes of q to pad with 0's */
243 	field_size = crypto_bignum_num_bytes(inkey->q);
244 	crypto_bignum_bn2bin(inkey->q, outkey->q.data + n_bytes - field_size);
245 
246 	/* Public key is only scalar y of l bytes */
247 	retstatus = caam_calloc_buf(&outkey->y, l_bytes);
248 	if (retstatus != CAAM_NO_ERROR)
249 		return retstatus;
250 
251 	/* Get the number of bytes of y to pad with 0's */
252 	field_size = crypto_bignum_num_bytes(inkey->y);
253 	crypto_bignum_bn2bin(inkey->y, outkey->y.data + l_bytes - field_size);
254 
255 	cache_operation(TEE_CACHECLEAN, outkey->g.data, outkey->g.length);
256 	cache_operation(TEE_CACHECLEAN, outkey->p.data, outkey->p.length);
257 	cache_operation(TEE_CACHECLEAN, outkey->q.data, outkey->q.length);
258 	cache_operation(TEE_CACHECLEAN, outkey->y.data, outkey->y.length);
259 
260 	return CAAM_NO_ERROR;
261 }
262 
263 /*
264  * Allocate a TEE DSA keypair.
265  *
266  * @key        Keypair
267  * @l_bits     L bits size (prime p size)
268  * @n_bits     N bits size (subprime q size)
269  */
do_allocate_keypair(struct dsa_keypair * key,size_t l_bits,size_t n_bits)270 static TEE_Result do_allocate_keypair(struct dsa_keypair *key, size_t l_bits,
271 				      size_t n_bits)
272 {
273 	DSA_TRACE("DSA allocate Keypair of L=%zu bits and N=%zu bits", l_bits,
274 		  n_bits);
275 
276 	/* Initialize the key fields to NULL */
277 	memset(key, 0, sizeof(*key));
278 
279 	/* Allocate Generator Scalar */
280 	key->g = crypto_bignum_allocate(l_bits);
281 	if (!key->g)
282 		goto err;
283 
284 	/* Allocate Prime Number Modulus */
285 	key->p = crypto_bignum_allocate(l_bits);
286 	if (!key->p)
287 		goto err;
288 
289 	/* Allocate Prime Number Modulus */
290 	key->q = crypto_bignum_allocate(n_bits);
291 	if (!key->q)
292 		goto err;
293 
294 	/* Allocate Private key X */
295 	key->x = crypto_bignum_allocate(CFG_CORE_BIGNUM_MAX_BITS);
296 	if (!key->x)
297 		goto err;
298 
299 	/* Allocate Public Key Y */
300 	key->y = crypto_bignum_allocate(l_bits);
301 	if (!key->y)
302 		goto err;
303 
304 	return TEE_SUCCESS;
305 
306 err:
307 	DSA_TRACE("Allocation error");
308 
309 	crypto_bignum_free(&key->g);
310 	crypto_bignum_free(&key->p);
311 	crypto_bignum_free(&key->q);
312 	crypto_bignum_free(&key->x);
313 
314 	return TEE_ERROR_OUT_OF_MEMORY;
315 }
316 
317 /*
318  * Allocate a DSA Public Key
319  *
320  * @key        Public Key
321  * @l_bits     L bits size (prime p size)
322  * @n_bits     N bits size (subprime q size)
323  */
do_allocate_publickey(struct dsa_public_key * key,size_t l_bits,size_t n_bits)324 static TEE_Result do_allocate_publickey(struct dsa_public_key *key,
325 					size_t l_bits, size_t n_bits)
326 {
327 	DSA_TRACE("DSA Allocate Public of L=%zu bits and N=%zu bits", l_bits,
328 		  n_bits);
329 
330 	/* Initialize the key fields to NULL */
331 	memset(key, 0, sizeof(*key));
332 
333 	/* Allocate Generator Scalar */
334 	key->g = crypto_bignum_allocate(l_bits);
335 	if (!key->g)
336 		goto err;
337 
338 	/* Allocate Prime Number Modulus */
339 	key->p = crypto_bignum_allocate(l_bits);
340 	if (!key->p)
341 		goto err;
342 
343 	/* Allocate Prime Number Modulus */
344 	key->q = crypto_bignum_allocate(n_bits);
345 	if (!key->q)
346 		goto err;
347 
348 	/* Allocate Public Key Y */
349 	key->y = crypto_bignum_allocate(l_bits);
350 	if (!key->y)
351 		goto err;
352 
353 	return TEE_SUCCESS;
354 
355 err:
356 	DSA_TRACE("Allocation error");
357 
358 	crypto_bignum_free(&key->g);
359 	crypto_bignum_free(&key->p);
360 	crypto_bignum_free(&key->q);
361 
362 	return TEE_ERROR_OUT_OF_MEMORY;
363 }
364 
365 /*
366  * Generates an DSA keypair
367  * Keypair @key contains the input primes p, g and generator g values
368  * The function computes private x and public y.
369  *
370  * @key        [in/out] Keypair
371  * @l_bits     L bits size (prime p size)
372  * @n_bits     N bits size (subprime q size)
373  */
do_gen_keypair(struct dsa_keypair * key,size_t l_bits,size_t n_bits)374 static TEE_Result do_gen_keypair(struct dsa_keypair *key, size_t l_bits,
375 				 size_t n_bits)
376 {
377 	TEE_Result ret = TEE_ERROR_GENERIC;
378 	enum caam_status retstatus = CAAM_FAILURE;
379 	struct caam_dsa_keypair caam_dsa_key = { };
380 	struct caam_jobctx jobctx = { };
381 	uint32_t *desc = NULL;
382 	uint32_t desclen = 0;
383 	size_t l_bytes = l_bits / 8;
384 	size_t n_bytes = n_bits / 8;
385 	enum caam_key_type key_type = caam_key_default_key_gen_type();
386 
387 	DSA_TRACE("Generate Key - Private (%zu bits) and Public (%zu bits)",
388 		  n_bits, l_bits);
389 
390 	/* Allocate the job used to prepare the operation */
391 	desc = caam_calloc_desc(MAX_DESC_KEY_GEN);
392 	if (!desc) {
393 		ret = TEE_ERROR_OUT_OF_MEMORY;
394 		goto out;
395 	}
396 
397 	/* Allocate Private Key to be generated */
398 	caam_dsa_key.x.key_type = caam_key_default_key_gen_type();
399 	caam_dsa_key.x.sec_size = n_bytes;
400 	caam_dsa_key.x.is_blob = false;
401 
402 	retstatus = caam_key_alloc(&caam_dsa_key.x);
403 	if (retstatus != CAAM_NO_ERROR) {
404 		ret = caam_status_to_tee_result(retstatus);
405 		goto out;
406 	}
407 
408 	caam_key_cache_op(TEE_CACHEFLUSH, &caam_dsa_key.x);
409 
410 	/* Allocate Public Key to be generated */
411 	retstatus = caam_calloc_align_buf(&caam_dsa_key.y, l_bytes);
412 	if (retstatus != CAAM_NO_ERROR) {
413 		ret = caam_status_to_tee_result(retstatus);
414 		goto out;
415 	}
416 	cache_operation(TEE_CACHEFLUSH, caam_dsa_key.y.data,
417 			caam_dsa_key.y.length);
418 
419 	/* Generator and Prime */
420 	ret = get_keypair_domain_params(&caam_dsa_key, key, l_bytes, n_bytes);
421 	if (ret != TEE_SUCCESS)
422 		goto out;
423 
424 	/*
425 	 * Build the descriptor using the PDB Public Key generation
426 	 * block (PD=0)
427 	 */
428 	caam_desc_init(desc);
429 	caam_desc_add_word(desc, DESC_HEADER(0));
430 	caam_desc_add_word(desc, PDB_DL_KEY_L_SIZE(l_bytes) |
431 				 PDB_DL_KEY_N_SIZE(n_bytes));
432 	caam_desc_add_ptr(desc, caam_dsa_key.p.paddr);
433 	caam_desc_add_ptr(desc, caam_dsa_key.q.paddr);
434 	caam_desc_add_ptr(desc, caam_dsa_key.g.paddr);
435 	caam_desc_add_ptr(desc, caam_dsa_key.x.buf.paddr);
436 	caam_desc_add_ptr(desc, caam_dsa_key.y.paddr);
437 
438 	switch (key_type) {
439 	case CAAM_KEY_PLAIN_TEXT:
440 		caam_desc_add_word(desc, PK_KEYPAIR_GEN(DL, NONE));
441 		break;
442 	case CAAM_KEY_BLACK_ECB:
443 		caam_desc_add_word(desc, PK_KEYPAIR_GEN(DL, ECB));
444 		break;
445 	case CAAM_KEY_BLACK_CCM:
446 		caam_desc_add_word(desc, PK_KEYPAIR_GEN(DL, CCM));
447 		break;
448 	default:
449 		ret = TEE_ERROR_GENERIC;
450 		goto out;
451 	}
452 
453 	desclen = caam_desc_get_len(desc);
454 	caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1));
455 
456 	DSA_DUMPDESC(desc);
457 
458 	jobctx.desc = desc;
459 	retstatus = caam_jr_enqueue(&jobctx, NULL);
460 
461 	if (retstatus == CAAM_NO_ERROR) {
462 		caam_key_cache_op(TEE_CACHEINVALIDATE, &caam_dsa_key.x);
463 
464 		cache_operation(TEE_CACHEINVALIDATE, caam_dsa_key.y.data,
465 				caam_dsa_key.y.length);
466 
467 		/* Copy Private and Public keypair */
468 		ret = caam_key_serialize_to_bn(key->x, &caam_dsa_key.x);
469 		if (ret != TEE_SUCCESS)
470 			goto out;
471 
472 		ret = crypto_bignum_bin2bn(caam_dsa_key.y.data,
473 					   caam_dsa_key.y.length, key->y);
474 		if (ret != TEE_SUCCESS)
475 			goto out;
476 
477 		DSA_DUMPBUF("X", caam_dsa_key.x.buf.data,
478 			    caam_dsa_key.x.buf.length);
479 		DSA_DUMPBUF("Y", caam_dsa_key.y.data, caam_dsa_key.y.length);
480 	} else {
481 		DSA_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status);
482 		ret = job_status_to_tee_result(jobctx.status);
483 	}
484 
485 out:
486 	caam_free_desc(&desc);
487 	do_keypair_free(&caam_dsa_key);
488 
489 	return ret;
490 }
491 
492 /*
493  * Signature of DSA message
494  * Note : the message to sign is already hashed
495  *
496  * @sdata    [in/out] DSA data to sign / Signature
497  * @l_bytes  L bytes size (prime p size)
498  * @n_bytes  N bytes size (subprime q size)
499  */
do_sign(struct drvcrypt_sign_data * sdata,size_t l_bytes,size_t n_bytes)500 static TEE_Result do_sign(struct drvcrypt_sign_data *sdata, size_t l_bytes,
501 			  size_t n_bytes)
502 {
503 	TEE_Result ret = TEE_ERROR_GENERIC;
504 	enum caam_status retstatus = CAAM_FAILURE;
505 	struct dsa_keypair *inkey = sdata->key;
506 	struct caam_dsa_keypair dsakey = { };
507 	struct caam_jobctx jobctx = { };
508 	uint32_t *desc = NULL;
509 	uint32_t desclen = 0;
510 	struct caamdmaobj msg = { };
511 	size_t sign_len = 0;
512 	struct caamdmaobj sign_c = { };
513 	struct caamdmaobj sign_d = { };
514 	uint32_t pdb_sgt_flags = 0;
515 
516 	DSA_TRACE("DSA Signature");
517 
518 	/* Allocate the job descriptor */
519 	desc = caam_calloc_desc(MAX_DESC_SIGN);
520 	if (!desc) {
521 		ret = TEE_ERROR_OUT_OF_MEMORY;
522 		goto out;
523 	}
524 
525 	/* Convert the private key to a local key */
526 	retstatus = do_keypriv_conv(&dsakey, inkey, l_bytes, n_bytes);
527 	if (retstatus != CAAM_NO_ERROR) {
528 		ret = caam_status_to_tee_result(retstatus);
529 		goto out;
530 	}
531 
532 	/* Prepare the input message CAAM Descriptor entry */
533 	ret = caam_dmaobj_input_sgtbuf(&msg, sdata->message.data,
534 				       sdata->message.length);
535 	if (ret)
536 		goto out;
537 
538 	if (msg.sgtbuf.sgt_type)
539 		pdb_sgt_flags |= PDB_SGT_PKSIGN_MSG;
540 
541 	caam_dmaobj_cache_push(&msg);
542 
543 	DSA_DUMPBUF("Message", sdata->message.data, sdata->message.length);
544 
545 	/*
546 	 * Re-allocate the signature result buffer with a maximum size
547 	 * of the roundup to 16 bytes of the secure size in bytes if
548 	 * the signature buffer is not aligned or too short.
549 	 *
550 	 *  - 1st Part: size_sec
551 	 *  - 2nd Part: size_sec roundup to 16 bytes
552 	 */
553 	sign_len = ROUNDUP(sdata->size_sec, 16) + sdata->size_sec;
554 
555 	ret = caam_dmaobj_output_sgtbuf(&sign_c, sdata->signature.data,
556 					sdata->signature.length, sign_len);
557 	if (ret)
558 		goto out;
559 
560 	if (sign_c.sgtbuf.sgt_type)
561 		pdb_sgt_flags |= PDB_SGT_PKSIGN_SIGN_C;
562 
563 	/* Prepare the 2nd Part of the signature. Derive from sign_c */
564 	ret = caam_dmaobj_derive_sgtbuf(&sign_d, &sign_c, sdata->size_sec,
565 					ROUNDUP(sdata->size_sec, 16));
566 	if (ret)
567 		goto out;
568 
569 	if (sign_d.sgtbuf.sgt_type)
570 		pdb_sgt_flags |= PDB_SGT_PKSIGN_SIGN_D;
571 
572 	caam_dmaobj_cache_push(&sign_c);
573 
574 	/*
575 	 * Build the descriptor using Predifined ECC curve
576 	 */
577 	caam_desc_init(desc);
578 	caam_desc_add_word(desc, DESC_HEADER(0));
579 	caam_desc_add_word(desc, PDB_DSA_SIGN_N(n_bytes) |
580 				 PDB_DSA_SIGN_L(l_bytes) | pdb_sgt_flags);
581 	/* Prime number */
582 	caam_desc_add_ptr(desc, dsakey.p.paddr);
583 	/* Prime Modulus */
584 	caam_desc_add_ptr(desc, dsakey.q.paddr);
585 	/* Generator */
586 	caam_desc_add_ptr(desc, dsakey.g.paddr);
587 	/* Secret key */
588 	caam_desc_add_ptr(desc, dsakey.x.buf.paddr);
589 	/* Input message */
590 	caam_desc_add_ptr(desc, msg.sgtbuf.paddr);
591 	/* Signature 1st part */
592 	caam_desc_add_ptr(desc, sign_c.sgtbuf.paddr);
593 	/* Signature 2nd part */
594 	caam_desc_add_ptr(desc, sign_d.sgtbuf.paddr);
595 	/* Message length */
596 	caam_desc_add_word(desc, sdata->message.length);
597 
598 	switch (dsakey.x.key_type) {
599 	case CAAM_KEY_PLAIN_TEXT:
600 		caam_desc_add_word(desc, DSA_SIGN(DL, HASHED, NONE));
601 		break;
602 	case CAAM_KEY_BLACK_ECB:
603 		caam_desc_add_word(desc, DSA_SIGN(DL, HASHED, ECB));
604 		break;
605 	case CAAM_KEY_BLACK_CCM:
606 		caam_desc_add_word(desc, DSA_SIGN(DL, HASHED, CCM));
607 		break;
608 	default:
609 		ret = TEE_ERROR_GENERIC;
610 		goto out;
611 	}
612 
613 	desclen = caam_desc_get_len(desc);
614 	caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1));
615 
616 	ECC_DUMPDESC(desc);
617 
618 	jobctx.desc = desc;
619 
620 	retstatus = caam_jr_enqueue(&jobctx, NULL);
621 	if (retstatus == CAAM_NO_ERROR) {
622 		/* Limit the copy to 2 * sdata->size_sec */
623 		sign_c.orig.length = 2 * sdata->size_sec;
624 		sdata->signature.length = caam_dmaobj_copy_to_orig(&sign_c);
625 
626 		DSA_DUMPBUF("Signature", sdata->signature.data,
627 			    sdata->signature.length);
628 
629 		ret = caam_status_to_tee_result(retstatus);
630 	} else {
631 		DSA_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status);
632 		ret = job_status_to_tee_result(jobctx.status);
633 	}
634 
635 out:
636 	caam_free_desc(&desc);
637 	do_keypair_free(&dsakey);
638 	caam_dmaobj_free(&msg);
639 	caam_dmaobj_free(&sign_c);
640 	caam_dmaobj_free(&sign_d);
641 
642 	return ret;
643 }
644 
645 /*
646  * Verification of the Signature of DSA message
647  * Note the message is already hashed
648  *
649  * @sdata   [in/out] DSA Signature to verify
650  * @l_bytes  L bytes size (prime p size)
651  * @n_bytes  N bytes size (subprime q size)
652  */
do_verify(struct drvcrypt_sign_data * sdata,size_t l_bytes,size_t n_bytes)653 static TEE_Result do_verify(struct drvcrypt_sign_data *sdata, size_t l_bytes,
654 			    size_t n_bytes)
655 {
656 	TEE_Result ret = TEE_ERROR_GENERIC;
657 	enum caam_status retstatus = CAAM_FAILURE;
658 	struct dsa_public_key *inkey = sdata->key;
659 	struct caam_dsa_keypair dsakey = { };
660 	struct caambuf tmp = { };
661 	struct caam_jobctx jobctx = { };
662 	uint32_t *desc = NULL;
663 	uint32_t desclen = 0;
664 	struct caamdmaobj msg = { };
665 	struct caamdmaobj sign_c = { };
666 	struct caamdmaobj sign_d = { };
667 	uint32_t pdb_sgt_flags = 0;
668 
669 	DSA_TRACE("DSA Verify");
670 
671 	/* Allocate the job descriptor */
672 	desc = caam_calloc_desc(MAX_DESC_VERIFY);
673 	if (!desc) {
674 		ret = TEE_ERROR_OUT_OF_MEMORY;
675 		goto out;
676 	}
677 
678 	/* Convert the Public key to local key */
679 	retstatus = do_keypub_conv(&dsakey, inkey, l_bytes, n_bytes);
680 	if (retstatus != CAAM_NO_ERROR) {
681 		ret = caam_status_to_tee_result(retstatus);
682 		goto out;
683 	}
684 
685 	/* Prepare the input message CAAM Descriptor entry */
686 	ret = caam_dmaobj_input_sgtbuf(&msg, sdata->message.data,
687 				       sdata->message.length);
688 	if (ret)
689 		goto out;
690 
691 	if (msg.sgtbuf.sgt_type)
692 		pdb_sgt_flags |= PDB_SGT_PKVERIF_MSG;
693 
694 	caam_dmaobj_cache_push(&msg);
695 
696 	/*
697 	 * Prepare the 1st Part of the signature
698 	 * Handle the full signature in case signature buffer needs to
699 	 * be reallocated.
700 	 */
701 	ret = caam_dmaobj_input_sgtbuf(&sign_c, sdata->signature.data,
702 				       sdata->signature.length);
703 	if (ret)
704 		goto out;
705 
706 	if (sign_c.sgtbuf.sgt_type)
707 		pdb_sgt_flags |= PDB_SGT_PKVERIF_SIGN_C;
708 
709 	/* Prepare the 2nd Part of the signature, derive from sign_c */
710 	ret = caam_dmaobj_derive_sgtbuf(&sign_d, &sign_c, sdata->size_sec,
711 					sdata->size_sec);
712 	if (ret)
713 		goto out;
714 
715 	if (sign_d.sgtbuf.sgt_type)
716 		pdb_sgt_flags |= PDB_SGT_PKVERIF_SIGN_D;
717 
718 	caam_dmaobj_cache_push(&sign_c);
719 
720 	/* Allocate a Temporary buffer used by the CAAM */
721 	retstatus = caam_alloc_align_buf(&tmp, l_bytes);
722 	if (retstatus != CAAM_NO_ERROR) {
723 		ret = caam_status_to_tee_result(retstatus);
724 		goto out;
725 	}
726 
727 	/*
728 	 * Build the descriptor using Predifined ECC curve
729 	 */
730 	caam_desc_init(desc);
731 	caam_desc_add_word(desc, DESC_HEADER(0));
732 	caam_desc_add_word(desc, PDB_DSA_VERIF_N(n_bytes) |
733 				 PDB_DSA_VERIF_L(l_bytes) | pdb_sgt_flags);
734 	/* Prime number */
735 	caam_desc_add_ptr(desc, dsakey.p.paddr);
736 	/* Prime Modulus */
737 	caam_desc_add_ptr(desc, dsakey.q.paddr);
738 	/* Generator */
739 	caam_desc_add_ptr(desc, dsakey.g.paddr);
740 	/* Public key */
741 	caam_desc_add_ptr(desc, dsakey.y.paddr);
742 	/* Input message */
743 	caam_desc_add_ptr(desc, msg.sgtbuf.paddr);
744 	/* Signature 1st part */
745 	caam_desc_add_ptr(desc, sign_c.sgtbuf.paddr);
746 	/* Signature 2nd part */
747 	caam_desc_add_ptr(desc, sign_d.sgtbuf.paddr);
748 	/* Temporary buffer */
749 	caam_desc_add_ptr(desc, tmp.paddr);
750 	/* Message length */
751 	caam_desc_add_word(desc, sdata->message.length);
752 
753 	caam_desc_add_word(desc, DSA_VERIFY(DL, HASHED));
754 	desclen = caam_desc_get_len(desc);
755 	caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1));
756 
757 	DSA_DUMPDESC(desc);
758 
759 	jobctx.desc = desc;
760 
761 	cache_operation(TEE_CACHEFLUSH, tmp.data, tmp.length);
762 
763 	retstatus = caam_jr_enqueue(&jobctx, NULL);
764 	if (retstatus == CAAM_JOB_STATUS && !jobctx.status) {
765 		DSA_TRACE("DSA Verify Status 0x%08" PRIx32, jobctx.status);
766 		ret = TEE_ERROR_SIGNATURE_INVALID;
767 	} else if (retstatus != CAAM_NO_ERROR) {
768 		DSA_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status);
769 		ret = job_status_to_tee_result(jobctx.status);
770 	} else {
771 		ret = caam_status_to_tee_result(retstatus);
772 	}
773 
774 out:
775 	caam_free_desc(&desc);
776 	do_keypair_free(&dsakey);
777 	caam_free_buf(&tmp);
778 	caam_dmaobj_free(&msg);
779 	caam_dmaobj_free(&sign_c);
780 	caam_dmaobj_free(&sign_d);
781 
782 	return ret;
783 }
784 
785 /*
786  * Registration of the DSA Driver
787  */
788 static struct drvcrypt_dsa driver_dsa = {
789 	.alloc_keypair = do_allocate_keypair,
790 	.alloc_publickey = do_allocate_publickey,
791 	.gen_keypair = do_gen_keypair,
792 	.sign = do_sign,
793 	.verify = do_verify,
794 };
795 
caam_dsa_init(struct caam_jrcfg * caam_jrcfg)796 enum caam_status caam_dsa_init(struct caam_jrcfg *caam_jrcfg)
797 {
798 	enum caam_status retstatus = CAAM_FAILURE;
799 	vaddr_t jr_base = caam_jrcfg->base + caam_jrcfg->offset;
800 
801 	if (caam_hal_ctrl_pknum(jr_base) &&
802 	    drvcrypt_register_dsa(&driver_dsa) == TEE_SUCCESS)
803 		retstatus = CAAM_NO_ERROR;
804 
805 	return retstatus;
806 }
807