• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * This file is part of the openHiTLS project.
3  *
4  * openHiTLS is licensed under the Mulan PSL v2.
5  * You can use this software according to the terms and conditions of the Mulan PSL v2.
6  * You may obtain a copy of Mulan PSL v2 at:
7  *
8  *     http://license.coscl.org.cn/MulanPSL2
9  *
10  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11  * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12  * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13  * See the Mulan PSL v2 for more details.
14  */
15 
16 #include "hitls_build.h"
17 #ifdef HITLS_CRYPTO_BN
18 
19 #include "securec.h"
20 #include "bsl_err_internal.h"
21 #include "crypt_errno.h"
22 #include "bn_basic.h"
23 #include "bn_bincal.h"
24 #include "bsl_sal.h"
25 
BN_Bin2Bn(BN_BigNum * r,const uint8_t * bin,uint32_t binLen)26 int32_t BN_Bin2Bn(BN_BigNum *r, const uint8_t *bin, uint32_t binLen)
27 {
28     if (r == NULL || bin == NULL) {
29         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
30         return CRYPT_NULL_INPUT;
31     }
32     (void)BN_Zeroize(r);
33     uint32_t zeroNum = 0;
34     for (; zeroNum < binLen; zeroNum++) {
35         if (bin[zeroNum] != 0) {
36             break;
37         }
38     }
39     if (zeroNum == binLen) {
40         // All data is 0.
41         return CRYPT_SUCCESS;
42     }
43     const uint8_t *base = bin + zeroNum;
44     uint32_t left = binLen - zeroNum;
45     uint32_t needRooms = (left % sizeof(BN_UINT) == 0) ? left / sizeof(BN_UINT)
46                                                     : (left / sizeof(BN_UINT)) + 1;
47     int32_t ret = BnExtend(r, needRooms);
48     if (ret != CRYPT_SUCCESS) {
49         return ret;
50     }
51     uint32_t offset = 0;
52     while (left > 0) {
53         BN_UINT num = 0; // single number
54         uint32_t m = (left >= sizeof(BN_UINT)) ? sizeof(BN_UINT) : left;
55         uint32_t i;
56         for (i = m; i > 0; i--) { // big-endian
57             num = (num << 8) | base[left - i]; // 8: indicates the number of bits in a byte.
58         }
59         r->data[offset++] = num;
60         left -= m;
61     }
62     r->size = BinFixSize(r->data, offset);
63     return CRYPT_SUCCESS;
64 }
65 
66 /* convert BN_UINT to bin */
Limb2Bin(uint8_t * bin,BN_UINT num)67 static inline void Limb2Bin(uint8_t *bin, BN_UINT num)
68 {
69     // convert BN_UINT to bin: buff[0] is the most significant bit.
70     uint32_t i;
71     for (i = 0; i < sizeof(BN_UINT); i++) { // big-endian
72         bin[sizeof(BN_UINT) - i - 1] = (uint8_t)(num >> (8 * i)); // 8: indicates the number of bits in a byte.
73     }
74 }
75 
BN_Bn2Bin(const BN_BigNum * a,uint8_t * bin,uint32_t * binLen)76 int32_t BN_Bn2Bin(const BN_BigNum *a, uint8_t *bin, uint32_t *binLen)
77 {
78     if (a == NULL || bin == NULL || binLen == NULL) {
79         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
80         return CRYPT_NULL_INPUT;
81     }
82     uint32_t bytes = BN_Bytes(a);
83     bytes = (bytes == 0) ? 1 : bytes; // If bytes is 0, 1 byte 0 data needs to be output.
84     if (*binLen < bytes) {
85         BSL_ERR_PUSH_ERROR(CRYPT_BN_BUFF_LEN_NOT_ENOUGH);
86         return CRYPT_BN_BUFF_LEN_NOT_ENOUGH;
87     }
88     int32_t ret = BN_Bn2BinFixZero(a, bin, bytes);
89     if (ret != CRYPT_SUCCESS) {
90         BSL_ERR_PUSH_ERROR(ret);
91         return ret;
92     }
93     *binLen = bytes;
94     return ret;
95 }
96 
BN_FixSize(BN_BigNum * a)97 void BN_FixSize(BN_BigNum *a)
98 {
99     if (a == NULL) {
100         return;
101     }
102     a->size = BinFixSize(a->data, a->size);
103 }
104 
BN_Extend(BN_BigNum * a,uint32_t words)105 int32_t BN_Extend(BN_BigNum *a, uint32_t words)
106 {
107     return BnExtend(a, words);
108 }
109 
110 // Padded 0s before bin to obtain the output data whose length is binLen.
BN_Bn2BinFixZero(const BN_BigNum * a,uint8_t * bin,uint32_t binLen)111 int32_t BN_Bn2BinFixZero(const BN_BigNum *a, uint8_t *bin, uint32_t binLen)
112 {
113     if (a == NULL || bin == NULL || binLen == 0) {
114         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
115         return CRYPT_NULL_INPUT;
116     }
117     uint32_t bytes = BN_Bytes(a);
118     if (binLen < bytes) {
119         BSL_ERR_PUSH_ERROR(CRYPT_BN_BUFF_LEN_NOT_ENOUGH);
120         return CRYPT_BN_BUFF_LEN_NOT_ENOUGH;
121     }
122     uint32_t fixLen = binLen - bytes;
123     uint8_t *base = bin + fixLen;
124     (void)memset_s(bin, binLen, 0, fixLen);
125     if (bytes == 0) {
126         return CRYPT_SUCCESS;
127     }
128 
129     uint32_t index = a->size - 1;
130     uint32_t left = bytes % sizeof(BN_UINT); // High-order non-integrated data
131     uint32_t offset = 0;
132     while (left != 0) {
133         base[offset] = (uint8_t)((a->data[index] >> (8 * (left - 1))) & 0xFF); // 1byte = 8bit
134         left--;
135         offset++;
136     }
137     if (offset != 0) {
138         index--;
139     }
140     uint32_t num = bytes / sizeof(BN_UINT); // High-order non-integrated data
141 
142     // Cyclically parse the entire data block.
143     for (uint32_t i = 0; i < num; i++) {
144         Limb2Bin(base + offset, a->data[index]);
145         index--;
146         offset += sizeof(BN_UINT);
147     }
148 
149     return CRYPT_SUCCESS;
150 }
151 
152 #if defined(HITLS_CRYPTO_CURVE_SM2_ASM) ||                                                 \
153     ((defined(HITLS_CRYPTO_CURVE_NISTP521) || defined(HITLS_CRYPTO_CURVE_NISTP384_ASM)) && \
154         defined(HITLS_CRYPTO_NIST_USE_ACCEL))
155 /* Convert BigNum to a 64-bit array in little-endian order. */
BN_Bn2U64Array(const BN_BigNum * a,uint64_t * array,uint32_t * len)156 int32_t BN_Bn2U64Array(const BN_BigNum *a, uint64_t *array, uint32_t *len)
157 {
158     // Number of BN_UINTs that can be accommodated
159     const uint64_t capacity = ((uint64_t)(*len)) * (sizeof(uint64_t) / sizeof(BN_UINT));
160     if (a->size > capacity || *len == 0) {
161         BSL_ERR_PUSH_ERROR(CRYPT_BN_SPACE_NOT_ENOUGH);
162         return CRYPT_BN_SPACE_NOT_ENOUGH;
163     }
164     if (BN_IsZero(a)) {
165         *len = 1;
166         array[0] = 0;
167         return CRYPT_SUCCESS;
168     }
169     // BN_UINT is 64-bit or 32-bit. Select one during compilation.
170     if (sizeof(BN_UINT) == sizeof(uint64_t)) {
171         uint32_t i = 0;
172         for (; i < a->size; i++) {
173             array[i] = a->data[i];
174         }
175         *len = i;
176     }
177     if (sizeof(BN_UINT) == sizeof(uint32_t)) {
178         uint32_t i = 0;
179         uint32_t j = 0;
180         for (; i < a->size - 1; i += 2) { // processes 2 BN_UINT each time. Here, a->size >= 1
181             array[j] = a->data[i];
182             array[j] |= ((uint64_t)a->data[i + 1]) << 32; // in the upper 32 bits
183             j++;
184         }
185         // When a->size is an odd number, process the tail.
186         if (i < a->size) {
187             array[j++] = a->data[i];
188         }
189         *len = j;
190     }
191     return CRYPT_SUCCESS;
192 }
193 
194 /* Convert a 64-bit array in little-endian order to a BigNum. */
BN_U64Array2Bn(BN_BigNum * r,const uint64_t * array,uint32_t len)195 int32_t BN_U64Array2Bn(BN_BigNum *r, const uint64_t *array, uint32_t len)
196 {
197     const uint64_t needRoom = ((uint64_t)len) * sizeof(uint64_t) / sizeof(BN_UINT);
198     if (r == NULL || array == NULL) {
199         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
200         return CRYPT_NULL_INPUT;
201     }
202     if (needRoom > UINT32_MAX) {
203         BSL_ERR_PUSH_ERROR(CRYPT_BN_BITS_TOO_MAX);
204         return CRYPT_BN_BITS_TOO_MAX;
205     }
206     int32_t ret = BnExtend(r, (uint32_t)needRoom);
207     if (ret != CRYPT_SUCCESS) {
208         return ret;
209     }
210 
211     (void)BN_Zeroize(r);
212     // BN_UINT is 64-bit or 32-bit. Select one during compilation.
213     if (sizeof(BN_UINT) == sizeof(uint64_t)) {
214         for (uint32_t i = 0; i < needRoom; i++) {
215             r->data[i] = array[i];
216         }
217     }
218     if (sizeof(BN_UINT) == sizeof(uint32_t)) {
219         for (uint64_t i = 0; i < len; i++) {
220             r->data[i * 2] = (BN_UINT)array[i]; // uint64_t is twice the width of uint32_t.
221             // obtain the upper 32 bits, uint64_t is twice the width of uint32_t.
222             r->data[i * 2 + 1] = (BN_UINT)(array[i] >> 32);
223         }
224     }
225     // can be forcibly converted to 32 bits because needRoom <= r->room
226     r->size = BinFixSize(r->data, (uint32_t)needRoom);
227     return CRYPT_SUCCESS;
228 }
229 #endif
230 
231 #if defined(HITLS_CRYPTO_CURVE_SM2_ASM) || (defined(HITLS_CRYPTO_CURVE_NISTP256_ASM) && \
232     defined(HITLS_CRYPTO_NIST_USE_ACCEL))
BN_BN2Array(const BN_BigNum * src,BN_UINT * dst,uint32_t size)233 int32_t BN_BN2Array(const BN_BigNum *src, BN_UINT *dst, uint32_t size)
234 {
235     if (size < src->size) {
236         BSL_ERR_PUSH_ERROR(CRYPT_BN_BUFF_LEN_NOT_ENOUGH);
237         return CRYPT_BN_BUFF_LEN_NOT_ENOUGH;
238     }
239 
240     (void)memset_s(dst, size * sizeof(BN_UINT), 0, size * sizeof(BN_UINT));
241     for (uint32_t i = 0; i < src->size; i++) {
242         dst[i] = src->data[i];
243     }
244     return CRYPT_SUCCESS;
245 }
246 
BN_Array2BN(BN_BigNum * dst,const BN_UINT * src,const uint32_t size)247 int32_t BN_Array2BN(BN_BigNum *dst, const BN_UINT *src, const uint32_t size)
248 {
249     int32_t ret = BnExtend(dst, size);
250     if (ret != CRYPT_SUCCESS) {
251         return ret;
252     }
253     // No error code is returned because the src has been checked NULL.
254     (void)BN_Zeroize(dst);
255     for (uint32_t i = 0; i < size; i++) {
256         dst->data[i] = src[i];
257     }
258     dst->size = BinFixSize(dst->data, size);
259     return CRYPT_SUCCESS;
260 }
261 #endif
262 
263 #ifdef HITLS_CRYPTO_BN_STR_CONV
264 
265 static const char HEX_MAP[] = "0123456789ABCDEF"; // Hexadecimal value corresponding to 0-15
266 
267 #define BITS_OF_NUM 4
268 #define BITS_OF_BYTE 8
269 
IsXdigit(const char str,bool isHex)270 static bool IsXdigit(const char str, bool isHex)
271 {
272     if ((str >= '0') && (str <= '9')) {
273         return true;
274     }
275     if (isHex) {
276         if ((str >= 'A') && (str <= 'F')) {
277             return true;
278         }
279         if ((str >= 'a') && (str <= 'f')) {
280             return true;
281         }
282     }
283     return false;
284 }
285 
StrToHex(char str)286 static unsigned char StrToHex(char str)
287 {
288     if ((str >= '0') && (str <= '9')) {
289         return (unsigned char)(str - '0');
290     }
291     if ((str >= 'A') && (str <= 'F')) {
292         return (unsigned char)(str - 'A' + 10); // Hexadecimal. A~F offset 10
293     }
294     if ((str >= 'a') && (str <= 'f')) {
295         return (unsigned char)(str - 'a' + 10); // Hexadecimal. a~f offset 10
296     }
297     return 0x00; // Unexpected character string, which is processed as 0.
298 }
299 
CheckInputStr(int32_t * outLen,const char * str,int32_t * negtive,bool isHex)300 static int32_t CheckInputStr(int32_t *outLen, const char *str, int32_t *negtive, bool isHex)
301 {
302     int32_t len = 0;
303     int32_t strMax = BN_MAX_BITS / BITS_OF_NUM; // BigNum storage limit: 2^29 bits
304     const char *inputStr = str;
305 
306     if (str[0] == '\0') {
307         BSL_ERR_PUSH_ERROR(CRYPT_BN_CONVERT_INPUT_INVALID);
308         return CRYPT_BN_CONVERT_INPUT_INVALID;
309     }
310     if (str[0] == '-') {
311         *negtive = 1;
312         inputStr++;
313     }
314 
315     int32_t initStrLen = strlen(inputStr);
316     if (initStrLen == 0 || initStrLen > strMax) {
317         BSL_ERR_PUSH_ERROR(CRYPT_BN_CONVERT_INPUT_INVALID);
318         return CRYPT_BN_CONVERT_INPUT_INVALID;
319     }
320     while (len < initStrLen) {
321         if (!IsXdigit(inputStr[len++], isHex)) { // requires that the entire content of a character string must be valid
322             BSL_ERR_PUSH_ERROR(CRYPT_BN_CONVERT_INPUT_INVALID);
323             return CRYPT_BN_CONVERT_INPUT_INVALID;
324         }
325     }
326     *outLen = len;
327 
328     return CRYPT_SUCCESS;
329 }
330 
OutputCheck(BN_BigNum ** r,int32_t num)331 static int32_t OutputCheck(BN_BigNum **r, int32_t num)
332 {
333     uint32_t needBits = (uint32_t)num * BITS_OF_NUM;
334     if (*r == NULL) {
335         *r = BN_Create(needBits);
336         if (*r == NULL) {
337             BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
338             return CRYPT_MEM_ALLOC_FAIL;
339         }
340     } else {
341         int32_t ret = BnExtend(*r, BITS_TO_BN_UNIT(needBits));
342         if (ret != CRYPT_SUCCESS) {
343             return ret;
344         }
345         (void)BN_Zeroize(*r);
346     }
347     return CRYPT_SUCCESS;
348 }
349 
BN_Hex2Bn(BN_BigNum ** r,const char * str)350 int32_t BN_Hex2Bn(BN_BigNum **r, const char *str)
351 {
352     int32_t ret;
353     int32_t len;
354     int32_t negtive = 0;
355     if (r == NULL || str == NULL) {
356         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
357         return CRYPT_NULL_INPUT;
358     }
359     const char *inputStr = str;
360     ret = CheckInputStr(&len, inputStr, &negtive, true);
361     if (ret != CRYPT_SUCCESS) {
362         BSL_ERR_PUSH_ERROR(ret);
363         return ret;
364     }
365 
366     ret = OutputCheck(r, len);
367     if (ret != CRYPT_SUCCESS) {
368         BSL_ERR_PUSH_ERROR(ret);
369         return ret;
370     }
371 
372     BN_UINT *p = (*r)->data;
373     if (negtive != 0) {
374         inputStr++;
375     }
376     int32_t unitBytes;
377     uint32_t tmpval = 0;
378     uint32_t size = 0; // Record the size that r will use.
379     int32_t bytes = sizeof(BN_UINT);
380     BN_UINT unitValue;
381     while (len > 0) {
382         unitBytes = (bytes * 2 <= len) ? bytes * 2 : len; // Prevents the number of char left being less than bytes *2
383         unitValue = 0;
384         for (; unitBytes > 0; unitBytes--) {
385             // interface ensures that all characters are valid at the begining
386             tmpval = StrToHex(inputStr[len - unitBytes]);
387             unitValue = (unitValue << 4) | tmpval; // The upper bits are shifted rightwards by 4 bits each time.
388         }
389         p[size++] = unitValue;
390         len -= bytes * 2; // Length of the character stream processed each time = Number of bytes x 2
391     }
392     (*r)->size = BinFixSize(p, size);
393     if (!BN_IsZero(*r)) {
394         (*r)->sign = negtive;
395     }
396     return CRYPT_SUCCESS;
397 }
398 
BN_Bn2Hex(const BN_BigNum * a)399 char *BN_Bn2Hex(const BN_BigNum *a)
400 {
401     uint32_t bytes = sizeof(BN_UINT);
402     if (a == NULL) {
403         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
404         return NULL;
405     }
406     // output character stream = Number of bytes x 2 + minus sign + terminator
407     char *ret = (char *)BSL_SAL_Malloc(a->size * bytes * 2 + 2);
408     if (ret == NULL) {
409         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
410         return NULL;
411     }
412 
413     char *p = ret;
414     if (BN_IsZero(a)) {
415         *p++ = '0';
416         *p++ = '\0';
417         return ret;
418     }
419     if (a->sign) {
420         *p++ = '-';
421     }
422     bool leadingZeros = true;
423     for (int32_t i = a->size - 1; i >= 0; i--) {
424         // processes data in a group of 8 bits
425         for (int32_t j = (int32_t)(bytes * BITS_OF_BYTE - BITS_OF_BYTE); j >= 0; j -= 8) {
426             uint32_t chars = (uint32_t)((a->data[i] >> (uint32_t)j) & 0xFF); // Take the last eight bits.
427             if (leadingZeros && (chars == 0)) {
428                 continue;
429             }
430             *p++ = HEX_MAP[chars >> 4]; // Higher 4 bits
431             *p++ = HEX_MAP[chars & 0x0F]; // Lower 4 bits
432             leadingZeros = false;
433         }
434     }
435     *p = '\0';
436     return ret;
437 }
438 
CalBnData(BN_BigNum ** r,int32_t num,const char * inputStr)439 static int32_t CalBnData(BN_BigNum **r, int32_t num, const char *inputStr)
440 {
441     int32_t ret = CRYPT_INVALID_ARG;
442     int32_t optTimes;
443     int32_t len = num;
444     const char *p = inputStr;
445     BN_UINT unitValue = 0;
446     /*
447      * Processes decimal strings in groups of BN_DEC_LEN.
448      * If the length of a string is not a multiple of BN_DEC_LEN, then in the first round of string processing,
449        handle according to the actual length of less than BN_DEC_LEN
450      */
451     optTimes = (len % BN_DEC_LEN == 0) ? 0 : (BN_DEC_LEN - len % BN_DEC_LEN);
452     while (len > 0) {
453         // keep the upper limit of each round of traversal as BN_DEC_LEN
454         for (; optTimes < BN_DEC_LEN; optTimes++, len--) {
455             unitValue *= 10; // A decimal number is multiplied by 10 and then added.
456             unitValue += *p - '0';
457             p++;
458         }
459 
460         ret = BN_MulLimb(*r, *r, BN_DEC_VAL);
461         if (ret != CRYPT_SUCCESS) {
462             BSL_ERR_PUSH_ERROR(ret);
463             goto ERR;
464         }
465 
466         ret = BN_AddLimb(*r, *r, unitValue);
467         if (ret != CRYPT_SUCCESS) {
468             BSL_ERR_PUSH_ERROR(ret);
469             goto ERR;
470         }
471         unitValue = 0;
472         optTimes = 0;
473     }
474 
475 ERR:
476     return ret;
477 }
478 
BN_Dec2Bn(BN_BigNum ** r,const char * str)479 int32_t BN_Dec2Bn(BN_BigNum **r, const char *str)
480 {
481     int32_t ret;
482     int32_t num;
483     int32_t negtive = 0;
484     if (r == NULL || str == NULL) {
485         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
486         return CRYPT_NULL_INPUT;
487     }
488     const char *inputStr = str;
489     ret = CheckInputStr(&num, inputStr, &negtive, false);
490     if (ret != CRYPT_SUCCESS) {
491         BSL_ERR_PUSH_ERROR(ret);
492         return ret;
493     }
494 
495     ret = OutputCheck(r, num);
496     if (ret != CRYPT_SUCCESS) {
497         BSL_ERR_PUSH_ERROR(ret);
498         return ret;
499     }
500 
501     if (negtive != 0) {
502         inputStr++;
503     }
504     ret = CalBnData(r, num, inputStr);
505     if (ret != CRYPT_SUCCESS) {
506         BSL_ERR_PUSH_ERROR(ret);
507         return ret;
508     }
509 
510     if (!BN_IsZero(*r)) {
511         (*r)->sign = negtive;
512     }
513     return ret;
514 }
515 
CalDecStr(const BN_BigNum * a,BN_UINT * bnInit,uint32_t unitNum,uint32_t * step)516 static int32_t CalDecStr(const BN_BigNum *a, BN_UINT *bnInit, uint32_t unitNum, uint32_t *step)
517 {
518     int32_t ret = CRYPT_INVALID_ARG;
519     BN_UINT *valNow = bnInit;
520     uint32_t index = 0;
521     BN_BigNum *bnDup = BN_Dup(a);
522     if (bnDup == NULL) {
523         ret = CRYPT_MEM_ALLOC_FAIL;
524         goto ERR;
525     }
526 
527     while (!BN_IsZero(bnDup)) {
528         BN_UINT rem;
529         // index records the amount of BN_UINT offset, cannot exceed the maximum value unitNum
530         if (index == unitNum) {
531             ret = CRYPT_SECUREC_FAIL;
532             goto ERR;
533         }
534         ret = BN_DivLimb(bnDup, &rem, bnDup, BN_DEC_VAL);
535         if (ret != CRYPT_SUCCESS) {
536             goto ERR;
537         }
538         valNow[index++] = rem;
539     }
540     (*step) = index - 1;
541 ERR:
542     BN_Destroy(bnDup);
543     return ret;
544 }
545 
NumToStr(char * output,uint32_t * restLen,BN_UINT valNow,bool isNeedPad,uint32_t * printNum)546 static int32_t NumToStr(char *output, uint32_t *restLen, BN_UINT valNow, bool isNeedPad, uint32_t *printNum)
547 {
548     BN_UINT num = valNow;
549     char *target = output;
550     uint32_t len = 0;
551     do {
552         if (*restLen < len + 1) {
553             BSL_ERR_PUSH_ERROR(CRYPT_BN_BUFF_LEN_NOT_ENOUGH);
554             return CRYPT_BN_BUFF_LEN_NOT_ENOUGH;
555         }
556         // The ASCII code of 0 to 9 is [48, 57]
557         target[len++] = num % 10 + 48; // Take last num by mod 10, and convet to 'char'.
558         num /= 10; // for taken the last digit by dividing 10
559     } while (num != 0);
560 
561     if (isNeedPad) {
562         if (*restLen < BN_DEC_LEN) {
563             BSL_ERR_PUSH_ERROR(CRYPT_BN_BUFF_LEN_NOT_ENOUGH);
564             return CRYPT_BN_BUFF_LEN_NOT_ENOUGH;
565         }
566         while (len < BN_DEC_LEN) {
567             target[len++] = '0';
568         }
569     }
570 
571     // Symmetrically swapped values at both ends, needs len / 2 times.
572     for (uint32_t j = 0; j < len / 2; j++) {
573         char t = target[j];
574         target[j] = target[len - 1 - j];
575         target[len - 1 - j] = t;
576     }
577     *restLen -= len;
578     *printNum = len;
579     return CRYPT_SUCCESS;
580 }
581 
FmtDecOutput(char * output,uint32_t outLen,const BN_UINT * bnInit,uint32_t steps)582 static int32_t FmtDecOutput(char *output, uint32_t outLen, const BN_UINT *bnInit, uint32_t steps)
583 {
584     uint32_t cpyNum = 0;
585     char *outputPtr = output;
586     uint32_t index = steps;
587     uint32_t restLen = outLen - 1; // Reserve the position of the terminator.
588     int32_t ret = NumToStr(outputPtr, &restLen, *(bnInit + index), false, &cpyNum);
589     if (ret != CRYPT_SUCCESS) {
590         return ret;
591     }
592     outputPtr += cpyNum;
593     while (index-- != 0) {
594         ret = NumToStr(outputPtr, &restLen, *(bnInit + index), true, &cpyNum);
595         if (ret != CRYPT_SUCCESS) {
596             return ret;
597         }
598         outputPtr += cpyNum;
599     }
600     *outputPtr = '\0';
601     return CRYPT_SUCCESS;
602 }
603 
BN_Bn2Dec(const BN_BigNum * a)604 char *BN_Bn2Dec(const BN_BigNum *a)
605 {
606     if (a == NULL) {
607         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
608         return NULL;
609     }
610     int32_t ret;
611     char *p = NULL;
612     uint32_t steps = 0;
613     /*
614      * Estimate the maximum length of a decimal BigNum
615      * x <= 10 ^ y < 2 ^ (bit + 1)
616      * y < lg_(2) ( 2 ^ (bit + 1))
617      * y < (bit + 1) * lg2 -- (lg_2 = 0.30102999566...)
618      * y < (bit + 1) * 0.303
619      * y < 3 * bit * 0.001 +  3 * bit * 0.100 + 1
620      */
621     uint32_t numLen = (BN_Bits(a) * 3) / 10 + (BN_Bits(a) * 3) / 1000 + 1;
622     uint32_t outLen = numLen + 3; // Add the sign, end symbol, and buffer space.
623     uint32_t unitNum = (numLen / BN_DEC_LEN) + 1;
624     char *result = BSL_SAL_Malloc(outLen);
625     BN_UINT *bnInit = (BN_UINT *)BSL_SAL_Malloc(unitNum * sizeof(BN_UINT));
626     if (result == NULL || bnInit == NULL) {
627         ret = CRYPT_MEM_ALLOC_FAIL;
628         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
629         goto ERR;
630     }
631 
632     p = result;
633     if (BN_IsZero(a)) {
634         *p++ = '0';
635         *p++ = '\0';
636         ret = CRYPT_SUCCESS;
637         goto ERR;
638     }
639 
640     if (a->sign) {
641         *p++ = '-';
642         outLen--;
643     }
644     ret = CalDecStr(a, bnInit, unitNum, &steps);
645     if (ret != CRYPT_SUCCESS) {
646         BSL_ERR_PUSH_ERROR(ret);
647         goto ERR;
648     }
649     ret = FmtDecOutput(p, outLen, bnInit, steps);
650     if (ret != CRYPT_SUCCESS) {
651         BSL_ERR_PUSH_ERROR(ret);
652         goto ERR;
653     }
654 
655 ERR:
656     BSL_SAL_FREE(bnInit);
657     if (ret == CRYPT_SUCCESS) {
658         return result;
659     }
660     BSL_SAL_FREE(result);
661     return NULL;
662 }
663 #endif /* HITLS_CRYPTO_BN_STR_CONV */
664 
665 #endif /* HITLS_CRYPTO_BN */
666