Undo commit d420ac2
[openssl.git] / crypto / bn / bn_print.c
1 /*
2  * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the OpenSSL license (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 #include <ctype.h>
12 #include <limits.h>
13 #include "internal/cryptlib.h"
14 #include <openssl/buffer.h>
15 #include "bn_lcl.h"
16
17 static const char Hex[] = "0123456789ABCDEF";
18
19 /* Must 'OPENSSL_free' the returned data */
20 char *BN_bn2hex(const BIGNUM *a)
21 {
22     int i, j, v, z = 0;
23     char *buf;
24     char *p;
25
26     if (BN_is_zero(a))
27         return OPENSSL_strdup("0");
28     buf = OPENSSL_malloc(a->top * BN_BYTES * 2 + 2);
29     if (buf == NULL) {
30         BNerr(BN_F_BN_BN2HEX, ERR_R_MALLOC_FAILURE);
31         goto err;
32     }
33     p = buf;
34     if (a->neg)
35         *(p++) = '-';
36     for (i = a->top - 1; i >= 0; i--) {
37         for (j = BN_BITS2 - 8; j >= 0; j -= 8) {
38             /* strip leading zeros */
39             v = ((int)(a->d[i] >> (long)j)) & 0xff;
40             if (z || (v != 0)) {
41                 *(p++) = Hex[v >> 4];
42                 *(p++) = Hex[v & 0x0f];
43                 z = 1;
44             }
45         }
46     }
47     *p = '\0';
48  err:
49     return (buf);
50 }
51
52 /* Must 'OPENSSL_free' the returned data */
53 char *BN_bn2dec(const BIGNUM *a)
54 {
55     int i = 0, num, ok = 0;
56     char *buf = NULL;
57     char *p;
58     BIGNUM *t = NULL;
59     BN_ULONG *bn_data = NULL, *lp;
60     int bn_data_num;
61
62     /*-
63      * get an upper bound for the length of the decimal integer
64      * num <= (BN_num_bits(a) + 1) * log(2)
65      *     <= 3 * BN_num_bits(a) * 0.101 + log(2) + 1     (rounding error)
66      *     <= 3 * BN_num_bits(a) / 10 + 3 * BN_num_bits / 1000 + 1 + 1
67      */
68     i = BN_num_bits(a) * 3;
69     num = (i / 10 + i / 1000 + 1) + 1;
70     bn_data_num = num / BN_DEC_NUM + 1;
71     bn_data = OPENSSL_malloc(bn_data_num * sizeof(BN_ULONG));
72     buf = OPENSSL_malloc(num + 3);
73     if ((buf == NULL) || (bn_data == NULL)) {
74         BNerr(BN_F_BN_BN2DEC, ERR_R_MALLOC_FAILURE);
75         goto err;
76     }
77     if ((t = BN_dup(a)) == NULL)
78         goto err;
79
80     p = buf;
81     lp = bn_data;
82     if (BN_is_zero(t)) {
83         *(p++) = '0';
84         *(p++) = '\0';
85     } else {
86         if (BN_is_negative(t))
87             *p++ = '-';
88
89         while (!BN_is_zero(t)) {
90             if (lp - bn_data >= bn_data_num)
91                 goto err;
92             *lp = BN_div_word(t, BN_DEC_CONV);
93             if (*lp == (BN_ULONG)-1)
94                 goto err;
95             lp++;
96         }
97         lp--;
98         /*
99          * We now have a series of blocks, BN_DEC_NUM chars in length, where
100          * the last one needs truncation. The blocks need to be reversed in
101          * order.
102          */
103         sprintf(p, BN_DEC_FMT1, *lp);
104         while (*p)
105             p++;
106         while (lp != bn_data) {
107             lp--;
108             sprintf(p, BN_DEC_FMT2, *lp);
109             while (*p)
110                 p++;
111         }
112     }
113     ok = 1;
114  err:
115     OPENSSL_free(bn_data);
116     BN_free(t);
117     if (ok)
118         return buf;
119     OPENSSL_free(buf);
120     return NULL;
121 }
122
123 int BN_hex2bn(BIGNUM **bn, const char *a)
124 {
125     BIGNUM *ret = NULL;
126     BN_ULONG l = 0;
127     int neg = 0, h, m, i, j, k, c;
128     int num;
129
130     if ((a == NULL) || (*a == '\0'))
131         return (0);
132
133     if (*a == '-') {
134         neg = 1;
135         a++;
136     }
137
138     for (i = 0; i <= (INT_MAX/4) && isxdigit((unsigned char)a[i]); i++)
139         continue;
140
141     if (i == 0 || i > INT_MAX/4)
142         goto err;
143
144     num = i + neg;
145     if (bn == NULL)
146         return (num);
147
148     /* a is the start of the hex digits, and it is 'i' long */
149     if (*bn == NULL) {
150         if ((ret = BN_new()) == NULL)
151             return (0);
152     } else {
153         ret = *bn;
154         BN_zero(ret);
155     }
156
157     /* i is the number of hex digits */
158     if (bn_expand(ret, i * 4) == NULL)
159         goto err;
160
161     j = i;                      /* least significant 'hex' */
162     m = 0;
163     h = 0;
164     while (j > 0) {
165         m = ((BN_BYTES * 2) <= j) ? (BN_BYTES * 2) : j;
166         l = 0;
167         for (;;) {
168             c = a[j - m];
169             k = OPENSSL_hexchar2int(c);
170             if (k < 0)
171                 k = 0;          /* paranoia */
172             l = (l << 4) | k;
173
174             if (--m <= 0) {
175                 ret->d[h++] = l;
176                 break;
177             }
178         }
179         j -= (BN_BYTES * 2);
180     }
181     ret->top = h;
182     bn_correct_top(ret);
183
184     *bn = ret;
185     bn_check_top(ret);
186     /* Don't set the negative flag if it's zero. */
187     if (ret->top != 0)
188         ret->neg = neg;
189     return (num);
190  err:
191     if (*bn == NULL)
192         BN_free(ret);
193     return (0);
194 }
195
196 int BN_dec2bn(BIGNUM **bn, const char *a)
197 {
198     BIGNUM *ret = NULL;
199     BN_ULONG l = 0;
200     int neg = 0, i, j;
201     int num;
202
203     if ((a == NULL) || (*a == '\0'))
204         return (0);
205     if (*a == '-') {
206         neg = 1;
207         a++;
208     }
209
210     for (i = 0; i <= (INT_MAX/4) && isdigit((unsigned char)a[i]); i++)
211         continue;
212
213     if (i == 0 || i > INT_MAX/4)
214         goto err;
215
216     num = i + neg;
217     if (bn == NULL)
218         return (num);
219
220     /*
221      * a is the start of the digits, and it is 'i' long. We chop it into
222      * BN_DEC_NUM digits at a time
223      */
224     if (*bn == NULL) {
225         if ((ret = BN_new()) == NULL)
226             return (0);
227     } else {
228         ret = *bn;
229         BN_zero(ret);
230     }
231
232     /* i is the number of digits, a bit of an over expand */
233     if (bn_expand(ret, i * 4) == NULL)
234         goto err;
235
236     j = BN_DEC_NUM - (i % BN_DEC_NUM);
237     if (j == BN_DEC_NUM)
238         j = 0;
239     l = 0;
240     while (--i >= 0) {
241         l *= 10;
242         l += *a - '0';
243         a++;
244         if (++j == BN_DEC_NUM) {
245             if (!BN_mul_word(ret, BN_DEC_CONV)
246                 || !BN_add_word(ret, l))
247                 goto err;
248             l = 0;
249             j = 0;
250         }
251     }
252
253     bn_correct_top(ret);
254     *bn = ret;
255     bn_check_top(ret);
256     /* Don't set the negative flag if it's zero. */
257     if (ret->top != 0)
258         ret->neg = neg;
259     return (num);
260  err:
261     if (*bn == NULL)
262         BN_free(ret);
263     return (0);
264 }
265
266 int BN_asc2bn(BIGNUM **bn, const char *a)
267 {
268     const char *p = a;
269
270     if (*p == '-')
271         p++;
272
273     if (p[0] == '0' && (p[1] == 'X' || p[1] == 'x')) {
274         if (!BN_hex2bn(bn, p + 2))
275             return 0;
276     } else {
277         if (!BN_dec2bn(bn, p))
278             return 0;
279     }
280     /* Don't set the negative flag if it's zero. */
281     if (*a == '-' && (*bn)->top != 0)
282         (*bn)->neg = 1;
283     return 1;
284 }
285
286 # ifndef OPENSSL_NO_STDIO
287 int BN_print_fp(FILE *fp, const BIGNUM *a)
288 {
289     BIO *b;
290     int ret;
291
292     if ((b = BIO_new(BIO_s_file())) == NULL)
293         return (0);
294     BIO_set_fp(b, fp, BIO_NOCLOSE);
295     ret = BN_print(b, a);
296     BIO_free(b);
297     return (ret);
298 }
299 # endif
300
301 int BN_print(BIO *bp, const BIGNUM *a)
302 {
303     int i, j, v, z = 0;
304     int ret = 0;
305
306     if ((a->neg) && (BIO_write(bp, "-", 1) != 1))
307         goto end;
308     if (BN_is_zero(a) && (BIO_write(bp, "0", 1) != 1))
309         goto end;
310     for (i = a->top - 1; i >= 0; i--) {
311         for (j = BN_BITS2 - 4; j >= 0; j -= 4) {
312             /* strip leading zeros */
313             v = ((int)(a->d[i] >> (long)j)) & 0x0f;
314             if (z || (v != 0)) {
315                 if (BIO_write(bp, &(Hex[v]), 1) != 1)
316                     goto end;
317                 z = 1;
318             }
319         }
320     }
321     ret = 1;
322  end:
323     return (ret);
324 }
325
326 char *BN_options(void)
327 {
328     static int init = 0;
329     static char data[16];
330
331     if (!init) {
332         init++;
333 #ifdef BN_LLONG
334         sprintf(data, "bn(%d,%d)",
335                 (int)sizeof(BN_ULLONG) * 8, (int)sizeof(BN_ULONG) * 8);
336 #else
337         sprintf(data, "bn(%d,%d)",
338                 (int)sizeof(BN_ULONG) * 8, (int)sizeof(BN_ULONG) * 8);
339 #endif
340     }
341     return (data);
342 }