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