Coverage Report

Created: 2025-06-13 06:56

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