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