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