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