• 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 <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