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 <stdint.h>
20 #include <stdbool.h>
21 #include "securec.h"
22 #include "bsl_err_internal.h"
23 #include "bsl_sal.h"
24 #include "crypt_errno.h"
25 #include "bn_bincal.h"
26 #include "bn_optimizer.h"
27 #include "crypt_utils.h"
28 #include "bn_montbin.h"
29
30 // The mont contains 4 BN_UINT* fields and 2 common fields.
31 #define MAX_MONT_SIZE ((BITS_TO_BN_UNIT(BN_MAX_BITS) * 4 + 2) * sizeof(BN_UINT))
32
CopyConsttime(BN_UINT * dst,const BN_UINT * a,const BN_UINT * b,uint32_t len,BN_UINT mask)33 static void CopyConsttime(BN_UINT *dst, const BN_UINT *a, const BN_UINT *b, uint32_t len, BN_UINT mask)
34 {
35 BN_UINT rmask = ~mask;
36 for (uint32_t i = 0; i < len; i++) {
37 dst[i] = (a[i] & mask) ^ (b[i] & rmask);
38 }
39 }
40
41 /* reduce(r) */
MontDecBin(BN_UINT * r,BN_Mont * mont)42 static void MontDecBin(BN_UINT *r, BN_Mont *mont)
43 {
44 uint32_t mSize = mont->mSize;
45 BN_UINT *x = mont->t;
46 BN_COPY_BYTES(x, mSize << 1, r, mSize);
47 Reduce(r, x, mont->one, mont->mod, mSize, mont->k0);
48 }
49
50 /* Return value is (r - m0)' mod r */
Inverse(BN_UINT m0)51 static BN_UINT Inverse(BN_UINT m0)
52 {
53 BN_UINT x = 2; /* 2^1 */
54 BN_UINT y = 1;
55 BN_UINT mask = 1; /* Mask */
56 for (uint32_t i = 1; i < BN_UINT_BITS; i++, x <<= 1) {
57 BN_UINT rH, rL;
58 mask = (mask << 1) | 1;
59 MUL_AB(rH, rL, m0, y);
60 if (x < (rL & mask)) {
61 y += x;
62 }
63 (void)rH;
64 }
65 return (BN_UINT)(0 - y);
66 }
67
68 /* Pre-computation */
MontExpReady(BN_BigNum * table[],uint32_t num,BN_Mont * mont,BN_Optimizer * opt,bool consttime)69 static int32_t MontExpReady(BN_BigNum *table[], uint32_t num, BN_Mont *mont, BN_Optimizer *opt, bool consttime)
70 {
71 BN_UINT *b = mont->b;
72 uint32_t i;
73 for (i = 1; i < num; i++) { /* Request num - 1 data blocks */
74 table[i] = OptimizerGetBn(opt, mont->mSize);
75 if (table[i] == NULL) {
76 BSL_ERR_PUSH_ERROR(CRYPT_BN_OPTIMIZER_GET_FAIL);
77 return CRYPT_BN_OPTIMIZER_GET_FAIL;
78 }
79 }
80 table[0] = table[1];
81 (void)memcpy_s(table[1]->data, mont->mSize * sizeof(BN_UINT), b, mont->mSize * sizeof(BN_UINT));
82
83 for (i = 2; i < num; i++) { /* precompute num - 2 data blocks */
84 int32_t ret = MontMulBin(table[i]->data, table[0]->data, table[i - 1]->data, mont, opt, consttime);
85 if (ret != CRYPT_SUCCESS) {
86 return ret;
87 }
88 }
89 return CRYPT_SUCCESS;
90 }
91
GetELimb(const BN_UINT * e,BN_UINT * eLimb,uint32_t base,uint32_t bits)92 static uint32_t GetELimb(const BN_UINT *e, BN_UINT *eLimb, uint32_t base, uint32_t bits)
93 {
94 if (bits > base) { /* Required data */
95 (*eLimb) = e[0] & (((1u) << base) - 1);
96 return base;
97 }
98 (*eLimb) = 0;
99 for (uint32_t i = 0; i < bits; i++) {
100 uint32_t bit = base - i - 1;
101 uint32_t nw = bit / BN_UINT_BITS; /* shift words */
102 uint32_t nb = bit % BN_UINT_BITS; /* shift bits */
103 (*eLimb) <<= 1;
104 (*eLimb) |= ((e[nw] >> nb) & 1);
105 }
106 return bits;
107 }
108
GetReadySize(uint32_t bits)109 static uint32_t GetReadySize(uint32_t bits)
110 {
111 if (bits > 512) { /* If bits are greater than 512 */
112 return 6; /* The size is 6. */
113 }
114 if (bits > 256) { /* If bits are greater than 256 */
115 return 5; /* The size is 5. */
116 }
117 if (bits > 128) { /* If bits are greater than 128 */
118 return 4; /* The size is 4. */
119 }
120 if (bits > 64) { /* If bits are greater than 64 */
121 return 3; /* The size is 3. */
122 }
123 if (bits > 32) { /* If bits are greater than 32 */
124 return 2; /* The size is 2. */
125 }
126 return 1;
127 }
128
129 /* r = r ^ e mod mont */
MontExpBin(BN_UINT * r,const BN_UINT * e,uint32_t eSize,BN_Mont * mont,BN_Optimizer * opt,bool consttime)130 static int32_t MontExpBin(BN_UINT *r, const BN_UINT *e, uint32_t eSize, BN_Mont *mont,
131 BN_Optimizer *opt, bool consttime)
132 {
133 BN_BigNum *table[64] = { 0 }; /* 0 -- 2^6 that is 0 -- 64 */
134 int32_t ret = OptimizerStart(opt);
135 if (ret != CRYPT_SUCCESS) {
136 return ret;
137 }
138 (void)memcpy_s(mont->b, mont->mSize * sizeof(BN_UINT), r, mont->mSize * sizeof(BN_UINT));
139 uint32_t base = BinBits(e, eSize) - 1;
140 uint32_t perSize = GetReadySize(base);
141 const uint32_t readySize = 1 << perSize;
142 ret = MontExpReady(table, readySize, mont, opt, consttime);
143 if (ret != CRYPT_SUCCESS) {
144 OptimizerEnd(opt);
145 return ret;
146 }
147 do {
148 BN_UINT eLimb;
149 uint32_t bit = GetELimb(e, &eLimb, base, perSize);
150 for (uint32_t i = 0; i < bit; i++) {
151 ret = MontSqrBin(r, mont, opt, consttime);
152 if (ret != CRYPT_SUCCESS) {
153 OptimizerEnd(opt);
154 return ret;
155 }
156 }
157 if (consttime == true) {
158 BN_UINT *x = mont->t;
159 BN_UINT mask = ~BN_IsZeroUintConsttime(eLimb);
160 ret = MontMulBin(x, r, table[eLimb]->data, mont, opt, consttime);
161 if (ret != CRYPT_SUCCESS) {
162 OptimizerEnd(opt);
163 return ret;
164 }
165 CopyConsttime(r, x, r, mont->mSize, mask);
166 } else if (eLimb != 0) {
167 ret = MontMulBin(r, r, table[eLimb]->data, mont, opt, consttime);
168 if (ret != CRYPT_SUCCESS) {
169 OptimizerEnd(opt);
170 return ret;
171 }
172 }
173 base -= bit;
174 } while (base != 0);
175 OptimizerEnd(opt);
176 return CRYPT_SUCCESS;
177 }
178
MontParaCheck(BN_BigNum * r,const BN_BigNum * a,const BN_BigNum * e,const BN_Mont * mont)179 static int32_t MontParaCheck(BN_BigNum *r, const BN_BigNum *a, const BN_BigNum *e, const BN_Mont *mont)
180 {
181 if (r == NULL || a == NULL || e == NULL || mont == NULL) {
182 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
183 return CRYPT_NULL_INPUT;
184 }
185 if (e->sign) {
186 BSL_ERR_PUSH_ERROR(CRYPT_BN_ERR_EXP_NO_NEGATIVE);
187 return CRYPT_BN_ERR_EXP_NO_NEGATIVE;
188 }
189 return BnExtend(r, mont->mSize);
190 }
191
DealBaseNum(const BN_BigNum * a,BN_Mont * mont,BN_Optimizer * opt,int32_t * ret)192 static const BN_BigNum *DealBaseNum(const BN_BigNum *a, BN_Mont *mont, BN_Optimizer *opt, int32_t *ret)
193 {
194 const BN_BigNum *aTmp = a;
195 if (BinCmp(a->data, a->size, mont->mod, mont->mSize) >= 0) {
196 BN_BigNum *tmpval = OptimizerGetBn(opt, a->size + 2); // BinDiv need a->room >= a->size + 2
197 BN_BigNum *tmpMod = OptimizerGetBn(opt, mont->mSize); // BinDiv need a->room >= a->size + 2
198 if (tmpval == NULL || tmpMod == NULL) {
199 BSL_ERR_PUSH_ERROR(CRYPT_BN_OPTIMIZER_GET_FAIL);
200 *ret = CRYPT_BN_OPTIMIZER_GET_FAIL;
201 return NULL;
202 }
203 *ret = BN_Copy(tmpval, a);
204 if (*ret != CRYPT_SUCCESS) {
205 BSL_ERR_PUSH_ERROR(*ret);
206 return NULL;
207 }
208 (void)memcpy_s(tmpMod->data, mont->mSize * sizeof(BN_UINT), mont->mod, mont->mSize * sizeof(BN_UINT));
209 tmpval->size = BinDiv(NULL, NULL, tmpval->data, tmpval->size, tmpMod->data, mont->mSize);
210 aTmp = tmpval;
211 }
212 return aTmp;
213 }
214
TmpValueHandle(BN_BigNum * r,const BN_BigNum * e,const BN_BigNum * a,BN_Optimizer * opt)215 static const BN_UINT *TmpValueHandle(BN_BigNum *r, const BN_BigNum *e, const BN_BigNum *a, BN_Optimizer *opt)
216 {
217 const BN_UINT *te = e->data;
218 uint32_t esize = e->size;
219 if (e == r) {
220 BN_BigNum *ee = OptimizerGetBn(opt, esize);
221 if (ee == NULL) {
222 return NULL;
223 }
224 (void)memcpy_s(ee->data, esize * sizeof(BN_UINT), e->data, esize * sizeof(BN_UINT));
225 te = ee->data;
226 }
227 BN_COPY_BYTES(r->data, r->room, a->data, a->size);
228 return te;
229 }
230
231 /* must satisfy the absolute value x < mod */
MontExpCore(BN_BigNum * r,const BN_BigNum * a,const BN_BigNum * e,BN_Mont * mont,BN_Optimizer * opt,bool consttime)232 static int32_t MontExpCore(BN_BigNum *r, const BN_BigNum *a, const BN_BigNum *e,
233 BN_Mont *mont, BN_Optimizer *opt, bool consttime)
234 {
235 if ((BinBits(e->data, e->size) == 0)) {
236 if (mont->mSize != 1) {
237 return BN_SetLimb(r, 1);
238 }
239 return (mont->mod[0] == 1) ? BN_Zeroize(r) : BN_SetLimb(r, 1);
240 }
241 if (a->size == 0) {
242 return BN_Zeroize(r);
243 }
244 int32_t ret = OptimizerStart(opt);
245 if (ret != CRYPT_SUCCESS) {
246 return ret;
247 }
248
249 /* if a >= mod */
250 const BN_BigNum *aTmp = DealBaseNum(a, mont, opt, &ret);
251 if (aTmp == NULL) {
252 OptimizerEnd(opt);
253 return ret;
254 }
255 const BN_UINT *te = TmpValueHandle(r, e, aTmp, opt);
256 if (te == NULL) {
257 OptimizerEnd(opt);
258 BSL_ERR_PUSH_ERROR(CRYPT_BN_OPTIMIZER_GET_FAIL);
259 return CRYPT_BN_OPTIMIZER_GET_FAIL;
260 }
261 /* field conversion */
262 ret = MontEncBin(r->data, mont, opt, consttime);
263 if (ret != CRYPT_SUCCESS) {
264 OptimizerEnd(opt);
265 return ret;
266 }
267 /* modular exponentiation */
268 ret = MontExpBin(r->data, te, e->size, mont, opt, consttime);
269 if (ret != CRYPT_SUCCESS) {
270 OptimizerEnd(opt);
271 return ret;
272 }
273 /* field conversion */
274 MontDecBin(r->data, mont);
275
276 /* negative number processing */
277 r->size = BinFixSize(r->data, mont->mSize);
278 if (aTmp->sign && ((te[0] & 0x1) == 1) && r->size != 0) {
279 BinSub(r->data, mont->mod, r->data, mont->mSize);
280 r->size = BinFixSize(r->data, mont->mSize);
281 }
282 r->sign = false;
283 OptimizerEnd(opt);
284 return CRYPT_SUCCESS;
285 }
286
MontExp(BN_BigNum * r,const BN_BigNum * a,const BN_BigNum * e,BN_Mont * mont,BN_Optimizer * opt,bool consttime)287 static int32_t MontExp(BN_BigNum *r, const BN_BigNum *a, const BN_BigNum *e, BN_Mont *mont,
288 BN_Optimizer *opt, bool consttime)
289 {
290 int32_t ret = MontParaCheck(r, a, e, mont);
291 if (ret != CRYPT_SUCCESS) {
292 return ret;
293 }
294 bool newOpt = (opt == NULL);
295 if (newOpt) {
296 opt = BN_OptimizerCreate();
297 if (opt == NULL) {
298 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
299 return CRYPT_MEM_ALLOC_FAIL;
300 }
301 }
302 ret = MontExpCore(r, a, e, mont, opt, consttime);
303 if (newOpt) {
304 BN_OptimizerDestroy(opt);
305 }
306 return ret;
307 }
308
BN_MontExp(BN_BigNum * r,const BN_BigNum * a,const BN_BigNum * e,BN_Mont * mont,BN_Optimizer * opt)309 int32_t BN_MontExp(BN_BigNum *r, const BN_BigNum *a, const BN_BigNum *e, BN_Mont *mont, BN_Optimizer *opt)
310 {
311 bool consttime = (BN_IsFlag(a, CRYPT_BN_FLAG_CONSTTIME) || BN_IsFlag(e, CRYPT_BN_FLAG_CONSTTIME));
312 return MontExp(r, a, e, mont, opt, consttime);
313 }
314
315 /* must satisfy the absolute value x < mod */
BN_MontExpConsttime(BN_BigNum * r,const BN_BigNum * a,const BN_BigNum * e,BN_Mont * mont,BN_Optimizer * opt)316 int32_t BN_MontExpConsttime(BN_BigNum *r, const BN_BigNum *a, const BN_BigNum *e, BN_Mont *mont, BN_Optimizer *opt)
317 {
318 return MontExp(r, a, e, mont, opt, true);
319 }
320
MontSize(uint32_t room)321 static uint32_t MontSize(uint32_t room)
322 {
323 uint32_t size = (uint32_t)(sizeof(BN_Mont) + sizeof(BN_UINT));
324 /* Requires 6 * room + 1 space. mod(1) + montRR(1) + b(1) + t(2) + one = 6.
325 In addition, one more room is required when the modulus is set later. */
326 size += (room * 6 + 1) * ((uint32_t)sizeof(BN_UINT));
327 return size;
328 }
329
BN_MontDestroy(BN_Mont * mont)330 void BN_MontDestroy(BN_Mont *mont)
331 {
332 if (mont == NULL) {
333 return;
334 }
335 (void)memset_s(mont, MontSize(mont->mSize), 0, MontSize(mont->mSize));
336 BSL_SAL_FREE(mont);
337 }
338
339 /* set the modulus */
SetMod(BN_Mont * mont,const BN_BigNum * mod)340 static void SetMod(BN_Mont *mont, const BN_BigNum *mod)
341 {
342 uint32_t mSize = mod->size;
343 (void)memcpy_s(mont->mod, mSize * sizeof(BN_UINT), mod->data, mSize * sizeof(BN_UINT));
344 (void)memset_s(mont->one, mSize * 3 * sizeof(BN_UINT), 0, mSize * 3 * sizeof(BN_UINT)); /* clear one and RR */
345 mont->one[0] = 1; /* set one */
346 mont->k0 = Inverse(mod->data[0]);
347 mont->montRR[mSize * 2] = 1; /* 2^2n */
348 mont->montRR[mSize * 2 + 1] = 0; /* 2 more rooms are provided to ensure the division does not exceed the limit */
349 mont->montRR[mSize * 2 + 2] = 0; /* 2 more rooms are provided to ensure the division does not exceed the limit */
350
351 // The size of the space required for calculating the montRR is 2 * mSize + 1
352 (void)BinDiv(NULL, NULL, mont->montRR, 2 * mSize + 1, mont->mod, mSize);
353 (void)memcpy_s(mont->mod, mSize * sizeof(BN_UINT), mod->data, mSize * sizeof(BN_UINT));
354 }
355
356 /* create a Montgomery structure, where m is a modulo */
BN_MontCreate(const BN_BigNum * m)357 BN_Mont *BN_MontCreate(const BN_BigNum *m)
358 {
359 if (m == NULL) {
360 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
361 return NULL;
362 }
363 if (!BN_GetBit(m, 0) || m->sign) {
364 BSL_ERR_PUSH_ERROR(CRYPT_INVALID_ARG);
365 return NULL;
366 }
367 uint32_t mSize = m->size;
368 uint32_t montSize = MontSize(mSize);
369 if (montSize > MAX_MONT_SIZE) {
370 BSL_ERR_PUSH_ERROR(CRYPT_BN_BITS_TOO_MAX);
371 return NULL;
372 }
373 BN_Mont *mont = BSL_SAL_Malloc(montSize);
374 if (mont == NULL) {
375 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
376 return NULL;
377 }
378 BN_UINT *base = AlignedPointer((uint8_t *)mont + sizeof(BN_Mont), sizeof(BN_UINT));
379 mont->mSize = mSize;
380 mont->mod = base; /* mSize */
381 mont->one = (base += mSize); /* mSize */
382 mont->montRR = (base += mSize); /* mSize */
383 mont->b = (base += mSize); /* mSize */
384 mont->t = base + mSize; /* 2 * mSize */
385 SetMod(mont, m);
386 return mont;
387 }
388
MontSqrBinCore(BN_UINT * r,BN_Mont * mont,BN_Optimizer * opt,bool consttime)389 int32_t MontSqrBinCore(BN_UINT *r, BN_Mont *mont, BN_Optimizer *opt, bool consttime)
390 {
391 int32_t ret = OptimizerStart(opt);
392 if (ret != CRYPT_SUCCESS) {
393 return ret;
394 }
395 uint32_t mSize = mont->mSize;
396 BN_UINT *x = mont->t;
397 #ifdef HITLS_CRYPTO_BN_COMBA
398 BN_BigNum *bnSpace = OptimizerGetBn(opt, SpaceSize(mSize));
399 if (bnSpace == NULL) {
400 OptimizerEnd(opt);
401 BSL_ERR_PUSH_ERROR(CRYPT_BN_OPTIMIZER_GET_FAIL);
402 return CRYPT_BN_OPTIMIZER_GET_FAIL;
403 }
404 SqrConquer(x, r, mSize, bnSpace->data, consttime);
405 #else
406 (void)consttime;
407 BinSqr(x, mSize << 1, r, mSize);
408 #endif
409 Reduce(r, x, mont->one, mont->mod, mSize, mont->k0);
410
411 OptimizerEnd(opt);
412 return CRYPT_SUCCESS;
413 }
414
415 /* reduce(a)= (a * R') mod N) */
ReduceCore(BN_UINT * r,BN_UINT * x,const BN_UINT * m,uint32_t mSize,BN_UINT m0)416 void ReduceCore(BN_UINT *r, BN_UINT *x, const BN_UINT *m, uint32_t mSize, BN_UINT m0)
417 {
418 BN_UINT carry = 0;
419 uint32_t n = 0;
420 /* Cyclic shift, obtain r = (x / R) mod N */
421 do {
422 BN_UINT q = x[n] * m0; /* q = (s[0] + x[i]) * m0 */
423 BN_UINT tmp = BinMulAcc(x + n, m, mSize, q); /* (s + qm) mod m == s. Refresh s[0] to x[0] */
424 /* Add carry to tmp and update carry flag. */
425 tmp = tmp + carry;
426 carry = (tmp < carry) ? 1 : 0;
427 /* Add tmp to x[mSize + n] and update the carry flag. */
428 x[mSize + n] += tmp;
429 carry = (x[mSize + n] < tmp) ? 1 : carry;
430 if (n + 1 == mSize) {
431 break;
432 }
433 n++;
434 } while (true);
435 /* If x < 2m, the carry value is 0 or -1. */
436 carry -= BinSub(r, x + mSize, m, mSize);
437 CopyConsttime(r, x + mSize, r, mSize, carry);
438 }
439
440 /* reduce(r * RR) */
MontEncBinCore(BN_UINT * r,BN_Mont * mont,BN_Optimizer * opt,bool consttime)441 int32_t MontEncBinCore(BN_UINT *r, BN_Mont *mont, BN_Optimizer *opt, bool consttime)
442 {
443 int32_t ret = OptimizerStart(opt);
444 if (ret != CRYPT_SUCCESS) {
445 return ret;
446 }
447 uint32_t mSize = mont->mSize;
448 BN_UINT *x = mont->t;
449 #ifdef HITLS_CRYPTO_BN_COMBA
450 BN_BigNum *bnSpace = OptimizerGetBn(opt, SpaceSize(mSize));
451 if (bnSpace == NULL) {
452 OptimizerEnd(opt);
453 BSL_ERR_PUSH_ERROR(CRYPT_BN_OPTIMIZER_GET_FAIL);
454 return CRYPT_BN_OPTIMIZER_GET_FAIL;
455 }
456
457 MulConquer(x, r, mont->montRR, mSize, bnSpace->data, consttime);
458 #else
459 (void)consttime;
460 BinMul(x, mSize << 1, r, mSize, mont->montRR, mSize);
461 #endif
462
463 Reduce(r, x, mont->one, mont->mod, mSize, mont->k0);
464
465 OptimizerEnd(opt);
466 return CRYPT_SUCCESS;
467 }
468
469 /* reduce(r * b) */
MontMulBinCore(BN_UINT * r,const BN_UINT * a,const BN_UINT * b,BN_Mont * mont,BN_Optimizer * opt,bool consttime)470 int32_t MontMulBinCore(BN_UINT *r, const BN_UINT *a, const BN_UINT *b, BN_Mont *mont, BN_Optimizer *opt, bool consttime)
471 {
472 int32_t ret = OptimizerStart(opt);
473 if (ret != CRYPT_SUCCESS) {
474 return ret;
475 }
476 uint32_t mSize = mont->mSize;
477 BN_UINT *x = mont->t;
478 #ifdef HITLS_CRYPTO_BN_COMBA
479 uint32_t size = SpaceSize(mSize);
480 BN_BigNum *bnSpace = OptimizerGetBn(opt, size);
481 if (bnSpace == NULL) {
482 OptimizerEnd(opt);
483 BSL_ERR_PUSH_ERROR(CRYPT_BN_OPTIMIZER_GET_FAIL);
484 return CRYPT_BN_OPTIMIZER_GET_FAIL;
485 }
486 MulConquer(x, a, b, mSize, bnSpace->data, consttime);
487 #else
488 (void)consttime;
489 BinMul(x, mSize << 1, a, mSize, b, mSize);
490 #endif
491 Reduce(r, x, mont->one, mont->mod, mSize, mont->k0);
492
493 OptimizerEnd(opt);
494 return CRYPT_SUCCESS;
495 }
496
497 #ifdef HITLS_CRYPTO_DSA
GetFirstData(BN_UINT * r,uint32_t base1,uint32_t base2,BN_BigNum * table1[],BN_BigNum * table2[],BN_Mont * mont,BN_Optimizer * opt)498 static int32_t GetFirstData(BN_UINT *r, uint32_t base1, uint32_t base2,
499 BN_BigNum *table1[], BN_BigNum *table2[], BN_Mont *mont,
500 BN_Optimizer *opt)
501 {
502 bool consttime = false;
503 if (base1 == base2) {
504 return MontMulBin(r, table1[0]->data, table2[0]->data, mont, opt, consttime);
505 } else if (base1 > base2) {
506 (void)memcpy_s(r, mont->mSize * sizeof(BN_UINT), table1[0]->data, mont->mSize * sizeof(BN_UINT));
507 } else {
508 (void)memcpy_s(r, mont->mSize * sizeof(BN_UINT), table2[0]->data, mont->mSize * sizeof(BN_UINT));
509 }
510 return CRYPT_SUCCESS;
511 }
512
513 /* Precalculate odd multiples of data. The data in the table is b^1, b^3, b^5...b^(2*num - 1) */
MontExpOddReady(BN_BigNum * table[],uint32_t num,BN_Mont * mont,BN_Optimizer * opt,bool consttime)514 static int32_t MontExpOddReady(BN_BigNum *table[], uint32_t num, BN_Mont *mont, BN_Optimizer *opt, bool consttime)
515 {
516 BN_UINT *b = mont->b;
517 uint32_t i;
518 for (i = 0; i < num; i++) { /* Request num - 1 data blocks */
519 table[i] = OptimizerGetBn(opt, mont->mSize);
520 if (table[i] == NULL) {
521 BSL_ERR_PUSH_ERROR(CRYPT_BN_OPTIMIZER_GET_FAIL);
522 return CRYPT_BN_OPTIMIZER_GET_FAIL;
523 }
524 }
525 (void)memcpy_s(table[0]->data, mont->mSize * sizeof(BN_UINT), b, mont->mSize * sizeof(BN_UINT));
526 if (num == 1) {
527 // When num is 1, pre-computation is not need.
528 return CRYPT_SUCCESS;
529 }
530 int32_t ret = MontSqrBin(table[0]->data, // b^2
531 mont, opt, consttime);
532 if (ret != CRYPT_SUCCESS) {
533 return ret;
534 }
535 ret = MontMulBin(table[1]->data, table[0]->data, mont->b, // b^3
536 mont, opt, consttime);
537 if (ret != CRYPT_SUCCESS) {
538 return ret;
539 }
540 for (i = 2; i < num; i++) { /* precompute num - 2 data blocks */
541 // b^(2*i + 1)
542 ret = MontMulBin(table[i]->data, table[0]->data, table[i - 1]->data, mont, opt, consttime);
543 if (ret != CRYPT_SUCCESS) {
544 return ret;
545 }
546 }
547 (void)memcpy_s(table[0]->data, mont->mSize * sizeof(BN_UINT), b, mont->mSize * sizeof(BN_UINT));
548 return CRYPT_SUCCESS;
549 }
550
551 // Obtain the data with the length of bits from the start position of the base to the eLimb,
552 // ignore the high-order 0 data, and obtain an odd number or 0.
GetOddLimbBin(const BN_UINT * e,BN_UINT * eLimb,uint32_t base,uint32_t bits,uint32_t size)553 uint32_t GetOddLimbBin(const BN_UINT *e, BN_UINT *eLimb, uint32_t base, uint32_t bits, uint32_t size)
554 {
555 (*eLimb) = 0;
556 if (base == 0) {
557 return 0;
558 }
559 uint32_t loc = base;
560 uint32_t retBits = 0;
561 // Offset from current. Check whether non-zero data exists.
562 while (true) {
563 loc--;
564 uint32_t nw = loc / BN_UINT_BITS; /* shift words */
565 uint32_t nb = loc % BN_UINT_BITS; /* shift retBits */
566 if (nw < size && ((e[nw] >> nb) & 1) != 0) {
567 // Exit the loop when the bit is 1.
568 break;
569 }
570 retBits++;
571 if (loc == 0) {
572 // If no valid bit is encountered until the end, the subsequent bits are returned.
573 return retBits;
574 }
575 }
576 // Obtain valid data from the loc location.
577 for (uint32_t i = 0; i < bits; i++) {
578 uint32_t nw = loc / BN_UINT_BITS; /* shift words */
579 uint32_t nb = loc % BN_UINT_BITS; /* shift retBits */
580 (*eLimb) <<= 1;
581 (*eLimb) |= ((e[nw] >> nb) & 1);
582 retBits++;
583 if (loc == 0) {
584 // The remaining data is insufficient and the system exits early.
585 break;
586 }
587 loc--;
588 }
589 // The data must be 0 or an odd number.
590 while ((*eLimb) != 0 && ((*eLimb) & 1) == 0) {
591 // If eLimb is not 0 and is an even number, shift the eLimb to right.
592 (*eLimb) >>= 1;
593 retBits--;
594 }
595 return retBits;
596 }
597
598 /* r = (a1 ^ e1) * (a2 ^ e2) mod mont */
MontExpMul(BN_UINT * r,const BN_BigNum * a1,const BN_BigNum * e1,const BN_BigNum * a2,const BN_BigNum * e2,BN_Mont * mont,BN_Optimizer * opt)599 static int32_t MontExpMul(BN_UINT *r, const BN_BigNum *a1, const BN_BigNum *e1,
600 const BN_BigNum *a2, const BN_BigNum *e2, BN_Mont *mont, BN_Optimizer *opt)
601 {
602 bool consttime = false;
603 BN_UINT eLimb1, eLimb2;
604 uint32_t bit1 = 0;
605 uint32_t bit2 = 0;
606 // The window retains only the values whose exponent is an odd number, reduce storage in half.
607 BN_BigNum *table1[32] = { 0 }; /* 0 -- (2^6 >> 1), that is 0 -- 32 */
608 BN_BigNum *table2[32] = { 0 }; /* 0 -- (2^6 >> 1), that is 0 -- 32 */
609 int32_t ret = OptimizerStart(opt);
610 if (ret != CRYPT_SUCCESS) {
611 BSL_ERR_PUSH_ERROR(ret);
612 return ret;
613 }
614 uint32_t base1 = BinBits(e1->data, e1->size);
615 uint32_t base2 = BinBits(e2->data, e2->size);
616 uint32_t base = (base1 > base2) ? base1 : base2;
617
618 uint32_t perSize1 = GetReadySize(base1);
619 uint32_t perSize2 = GetReadySize(base2);
620 const uint32_t readySize1 = 1 << (perSize1 - 1);
621 const uint32_t readySize2 = 1 << (perSize2 - 1);
622
623 // Generate the pre-computation table.
624 (void)memcpy_s(mont->b, mont->mSize * sizeof(BN_UINT), a1->data, mont->mSize * sizeof(BN_UINT));
625 GOTO_ERR_IF(MontExpOddReady(table1, readySize1, mont, opt, consttime), ret);
626 (void)memcpy_s(mont->b, mont->mSize * sizeof(BN_UINT), a2->data, mont->mSize * sizeof(BN_UINT));
627 GOTO_ERR_IF(MontExpOddReady(table2, readySize2, mont, opt, consttime), ret);
628 // Obtain the first data.
629 GOTO_ERR_IF(GetFirstData(r, base1, base2, table1, table2, mont, opt), ret);
630 base--;
631
632 while (base != 0) {
633 bit1 = (bit1 == 0) ? GetOddLimbBin(e1->data, &eLimb1, base, perSize1, e1->size) : bit1;
634 bit2 = (bit2 == 0) ? GetOddLimbBin(e2->data, &eLimb2, base, perSize2, e2->size) : bit2;
635 uint32_t bit = (bit1 < bit2) ? bit1 : bit2;
636 for (uint32_t i = 0; i < bit; i++) {
637 GOTO_ERR_IF(MontSqrBin(r, mont, opt, consttime), ret);
638 }
639 if (bit == bit1 && eLimb1 != 0) {
640 GOTO_ERR_IF(MontMulBin(r, r, table1[(eLimb1 - 1) >> 1]->data, mont, opt, consttime), ret);
641 }
642 if (bit == bit2 && eLimb2 != 0) {
643 GOTO_ERR_IF(MontMulBin(r, r, table2[(eLimb2 - 1) >> 1]->data, mont, opt, consttime), ret);
644 }
645 bit1 -= bit;
646 bit2 -= bit;
647 base -= bit;
648 };
649 ERR:
650 OptimizerEnd(opt);
651 return ret;
652 }
653
MontExpMulParaCheck(BN_BigNum * r,const BN_BigNum * a1,const BN_BigNum * e1,const BN_BigNum * a2,const BN_BigNum * e2,const BN_Mont * mont,const BN_Optimizer * opt)654 static int32_t MontExpMulParaCheck(BN_BigNum *r, const BN_BigNum *a1,
655 const BN_BigNum *e1, const BN_BigNum *a2, const BN_BigNum *e2, const BN_Mont *mont,
656 const BN_Optimizer *opt)
657 {
658 if (r == NULL || a1 == NULL || e1 == NULL || a2 == NULL || e2 == NULL || mont == NULL || opt == NULL) {
659 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
660 return CRYPT_NULL_INPUT;
661 }
662 if (e1->sign || e2->sign) {
663 BSL_ERR_PUSH_ERROR(CRYPT_BN_ERR_EXP_NO_NEGATIVE);
664 return CRYPT_BN_ERR_EXP_NO_NEGATIVE;
665 }
666 return BnExtend(r, mont->mSize);
667 }
668
669 typedef struct {
670 BN_BigNum *a1;
671 BN_BigNum *a2;
672 BN_BigNum *e1;
673 BN_BigNum *e2;
674 } MontsMulFactor;
675
MontsFactorGetByOptThenCopy(MontsMulFactor * dst,const MontsMulFactor * src,uint32_t mSize,BN_Optimizer * opt)676 static int32_t MontsFactorGetByOptThenCopy(MontsMulFactor *dst, const MontsMulFactor *src,
677 uint32_t mSize, BN_Optimizer *opt)
678 {
679 dst->a1 = OptimizerGetBn(opt, mSize);
680 dst->a2 = OptimizerGetBn(opt, mSize);
681 dst->e1 = OptimizerGetBn(opt, mSize);
682 dst->e2 = OptimizerGetBn(opt, mSize);
683 if (dst->a1 == NULL || dst->a2 == NULL || dst->e1 == NULL || dst->e2 == NULL) {
684 BSL_ERR_PUSH_ERROR(CRYPT_BN_OPTIMIZER_GET_FAIL);
685 return CRYPT_BN_OPTIMIZER_GET_FAIL;
686 }
687 int32_t ret = BN_Copy(dst->a1, src->a1);
688 if (ret != CRYPT_SUCCESS) {
689 return ret;
690 }
691 ret = BN_Copy(dst->a2, src->a2);
692 if (ret != CRYPT_SUCCESS) {
693 return ret;
694 }
695 ret = BN_Copy(dst->e1, src->e1);
696 if (ret != CRYPT_SUCCESS) {
697 return ret;
698 }
699 return BN_Copy(dst->e2, src->e2);
700 }
701
702 /* r = (a1 ^ e1) * (a2 ^ e2) mod mont */
BN_MontExpMul(BN_BigNum * r,const BN_BigNum * a1,const BN_BigNum * e1,const BN_BigNum * a2,const BN_BigNum * e2,BN_Mont * mont,BN_Optimizer * opt)703 int32_t BN_MontExpMul(BN_BigNum *r, const BN_BigNum *a1, const BN_BigNum *e1,
704 const BN_BigNum *a2, const BN_BigNum *e2, BN_Mont *mont, BN_Optimizer *opt)
705 {
706 int32_t ret = MontExpMulParaCheck(r, a1, e1, a2, e2, mont, opt);
707 if (ret != CRYPT_SUCCESS) {
708 return ret;
709 }
710 if (BinCmp(a2->data, a2->size, mont->mod, mont->mSize) >= 0 ||
711 BinCmp(a1->data, a1->size, mont->mod, mont->mSize) >= 0) {
712 /* a1 >= mod || a2 >= mod */
713 BSL_ERR_PUSH_ERROR(CRYPT_BN_MONT_BASE_TOO_MAX);
714 return CRYPT_BN_MONT_BASE_TOO_MAX;
715 }
716 if (BN_IsZero(a1) || BN_IsZero(a2)) {
717 return BN_Zeroize(r);
718 }
719 if (BN_IsZero(e1)) {
720 return MontExpCore(r, a2, e2, mont, opt, false);
721 }
722 if (BN_IsZero(e2)) {
723 return MontExpCore(r, a1, e1, mont, opt, false);
724 }
725 ret = OptimizerStart(opt);
726 if (ret != CRYPT_SUCCESS) {
727 BSL_ERR_PUSH_ERROR(ret);
728 return ret;
729 }
730 MontsMulFactor factor;
731 const MontsMulFactor srcFactor = {(BN_BigNum *)(uintptr_t)a1, (BN_BigNum *)(uintptr_t)a2,
732 (BN_BigNum *)(uintptr_t)e1, (BN_BigNum *)(uintptr_t)e2};
733 GOTO_ERR_IF_EX(MontsFactorGetByOptThenCopy(&factor, &srcFactor, mont->mSize, opt), ret);
734 /* field conversion */
735 GOTO_ERR_IF(MontEncBin(factor.a1->data, mont, opt, false), ret);
736 GOTO_ERR_IF(MontEncBin(factor.a2->data, mont, opt, false), ret);
737 /* modular exponentiation */
738 GOTO_ERR_IF_EX(MontExpMul(r->data, factor.a1, factor.e1, factor.a2, factor.e2, mont, opt), ret);
739 /* field conversion */
740 MontDecBin(r->data, mont);
741 r->size = BinFixSize(r->data, mont->mSize);
742 r->sign = false;
743 ERR:
744 OptimizerEnd(opt);
745 return ret;
746 }
747 #endif
748
749 #if defined(HITLS_CRYPTO_RSA)
750
MontMulCore(BN_BigNum * r,const BN_BigNum * a,const BN_BigNum * b,BN_Mont * mont,BN_Optimizer * opt)751 int32_t MontMulCore(BN_BigNum *r, const BN_BigNum *a, const BN_BigNum *b, BN_Mont *mont, BN_Optimizer *opt)
752 {
753 int32_t ret;
754 BN_BigNum *t1 = OptimizerGetBn(opt, mont->mSize);
755 if (t1 == NULL) {
756 BSL_ERR_PUSH_ERROR(CRYPT_BN_OPTIMIZER_GET_FAIL);
757 return CRYPT_BN_OPTIMIZER_GET_FAIL;
758 }
759 BN_COPY_BYTES(t1->data, mont->mSize, a->data, a->size);
760 BN_COPY_BYTES(r->data, mont->mSize, b->data, b->size);
761 GOTO_ERR_IF(MontEncBin(t1->data, mont, opt, false), ret);
762 GOTO_ERR_IF(MontEncBin(r->data, mont, opt, false), ret);
763 GOTO_ERR_IF(MontMulBin(r->data, t1->data, r->data, mont, opt, false), ret);
764 MontDecBin(r->data, mont);
765 r->size = BinFixSize(r->data, mont->mSize);
766 ERR:
767 return ret;
768 }
769
770 #endif // HITLS_CRYPTO_RSA
771
772 #if defined(HITLS_CRYPTO_BN_PRIME)
773
MontSqrCore(BN_BigNum * r,const BN_BigNum * a,BN_Mont * mont,BN_Optimizer * opt)774 int32_t MontSqrCore(BN_BigNum *r, const BN_BigNum *a, BN_Mont *mont, BN_Optimizer *opt)
775 {
776 int32_t ret;
777 BN_COPY_BYTES(r->data, mont->mSize, a->data, a->size);
778 GOTO_ERR_IF(MontEncBin(r->data, mont, opt, false), ret);
779 GOTO_ERR_IF(MontSqrBin(r->data, mont, opt, false), ret);
780 MontDecBin(r->data, mont);
781 r->size = BinFixSize(r->data, mont->mSize);
782 ERR:
783 return ret;
784 }
785
786 #endif // HITLS_CRYPTO_BN_PRIME
787
788 #ifdef HITLS_CRYPTO_CURVE_MONT
789
BnMontEnc(BN_BigNum * r,BN_Mont * mont,BN_Optimizer * opt,bool consttime)790 int32_t BnMontEnc(BN_BigNum *r, BN_Mont *mont, BN_Optimizer *opt, bool consttime)
791 {
792 int32_t ret;
793 GOTO_ERR_IF(MontEncBin(r->data, mont, opt, consttime), ret);
794 r->size = BinFixSize(r->data, mont->mSize);
795 ERR:
796 return ret;
797 }
798
BnMontDec(BN_BigNum * r,BN_Mont * mont)799 void BnMontDec(BN_BigNum *r, BN_Mont *mont)
800 {
801 MontDecBin(r->data, mont);
802 r->size = BinFixSize(r->data, mont->mSize);
803 }
804
BN_EcPrimeMontSqr(BN_BigNum * r,const BN_BigNum * a,void * data,BN_Optimizer * opt)805 int32_t BN_EcPrimeMontSqr(BN_BigNum *r, const BN_BigNum *a, void *data, BN_Optimizer *opt)
806 {
807 if (r == NULL || a == NULL || data == NULL || opt == NULL) {
808 BSL_ERR_PUSH_ERROR((CRYPT_NULL_INPUT));
809 return CRYPT_NULL_INPUT;
810 }
811 int32_t ret;
812 BN_Mont *mont = (BN_Mont *)data;
813 BN_COPY_BYTES(r->data, mont->mSize, a->data, a->size);
814 GOTO_ERR_IF(MontSqrBin(r->data, mont, opt, false), ret);
815 r->size = BinFixSize(r->data, mont->mSize);
816 ERR:
817 return ret;
818 }
819
BN_EcPrimeMontMul(BN_BigNum * r,const BN_BigNum * a,const BN_BigNum * b,void * data,BN_Optimizer * opt)820 int32_t BN_EcPrimeMontMul(BN_BigNum *r, const BN_BigNum *a, const BN_BigNum *b, void *data, BN_Optimizer *opt)
821 {
822 if (r == NULL || a == NULL || b == NULL || data == NULL || opt == NULL) {
823 BSL_ERR_PUSH_ERROR((CRYPT_NULL_INPUT));
824 return CRYPT_NULL_INPUT;
825 }
826 int32_t ret;
827 BN_Mont *mont = (BN_Mont *)data;
828 GOTO_ERR_IF(MontMulBin(r->data, a->data, b->data, mont, opt, false), ret);
829 r->size = BinFixSize(r->data, mont->mSize);
830 ERR:
831 return ret;
832 }
833 #endif // HITLS_CRYPTO_CURVE_MONT
834
835 #endif /* HITLS_CRYPTO_BN */
836