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(®_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