1*02b4cf42SLin Jinhan // SPDX-License-Identifier: GPL-2.0
2*02b4cf42SLin Jinhan /*
3*02b4cf42SLin Jinhan * Copyright (c) 2024 Rockchip Electronics Co., Ltd
4*02b4cf42SLin Jinhan */
5*02b4cf42SLin Jinhan
6*02b4cf42SLin Jinhan #include <common.h>
7*02b4cf42SLin Jinhan #include <crypto.h>
8*02b4cf42SLin Jinhan #include <dm.h>
9*02b4cf42SLin Jinhan #include <linux/errno.h>
10*02b4cf42SLin Jinhan #include <rockchip/crypto_mpa.h>
11*02b4cf42SLin Jinhan #include <rockchip/crypto_v2.h>
12*02b4cf42SLin Jinhan #include <rockchip/crypto_ecc.h>
13*02b4cf42SLin Jinhan
14*02b4cf42SLin Jinhan #define WORDS2BYTES(words) ((words) * 4)
15*02b4cf42SLin Jinhan
16*02b4cf42SLin Jinhan #define RK_ECP_IS_BIGNUM_INVALID(b) (!b || !b->d || b->size > RK_ECP_MAX_WORDS)
17*02b4cf42SLin Jinhan #define RK_ECP_IS_POINT_INVALID(p) (RK_ECP_IS_BIGNUM_INVALID(p->x) && \
18*02b4cf42SLin Jinhan RK_ECP_IS_BIGNUM_INVALID(p->y))
19*02b4cf42SLin Jinhan
20*02b4cf42SLin Jinhan /*************************************************************/
21*02b4cf42SLin Jinhan /* Macros for waiting EC machine ready states */
22*02b4cf42SLin Jinhan /*************************************************************/
23*02b4cf42SLin Jinhan #define RK_ECP_WRITE_REG(offset, val) crypto_write((val), (offset))
24*02b4cf42SLin Jinhan #define RK_ECP_READ_REG(offset) crypto_read((offset))
25*02b4cf42SLin Jinhan
26*02b4cf42SLin Jinhan #define RK_ECP_RAM_FOR_ECC() \
27*02b4cf42SLin Jinhan RK_ECP_WRITE_REG(RK_ECC_RAM_CTL, RK_ECC_RAM_CTL_SEL_MASK | RK_ECC_RAM_CTL_ECC)
28*02b4cf42SLin Jinhan
29*02b4cf42SLin Jinhan #define RK_ECP_RAM_FOR_CPU() \
30*02b4cf42SLin Jinhan RK_ECP_WRITE_REG(RK_ECC_RAM_CTL, RK_ECC_RAM_CTL_SEL_MASK | RK_ECC_RAM_CTL_CPU)
31*02b4cf42SLin Jinhan
32*02b4cf42SLin Jinhan /* big endian to little endian */
33*02b4cf42SLin Jinhan #define RK_ECP_LOAD_DATA(dst, big_src) rk_ecp_load_data(dst, big_src)
34*02b4cf42SLin Jinhan
35*02b4cf42SLin Jinhan /* little endian to littel endian */
36*02b4cf42SLin Jinhan #define RK_ECP_LOAD_DATA_EXT(dst, src, n_bytes) \
37*02b4cf42SLin Jinhan do { \
38*02b4cf42SLin Jinhan util_word_memset((void *)(dst), 0, RK_ECP_MAX_WORDS);\
39*02b4cf42SLin Jinhan util_word_memcpy((void *)(dst), (void *)(src), (n_bytes) / 4); \
40*02b4cf42SLin Jinhan } while (0)
41*02b4cf42SLin Jinhan
42*02b4cf42SLin Jinhan #define RK_GET_GRPOUP_NBYTES(grp) ((grp)->p_len)
43*02b4cf42SLin Jinhan
44*02b4cf42SLin Jinhan #define RK_LOAD_GROUP_A(G) do { \
45*02b4cf42SLin Jinhan grp->curve_name = #G; \
46*02b4cf42SLin Jinhan grp->wide = G ## _wide;\
47*02b4cf42SLin Jinhan grp->p = G ## _p; \
48*02b4cf42SLin Jinhan grp->p_len = sizeof(G ## _p); \
49*02b4cf42SLin Jinhan grp->a = G ## _a; \
50*02b4cf42SLin Jinhan grp->a_len = sizeof(G ## _a); \
51*02b4cf42SLin Jinhan grp->n = G ## _n; \
52*02b4cf42SLin Jinhan grp->n_len = sizeof(G ## _n); \
53*02b4cf42SLin Jinhan grp->gx = G ## _gx; \
54*02b4cf42SLin Jinhan grp->gx_len = sizeof(G ## _gx); \
55*02b4cf42SLin Jinhan grp->gy = G ## _gy; \
56*02b4cf42SLin Jinhan grp->gy_len = sizeof(G ## _gy); \
57*02b4cf42SLin Jinhan } while (0)
58*02b4cf42SLin Jinhan
59*02b4cf42SLin Jinhan /* transform to big endian */
60*02b4cf42SLin Jinhan /*
61*02b4cf42SLin Jinhan * Domain parameters for secp192r1
62*02b4cf42SLin Jinhan */
63*02b4cf42SLin Jinhan static const uint32_t secp192r1_wide = RK_ECC_CURVE_WIDE_192;
64*02b4cf42SLin Jinhan
65*02b4cf42SLin Jinhan static const uint8_t secp192r1_p[] = {
66*02b4cf42SLin Jinhan 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
67*02b4cf42SLin Jinhan 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
68*02b4cf42SLin Jinhan 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
69*02b4cf42SLin Jinhan };
70*02b4cf42SLin Jinhan
71*02b4cf42SLin Jinhan static const uint8_t secp192r1_a[] = {
72*02b4cf42SLin Jinhan 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
73*02b4cf42SLin Jinhan 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
74*02b4cf42SLin Jinhan 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
75*02b4cf42SLin Jinhan };
76*02b4cf42SLin Jinhan
77*02b4cf42SLin Jinhan static const uint8_t secp192r1_gx[] = {
78*02b4cf42SLin Jinhan 0x12, 0x10, 0xFF, 0x82, 0xFD, 0x0A, 0xFF, 0xF4,
79*02b4cf42SLin Jinhan 0x00, 0x88, 0xA1, 0x43, 0xEB, 0x20, 0xBF, 0x7C,
80*02b4cf42SLin Jinhan 0xF6, 0x90, 0x30, 0xB0, 0x0E, 0xA8, 0x8D, 0x18,
81*02b4cf42SLin Jinhan };
82*02b4cf42SLin Jinhan
83*02b4cf42SLin Jinhan static const uint8_t secp192r1_gy[] = {
84*02b4cf42SLin Jinhan 0x11, 0x48, 0x79, 0x1E, 0xA1, 0x77, 0xF9, 0x73,
85*02b4cf42SLin Jinhan 0xD5, 0xCD, 0x24, 0x6B, 0xED, 0x11, 0x10, 0x63,
86*02b4cf42SLin Jinhan 0x78, 0xDA, 0xC8, 0xFF, 0x95, 0x2B, 0x19, 0x07,
87*02b4cf42SLin Jinhan };
88*02b4cf42SLin Jinhan
89*02b4cf42SLin Jinhan static const uint8_t secp192r1_n[] = {
90*02b4cf42SLin Jinhan 0x31, 0x28, 0xD2, 0xB4, 0xB1, 0xC9, 0x6B, 0x14,
91*02b4cf42SLin Jinhan 0x36, 0xF8, 0xDE, 0x99, 0xFF, 0xFF, 0xFF, 0xFF,
92*02b4cf42SLin Jinhan 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
93*02b4cf42SLin Jinhan };
94*02b4cf42SLin Jinhan
95*02b4cf42SLin Jinhan /*
96*02b4cf42SLin Jinhan * Domain parameters for secp224r1
97*02b4cf42SLin Jinhan */
98*02b4cf42SLin Jinhan static const uint32_t secp224r1_wide = RK_ECC_CURVE_WIDE_224;
99*02b4cf42SLin Jinhan
100*02b4cf42SLin Jinhan static const uint8_t secp224r1_p[] = {
101*02b4cf42SLin Jinhan 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
102*02b4cf42SLin Jinhan 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
103*02b4cf42SLin Jinhan 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
104*02b4cf42SLin Jinhan 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
105*02b4cf42SLin Jinhan };
106*02b4cf42SLin Jinhan
107*02b4cf42SLin Jinhan static const uint8_t secp224r1_a[] = {
108*02b4cf42SLin Jinhan 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
109*02b4cf42SLin Jinhan 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF,
110*02b4cf42SLin Jinhan 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
111*02b4cf42SLin Jinhan 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
112*02b4cf42SLin Jinhan };
113*02b4cf42SLin Jinhan
114*02b4cf42SLin Jinhan static const uint8_t secp224r1_gx[] = {
115*02b4cf42SLin Jinhan 0x21, 0x1D, 0x5C, 0x11, 0xD6, 0x80, 0x32, 0x34,
116*02b4cf42SLin Jinhan 0x22, 0x11, 0xC2, 0x56, 0xD3, 0xC1, 0x03, 0x4A,
117*02b4cf42SLin Jinhan 0xB9, 0x90, 0x13, 0x32, 0x7F, 0xBF, 0xB4, 0x6B,
118*02b4cf42SLin Jinhan 0xBD, 0x0C, 0x0E, 0xB7,
119*02b4cf42SLin Jinhan };
120*02b4cf42SLin Jinhan
121*02b4cf42SLin Jinhan static const uint8_t secp224r1_gy[] = {
122*02b4cf42SLin Jinhan 0x34, 0x7E, 0x00, 0x85, 0x99, 0x81, 0xD5, 0x44,
123*02b4cf42SLin Jinhan 0x64, 0x47, 0x07, 0x5A, 0xA0, 0x75, 0x43, 0xCD,
124*02b4cf42SLin Jinhan 0xE6, 0xDF, 0x22, 0x4C, 0xFB, 0x23, 0xF7, 0xB5,
125*02b4cf42SLin Jinhan 0x88, 0x63, 0x37, 0xBD,
126*02b4cf42SLin Jinhan };
127*02b4cf42SLin Jinhan
128*02b4cf42SLin Jinhan static const uint8_t secp224r1_n[] = {
129*02b4cf42SLin Jinhan 0x3D, 0x2A, 0x5C, 0x5C, 0x45, 0x29, 0xDD, 0x13,
130*02b4cf42SLin Jinhan 0x3E, 0xF0, 0xB8, 0xE0, 0xA2, 0x16, 0xFF, 0xFF,
131*02b4cf42SLin Jinhan 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
132*02b4cf42SLin Jinhan 0xFF, 0xFF, 0xFF, 0xFF,
133*02b4cf42SLin Jinhan };
134*02b4cf42SLin Jinhan
135*02b4cf42SLin Jinhan /*
136*02b4cf42SLin Jinhan * Domain parameters for secp256r1
137*02b4cf42SLin Jinhan */
138*02b4cf42SLin Jinhan static const uint32_t secp256r1_wide = RK_ECC_CURVE_WIDE_256;
139*02b4cf42SLin Jinhan
140*02b4cf42SLin Jinhan static const uint8_t secp256r1_p[] = {
141*02b4cf42SLin Jinhan 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
142*02b4cf42SLin Jinhan 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
143*02b4cf42SLin Jinhan 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
144*02b4cf42SLin Jinhan 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
145*02b4cf42SLin Jinhan };
146*02b4cf42SLin Jinhan
147*02b4cf42SLin Jinhan static const uint8_t secp256r1_a[] = {
148*02b4cf42SLin Jinhan 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
149*02b4cf42SLin Jinhan 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
150*02b4cf42SLin Jinhan 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
151*02b4cf42SLin Jinhan 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
152*02b4cf42SLin Jinhan };
153*02b4cf42SLin Jinhan
154*02b4cf42SLin Jinhan static const uint8_t secp256r1_gx[] = {
155*02b4cf42SLin Jinhan 0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4,
156*02b4cf42SLin Jinhan 0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77,
157*02b4cf42SLin Jinhan 0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8,
158*02b4cf42SLin Jinhan 0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B,
159*02b4cf42SLin Jinhan };
160*02b4cf42SLin Jinhan
161*02b4cf42SLin Jinhan static const uint8_t secp256r1_gy[] = {
162*02b4cf42SLin Jinhan 0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB,
163*02b4cf42SLin Jinhan 0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B,
164*02b4cf42SLin Jinhan 0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E,
165*02b4cf42SLin Jinhan 0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F,
166*02b4cf42SLin Jinhan };
167*02b4cf42SLin Jinhan
168*02b4cf42SLin Jinhan static const uint8_t secp256r1_n[] = {
169*02b4cf42SLin Jinhan 0x51, 0x25, 0x63, 0xFC, 0xC2, 0xCA, 0xB9, 0xF3,
170*02b4cf42SLin Jinhan 0x84, 0x9E, 0x17, 0xA7, 0xAD, 0xFA, 0xE6, 0xBC,
171*02b4cf42SLin Jinhan 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
172*02b4cf42SLin Jinhan 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
173*02b4cf42SLin Jinhan };
174*02b4cf42SLin Jinhan
175*02b4cf42SLin Jinhan /*
176*02b4cf42SLin Jinhan * Domain parameters for sm2p256v1_p
177*02b4cf42SLin Jinhan */
178*02b4cf42SLin Jinhan static const uint32_t sm2p256v1_wide = RK_ECC_CURVE_WIDE_256;
179*02b4cf42SLin Jinhan
180*02b4cf42SLin Jinhan static const uint8_t sm2p256v1_p[] = {
181*02b4cf42SLin Jinhan 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
182*02b4cf42SLin Jinhan 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
183*02b4cf42SLin Jinhan 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
184*02b4cf42SLin Jinhan 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF,
185*02b4cf42SLin Jinhan };
186*02b4cf42SLin Jinhan
187*02b4cf42SLin Jinhan static const uint8_t sm2p256v1_a[] = {
188*02b4cf42SLin Jinhan 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
189*02b4cf42SLin Jinhan 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
190*02b4cf42SLin Jinhan 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
191*02b4cf42SLin Jinhan 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF,
192*02b4cf42SLin Jinhan };
193*02b4cf42SLin Jinhan
194*02b4cf42SLin Jinhan static const uint8_t sm2p256v1_gx[] = {
195*02b4cf42SLin Jinhan 0xC7, 0x74, 0x4C, 0x33, 0x89, 0x45, 0x5A, 0x71,
196*02b4cf42SLin Jinhan 0xE1, 0x0B, 0x66, 0xF2, 0xBF, 0x0B, 0xE3, 0x8F,
197*02b4cf42SLin Jinhan 0x94, 0xC9, 0x39, 0x6A, 0x46, 0x04, 0x99, 0x5F,
198*02b4cf42SLin Jinhan 0x19, 0x81, 0x19, 0x1F, 0x2C, 0xAE, 0xC4, 0x32,
199*02b4cf42SLin Jinhan };
200*02b4cf42SLin Jinhan
201*02b4cf42SLin Jinhan static const uint8_t sm2p256v1_gy[] = {
202*02b4cf42SLin Jinhan 0xA0, 0xF0, 0x39, 0x21, 0xE5, 0x32, 0xDF, 0x02,
203*02b4cf42SLin Jinhan 0x40, 0x47, 0x2A, 0xC6, 0x7C, 0x87, 0xA9, 0xD0,
204*02b4cf42SLin Jinhan 0x53, 0x21, 0x69, 0x6B, 0xE3, 0xCE, 0xBD, 0x59,
205*02b4cf42SLin Jinhan 0x9C, 0x77, 0xF6, 0xF4, 0xA2, 0x36, 0x37, 0xBC,
206*02b4cf42SLin Jinhan };
207*02b4cf42SLin Jinhan
208*02b4cf42SLin Jinhan static const uint8_t sm2p256v1_n[] = {
209*02b4cf42SLin Jinhan 0x23, 0x41, 0xD5, 0x39, 0x09, 0xF4, 0xBB, 0x53,
210*02b4cf42SLin Jinhan 0x2B, 0x05, 0xC6, 0x21, 0x6B, 0xDF, 0x03, 0x72,
211*02b4cf42SLin Jinhan 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
212*02b4cf42SLin Jinhan 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF,
213*02b4cf42SLin Jinhan };
214*02b4cf42SLin Jinhan
word_reverse(u32 word)215*02b4cf42SLin Jinhan static inline u32 word_reverse(u32 word)
216*02b4cf42SLin Jinhan {
217*02b4cf42SLin Jinhan u32 i;
218*02b4cf42SLin Jinhan u32 new_word = 0;
219*02b4cf42SLin Jinhan
220*02b4cf42SLin Jinhan for (i = 0; i < sizeof(u32); i++) {
221*02b4cf42SLin Jinhan new_word |= (word & 0xff) << (8 * (sizeof(u32) - i - 1));
222*02b4cf42SLin Jinhan word >>= 8;
223*02b4cf42SLin Jinhan }
224*02b4cf42SLin Jinhan
225*02b4cf42SLin Jinhan return new_word;
226*02b4cf42SLin Jinhan }
227*02b4cf42SLin Jinhan
is_ec_supported(void)228*02b4cf42SLin Jinhan static inline bool is_ec_supported(void)
229*02b4cf42SLin Jinhan {
230*02b4cf42SLin Jinhan return !!RK_ECP_READ_REG(RK_ECC_MAX_CURVE_WIDE);
231*02b4cf42SLin Jinhan }
232*02b4cf42SLin Jinhan
233*02b4cf42SLin Jinhan /* reverse endian word copy */
rk_ecp_load_data(u32 * dst,struct mpa_num * src)234*02b4cf42SLin Jinhan static int rk_ecp_load_data(u32 *dst, struct mpa_num *src)
235*02b4cf42SLin Jinhan {
236*02b4cf42SLin Jinhan u32 i;
237*02b4cf42SLin Jinhan u32 dst_pos, src_pos;
238*02b4cf42SLin Jinhan
239*02b4cf42SLin Jinhan util_word_memset(dst, 0, RK_ECP_MAX_WORDS);
240*02b4cf42SLin Jinhan
241*02b4cf42SLin Jinhan dst_pos = src->size - 1;
242*02b4cf42SLin Jinhan src_pos = 0;
243*02b4cf42SLin Jinhan
244*02b4cf42SLin Jinhan for (i = 0; i < src->size; i++)
245*02b4cf42SLin Jinhan dst[dst_pos--] = word_reverse(src->d[src_pos++]);
246*02b4cf42SLin Jinhan
247*02b4cf42SLin Jinhan return 0;
248*02b4cf42SLin Jinhan }
249*02b4cf42SLin Jinhan
rk_word_cmp_zero(uint32_t * buf1,uint32_t n_words)250*02b4cf42SLin Jinhan static int rk_word_cmp_zero(uint32_t *buf1, uint32_t n_words)
251*02b4cf42SLin Jinhan {
252*02b4cf42SLin Jinhan int ret = 0;
253*02b4cf42SLin Jinhan uint32_t i;
254*02b4cf42SLin Jinhan
255*02b4cf42SLin Jinhan for (i = 0 ; i < n_words; i++) {
256*02b4cf42SLin Jinhan if (buf1[i] != 0)
257*02b4cf42SLin Jinhan ret = -EINVAL;
258*02b4cf42SLin Jinhan }
259*02b4cf42SLin Jinhan
260*02b4cf42SLin Jinhan return ret;
261*02b4cf42SLin Jinhan }
262*02b4cf42SLin Jinhan
263*02b4cf42SLin Jinhan /*
264*02b4cf42SLin Jinhan * Set a group using well-known domain parameters
265*02b4cf42SLin Jinhan */
rk_ecp_group_load(struct rk_ecp_group * grp,enum rk_ecp_group_id id)266*02b4cf42SLin Jinhan static int rk_ecp_group_load(struct rk_ecp_group *grp, enum rk_ecp_group_id id)
267*02b4cf42SLin Jinhan {
268*02b4cf42SLin Jinhan memset(grp, 0x00, sizeof(*grp));
269*02b4cf42SLin Jinhan
270*02b4cf42SLin Jinhan grp->id = id;
271*02b4cf42SLin Jinhan
272*02b4cf42SLin Jinhan switch (id) {
273*02b4cf42SLin Jinhan case RK_ECP_DP_SECP192R1:
274*02b4cf42SLin Jinhan RK_LOAD_GROUP_A(secp192r1);
275*02b4cf42SLin Jinhan return 0;
276*02b4cf42SLin Jinhan
277*02b4cf42SLin Jinhan case RK_ECP_DP_SECP224R1:
278*02b4cf42SLin Jinhan RK_LOAD_GROUP_A(secp224r1);
279*02b4cf42SLin Jinhan return 0;
280*02b4cf42SLin Jinhan
281*02b4cf42SLin Jinhan case RK_ECP_DP_SECP256R1:
282*02b4cf42SLin Jinhan RK_LOAD_GROUP_A(secp256r1);
283*02b4cf42SLin Jinhan return 0;
284*02b4cf42SLin Jinhan
285*02b4cf42SLin Jinhan case RK_ECP_DP_SM2P256V1:
286*02b4cf42SLin Jinhan RK_LOAD_GROUP_A(sm2p256v1);
287*02b4cf42SLin Jinhan return 0;
288*02b4cf42SLin Jinhan
289*02b4cf42SLin Jinhan default:
290*02b4cf42SLin Jinhan return -EINVAL;
291*02b4cf42SLin Jinhan }
292*02b4cf42SLin Jinhan }
293*02b4cf42SLin Jinhan
rockchip_ecc_request_set(uint32_t ecc_ctl,uint32_t wide)294*02b4cf42SLin Jinhan static int rockchip_ecc_request_set(uint32_t ecc_ctl, uint32_t wide)
295*02b4cf42SLin Jinhan {
296*02b4cf42SLin Jinhan RK_ECP_WRITE_REG(RK_ECC_CURVE_WIDE, wide);
297*02b4cf42SLin Jinhan
298*02b4cf42SLin Jinhan RK_ECP_WRITE_REG(RK_ECC_INT_EN, 0);
299*02b4cf42SLin Jinhan RK_ECP_WRITE_REG(RK_ECC_INT_ST, RK_ECP_READ_REG(RK_ECC_INT_ST));
300*02b4cf42SLin Jinhan RK_ECP_WRITE_REG(RK_ECC_CTL, ecc_ctl);
301*02b4cf42SLin Jinhan
302*02b4cf42SLin Jinhan return 0;
303*02b4cf42SLin Jinhan }
304*02b4cf42SLin Jinhan
rockchip_ecc_request_wait_done(void)305*02b4cf42SLin Jinhan static int rockchip_ecc_request_wait_done(void)
306*02b4cf42SLin Jinhan {
307*02b4cf42SLin Jinhan int ret = 0;
308*02b4cf42SLin Jinhan u32 reg_val = 0;
309*02b4cf42SLin Jinhan
310*02b4cf42SLin Jinhan do {
311*02b4cf42SLin Jinhan reg_val = crypto_read(RK_ECC_INT_ST);
312*02b4cf42SLin Jinhan } while ((reg_val & 0x01) != RK_ECC_INT_ST_DONE);
313*02b4cf42SLin Jinhan
314*02b4cf42SLin Jinhan if (RK_ECP_READ_REG(RK_ECC_ABN_ST)) {
315*02b4cf42SLin Jinhan ret = -EFAULT;
316*02b4cf42SLin Jinhan goto exit;
317*02b4cf42SLin Jinhan }
318*02b4cf42SLin Jinhan
319*02b4cf42SLin Jinhan exit:
320*02b4cf42SLin Jinhan if (ret) {
321*02b4cf42SLin Jinhan printf("RK_ECC_CTL = %08x\n", RK_ECP_READ_REG(RK_ECC_CTL));
322*02b4cf42SLin Jinhan printf("RK_ECC_INT_EN = %08x\n", RK_ECP_READ_REG(RK_ECC_INT_EN));
323*02b4cf42SLin Jinhan printf("RK_ECC_CURVE_WIDE = %08x\n", RK_ECP_READ_REG(RK_ECC_CURVE_WIDE));
324*02b4cf42SLin Jinhan printf("RK_ECC_RAM_CTL = %08x\n", RK_ECP_READ_REG(RK_ECC_RAM_CTL));
325*02b4cf42SLin Jinhan printf("RK_ECC_INT_ST = %08x\n", RK_ECP_READ_REG(RK_ECC_INT_ST));
326*02b4cf42SLin Jinhan printf("RK_ECC_ABN_ST = %08x\n", RK_ECP_READ_REG(RK_ECC_ABN_ST));
327*02b4cf42SLin Jinhan }
328*02b4cf42SLin Jinhan
329*02b4cf42SLin Jinhan RK_ECP_WRITE_REG(RK_ECC_CTL, 0);
330*02b4cf42SLin Jinhan RK_ECP_RAM_FOR_CPU();
331*02b4cf42SLin Jinhan
332*02b4cf42SLin Jinhan return ret;
333*02b4cf42SLin Jinhan }
334*02b4cf42SLin Jinhan
rockchip_ecc_request_trigger(void)335*02b4cf42SLin Jinhan static int rockchip_ecc_request_trigger(void)
336*02b4cf42SLin Jinhan {
337*02b4cf42SLin Jinhan uint32_t ecc_ctl = RK_ECP_READ_REG(RK_ECC_CTL);
338*02b4cf42SLin Jinhan
339*02b4cf42SLin Jinhan RK_ECP_RAM_FOR_ECC();
340*02b4cf42SLin Jinhan
341*02b4cf42SLin Jinhan RK_ECP_WRITE_REG(RK_ECC_CTL, ecc_ctl | RK_ECC_CTL_REQ_ECC);
342*02b4cf42SLin Jinhan
343*02b4cf42SLin Jinhan return rockchip_ecc_request_wait_done();
344*02b4cf42SLin Jinhan }
345*02b4cf42SLin Jinhan
rockchip_ecc_get_group_id(uint32_t crypto_algo)346*02b4cf42SLin Jinhan static uint32_t rockchip_ecc_get_group_id(uint32_t crypto_algo)
347*02b4cf42SLin Jinhan {
348*02b4cf42SLin Jinhan switch (crypto_algo) {
349*02b4cf42SLin Jinhan case CRYPTO_ECC_192R1:
350*02b4cf42SLin Jinhan return RK_ECP_DP_SECP192R1;
351*02b4cf42SLin Jinhan case CRYPTO_ECC_224R1:
352*02b4cf42SLin Jinhan return RK_ECP_DP_SECP224R1;
353*02b4cf42SLin Jinhan case CRYPTO_ECC_256R1:
354*02b4cf42SLin Jinhan return RK_ECP_DP_SECP256R1;
355*02b4cf42SLin Jinhan case CRYPTO_SM2:
356*02b4cf42SLin Jinhan return RK_ECP_DP_SM2P256V1;
357*02b4cf42SLin Jinhan default:
358*02b4cf42SLin Jinhan return RK_ECP_DP_NONE;
359*02b4cf42SLin Jinhan }
360*02b4cf42SLin Jinhan }
361*02b4cf42SLin Jinhan
rockchip_ecc_verify(uint32_t crypto_algo,uint8_t * hash,uint32_t hash_len,struct rk_ecp_point * point_P,struct rk_ecp_point * point_sign)362*02b4cf42SLin Jinhan int rockchip_ecc_verify(uint32_t crypto_algo, uint8_t *hash, uint32_t hash_len,
363*02b4cf42SLin Jinhan struct rk_ecp_point *point_P, struct rk_ecp_point *point_sign)
364*02b4cf42SLin Jinhan {
365*02b4cf42SLin Jinhan int ret;
366*02b4cf42SLin Jinhan uint32_t curve_sel = 0;
367*02b4cf42SLin Jinhan struct mpa_num *bn_hash = NULL;
368*02b4cf42SLin Jinhan uint32_t group_id = rockchip_ecc_get_group_id(crypto_algo);
369*02b4cf42SLin Jinhan struct rk_ecp_group grp;
370*02b4cf42SLin Jinhan struct rk_ecc_verify *ecc_st = (struct rk_ecc_verify *)SM2_RAM_BASE;
371*02b4cf42SLin Jinhan
372*02b4cf42SLin Jinhan if (!is_ec_supported())
373*02b4cf42SLin Jinhan return -ENOSYS;
374*02b4cf42SLin Jinhan
375*02b4cf42SLin Jinhan if (!hash ||
376*02b4cf42SLin Jinhan hash_len == 0 ||
377*02b4cf42SLin Jinhan hash_len > RK_ECP_MAX_BYTES ||
378*02b4cf42SLin Jinhan RK_ECP_IS_POINT_INVALID(point_P) ||
379*02b4cf42SLin Jinhan RK_ECP_IS_POINT_INVALID(point_sign)) {
380*02b4cf42SLin Jinhan ret = -EINVAL;
381*02b4cf42SLin Jinhan goto exit;
382*02b4cf42SLin Jinhan }
383*02b4cf42SLin Jinhan
384*02b4cf42SLin Jinhan ret = rk_ecp_group_load(&grp, group_id);
385*02b4cf42SLin Jinhan if (ret)
386*02b4cf42SLin Jinhan goto exit;
387*02b4cf42SLin Jinhan
388*02b4cf42SLin Jinhan rk_mpa_alloc(&bn_hash, hash, BYTE2WORD(hash_len));
389*02b4cf42SLin Jinhan if (!bn_hash) {
390*02b4cf42SLin Jinhan ret = -ENOMEM;
391*02b4cf42SLin Jinhan goto exit;
392*02b4cf42SLin Jinhan }
393*02b4cf42SLin Jinhan
394*02b4cf42SLin Jinhan RK_ECP_RAM_FOR_CPU();
395*02b4cf42SLin Jinhan
396*02b4cf42SLin Jinhan curve_sel = group_id == RK_ECP_DP_SM2P256V1 ?
397*02b4cf42SLin Jinhan RK_ECC_CTL_FUNC_SM2_CURVER : RK_ECC_CTL_FUNC_ECC_CURVER;
398*02b4cf42SLin Jinhan
399*02b4cf42SLin Jinhan RK_ECP_LOAD_DATA(ecc_st->e, bn_hash);
400*02b4cf42SLin Jinhan RK_ECP_LOAD_DATA(ecc_st->r_, point_sign->x);
401*02b4cf42SLin Jinhan RK_ECP_LOAD_DATA(ecc_st->s_, point_sign->y);
402*02b4cf42SLin Jinhan RK_ECP_LOAD_DATA(ecc_st->p_x, point_P->x);
403*02b4cf42SLin Jinhan RK_ECP_LOAD_DATA(ecc_st->p_y, point_P->y);
404*02b4cf42SLin Jinhan
405*02b4cf42SLin Jinhan RK_ECP_LOAD_DATA_EXT(ecc_st->A, grp.a, grp.a_len);
406*02b4cf42SLin Jinhan RK_ECP_LOAD_DATA_EXT(ecc_st->P, grp.p, grp.p_len);
407*02b4cf42SLin Jinhan RK_ECP_LOAD_DATA_EXT(ecc_st->N, grp.n, grp.n_len);
408*02b4cf42SLin Jinhan
409*02b4cf42SLin Jinhan RK_ECP_LOAD_DATA_EXT(ecc_st->G_x, grp.gx, grp.gx_len);
410*02b4cf42SLin Jinhan RK_ECP_LOAD_DATA_EXT(ecc_st->G_y, grp.gy, grp.gy_len);
411*02b4cf42SLin Jinhan
412*02b4cf42SLin Jinhan rockchip_ecc_request_set(curve_sel | RK_ECC_CTL_FUNC_SEL_VERIFY, grp.wide);
413*02b4cf42SLin Jinhan
414*02b4cf42SLin Jinhan ret = rockchip_ecc_request_trigger();
415*02b4cf42SLin Jinhan if (ret ||
416*02b4cf42SLin Jinhan rk_word_cmp_zero(ecc_st->v, RK_ECP_MAX_WORDS) ||
417*02b4cf42SLin Jinhan rk_word_cmp_zero(ecc_st->r_, RK_ECP_MAX_WORDS) == 0) {
418*02b4cf42SLin Jinhan ret = -EKEYREJECTED;
419*02b4cf42SLin Jinhan }
420*02b4cf42SLin Jinhan exit:
421*02b4cf42SLin Jinhan rk_mpa_free(&bn_hash);
422*02b4cf42SLin Jinhan
423*02b4cf42SLin Jinhan return ret;
424*02b4cf42SLin Jinhan }
425