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