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.c
21 *
22 * @brief This is the source file for B91
23 *
24 * @author Driver Group
25 *
26 *******************************************************************************************************/
27 #include "pke.h"
28 #include "string.h"
29
30 /**
31 * @brief get real bit length of big number a of wordLen words.
32 * @param[in] a - the buffer a.
33 * @param[in] wordLen - the length of a.
34 * @return the real bit length of big number a of wordLen words.
35 */
valid_bits_get(const unsigned int * a,unsigned int wordLen)36 unsigned int valid_bits_get(const unsigned int *a, unsigned int wordLen)
37 {
38 unsigned int i = 0;
39 unsigned int j = 0;
40
41 if(0 == wordLen)
42 {
43 return 0;
44 }
45
46 for (i = wordLen; i > 0; i--)
47 {
48 if (a[i - 1])
49 {
50 break;
51 }
52 }
53
54 if(0 == i)
55 {
56 return 0;
57 }
58
59 for (j = 32; j > 0; j--)
60 {
61 if (a[i - 1] & (0x1 << (j - 1)))
62 {
63 break;
64 }
65 }
66
67 return ((i - 1) << 5) + j;
68 }
69
70 /**
71 * @brief get real word lenth of big number a of max_words words.
72 * @param[in] a - the buffer a.
73 * @param[in] max_words - the length of a.
74 * @return get real word lenth of big number a.
75 */
valid_words_get(unsigned int * a,unsigned int max_words)76 unsigned int valid_words_get(unsigned int *a, unsigned int max_words)
77 {
78 unsigned int i = 0;
79
80 for (i = max_words; i > 0; i--)
81 {
82 if (a[i - 1])
83 {
84 return i;
85 }
86 }
87
88 return 0;
89 }
90
91 /**
92 * @brief compare big integer a and b.
93 * @param[in] a - value.
94 * @param[in] aWordLen - the length of a.
95 * @param[in] b - value.
96 * @param[in] bWordLen - the length of b.
97 * @return 0:a=b, 1:a>b, -1: a<b.
98 */
big_integer_compare(unsigned int * a,unsigned int aWordLen,unsigned int * b,unsigned int bWordLen)99 signed int big_integer_compare(unsigned int *a, unsigned int aWordLen, unsigned int *b, unsigned int bWordLen)
100 {
101 signed int i;
102
103 aWordLen = valid_words_get(a, aWordLen);
104 bWordLen = valid_words_get(b, bWordLen);
105
106 if(aWordLen > bWordLen)
107 return 1;
108 if(aWordLen < bWordLen)
109 return -1;
110
111 for(i=(aWordLen-1); i>=0; i--)
112 {
113 if(a[i] > b[i])
114 return 1;
115 if(a[i] < b[i])
116 return -1;
117 }
118
119 return 0;
120 }
121
122 /**
123 * @brief c = a - b.
124 * @param[in] a - integer a.
125 * @param[in] b - integer b.
126 * @param[in] wordLen - the length of a and b.
127 * @param[out] c - integer c = a - b.
128 * @return none.
129 */
sub_u32(unsigned int * a,unsigned int * b,unsigned int * c,unsigned int wordLen)130 void sub_u32(unsigned int *a, unsigned int *b, unsigned int *c, unsigned int wordLen)
131 {
132 unsigned int i, carry, temp;
133
134 carry = 0;
135 for(i=0; i<wordLen; i++)
136 {
137 temp = a[i]-b[i];
138 c[i] = temp-carry;
139 if(temp > a[i] || c[i] > temp)
140 {
141 carry = 1;
142 }
143 else
144 {
145 carry = 0;
146 }
147 }
148 }
149
150 /**
151 * @brief a = a/(2^n).
152 * @param[in] a - big integer a.
153 * @param[in] aWordLen - word length of a.
154 * @param[in] n - exponent of 2^n.
155 * @return word length of a = a/(2^n).
156 * @attention: 1. make sure aWordLen is real word length of a.
157 * 2. a may be 0, then aWordLen is 0, to make sure aWordLen-1 is available, so data
158 * type of aWordLen is int32_t, not uint32_t.
159 */
div2n_u32(unsigned int a[],signed int aWordLen,unsigned int n)160 unsigned int div2n_u32(unsigned int a[], signed int aWordLen, unsigned int n)
161 {
162 signed int i;
163 unsigned int j;
164
165 if(!aWordLen)
166 return 0;
167
168 if(n < 32)
169 {
170 for(i=0; i<aWordLen-1; i++)
171 {
172 a[i] >>= n;
173 a[i] |= (a[i+1]<<(32-n));
174 }
175 a[i] >>= n;
176
177 if(!a[i])
178 return i;
179 return aWordLen;
180 }
181 else //general method
182 {
183 j = n>>5;
184 n &= 31;
185 for(i=0; i<aWordLen-(signed int)j-1; i++)
186 {
187 a[i] = a[i+j]>>n;
188 a[i] |= (a[i+j+1]<<(32-n));
189 }
190 a[i] = a[i+j]>>n;
191 memset(a+aWordLen-j, 0, j<<2);
192
193 if(!a[i])
194 return i;
195 return aWordLen - j;
196 }
197 }
198
199 /**
200 * @brief get result operand from specified addr.
201 * @param[in] baseaddr - the address.
202 * @param[in] data - the buffer data.
203 * @param[in] wordLen - the length of data.
204 * @return none.
205 */
pke_read_operand(unsigned int * baseaddr,unsigned int * data,unsigned int wordLen)206 void pke_read_operand(unsigned int *baseaddr, unsigned int *data, unsigned int wordLen)
207 {
208 unsigned int i;
209
210 if(baseaddr != data)
211 {
212 for (i = 0; i < wordLen; i++)
213 {
214 data[i] = baseaddr[i];
215 }
216 }
217 }
218
219 /**
220 * @brief load operand to specified addr.
221 * @param[in] data - the buffer data.
222 * @param[in] wordLen - the length of data.
223 * @param[out] baseaddr - the address.
224 * @return none.
225 */
pke_load_operand(unsigned int * baseaddr,unsigned int * data,unsigned int wordLen)226 void pke_load_operand(unsigned int *baseaddr, unsigned int *data, unsigned int wordLen)
227 {
228 unsigned int i;
229
230 if(baseaddr != data)
231 {
232 for (i = 0; i < wordLen; i++)
233 {
234 baseaddr[i] = data[i];
235 }
236 for (i = wordLen; i < 9; i++)
237 {
238 baseaddr[i] = 0x00000000;
239 }
240 }
241 }
242
243 /**
244 * @brief This function is to complete the calculation of the corresponding function of the PKE module.
245 * @param[in] addr - micro code.
246 * @param[in] cfg - pke exe cfg.
247 * @return 0 - normal stop.
248 * 1 - received a termination request(CTRL.STOP is high).
249 * 2 - no valid modulo inverse.
250 * 3 - point is not on the curve(CTRL.CMD:PVER).
251 * 4 - invalid microcode.
252 */
pke_opr_cal(pke_microcode_e addr,pke_exe_cfg_e cfg)253 unsigned char pke_opr_cal(pke_microcode_e addr, pke_exe_cfg_e cfg)
254 {
255 pke_set_microcode(addr);
256
257 if(0x00 != cfg)
258 pke_set_exe_cfg(cfg);
259
260 pke_clr_irq_status(FLD_PKE_STAT_DONE);
261
262 pke_opr_start();
263
264 while(!pke_get_irq_status(FLD_PKE_STAT_DONE)){} //0(in progress) 1(done))
265
266 return (pke_check_rt_code());
267 }
268
269 /**
270 * @brief load the pre-calculated mont parameters H(R^2 mod modulus) and
271 * n1( - modulus ^(-1) mod 2^w ).
272 * @param[in] H - R^2 mod modulus.
273 * @param[in] n1 - modulus ^(-1) mod 2^w, here w is 32 acutally.
274 * @param[in] wordLen - word length of modulus or H.
275 * @return: none.
276 */
pke_load_pre_calc_mont(unsigned int * H,unsigned int * n1,unsigned int wordLen)277 void pke_load_pre_calc_mont(unsigned int *H, unsigned int *n1, unsigned int wordLen)
278 {
279 pke_set_operand_width(wordLen<<5);
280
281 pke_load_operand((unsigned int *)reg_pke_a_ram(3), H, wordLen);
282 pke_load_operand((unsigned int *)reg_pke_b_ram(4), n1, 1);
283 }
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 */
pke_calc_pre_mont(const unsigned int * modulus,unsigned int wordLen)292 unsigned char pke_calc_pre_mont(const unsigned int *modulus, unsigned int wordLen)
293 {
294 unsigned char ret;
295
296 pke_set_operand_width(wordLen<<5);
297
298 pke_load_operand((unsigned int *)reg_pke_b_ram(3), (unsigned int *)modulus, wordLen); //B3 modulus
299
300 ret = pke_opr_cal(PKE_MICROCODE_CAL_PRE_MON, 0x00);
301
302 return ret;
303 }
304
305 /**
306 * @brief ECCP curve point del point, Q=2P.
307 * @param[in] curve - ECCP_CURVE struct pointer.
308 * @param[in] Px - x coordinate of point P.
309 * @param[in] Py - y coordinate of point P.
310 * @param[out] Qx - x coordinate of point Q=2P.
311 * @param[out] Qy - y coordinate of point Q=2P.
312 * @return PKE_SUCCESS(success), other(error).
313 */
pke_eccp_point_del(eccp_curve_t * curve,unsigned int * Px,unsigned int * Py,unsigned int * Qx,unsigned int * Qy)314 unsigned char pke_eccp_point_del(eccp_curve_t *curve, unsigned int *Px, unsigned int *Py,
315 unsigned int *Qx, unsigned int *Qy)
316 {
317 unsigned char ret;
318 unsigned int wordLen = (curve->eccp_p_bitLen + 31)>>5;
319
320 pke_set_operand_width(curve->eccp_p_bitLen);
321
322 pke_load_operand((unsigned int *)reg_pke_a_ram(0), Px, wordLen); //A0 Px
323 pke_load_operand((unsigned int *)reg_pke_a_ram(1), Py, wordLen); //A1 Py
324 pke_load_operand((unsigned int *)reg_pke_a_ram(5), curve->eccp_a, wordLen); //A5 a
325 pke_load_operand((unsigned int *)reg_pke_b_ram(3), curve->eccp_p, wordLen); //B3 p
326
327 if((0 != curve->eccp_p_h) && (0 != curve->eccp_p_n1))
328 {
329 pke_load_operand((unsigned int *)reg_pke_a_ram(3), curve->eccp_p_h, wordLen); //A3 p_h
330 pke_load_operand((unsigned int *)reg_pke_b_ram(4), curve->eccp_p_n1, 1); //B4 p_n1
331 }
332 else
333 {
334 pke_opr_cal(PKE_MICROCODE_CAL_PRE_MON, 0x00);
335 }
336
337
338 ret = pke_opr_cal(PKE_MICROCODE_PDBL, PKE_EXE_CFG_ALL_NON_MONT);
339 if(ret)
340 {
341 return ret;
342 }
343
344 pke_read_operand((unsigned int *)reg_pke_a_ram(0), Qx, wordLen);
345 if(Qy != 0)
346 {
347 pke_read_operand((unsigned int *)reg_pke_a_ram(1), Qy, wordLen);
348 }
349
350 return ret;
351 }
352
353 /**
354 * @brief ECCP curve point add, Q=P1+P2.
355 * @param[in] curve - eccp curve struct pointer.
356 * @param[in] P1x - x coordinate of point P1.
357 * @param[in] P1y - y coordinate of point P1.
358 * @param[in] P2x - x coordinate of point P2.
359 * @param[in] P2y - y coordinate of point P2.
360 * @param[out] Qx - x coordinate of point Q=P1+P2.
361 * @param[out] Qy - y coordinate of point Q=P1+P2.
362 * @return PKE_SUCCESS(success), other(error).
363 */
pke_eccp_point_add(eccp_curve_t * curve,unsigned int * P1x,unsigned int * P1y,unsigned int * P2x,unsigned int * P2y,unsigned int * Qx,unsigned int * Qy)364 unsigned char pke_eccp_point_add(eccp_curve_t *curve, unsigned int *P1x, unsigned int *P1y, unsigned int *P2x, unsigned int *P2y,
365 unsigned int *Qx, unsigned int *Qy)
366 {
367 unsigned char ret;
368 unsigned int wordLen = (curve->eccp_p_bitLen + 31)>>5;
369
370 pke_set_operand_width(curve->eccp_p_bitLen);
371
372 pke_load_operand((unsigned int *)reg_pke_b_ram(0), P1x, wordLen); //B0 P1x
373 pke_load_operand((unsigned int *)reg_pke_b_ram(1), P1y, wordLen); //B1 P1y
374 pke_load_operand((unsigned int *)reg_pke_a_ram(0), P2x, wordLen); //A0 P2x
375 pke_load_operand((unsigned int *)reg_pke_a_ram(1), P2y, wordLen); //A1 P2y
376 pke_load_operand((unsigned int *)reg_pke_b_ram(3), curve->eccp_p, wordLen); //B3 p
377
378 if((0 != curve->eccp_p_h) && (0 != curve->eccp_p_n1))
379 {
380 pke_load_operand((unsigned int *)reg_pke_a_ram(3), curve->eccp_p_h, wordLen); //A3 p_h
381 pke_load_operand((unsigned int *)reg_pke_b_ram(4), curve->eccp_p_n1, 1); //B4 p_n1
382 }
383 else
384 {
385 pke_opr_cal(PKE_MICROCODE_CAL_PRE_MON, 0x00);
386 }
387
388 ret = pke_opr_cal(PKE_MICROCODE_PADD, PKE_EXE_CFG_ALL_NON_MONT);
389 if(ret)
390 {
391 return ret;
392 }
393
394 pke_read_operand((unsigned int *)reg_pke_a_ram(0), Qx, wordLen);
395 pke_read_operand((unsigned int *)reg_pke_a_ram(1), Qy, wordLen);
396
397 return ret;
398 }
399
400 /**
401 * @brief check whether the input point P is on ECCP curve or not.
402 * @param[in] curve - ECCP_CURVE struct pointer.
403 * @param[in] Px - x coordinate of point P.
404 * @param[in] Py - y coordinate of point P.
405 * @return PKE_SUCCESS(success, on the curve), other(error or not on the curve).
406 */
pke_eccp_point_verify(eccp_curve_t * curve,unsigned int * Px,unsigned int * Py)407 unsigned char pke_eccp_point_verify(eccp_curve_t *curve, unsigned int *Px, unsigned int *Py)
408 {
409 signed int ret;
410 unsigned int wordLen = (curve->eccp_p_bitLen + 31)>>5;
411
412 pke_set_operand_width(curve->eccp_p_bitLen);
413
414 pke_load_operand((unsigned int *)reg_pke_b_ram(0), Px, wordLen); //B0 Px
415 pke_load_operand((unsigned int *)reg_pke_b_ram(1), Py, wordLen); //B1 Py
416 pke_load_operand((unsigned int *)reg_pke_a_ram(5), curve->eccp_a, wordLen); //A5 a
417 pke_load_operand((unsigned int *)reg_pke_a_ram(4), curve->eccp_b, wordLen); //A4 b
418 pke_load_operand((unsigned int *)reg_pke_b_ram(3), curve->eccp_p, wordLen); //B3 p
419
420 if((0 != curve->eccp_p_h) && (0 != curve->eccp_p_n1))
421 {
422 pke_load_operand((unsigned int *)reg_pke_a_ram(3), curve->eccp_p_h, wordLen); //A3 p_h
423 pke_load_operand((unsigned int *)reg_pke_b_ram(4), curve->eccp_p_n1, 1); //B4 p_n1
424 }
425 else
426 {
427 pke_opr_cal(PKE_MICROCODE_CAL_PRE_MON, 0x00);
428 }
429
430 ret = pke_opr_cal(PKE_MICROCODE_PVER, PKE_EXE_CFG_ALL_NON_MONT);
431 if(ret)
432 {
433 return ret;
434 }
435
436 return PKE_SUCCESS;
437 }
438
439 /**
440 * @brief ECCP curve point mul(random point), Q=[k]P.
441 * @param[in] curve - ECCP_CURVE struct pointer.
442 * @param[in] k - scalar.
443 * @param[in] Px - x coordinate of point P.
444 * @param[in] Py - y coordinate of point P.
445 * @param[out] Qx - x coordinate of point Q=[k]P.
446 * @param[out] Qy - y coordinate of point Q=[k]P.
447 * @return PKE_SUCCESS(success), other(error).
448 */
pke_eccp_point_mul(eccp_curve_t * curve,unsigned int * k,unsigned int * Px,unsigned int * Py,unsigned int * Qx,unsigned int * Qy)449 unsigned char pke_eccp_point_mul(eccp_curve_t *curve, unsigned int *k, unsigned int *Px, unsigned int *Py,
450 unsigned int *Qx, unsigned int *Qy)
451 {
452 unsigned char ret;
453 unsigned int wordLen = (curve->eccp_p_bitLen + 31)>>5;
454
455 pke_set_operand_width(curve->eccp_p_bitLen);
456
457 pke_load_operand((unsigned int *)reg_pke_b_ram(0), Px, wordLen); //B0 Px
458 pke_load_operand((unsigned int *)reg_pke_b_ram(1), Py, wordLen); //B1 Py
459 pke_load_operand((unsigned int *)reg_pke_a_ram(5), curve->eccp_a, wordLen); //A5 a
460 pke_load_operand((unsigned int *)reg_pke_a_ram(4), k, wordLen); //A4 k
461 pke_load_operand((unsigned int *)reg_pke_b_ram(3), curve->eccp_p, wordLen); //B3 p
462
463 if((0 != curve->eccp_p_h) && (0 != curve->eccp_p_n1))
464 {
465 pke_load_operand((unsigned int *)reg_pke_a_ram(3), curve->eccp_p_h, wordLen); //A3 p_h
466 pke_load_operand((unsigned int *)reg_pke_b_ram(4), curve->eccp_p_n1, 1); //B4 p_n1
467 }
468 else
469 {
470 pke_opr_cal(PKE_MICROCODE_CAL_PRE_MON, 0x00);
471 }
472
473
474 ret = pke_opr_cal(PKE_MICROCODE_PMUL, PKE_EXE_CFG_ALL_NON_MONT);
475 if(ret)
476 {
477 return ret;
478 }
479
480 pke_read_operand((unsigned int *)reg_pke_a_ram(0), Qx, wordLen);
481 if(Qy != 0)
482 {
483 pke_read_operand((unsigned int *)reg_pke_a_ram(1), Qy, wordLen);
484 }
485
486 return ret;
487 }
488
489 /**
490 * @brief out = a*b mod modulus.
491 * @param[in] modulus - modulus.
492 * @param[in] a - integer a.
493 * @param[in] b - integer b.
494 * @param[in] wordLen - word length of modulus, a, b.
495 * @param[out] out - out = a*b mod modulus.
496 * @return PKE_SUCCESS(success), other(error).
497 */
pke_mod_mul(const unsigned int * modulus,const unsigned int * a,const unsigned int * b,unsigned int * out,unsigned int wordLen)498 unsigned char pke_mod_mul(const unsigned int *modulus, const unsigned int *a, const unsigned int *b,
499 unsigned int *out, unsigned int wordLen)
500 {
501 unsigned char ret;
502
503 pke_set_operand_width(wordLen<<5);
504
505 pke_load_operand((unsigned int *)(reg_pke_b_ram(3)), (unsigned int *)modulus, wordLen); //B3 modulus
506 pke_load_operand((unsigned int *)(reg_pke_a_ram(0)), (unsigned int *)a, wordLen); //A0 a
507 pke_load_operand((unsigned int *)(reg_pke_b_ram(0)), (unsigned int *)b, wordLen); //B0 b
508
509 ret = pke_opr_cal(PKE_MICROCODE_MODMUL, PKE_EXE_CFG_ALL_NON_MONT);
510 if(ret)
511 {
512 return ret;
513 }
514
515 pke_read_operand((unsigned int *)(reg_pke_a_ram(0)), out, wordLen); //A0 result
516
517 return PKE_SUCCESS;
518 }
519
520 /**
521 * @brief ainv = a^(-1) mod modulus.
522 * @param[in] modulus - modulus.
523 * @param[in] a - integer a.
524 * @param[in] modWordLen - word length of modulus, ainv.
525 * @param[in] aWordLen - word length of integer a.
526 * @param[out] ainv - ainv = a^(-1) mod modulus.
527 * @return: PKE_SUCCESS(success), other(inverse not exists or error).
528 */
pke_mod_inv(const unsigned int * modulus,const unsigned int * a,unsigned int * ainv,unsigned int modWordLen,unsigned int aWordLen)529 unsigned char pke_mod_inv(const unsigned int *modulus, const unsigned int *a, unsigned int *ainv, unsigned int modWordLen,
530 unsigned int aWordLen)
531 {
532 unsigned char ret;
533
534 pke_set_operand_width(modWordLen<<5);
535
536
537 pke_load_operand((unsigned int *)(reg_pke_b_ram(3)), (unsigned int *)modulus, modWordLen); //B3 modulus
538 pke_load_operand((unsigned int *)(reg_pke_b_ram(0)), (unsigned int *)a, aWordLen); //B0 a
539
540 ret = pke_opr_cal(PKE_MICROCODE_MODINV, 0x00);
541 if(ret)
542 {
543 return ret;
544 }
545
546 pke_read_operand((unsigned int *)(reg_pke_a_ram(0)), (unsigned int *)ainv, modWordLen); //A0 ainv
547
548 return PKE_SUCCESS;
549 }
550
551 /**
552 * @brief out = (a+b) mod modulus.
553 * @param[in] modulus - modulus.
554 * @param[in] a - integer a.
555 * @param[in] b - integer b.
556 * @param[in] wordLen - word length of modulus, a, b.
557 * @param[out] out - out = a+b mod modulus.
558 * @return PKE_SUCCESS(success), other(error).
559 */
pke_mod_add(const unsigned int * modulus,const unsigned int * a,const unsigned int * b,unsigned int * out,unsigned int wordLen)560 unsigned char pke_mod_add(const unsigned int *modulus, const unsigned int *a, const unsigned int *b,
561 unsigned int *out, unsigned int wordLen)
562 {
563 unsigned char ret;
564
565 pke_set_operand_width(wordLen<<5);
566
567 pke_load_operand((unsigned int *)(reg_pke_b_ram(3)), (unsigned int *)modulus, wordLen); //B3 modulus
568 pke_load_operand((unsigned int *)(reg_pke_a_ram(0)), (unsigned int *)a, wordLen); //A0 a
569 pke_load_operand((unsigned int *)(reg_pke_b_ram(0)), (unsigned int *)b, wordLen); //B0 b
570
571 ret = pke_opr_cal(PKE_MICROCODE_MODADD, 0x00);
572 if(ret)
573 {
574 return ret;
575 }
576
577 pke_read_operand((unsigned int *)(reg_pke_a_ram(0)), out, wordLen); //A0 result
578
579 return PKE_SUCCESS;
580 }
581
582 /**
583 * @brief out = (a-b) mod modulus.
584 * @param[in] modulus - input, modulus.
585 * @param[in] a - input, integer a.
586 * @param[in] b - input, integer b.
587 * @param[in] wordLen - input, word length of modulus, a, b.
588 * @param[out] out - output, out = a-b mod modulus.
589 * @return PKE_SUCCESS(success), other(error).
590 */
pke_mod_sub(const unsigned int * modulus,const unsigned int * a,const unsigned int * b,unsigned int * out,unsigned int wordLen)591 unsigned char pke_mod_sub(const unsigned int *modulus, const unsigned int *a, const unsigned int *b,
592 unsigned int *out, unsigned int wordLen)
593 {
594 unsigned char ret;
595
596 pke_set_operand_width(wordLen<<5);
597
598 pke_load_operand((unsigned int *)(reg_pke_b_ram(3)), (unsigned int *)modulus, wordLen); //B3 modulus
599 pke_load_operand((unsigned int *)(reg_pke_a_ram(0)), (unsigned int *)a, wordLen); //A0 a
600 pke_load_operand((unsigned int *)(reg_pke_b_ram(0)), (unsigned int *)b, wordLen); //B0 b
601
602 ret = pke_opr_cal(PKE_MICROCODE_MODSUB, 0x00);
603 if(ret)
604 {
605 return ret;
606 }
607
608 pke_read_operand((unsigned int *)(reg_pke_a_ram(0)), out, wordLen); //A0 result
609
610 return PKE_SUCCESS;
611 }
612
613 /**
614 * @brief c25519 point mul(random point), Q=[k]P.
615 * @param[in] curve - c25519 curve struct pointer.
616 * @param[in] k - scalar.
617 * @param[in] Pu - u coordinate of point P.
618 * @param[out] Qu - u coordinate of point Q=[k]P.
619 * @return PKE_SUCCESS(success), other(error).
620 */
pke_x25519_point_mul(mont_curve_t * curve,unsigned int * k,unsigned int * Pu,unsigned int * Qu)621 unsigned char pke_x25519_point_mul(mont_curve_t *curve, unsigned int *k, unsigned int *Pu, unsigned int *Qu)
622 {
623 unsigned char ret;
624 unsigned int wordLen = (curve->mont_p_bitLen + 31)>>5;
625
626 pke_set_operand_width(curve->mont_p_bitLen);
627
628 pke_load_operand((unsigned int *)reg_pke_a_ram(0), Pu, wordLen); //A0 Pu
629 pke_load_operand((unsigned int *)reg_pke_b_ram(0), curve->mont_a24, wordLen); //B0 a24
630 pke_load_operand((unsigned int *)reg_pke_a_ram(4), k, wordLen); //A4 k
631 pke_load_operand((unsigned int *)reg_pke_b_ram(3), curve->mont_p, wordLen); //B3 p
632
633 if((NULL != curve->mont_p_h) && (NULL != curve->mont_p_n1))
634 {
635 pke_load_operand((unsigned int *)reg_pke_a_ram(3), curve->mont_p_h, wordLen); //A3 p_h
636 pke_load_operand((unsigned int *)reg_pke_b_ram(4), curve->mont_p_n1, 1); //B4 p_n1
637 }
638 else
639 {
640 pke_opr_cal(PKE_MICROCODE_CAL_PRE_MON, 0x00);
641 }
642
643
644 ret = pke_opr_cal(PKE_MICROCODE_C25519_PMUL, PKE_EXE_CFG_ALL_NON_MONT);
645 if(ret)
646 {
647 return ret;
648 }
649
650 pke_read_operand((unsigned int *)reg_pke_a_ram(1), Qu, wordLen);
651
652 return ret;
653 }
654
655 /**
656 * @brief edwards25519 curve point mul(random point), Q=[k]P.
657 * @param[in] curve - edwards25519 curve struct pointer.
658 * @param[in] k - scalar.
659 * @param[in] Px - x coordinate of point P.
660 * @param[in] Py - y coordinate of point P.
661 * @param[out] Qx - x coordinate of point Q=[k]P.
662 * @param[out] Qy - y coordinate of point Q=[k]P.
663 * @return PKE_SUCCESS(success), other(error).
664 */
pke_ed25519_point_mul(edward_curve_t * curve,unsigned int * k,unsigned int * Px,unsigned int * Py,unsigned int * Qx,unsigned int * Qy)665 unsigned char pke_ed25519_point_mul(edward_curve_t *curve, unsigned int *k, unsigned int *Px, unsigned int *Py,
666 unsigned int *Qx, unsigned int *Qy)
667 {
668 unsigned char ret;
669 unsigned int wordLen = (curve->edward_p_bitLen + 31)>>5;
670
671 pke_set_operand_width(curve->edward_p_bitLen);
672
673 pke_load_operand((unsigned int *)reg_pke_a_ram(1), Px, wordLen); //A1 Px
674 pke_load_operand((unsigned int *)reg_pke_a_ram(2), Py, wordLen); //A2 Py
675 pke_load_operand((unsigned int *)reg_pke_b_ram(0), curve->edward_d, wordLen); //B0 d
676 pke_load_operand((unsigned int *)reg_pke_a_ram(0), k, wordLen); //A0 k
677 pke_load_operand((unsigned int *)reg_pke_b_ram(3), curve->edward_p, wordLen); //B3 p
678
679 if((0 != curve->edward_p_h) && (0 != curve->edward_p_n1))
680 {
681 pke_load_operand((unsigned int *)reg_pke_a_ram(3), curve->edward_p_h, wordLen); //A3 p_h
682 pke_load_operand((unsigned int *)reg_pke_b_ram(4), curve->edward_p_n1, 1); //B4 p_n1
683 }
684 else
685 {
686 pke_opr_cal(PKE_MICROCODE_CAL_PRE_MON, 0x00);
687 }
688
689
690 ret = pke_opr_cal(PKE_MICROCODE_Ed25519_PMUL, PKE_EXE_CFG_ALL_NON_MONT);
691 if(ret)
692 {
693 return ret;
694 }
695
696 pke_read_operand((unsigned int *)reg_pke_a_ram(1), Qx, wordLen);
697 if(Qy != 0)
698 {
699 pke_read_operand((unsigned int *)reg_pke_a_ram(2), Qy, wordLen);
700 }
701
702 return ret;
703 }
704
705 /**
706 * @brief edwards25519 point add, Q=P1+P2.
707 * @param[in] curve - edwards25519 curve struct pointer.
708 * @param[in] P1x - x coordinate of point P1.
709 * @param[in] P1y - y coordinate of point P1.
710 * @param[in] P2x - x coordinate of point P2.
711 * @param[in] P2y - y coordinate of point P2.
712 * @param[out] Qx - x coordinate of point Qx=P1x+P2x.
713 * @param[out] Qy - y coordinate of point Qy=P1y+P2y.
714 * @return PKE_SUCCESS(success), other(error).
715 */
pke_ed25519_point_add(edward_curve_t * curve,unsigned int * P1x,unsigned int * P1y,unsigned int * P2x,unsigned int * P2y,unsigned int * Qx,unsigned int * Qy)716 unsigned char pke_ed25519_point_add(edward_curve_t *curve, unsigned int *P1x, unsigned int *P1y, unsigned int *P2x, unsigned int *P2y,
717 unsigned int *Qx, unsigned int *Qy)
718 {
719 unsigned char ret;
720 unsigned int wordLen = (curve->edward_p_bitLen + 31)>>5;
721
722 pke_set_operand_width(curve->edward_p_bitLen);
723
724 pke_load_operand((unsigned int *)reg_pke_a_ram(1), P1x, wordLen); //A1 P1x
725 pke_load_operand((unsigned int *)reg_pke_a_ram(2), P1y, wordLen); //A2 P1y
726 pke_load_operand((unsigned int *)reg_pke_b_ram(1), P2x, wordLen); //B1 P2x
727 pke_load_operand((unsigned int *)reg_pke_b_ram(2), P2y, wordLen); //B2 P2y
728 pke_load_operand((unsigned int *)reg_pke_b_ram(0), curve->edward_d, wordLen); //B0 d
729 pke_load_operand((unsigned int *)reg_pke_b_ram(3), curve->edward_p, wordLen); //B3 p
730
731 if((0 != curve->edward_p_h) && (0 != curve->edward_p_n1))
732 {
733 pke_load_operand((unsigned int *)reg_pke_a_ram(3), curve->edward_p_h, wordLen); //A3 p_h
734 pke_load_operand((unsigned int *)reg_pke_b_ram(4), curve->edward_p_n1, 1); //B4 p_n1
735 }
736 else
737 {
738 pke_opr_cal(PKE_MICROCODE_CAL_PRE_MON, 0x00);
739 }
740
741 ret = pke_opr_cal(PKE_MICROCODE_Ed25519_PADD, PKE_EXE_CFG_ALL_NON_MONT);
742 if(ret)
743 {
744 return ret;
745 }
746
747 pke_read_operand((unsigned int *)reg_pke_a_ram(1), Qx, wordLen);
748 pke_read_operand((unsigned int *)reg_pke_a_ram(2), Qy, wordLen);
749
750 return ret;
751 }
752
753 /**
754 * @brief c = a mod b.
755 * @param[in] a - integer a.
756 * @param[in] b - integer b.
757 * @param[in] aWordLen - word length of a.
758 * @param[in] bWordLen - word length of b.
759 * @param[in] b_h - parameter b_h.
760 * @param[in] b_n1 - parameter b_n1.
761 * @param[out] c - c = a mod b.
762 * @return PKE_SUCCESS(success), other(error).
763 */
pke_mod(unsigned int * a,unsigned int aWordLen,unsigned int * b,unsigned int * b_h,unsigned int * b_n1,unsigned int bWordLen,unsigned int * c)764 unsigned char pke_mod(unsigned int *a, unsigned int aWordLen, unsigned int *b, unsigned int *b_h, unsigned int *b_n1,
765 unsigned int bWordLen, unsigned int *c)
766 {
767 signed int ret;
768 unsigned int bitLen, tmpLen;
769 unsigned int *a_high, *a_low, *p;
770
771 ret = big_integer_compare(a, aWordLen, b, bWordLen);
772 if(ret < 0)
773 {
774 aWordLen = valid_words_get(a, aWordLen);
775 memcpy(c, a, aWordLen<<2);
776 memset(c+aWordLen, 0, (bWordLen-aWordLen)<<2);
777
778 return PKE_SUCCESS;
779 }
780 else if(0 == ret)
781 {
782 memset(c, 0, bWordLen<<2);
783
784 return PKE_SUCCESS;
785 }
786
787 bitLen = valid_bits_get(b, bWordLen) & 0x1F;
788 pke_set_operand_width(bWordLen<<5);
789 p = (unsigned int *)reg_pke_a_ram(1);
790
791 //get a_high mod b
792 a_high = c;
793 if(bitLen)
794 {
795 tmpLen = aWordLen-bWordLen+1;
796 memcpy(p, a+bWordLen-1, tmpLen<<2);
797 div2n_u32(p, tmpLen, bitLen);
798 if(tmpLen < bWordLen)
799 {
800 memset(p+tmpLen, 0, (bWordLen-tmpLen)<<2);
801 }
802
803 if(big_integer_compare(p, bWordLen, b, bWordLen) >= 0)
804 {
805 sub_u32(p, b, a_high, bWordLen);
806 }
807 else
808 {
809 memcpy(a_high, p, bWordLen<<2);
810 }
811 }
812 else
813 {
814 tmpLen = aWordLen - bWordLen;
815 if(big_integer_compare(a+bWordLen, tmpLen, b, bWordLen) > 0)
816 {
817 sub_u32(a+bWordLen, b, a_high, bWordLen);
818 }
819 else
820 {
821 memcpy(a_high, a+bWordLen, tmpLen<<2);
822 memset(a_high+tmpLen, 0, (bWordLen-tmpLen)<<2);
823 }
824 }
825
826 if(0 == b_h || 0 == b_n1)
827 {
828 ret = pke_calc_pre_mont(b, bWordLen);
829 if(PKE_SUCCESS != ret)
830 {
831 return ret;
832 }
833 }
834 else
835 {
836 pke_load_pre_calc_mont(b_h, b_n1, bWordLen);
837 }
838
839 //get 1000...000 mod b
840 memset(p, 0, bWordLen<<2);
841 if(bitLen)
842 {
843 p[bWordLen-1] = 1<<(bitLen);
844 }
845 sub_u32(p, b, (unsigned int *)reg_pke_b_ram(1), bWordLen);
846
847
848 //get a_high * 1000..000 mod b
849 pke_set_exe_cfg(PKE_EXE_CFG_ALL_NON_MONT);
850 pke_calc_pre_mont(b, bWordLen);
851 ret = pke_mod_mul(b, (unsigned int *)reg_pke_b_ram(1), a_high, (unsigned int *)reg_pke_b_ram(1), bWordLen);
852 if(PKE_SUCCESS != ret)
853 {
854 return ret;
855 }
856
857 //get a_low mod b
858 if(bitLen)
859 {
860 a_low = c;
861 memcpy(p, a, bWordLen<<2);
862 p[bWordLen-1] &= ((1<<(bitLen))-1);
863 if(big_integer_compare(p, bWordLen, b, bWordLen) >= 0)
864 {
865 sub_u32(p, b, a_low, bWordLen);
866 }
867 else
868 {
869 memcpy(a_low, p, bWordLen<<2);
870 }
871 }
872 else
873 {
874 if(big_integer_compare(a, bWordLen, b, bWordLen) >= 0)
875 {
876 a_low = c;
877 sub_u32(a, b, a_low, bWordLen);
878 }
879 else
880 {
881 a_low = a;
882 }
883 }
884
885 return pke_mod_add(b, a_low, (unsigned int *)reg_pke_b_ram(1), c, bWordLen);
886 }
887
888
889
890
891
892