xref: /OK3568_Linux_fs/u-boot/drivers/crypto/rockchip/crypto_v2_pka.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd
4  */
5 
6 #include <common.h>
7 #include <crypto.h>
8 #include <dm.h>
9 #include <linux/errno.h>
10 #include <rockchip/crypto_v2.h>
11 #include <rockchip/crypto_v2_pka.h>
12 
13 #define CRYPT_OK	(0)
14 #define CRYPT_ERROR	(-1)
15 
rk_pka_ram_ctrl_enable(void)16 void rk_pka_ram_ctrl_enable(void)
17 {
18 	crypto_write((CRYPTO_RAM_PKA_RDY << CRYPTO_WRITE_MASK_SHIFT) |
19 		     CRYPTO_RAM_PKA_RDY, CRYPTO_RAM_CTL);
20 }
21 
rk_pka_ram_ctrl_disable(void)22 void rk_pka_ram_ctrl_disable(void)
23 {
24 	crypto_write((CRYPTO_RAM_PKA_RDY << CRYPTO_WRITE_MASK_SHIFT),
25 		     CRYPTO_RAM_CTL);
26 }
27 
rk_pka_wait_on_ram_ready(void)28 void rk_pka_wait_on_ram_ready(void)
29 {
30 	u32 output_reg_val;
31 
32 	do {
33 		output_reg_val = crypto_read(CRYPTO_RAM_ST);
34 	} while ((output_reg_val & 0x01) != CRYPTO_CLK_RAM_RDY);
35 }
36 
rk_pka_wait_on_pipe_ready(void)37 void rk_pka_wait_on_pipe_ready(void)
38 {
39 	u32 output_reg_val;
40 
41 	do {
42 		output_reg_val = crypto_read(CRYPTO_PKA_PIPE_RDY);
43 	} while ((output_reg_val & 0x01) != RK_PKA_PIPE_READY);
44 }
45 
rk_pka_wait_on_done(void)46 void rk_pka_wait_on_done(void)
47 {
48 	u32 output_reg_val;
49 
50 	do {
51 		output_reg_val = crypto_read(CRYPTO_PKA_DONE);
52 	} while ((output_reg_val & 0x01) != RK_PKA_OP_DONE);
53 }
54 
rk_pka_set_startmemaddr_reg(u32 start_mem_addr)55 void rk_pka_set_startmemaddr_reg(u32 start_mem_addr)
56 {
57 	crypto_write(start_mem_addr, CRYPTO_PKA_MON_READ);
58 }
59 
rk_pka_set_N_NP_T0_T1_reg(u32 N,u32 NP,u32 T0,u32 T1)60 void rk_pka_set_N_NP_T0_T1_reg(u32 N, u32 NP, u32 T0,
61 			       u32 T1)
62 {
63 	rk_pka_wait_on_done();
64 	crypto_write((u32)((N) << RK_PKA_N_NP_T0_T1_REG_N_POS |
65 				(NP) << RK_PKA_N_NP_T0_T1_REG_NP_POS |
66 				(T0) << RK_PKA_N_NP_T0_T1_REG_T0_POS |
67 				(T1) << RK_PKA_N_NP_T0_T1_REG_T1_POS),
68 				CRYPTO_N_NP_T0_T1_ADDR);
69 }
70 
rk_pka_set_default_N_NP_T0_T1_reg(void)71 void rk_pka_set_default_N_NP_T0_T1_reg(void)
72 {
73 	crypto_write(RK_PKA_N_NP_T0_T1_REG_DEFAULT_VAL, CRYPTO_N_NP_T0_T1_ADDR);
74 }
75 
rk_pka_get_status(u32 * status)76 void rk_pka_get_status(u32 *status)
77 {
78 	rk_pka_wait_on_done();
79 	*status = crypto_read(CRYPTO_PKA_STATUS);
80 }
81 
rk_pka_get_status_alu_outzero(u32 * status)82 void rk_pka_get_status_alu_outzero(u32 *status)
83 {
84 	rk_pka_wait_on_done();
85 	*status = crypto_read(CRYPTO_PKA_STATUS);
86 	*status = ((*status) >> RK_PKA_STATUS_ALU_OUT_ZERO_POS) & 1UL;
87 }
88 
rk_pka_get_status_mod_overfl(u32 * status)89 void rk_pka_get_status_mod_overfl(u32 *status)
90 {
91 	rk_pka_wait_on_done();
92 	*status = crypto_read(CRYPTO_PKA_STATUS);
93 	*status = ((*status) >> RK_PKA_STATUS_ALU_MODOVRFLW_POS) & 1;
94 }
95 
rk_pka_get_status_div_byzero(u32 * status)96 void rk_pka_get_status_div_byzero(u32 *status)
97 {
98 	rk_pka_wait_on_done();
99 	*status = crypto_read(CRYPTO_PKA_STATUS);
100 	*status = ((*status) >> RK_PKA_STATUS_DIV_BY_ZERO_POS) & 1;
101 }
102 
rk_pka_get_status_carry(u32 * status)103 void rk_pka_get_status_carry(u32 *status)
104 {
105 	rk_pka_wait_on_done();
106 	*status = crypto_read(CRYPTO_PKA_STATUS);
107 	*status = ((*status) >> RK_PKA_STATUS_ALU_CARRY_POS) & 1;
108 }
109 
rk_pka_get_status_alu_signout(u32 * status)110 void rk_pka_get_status_alu_signout(u32 *status)
111 {
112 	rk_pka_wait_on_done();
113 	*status = crypto_read(CRYPTO_PKA_STATUS);
114 	*status = ((*status) >> RK_PKA_STATUS_ALU_SIGN_OUT_POS) & 1;
115 }
116 
rk_pka_get_status_modinv_ofzero(u32 * status)117 void rk_pka_get_status_modinv_ofzero(u32 *status)
118 {
119 	rk_pka_wait_on_done();
120 	*status = crypto_read(CRYPTO_PKA_STATUS);
121 	*status = ((*status) >> RK_PKA_STATUS_MODINV_OF_ZERO_POS) & 1;
122 }
123 
rk_pka_get_status_opcode(u32 * status)124 void rk_pka_get_status_opcode(u32 *status)
125 {
126 	rk_pka_wait_on_done();
127 	*status = crypto_read(CRYPTO_PKA_STATUS);
128 	*status = ((*status) >> RK_PKA_STATUS_OPCODE_POS) &
129 			  RK_PKA_STATUS_OPCODE_MASK;
130 }
131 
rk_pka_get_status_tag(u32 * status)132 void rk_pka_get_status_tag(u32 *status)
133 {
134 	rk_pka_wait_on_done();
135 	*status = crypto_read(CRYPTO_PKA_STATUS);
136 	*status = ((*status) >> RK_PKA_STATUS_TAG_POS) & RK_PKA_STATUS_TAG_MASK;
137 }
138 
rk_pka_set_regsize(u32 size_bits,u32 entry_num)139 void rk_pka_set_regsize(u32 size_bits, u32 entry_num)
140 {
141 	rk_pka_wait_on_done();
142 	crypto_write(size_bits, CRYPTO_PKA_L0 + 4 * (entry_num));
143 }
144 
rk_pka_read_regsize(u32 * size_bits,u32 entry_num)145 void rk_pka_read_regsize(u32 *size_bits, u32 entry_num)
146 {
147 	rk_pka_wait_on_done();
148 	*size_bits = crypto_read(CRYPTO_PKA_L0 + 4 * (entry_num));
149 }
150 
rk_pka_set_regaddr(u32 vir_reg,u32 phys_addr)151 void rk_pka_set_regaddr(u32 vir_reg, u32 phys_addr)
152 {
153 	rk_pka_wait_on_done();
154 	crypto_write(phys_addr, CRYPTO_MEMORY_MAP0 + 4 * (vir_reg));
155 }
156 
rk_pka_get_regaddr(u32 vir_reg,u32 * phys_addr)157 void rk_pka_get_regaddr(u32 vir_reg, u32 *phys_addr)
158 {
159 	*phys_addr = crypto_read(CRYPTO_MEMORY_MAP0 + 4 * (vir_reg));
160 }
161 
rk_pka_read_regaddr(u32 vir_reg,u32 * phys_addr)162 void rk_pka_read_regaddr(u32 vir_reg, u32 *phys_addr)
163 {
164 	rk_pka_wait_on_done();
165 	*phys_addr = crypto_read(CRYPTO_MEMORY_MAP0 + 4 * (vir_reg));
166 }
167 
rk_pka_make_full_opcode(u32 opcode,u32 len_id,u32 is_a_immed,u32 op_a,u32 is_b_immed,u32 op_b,u32 res_discard,u32 res,u32 tag)168 u32 rk_pka_make_full_opcode(u32 opcode, u32 len_id,
169 			    u32 is_a_immed, u32 op_a,
170 			    u32 is_b_immed, u32 op_b,
171 			    u32 res_discard, u32 res,
172 			    u32 tag)
173 {
174 	u32 full_opcode;
175 
176 	full_opcode =
177 		(((u32)(opcode) & 31) << RK_PKA_OPCODE_OPERATION_ID_POS |
178 		((u32)(len_id) & 7) << RK_PKA_OPCODE_LEN_POS |
179 		((u32)(is_a_immed) & 1) << RK_PKA_OPCODE_OPERAND_1_IMMED_POS |
180 		((u32)(op_a) & 31)	<< RK_PKA_OPCODE_OPERAND_1_POS	|
181 		((u32)(is_b_immed) & 1) << RK_PKA_OPCODE_OPERAND_2_IMMED_POS |
182 		((u32)(op_b) & 31) << RK_PKA_OPCODE_OPERAND_2_POS	|
183 		((u32)(res_discard) & 1) << RK_PKA_OPCODE_R_DISCARD_POS	|
184 		((u32)(res) & 31) << RK_PKA_OPCODE_RESULT_POS |
185 		((u32)(tag) & 31) << RK_PKA_OPCODE_TAG_POS);
186 	return full_opcode;
187 }
188 
rk_pka_hw_load_value2pka_mem(u32 addr,u32 val)189 void rk_pka_hw_load_value2pka_mem(u32 addr, u32 val)
190 {
191 	u32 *vaddr;
192 
193 	vaddr = (u32 *)((addr) + RK_PKA_DATA_REGS_MEMORY_OFFSET_ADDR);
194 	rk_pka_ram_ctrl_disable();
195 	rk_pka_wait_on_ram_ready();
196 	*vaddr = val;
197 	rk_pka_ram_ctrl_enable();
198 }
199 
rk_pka_hw_load_block2pka_mem(u32 addr,u32 * ptr,u32 size_words)200 void rk_pka_hw_load_block2pka_mem(u32 addr, u32 *ptr,
201 				  u32 size_words)
202 {
203 	u8 *vaddr =
204 		(u8 *)((addr) + RK_PKA_DATA_REGS_MEMORY_OFFSET_ADDR);
205 
206 	rk_pka_ram_ctrl_disable();
207 	rk_pka_wait_on_ram_ready();
208 	RK_PKA_FastMemCpy(vaddr, (u8 *)ptr, size_words);
209 	rk_pka_ram_ctrl_enable();
210 }
211 
rk_pka_hw_reverse_load_block2pka_mem(u32 addr,u32 * ptr,u32 size_words)212 void rk_pka_hw_reverse_load_block2pka_mem(u32 addr, u32 *ptr,
213 					  u32 size_words)
214 {
215 	u8 *vaddr =
216 		(u8 *)((addr) + RK_PKA_DATA_REGS_MEMORY_OFFSET_ADDR);
217 
218 	rk_pka_ram_ctrl_disable();
219 	rk_pka_wait_on_ram_ready();
220 	RK_PKA_ReverseMemcpy(vaddr, (u8 *)ptr, size_words);
221 	rk_pka_ram_ctrl_enable();
222 }
223 
rk_pka_hw_clear_pka_mem(u32 addr,u32 size_words)224 void rk_pka_hw_clear_pka_mem(u32 addr, u32 size_words)
225 {
226 	u8 *vaddr =
227 		(u8 *)((addr) + RK_PKA_DATA_REGS_MEMORY_OFFSET_ADDR);
228 
229 	rk_pka_ram_ctrl_disable();
230 	rk_pka_wait_on_ram_ready();
231 	RK_PKA_MemSetZero(vaddr, size_words);
232 	rk_pka_ram_ctrl_enable();
233 }
234 
rk_pka_hw_read_value_from_pka_mem(u32 addr,u32 * val)235 void rk_pka_hw_read_value_from_pka_mem(u32 addr, u32 *val)
236 {
237 	u32 *vaddr;
238 
239 	vaddr = (u32 *)((addr) + RK_PKA_DATA_REGS_MEMORY_OFFSET_ADDR);
240 	rk_pka_ram_ctrl_disable();
241 	rk_pka_wait_on_ram_ready();
242 	*val = *vaddr;
243 	rk_pka_ram_ctrl_enable();
244 }
245 
rk_pka_hw_read_block_from_pka_mem(u32 addr,u32 * ptr,u32 size_words)246 void rk_pka_hw_read_block_from_pka_mem(u32 addr, u32 *ptr,
247 				       u32 size_words)
248 {
249 	u8 *vaddr =
250 		(u8 *)((addr) + RK_PKA_DATA_REGS_MEMORY_OFFSET_ADDR);
251 
252 	rk_pka_ram_ctrl_disable();
253 	rk_pka_wait_on_ram_ready();
254 	RK_PKA_FastMemCpy((u8 *)(ptr), vaddr, size_words);
255 	rk_pka_ram_ctrl_enable();
256 }
257 
rk_pka_hw_reverse_read_block_from_pka_mem(u32 addr,u32 * ptr,u32 size_words)258 void rk_pka_hw_reverse_read_block_from_pka_mem(u32 addr, u32 *ptr,
259 					       u32 size_words)
260 {
261 	u8 *vaddr =
262 		(u8 *)((addr) + RK_PKA_DATA_REGS_MEMORY_OFFSET_ADDR);
263 
264 	rk_pka_ram_ctrl_disable();
265 	rk_pka_wait_on_ram_ready();
266 	RK_PKA_ReverseMemcpy((u8 *)(ptr), vaddr,
267 			     size_words * sizeof(u32));
268 	rk_pka_ram_ctrl_enable();
269 }
270 
rk_pka_exec_operation(u32 opcode,u8 len_id,u8 is_a_immed,s8 op_a,u8 is_b_immed,s8 op_b,u8 res_discard,s8 res,u8 tag)271 u32 rk_pka_exec_operation(u32 opcode, u8 len_id,
272 			  u8 is_a_immed, s8 op_a,
273 			  u8 is_b_immed, s8 op_b,
274 			  u8 res_discard, s8 res, u8 tag)
275 {
276 	u32 status;
277 	u32 full_opcode;
278 	u32 error = CRYPT_OK;
279 
280 	if (res == RES_DISCARD) {
281 		res_discard = 1;
282 		res = 0;
283 	}
284 
285 	full_opcode = rk_pka_make_full_opcode(opcode, len_id,
286 					      is_a_immed, op_a,
287 					      is_b_immed, op_b,
288 					      res_discard, res, tag);
289 
290 	/* write full opcode into PKA CRYPTO_OPCODE register */
291 	crypto_write(full_opcode, CRYPTO_OPCODE);
292 
293 	/*************************************************/
294 	/* finishing operations for different cases      */
295 	/*************************************************/
296 	switch (opcode) {
297 	case PKA_Div:
298 		/* for Div operation check, that op_b != 0*/
299 		rk_pka_get_status_div_byzero(&status);
300 		if (status == 1) {
301 			error = RK_PKA_DIVIDER_IS_NULL_ERROR;
302 			goto end;
303 		}
304 		break;
305 	case PKA_Terminate:
306 		/* wait for PKA done bit */
307 		rk_pka_wait_on_done();
308 		break;
309 	default:
310 		/* wait for PKA pipe ready bit */
311 		rk_pka_wait_on_pipe_ready();
312 	}
313 
314 end:
315 	return error;
316 }
317 
rk_pka_set_sizes_tab(u32 regs_sizes_ptr[RK_PKA_MAX_REGS_COUNT],u32 count_of_sizes,u32 max_size_bits,u32 is_default_map)318 u32 rk_pka_set_sizes_tab(u32 regs_sizes_ptr[RK_PKA_MAX_REGS_COUNT],
319 			 u32 count_of_sizes, u32 max_size_bits,
320 			 u32 is_default_map)
321 {
322 	u32 i;
323 	u32 error;
324 	u32 max_size, min_size, maxsize_words;
325 
326 	error = CRYPT_OK;
327 	max_size = 0;
328 	min_size = 0xFFFFFFFF;
329 
330 	if (is_default_map > 1)
331 		return  RK_PKA_SET_MAP_MODE_ERROR;
332 
333 	/* 1. Case of user defined settings */
334 	if (is_default_map == 0) {
335 		/* find maximal and minimal sizes  */
336 		for (i = 0; i < count_of_sizes; i++) {
337 			if (max_size < regs_sizes_ptr[i] &&
338 			    regs_sizes_ptr[i] != 0xFFFFFFFF)
339 				max_size = regs_sizes_ptr[i];
340 
341 			if (min_size > regs_sizes_ptr[i])
342 				min_size = regs_sizes_ptr[i];
343 		}
344 
345 		/* set sizes into PKA registers sizes table */
346 		for (i = 0; i < count_of_sizes; i++)
347 			crypto_write(regs_sizes_ptr[i], CRYPTO_PKA_L0 + 4 * i);
348 	} else {
349 		/* 2. Case of default settings */
350 		maxsize_words = (max_size_bits + 31) / 32;
351 		/* write exact size into first table entry */
352 		crypto_write(max_size_bits, CRYPTO_PKA_L0);
353 
354 		/* write size with extra word into tab[1] = tab[0] + 32 */
355 		crypto_write(32 * maxsize_words + 32, CRYPTO_PKA_L0 + 4);
356 
357 		/* count of entries, which was set */
358 		count_of_sizes = 2;
359 	}
360 
361 	for (i = count_of_sizes; i < 8; i++)
362 		crypto_write(0xFFFFFFFF, CRYPTO_PKA_L0 + 4 * i);
363 
364 	return error;
365 }
366 
rk_pka_set_map_tab(struct rk_pka_regs_map * regs_map_ptr,u32 * count_of_regs,u32 maxsize_words,u32 N_NP_T0_T1,u32 is_default_map)367 u32 rk_pka_set_map_tab(struct rk_pka_regs_map *regs_map_ptr,
368 		       u32 *count_of_regs, u32 maxsize_words,
369 		       u32 N_NP_T0_T1, u32 is_default_map)
370 {
371 	u32 i;
372 	u32 error;
373 	u32 cur_addr;
374 	u32 default_max_size, default_count_of_regs;
375 
376 	error = CRYPT_OK;
377 	cur_addr = 0;
378 
379 	if (is_default_map == 1) {
380 		default_max_size = 32 * maxsize_words;
381 		default_count_of_regs =
382 			min(32, (8 * RK_PKA_MAX_REGS_MEM_SIZE_BYTES) /
383 				default_max_size);
384 
385 		for (i = 0; i < 32 - 2; i++) {
386 			if (i < default_count_of_regs - 2) {
387 				crypto_write(cur_addr,
388 					     CRYPTO_MEMORY_MAP0 + 4 * i);
389 				cur_addr = cur_addr + default_max_size / 8;
390 			} else {
391 				crypto_write(0xFFC, CRYPTO_MEMORY_MAP0 + 4 * i);
392 			}
393 		}
394 		crypto_write(cur_addr, CRYPTO_MEMORY_MAP0 + 4 * 30);
395 		cur_addr = cur_addr + default_max_size / 8;
396 		crypto_write(cur_addr, CRYPTO_MEMORY_MAP0 + 4 * 31);
397 		*count_of_regs = default_count_of_regs;
398 		crypto_write((u32)RK_PKA_N_NP_T0_T1_REG_DEFAULT_VAL,
399 			     CRYPTO_N_NP_T0_T1_ADDR);
400 	}
401 
402 	if (is_default_map == 0) {
403 		for (i = 0; i < *count_of_regs; i++)
404 			crypto_write(regs_map_ptr->regs_addr[i],
405 				     CRYPTO_MEMORY_MAP0 +
406 				     4 * regs_map_ptr->reges_num[i]);
407 
408 		crypto_write(N_NP_T0_T1, CRYPTO_N_NP_T0_T1_ADDR);
409 	}
410 
411 	return error;
412 }
413 
rk_pka_clear_block_of_regs(u8 first_reg,u8 count_of_regs,u8 len_id)414 u32 rk_pka_clear_block_of_regs(u8 first_reg, u8 count_of_regs,
415 			       u8 len_id)
416 {
417 	u32 i;
418 	u32 size, addr;
419 	s32 count_temps;
420 
421 	rk_pka_read_regsize(&size, len_id);
422 
423 	count_temps = 0;
424 
425 	if (first_reg + count_of_regs > 30) {
426 		count_temps = min((count_of_regs + first_reg - 30), 2);
427 		count_of_regs = 30;
428 	} else {
429 		count_temps = 2;
430 	}
431 
432 	/* clear ordinary registers */
433 	for (i = 0; i < count_of_regs; i++)
434 		RK_PKA_Clr(len_id, first_reg + i/*regNum*/, 0/*tag*/);
435 
436 	/* clear PKA temp registers using macros (without PKA operations */
437 	if (count_temps > 0) {
438 		/* calculate size of register in words */
439 		size = (size + 31) / 32;
440 		rk_pka_wait_on_done();
441 		rk_pka_get_regaddr(30/*vir_reg*/, &addr/*phys_addr*/);
442 		rk_pka_hw_clear_pka_mem(addr, size);
443 
444 		if (count_temps > 1) {
445 			rk_pka_get_regaddr(31/*vir_reg*/, &addr/*phys_addr*/);
446 			rk_pka_hw_clear_pka_mem(addr, size);
447 		}
448 	}
449 	return CRYPT_OK;
450 }
451 
rk_pka_init(u32 regs_sizes_ptr[RK_PKA_MAX_REGS_COUNT],u32 count_of_sizes,struct rk_pka_regs_map * regs_map_ptr,u32 count_of_regs,u32 op_size_bits,u32 regsize_words,u32 N_NP_T0_T1,u32 is_default_map)452 u32 rk_pka_init(u32 regs_sizes_ptr[RK_PKA_MAX_REGS_COUNT], u32 count_of_sizes,
453 		struct rk_pka_regs_map *regs_map_ptr, u32 count_of_regs,
454 		u32 op_size_bits, u32 regsize_words,
455 		u32 N_NP_T0_T1, u32 is_default_map)
456 {
457 	u32 addr;
458 	u32 error;
459 
460 	error = CRYPT_OK;
461 
462 	PKA_CLK_ENABLE();
463 	rk_pka_ram_ctrl_enable();
464 
465 	error = rk_pka_set_sizes_tab(regs_sizes_ptr, count_of_sizes,
466 				     op_size_bits, is_default_map);
467 
468 	if (error != CRYPT_OK)
469 		return error;
470 
471 	error = rk_pka_set_map_tab(regs_map_ptr, &count_of_regs, regsize_words,
472 				   N_NP_T0_T1, is_default_map);
473 
474 	if (error != CRYPT_OK)
475 		return error;
476 
477 	/* set size of register into RegsSizesTable */
478 	crypto_write(32 * regsize_words, CRYPTO_PKA_L0 + 3 * 4);
479 
480 	/* clean PKA data memory */
481 	rk_pka_clear_block_of_regs(0, count_of_regs - 2, 3);
482 
483 	/* clean temp PKA registers 30,31 */
484 	rk_pka_wait_on_done();
485 	rk_pka_get_regaddr(30/*vir_reg*/, &addr/*phys_addr*/);
486 	rk_pka_hw_clear_pka_mem(addr, regsize_words);
487 	rk_pka_get_regaddr(31/*vir_reg*/, &addr/*phys_addr*/);
488 	rk_pka_hw_clear_pka_mem(addr, regsize_words);
489 
490 	return error;
491 }
492 
rk_pka_finish(void)493 void rk_pka_finish(void)
494 {
495 	RK_PKA_Terminate(0);
496 	PKA_CLK_DISABLE();
497 }
498 
rk_pka_copy_data_into_reg(s8 dst_reg,u8 len_id,u32 * src_ptr,u32 size_words)499 void rk_pka_copy_data_into_reg(s8 dst_reg, u8 len_id,
500 			       u32 *src_ptr, u32 size_words)
501 {
502 	u32 cur_addr;
503 	u32 reg_size;
504 
505 	RK_PKA_Terminate(0);
506 
507 	rk_pka_read_regaddr(dst_reg, &cur_addr);
508 
509 	rk_pka_read_regsize(&reg_size, len_id);
510 	reg_size = (reg_size + 31) / 32;
511 
512 	rk_pka_hw_load_block2pka_mem(cur_addr, src_ptr, size_words);
513 	cur_addr = cur_addr + sizeof(u32) * size_words;
514 
515 	rk_pka_hw_clear_pka_mem(cur_addr, reg_size - size_words);
516 }
517 
rk_pka_copy_data_from_reg(u32 * dst_ptr,u32 size_words,s8 src_reg)518 void rk_pka_copy_data_from_reg(u32 *dst_ptr, u32 size_words,
519 			       s8 src_reg)
520 {
521 	u32 cur_addr;
522 
523 	crypto_write(0, CRYPTO_OPCODE);
524 
525 	rk_pka_wait_on_done();
526 
527 	rk_pka_read_regaddr(src_reg, &cur_addr);
528 
529 	rk_pka_hw_read_block_from_pka_mem(cur_addr, dst_ptr, size_words);
530 }
531 
rk_pka_calcNp_and_initmodop(u32 len_id,u32 mod_size_bits,s8 r_t0,s8 r_t1,s8 r_t2)532 u32 rk_pka_calcNp_and_initmodop(u32 len_id, u32 mod_size_bits,
533 				s8 r_t0, s8 r_t1, s8 r_t2)
534 {
535 	u32 i;
536 	u32 s;
537 	u32 error;
538 	u32 num_bits, num_words;
539 
540 	/* Set s = 132 */
541 	s = 132;
542 
543 	/*-------------------------------------------------------------------*/
544 	/* Step 1,2. Set registers: Set op_a = 2^(sizeN+32)                  */
545 	/*           Registers using: 0 - N (is set in register 0,           */
546 	/*           1 - NP, temp regs: r_t0 (A), r_t1, r_t2.                */
547 	/*           len_id: 0 - exact size, 1 - exact+32 bit                */
548 	/*-------------------------------------------------------------------*/
549 
550 	/* set register r_t0 = 0 */
551 	RK_PKA_Clr(len_id + 1, r_t0/*op_a*/, 0/*tag*/); /* r2 = 0 */
552 
553 	/* calculate bit position of said bit in the word */
554 	num_bits = mod_size_bits % 32;
555 	num_words = mod_size_bits / 32;
556 
557 	/* set 1 into register r_t0 */
558 	RK_PKA_Set0(len_id + 1, r_t0/*op_a*/, r_t0/*res*/, 0/*tag*/);
559 
560 	/* shift 1 to num_bits+31 position */
561 	if (num_bits > 0)
562 		RK_PKA_SHL0(len_id + 1, r_t0/*op_a*/, num_bits - 1/*s*/,
563 			    r_t0/*res*/, 0/*tag*/);
564 
565 	/* shift to word position */
566 	for (i = 0; i < num_words; i++)
567 		RK_PKA_SHL0(len_id + 1, r_t0/*op_a*/, 31/*s*/,
568 			    r_t0/*res*/, 0/*tag*/);
569 
570 	/*-------------------------------------------------------------------*/
571 	/* Step 3.  Dividing:  (op_a * 2**s) / N                             */
572 	/*-------------------------------------------------------------------*/
573 	error = rk_pka_div_long_num(len_id,        /*len_id*/
574 				    r_t0,          /*op_a*/
575 				    s,            /*shift*/
576 				    0,            /*op_b = N*/
577 				    1,            /*res NP*/
578 				    r_t1,          /*temp reg*/
579 				    r_t2           /*temp reg*/);
580 
581 	return error;
582 
583 }  /* END OF LLF_PKI_PKA_ExecCalcNpAndInitModOp */
584 
585 /***********   LLF_PKI_PKA_DivLongNum function      **********************/
586 /**
587  * @brief The function divides long number A*(2^S) by B:
588  *            res =  A*(2^S) / B,  remainder A = A*(2^S) % B.
589  *        where: A,B - are numbers of size, which is not grate than,
590  *		 maximal operands size,
591  *		 and B > 2^S;
592  *               S  - exponent of binary factor of A.
593  *               ^  - exponentiation operator.
594  *
595  *        The function algorithm:
596  *
597  *        1. Let nWords = S/32; nBits = S % 32;
598  *        2. Set res = 0, r_t1 = op_a;
599  *        3. for(i=0; i<=nWords; i++) do:
600  *            3.1. if(i < nWords )
601  *                   s1 = 32;
602  *                 else
603  *                   s1 = nBits;
604  *            3.2. r_t1 = r_t1 << s1;
605  *            3.3. call PKA_div for calculating the quotient and remainder:
606  *                      r_t2 = floor(r_t1/op_b) //quotient;
607  *                      r_t1 = r_t1 % op_b   //remainder (is in r_t1 register);
608  *            3.4. res = (res << s1) + r_t2;
609  *           end do;
610  *        4. Exit.
611  *
612  *        Assuming:
613  *                  - 5 PKA registers are used: op_a, op_b, res, r_t1, r_t2.
614  *                  - The registers sizes and mapping tables are set on
615  *                    default mode according to operands size.
616  *                  - The PKA clocks are initialized.
617  *        NOTE !   Operand op_a shall be overwritten by remainder.
618  *
619  * @param[in] len_id    - ID of operation size (modSize+32).
620  * @param[in] op_a      - Operand A: virtual register pointer of A.
621  * @param[in] S        - exponent of binary factor of A.
622  * @param[in] op_b      - Operand B: virtual register pointer of B.
623  * @param[in] res      - Virtual register pointer for result quotient.
624  * @param[in] r_t1      - Virtual pointer to remainder.
625  * @param[in] r_t2      - Virtual pointer of temp register.
626  * @param[in] VirtualHwBaseAddr -  Virtual HW base address, passed by user.
627  *
628  * @return CRYSError_t - On success CRYPT_OK is returned:
629  *
630  */
rk_pka_div_long_num(u8 len_id,s8 op_a,u32 s,s8 op_b,s8 res,s8 r_t1,s8 r_t2)631 u32 rk_pka_div_long_num(u8 len_id, s8 op_a, u32 s,
632 			s8 op_b, s8 res, s8 r_t1, s8 r_t2)
633 {
634 	s8 s1;
635 	u32  i;
636 	u32  n_bits, n_words;
637 
638 	/* calculate shifting parameters (words and bits ) */
639 	n_words = ((u32)s + 31) / 32;
640 	n_bits = (u32)s % 32;
641 
642 	/* copy operand op_a (including extra word) into temp reg r_t1 */
643 	RK_PKA_Copy(len_id + 1, r_t1/*dst*/, op_a/*src*/, 0 /*tag*/);
644 
645 	/* set res = 0 (including extra word) */
646 	RK_PKA_Clear(len_id + 1, res/*dst*/, 0 /*tag*/);
647 
648 	/* set s1 = 0 for first dividing in loop */
649 	s1 = 0;
650 
651 	/*----------------------------------------------------*/
652 	/* Step 1.  Shifting and dividing loop                */
653 	/*----------------------------------------------------*/
654 	for (i = 0; i < n_words; i++) {
655 		/* 3.1 set shift value s1  */
656 		if (i > 0)
657 			s1 = 32;
658 		else
659 			s1 = n_bits;
660 
661 		/* 3.2. shift: r_t1 = r_t1 * 2**s1 (in code (s1-1),
662 		 * because PKA performs s+1 shifts)
663 		 */
664 		if (s1 > 0)
665 			RK_PKA_SHL0(len_id + 1, r_t1/*op_a*/, (s1 - 1)/*s*/,
666 				    r_t1/*res*/, 0/*tag*/);
667 
668 		/* 3.3. perform PKA_Div for calculating a quotient
669 		 * r_t2 = floor(r_t1 / N)
670 		and remainder r_t1 = r_t1 % op_b
671 		 */
672 		RK_PKA_Div(len_id + 1, r_t1/*op_a*/, op_b/*B*/, r_t2/*res*/,
673 			   0/*tag*/);
674 
675 		/* 3.4. res = res * 2**s1 + res;   */
676 		if (s1 > 0)
677 			RK_PKA_SHL0(len_id + 1, res /*op_a*/, (s1 - 1)/*s*/,
678 				    res /*res*/, 0 /*tag*/);
679 
680 		RK_PKA_Add(len_id + 1, res/*op_a*/, r_t2/*op_b*/, res/*res*/,
681 			   0/*tag*/);
682 	}
683 
684 	rk_pka_wait_on_done();
685 	return CRYPT_OK;
686 }  /* END OF LLF_PKI_PKA_DivLongNum */
687 
688 /******LLF_PKI_CalcNpAndInitModOp function (physical pointers)***************/
689 /**
690  * @brief The function initializes  modulus and Barret tag NP,
691  *	      used in modular PKA operations.
692  *
693  *        The function does the following:
694  *          - calculates mod size in bits and sets it into PKA table sizes;
695  *          - if parameter NpCreateFlag = PKA_CreateNP, then the function
696  *            writes the modulus and the tag into registers
697  *            r0 and r1 accordingly;
698  *          - if NpCreateFlag= PKA_SetNP, the function calls the
699  *            LLF_PKI_PKA_ExecCalcNpAndInitModOp, which calculates the Barret
700  *            tag NP and initializes PKA registers; then the function outputs
701  *            calcu1lated NP value.
702  *
703  *       Assumings: - The registers mapping table is set on default mode,
704  *            according to modulus size:
705  *         -- count of allowed registers is not less, than 7 (including 3
706  *            registers r_t0,r_t2,rT3 for internal calculations and 4 default
707  *            special registers N,NP,T0,T1);
708  *         -- modulus exact and exact+32 bit sizes should be set into first
709  *            two entries of sizes-table accordingly.
710  *
711  * @param[in]  N_ptr        - The pointer to the buffer, containing modulus N,
712  * @param[in]  N_sizeBits   - The size of modulus in bytes, must be
713  *				16 <= N_sizeBytes <= 264.
714  * @param[out] NP_ptr       - The pointer to the buffer, containing
715  *				result - modulus tag NP.
716  * @param[in]  NpCreateFlag - Parameter, defining whether the NP shall be
717  *				taken from NP buffer and set into
718  *                            PKA register NP ( NpCreateFlag= PKA_CreateNP= 1 )
719  *                            or it shall be calculated and send to
720  *                            NP buffer ( NpCreateFlag= PKA_SetNP= 0 ).
721  * @param[in]  r_t0,r_t1,r_t2  - Virtual pointers to temp registers
722  *						  (sequence numbers).
723  * @param[in]  VirtualHwBaseAddr -  Virtual HW base address, passed by user.
724  *
725  * @return CRYSError_t - On success CRYPT_OK is returned,
726  *				on failure an error code:
727  *				LLF_PKI_PKA_ILLEGAL_PTR_ERROR
728  *				LLF_PKI_PKA_ILLEGAL_OPERAND_LEN_ERROR
729  *
730  */
rk_calcNp_and_initmodop(u32 * N_ptr,u32 N_size_bits,u32 * NP_ptr,u8 np_create_flag,s8 r_t0,s8 r_t1,s8 r_t2)731 u32 rk_calcNp_and_initmodop(u32 *N_ptr, u32 N_size_bits,
732 			    u32 *NP_ptr, u8 np_create_flag,
733 			    s8 r_t0, s8 r_t1, s8 r_t2)
734 {
735 	u32 N_size_words;
736 	u32 error = CRYPT_OK;
737 
738 	/* calculate size of modulus in bytes and in words */
739 	N_size_words = (N_size_bits + 31) / 32;
740 
741 	/* copy modulus N into r0 register */
742 	rk_pka_copy_data_into_reg(0/*dst_reg*/, 1/*len_id*/, N_ptr/*src_ptr*/,
743 				  N_size_words);
744 
745 	/* if np_create_flag == PKA_SetNP, then set NP into PKA register r1 */
746 	if (np_create_flag == RK_PKA_SET_NP) {
747 		/* copy the NP into r1 register NP */
748 		rk_pka_copy_data_into_reg(1/*dst_reg*/, 1/*len_id*/,
749 					  NP_ptr/*src_ptr*/,
750 					  RK_PKA_BARRETT_IN_WORDS);
751 	} else {
752 		/*---------------------------------------------------------*/
753 		/*     execute calculation of NP and initialization of PKA */
754 		/*---------------------------------------------------------*/
755 
756 		rk_pka_calcNp_and_initmodop(0/*len_id*/, N_size_bits,
757 					    r_t0, r_t1, r_t2);
758 
759 		/* output of NP value */
760 		rk_pka_copy_data_from_reg(NP_ptr/*dst_ptr*/,
761 					  RK_PKA_BARRETT_IN_WORDS,
762 					  1/*srcReg*/);
763 	}
764 	/* End of the function */
765 	return error;
766 } /* END OF LLF_PKI_CalcNpAndInitModOp */
767 
768 #define RK_NEG_SIGN -1
769 #define RK_POS_SIGN  1
770 
771 #define RK_WORD_SIZE                  32
772 
773 #define rk_mpanum_is_zero(x) ((x)->size == 0)
774 #define rk_mpanum_neg(x) ((x)->size = -((x)->size))
775 #define rk_mpanum_size(x) ((int)((x)->size >= 0 ? \
776 				 (x)->size : -(x)->size))
777 #define rk_mpanum_sign(x) ((x)->size >= 0 ? RK_POS_SIGN : RK_NEG_SIGN)
778 #define rk_mpanum_msw(x) ((x)->d[rk_mpanum_size(x) - 1])
779 
780 /*  --------------------------------------------------------------------
781  *  Function:  mpa_highest_bit_index
782  *  Returns the index of the highest 1 in |src|.
783  *  The index starts at 0 for the least significant bit.
784  *  If src == zero, it will return -1
785  *
786  */
mpa_highest_bit_index(const struct mpa_num * src)787 static int mpa_highest_bit_index(const struct mpa_num *src)
788 {
789 	u32 w;
790 	u32 b;
791 
792 	if (rk_mpanum_is_zero(src))
793 		return -1;
794 
795 	w = rk_mpanum_msw(src);
796 
797 	for (b = 0; b < RK_WORD_SIZE; b++) {
798 		w >>= 1;
799 		if (w == 0)
800 			break;
801 	}
802 	return (int)(rk_mpanum_size(src) - 1) * RK_WORD_SIZE + b;
803 }
804 
805 /*get bignum data length*/
rk_check_size(u32 * data,u32 max_word_size)806 static int rk_check_size(u32 *data, u32 max_word_size)
807 {
808 	for (int i = (max_word_size - 1); i >= 0; i--) {
809 		if (data[i] == 0)
810 			continue;
811 		else
812 			return (i + 1);
813 	}
814 	return 0;
815 }
816 
rk_mpa_alloc(struct mpa_num ** mpa,void * data,u32 word_size)817 int rk_mpa_alloc(struct mpa_num **mpa, void *data, u32 word_size)
818 {
819 	u32 alignment = sizeof(u32);
820 	u32 byte_size = word_size * sizeof(u32);
821 	struct mpa_num *tmp_mpa = NULL;
822 
823 	if (!mpa || word_size == 0)
824 		return -EINVAL;
825 
826 	*mpa = NULL;
827 
828 	tmp_mpa = malloc(sizeof(*tmp_mpa));
829 	if (!tmp_mpa)
830 		return -ENOMEM;
831 
832 	memset(tmp_mpa, 0x00, sizeof(*tmp_mpa));
833 
834 	if (!data || (unsigned long)data % alignment) {
835 		tmp_mpa->d = memalign(alignment, byte_size);
836 		if (!tmp_mpa->d) {
837 			free(tmp_mpa);
838 			return -ENOMEM;
839 		}
840 
841 		if (data)
842 			memcpy(tmp_mpa->d, data, byte_size);
843 		else
844 			memset(tmp_mpa->d, 0x00, byte_size);
845 
846 		tmp_mpa->alloc = MPA_USE_ALLOC;
847 	} else {
848 		tmp_mpa->d = data;
849 	}
850 
851 	tmp_mpa->size  = word_size;
852 
853 	*mpa = tmp_mpa;
854 
855 	return 0;
856 }
857 
rk_mpa_free(struct mpa_num ** mpa)858 void rk_mpa_free(struct mpa_num **mpa)
859 {
860 	struct mpa_num *tmp_mpa = NULL;
861 
862 	if (mpa && (*mpa)) {
863 		tmp_mpa = *mpa;
864 		if (tmp_mpa->alloc == MPA_USE_ALLOC)
865 			free(tmp_mpa->d);
866 
867 		free(tmp_mpa);
868 	}
869 }
870 
871 /* c = |a| + |b| */
rk_abs_add(void * a,void * b,void * c)872 int rk_abs_add(void *a, void *b, void *c)
873 {
874 	int max_word_size;
875 	u32 error = CRYPT_OK;
876 	struct mpa_num *m_a, *m_b, *m_c;
877 
878 	m_a = (struct mpa_num *)a;
879 	m_b = (struct mpa_num *)b;
880 	m_c = (struct mpa_num *)c;
881 
882 	max_word_size = rk_mpanum_size(m_a);
883 	if (max_word_size < rk_mpanum_size(m_b))
884 		max_word_size = rk_mpanum_size(m_b);
885 
886 	error = RK_PKA_DefaultInitPKA(max_word_size * 32, max_word_size + 1);
887 	if (error != CRYPT_OK)
888 		goto exit;
889 
890 	rk_pka_copy_data_into_reg(2/*dst_reg*/, 1/*len_id*/, m_a->d,
891 				  rk_mpanum_size(m_a));
892 	rk_pka_copy_data_into_reg(3/*dst_reg*/, 1/*len_id*/, m_b->d,
893 				  rk_mpanum_size(m_b));
894 	RK_PKA_Add(1/*len_id*/, 2/*op_a*/, 3/*op_b*/, 4/*res*/, 0/*tag*/);
895 	rk_pka_copy_data_from_reg(m_c->d, max_word_size + 1,
896 				  4/*srcReg*/);
897 
898 	m_c->size = rk_check_size(m_c->d,  max_word_size + 1);
899 
900 	rk_pka_clear_block_of_regs(0/*FirstReg*/, 5/*Count*/, 1/*len_id*/);
901 	rk_pka_clear_block_of_regs(30/*FirstReg*/, 2/*Count*/, 1/*len_id*/);
902 	rk_pka_finish();
903 
904 exit:
905 	return error;
906 }
907 
908 /*c = a % b*/
rk_mod(void * a,void * b,void * c)909 int rk_mod(void *a, void *b, void *c)
910 {
911 	int max_word_size;
912 	u32 error = CRYPT_OK;
913 	struct mpa_num *m_a, *m_b, *m_c;
914 
915 	m_a = (struct mpa_num *)a;
916 	m_b = (struct mpa_num *)b;
917 	m_c = (struct mpa_num *)c;
918 
919 	if (!a || !b || !c || rk_mpanum_size(m_b) == 0) {
920 		error = CRYPT_ERROR;
921 		goto exit;
922 	}
923 
924 	max_word_size = rk_mpanum_size(m_a);
925 	if (max_word_size < rk_mpanum_size(m_b))
926 		max_word_size = rk_mpanum_size(m_b);
927 
928 	error = RK_PKA_DefaultInitPKA(max_word_size * 32, max_word_size + 1);
929 	if (error != CRYPT_OK)
930 		goto exit;
931 
932 	rk_pka_copy_data_into_reg(2/*dst_reg*/, 1/*len_id*/,
933 				  m_a->d/*src_ptr*/,
934 				  rk_mpanum_size(m_a));
935 	rk_pka_copy_data_into_reg(3/*dst_reg*/, 1/*len_id*/,
936 				  m_b->d/*src_ptr*/,
937 				  rk_mpanum_size(m_b));
938 	RK_PKA_Div(0/*len_id*/, 2/*op_a*/, 3/*op_b*/, 4/*res*/, 0/*tag*/);
939 	rk_pka_copy_data_from_reg(m_c->d,  max_word_size, 2/*srcReg*/);
940 	m_c->size = rk_check_size(m_c->d, max_word_size);
941 
942 	rk_pka_clear_block_of_regs(0/*FirstReg*/, 5/*Count*/, 1/*len_id*/);
943 	rk_pka_clear_block_of_regs(30/*FirstReg*/, 2/*Count*/, 1/*len_id*/);
944 	rk_pka_finish();
945 
946 exit:
947 	return error;
948 }
949 
950 /*d = (a ^ b) % c*/
rk_exptmod(void * a,void * b,void * c,void * d)951 int rk_exptmod(void *a, void *b, void *c, void *d)
952 {
953 	struct mpa_num *tmpa;
954 	u32 op_Np[5];
955 	u32 error = CRYPT_OK;
956 	int max_word_size, exact_size;
957 	struct mpa_num *m_b, *m_c, *m_d;
958 
959 	m_b = (struct mpa_num *)b;
960 	m_c = (struct mpa_num *)c;
961 	m_d = (struct mpa_num *)d;
962 
963 	if (rk_mpa_alloc(&tmpa, NULL, RK_MAX_RSA_BWORDS) != 0)
964 		return CRYPT_ERROR;
965 
966 	error = rk_mod(a, c, tmpa);
967 	if (error) {
968 		error = CRYPT_ERROR;
969 		goto exit;
970 	}
971 
972 	if (!a || !b || !c || !d || rk_mpanum_size(m_c) == 0) {
973 		error = CRYPT_ERROR;
974 		goto exit;
975 	}
976 
977 	max_word_size = rk_mpanum_size(tmpa);
978 	if (max_word_size < rk_mpanum_size(m_b))
979 		max_word_size = rk_mpanum_size(m_b);
980 	if (max_word_size < rk_mpanum_size(m_c))
981 		max_word_size = rk_mpanum_size(m_c);
982 
983 	error = RK_PKA_DefaultInitPKA(max_word_size * 32, max_word_size + 1);
984 	if (error != CRYPT_OK)
985 		goto exit;
986 
987 	/* write exact size into first table entry */
988 	exact_size = mpa_highest_bit_index(m_c) + 1;
989 	crypto_write(exact_size, CRYPTO_PKA_L0);
990 
991 	/* write size with extra word into tab[1] = tab[0] + 32 */
992 	crypto_write(exact_size + 32, CRYPTO_PKA_L0 + 4);
993 
994 	/* calculate NP by initialization PKA for modular operations */
995 	error = rk_calcNp_and_initmodop(
996 					(m_c)->d, /*in N*/
997 					exact_size, /*in N size*/
998 					op_Np, /*out NP*/
999 					RK_PKA_CREATE_NP, /*in caculate NP*/
1000 					2, /*in *r_t0*/
1001 					3, /*in r_t1*/
1002 					4 /*in r_t2*/);
1003 	if (error != CRYPT_OK) {
1004 		printf("rk_calcNp_and_initmodop fail");
1005 		goto exit;
1006 	}
1007 	rk_pka_clear_block_of_regs(2/* FirstReg*/, 3, 1/*len_id*/);
1008 
1009 	rk_pka_copy_data_into_reg(2/*dst_reg*/, 1/*len_id*/,
1010 				  tmpa->d/*src_ptr*/,
1011 				  rk_mpanum_size(tmpa));
1012 	rk_pka_copy_data_into_reg(3/*dst_reg*/, 1/*len_id*/,
1013 				  (m_b)->d/*src_ptr*/,
1014 				  rk_mpanum_size(m_b));
1015 	rk_pka_copy_data_into_reg(0/*dst_reg*/, 1/*len_id*/,
1016 				  m_c->d/*src_ptr*/,
1017 				  rk_mpanum_size(m_c));
1018 	RK_PKA_ModExp(0, 2, 3, 4, 0);
1019 	rk_pka_copy_data_from_reg(m_d->d,  max_word_size, 4/*srcReg*/);
1020 
1021 	m_d->size = rk_check_size(m_d->d, max_word_size);
1022 
1023 	rk_pka_clear_block_of_regs(0/*FirstReg*/, 5/*Count*/, 1/*len_id*/);
1024 	rk_pka_clear_block_of_regs(30/*FirstReg*/, 2/*Count*/, 1/*len_id*/);
1025 	rk_pka_finish();
1026 
1027 exit:
1028 	rk_mpa_free(&tmpa);
1029 	return error;
1030 }
1031 
1032 /*d = (a ^ b) % c*/
rk_exptmod_np(void * m,void * e,void * n,void * np,void * d)1033 int rk_exptmod_np(void *m, void *e, void *n, void *np, void *d)
1034 {
1035 	struct mpa_num *tmpa;
1036 	u32 op_Np[5];
1037 	u32 error = CRYPT_OK;
1038 	int max_word_size, exact_size;
1039 	struct mpa_num *m_e, *m_n, *m_np, *m_d;
1040 
1041 	m_e = (struct mpa_num *)e;
1042 	m_n = (struct mpa_num *)n;
1043 	m_np = (struct mpa_num *)np;
1044 	m_d = (struct mpa_num *)d;
1045 
1046 	if (rk_mpa_alloc(&tmpa, NULL, RK_MAX_RSA_BWORDS) != 0)
1047 		return CRYPT_ERROR;
1048 
1049 	error = rk_mod(m, n, tmpa);
1050 	if (error) {
1051 		error = CRYPT_ERROR;
1052 		goto exit;
1053 	}
1054 
1055 	if (!m || !e || !n || !d || rk_mpanum_size(m_n) == 0) {
1056 		error = CRYPT_ERROR;
1057 		goto exit;
1058 	}
1059 
1060 	max_word_size = rk_mpanum_size(tmpa);
1061 	if (max_word_size < rk_mpanum_size(m_e))
1062 		max_word_size = rk_mpanum_size(m_e);
1063 	if (max_word_size < rk_mpanum_size(m_n))
1064 		max_word_size = rk_mpanum_size(m_n);
1065 
1066 	error = RK_PKA_DefaultInitPKA(max_word_size * 32, max_word_size + 1);
1067 	if (error != CRYPT_OK)
1068 		goto exit;
1069 
1070 	/* write exact size into first table entry */
1071 	exact_size = mpa_highest_bit_index(m_n) + 1;
1072 	crypto_write(exact_size, CRYPTO_PKA_L0);
1073 
1074 	/* write size with extra word into tab[1] = tab[0] + 32 */
1075 	crypto_write(exact_size + 32, CRYPTO_PKA_L0 + 4);
1076 
1077 	/* calculate NP by initialization PKA for modular operations */
1078 	if (m_np && m_np->d)
1079 		error = rk_calcNp_and_initmodop((m_n)->d, /*in N*/
1080 						exact_size,	/*in N size*/
1081 						m_np->d,	/*out NP*/
1082 						RK_PKA_SET_NP, /*in set NP*/
1083 						2,	/*in *r_t0*/
1084 						3,	/*in r_t1*/
1085 						4	/*in r_t2*/);
1086 	else
1087 		error = rk_calcNp_and_initmodop((m_n)->d,/*in N*/
1088 						exact_size,	/*in N size*/
1089 						op_Np,	/*out NP*/
1090 						RK_PKA_CREATE_NP,
1091 						2,	/*in *r_t0*/
1092 						3,	/*in r_t1*/
1093 						4	/*in r_t2*/);
1094 	if (error != CRYPT_OK) {
1095 		printf("rk_calcNp_and_initmodop fail");
1096 		goto exit;
1097 	}
1098 	rk_pka_clear_block_of_regs(2/* FirstReg*/, 3, 1/*len_id*/);
1099 
1100 	rk_pka_copy_data_into_reg(2/*dst_reg*/, 1/*len_id*/,
1101 				  (tmpa)->d/*src_ptr*/,
1102 				  rk_mpanum_size(tmpa));
1103 	rk_pka_copy_data_into_reg(3/*dst_reg*/, 1/*len_id*/,
1104 				  m_e->d/*src_ptr*/,
1105 				  rk_mpanum_size(m_e));
1106 	rk_pka_copy_data_into_reg(0/*dst_reg*/, 1/*len_id*/,
1107 				  (m_n)->d/*src_ptr*/,
1108 				  rk_mpanum_size(m_n));
1109 	RK_PKA_ModExp(0, 2, 3, 4, 0);
1110 	rk_pka_copy_data_from_reg(m_d->d, max_word_size, 4/*srcReg*/);
1111 
1112 	m_d->size = rk_check_size(m_d->d, max_word_size);
1113 
1114 	rk_pka_clear_block_of_regs(0/*FirstReg*/, 5/*Count*/, 1/*len_id*/);
1115 	rk_pka_clear_block_of_regs(30/*FirstReg*/, 2/*Count*/, 1/*len_id*/);
1116 	rk_pka_finish();
1117 
1118 exit:
1119 	rk_mpa_free(&tmpa);
1120 	return error;
1121 }
1122