1 /******************************************************************************
2 * Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
3 * All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *****************************************************************************/
18 #pragma once
19
20 #include "reg_include/register_b91.h"
21
22 #define GET_WORD_LEN(bitLen) (((bitLen) + 31) / 32)
23 #define GET_BYTE_LEN(bitLen) (((bitLen) + 7) / 8)
24
25 #define PKE_BASE (0X80110000)
26 #define reg_pke_a_ram(a) ((volatile unsigned long *)(PKE_BASE + 0x0400 + (a) * (0x24)))
27 #define reg_pke_b_ram(b) ((volatile unsigned long *)(PKE_BASE + 0x1000 + (b) * (0x24)))
28
29 /********* oprand length *********/
30 #define PKE_OPERAND_MAX_WORD_LEN (0x08)
31 #define PKE_OPERAND_MAX_BIT_LEN (0x100)
32 #define ECC_MAX_WORD_LEN PKE_OPERAND_MAX_WORD_LEN
33 #define ECC_MAX_BIT_LEN PKE_OPERAND_MAX_BIT_LEN
34
35 #ifndef NULL
36 #define NULL 0
37 #endif
38
39 /**
40 * eccp curve
41 */
42 typedef struct {
43 unsigned int eccp_p_bitLen; // bit length of prime p
44 unsigned int eccp_n_bitLen; // bit length of order n
45 unsigned int *eccp_p;
46 unsigned int *eccp_p_h;
47 unsigned int *eccp_p_n1;
48 unsigned int *eccp_a;
49 unsigned int *eccp_b;
50 unsigned int *eccp_Gx;
51 unsigned int *eccp_Gy;
52 unsigned int *eccp_n;
53 unsigned int *eccp_n_h;
54 unsigned int *eccp_n_n1;
55 } eccp_curve_t;
56
57 /**
58 * mont curve
59 */
60 typedef struct {
61 unsigned int mont_p_bitLen; // bit length of prime p
62 unsigned int *mont_p;
63 unsigned int *mont_p_h;
64 unsigned int *mont_p_n1;
65 unsigned int *mont_a24;
66 unsigned int *mont_u;
67 unsigned int *mont_v;
68 unsigned int *mont_n;
69 unsigned int *mont_n_h;
70 unsigned int *mont_n_n1;
71 unsigned int *mont_h;
72 } mont_curve_t;
73
74 /**
75 * edward curve
76 */
77 typedef struct {
78 unsigned int edward_p_bitLen; // bit length of prime p
79 unsigned int *edward_p;
80 unsigned int *edward_p_h;
81 unsigned int *edward_p_n1;
82 unsigned int *edward_d;
83 unsigned int *edward_Gx;
84 unsigned int *edward_Gy;
85 unsigned int *edward_n;
86 unsigned int *edward_n_h;
87 unsigned int *edward_n_n1;
88 unsigned int *edward_h;
89 } edward_curve_t;
90
91 /**
92 * pke return code
93 */
94 typedef enum {
95 PKE_SUCCESS = 0,
96 PKE_ACTIVE_STOP,
97 PKE_MOD_INV_NOT_EXIST,
98 PKE_POINT_NOT_ON_CURVE,
99 PKE_INVALID_MICRO_CODE,
100 PKE_POINTOR_NULL,
101 PKE_INVALID_INPUT,
102 } pke_ret_code_e;
103
104 /**
105 * pke exe cfg
106 */
107 typedef enum {
108 PKE_EXE_CFG_ALL_NON_MONT = 0x15,
109 PKE_EXE_CFG_ALL_MONT = 0x2A,
110 } pke_exe_cfg_e;
111
112 /**
113 * pke micro code
114 */
115 typedef enum {
116 PKE_MICROCODE_PDBL = 0x04,
117 PKE_MICROCODE_PADD = 0x08,
118 PKE_MICROCODE_PVER = 0x0C,
119 PKE_MICROCODE_PMUL = 0x10,
120 PKE_MICROCODE_MODMUL = 0x18,
121 PKE_MICROCODE_MODINV = 0x1C,
122 PKE_MICROCODE_MODADD = 0x20,
123 PKE_MICROCODE_MODSUB = 0x24,
124 PKE_MICROCODE_CAL_PRE_MON = 0x28,
125 PKE_MICROCODE_C25519_PMUL = 0x34,
126 PKE_MICROCODE_Ed25519_PMUL = 0x38,
127 PKE_MICROCODE_Ed25519_PADD = 0x3C,
128 } pke_microcode_e;
129
130 /**
131 * @brief This function serves to get pke status.
132 * @param[in] status - the interrupt status to be obtained.
133 * @return pke status.
134 */
pke_get_irq_status(pke_status_e status)135 static inline unsigned int pke_get_irq_status(pke_status_e status)
136 {
137 return reg_pke_stat & status;
138 }
139
140 /**
141 * @brief This function serves to clear pke status.
142 * @param[in] status - the interrupt status that needs to be cleared.
143 * @return none.
144 */
pke_clr_irq_status(pke_status_e status)145 static inline void pke_clr_irq_status(pke_status_e status)
146 {
147 BM_CLR(reg_pke_stat, status);
148 }
149
150 /**
151 * @brief This function serves to enable pke interrupt function.
152 * @param[in] mask - the irq mask.
153 * @return none.
154 */
pke_set_irq_mask(pke_conf_e mask)155 static inline void pke_set_irq_mask(pke_conf_e mask)
156 {
157 BM_SET(reg_pke_conf, mask);
158 }
159
160 /**
161 * @brief This function serves to disable PKE interrupt function.
162 * @param[in] mask - the irq mask.
163 * @return none.
164 */
pke_clr_irq_mask(pke_conf_e mask)165 static inline void pke_clr_irq_mask(pke_conf_e mask)
166 {
167 BM_CLR(reg_pke_conf, mask);
168 }
169
170 /**
171 * @brief set operation micro code.
172 * @param[in] addr - pke micro code.
173 * @return none.
174 */
pke_set_microcode(pke_microcode_e addr)175 static inline void pke_set_microcode(pke_microcode_e addr)
176 {
177 reg_pke_mc_ptr = addr;
178 }
179
180 /**
181 * @brief set exe config.
182 * @param[in] cfg - pke exe conf.
183 * @return none.
184 */
pke_set_exe_cfg(pke_exe_cfg_e cfg)185 static inline void pke_set_exe_cfg(pke_exe_cfg_e cfg)
186 {
187 reg_pke_exe_conf = cfg;
188 }
189
190 /**
191 * @brief start pke calculate.
192 * @return none.
193 */
pke_opr_start(void)194 static inline void pke_opr_start(void)
195 {
196 BM_SET(reg_pke_ctrl, FLD_PKE_CTRL_START);
197 }
198
199 /**
200 * @brief This is used to indicate the reason when the pke stopped.
201 * @return 0 - normal stop.
202 * 1 - received a termination request(CTRL.STOP is high).
203 * 2 - no valid modulo inverse.
204 * 3 - point is not on the curve(CTRL.CMD:PVER).
205 * 4 - invalid microcode.
206 */
pke_check_rt_code(void)207 static inline unsigned char pke_check_rt_code(void)
208 {
209 return (unsigned char)(reg_pke_rt_code & FLD_PKE_RT_CODE_STOP_LOG);
210 }
211
212 /**
213 * @brief set operand width please make sure 0 < bitLen <= 256.
214 * @param[in] bitLen - operand width.
215 * @return none.
216 */
pke_set_operand_width(unsigned int bitLen)217 static inline void pke_set_operand_width(unsigned int bitLen)
218 {
219 BM_CLR(reg_pke_conf, FLD_PKE_CONF_PARTIAL_RADIX);
220 BM_SET(reg_pke_conf, GET_WORD_LEN(bitLen) << 16);
221 BM_CLR(reg_pke_conf, FLD_PKE_CONF_BASE_RADIX);
222 BM_SET(reg_pke_conf, 2 << 24);
223 }
224
225 /**
226 * @brief compare big integer a and b.
227 * @param[in] a - value.
228 * @param[in] aWordLen - the length of a.
229 * @param[in] b - value.
230 * @param[in] bWordLen - the length of b.
231 * @return 0:a=b, 1:a>b, -1: a<b.
232 */
233 signed int big_integer_compare(unsigned int *a, unsigned int aWordLen, unsigned int *b, unsigned int bWordLen);
234
235 /**
236 * @brief c = a - b.
237 * @param[in] a - integer a.
238 * @param[in] b - integer b.
239 * @param[in] wordLen - the length of a and b.
240 * @param[out] c - integer c = a - b.
241 * @return none.
242 */
243 void sub_u32(unsigned int *a, unsigned int *b, unsigned int *c, unsigned int wordLen);
244
245 /**
246 * @brief a = a/(2^n).
247 * @param[in] a - big integer a.
248 * @param[in] aWordLen - word length of a.
249 * @param[in] n - exponent of 2^n.
250 * @return word length of a = a/(2^n).
251 * @attention: 1. make sure aWordLen is real word length of a.
252 * 2. a may be 0, then aWordLen is 0, to make sure aWordLen-1 is available, so data
253 * type of aWordLen is int32_t, not uint32_t.
254 */
255 unsigned int div2n_u32(unsigned int a[], signed int aWordLen, unsigned int n);
256
257 /**
258 * @brief load the pre-calculated mont parameters H(R^2 mod modulus) and
259 * n1( - modulus ^(-1) mod 2^w ).
260 * @param[in] H - R^2 mod modulus.
261 * @param[in] n1 - modulus ^(-1) mod 2^w, here w is 32 acutally.
262 * @param[in] wordLen - word length of modulus or H.
263 * @return: none.
264 */
265 void pke_load_pre_calc_mont(unsigned int *H, unsigned int *n1, unsigned int wordLen);
266
267 /**
268 * @brief calc h(R^2 mod modulus) and n1( - modulus ^(-1) mod 2^w ) for modmul, pointMul. etc.
269 * here w is bit width of word, i,e. 32.
270 * @param[in] modulus - input, modulus.
271 * @param[in] wordLen - input, word length of modulus or H.
272 * @return PKE_SUCCESS(success), other(error).
273 */
274 unsigned char pke_calc_pre_mont(const unsigned int *modulus, unsigned int wordLen);
275
276 /**
277 * @brief out = a*b mod modulus.
278 * @param[in] modulus - modulus.
279 * @param[in] a - integer a.
280 * @param[in] b - integer b.
281 * @param[in] wordLen - word length of modulus, a, b.
282 * @param[out] out - out = a*b mod modulus.
283 * @return PKE_SUCCESS(success), other(error).
284 */
285 unsigned char pke_mod_mul(const unsigned int *modulus, const unsigned int *a, const unsigned int *b, unsigned int *out,
286 unsigned int wordLen);
287
288 /**
289 * @brief ainv = a^(-1) mod modulus.
290 * @param[in] modulus - modulus.
291 * @param[in] a - integer a.
292 * @param[in] modWordLen - word length of modulus, ainv.
293 * @param[in] aWordLen - word length of integer a.
294 * @param[out] ainv - ainv = a^(-1) mod modulus.
295 * @return: PKE_SUCCESS(success), other(inverse not exists or error).
296 */
297 unsigned char pke_mod_inv(const unsigned int *modulus, const unsigned int *a, unsigned int *ainv,
298 unsigned int modWordLen, unsigned int aWordLen);
299
300 /**
301 * @brief out = (a+b) mod modulus.
302 * @param[in] modulus - modulus.
303 * @param[in] a - integer a.
304 * @param[in] b - integer b.
305 * @param[in] wordLen - word length of modulus, a, b.
306 * @param[out] out - out = a+b mod modulus.
307 * @return PKE_SUCCESS(success), other(error).
308 */
309 unsigned char pke_mod_add(const unsigned int *modulus, const unsigned int *a, const unsigned int *b, unsigned int *out,
310 unsigned int wordLen);
311
312 /**
313 * @brief out = (a-b) mod modulus.
314 * @param[in] modulus - input, modulus.
315 * @param[in] a - input, integer a.
316 * @param[in] b - input, integer b.
317 * @param[in] wordLen - input, word length of modulus, a, b.
318 * @param[out] out - output, out = a-b mod modulus.
319 * @return PKE_SUCCESS(success), other(error).
320 */
321 unsigned char pke_mod_sub(const unsigned int *modulus, const unsigned int *a, const unsigned int *b, unsigned int *out,
322 unsigned int wordLen);
323
324 /**
325 * @brief c = a mod b.
326 * @param[in] a - integer a.
327 * @param[in] b - integer b.
328 * @param[in] aWordLen - word length of a.
329 * @param[in] bWordLen - word length of b.
330 * @param[in] b_h - parameter b_h.
331 * @param[in] b_n1 - parameter b_n1.
332 * @param[out] c - c = a mod b.
333 * @return PKE_SUCCESS(success), other(error).
334 */
335 unsigned char pke_mod(unsigned int *a, unsigned int aWordLen, unsigned int *b, unsigned int *b_h, unsigned int *b_n1,
336 unsigned int bWordLen, unsigned int *c);
337
338 /**
339 * @brief ECCP curve point del point, Q=2P.
340 * @param[in] curve - ECCP_CURVE struct pointer.
341 * @param[in] Px - x coordinate of point P.
342 * @param[in] Py - y coordinate of point P.
343 * @param[out] Qx - x coordinate of point Q=2P.
344 * @param[out] Qy - y coordinate of point Q=2P.
345 * @return PKE_SUCCESS(success), other(error).
346 */
347 unsigned char pke_eccp_point_del(eccp_curve_t *curve, unsigned int *Px, unsigned int *Py, unsigned int *Qx,
348 unsigned int *Qy);
349
350 /**
351 * @brief check whether the input point P is on ECCP curve or not.
352 * @param[in] curve - ECCP_CURVE struct pointer.
353 * @param[in] Px - x coordinate of point P.
354 * @param[in] Py - y coordinate of point P.
355 * @return PKE_SUCCESS(success, on the curve), other(error or not on the curve).
356 */
357 unsigned char pke_eccp_point_verify(eccp_curve_t *curve, unsigned int *Px, unsigned int *Py);
358
359 /**
360 * @brief ECCP curve point mul(random point), Q=[k]P.
361 * @param[in] curve - ECCP_CURVE struct pointer.
362 * @param[in] k - scalar.
363 * @param[in] Px - x coordinate of point P.
364 * @param[in] Py - y coordinate of point P.
365 * @param[out] Qx - x coordinate of point Q=[k]P.
366 * @param[out] Qy - y coordinate of point Q=[k]P.
367 * @return PKE_SUCCESS(success), other(error).
368 */
369 unsigned char pke_eccp_point_mul(eccp_curve_t *curve, unsigned int *k, unsigned int *Px, unsigned int *Py,
370 unsigned int *Qx, unsigned int *Qy);
371
372 /**
373 * @brief ECCP curve point add, Q=P1+P2.
374 * @param[in] curve - eccp curve struct pointer.
375 * @param[in] P1x - x coordinate of point P1.
376 * @param[in] P1y - y coordinate of point P1.
377 * @param[in] P2x - x coordinate of point P2.
378 * @param[in] P2y - y coordinate of point P2.
379 * @param[out] Qx - x coordinate of point Q=P1+P2.
380 * @param[out] Qy - y coordinate of point Q=P1+P2.
381 * @return PKE_SUCCESS(success), other(error).
382 */
383 unsigned char pke_eccp_point_add(eccp_curve_t *curve, unsigned int *P1x, unsigned int *P1y, unsigned int *P2x,
384 unsigned int *P2y, unsigned int *Qx, unsigned int *Qy);
385
386 /**
387 * @brief c25519 point mul(random point), Q=[k]P.
388 * @param[in] curve - c25519 curve struct pointer.
389 * @param[in] k - scalar.
390 * @param[in] Pu - u coordinate of point P.
391 * @param[out] Qu - u coordinate of point Q=[k]P.
392 * @return PKE_SUCCESS(success), other(error).
393 */
394 unsigned char pke_x25519_point_mul(mont_curve_t *curve, unsigned int *k, unsigned int *Pu, unsigned int *Qu);
395
396 /**
397 * @brief edwards25519 curve point mul(random point), Q=[k]P.
398 * @param[in] curve - edwards25519 curve struct pointer.
399 * @param[in] k - scalar.
400 * @param[in] Px - x coordinate of point P.
401 * @param[in] Py - y coordinate of point P.
402 * @param[out] Qx - x coordinate of point Q=[k]P.
403 * @param[out] Qy - y coordinate of point Q=[k]P.
404 * @return PKE_SUCCESS(success), other(error).
405 */
406 unsigned char pke_ed25519_point_mul(edward_curve_t *curve, unsigned int *k, unsigned int *Px, unsigned int *Py,
407 unsigned int *Qx, unsigned int *Qy);
408
409 /**
410 * @brief edwards25519 point add, Q=P1+P2.
411 * @param[in] curve - edwards25519 curve struct pointer.
412 * @param[in] P1x - x coordinate of point P1.
413 * @param[in] P1y - y coordinate of point P1.
414 * @param[in] P2x - x coordinate of point P2.
415 * @param[in] P2y - y coordinate of point P2.
416 * @param[out] Qx - x coordinate of point Q=P1+P2.
417 * @param[out] Qy - y coordinate of point Q=P1+P2.
418 * @return PKE_SUCCESS(success), other(error).
419 */
420 unsigned char pke_ed25519_point_add(edward_curve_t *curve, unsigned int *P1x, unsigned int *P1y, unsigned int *P2x,
421 unsigned int *P2y, unsigned int *Qx, unsigned int *Qy);
422