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