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