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