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