Coverage Report

Created: 2025-06-13 06:58

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