Coverage Report

Created: 2026-09-12 06:55

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