/src/dropbear/libtommath/bn_mp_read_radix.c
Line | Count | Source (jump to first uncovered line) |
1 | | #include "tommath_private.h" |
2 | | #ifdef BN_MP_READ_RADIX_C |
3 | | /* LibTomMath, multiple-precision integer library -- Tom St Denis */ |
4 | | /* SPDX-License-Identifier: Unlicense */ |
5 | | |
6 | 256 | #define MP_TOUPPER(c) ((((c) >= 'a') && ((c) <= 'z')) ? (((c) + 'A') - 'a') : (c)) |
7 | | |
8 | | /* read a string [ASCII] in a given radix */ |
9 | | mp_err mp_read_radix(mp_int *a, const char *str, int radix) |
10 | 4 | { |
11 | 4 | mp_err err; |
12 | 4 | int y; |
13 | 4 | mp_sign neg; |
14 | 4 | unsigned pos; |
15 | 4 | char ch; |
16 | | |
17 | | /* zero the digit bignum */ |
18 | 4 | mp_zero(a); |
19 | | |
20 | | /* make sure the radix is ok */ |
21 | 4 | if ((radix < 2) || (radix > 64)) { |
22 | 0 | return MP_VAL; |
23 | 0 | } |
24 | | |
25 | | /* if the leading digit is a |
26 | | * minus set the sign to negative. |
27 | | */ |
28 | 4 | if (*str == '-') { |
29 | 0 | ++str; |
30 | 0 | neg = MP_NEG; |
31 | 4 | } else { |
32 | 4 | neg = MP_ZPOS; |
33 | 4 | } |
34 | | |
35 | | /* set the integer to the default of zero */ |
36 | 4 | mp_zero(a); |
37 | | |
38 | | /* process each digit of the string */ |
39 | 260 | while (*str != '\0') { |
40 | | /* if the radix <= 36 the conversion is case insensitive |
41 | | * this allows numbers like 1AB and 1ab to represent the same value |
42 | | * [e.g. in hex] |
43 | | */ |
44 | 256 | ch = (radix <= 36) ? (char)MP_TOUPPER((int)*str) : *str; |
45 | 256 | pos = (unsigned)(ch - '('); |
46 | 256 | if (mp_s_rmap_reverse_sz < pos) { |
47 | 0 | break; |
48 | 0 | } |
49 | 256 | y = (int)mp_s_rmap_reverse[pos]; |
50 | | |
51 | | /* if the char was found in the map |
52 | | * and is less than the given radix add it |
53 | | * to the number, otherwise exit the loop. |
54 | | */ |
55 | 256 | if ((y == 0xff) || (y >= radix)) { |
56 | 0 | break; |
57 | 0 | } |
58 | 256 | if ((err = mp_mul_d(a, (mp_digit)radix, a)) != MP_OKAY) { |
59 | 0 | return err; |
60 | 0 | } |
61 | 256 | if ((err = mp_add_d(a, (mp_digit)y, a)) != MP_OKAY) { |
62 | 0 | return err; |
63 | 0 | } |
64 | 256 | ++str; |
65 | 256 | } |
66 | | |
67 | | /* if an illegal character was found, fail. */ |
68 | 4 | if (!((*str == '\0') || (*str == '\r') || (*str == '\n'))) { |
69 | 0 | mp_zero(a); |
70 | 0 | return MP_VAL; |
71 | 0 | } |
72 | | |
73 | | /* set the sign only if a != 0 */ |
74 | 4 | if (!MP_IS_ZERO(a)) { |
75 | 4 | a->sign = neg; |
76 | 4 | } |
77 | 4 | return MP_OKAY; |
78 | 4 | } |
79 | | #endif |