1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright 2020-2021 NXP
4  *
5  * CAAM DSA Prime Numbering.
6  * Implementation of Prime Number functions
7  */
8 #include <caam_common.h>
9 #include <caam_desc_ccb_defines.h>
10 #include <caam_jr.h>
11 #include <caam_utils_mem.h>
12 #include <crypto/crypto.h>
13 #include <kernel/panic.h>
14 #include <mm/core_memprot.h>
15 #include <string.h>
16 #include <tee_api_types.h>
17 #include <tee/cache.h>
18 
19 #include "local.h"
20 
21 #define PRIME_DESC_ENTRIES 62
22 
23 /* Define the number max of try to generate valid primes */
24 #define DSA_MAX_TRIES_PRIME_Q 50000
25 #define DSA_MAX_TRIES_PRIME_P 500
26 
27 #define DSA_TRY_FAIL	    0x42
28 #define DSA_NOT_PRIME	    0x43
29 #define DSA_PRIME_TOO_SMALL 0x44
30 
31 struct dsa_hash {
32 	unsigned int op; /* CAAM Hash operation code */
33 	size_t size;	 /* Hash digest size */
34 };
35 
36 /*
37  * Build the descriptor generating a DSA prime Q
38  * Referring to FIPS.186-4, Section A.1.1.2 Generation of the
39  * Probable Primes p and q Using an Approved Hash Function
40  *
41  * @desc          [out] Descriptor built
42  * @seed          [out] Resulting seed used to generate prime
43  * @prime         [in/out] Prime generation data
44  * @hash_func     Selected Hash function
45  */
do_desc_prime_q(uint32_t * desc,struct caambuf * seed,struct prime_data_dsa * prime,struct dsa_hash * hash_func)46 static void do_desc_prime_q(uint32_t *desc, struct caambuf *seed,
47 			    struct prime_data_dsa *prime,
48 			    struct dsa_hash *hash_func)
49 {
50 	unsigned int desclen = 0;
51 	unsigned int retry_new_mr_failed = 0;
52 	unsigned int retry_mr_test = 0;
53 
54 	caam_desc_init(desc);
55 	caam_desc_add_word(desc, DESC_HEADER(0));
56 
57 	/* Set the PKHA N and A register size */
58 	caam_desc_add_word(desc, LD_IMM(CLASS_1, REG_PKHA_N_SIZE, 4));
59 	caam_desc_add_word(desc, prime->q->length);
60 	caam_desc_add_word(desc, LD_IMM(CLASS_1, REG_PKHA_A_SIZE, 4));
61 	caam_desc_add_word(desc, prime->q->length);
62 
63 	caam_desc_add_word(desc, MATH(ADD, ZERO, IMM_DATA, VSOL, 4));
64 	caam_desc_add_word(desc, DSA_MAX_TRIES_PRIME_Q);
65 
66 	caam_desc_add_word(desc, MATHI_OP1(SHIFT_L, ONE, 63, REG2, 8));
67 
68 	retry_new_mr_failed = caam_desc_get_len(desc);
69 
70 	/* Decrement the number of try */
71 	caam_desc_add_word(desc, MATH(SUB, VSOL, ONE, VSOL, 4));
72 	/* Exceed retry count - exit with DSA_TRY_FAIL error */
73 	caam_desc_add_word(desc,
74 			   HALT_USER(ALL_COND_TRUE, MATH_N, DSA_TRY_FAIL));
75 
76 	/* Clear Class 2 SHA */
77 	caam_desc_add_word(desc, LD_IMM(CLASS_NO, REG_CLEAR_WRITTEN, 4));
78 	caam_desc_add_word(desc, CLR_WR_RST_C2_CHA | CLR_WR_RST_C2_DSZ);
79 
80 	/*
81 	 * Step 5. Generate Random Seed
82 	 *
83 	 * Seed Length shall be equal or greater than N (Q prime length)
84 	 * Seed result push in Message Data
85 	 */
86 	if (seed->length > 16) {
87 		caam_desc_add_word(desc, LD_IMM(CLASS_NO, REG_NFIFO_n_SIZE, 4));
88 		caam_desc_add_word(desc, NFIFO_PAD(BOTH, 0, MSG, RND, 16));
89 
90 		caam_desc_add_word(desc, LD_IMM(CLASS_NO, REG_NFIFO_n_SIZE, 4));
91 		caam_desc_add_word(desc,
92 				   NFIFO_PAD(BOTH, NFIFO_LC1 | NFIFO_LC2, MSG,
93 					     RND, seed->length - 16));
94 	} else {
95 		caam_desc_add_word(desc, LD_IMM(CLASS_NO, REG_NFIFO_n_SIZE, 4));
96 		caam_desc_add_word(desc, NFIFO_PAD(BOTH, NFIFO_LC1 | NFIFO_LC2,
97 						   MSG, RND, seed->length));
98 	}
99 
100 	caam_desc_add_word(desc, MOVE(C1_ALIGN, OFIFO, 0, seed->length));
101 	caam_desc_add_word(desc, FIFO_ST(MSG_DATA, seed->length));
102 	caam_desc_add_ptr(desc, seed->paddr);
103 
104 	/*
105 	 * Hash the Seed, this is a pseudo U, bits upper N - 1 still present
106 	 */
107 	caam_desc_add_word(desc, HASH_INITFINAL(hash_func->op));
108 
109 	/*
110 	 * Step 6. U = hash(seed) mod 2^(N-1)
111 	 * Step 7. q = 2^(N-1) + U + 1 - (U mod 2)
112 	 */
113 	/* Trash the bits > N - 1, the hash size is >= N */
114 	caam_desc_add_word(desc,
115 			   MOVE_WAIT(C2_CTX_REG, MATH_REG0,
116 				     hash_func->size - prime->q->length, 8));
117 
118 	/* Get the MSB of U and set the bit N-1 */
119 	caam_desc_add_word(desc, MATH(OR, REG2, REG0, REG0, 8));
120 
121 	/* Move the candidate prime q's MSB into IFIFO */
122 	caam_desc_add_word(desc, MOVE_WAIT(MATH_REG0, IFIFO, 0, 8));
123 
124 	/*
125 	 * Move the candidate prime q's intermediate value into IFIFO
126 	 */
127 	caam_desc_add_word(desc,
128 			   MOVE_WAIT(C2_CTX_REG, IFIFO,
129 				     hash_func->size - prime->q->length + 8,
130 				     prime->q->length - 16));
131 
132 	/* Get the LSB of U and set the bit 0 */
133 	caam_desc_add_word(desc, MOVE_WAIT(C2_CTX_REG, MATH_REG0,
134 					   hash_func->size - 8, 8));
135 	caam_desc_add_word(desc, MATH(OR, ONE, REG0, REG0, 8));
136 
137 	/* Move the candidate prime q's LSB into IFIFO */
138 	caam_desc_add_word(desc, MOVE_WAIT(MATH_REG0, IFIFO, 0, 8));
139 
140 	/* Move the IFIFO in to PKHA N */
141 	caam_desc_add_word(desc, LD_IMM(CLASS_NO, REG_NFIFO, 8));
142 	caam_desc_add_word(desc, NFIFO_NOPAD(C1, NFIFO_FC1, IFIFO, PKHA_N, 0));
143 	caam_desc_add_word(desc, prime->q->length);
144 
145 	/* Store the Prime q here because Miller-Rabin test affect PKHA N */
146 	caam_desc_add_word(desc, FIFO_ST(PKHA_N, prime->q->length));
147 	caam_desc_add_ptr(desc, prime->q->paddr);
148 
149 	/*
150 	 * Step 8. Test q prime with 'miller-rabin' test
151 	 *
152 	 * Load the number of Miller-Rabin test iteration
153 	 */
154 	caam_desc_add_word(desc, MATH(ADD, IMM_DATA, ZERO, SIL, 4));
155 	if (prime->p->length <= 1024 / 8)
156 		caam_desc_add_word(desc, 40);
157 	else if (prime->p->length >= 3072 / 8)
158 		caam_desc_add_word(desc, 64);
159 	else
160 		caam_desc_add_word(desc, 56);
161 
162 	retry_mr_test = caam_desc_get_len(desc);
163 
164 	/* Generate 8 random bytes 'miller-rabin seed' */
165 	caam_desc_add_word(desc, LD_IMM(CLASS_NO, REG_NFIFO, 8));
166 	caam_desc_add_word(desc, NFIFO_PAD(C1, NFIFO_FC1, PKHA_A, RND, 0));
167 	caam_desc_add_word(desc, prime->q->length);
168 	caam_desc_add_word(desc, FIFO_LD_IMM(CLASS_1, PKHA_B, NOACTION, 1));
169 	caam_desc_add_word(desc, 0x01);
170 	caam_desc_add_word(desc, PKHA_OP(MR_PRIMER_TEST, B));
171 
172 	desclen = caam_desc_get_len(desc);
173 
174 	/*
175 	 * Step 9. If q is not q prime back to step 5
176 	 */
177 	caam_desc_add_word(desc, JUMP_CNO_LOCAL(ANY_COND_FALSE,
178 						JMP_COND(PKHA_IS_PRIME),
179 						retry_new_mr_failed - desclen));
180 	caam_desc_add_word(desc, MATH(SUB, SIL, ONE, SIL, 4));
181 
182 	desclen = caam_desc_get_len(desc);
183 	/* Test while number of MR test iteration not complete */
184 	caam_desc_add_word(desc,
185 			   JUMP_CNO_LOCAL(ALL_COND_FALSE,
186 					  JMP_COND(MATH_N) | JMP_COND(MATH_Z),
187 					  retry_mr_test - desclen));
188 	DSA_TRACE("Prime Q descriptor");
189 	DSA_DUMPDESC(desc);
190 }
191 
192 /*
193  * Build the descriptor generating the intermediate value X (step 11.3)
194  * Referring to FIPS.186-4, Section A.1.1.2 Generation of the
195  * Probable Primes p and q Using an Approved Hash Function
196  *
197  * @desc        [out] Descriptor built
198  * @x           [out] Value X
199  * @seed        [in/out] Seed to hash and next seed for next loop
200  * @prime       [in/out] Prime generation data
201  * @hash_func   Selected Hash function
202  * @mod_n       Modular value (0xFF filled buffer)
203  * @desc_p      Physical address of the descriptor doing Prime P
204  */
do_desc_gen_x(uint32_t * desc,struct caambuf * x,struct caambuf * seed,struct prime_data_dsa * prime,struct dsa_hash * hash_func,struct caambuf * mod_n,paddr_t desc_p)205 static void do_desc_gen_x(uint32_t *desc, struct caambuf *x,
206 			  struct caambuf *seed, struct prime_data_dsa *prime,
207 			  struct dsa_hash *hash_func, struct caambuf *mod_n,
208 			  paddr_t desc_p)
209 {
210 	unsigned int desclen = 0;
211 	unsigned int loop_n = 0;
212 	size_t n = 0;
213 	size_t b = 0;
214 	size_t b_offset = 0;
215 
216 	/*
217 	 * Step 3. n = ceil(L / outlen) - 1
218 	 * where outlen is the hash size in bits
219 	 *
220 	 * Note build descriptor with n = ceil(L / outlen) to
221 	 * pre-calculate seed for next run.
222 	 */
223 	n = (prime->p->length + hash_func->size) * 8 - 1;
224 	n /= hash_func->size * 8;
225 
226 	/*
227 	 * Step 4. b = L - 1 - (n  * outlen)
228 	 *
229 	 * Note b determine the number of bits to keep in the last
230 	 * Vn computed.
231 	 * Calculate b_offset which is the offset in bytes to remove from
232 	 * the calculated hash
233 	 */
234 	b = prime->p->length * 8 - 1 - (n - 1) * hash_func->size * 8;
235 
236 	DSA_TRACE("Prime p => n = %zu | b = %zu", n - 1, b);
237 	b_offset = hash_func->size - (b + 1) / 8;
238 	DSA_TRACE("Vn offset is %zu", b_offset);
239 
240 	caam_desc_init(desc);
241 	caam_desc_add_word(desc, DESC_HEADER(0));
242 
243 	caam_desc_add_word(desc, SEQ_OUT_PTR(x->length));
244 	caam_desc_add_ptr(desc, x->paddr);
245 
246 	caam_desc_add_word(desc, MATHI_OP1(SHIFT_L, ONE, 63, REG2, 8));
247 
248 	caam_desc_add_word(desc, MATH(ADD, ZERO, IMM_DATA, REG0, 4));
249 	caam_desc_add_word(desc, n);
250 
251 	caam_desc_add_word(desc,
252 			   FIFO_LD(CLASS_1, PKHA_N, NOACTION, seed->length));
253 	caam_desc_add_ptr(desc, mod_n->paddr);
254 
255 	/*
256 	 * Because the Sequence Out Pointer is incremental store, we need
257 	 * to build w number in reverse.
258 	 *
259 	 * Hence, calculate the last seed number of the loop and save it.
260 	 * Step 11.9 is automatically done here by incrementing seed number.
261 	 */
262 	caam_desc_add_word(desc, FIFO_LD_IMM(CLASS_1, PKHA_B, NOACTION, 1));
263 	caam_desc_add_word(desc, n);
264 	caam_desc_add_word(desc,
265 			   FIFO_LD(CLASS_1, PKHA_A, NOACTION, seed->length));
266 	caam_desc_add_ptr(desc, seed->paddr);
267 	caam_desc_add_word(desc, PKHA_OP(MOD_ADD_A_B, A));
268 	caam_desc_add_word(desc, FIFO_ST(PKHA_A, seed->length));
269 	caam_desc_add_ptr(desc, seed->paddr);
270 
271 	caam_desc_add_word(desc, PKHA_CPY_NSIZE(A0, B1));
272 	caam_desc_add_word(desc, FIFO_LD_IMM(CLASS_1, PKHA_B, NOACTION, 1));
273 	caam_desc_add_word(desc, 1);
274 
275 	caam_desc_add_word(desc, WAIT_COND(ALL_COND_TRUE, NIFP));
276 
277 	/*
278 	 * Step 11.1
279 	 * For j = 0 to n do
280 	 *    Vj = hash((seed + offset + j) mod 2^seedlen
281 	 * Step 11.2
282 	 *    W = V0 + (V1 * 2^outlen) + ... +
283 	 *        (Vn-1 * 2^((n-1)*outlen)) +
284 	 *        ((Vn mod 2^b) * 2^(n*outlen))
285 	 */
286 	loop_n = caam_desc_get_len(desc);
287 
288 	caam_desc_add_word(desc, LD_IMM(CLASS_NO, REG_CLEAR_WRITTEN, 4));
289 	caam_desc_add_word(desc, CLR_WR_IFIFO_NFIFO | CLR_WR_RST_C2_CHA |
290 					 CLR_WR_RST_C2_DSZ);
291 
292 	caam_desc_add_word(desc, HASH_INITFINAL(hash_func->op));
293 	caam_desc_add_word(desc, LD_NOCLASS_IMM(REG_CHA_CTRL, 4));
294 	caam_desc_add_word(desc, CCTRL_ULOAD_PKHA_A);
295 
296 	caam_desc_add_word(desc,
297 			   MOVE_WAIT(OFIFO, IFIFO_C2_LC2, 0, seed->length));
298 
299 	/* If Math Register 2 is zero bypass the high bit set to one */
300 	caam_desc_add_word(desc, MATH(SUB, REG2, ONE, NODEST, 8));
301 	caam_desc_add_word(desc,
302 			   JUMP_CNO_LOCAL(ANY_COND_TRUE,
303 					  JMP_COND(MATH_N) | JMP_COND(MATH_Z),
304 					  8));
305 	/*
306 	 * Step 11.3
307 	 * X = W + 2^(L-1)
308 	 *
309 	 * Set the high bit to one
310 	 * Remark: the DSA key is a modulus 8 bytes, hence no need
311 	 *         to check if the b_offset is less than 8.
312 	 */
313 	caam_desc_add_word(desc, MOVE_WAIT(C2_CTX_REG, MATH_REG1, b_offset, 8));
314 	caam_desc_add_word(desc, MATH(OR, REG2, REG1, REG1, 8));
315 	caam_desc_add_word(desc, MOVE(MATH_REG1, OFIFO, 0, 8));
316 
317 	if (hash_func->size - b_offset > 8)
318 		caam_desc_add_word(desc,
319 				   MOVE_WAIT(C2_CTX_REG, OFIFO, b_offset + 8,
320 					     hash_func->size - b_offset - 8));
321 	caam_desc_add_word(desc,
322 			   FIFO_ST_SEQ(MSG_DATA, hash_func->size - b_offset));
323 
324 	/*
325 	 * Reset MATH Register 2 to bypass the High Bit set
326 	 * operation next loop
327 	 */
328 	caam_desc_add_word(desc, MATH(AND, REG2, ZERO, REG2, 8));
329 
330 	caam_desc_add_word(desc,
331 			   JUMP_CNO_LOCAL(ALL_COND_TRUE, JMP_COND(NONE), 2));
332 
333 	/* Bypass High Bit set */
334 	caam_desc_add_word(desc,
335 			   ST_NOIMM_SEQ(CLASS_2, REG_CTX, hash_func->size));
336 
337 	caam_desc_add_word(desc, PKHA_CPY_NSIZE(B1, A0));
338 	caam_desc_add_word(desc, PKHA_OP(MOD_SUB_A_B, A));
339 	caam_desc_add_word(desc, PKHA_CPY_NSIZE(A0, B1));
340 
341 	desclen = caam_desc_get_len(desc);
342 	caam_desc_add_word(desc, JUMP_CNO_LOCAL_DEC(ALL_COND_FALSE, MATH_0,
343 						    JMP_COND_MATH(N) |
344 							    JMP_COND_MATH(Z),
345 						    loop_n - desclen));
346 	/* Jump to the next descriptor desc */
347 	caam_desc_add_word(desc, JUMP_NOTLOCAL(CLASS_NO, ALL_COND_TRUE,
348 					       JMP_COND(NONE)));
349 	caam_desc_add_ptr(desc, desc_p);
350 
351 	DSA_TRACE("X descriptor");
352 	DSA_DUMPDESC(desc);
353 }
354 
355 /*
356  * Build the descriptor generating the Prime P from value X
357  * Referring to FIPS.186-4, Section A.1.1.2 Generation of the
358  * Probable Primes p and q Using an Approved Hash Function
359  *
360  * @desc        [out] Descriptor built
361  * @prime       [in/out] Prime generation data
362  * @x           Value X
363  * @mod_n       Modular value (0xFF filled buffer)
364  */
do_desc_prime_p(uint32_t * desc,struct prime_data_dsa * prime,struct caambuf * x,struct caambuf * mod_n)365 static void do_desc_prime_p(uint32_t *desc, struct prime_data_dsa *prime,
366 			    struct caambuf *x, struct caambuf *mod_n)
367 {
368 	unsigned int desclen = 0;
369 	unsigned int retry_mr_test = 0;
370 	size_t index = 0;
371 
372 	caam_desc_init(desc);
373 	caam_desc_add_word(desc, DESC_HEADER(0));
374 
375 	caam_desc_add_word(desc,
376 			   FIFO_LD(CLASS_1, PKHA_N, NOACTION, mod_n->length));
377 	caam_desc_add_ptr(desc, mod_n->paddr);
378 
379 	/*
380 	 * Step 11.4
381 	 * c = X mod 2q
382 	 */
383 
384 	/* Calculate 2q and store it in PKHA N */
385 	caam_desc_add_word(desc, FIFO_LD(CLASS_1, PKHA_A, NOACTION,
386 					 prime->q->length));
387 	caam_desc_add_ptr(desc, prime->q->paddr);
388 	caam_desc_add_word(desc, PKHA_CPY_SSIZE(A0, B0));
389 	caam_desc_add_word(desc, PKHA_OP(MOD_ADD_A_B, A));
390 
391 	caam_desc_add_word(desc, PKHA_CPY_SSIZE(A0, N0));
392 
393 	/* c = X mod 2q */
394 	caam_desc_add_word(desc, FIFO_LD(CLASS_1, PKHA_A, NOACTION, x->length));
395 	caam_desc_add_ptr(desc, x->paddr);
396 	caam_desc_add_word(desc,
397 			   JUMP_CNO_LOCAL(ALL_COND_TRUE, JMP_COND(NIFP), 1) |
398 			   BIT(24));
399 	caam_desc_add_word(desc, PKHA_OP(MOD_AMODN, A));
400 
401 	/*
402 	 * Step 11.5
403 	 * p = X - (c - 1)
404 	 */
405 	caam_desc_add_word(desc,
406 			   FIFO_LD(CLASS_1, PKHA_N, NOACTION, mod_n->length));
407 	caam_desc_add_ptr(desc, mod_n->paddr);
408 
409 	caam_desc_add_word(desc, FIFO_LD_IMM(CLASS_1, PKHA_B, NOACTION, 1));
410 	caam_desc_add_ptr(desc, 1);
411 	caam_desc_add_word(desc, PKHA_OP(MOD_SUB_A_B, B));
412 
413 	caam_desc_add_word(desc, FIFO_LD(CLASS_1, PKHA_A, NOACTION, x->length));
414 	caam_desc_add_ptr(desc, x->paddr);
415 	caam_desc_add_word(desc, PKHA_OP(MOD_SUB_A_B, A));
416 
417 	/*
418 	 * Save the candidate Prime q now because N is going to be
419 	 * affected by the Miller-Rabin test
420 	 */
421 	caam_desc_add_word(desc, PKHA_CPY_SSIZE(A0, N0));
422 	caam_desc_add_word(desc, FIFO_ST(PKHA_N, prime->p->length));
423 	caam_desc_add_ptr(desc, prime->p->paddr);
424 	caam_desc_add_word(desc, FIFO_ST_SEQ(MSG_DATA, 0));
425 
426 	/*
427 	 * Step 11.6
428 	 * if (p < 2^(L-1)) then go to step 11.9
429 	 *
430 	 */
431 	caam_desc_add_word(desc, LD_NOCLASS_IMM(REG_CHA_CTRL, 4));
432 	caam_desc_add_word(desc, CCTRL_ULOAD_PKHA_A);
433 
434 	/* Keep the MSB from p candidate and check if bit 2^(L-1) is set */
435 	caam_desc_add_word(desc, MOVE_WAIT(OFIFO, MATH_REG0, 0, 8));
436 	for (index = 1; index < prime->p->length / 128; index++)
437 		caam_desc_add_word(desc, MOVE(OFIFO, C1_CTX_REG, 0, 128));
438 
439 	caam_desc_add_word(desc, MOVE(OFIFO, C1_CTX_REG, 0, 124));
440 
441 	caam_desc_add_word(desc, MATHI_OP1(SHIFT_L, ONE, 63, REG2, 8));
442 	caam_desc_add_word(desc, MATH(AND, REG0, REG2, REG0, 8));
443 
444 	caam_desc_add_word(desc, HALT_USER(ALL_COND_TRUE, MATH_Z,
445 					   DSA_PRIME_TOO_SMALL));
446 
447 	/*
448 	 * Step 11.7
449 	 * Test whether or not p is prime
450 	 *
451 	 * Referring to FIPS.186-4, Table C.1
452 	 * Get the number Miller-Rabin test interation function
453 	 * of the prime number size
454 	 */
455 	caam_desc_add_word(desc, MATH(ADD, IMM_DATA, ZERO, REG0, 4));
456 	if (prime->p->length <= 1024 / 8)
457 		caam_desc_add_word(desc, 40);
458 	else if (prime->p->length >= 3072 / 8)
459 		caam_desc_add_word(desc, 64);
460 	else
461 		caam_desc_add_word(desc, 56);
462 
463 	retry_mr_test = caam_desc_get_len(desc);
464 	/* Generate 8 random bytes 'miller-rabin seed' */
465 	caam_desc_add_word(desc, LD_IMM(CLASS_NO, REG_NFIFO, 8));
466 	caam_desc_add_word(desc, NFIFO_PAD(C1, NFIFO_FC1, PKHA_A, RND, 0));
467 	caam_desc_add_word(desc, prime->p->length);
468 	caam_desc_add_word(desc, FIFO_LD_IMM(CLASS_1, PKHA_B, NOACTION, 1));
469 	caam_desc_add_word(desc, 0x01);
470 	caam_desc_add_word(desc, PKHA_OP(MR_PRIMER_TEST, B));
471 
472 	desclen = caam_desc_get_len(desc);
473 
474 	/*
475 	 * Step 11.8
476 	 * if p is not a prime continue to step 11.9
477 	 */
478 	caam_desc_add_word(desc, HALT_USER(ALL_COND_FALSE, PKHA_IS_PRIME,
479 					   DSA_NOT_PRIME));
480 
481 	desclen = caam_desc_get_len(desc);
482 	/* Test while number of MR test iteration not complete */
483 	caam_desc_add_word(desc, JUMP_CNO_LOCAL_DEC(ALL_COND_FALSE, MATH_0,
484 						    JMP_COND_MATH(N) |
485 						    JMP_COND_MATH(Z),
486 						    retry_mr_test - desclen));
487 
488 	DSA_TRACE("Prime P descriptor");
489 	DSA_DUMPDESC(desc);
490 
491 	/*
492 	 * Ensure descriptor is pushed in physical memory because it's
493 	 * called from another descriptor.
494 	 */
495 	cache_operation(TEE_CACHECLEAN, desc, DESC_SZBYTES(PRIME_DESC_ENTRIES));
496 }
497 
498 /*
499  * Run the Prime Q descriptor.
500  *
501  * @desc Descriptor built
502  */
run_prime_q(uint32_t * desc,struct prime_data_dsa * prime)503 static enum caam_status run_prime_q(uint32_t *desc,
504 				    struct prime_data_dsa *prime)
505 {
506 	enum caam_status retstatus = CAAM_FAILURE;
507 	struct caam_jobctx jobctx = { };
508 
509 	cache_operation(TEE_CACHEFLUSH, prime->q->data, prime->q->length);
510 
511 	jobctx.desc = desc;
512 	retstatus = caam_jr_enqueue(&jobctx, NULL);
513 
514 	if (retstatus != CAAM_NO_ERROR) {
515 		DSA_TRACE("Prime Q Status 0x%08" PRIx32 " ret 0x%08" PRIx32,
516 			  jobctx.status, retstatus);
517 		retstatus = CAAM_FAILURE;
518 	} else {
519 		cache_operation(TEE_CACHEINVALIDATE, prime->q->data,
520 				prime->q->length);
521 		DSA_DUMPBUF("Prime Q", prime->q->data, prime->q->length);
522 	}
523 
524 	return retstatus;
525 }
526 
527 /*
528  * Run the Prime P descriptors.
529  *
530  * @desc   Descriptor built
531  * @prime  Prime generation data
532  */
run_prime_p(uint32_t * desc,struct prime_data_dsa * prime)533 static enum caam_status run_prime_p(uint32_t *desc,
534 				    struct prime_data_dsa *prime)
535 {
536 	enum caam_status retstatus = CAAM_FAILURE;
537 	struct caam_jobctx jobctx = { };
538 	size_t counter = 0;
539 
540 	cache_operation(TEE_CACHEFLUSH, prime->p->data, prime->p->length);
541 
542 	jobctx.desc = desc;
543 	for (counter = 0; counter < 4 * prime->p->length * 8; counter++) {
544 		retstatus = caam_jr_enqueue(&jobctx, NULL);
545 
546 		if (retstatus == CAAM_NO_ERROR) {
547 			DSA_TRACE("Prime P try: counter=%zu", counter);
548 			cache_operation(TEE_CACHEINVALIDATE, prime->p->data,
549 					prime->p->length);
550 			DSA_DUMPBUF("Prime P", prime->p->data,
551 				    prime->p->length);
552 
553 			return retstatus;
554 		}
555 
556 		if (retstatus == CAAM_JOB_STATUS) {
557 			if (JRSTA_GET_HALT_USER(jobctx.status) !=
558 				    DSA_NOT_PRIME &&
559 			    JRSTA_GET_HALT_USER(jobctx.status) !=
560 				    DSA_PRIME_TOO_SMALL) {
561 				DSA_TRACE("Prime P status 0x%08" PRIx32,
562 					  jobctx.status);
563 				return CAAM_FAILURE;
564 			}
565 		}
566 	}
567 
568 	/* This is not a prime, will try with another prime q */
569 	return CAAM_BAD_PARAM;
570 }
571 
572 /*
573  * Generate the DSA parameter G (generator)
574  * Referring to FIPS.186-4, Section A.2.1 Unverifiable Generation of the
575  * Generator g
576  *
577  * @desc        Descriptor buffer to use
578  * @prime       [in/out] Prime generation data
579  * @mod_n       Modular value (0xFF filled buffer)
580  */
do_generator(uint32_t * desc,struct prime_data_dsa * prime,struct caambuf * mod_n)581 static enum caam_status do_generator(uint32_t *desc,
582 				     struct prime_data_dsa *prime,
583 				     struct caambuf *mod_n)
584 {
585 	enum caam_status retstatus = CAAM_FAILURE;
586 	struct caam_jobctx jobctx = { };
587 	unsigned int desclen = 0;
588 	unsigned int retry_new_h = 0;
589 
590 	caam_desc_init(desc);
591 	caam_desc_add_word(desc, DESC_HEADER(0));
592 
593 	caam_desc_add_word(desc,
594 			   FIFO_LD(CLASS_1, PKHA_N, NOACTION, mod_n->length));
595 	caam_desc_add_ptr(desc, mod_n->paddr);
596 
597 	/*
598 	 * Step 1.
599 	 * e = (p - 1)/q
600 	 */
601 	caam_desc_add_word(desc, FIFO_LD(CLASS_1, PKHA_A, NOACTION,
602 					 prime->p->length));
603 	caam_desc_add_ptr(desc, prime->p->paddr);
604 	caam_desc_add_word(desc, FIFO_LD_IMM(CLASS_1, PKHA_B, NOACTION, 1));
605 	caam_desc_add_ptr(desc, 1);
606 	/* PKHA B = (p - 1) */
607 	caam_desc_add_word(desc, PKHA_OP(MOD_SUB_A_B, B));
608 
609 	caam_desc_add_word(desc, FIFO_LD(CLASS_1, PKHA_A, NOACTION,
610 					 prime->q->length));
611 	caam_desc_add_ptr(desc, prime->q->paddr);
612 	/* PKHA A = 1/q */
613 	caam_desc_add_word(desc, PKHA_OP(MOD_INV_A, A));
614 
615 	/* PKHA E = (p - 1)/q */
616 	caam_desc_add_word(desc, PKHA_OP(MOD_MUL_A_B, A));
617 	caam_desc_add_word(desc, PKHA_CPY_SSIZE(A0, E));
618 
619 	/* Load N with prime p */
620 	caam_desc_add_word(desc, FIFO_LD(CLASS_1, PKHA_N, NOACTION,
621 					 prime->p->length));
622 	caam_desc_add_ptr(desc, prime->p->paddr);
623 
624 	/*
625 	 * Step 2. Generate a Random h
626 	 * where 1 < h < (p - 1)
627 	 *
628 	 * To ensure h < (p - 1), generate a random of p length - 2
629 	 */
630 	retry_new_h = caam_desc_get_len(desc);
631 	caam_desc_add_word(desc, LD_IMM(CLASS_NO, REG_NFIFO, 8));
632 	caam_desc_add_word(desc, NFIFO_PAD(C1, NFIFO_FC1, PKHA_A, RND, 0));
633 	caam_desc_add_word(desc, prime->p->length - 2);
634 
635 	/*
636 	 * Step 3.
637 	 * g = h^e mod p
638 	 */
639 	caam_desc_add_word(desc, PKHA_OP(MOD_EXP_A_E, A));
640 
641 	/*
642 	 * Step 4.
643 	 * if (g = 1) then go to step 2
644 	 */
645 	desclen = caam_desc_get_len(desc);
646 	caam_desc_add_word(desc,
647 			   JUMP_CNO_LOCAL(ALL_COND_TRUE, JMP_COND(PKHA_GCD_1),
648 					  retry_new_h - desclen));
649 
650 	/* g is good save it */
651 	caam_desc_add_word(desc, FIFO_ST(PKHA_A, prime->g->length));
652 	caam_desc_add_ptr(desc, prime->g->paddr);
653 
654 	DSA_DUMPDESC(desc);
655 
656 	cache_operation(TEE_CACHEFLUSH, prime->g->data, prime->g->length);
657 
658 	jobctx.desc = desc;
659 	retstatus = caam_jr_enqueue(&jobctx, NULL);
660 
661 	if (retstatus != CAAM_NO_ERROR) {
662 		DSA_TRACE("Generator G Status 0x%08" PRIx32 " ret 0x%08" PRIx32,
663 			  jobctx.status, retstatus);
664 		return CAAM_FAILURE;
665 	}
666 
667 	cache_operation(TEE_CACHEINVALIDATE, prime->g->data, prime->g->length);
668 	DSA_DUMPBUF("Generator G", prime->g->data, prime->g->length);
669 
670 	return CAAM_NO_ERROR;
671 }
672 
caam_prime_dsa_gen(struct prime_data_dsa * data)673 enum caam_status caam_prime_dsa_gen(struct prime_data_dsa *data)
674 {
675 	enum caam_status retstatus = CAAM_FAILURE;
676 	uint32_t *desc_all = NULL;
677 	uint32_t *desc_q = NULL;
678 	uint32_t *desc_x = NULL;
679 	uint32_t *desc_p = NULL;
680 	struct caambuf seed = { };
681 	struct caambuf mod_n = { };
682 	struct dsa_hash hash_func = { OP_ALGO(SHA256), TEE_SHA256_HASH_SIZE };
683 	size_t nb_tries = 0;
684 	struct caambuf x = { };
685 
686 	/*
687 	 * For the now as the DSA Prime p size is limited to 3072, Prime q
688 	 * is also limited to 256. Hence the hash function to use is
689 	 * SHA-256.
690 	 * Ensure here that limit is not crossed because on some i.MX device
691 	 * hash is limited to 256.
692 	 */
693 	if (data->q->length > 256)
694 		return CAAM_BAD_PARAM;
695 
696 	retstatus = caam_calloc_buf(&mod_n, data->p->length);
697 	if (retstatus != CAAM_NO_ERROR)
698 		goto out;
699 
700 	memset(mod_n.data, 0xFF, mod_n.length);
701 	cache_operation(TEE_CACHECLEAN, mod_n.data, mod_n.length);
702 
703 	retstatus = caam_calloc_align_buf(&seed, data->q->length);
704 	if (retstatus != CAAM_NO_ERROR)
705 		return retstatus;
706 
707 	retstatus = caam_calloc_buf(&x, data->p->length);
708 	if (retstatus != CAAM_NO_ERROR)
709 		return retstatus;
710 
711 	desc_all = caam_calloc_desc(PRIME_DESC_ENTRIES * 3);
712 	if (!desc_all) {
713 		retstatus = CAAM_OUT_MEMORY;
714 		goto out;
715 	}
716 
717 	DSA_TRACE("Do primes P %zu bytes, Q %zu bytes", data->p->length,
718 		  data->q->length);
719 
720 	desc_q = desc_all;
721 	desc_x = desc_q + PRIME_DESC_ENTRIES;
722 	desc_p = desc_x + PRIME_DESC_ENTRIES;
723 
724 	do_desc_prime_q(desc_q, &seed, data, &hash_func);
725 	do_desc_gen_x(desc_x, &x, &seed, data, &hash_func, &mod_n,
726 		      virt_to_phys(desc_p));
727 	do_desc_prime_p(desc_p, data, &x, &mod_n);
728 
729 	cache_operation(TEE_CACHEFLUSH, data->p->data, data->p->length);
730 	cache_operation(TEE_CACHEFLUSH, seed.data, seed.length);
731 	cache_operation(TEE_CACHEFLUSH, x.data, x.length);
732 
733 	for (nb_tries = DSA_MAX_TRIES_PRIME_P; nb_tries > 0; nb_tries--) {
734 		retstatus = run_prime_q(desc_q, data);
735 
736 		if (retstatus == CAAM_NO_ERROR) {
737 			retstatus = run_prime_p(desc_x, data);
738 			if (retstatus == CAAM_NO_ERROR)
739 				break;
740 		}
741 
742 		if (retstatus == CAAM_FAILURE) {
743 			DSA_TRACE("DSA Prime P/Q Generation failed");
744 			break;
745 		}
746 	}
747 
748 	if (retstatus == CAAM_NO_ERROR)
749 		retstatus = do_generator(desc_all, data, &mod_n);
750 
751 out:
752 	caam_free_desc(&desc_all);
753 	caam_free_buf(&seed);
754 	caam_free_buf(&x);
755 	caam_free_buf(&mod_n);
756 
757 	return retstatus;
758 }
759