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