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