1 /* Copyright (C) 1995-1998 Eric Young ([email protected])
2 * All rights reserved.
3 *
4 * This package is an SSL implementation written
5 * by Eric Young ([email protected]).
6 * The implementation was written so as to conform with Netscapes SSL.
7 *
8 * This library is free for commercial and non-commercial use as long as
9 * the following conditions are aheared to. The following conditions
10 * apply to all code found in this distribution, be it the RC4, RSA,
11 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
12 * included with this distribution is covered by the same copyright terms
13 * except that the holder is Tim Hudson ([email protected]).
14 *
15 * Copyright remains Eric Young's, and as such any Copyright notices in
16 * the code are not to be removed.
17 * If this package is used in a product, Eric Young should be given attribution
18 * as the author of the parts of the library used.
19 * This can be in the form of a textual message at program startup or
20 * in documentation (online or textual) provided with the package.
21 *
22 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions
24 * are met:
25 * 1. Redistributions of source code must retain the copyright
26 * notice, this list of conditions and the following disclaimer.
27 * 2. Redistributions in binary form must reproduce the above copyright
28 * notice, this list of conditions and the following disclaimer in the
29 * documentation and/or other materials provided with the distribution.
30 * 3. All advertising materials mentioning features or use of this software
31 * must display the following acknowledgement:
32 * "This product includes cryptographic software written by
33 * Eric Young ([email protected])"
34 * The word 'cryptographic' can be left out if the rouines from the library
35 * being used are not cryptographic related :-).
36 * 4. If you include any Windows specific code (or a derivative thereof) from
37 * the apps directory (application code) you must include an acknowledgement:
38 * "This product includes software written by Tim Hudson ([email protected])"
39 *
40 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50 * SUCH DAMAGE.
51 *
52 * The licence and distribution terms for any publically available version or
53 * derivative of this code cannot be changed. i.e. this code cannot simply be
54 * copied and put under another distribution licence
55 * [including the GNU Public Licence.] */
56
57 #include <openssl/bn.h>
58
59 #include <assert.h>
60 #include <ctype.h>
61 #include <limits.h>
62 #include <stdio.h>
63
64 #include <openssl/bio.h>
65 #include <openssl/bytestring.h>
66 #include <openssl/err.h>
67 #include <openssl/mem.h>
68
69 #include "../fipsmodule/bn/internal.h"
70
71
BN_bn2cbb_padded(CBB * out,size_t len,const BIGNUM * in)72 int BN_bn2cbb_padded(CBB *out, size_t len, const BIGNUM *in) {
73 uint8_t *ptr;
74 return CBB_add_space(out, &ptr, len) && BN_bn2bin_padded(ptr, len, in);
75 }
76
77 static const char hextable[] = "0123456789abcdef";
78
BN_bn2hex(const BIGNUM * bn)79 char *BN_bn2hex(const BIGNUM *bn) {
80 int width = bn_minimal_width(bn);
81 char *buf = OPENSSL_malloc(1 /* leading '-' */ + 1 /* zero is non-empty */ +
82 width * BN_BYTES * 2 + 1 /* trailing NUL */);
83 if (buf == NULL) {
84 return NULL;
85 }
86
87 char *p = buf;
88 if (bn->neg) {
89 *(p++) = '-';
90 }
91
92 if (BN_is_zero(bn)) {
93 *(p++) = '0';
94 }
95
96 int z = 0;
97 for (int i = width - 1; i >= 0; i--) {
98 for (int j = BN_BITS2 - 8; j >= 0; j -= 8) {
99 // strip leading zeros
100 int v = ((int)(bn->d[i] >> (long)j)) & 0xff;
101 if (z || v != 0) {
102 *(p++) = hextable[v >> 4];
103 *(p++) = hextable[v & 0x0f];
104 z = 1;
105 }
106 }
107 }
108 *p = '\0';
109
110 return buf;
111 }
112
113 // decode_hex decodes |in_len| bytes of hex data from |in| and updates |bn|.
decode_hex(BIGNUM * bn,const char * in,int in_len)114 static int decode_hex(BIGNUM *bn, const char *in, int in_len) {
115 if (in_len > INT_MAX/4) {
116 OPENSSL_PUT_ERROR(BN, BN_R_BIGNUM_TOO_LONG);
117 return 0;
118 }
119 // |in_len| is the number of hex digits.
120 if (!bn_expand(bn, in_len * 4)) {
121 return 0;
122 }
123
124 int i = 0;
125 while (in_len > 0) {
126 // Decode one |BN_ULONG| at a time.
127 int todo = BN_BYTES * 2;
128 if (todo > in_len) {
129 todo = in_len;
130 }
131
132 BN_ULONG word = 0;
133 int j;
134 for (j = todo; j > 0; j--) {
135 uint8_t hex = 0;
136 if (!OPENSSL_fromxdigit(&hex, in[in_len - j])) {
137 // This shouldn't happen. The caller checks |OPENSSL_isxdigit|.
138 assert(0);
139 }
140 word = (word << 4) | hex;
141 }
142
143 bn->d[i++] = word;
144 in_len -= todo;
145 }
146 assert(i <= bn->dmax);
147 bn->width = i;
148 return 1;
149 }
150
151 // decode_dec decodes |in_len| bytes of decimal data from |in| and updates |bn|.
decode_dec(BIGNUM * bn,const char * in,int in_len)152 static int decode_dec(BIGNUM *bn, const char *in, int in_len) {
153 int i, j;
154 BN_ULONG l = 0;
155
156 // Decode |BN_DEC_NUM| digits at a time.
157 j = BN_DEC_NUM - (in_len % BN_DEC_NUM);
158 if (j == BN_DEC_NUM) {
159 j = 0;
160 }
161 l = 0;
162 for (i = 0; i < in_len; i++) {
163 l *= 10;
164 l += in[i] - '0';
165 if (++j == BN_DEC_NUM) {
166 if (!BN_mul_word(bn, BN_DEC_CONV) ||
167 !BN_add_word(bn, l)) {
168 return 0;
169 }
170 l = 0;
171 j = 0;
172 }
173 }
174 return 1;
175 }
176
177 typedef int (*decode_func) (BIGNUM *bn, const char *in, int in_len);
178 typedef int (*char_test_func) (int c);
179
bn_x2bn(BIGNUM ** outp,const char * in,decode_func decode,char_test_func want_char)180 static int bn_x2bn(BIGNUM **outp, const char *in, decode_func decode, char_test_func want_char) {
181 BIGNUM *ret = NULL;
182 int neg = 0, i;
183 int num;
184
185 if (in == NULL || *in == 0) {
186 return 0;
187 }
188
189 if (*in == '-') {
190 neg = 1;
191 in++;
192 }
193
194 for (i = 0; want_char((unsigned char)in[i]) && i + neg < INT_MAX; i++) {}
195
196 num = i + neg;
197 if (outp == NULL) {
198 return num;
199 }
200
201 // in is the start of the hex digits, and it is 'i' long
202 if (*outp == NULL) {
203 ret = BN_new();
204 if (ret == NULL) {
205 return 0;
206 }
207 } else {
208 ret = *outp;
209 BN_zero(ret);
210 }
211
212 if (!decode(ret, in, i)) {
213 goto err;
214 }
215
216 bn_set_minimal_width(ret);
217 if (!BN_is_zero(ret)) {
218 ret->neg = neg;
219 }
220
221 *outp = ret;
222 return num;
223
224 err:
225 if (*outp == NULL) {
226 BN_free(ret);
227 }
228
229 return 0;
230 }
231
BN_hex2bn(BIGNUM ** outp,const char * in)232 int BN_hex2bn(BIGNUM **outp, const char *in) {
233 return bn_x2bn(outp, in, decode_hex, OPENSSL_isxdigit);
234 }
235
BN_bn2dec(const BIGNUM * a)236 char *BN_bn2dec(const BIGNUM *a) {
237 // It is easier to print strings little-endian, so we assemble it in reverse
238 // and fix at the end.
239 BIGNUM *copy = NULL;
240 CBB cbb;
241 if (!CBB_init(&cbb, 16) ||
242 !CBB_add_u8(&cbb, 0 /* trailing NUL */)) {
243 goto err;
244 }
245
246 if (BN_is_zero(a)) {
247 if (!CBB_add_u8(&cbb, '0')) {
248 goto err;
249 }
250 } else {
251 copy = BN_dup(a);
252 if (copy == NULL) {
253 goto err;
254 }
255
256 while (!BN_is_zero(copy)) {
257 BN_ULONG word = BN_div_word(copy, BN_DEC_CONV);
258 if (word == (BN_ULONG)-1) {
259 goto err;
260 }
261
262 const int add_leading_zeros = !BN_is_zero(copy);
263 for (int i = 0; i < BN_DEC_NUM && (add_leading_zeros || word != 0); i++) {
264 if (!CBB_add_u8(&cbb, '0' + word % 10)) {
265 goto err;
266 }
267 word /= 10;
268 }
269 assert(word == 0);
270 }
271 }
272
273 if (BN_is_negative(a) &&
274 !CBB_add_u8(&cbb, '-')) {
275 goto err;
276 }
277
278 uint8_t *data;
279 size_t len;
280 if (!CBB_finish(&cbb, &data, &len)) {
281 goto err;
282 }
283
284 // Reverse the buffer.
285 for (size_t i = 0; i < len/2; i++) {
286 uint8_t tmp = data[i];
287 data[i] = data[len - 1 - i];
288 data[len - 1 - i] = tmp;
289 }
290
291 BN_free(copy);
292 return (char *)data;
293
294 err:
295 BN_free(copy);
296 CBB_cleanup(&cbb);
297 return NULL;
298 }
299
BN_dec2bn(BIGNUM ** outp,const char * in)300 int BN_dec2bn(BIGNUM **outp, const char *in) {
301 return bn_x2bn(outp, in, decode_dec, OPENSSL_isdigit);
302 }
303
BN_asc2bn(BIGNUM ** outp,const char * in)304 int BN_asc2bn(BIGNUM **outp, const char *in) {
305 const char *const orig_in = in;
306 if (*in == '-') {
307 in++;
308 }
309
310 if (in[0] == '0' && (in[1] == 'X' || in[1] == 'x')) {
311 if (!BN_hex2bn(outp, in+2)) {
312 return 0;
313 }
314 } else {
315 if (!BN_dec2bn(outp, in)) {
316 return 0;
317 }
318 }
319
320 if (*orig_in == '-' && !BN_is_zero(*outp)) {
321 (*outp)->neg = 1;
322 }
323
324 return 1;
325 }
326
BN_print(BIO * bp,const BIGNUM * a)327 int BN_print(BIO *bp, const BIGNUM *a) {
328 int i, j, v, z = 0;
329 int ret = 0;
330
331 if (a->neg && BIO_write(bp, "-", 1) != 1) {
332 goto end;
333 }
334
335 if (BN_is_zero(a) && BIO_write(bp, "0", 1) != 1) {
336 goto end;
337 }
338
339 for (i = bn_minimal_width(a) - 1; i >= 0; i--) {
340 for (j = BN_BITS2 - 4; j >= 0; j -= 4) {
341 // strip leading zeros
342 v = ((int)(a->d[i] >> (long)j)) & 0x0f;
343 if (z || v != 0) {
344 if (BIO_write(bp, &hextable[v], 1) != 1) {
345 goto end;
346 }
347 z = 1;
348 }
349 }
350 }
351 ret = 1;
352
353 end:
354 return ret;
355 }
356
BN_print_fp(FILE * fp,const BIGNUM * a)357 int BN_print_fp(FILE *fp, const BIGNUM *a) {
358 BIO *b = BIO_new_fp(fp, BIO_NOCLOSE);
359 if (b == NULL) {
360 return 0;
361 }
362
363 int ret = BN_print(b, a);
364 BIO_free(b);
365 return ret;
366 }
367
368
BN_bn2mpi(const BIGNUM * in,uint8_t * out)369 size_t BN_bn2mpi(const BIGNUM *in, uint8_t *out) {
370 const size_t bits = BN_num_bits(in);
371 const size_t bytes = (bits + 7) / 8;
372 // If the number of bits is a multiple of 8, i.e. if the MSB is set,
373 // prefix with a zero byte.
374 int extend = 0;
375 if (bytes != 0 && (bits & 0x07) == 0) {
376 extend = 1;
377 }
378
379 const size_t len = bytes + extend;
380 if (len < bytes ||
381 4 + len < len ||
382 (len & 0xffffffff) != len) {
383 // If we cannot represent the number then we emit zero as the interface
384 // doesn't allow an error to be signalled.
385 if (out) {
386 OPENSSL_memset(out, 0, 4);
387 }
388 return 4;
389 }
390
391 if (out == NULL) {
392 return 4 + len;
393 }
394
395 out[0] = len >> 24;
396 out[1] = len >> 16;
397 out[2] = len >> 8;
398 out[3] = len;
399 if (extend) {
400 out[4] = 0;
401 }
402 BN_bn2bin(in, out + 4 + extend);
403 if (in->neg && len > 0) {
404 out[4] |= 0x80;
405 }
406 return len + 4;
407 }
408
BN_mpi2bn(const uint8_t * in,size_t len,BIGNUM * out)409 BIGNUM *BN_mpi2bn(const uint8_t *in, size_t len, BIGNUM *out) {
410 if (len < 4) {
411 OPENSSL_PUT_ERROR(BN, BN_R_BAD_ENCODING);
412 return NULL;
413 }
414 const size_t in_len = ((size_t)in[0] << 24) |
415 ((size_t)in[1] << 16) |
416 ((size_t)in[2] << 8) |
417 ((size_t)in[3]);
418 if (in_len != len - 4) {
419 OPENSSL_PUT_ERROR(BN, BN_R_BAD_ENCODING);
420 return NULL;
421 }
422
423 int out_is_alloced = 0;
424 if (out == NULL) {
425 out = BN_new();
426 if (out == NULL) {
427 return NULL;
428 }
429 out_is_alloced = 1;
430 }
431
432 if (in_len == 0) {
433 BN_zero(out);
434 return out;
435 }
436
437 in += 4;
438 if (BN_bin2bn(in, in_len, out) == NULL) {
439 if (out_is_alloced) {
440 BN_free(out);
441 }
442 return NULL;
443 }
444 out->neg = ((*in) & 0x80) != 0;
445 if (out->neg) {
446 BN_clear_bit(out, BN_num_bits(out) - 1);
447 }
448 return out;
449 }
450
BN_bn2binpad(const BIGNUM * in,uint8_t * out,int len)451 int BN_bn2binpad(const BIGNUM *in, uint8_t *out, int len) {
452 if (len < 0 ||
453 !BN_bn2bin_padded(out, (size_t)len, in)) {
454 return -1;
455 }
456 return len;
457 }
458
BN_bn2lebinpad(const BIGNUM * in,uint8_t * out,int len)459 int BN_bn2lebinpad(const BIGNUM *in, uint8_t *out, int len) {
460 if (len < 0 ||
461 !BN_bn2le_padded(out, (size_t)len, in)) {
462 return -1;
463 }
464 return len;
465 }
466