/src/openssl/crypto/bn/bn_conv.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. |
3 | | * |
4 | | * Licensed under the Apache License 2.0 (the "License"). You may not use |
5 | | * this file except in compliance with the License. You can obtain a copy |
6 | | * in the file LICENSE in the source distribution or at |
7 | | * https://www.openssl.org/source/license.html |
8 | | */ |
9 | | |
10 | | #include <stdio.h> |
11 | | |
12 | | #include <openssl/err.h> |
13 | | #include "crypto/ctype.h" |
14 | | #include "bn_local.h" |
15 | | |
16 | | /* Must 'OPENSSL_free' the returned data */ |
17 | | char *BN_bn2hex(const BIGNUM *a) |
18 | 0 | { |
19 | 0 | int i, j, v, z = 0; |
20 | 0 | char *buf; |
21 | 0 | char *p; |
22 | |
|
23 | 0 | if (BN_is_zero(a)) |
24 | 0 | return OPENSSL_strdup("0"); |
25 | 0 | buf = OPENSSL_malloc(a->top * BN_BYTES * 2 + 2); |
26 | 0 | if (buf == NULL) |
27 | 0 | goto err; |
28 | 0 | p = buf; |
29 | 0 | if (a->neg) |
30 | 0 | *p++ = '-'; |
31 | 0 | for (i = a->top - 1; i >= 0; i--) { |
32 | 0 | for (j = BN_BITS2 - 8; j >= 0; j -= 8) { |
33 | | /* strip leading zeros */ |
34 | 0 | v = (int)((a->d[i] >> j) & 0xff); |
35 | 0 | if (z || v != 0) { |
36 | 0 | p += ossl_to_hex(p, v); |
37 | 0 | z = 1; |
38 | 0 | } |
39 | 0 | } |
40 | 0 | } |
41 | 0 | *p = '\0'; |
42 | 0 | err: |
43 | 0 | return buf; |
44 | 0 | } |
45 | | |
46 | | #ifndef FIPS_MODULE |
47 | | /* No BIO_snprintf in FIPS_MODULE */ |
48 | | /* Must 'OPENSSL_free' the returned data */ |
49 | | char *BN_bn2dec(const BIGNUM *a) |
50 | 0 | { |
51 | 0 | int i = 0, num, ok = 0, n, tbytes; |
52 | 0 | char *buf = NULL; |
53 | 0 | char *p; |
54 | 0 | BIGNUM *t = NULL; |
55 | 0 | BN_ULONG *bn_data = NULL, *lp; |
56 | 0 | int bn_data_num; |
57 | | |
58 | | /*- |
59 | | * get an upper bound for the length of the decimal integer |
60 | | * num <= (BN_num_bits(a) + 1) * log(2) |
61 | | * <= 3 * BN_num_bits(a) * 0.101 + log(2) + 1 (rounding error) |
62 | | * <= 3 * BN_num_bits(a) / 10 + 3 * BN_num_bits / 1000 + 1 + 1 |
63 | | */ |
64 | 0 | i = BN_num_bits(a) * 3; |
65 | 0 | num = (i / 10 + i / 1000 + 1) + 1; |
66 | 0 | tbytes = num + 3; /* negative and terminator and one spare? */ |
67 | 0 | bn_data_num = num / BN_DEC_NUM + 1; |
68 | 0 | bn_data = OPENSSL_malloc_array(bn_data_num, sizeof(BN_ULONG)); |
69 | 0 | buf = OPENSSL_malloc(tbytes); |
70 | 0 | if (buf == NULL || bn_data == NULL) |
71 | 0 | goto err; |
72 | 0 | if ((t = BN_dup(a)) == NULL) |
73 | 0 | goto err; |
74 | | |
75 | 0 | p = buf; |
76 | 0 | lp = bn_data; |
77 | 0 | if (BN_is_zero(t)) { |
78 | 0 | *p++ = '0'; |
79 | 0 | *p++ = '\0'; |
80 | 0 | } else { |
81 | 0 | if (BN_is_negative(t)) |
82 | 0 | *p++ = '-'; |
83 | |
|
84 | 0 | while (!BN_is_zero(t)) { |
85 | 0 | if (lp - bn_data >= bn_data_num) |
86 | 0 | goto err; |
87 | 0 | *lp = BN_div_word(t, BN_DEC_CONV); |
88 | 0 | if (*lp == (BN_ULONG)-1) |
89 | 0 | goto err; |
90 | 0 | lp++; |
91 | 0 | } |
92 | 0 | lp--; |
93 | | /* |
94 | | * We now have a series of blocks, BN_DEC_NUM chars in length, where |
95 | | * the last one needs truncation. The blocks need to be reversed in |
96 | | * order. |
97 | | */ |
98 | 0 | n = snprintf(p, tbytes - (size_t)(p - buf), BN_DEC_FMT1, *lp); |
99 | 0 | if (n < 0 || (size_t)n >= tbytes - (size_t)(p - buf)) |
100 | 0 | goto err; |
101 | 0 | p += n; |
102 | 0 | while (lp != bn_data) { |
103 | 0 | lp--; |
104 | 0 | n = snprintf(p, tbytes - (size_t)(p - buf), BN_DEC_FMT2, *lp); |
105 | 0 | if (n < 0 || (size_t)n >= tbytes - (size_t)(p - buf)) |
106 | 0 | goto err; |
107 | 0 | p += n; |
108 | 0 | } |
109 | 0 | } |
110 | 0 | ok = 1; |
111 | 0 | err: |
112 | 0 | OPENSSL_free(bn_data); |
113 | 0 | BN_free(t); |
114 | 0 | if (ok) |
115 | 0 | return buf; |
116 | 0 | OPENSSL_free(buf); |
117 | 0 | return NULL; |
118 | 0 | } |
119 | | #endif |
120 | | |
121 | | int BN_hex2bn(BIGNUM **bn, const char *a) |
122 | 32 | { |
123 | 32 | BIGNUM *ret = NULL; |
124 | 32 | BN_ULONG l = 0; |
125 | 32 | int neg = 0, h, m, i, j, k, c; |
126 | 32 | int num; |
127 | | |
128 | 32 | if (a == NULL || *a == '\0') |
129 | 0 | return 0; |
130 | | |
131 | 32 | if (*a == '-') { |
132 | 0 | neg = 1; |
133 | 0 | a++; |
134 | 0 | } |
135 | | |
136 | 12.3k | for (i = 0; i <= INT_MAX / 4 && ossl_isxdigit(a[i]); i++) |
137 | 12.2k | continue; |
138 | | |
139 | 32 | if (i == 0 || i > INT_MAX / 4) |
140 | 0 | return 0; |
141 | | |
142 | 32 | num = i + neg; |
143 | 32 | if (bn == NULL) |
144 | 0 | return num; |
145 | | |
146 | | /* a is the start of the hex digits, and it is 'i' long */ |
147 | 32 | if (*bn == NULL) { |
148 | 0 | if ((ret = BN_new()) == NULL) |
149 | 0 | return 0; |
150 | 32 | } else { |
151 | 32 | ret = *bn; |
152 | 32 | if (BN_get_flags(ret, BN_FLG_STATIC_DATA)) { |
153 | 0 | ERR_raise(ERR_LIB_BN, ERR_R_PASSED_INVALID_ARGUMENT); |
154 | 0 | return 0; |
155 | 0 | } |
156 | 32 | BN_zero(ret); |
157 | 32 | } |
158 | | |
159 | | /* i is the number of hex digits */ |
160 | 32 | if (bn_expand(ret, i * 4) == NULL) |
161 | 0 | goto err; |
162 | | |
163 | 32 | j = i; /* least significant 'hex' */ |
164 | 32 | m = 0; |
165 | 32 | h = 0; |
166 | 800 | while (j > 0) { |
167 | 768 | m = (BN_BYTES * 2 <= j) ? BN_BYTES * 2 : j; |
168 | 768 | l = 0; |
169 | 12.2k | for (;;) { |
170 | 12.2k | c = a[j - m]; |
171 | 12.2k | k = OPENSSL_hexchar2int(c); |
172 | 12.2k | if (k < 0) |
173 | 0 | k = 0; /* paranoia */ |
174 | 12.2k | l = (l << 4) | k; |
175 | | |
176 | 12.2k | if (--m <= 0) { |
177 | 768 | ret->d[h++] = l; |
178 | 768 | break; |
179 | 768 | } |
180 | 12.2k | } |
181 | 768 | j -= BN_BYTES * 2; |
182 | 768 | } |
183 | 32 | ret->top = h; |
184 | 32 | bn_correct_top(ret); |
185 | | |
186 | 32 | *bn = ret; |
187 | 32 | bn_check_top(ret); |
188 | | /* Don't set the negative flag if it's zero. */ |
189 | 32 | if (ret->top != 0) |
190 | 32 | ret->neg = neg; |
191 | 32 | return num; |
192 | 0 | err: |
193 | 0 | if (*bn == NULL) |
194 | 0 | BN_free(ret); |
195 | 0 | return 0; |
196 | 32 | } |
197 | | |
198 | | int BN_dec2bn(BIGNUM **bn, const char *a) |
199 | 0 | { |
200 | 0 | BIGNUM *ret = NULL; |
201 | 0 | BN_ULONG l = 0; |
202 | 0 | int neg = 0, i, j; |
203 | 0 | int num; |
204 | |
|
205 | 0 | if (a == NULL || *a == '\0') |
206 | 0 | return 0; |
207 | 0 | if (*a == '-') { |
208 | 0 | neg = 1; |
209 | 0 | a++; |
210 | 0 | } |
211 | |
|
212 | 0 | for (i = 0; i <= INT_MAX / 4 && ossl_isdigit(a[i]); i++) |
213 | 0 | continue; |
214 | |
|
215 | 0 | if (i == 0 || i > INT_MAX / 4) |
216 | 0 | goto err; |
217 | | |
218 | 0 | num = i + neg; |
219 | 0 | if (bn == NULL) |
220 | 0 | return num; |
221 | | |
222 | | /* |
223 | | * a is the start of the digits, and it is 'i' long. We chop it into |
224 | | * BN_DEC_NUM digits at a time |
225 | | */ |
226 | 0 | if (*bn == NULL) { |
227 | 0 | if ((ret = BN_new()) == NULL) |
228 | 0 | return 0; |
229 | 0 | } else { |
230 | 0 | ret = *bn; |
231 | 0 | BN_zero(ret); |
232 | 0 | } |
233 | | |
234 | | /* i is the number of digits, a bit of an over expand */ |
235 | 0 | if (bn_expand(ret, i * 4) == NULL) |
236 | 0 | goto err; |
237 | | |
238 | 0 | j = BN_DEC_NUM - i % BN_DEC_NUM; |
239 | 0 | if (j == BN_DEC_NUM) |
240 | 0 | j = 0; |
241 | 0 | l = 0; |
242 | 0 | while (--i >= 0) { |
243 | 0 | l *= 10; |
244 | 0 | l += *a - '0'; |
245 | 0 | a++; |
246 | 0 | if (++j == BN_DEC_NUM) { |
247 | 0 | if (!BN_mul_word(ret, BN_DEC_CONV) |
248 | 0 | || !BN_add_word(ret, l)) |
249 | 0 | goto err; |
250 | 0 | l = 0; |
251 | 0 | j = 0; |
252 | 0 | } |
253 | 0 | } |
254 | | |
255 | 0 | bn_correct_top(ret); |
256 | 0 | *bn = ret; |
257 | 0 | bn_check_top(ret); |
258 | | /* Don't set the negative flag if it's zero. */ |
259 | 0 | if (ret->top != 0) |
260 | 0 | ret->neg = neg; |
261 | 0 | return num; |
262 | 0 | err: |
263 | 0 | if (*bn == NULL) |
264 | 0 | BN_free(ret); |
265 | 0 | return 0; |
266 | 0 | } |
267 | | |
268 | | int BN_asc2bn(BIGNUM **bn, const char *a) |
269 | 0 | { |
270 | 0 | const char *p = a; |
271 | |
|
272 | 0 | if (*p == '-') |
273 | 0 | p++; |
274 | |
|
275 | 0 | if (p[0] == '0' && (p[1] == 'X' || p[1] == 'x')) { |
276 | 0 | if (!BN_hex2bn(bn, p + 2)) |
277 | 0 | return 0; |
278 | 0 | } else { |
279 | 0 | if (!BN_dec2bn(bn, p)) |
280 | 0 | return 0; |
281 | 0 | } |
282 | | /* Don't set the negative flag if it's zero. */ |
283 | 0 | if (*a == '-' && (*bn)->top != 0) |
284 | 0 | (*bn)->neg = 1; |
285 | 0 | return 1; |
286 | 0 | } |