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