• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * This file is part of the openHiTLS project.
3  *
4  * openHiTLS is licensed under the Mulan PSL v2.
5  * You can use this software according to the terms and conditions of the Mulan PSL v2.
6  * You may obtain a copy of Mulan PSL v2 at:
7  *
8  *     http://license.coscl.org.cn/MulanPSL2
9  *
10  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11  * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12  * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13  * See the Mulan PSL v2 for more details.
14  */
15 
16 #include "hitls_build.h"
17 #ifdef HITLS_CRYPTO_BN
18 
19 #include "securec.h"
20 #include "bsl_sal.h"
21 #include "bsl_err_internal.h"
22 #include "crypt_errno.h"
23 #include "crypt_utils.h"
24 #include "bn_basic.h"
25 #include "bn_bincal.h"
26 #include "bn_ucal.h"
27 #include "bn_optimizer.h"
28 
29 #define SMALL_CONQUER_SIZE 8
30 
BN_Cmp(const BN_BigNum * a,const BN_BigNum * b)31 int32_t BN_Cmp(const BN_BigNum *a, const BN_BigNum *b)
32 {
33     if (a == NULL || b == NULL) {
34         if (a != NULL) {
35             return -1;
36         }
37         if (b != NULL) {
38             return 1;
39         }
40         return 0;
41     }
42     if (a->sign != b->sign) {
43         return a->sign == false ? 1 : -1;
44     }
45     if (a->sign == true) {
46         return BinCmp(b->data, b->size, a->data, a->size);
47     }
48     return BinCmp(a->data, a->size, b->data, b->size);
49 }
50 
BN_Add(BN_BigNum * r,const BN_BigNum * a,const BN_BigNum * b)51 int32_t BN_Add(BN_BigNum *r, const BN_BigNum *a, const BN_BigNum *b)
52 {
53     if (r == NULL || a == NULL || b == NULL) {
54         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
55         return CRYPT_NULL_INPUT;
56     }
57 
58     if (a->sign == b->sign) {
59         r->sign = a->sign;
60         return UAdd(r, a, b);
61     }
62     // compare absolute value
63     int32_t res = BinCmp(a->data, a->size, b->data, b->size);
64     if (res > 0) {
65         r->sign = a->sign;
66         return USub(r, a, b);
67     } else if (res < 0) {
68         r->sign = b->sign;
69         return USub(r, b, a);
70     }
71     return BN_Zeroize(r);
72 }
73 
BN_AddLimb(BN_BigNum * r,const BN_BigNum * a,BN_UINT w)74 int32_t BN_AddLimb(BN_BigNum *r, const BN_BigNum *a, BN_UINT w)
75 {
76     if (r == NULL || a == NULL) {
77         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
78         return CRYPT_NULL_INPUT;
79     }
80     if (a->size == 0) {
81         return BN_SetLimb(r, w);
82     }
83     int32_t ret;
84     if (a->sign == false) { // a is positive
85         ret = BnExtend(r, a->size + 1);
86         if (ret != CRYPT_SUCCESS) {
87             return ret;
88         }
89         BN_UINT carry = BinInc(r->data, a->data, a->size, w);
90         if (carry != 0) {
91             uint32_t size = a->size;
92             r->size = size + 1;
93             r->data[size] = carry;
94         } else {
95             r->size = a->size;
96         }
97         r->sign = false;
98         return CRYPT_SUCCESS;
99     }
100     ret = BnExtend(r, a->size);
101     if (ret != CRYPT_SUCCESS) {
102         return ret;
103     }
104     if (a->size == 1) {
105         if (a->data[0] > w) {
106             r->sign = true;
107             r->data[0] = a->data[0] - w;
108             r->size = 1;
109         } else if (a->data[0] == w) {
110             r->sign = false;
111             r->data[0] = 0;
112             r->size = 0;
113         } else {
114             r->sign = false;
115             r->data[0] = w - a->data[0];
116             r->size = 1;
117         }
118         return CRYPT_SUCCESS;
119     }
120     r->sign = true;
121     UDec(r, a, w);
122     return CRYPT_SUCCESS;
123 }
124 
BN_Sub(BN_BigNum * r,const BN_BigNum * a,const BN_BigNum * b)125 int32_t BN_Sub(BN_BigNum *r, const BN_BigNum *a, const BN_BigNum *b)
126 {
127     if (r == NULL || a == NULL || b == NULL) {
128         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
129         return CRYPT_NULL_INPUT;
130     }
131     if (a->sign != b->sign) {
132         r->sign = a->sign;
133         return UAdd(r, a, b);
134     }
135     // compare absolute value
136     int32_t res = BinCmp(a->data, a->size, b->data, b->size);
137     if (res == 0) {
138         return BN_Zeroize(r);
139     } else if (res > 0) {
140         r->sign = a->sign;
141         return USub(r, a, b);
142     }
143     r->sign = !b->sign;
144     return USub(r, b, a);
145 }
146 
BN_SubLimb(BN_BigNum * r,const BN_BigNum * a,BN_UINT w)147 int32_t BN_SubLimb(BN_BigNum *r, const BN_BigNum *a, BN_UINT w)
148 {
149     if (r == NULL || a == NULL) {
150         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
151         return CRYPT_NULL_INPUT;
152     }
153     int32_t ret;
154     if (a->size == 0) {
155         if (BN_SetLimb(r, w) != CRYPT_SUCCESS) {
156             BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
157             return CRYPT_MEM_ALLOC_FAIL;
158         }
159         r->sign = (w == 0) ? false : true;
160         return CRYPT_SUCCESS;
161     }
162     if (a->sign == true) {
163         ret = BnExtend(r, a->size + 1);
164         if (ret != CRYPT_SUCCESS) {
165             return ret;
166         }
167         BN_UINT carry = BinInc(r->data, a->data, a->size, w);
168         if (carry != 0) {
169             uint32_t size = a->size;
170             r->data[size] = carry;
171             r->size = size + 1;
172         } else {
173             r->size = a->size;
174         }
175         r->sign = true;
176         return CRYPT_SUCCESS;
177     }
178     ret = BnExtend(r, a->size);
179     if (ret != CRYPT_SUCCESS) {
180         return ret;
181     }
182     if (a->size == 1) {
183         if (a->data[0] >= w) {
184             r->data[0] = a->data[0] - w;
185             r->size = BinFixSize(r->data, 1);
186         } else {
187             r->sign = true;
188             r->data[0] = w - a->data[0];
189             r->size = 1;
190         }
191         return CRYPT_SUCCESS;
192     }
193     r->sign = false;
194     UDec(r, a, w);
195     return CRYPT_SUCCESS;
196 }
197 
198 #ifdef HITLS_CRYPTO_BN_COMBA
BnMulConquer(BN_BigNum * t,const BN_BigNum * a,const BN_BigNum * b,BN_Optimizer * opt)199 static int32_t BnMulConquer(BN_BigNum *t, const BN_BigNum *a, const BN_BigNum *b, BN_Optimizer *opt)
200 {
201     if (a->size <= SMALL_CONQUER_SIZE && a->size % 2 == 0) { // 2 is to check if a->size is even
202         MulConquer(t->data, a->data, b->data, a->size, NULL, false);
203     } else {
204         BN_BigNum *tmpBn = OptimizerGetBn(opt, SpaceSize(a->size));
205         if (tmpBn == NULL) {
206             BSL_ERR_PUSH_ERROR(CRYPT_BN_OPTIMIZER_GET_FAIL);
207             return CRYPT_BN_OPTIMIZER_GET_FAIL;
208         }
209         MulConquer(t->data, a->data, b->data, a->size, tmpBn->data, false);
210     }
211     t->size = a->size + b->size;
212     return CRYPT_SUCCESS;
213 }
214 #endif
215 
BN_Mul(BN_BigNum * r,const BN_BigNum * a,const BN_BigNum * b,BN_Optimizer * opt)216 int32_t BN_Mul(BN_BigNum *r, const BN_BigNum *a, const BN_BigNum *b, BN_Optimizer *opt)
217 {
218     if (r == NULL || a == NULL || b == NULL || opt == NULL) {
219         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
220         return CRYPT_NULL_INPUT;
221     }
222 
223     if (a->size == 0 || b->size == 0) {
224         return BN_Zeroize(r);
225     }
226     uint32_t size = a->size + b->size;
227     int32_t ret = BnExtend(r, size);
228     if (ret != CRYPT_SUCCESS) {
229         return ret;
230     }
231     ret = OptimizerStart(opt); // using the Optimizer
232     if (ret != CRYPT_SUCCESS) {
233         BSL_ERR_PUSH_ERROR(ret);
234         return ret;
235     }
236     BN_BigNum *t = NULL;
237     if (r == a || r == b) {
238         t = OptimizerGetBn(opt, r->room); // apply for a BN object
239         if (t == NULL) {
240             OptimizerEnd(opt); // release occupation from the optimizer
241             BSL_ERR_PUSH_ERROR(CRYPT_BN_OPTIMIZER_GET_FAIL);
242             return CRYPT_BN_OPTIMIZER_GET_FAIL;
243         }
244     } else {
245         t = r;
246     }
247 
248     t->sign = a->sign != b->sign;
249 #ifdef HITLS_CRYPTO_BN_COMBA
250     if (a->size == b->size) {
251         ret = BnMulConquer(t, a, b, opt);
252         if (ret != CRYPT_SUCCESS) {
253             OptimizerEnd(opt);
254             return ret;
255         }
256     } else {
257 #endif
258         t->size = BinMul(t->data, t->room, a->data, a->size, b->data, b->size);
259 #ifdef HITLS_CRYPTO_BN_COMBA
260     }
261 #endif
262 
263     if (r != t) {
264         ret = BN_Copy(r, t);
265         if (ret != CRYPT_SUCCESS) {
266             OptimizerEnd(opt); // release occupation from the optimizer
267             BSL_ERR_PUSH_ERROR(ret);
268             return ret;
269         }
270     }
271     r->size = BinFixSize(r->data, size);
272     OptimizerEnd(opt);
273     return CRYPT_SUCCESS;
274 }
275 
BN_MulLimb(BN_BigNum * r,const BN_BigNum * a,const BN_UINT w)276 int32_t BN_MulLimb(BN_BigNum *r, const BN_BigNum *a, const BN_UINT w)
277 {
278     if (r == NULL || a == NULL) {
279         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
280         return CRYPT_NULL_INPUT;
281     }
282 
283     if (BN_Bits(a) == 0 || w == 0) {
284         return BN_Zeroize(r);
285     }
286 
287     int32_t ret = BnExtend(r, a->size + 1);
288     if (ret != CRYPT_SUCCESS) {
289         return ret;
290     }
291     BN_UINT carry = 0;
292     uint32_t loc;
293     for (loc = 0; loc < a->size; loc++) {
294         BN_UINT rh;
295         BN_UINT rl;
296         MUL_AB(rh, rl, a->data[loc], w);
297         ADD_AB(carry, r->data[loc], rl, carry);
298         carry += rh;
299     }
300     if (carry != 0) {
301         r->data[loc++] = carry; // Input parameter checking ensures that no out-of-bounds
302     }
303     r->sign = a->sign;
304     r->size = loc;
305     return CRYPT_SUCCESS;
306 }
307 
BN_Sqr(BN_BigNum * r,const BN_BigNum * a,BN_Optimizer * opt)308 int32_t BN_Sqr(BN_BigNum *r, const BN_BigNum *a, BN_Optimizer *opt)
309 {
310     if (r == NULL || a == NULL || opt == NULL) {
311         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
312         return CRYPT_NULL_INPUT;
313     }
314     if (a->size == 0) {
315         return BN_Zeroize(r);
316     }
317     int32_t ret = BnExtend(r, a->size * 2); // The maximum bit required for mul is 2x that of a.
318     if (ret != CRYPT_SUCCESS) {
319         return ret;
320     }
321     ret = OptimizerStart(opt); // using the Optimizer
322     if (ret != CRYPT_SUCCESS) {
323         BSL_ERR_PUSH_ERROR(ret);
324         return ret;
325     }
326 
327 #ifdef HITLS_CRYPTO_BN_COMBA
328     if (a->size <= SMALL_CONQUER_SIZE && a->size % 2 == 0) { // 2 is to check if a->size is even.
329         SqrConquer(r->data, a->data, a->size, NULL, false);
330     } else {
331         BN_BigNum *tmpBn = OptimizerGetBn(opt, SpaceSize(a->size));
332         if (tmpBn == NULL) {
333             OptimizerEnd(opt);
334             BSL_ERR_PUSH_ERROR(CRYPT_BN_OPTIMIZER_GET_FAIL);
335             return CRYPT_BN_OPTIMIZER_GET_FAIL;
336         }
337         SqrConquer(r->data, a->data, a->size, tmpBn->data, false);
338     }
339 #else
340     BinSqr(r->data, a->size << 1, a->data, a->size);
341 #endif
342 
343     r->size = BinFixSize(r->data, a->size * 2); // The r->data size is a->size * 2.
344     r->sign = false; // The square must be positive.
345     OptimizerEnd(opt);
346     return CRYPT_SUCCESS;
347 }
348 
DivInputCheck(const BN_BigNum * q,const BN_BigNum * r,const BN_BigNum * x,const BN_BigNum * y,const BN_Optimizer * opt)349 int32_t DivInputCheck(const BN_BigNum *q, const BN_BigNum *r, const BN_BigNum *x,
350     const BN_BigNum *y, const BN_Optimizer *opt)
351 {
352     if (x == NULL || y == NULL || opt == NULL) {
353         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
354         return CRYPT_NULL_INPUT;
355     }
356     if (q == r) {
357         BSL_ERR_PUSH_ERROR(CRYPT_INVALID_ARG);
358         return CRYPT_INVALID_ARG;
359     }
360     // The divisor cannot be 0.
361     if (y->size == 0) {
362         return CRYPT_BN_ERR_DIVISOR_ZERO;
363     }
364     return CRYPT_SUCCESS;
365 }
366 
367 // If x <= y, perform special processing.
DivSimple(BN_BigNum * q,BN_BigNum * r,const BN_BigNum * x,const BN_BigNum * y,int32_t flag)368 int32_t DivSimple(BN_BigNum *q, BN_BigNum *r, const BN_BigNum *x, const BN_BigNum *y, int32_t flag)
369 {
370     int32_t ret;
371     if (flag < 0) {
372         if (r != NULL) {
373             ret = BN_Copy(r, x);
374             if (ret != CRYPT_SUCCESS) {
375                 BSL_ERR_PUSH_ERROR(ret);
376                 return ret;
377             }
378         }
379         if (q != NULL) {
380             return BN_Zeroize(q);
381         }
382     } else {
383         if (q != NULL) {
384             bool sign = (x->sign != y->sign);
385             ret = BN_SetLimb(q, 1);
386             if (ret != CRYPT_SUCCESS) {
387                 BSL_ERR_PUSH_ERROR(ret);
388                 return ret;
389             }
390             q->sign = sign;
391         }
392         if (r != NULL) {
393             return BN_Zeroize(r);
394         }
395     }
396     return CRYPT_SUCCESS;
397 }
398 
BN_Div(BN_BigNum * q,BN_BigNum * r,const BN_BigNum * x,const BN_BigNum * y,BN_Optimizer * opt)399 int32_t BN_Div(BN_BigNum *q, BN_BigNum *r, const BN_BigNum *x, const BN_BigNum *y, BN_Optimizer *opt)
400 {
401     int32_t ret = DivInputCheck(q, r, x, y, opt);
402     if (ret != CRYPT_SUCCESS) {
403         return ret;
404     }
405     ret = BinCmp(x->data, x->size, y->data, y->size);
406     if (ret <= 0) { // simple processing when dividend <= divisor
407         return DivSimple(q, r, x, y, ret);
408     }
409 
410     ret = OptimizerStart(opt); // using the Optimizer
411     if (ret != CRYPT_SUCCESS) {
412         BSL_ERR_PUSH_ERROR(ret);
413         return ret;
414     }
415     /* Apply for temporary space for the q and r of the BN. */
416     BN_BigNum *qTmp = OptimizerGetBn(opt, x->size + 2);  // BinDiv:x->room >= xSize + 2
417     BN_BigNum *rTmp = OptimizerGetBn(opt, x->size + 2);  // BinDiv:x->room >= xSize + 2
418     BN_BigNum *yTmp = OptimizerGetBn(opt, y->size);
419     if (qTmp == NULL || rTmp == NULL || yTmp == NULL) {
420         BSL_ERR_PUSH_ERROR(CRYPT_BN_OPTIMIZER_GET_FAIL);
421         ret = CRYPT_BN_OPTIMIZER_GET_FAIL;
422         goto err;
423     }
424 
425     (void)memcpy_s(yTmp->data, y->size * sizeof(BN_UINT), y->data, y->size * sizeof(BN_UINT));
426     (void)memcpy_s(rTmp->data, x->size * sizeof(BN_UINT), x->data, x->size * sizeof(BN_UINT));
427     rTmp->sign = x->sign;
428 
429     rTmp->size = BinDiv(qTmp->data, &(qTmp->size), rTmp->data, x->size, yTmp->data, y->size);
430     if (q != NULL) {
431         ret = BnExtend(q, qTmp->size);
432         if (ret != CRYPT_SUCCESS) {
433             goto err;
434         }
435         q->sign = (x->sign != y->sign);
436         (void)memcpy_s(q->data, qTmp->size * sizeof(BN_UINT), qTmp->data, qTmp->size * sizeof(BN_UINT));
437         q->size = qTmp->size;
438     }
439     if (r != NULL) {
440         ret = BnExtend(r, rTmp->size);
441         if (ret != CRYPT_SUCCESS) {
442             goto err;
443         }
444         r->sign = (rTmp->size == 0) ? false : rTmp->sign; // The symbol can only be positive when the value is 0.
445         (void)memcpy_s(r->data, rTmp->size * sizeof(BN_UINT), rTmp->data, rTmp->size * sizeof(BN_UINT));
446         r->size = rTmp->size;
447     }
448 err:
449     OptimizerEnd(opt); // release occupation from the optimizer
450     return ret;
451 }
452 
DivLimbInputCheck(const BN_BigNum * q,const BN_UINT * r,const BN_BigNum * x,const BN_UINT y)453 int32_t DivLimbInputCheck(const BN_BigNum *q, const BN_UINT *r, const BN_BigNum *x, const BN_UINT y)
454 {
455     if (x == NULL || (q == NULL && r == NULL)) { // q and r cannot be NULL at the same time
456         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
457         return CRYPT_NULL_INPUT;
458     }
459 
460     if (y == 0) {
461         BSL_ERR_PUSH_ERROR(CRYPT_BN_ERR_DIVISOR_ZERO);
462         return CRYPT_BN_ERR_DIVISOR_ZERO;
463     }
464     return CRYPT_SUCCESS;
465 }
466 
BN_DivLimb(BN_BigNum * q,BN_UINT * r,const BN_BigNum * x,const BN_UINT y)467 int32_t BN_DivLimb(BN_BigNum *q, BN_UINT *r, const BN_BigNum *x, const BN_UINT y)
468 {
469     int32_t ret = DivLimbInputCheck(q, r, x, y);
470     if (ret != CRYPT_SUCCESS) {
471         return ret;
472     }
473 
474     // Apply for a copy of object x.
475     BN_BigNum *xTmp = BN_Dup(x);
476     if (xTmp == NULL) {
477         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
478         return CRYPT_MEM_ALLOC_FAIL;
479     }
480 
481     BN_UINT rem = 0;
482     BN_UINT yTmp = y;
483     uint32_t shifts;
484     if (x->size == 0) {
485         goto end;
486     }
487 
488     shifts = GetZeroBitsUint(yTmp);
489     if (shifts != 0) {
490         yTmp <<= shifts; // Ensure that the most significant bit of the divisor is 1.
491         ret = BN_Lshift(xTmp, xTmp, shifts);
492         if (ret != CRYPT_SUCCESS) {
493             BSL_ERR_PUSH_ERROR(ret);
494             BN_Destroy(xTmp);
495             return ret;
496         }
497     }
498 
499     for (int32_t i = (int32_t)(xTmp->size - 1); i >= 0; i--) {
500         BN_UINT quo;
501         DIV_ND(quo, rem, rem, xTmp->data[i], yTmp);
502         xTmp->data[i] = quo;
503     }
504 
505     xTmp->size = BinFixSize(xTmp->data, xTmp->size);
506     if (xTmp->size == 0) {
507         xTmp->sign = 0;
508     }
509     rem >>= shifts;
510 
511 end:
512     if (q != NULL) {
513         ret = BN_Copy(q, xTmp);
514         if (ret != CRYPT_SUCCESS) {
515             BN_Destroy(xTmp);
516             BSL_ERR_PUSH_ERROR(ret);
517             return ret;
518         }
519     }
520     if (r != NULL) {
521         *r = rem;
522     }
523     BN_Destroy(xTmp);
524     return ret;
525 }
526 
BN_Mod(BN_BigNum * r,const BN_BigNum * a,const BN_BigNum * m,BN_Optimizer * opt)527 int32_t BN_Mod(BN_BigNum *r, const BN_BigNum *a, const BN_BigNum *m, BN_Optimizer *opt)
528 {
529     // check input parameters
530     if (r == NULL || a == NULL || m == NULL || opt == NULL) {
531         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
532         return CRYPT_NULL_INPUT;
533     }
534     if (m->size == 0) {
535         BSL_ERR_PUSH_ERROR(CRYPT_BN_ERR_DIVISOR_ZERO);
536         return CRYPT_BN_ERR_DIVISOR_ZERO;
537     }
538     int32_t ret = BnExtend(r, m->size);
539     if (ret != CRYPT_SUCCESS) {
540         return ret;
541     }
542     ret = OptimizerStart(opt);
543     if (ret != CRYPT_SUCCESS) {
544         BSL_ERR_PUSH_ERROR(ret);
545         return ret;
546     }
547     BN_BigNum *t = OptimizerGetBn(opt, m->size);
548     if (t == NULL) {
549         OptimizerEnd(opt);
550         BSL_ERR_PUSH_ERROR(CRYPT_BN_OPTIMIZER_GET_FAIL);
551         return CRYPT_BN_OPTIMIZER_GET_FAIL;
552     }
553     ret = BN_Div(NULL, t, a, m, opt);
554     if (ret != CRYPT_SUCCESS) {
555         BSL_ERR_PUSH_ERROR(ret);
556         OptimizerEnd(opt);
557         return ret;
558     }
559     // t is a positive number
560     if (t->sign == false) {
561         ret = BN_Copy(r, t);
562         OptimizerEnd(opt);
563         return ret;
564     }
565     // When t is a negative number, the modulo operation result must be positive.
566     if (m->sign == true) { // m is a negative number
567         ret = BN_Sub(r, t, m);
568     } else { // m is a positive number
569         ret = BN_Add(r, t, m);
570     }
571     if (ret != CRYPT_SUCCESS) {
572         BSL_ERR_PUSH_ERROR(ret);
573     }
574     OptimizerEnd(opt);
575     return ret;
576 }
577 
BN_ModLimb(BN_UINT * r,const BN_BigNum * a,const BN_UINT m)578 int32_t BN_ModLimb(BN_UINT *r, const BN_BigNum *a, const BN_UINT m)
579 {
580     if (r == NULL || a == NULL) {
581         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
582         return CRYPT_NULL_INPUT;
583     }
584     if (m == 0) {
585         BSL_ERR_PUSH_ERROR(CRYPT_BN_ERR_DIVISOR_ZERO);
586         return CRYPT_BN_ERR_DIVISOR_ZERO;
587     }
588 
589     if (a->size == 0) {
590         *r = 0;
591         return CRYPT_SUCCESS;
592     }
593     int32_t ret = BN_DivLimb(NULL, r, a, m);
594     if (ret != CRYPT_SUCCESS) {
595         BSL_ERR_PUSH_ERROR(ret);
596         return ret;
597     }
598     if (a->sign) {
599         *r = m - *r;
600     }
601     return ret;
602 }
603 
604 // Check the input parameters of basic operations such as modulo addition, subtraction, and multiplication.
ModBaseInputCheck(BN_BigNum * r,const BN_BigNum * a,const BN_BigNum * b,const BN_BigNum * mod,const BN_Optimizer * opt)605 int32_t ModBaseInputCheck(BN_BigNum *r, const BN_BigNum *a, const BN_BigNum *b,
606     const BN_BigNum *mod, const BN_Optimizer *opt)
607 {
608     if (r == NULL || a == NULL || b == NULL || mod == NULL || opt == NULL) {
609         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
610         return CRYPT_NULL_INPUT;
611     }
612     int32_t ret = BnExtend(r, mod->size);
613     if (ret != CRYPT_SUCCESS) {
614         return ret;
615     }
616     // mod cannot be 0
617     if (BN_IsZero(mod)) {
618         BSL_ERR_PUSH_ERROR(CRYPT_BN_ERR_DIVISOR_ZERO);
619         return CRYPT_BN_ERR_DIVISOR_ZERO;
620     }
621 
622     return CRYPT_SUCCESS;
623 }
624 
BN_ModSub(BN_BigNum * r,const BN_BigNum * a,const BN_BigNum * b,const BN_BigNum * mod,BN_Optimizer * opt)625 int32_t BN_ModSub(BN_BigNum *r, const BN_BigNum *a, const BN_BigNum *b, const BN_BigNum *mod, BN_Optimizer *opt)
626 {
627     int32_t ret;
628     ret = ModBaseInputCheck(r, a, b, mod, opt);
629     if (ret != CRYPT_SUCCESS) {
630         return ret;
631     }
632 
633     ret = OptimizerStart(opt); // using the Optimizer
634     if (ret != CRYPT_SUCCESS) {
635         return ret;
636     }
637     /* Difference: Apply for the temporary space of the BN object. */
638     uint32_t subTmpSize = (a->size > b ->size) ? a->size : b->size;
639     BN_BigNum *t = OptimizerGetBn(opt, subTmpSize);
640     if (t == NULL) {
641         ret = CRYPT_BN_OPTIMIZER_GET_FAIL;
642         BSL_ERR_PUSH_ERROR(ret);
643         goto err;
644     }
645     ret = BN_Sub(t, a, b);
646     if (ret != CRYPT_SUCCESS) {
647         BSL_ERR_PUSH_ERROR(ret);
648         goto err;
649     }
650     ret = BN_Mod(r, t, mod, opt);
651     if (ret != CRYPT_SUCCESS) {
652         BSL_ERR_PUSH_ERROR(ret);
653     }
654 err:
655     OptimizerEnd(opt); // release occupation from the optimizer
656     return ret;
657 }
658 
BN_ModAdd(BN_BigNum * r,const BN_BigNum * a,const BN_BigNum * b,const BN_BigNum * mod,BN_Optimizer * opt)659 int32_t BN_ModAdd(BN_BigNum *r, const BN_BigNum *a, const BN_BigNum *b, const BN_BigNum *mod, BN_Optimizer *opt)
660 {
661     int32_t ret;
662     ret = ModBaseInputCheck(r, a, b, mod, opt);
663     if (ret != CRYPT_SUCCESS) {
664         return ret;
665     }
666 
667     ret = OptimizerStart(opt); // using the Optimizer
668     if (ret != CRYPT_SUCCESS) {
669         return ret;
670     }
671     /* Difference: Apply for the temporary space of the BN object. */
672     uint32_t addTmpSize = (a->size > b ->size) ? a->size : b->size;
673     BN_BigNum *t = OptimizerGetBn(opt, addTmpSize);
674     if (t == NULL) {
675         ret = CRYPT_BN_OPTIMIZER_GET_FAIL;
676         BSL_ERR_PUSH_ERROR(ret);
677         goto err;
678     }
679     ret = BN_Add(t, a, b);
680     if (ret != CRYPT_SUCCESS) {
681         BSL_ERR_PUSH_ERROR(ret);
682         goto err;
683     }
684     ret = BN_Mod(r, t, mod, opt);
685     if (ret != CRYPT_SUCCESS) {
686         BSL_ERR_PUSH_ERROR(ret);
687     }
688 err:
689     OptimizerEnd(opt); // release occupation from the optimizer
690     return ret;
691 }
692 
BN_ModMul(BN_BigNum * r,const BN_BigNum * a,const BN_BigNum * b,const BN_BigNum * mod,BN_Optimizer * opt)693 int32_t BN_ModMul(BN_BigNum *r, const BN_BigNum *a, const BN_BigNum *b, const BN_BigNum *mod, BN_Optimizer *opt)
694 {
695     int32_t ret;
696 
697     ret = ModBaseInputCheck(r, a, b, mod, opt);
698     if (ret != CRYPT_SUCCESS) {
699         return ret;
700     }
701 
702     ret = OptimizerStart(opt); // using the Optimizer
703     if (ret != CRYPT_SUCCESS) {
704         return ret;
705     }
706     /* Apply for the temporary space of the BN object. */
707     BN_BigNum *t = OptimizerGetBn(opt, a->size + b->size + 1);
708     if (t == NULL) {
709         ret = CRYPT_BN_OPTIMIZER_GET_FAIL;
710         BSL_ERR_PUSH_ERROR(ret);
711         goto err;
712     }
713     ret = BN_Mul(t, a, b, opt);
714     if (ret != CRYPT_SUCCESS) {
715         BSL_ERR_PUSH_ERROR(ret);
716         goto err;
717     }
718     ret = BN_Mod(r, t, mod, opt);
719     if (ret != CRYPT_SUCCESS) {
720         BSL_ERR_PUSH_ERROR(ret);
721     }
722 err:
723     OptimizerEnd(opt); // release occupation from the optimizer
724     return ret;
725 }
726 
BN_ModSqr(BN_BigNum * r,const BN_BigNum * a,const BN_BigNum * mod,BN_Optimizer * opt)727 int32_t BN_ModSqr(BN_BigNum *r, const BN_BigNum *a, const BN_BigNum *mod, BN_Optimizer *opt)
728 {
729     bool invalidInput = (r == NULL || a == NULL || mod == NULL || opt == NULL);
730     if (invalidInput) {
731         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
732         return CRYPT_NULL_INPUT;
733     }
734     // mod cannot be 0
735     if (BN_IsZero(mod)) {
736         BSL_ERR_PUSH_ERROR(CRYPT_BN_ERR_DIVISOR_ZERO);
737         return CRYPT_BN_ERR_DIVISOR_ZERO;
738     }
739 
740     int32_t ret = BnExtend(r, mod->size);
741     if (ret != CRYPT_SUCCESS) {
742         return ret;
743     }
744 
745     ret = OptimizerStart(opt); // using the Optimizer
746     if (ret != CRYPT_SUCCESS) {
747         BSL_ERR_PUSH_ERROR(ret);
748         return ret;
749     }
750     /* Apply for the temporary space of the BN object. */
751     BN_BigNum *t = OptimizerGetBn(opt, (a->size << 1) + 1);
752     if (t == NULL) {
753         ret = CRYPT_BN_OPTIMIZER_GET_FAIL;
754         BSL_ERR_PUSH_ERROR(ret);
755         goto err;
756     }
757     ret = BN_Sqr(t, a, opt);
758     if (ret != CRYPT_SUCCESS) {
759         BSL_ERR_PUSH_ERROR(ret);
760         goto err;
761     }
762     ret = BN_Mod(r, t, mod, opt);
763     if (ret != CRYPT_SUCCESS) {
764         BSL_ERR_PUSH_ERROR(ret);
765     }
766 err:
767     OptimizerEnd(opt); // release occupation from the optimizer
768     return ret;
769 }
770 
ModExpInputCheck(BN_BigNum * r,const BN_BigNum * a,const BN_BigNum * e,const BN_BigNum * m,const BN_Optimizer * opt)771 int32_t ModExpInputCheck(BN_BigNum *r, const BN_BigNum *a, const BN_BigNum *e,
772     const BN_BigNum *m, const BN_Optimizer *opt)
773 {
774     bool invalidInput = (r == NULL || a == NULL || e == NULL || m == NULL || opt == NULL);
775     if (invalidInput) {
776         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
777         return CRYPT_NULL_INPUT;
778     }
779     // mod cannot be 0
780     if (BN_IsZero(m)) {
781         BSL_ERR_PUSH_ERROR(CRYPT_BN_ERR_DIVISOR_ZERO);
782         return CRYPT_BN_ERR_DIVISOR_ZERO;
783     }
784     // the power cannot be negative
785     if (e->sign == true) {
786         BSL_ERR_PUSH_ERROR(CRYPT_BN_ERR_EXP_NO_NEGATIVE);
787         return CRYPT_BN_ERR_EXP_NO_NEGATIVE;
788     }
789     return BnExtend(r, m->size);
790 }
791 
ModExpCore(BN_BigNum * x,BN_BigNum * y,const BN_BigNum * e,const BN_BigNum * m,BN_Optimizer * opt)792 int32_t ModExpCore(BN_BigNum *x, BN_BigNum *y, const BN_BigNum *e, const BN_BigNum *m, BN_Optimizer *opt)
793 {
794     int32_t ret;
795     if (BN_GetBit(e, 0) == 1) {
796         (void)BN_Copy(x, y); // ignores the returned value, we can ensure that no error occurs when applying memory
797     } else { // set the value to 1
798         (void)BN_SetLimb(x, 1); // ignores the returned value, we can ensure that no error occurs when applying memory
799     }
800 
801     uint32_t bits = BN_Bits(e);
802     for (uint32_t i = 1; i < bits; i++) {
803         ret = BN_ModSqr(y, y, m, opt); // y is a temporary variable, which is multiplied by x
804         if (ret != CRYPT_SUCCESS) {
805             BSL_ERR_PUSH_ERROR(ret);
806             return ret;
807         }
808         if (BN_GetBit(e, i) == 1) {
809             ret = BN_ModMul(x, x, y, m, opt); // x^1101  = x^1 * x^100 * x^1000
810             if (ret != CRYPT_SUCCESS) {
811                 BSL_ERR_PUSH_ERROR(ret);
812                 return ret;
813             }
814         }
815     }
816     return CRYPT_SUCCESS;
817 }
818 
SwitchMont(BN_BigNum * r,const BN_BigNum * a,const BN_BigNum * e,const BN_BigNum * m,BN_Optimizer * opt)819 static int32_t SwitchMont(BN_BigNum *r, const BN_BigNum *a, const BN_BigNum *e, const BN_BigNum *m, BN_Optimizer *opt)
820 {
821     BN_Mont *mont = BN_MontCreate(m);
822     if (mont == NULL) {
823         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
824         return CRYPT_NULL_INPUT;
825     }
826     int32_t ret = BN_MontExp(r, a, e, mont, opt);
827     BN_MontDestroy(mont);
828     return ret;
829 }
830 
BN_ModExp(BN_BigNum * r,const BN_BigNum * a,const BN_BigNum * e,const BN_BigNum * m,BN_Optimizer * opt)831 int32_t BN_ModExp(BN_BigNum *r, const BN_BigNum *a, const BN_BigNum *e, const BN_BigNum *m, BN_Optimizer *opt)
832 {
833     int32_t ret = ModExpInputCheck(r, a, e, m, opt);
834     if (ret != CRYPT_SUCCESS) {
835         return ret;
836     }
837 
838     // When m = 1 or -1
839     if (m->size == 1 && m->data[0] == 1) {
840         return BN_Zeroize(r);
841     }
842     if (BN_IsOdd(m) && !BN_IsNegative(m)) {
843         return SwitchMont(r, a, e, m, opt);
844     }
845 
846     ret = OptimizerStart(opt); // using the Optimizer
847     if (ret != CRYPT_SUCCESS) {
848         BSL_ERR_PUSH_ERROR(ret);
849         return ret;
850     }
851 
852     /* Apply for the temporary space of the BN object. */
853     BN_BigNum *x = OptimizerGetBn(opt, m->size);
854     BN_BigNum *y = OptimizerGetBn(opt, m->size);
855     if (x == NULL || y == NULL) {
856         OptimizerEnd(opt); // release occupation from the optimizer
857         BSL_ERR_PUSH_ERROR(CRYPT_BN_OPTIMIZER_GET_FAIL);
858         return CRYPT_BN_OPTIMIZER_GET_FAIL;
859     }
860     // step 1: Obtain the modulus once, and then determine the power and remainder.
861     ret = BN_Mod(y, a, m, opt);
862     if (ret != CRYPT_SUCCESS) {
863         OptimizerEnd(opt);
864         BSL_ERR_PUSH_ERROR(ret);
865         return ret;
866     }
867 
868     // step2: check the power. Any number to the power of 0 is 1. (0 to the power of 0 to the power of 0)
869     if (BN_IsZero(e) || BN_IsOne(y)) {
870         OptimizerEnd(opt);
871         return BN_SetLimb(r, 1);
872     }
873     // step3: The remainder is 0 and the result must be 0.
874     if (BN_IsZero(y)) {
875         OptimizerEnd(opt); // release occupation from the optimizer
876         return BN_Zeroize(r);
877     }
878     /* Power factorization: e binary x^1101  = x^1 * x^100 * x^1000
879                             e Decimal x^13    = x^1 * x^4 * x^8  */
880     ret = ModExpCore(x, y, e, m, opt);
881     if (ret != CRYPT_SUCCESS) {
882         OptimizerEnd(opt);
883         BSL_ERR_PUSH_ERROR(ret);
884         return ret;
885     }
886     ret = BN_Copy(r, x);
887     if (ret != CRYPT_SUCCESS) {
888         BSL_ERR_PUSH_ERROR(ret);
889     }
890     OptimizerEnd(opt); // release occupation from the optimizer
891 
892     return ret;
893 }
894 
BN_Rshift(BN_BigNum * r,const BN_BigNum * a,uint32_t n)895 int32_t BN_Rshift(BN_BigNum *r, const BN_BigNum *a, uint32_t n)
896 {
897     if (r == NULL || a == NULL) {
898         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
899         return CRYPT_NULL_INPUT;
900     }
901     if (BN_Bits(a) <= n) {
902         return BN_Zeroize(r);
903     }
904     int32_t ret = BnExtend(r, BITS_TO_BN_UNIT(BN_Bits(a) - n));
905     if (ret != CRYPT_SUCCESS) {
906         return ret;
907     }
908 
909     r->sign = a->sign;
910     uint32_t size = BinRshift(r->data, a->data, a->size, n);
911     if (size < r->size) {
912         if (memset_s(r->data + size, (r->room - size) * sizeof(BN_UINT), 0,
913             (r->size - size) * sizeof(BN_UINT)) != EOK) {
914             BSL_ERR_PUSH_ERROR(CRYPT_SECUREC_FAIL);
915             return CRYPT_SECUREC_FAIL;
916         }
917     }
918     r->size = size;
919     return CRYPT_SUCCESS;
920 }
921 
BN_Lshift(BN_BigNum * r,const BN_BigNum * a,uint32_t n)922 int32_t BN_Lshift(BN_BigNum *r, const BN_BigNum *a, uint32_t n)
923 {
924     if (r == NULL || a == NULL) {
925         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
926         return CRYPT_NULL_INPUT;
927     }
928 
929     uint32_t incUnit = n % BN_UINT_BITS == 0 ? (n / BN_UINT_BITS) : ((n / BN_UINT_BITS) + 1);
930     int32_t ret = BnExtend(r, a->size + incUnit);
931     if (ret != CRYPT_SUCCESS) {
932         return ret;
933     }
934 
935     if (a->size != 0) {
936         r->size = BinLshift(r->data, a->data, a->size, n);
937     } else {
938         (void)BN_Zeroize(r);
939     }
940     r->sign = a->sign;
941     return CRYPT_SUCCESS;
942 }
943 
944 #ifdef HITLS_CRYPTO_ECC
945 // '~mask' is the mask of a and 'mask' is the mask of b.
BN_CopyWithMask(BN_BigNum * r,const BN_BigNum * a,const BN_BigNum * b,BN_UINT mask)946 int32_t BN_CopyWithMask(BN_BigNum *r, const BN_BigNum *a, const BN_BigNum *b,
947     BN_UINT mask)
948 {
949     if (r == NULL || a == NULL || b == NULL) {
950         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
951         return CRYPT_NULL_INPUT;
952     }
953     if ((a->room != r->room) || (b->room != r->room)) {
954         BSL_ERR_PUSH_ERROR(CRYPT_BN_ERR_MASKCOPY_LEN);
955         return CRYPT_BN_ERR_MASKCOPY_LEN;
956     }
957     BN_UINT rmask = ~mask;
958     uint32_t len = r->room;
959     BN_UINT *dst = r->data;
960     BN_UINT *srcA = a->data;
961     BN_UINT *srcB = b->data;
962     for (uint32_t i = 0; i < len; i++) {
963         dst[i] = (srcA[i] & rmask) ^ (srcB[i] & mask);
964     }
965     r->sign = (mask != 0) ? (a->sign) : (b->sign);
966     r->size = (a->size & (uint32_t)rmask) ^ (b->size & (uint32_t)mask);
967     return CRYPT_SUCCESS;
968 }
969 #endif
970 
971 #if defined(HITLS_CRYPTO_ECC) && defined(HITLS_CRYPTO_CURVE_MONT)
972 /* Invoked by the ECC module and the sign can be ignored.
973  * if mask = BN_MASK, a, b --> b, a
974  * if mask = 0, a, b --> a, b
975  */
BN_SwapWithMask(BN_BigNum * a,BN_BigNum * b,BN_UINT mask)976 int32_t BN_SwapWithMask(BN_BigNum *a, BN_BigNum *b, BN_UINT mask)
977 {
978     if (a == NULL || b == NULL) {
979         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
980         return CRYPT_NULL_INPUT;
981     }
982     if (a->room != b->room) {
983         BSL_ERR_PUSH_ERROR(CRYPT_BN_ERR_SWAP_LEN);
984         return CRYPT_BN_ERR_SWAP_LEN;
985     }
986     BN_UINT rmask = ~mask;
987     BN_UINT *srcA = a->data;
988     BN_UINT *srcB = b->data;
989     BN_UINT tmp1;
990     BN_UINT tmp2;
991     for (uint32_t i = 0; i < a->room; i++) {
992         tmp1 = srcA[i];
993         tmp2 = srcB[i];
994         srcA[i] = (tmp1 & rmask) | (tmp2 & mask);
995         srcB[i] = (tmp2 & rmask) | (tmp1 & mask);
996     }
997     tmp1 = a->size;
998     tmp2 = b->size;
999     a->size = (tmp1 & (uint32_t)rmask) | (tmp2 & (uint32_t)mask);
1000     b->size = (tmp2 & (uint32_t)rmask) | (tmp1 & (uint32_t)mask);
1001     return CRYPT_SUCCESS;
1002 }
1003 #endif // HITLS_CRYPTO_ECC and HITLS_CRYPTO_CURVE_MONT
1004 
1005 #endif /* HITLS_CRYPTO_BN */
1006