/src/libressl/crypto/bn/bn_print.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* $OpenBSD: bn_print.c,v 1.33 2022/01/20 10:53:33 inoguchi Exp $ */ |
2 | | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 | | * All rights reserved. |
4 | | * |
5 | | * This package is an SSL implementation written |
6 | | * by Eric Young (eay@cryptsoft.com). |
7 | | * The implementation was written so as to conform with Netscapes SSL. |
8 | | * |
9 | | * This library is free for commercial and non-commercial use as long as |
10 | | * the following conditions are aheared to. The following conditions |
11 | | * apply to all code found in this distribution, be it the RC4, RSA, |
12 | | * lhash, DES, etc., code; not just the SSL code. The SSL documentation |
13 | | * included with this distribution is covered by the same copyright terms |
14 | | * except that the holder is Tim Hudson (tjh@cryptsoft.com). |
15 | | * |
16 | | * Copyright remains Eric Young's, and as such any Copyright notices in |
17 | | * the code are not to be removed. |
18 | | * If this package is used in a product, Eric Young should be given attribution |
19 | | * as the author of the parts of the library used. |
20 | | * This can be in the form of a textual message at program startup or |
21 | | * in documentation (online or textual) provided with the package. |
22 | | * |
23 | | * Redistribution and use in source and binary forms, with or without |
24 | | * modification, are permitted provided that the following conditions |
25 | | * are met: |
26 | | * 1. Redistributions of source code must retain the copyright |
27 | | * notice, this list of conditions and the following disclaimer. |
28 | | * 2. Redistributions in binary form must reproduce the above copyright |
29 | | * notice, this list of conditions and the following disclaimer in the |
30 | | * documentation and/or other materials provided with the distribution. |
31 | | * 3. All advertising materials mentioning features or use of this software |
32 | | * must display the following acknowledgement: |
33 | | * "This product includes cryptographic software written by |
34 | | * Eric Young (eay@cryptsoft.com)" |
35 | | * The word 'cryptographic' can be left out if the rouines from the library |
36 | | * being used are not cryptographic related :-). |
37 | | * 4. If you include any Windows specific code (or a derivative thereof) from |
38 | | * the apps directory (application code) you must include an acknowledgement: |
39 | | * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
40 | | * |
41 | | * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
42 | | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
43 | | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
44 | | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
45 | | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
46 | | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
47 | | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
48 | | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
49 | | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
50 | | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
51 | | * SUCH DAMAGE. |
52 | | * |
53 | | * The licence and distribution terms for any publically available version or |
54 | | * derivative of this code cannot be changed. i.e. this code cannot simply be |
55 | | * copied and put under another distribution licence |
56 | | * [including the GNU Public Licence.] |
57 | | */ |
58 | | |
59 | | #include <ctype.h> |
60 | | #include <limits.h> |
61 | | #include <stdio.h> |
62 | | |
63 | | #include <openssl/opensslconf.h> |
64 | | |
65 | | #include <openssl/bio.h> |
66 | | #include <openssl/buffer.h> |
67 | | #include <openssl/err.h> |
68 | | |
69 | | #include "bn_lcl.h" |
70 | | |
71 | | static const char Hex[]="0123456789ABCDEF"; |
72 | | |
73 | | /* Must 'free' the returned data */ |
74 | | char * |
75 | | BN_bn2hex(const BIGNUM *a) |
76 | 3.38k | { |
77 | 3.38k | int i, j, v, z = 0; |
78 | 3.38k | char *buf; |
79 | 3.38k | char *p; |
80 | | |
81 | 3.38k | buf = malloc(BN_is_negative(a) + a->top * BN_BYTES * 2 + 2); |
82 | 3.38k | if (buf == NULL) { |
83 | 0 | BNerror(ERR_R_MALLOC_FAILURE); |
84 | 0 | goto err; |
85 | 0 | } |
86 | 3.38k | p = buf; |
87 | 3.38k | if (BN_is_negative(a)) |
88 | 1.16k | *p++ = '-'; |
89 | 3.38k | if (BN_is_zero(a)) |
90 | 0 | *p++ = '0'; |
91 | 15.9k | for (i = a->top - 1; i >=0; i--) { |
92 | 112k | for (j = BN_BITS2 - 8; j >= 0; j -= 8) { |
93 | | /* strip leading zeros */ |
94 | 100k | v = ((int)(a->d[i] >> (long)j)) & 0xff; |
95 | 100k | if (z || (v != 0)) { |
96 | 82.4k | *p++ = Hex[v >> 4]; |
97 | 82.4k | *p++ = Hex[v & 0x0f]; |
98 | 82.4k | z = 1; |
99 | 82.4k | } |
100 | 100k | } |
101 | 12.5k | } |
102 | 3.38k | *p = '\0'; |
103 | | |
104 | 3.38k | err: |
105 | 3.38k | return (buf); |
106 | 3.38k | } |
107 | | |
108 | | /* Must 'free' the returned data */ |
109 | | char * |
110 | | BN_bn2dec(const BIGNUM *a) |
111 | 15.8k | { |
112 | 15.8k | int i = 0, num, bn_data_num, ok = 0; |
113 | 15.8k | char *buf = NULL; |
114 | 15.8k | char *p; |
115 | 15.8k | BIGNUM *t = NULL; |
116 | 15.8k | BN_ULONG *bn_data = NULL, *lp; |
117 | | |
118 | 15.8k | if (BN_is_zero(a)) { |
119 | 380 | buf = malloc(BN_is_negative(a) + 2); |
120 | 380 | if (buf == NULL) { |
121 | 0 | BNerror(ERR_R_MALLOC_FAILURE); |
122 | 0 | goto err; |
123 | 0 | } |
124 | 380 | p = buf; |
125 | 380 | if (BN_is_negative(a)) |
126 | 0 | *p++ = '-'; |
127 | 380 | *p++ = '0'; |
128 | 380 | *p++ = '\0'; |
129 | 380 | return (buf); |
130 | 380 | } |
131 | | |
132 | | /* get an upper bound for the length of the decimal integer |
133 | | * num <= (BN_num_bits(a) + 1) * log(2) |
134 | | * <= 3 * BN_num_bits(a) * 0.1001 + log(2) + 1 (rounding error) |
135 | | * <= BN_num_bits(a)/10 + BN_num_bits/1000 + 1 + 1 |
136 | | */ |
137 | 15.4k | i = BN_num_bits(a) * 3; |
138 | 15.4k | num = (i / 10 + i / 1000 + 1) + 1; |
139 | 15.4k | bn_data_num = num / BN_DEC_NUM + 1; |
140 | 15.4k | bn_data = reallocarray(NULL, bn_data_num, sizeof(BN_ULONG)); |
141 | 15.4k | buf = malloc(num + 3); |
142 | 15.4k | if ((buf == NULL) || (bn_data == NULL)) { |
143 | 0 | BNerror(ERR_R_MALLOC_FAILURE); |
144 | 0 | goto err; |
145 | 0 | } |
146 | 15.4k | if ((t = BN_dup(a)) == NULL) |
147 | 0 | goto err; |
148 | | |
149 | 38.1k | #define BUF_REMAIN (num+3 - (size_t)(p - buf)) |
150 | 15.4k | p = buf; |
151 | 15.4k | lp = bn_data; |
152 | 15.4k | if (BN_is_negative(t)) |
153 | 12.1k | *p++ = '-'; |
154 | | |
155 | 53.5k | while (!BN_is_zero(t)) { |
156 | 38.1k | if (lp - bn_data >= bn_data_num) |
157 | 0 | goto err; |
158 | 38.1k | *lp = BN_div_word(t, BN_DEC_CONV); |
159 | 38.1k | if (*lp == (BN_ULONG)-1) |
160 | 0 | goto err; |
161 | 38.1k | lp++; |
162 | 38.1k | } |
163 | 15.4k | lp--; |
164 | | /* We now have a series of blocks, BN_DEC_NUM chars |
165 | | * in length, where the last one needs truncation. |
166 | | * The blocks need to be reversed in order. */ |
167 | 15.4k | snprintf(p, BUF_REMAIN, BN_DEC_FMT1, *lp); |
168 | 105k | while (*p) |
169 | 89.7k | p++; |
170 | 38.1k | while (lp != bn_data) { |
171 | 22.6k | lp--; |
172 | 22.6k | snprintf(p, BUF_REMAIN, BN_DEC_FMT2, *lp); |
173 | 453k | while (*p) |
174 | 431k | p++; |
175 | 22.6k | } |
176 | 15.4k | ok = 1; |
177 | | |
178 | 15.4k | err: |
179 | 15.4k | free(bn_data); |
180 | 15.4k | BN_free(t); |
181 | 15.4k | if (!ok && buf) { |
182 | 0 | free(buf); |
183 | 0 | buf = NULL; |
184 | 0 | } |
185 | | |
186 | 15.4k | return (buf); |
187 | 15.4k | } |
188 | | |
189 | | int |
190 | | BN_hex2bn(BIGNUM **bn, const char *a) |
191 | 0 | { |
192 | 0 | BIGNUM *ret = NULL; |
193 | 0 | BN_ULONG l = 0; |
194 | 0 | int neg = 0, h, m, i,j, k, c; |
195 | 0 | int num; |
196 | |
|
197 | 0 | if ((a == NULL) || (*a == '\0')) |
198 | 0 | return (0); |
199 | | |
200 | 0 | if (*a == '-') { |
201 | 0 | neg = 1; |
202 | 0 | a++; |
203 | 0 | } |
204 | |
|
205 | 0 | for (i = 0; i <= (INT_MAX / 4) && isxdigit((unsigned char)a[i]); i++) |
206 | 0 | ; |
207 | 0 | if (i > INT_MAX / 4) |
208 | 0 | goto err; |
209 | | |
210 | 0 | num = i + neg; |
211 | 0 | if (bn == NULL) |
212 | 0 | return (num); |
213 | | |
214 | | /* a is the start of the hex digits, and it is 'i' long */ |
215 | 0 | if (*bn == NULL) { |
216 | 0 | if ((ret = BN_new()) == NULL) |
217 | 0 | return (0); |
218 | 0 | } else { |
219 | 0 | ret = *bn; |
220 | 0 | BN_zero(ret); |
221 | 0 | } |
222 | | |
223 | | /* i is the number of hex digits */ |
224 | 0 | if (bn_expand(ret, i * 4) == NULL) |
225 | 0 | goto err; |
226 | | |
227 | 0 | j = i; /* least significant 'hex' */ |
228 | 0 | m = 0; |
229 | 0 | h = 0; |
230 | 0 | while (j > 0) { |
231 | 0 | m = ((BN_BYTES * 2) <= j) ? (BN_BYTES * 2) : j; |
232 | 0 | l = 0; |
233 | 0 | for (;;) { |
234 | 0 | c = a[j - m]; |
235 | 0 | if ((c >= '0') && (c <= '9')) |
236 | 0 | k = c - '0'; |
237 | 0 | else if ((c >= 'a') && (c <= 'f')) |
238 | 0 | k = c - 'a' + 10; |
239 | 0 | else if ((c >= 'A') && (c <= 'F')) |
240 | 0 | k = c - 'A' + 10; |
241 | 0 | else |
242 | 0 | k = 0; /* paranoia */ |
243 | 0 | l = (l << 4) | k; |
244 | |
|
245 | 0 | if (--m <= 0) { |
246 | 0 | ret->d[h++] = l; |
247 | 0 | break; |
248 | 0 | } |
249 | 0 | } |
250 | 0 | j -= (BN_BYTES * 2); |
251 | 0 | } |
252 | 0 | ret->top = h; |
253 | 0 | bn_correct_top(ret); |
254 | 0 | ret->neg = neg; |
255 | |
|
256 | 0 | *bn = ret; |
257 | 0 | bn_check_top(ret); |
258 | 0 | return (num); |
259 | | |
260 | 0 | err: |
261 | 0 | if (*bn == NULL) |
262 | 0 | BN_free(ret); |
263 | 0 | return (0); |
264 | 0 | } |
265 | | |
266 | | int |
267 | | BN_dec2bn(BIGNUM **bn, const char *a) |
268 | 0 | { |
269 | 0 | BIGNUM *ret = NULL; |
270 | 0 | BN_ULONG l = 0; |
271 | 0 | int neg = 0, i, j; |
272 | 0 | int num; |
273 | |
|
274 | 0 | if ((a == NULL) || (*a == '\0')) |
275 | 0 | return (0); |
276 | 0 | if (*a == '-') { |
277 | 0 | neg = 1; |
278 | 0 | a++; |
279 | 0 | } |
280 | |
|
281 | 0 | for (i = 0; i <= (INT_MAX / 4) && isdigit((unsigned char)a[i]); i++) |
282 | 0 | ; |
283 | 0 | if (i > INT_MAX / 4) |
284 | 0 | goto err; |
285 | | |
286 | 0 | num = i + neg; |
287 | 0 | if (bn == NULL) |
288 | 0 | return (num); |
289 | | |
290 | | /* a is the start of the digits, and it is 'i' long. |
291 | | * We chop it into BN_DEC_NUM digits at a time */ |
292 | 0 | if (*bn == NULL) { |
293 | 0 | if ((ret = BN_new()) == NULL) |
294 | 0 | return (0); |
295 | 0 | } else { |
296 | 0 | ret = *bn; |
297 | 0 | BN_zero(ret); |
298 | 0 | } |
299 | | |
300 | | /* i is the number of digits, a bit of an over expand */ |
301 | 0 | if (bn_expand(ret, i * 4) == NULL) |
302 | 0 | goto err; |
303 | | |
304 | 0 | j = BN_DEC_NUM - (i % BN_DEC_NUM); |
305 | 0 | if (j == BN_DEC_NUM) |
306 | 0 | j = 0; |
307 | 0 | l = 0; |
308 | 0 | while (*a) { |
309 | 0 | l *= 10; |
310 | 0 | l += *a - '0'; |
311 | 0 | a++; |
312 | 0 | if (++j == BN_DEC_NUM) { |
313 | 0 | if (!BN_mul_word(ret, BN_DEC_CONV)) |
314 | 0 | goto err; |
315 | 0 | if (!BN_add_word(ret, l)) |
316 | 0 | goto err; |
317 | 0 | l = 0; |
318 | 0 | j = 0; |
319 | 0 | } |
320 | 0 | } |
321 | 0 | ret->neg = neg; |
322 | |
|
323 | 0 | bn_correct_top(ret); |
324 | 0 | *bn = ret; |
325 | 0 | bn_check_top(ret); |
326 | 0 | return (num); |
327 | | |
328 | 0 | err: |
329 | 0 | if (*bn == NULL) |
330 | 0 | BN_free(ret); |
331 | 0 | return (0); |
332 | 0 | } |
333 | | |
334 | | int |
335 | | BN_asc2bn(BIGNUM **bn, const char *a) |
336 | 0 | { |
337 | 0 | const char *p = a; |
338 | 0 | if (*p == '-') |
339 | 0 | p++; |
340 | |
|
341 | 0 | if (p[0] == '0' && (p[1] == 'X' || p[1] == 'x')) { |
342 | 0 | if (!BN_hex2bn(bn, p + 2)) |
343 | 0 | return 0; |
344 | 0 | } else { |
345 | 0 | if (!BN_dec2bn(bn, p)) |
346 | 0 | return 0; |
347 | 0 | } |
348 | 0 | if (*a == '-') |
349 | 0 | (*bn)->neg = 1; |
350 | 0 | return 1; |
351 | 0 | } |
352 | | |
353 | | #ifndef OPENSSL_NO_BIO |
354 | | int |
355 | | BN_print_fp(FILE *fp, const BIGNUM *a) |
356 | 0 | { |
357 | 0 | BIO *b; |
358 | 0 | int ret; |
359 | |
|
360 | 0 | if ((b = BIO_new(BIO_s_file())) == NULL) |
361 | 0 | return (0); |
362 | 0 | BIO_set_fp(b, fp, BIO_NOCLOSE); |
363 | 0 | ret = BN_print(b, a); |
364 | 0 | BIO_free(b); |
365 | 0 | return (ret); |
366 | 0 | } |
367 | | |
368 | | int |
369 | | BN_print(BIO *bp, const BIGNUM *a) |
370 | 0 | { |
371 | 0 | int i, j, v, z = 0; |
372 | 0 | int ret = 0; |
373 | |
|
374 | 0 | if ((a->neg) && (BIO_write(bp, "-", 1) != 1)) |
375 | 0 | goto end; |
376 | 0 | if (BN_is_zero(a) && (BIO_write(bp, "0", 1) != 1)) |
377 | 0 | goto end; |
378 | 0 | for (i = a->top - 1; i >= 0; i--) { |
379 | 0 | for (j = BN_BITS2 - 4; j >= 0; j -= 4) { |
380 | | /* strip leading zeros */ |
381 | 0 | v = ((int)(a->d[i] >> (long)j)) & 0x0f; |
382 | 0 | if (z || (v != 0)) { |
383 | 0 | if (BIO_write(bp, &(Hex[v]), 1) != 1) |
384 | 0 | goto end; |
385 | 0 | z = 1; |
386 | 0 | } |
387 | 0 | } |
388 | 0 | } |
389 | 0 | ret = 1; |
390 | |
|
391 | 0 | end: |
392 | 0 | return (ret); |
393 | 0 | } |
394 | | #endif |
395 | | |
396 | | char * |
397 | | BN_options(void) |
398 | 0 | { |
399 | 0 | static int init = 0; |
400 | 0 | static char data[16]; |
401 | |
|
402 | 0 | if (!init) { |
403 | 0 | init++; |
404 | | #ifdef BN_LLONG |
405 | | snprintf(data,sizeof data, "bn(%d,%d)", |
406 | | (int)sizeof(BN_ULLONG) * 8, (int)sizeof(BN_ULONG) * 8); |
407 | | #else |
408 | 0 | snprintf(data,sizeof data, "bn(%d,%d)", |
409 | 0 | (int)sizeof(BN_ULONG) * 8, (int)sizeof(BN_ULONG) * 8); |
410 | 0 | #endif |
411 | 0 | } |
412 | 0 | return (data); |
413 | 0 | } |