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