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