xref: /openbsd-src/regress/lib/libcrypto/bn/bn_convert.c (revision 5b7d9130dd621995378809e175740fcca36ec6d2)
1 /*	$OpenBSD: bn_convert.c,v 1.9 2024/11/05 18:20:08 tb Exp $ */
2 /*
3  * Copyright (c) 2023 Joel Sing <jsing@openbsd.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <err.h>
19 #include <string.h>
20 
21 #include <openssl/bn.h>
22 
23 /*
24  * Additional test coverage is needed for:
25  *
26  * - BN_print()/BN_print_fp()
27  *
28  * - Invalid inputs to {asc,dec,hex,mpi}2bn
29  * - Zero padded inputs
30  */
31 
32 static void
33 hexdump(const unsigned char *buf, size_t len)
34 {
35 	size_t i;
36 
37 	for (i = 1; i <= len; i++)
38 		fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n");
39 
40 	fprintf(stderr, "\n");
41 }
42 
43 static int
44 check_bin_output(size_t test_no, const char *label, const uint8_t *bin,
45     size_t bin_len, const BIGNUM *bn)
46 {
47 	uint8_t *out = NULL;
48 	int out_len;
49 	int ret;
50 	int failed = 1;
51 
52 	out_len = BN_num_bytes(bn);
53 	if (out_len != (int)bin_len) {
54 		fprintf(stderr, "FAIL: Test %zu %s - BN_num_bytes() = %d, "
55 		    "want %zu\n", test_no, label, out_len, bin_len);
56 		goto failure;
57 	}
58 	if (out_len > 0 && (out = malloc(out_len)) == NULL)
59 		err(1, "malloc");
60 	if ((ret = BN_bn2bin(bn, out)) != out_len) {
61 		fprintf(stderr, "FAIL: Test %zu %s - BN_bn2bin() returned %d, "
62 		    "want %d\n", test_no, label, ret, out_len);
63 		goto failure;
64 	}
65 	if (memcmp(out, bin, bin_len) != 0) {
66 		fprintf(stderr, "FAIL: Test %zu %s - output from "
67 		    "BN_bn2bin() differs\n", test_no, label);
68 		fprintf(stderr, "Got:\n");
69 		hexdump(out, out_len);
70 		fprintf(stderr, "Want:\n");
71 		hexdump(bin, bin_len);
72 		goto failure;
73 	}
74 
75 	failed = 0;
76 
77  failure:
78 	free(out);
79 
80 	return failed;
81 }
82 
83 struct bn_asc2bn_test {
84 	const char *in;
85 	const uint8_t bin[64];
86 	size_t bin_len;
87 	int neg;
88 	int want_error;
89 };
90 
91 static const struct bn_asc2bn_test bn_asc2bn_tests[] = {
92 	{
93 		.in = "",
94 		.want_error = 1,
95 	},
96 	{
97 		.in = "-",
98 		.want_error = 1,
99 	},
100 	{
101 		.in = "0",
102 		.bin = { 0x00, },
103 		.bin_len = 0,
104 		.neg = 0,
105 	},
106 	{
107 		.in = "0x0",
108 		.bin = { 0x00, },
109 		.bin_len = 0,
110 		.neg = 0,
111 	},
112 	{
113 		.in = "-0",
114 		.bin = { 0x00, },
115 		.bin_len = 0,
116 		.neg = 0,
117 	},
118 	{
119 		.in = "-0x0",
120 		.bin = { 0x00, },
121 		.bin_len = 0,
122 		.neg = 0,
123 	},
124 	{
125 		.in = "123456789",
126 		.bin = { 0x07, 0x5b, 0xcd, 0x15, },
127 		.bin_len = 4,
128 		.neg = 0,
129 	},
130 	{
131 		.in = "0123456789",
132 		.bin = { 0x07, 0x5b, 0xcd, 0x15, },
133 		.bin_len = 4,
134 		.neg = 0,
135 	},
136 	{
137 		.in = "-123456789",
138 		.bin = { 0x07, 0x5b, 0xcd, 0x15, },
139 		.bin_len = 4,
140 		.neg = 1,
141 	},
142 	{
143 		.in = "0X123456789",
144 		.bin = { 0x01, 0x23, 0x45, 0x67, 0x89, },
145 		.bin_len = 5,
146 		.neg = 0,
147 	},
148 	{
149 		.in = "0x123456789",
150 		.bin = { 0x01, 0x23, 0x45, 0x67, 0x89, },
151 		.bin_len = 5,
152 		.neg = 0,
153 	},
154 	{
155 		.in = "-0x123456789",
156 		.bin = { 0x01, 0x23, 0x45, 0x67, 0x89, },
157 		.bin_len = 5,
158 		.neg = 1,
159 	},
160 	{
161 		.in = "abcdef123456789",
162 		.want_error = 1,
163 	},
164 	{
165 		.in = "0x000123456789abCdEf",
166 		.bin = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
167 		.bin_len = 8,
168 		.neg = 0,
169 	},
170 };
171 
172 #define N_BN_ASC2BN_TESTS \
173     (sizeof(bn_asc2bn_tests) / sizeof(*bn_asc2bn_tests))
174 
175 static int
176 test_bn_asc2bn(void)
177 {
178 	const struct bn_asc2bn_test *bat;
179 	BIGNUM *bn = NULL;
180 	size_t i;
181 	int failed = 1;
182 
183 	for (i = 0; i < N_BN_ASC2BN_TESTS; i++) {
184 		bat = &bn_asc2bn_tests[i];
185 
186 		BN_free(bn);
187 		bn = NULL;
188 
189 		if (!BN_asc2bn(&bn, bat->in)) {
190 			if (bat->want_error)
191 				continue;
192 			fprintf(stderr, "FAIL: Test %zu - BN_asc2bn() failed\n", i);
193 			goto failure;
194 		}
195 		if (bat->want_error) {
196 			fprintf(stderr, "FAIL: Test %zu - BN_asc2bn() succeeded "
197 			    "when it should have failed\n", i);
198 			goto failure;
199 		}
200 
201 		if (check_bin_output(i, "BN_asc2bn()", bat->bin, bat->bin_len,
202 		    bn) != 0)
203 			goto failure;
204 
205 		if (BN_is_negative(bn) != bat->neg) {
206 			fprintf(stderr, "FAIL: Test %zu - BN_asc2bn() resulted "
207 			    "in negative %d, want %d", i, BN_is_negative(bn),
208 			    bat->neg);
209 			goto failure;
210 		}
211 	}
212 
213 	/*
214 	 * While it makes little sense to call BN_asc2bn() with a NULL bn,
215 	 * check for consistent behavior.
216 	 */
217 	if (!BN_asc2bn(NULL, "1") || !BN_asc2bn(NULL, "-1") ||
218 	    !BN_asc2bn(NULL, "0x1") || !BN_asc2bn(NULL, "-0x1")) {
219 		fprintf(stderr, "FAIL: BN_asc2bn() with NULL BIGNUM failed\n");
220 		goto failure;
221 	}
222 
223 	failed = 0;
224 
225  failure:
226 	BN_free(bn);
227 
228 	return failed;
229 }
230 
231 struct bn_convert_test {
232 	const uint8_t bin[64];
233 	size_t bin_len;
234 	int neg;
235 	const char *dec;
236 	const char *hex;
237 	const uint8_t mpi[64];
238 	int mpi_len;
239 };
240 
241 static const struct bn_convert_test bn_convert_tests[] = {
242 	{
243 		.bin = { 0x0, },
244 		.bin_len = 0,
245 		.neg = 0,
246 		.dec = "0",
247 		.hex = "0",
248 		.mpi = { 0x00, 0x00, 0x00, 0x00, },
249 		.mpi_len = 4,
250 	},
251 	{
252 		.bin = { 0x1, },
253 		.bin_len = 1,
254 		.neg = 0,
255 		.dec = "1",
256 		.hex = "01",
257 		.mpi = { 0x00, 0x00, 0x00, 0x01, 0x01, },
258 		.mpi_len = 5,
259 	},
260 	{
261 		.bin = { 0x1, },
262 		.bin_len = 1,
263 		.neg = 1,
264 		.dec = "-1",
265 		.hex = "-01",
266 		.mpi = { 0x00, 0x00, 0x00, 0x01, 0x81, },
267 		.mpi_len = 5,
268 	},
269 	{
270 		.bin = { 0x7f, 0xff, 0xff, },
271 		.bin_len = 3,
272 		.neg = 0,
273 		.dec = "8388607",
274 		.hex = "7FFFFF",
275 		.mpi = { 0x00, 0x00, 0x00, 0x03, 0x7f, 0xff, 0xff, },
276 		.mpi_len = 7,
277 	},
278 	{
279 		.bin = { 0x7f, 0xff, 0xff, },
280 		.bin_len = 3,
281 		.neg = 1,
282 		.dec = "-8388607",
283 		.hex = "-7FFFFF",
284 		.mpi = { 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, },
285 		.mpi_len = 7,
286 	},
287 	{
288 		.bin = { 0x01, 0x02, 0x03, 0x04, },
289 		.bin_len = 4,
290 		.neg = 0,
291 		.dec = "16909060",
292 		.hex = "01020304",
293 		.mpi = { 0x00, 0x00, 0x00, 0x04, 0x01, 0x02, 0x03, 0x04, },
294 		.mpi_len = 8,
295 	},
296 	{
297 		.bin = { 0x04, 0x03, 0x02, 0x01, },
298 		.bin_len = 4,
299 		.neg = 0,
300 		.dec = "67305985",
301 		.hex = "04030201",
302 		.mpi = { 0x00, 0x00, 0x00, 0x04, 0x04, 0x03, 0x02, 0x01, },
303 		.mpi_len = 8,
304 	},
305 	{
306 		.bin = { 0xff, 0xff, 0xff, 0xff, },
307 		.bin_len = 4,
308 		.neg = 0,
309 		.dec = "4294967295",
310 		.hex = "FFFFFFFF",
311 		.mpi = {
312 			0x00, 0x00, 0x00, 0x05, 0x00, 0xff, 0xff, 0xff,
313 			0xff,
314 		 },
315 		.mpi_len = 9,
316 	},
317 	{
318 		.bin = { 0xff, 0xff, 0xff, 0xff, },
319 		.bin_len = 4,
320 		.neg = 1,
321 		.dec = "-4294967295",
322 		.hex = "-FFFFFFFF",
323 		.mpi = {
324 			0x00, 0x00, 0x00, 0x05, 0x80, 0xff, 0xff, 0xff,
325 			0xff,
326 		 },
327 		.mpi_len = 9,
328 	},
329 	{
330 		.bin = { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, },
331 		.bin_len = 8,
332 		.neg = 0,
333 		.dec = "18446744069414584320",
334 		.hex = "FFFFFFFF00000000",
335 		.mpi = {
336 			0x00, 0x00, 0x00, 0x09, 0x00, 0xff, 0xff, 0xff,
337 			0xff, 0x00, 0x00, 0x00, 0x00,
338 		 },
339 		.mpi_len = 13,
340 	},
341 	{
342 		.bin = { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, },
343 		.bin_len = 8,
344 		.neg = 1,
345 		.dec = "-18446744069414584320",
346 		.hex = "-FFFFFFFF00000000",
347 		.mpi = {
348 			0x00, 0x00, 0x00, 0x09, 0x80, 0xff, 0xff, 0xff,
349 			0xff, 0x00, 0x00, 0x00, 0x00,
350 		 },
351 		.mpi_len = 13,
352 	},
353 	{
354 		.bin = { 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, },
355 		.bin_len = 8,
356 		.neg = 0,
357 		.dec = "9223794255762391041",
358 		.hex = "8001800180018001",
359 		.mpi = {
360 			0x00, 0x00, 0x00, 0x09, 0x00, 0x80, 0x01, 0x80,
361 			0x01, 0x80, 0x01, 0x80, 0x01,
362 		 },
363 		.mpi_len = 13,
364 	},
365 	{
366 		.bin = { 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, },
367 		.bin_len = 8,
368 		.neg = 1,
369 		.dec = "-9223794255762391041",
370 		.hex = "-8001800180018001",
371 		.mpi = {
372 			0x00, 0x00, 0x00, 0x09, 0x80, 0x80, 0x01, 0x80,
373 			0x01, 0x80, 0x01, 0x80, 0x01,
374 		 },
375 		.mpi_len = 13,
376 	},
377 	{
378 		.bin = {
379 			0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80,
380 			0x01,
381 		},
382 		.bin_len = 9,
383 		.neg = 0,
384 		.dec = "27670538329471942657",
385 		.hex = "018001800180018001",
386 		.mpi = {
387 			0x00, 0x00, 0x00, 0x09, 0x01, 0x80, 0x01, 0x80,
388 			0x01, 0x80, 0x01, 0x80, 0x01,
389 		 },
390 		.mpi_len = 13,
391 	},
392 	{
393 		.bin = {
394 			0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80,
395 			0x01,
396 		},
397 		.bin_len = 9,
398 		.neg = 1,
399 		.dec = "-27670538329471942657",
400 		.hex = "-018001800180018001",
401 		.mpi = {
402 			0x00, 0x00, 0x00, 0x09, 0x81, 0x80, 0x01, 0x80,
403 			0x01, 0x80, 0x01, 0x80, 0x01,
404 		 },
405 		.mpi_len = 13,
406 	},
407 	{
408 		.bin = {
409 			0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff,
410 			0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff,
411 			0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff,
412 			0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff,
413 		},
414 		.bin_len = 32,
415 		.neg = 0,
416 		.dec = "57895161181645529494837117048595051142566530671229791132691030063130991362047",
417 		.hex = "7FFF7FFF7FFF7FFF7FFF7FFF7FFF7FFF7FFF7FFF7FFF7FFF7FFF7FFF7FFF7FFF",
418 		.mpi = {
419 			0x00, 0x00, 0x00, 0x20, 0x7f, 0xff, 0x7f, 0xff,
420 			0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff,
421 			0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff,
422 			0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff,
423 			0x7f, 0xff, 0x7f, 0xff,
424 		 },
425 		.mpi_len = 36,
426 	},
427 	{
428 		.bin = {
429 			0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff,
430 			0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff,
431 			0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff,
432 			0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff,
433 		},
434 		.bin_len = 32,
435 		.neg = 1,
436 		.dec = "-57895161181645529494837117048595051142566530671229791132691030063130991362047",
437 		.hex = "-7FFF7FFF7FFF7FFF7FFF7FFF7FFF7FFF7FFF7FFF7FFF7FFF7FFF7FFF7FFF7FFF",
438 		.mpi = {
439 			0x00, 0x00, 0x00, 0x20, 0xff, 0xff, 0x7f, 0xff,
440 			0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff,
441 			0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff,
442 			0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff,
443 			0x7f, 0xff, 0x7f, 0xff,
444 		 },
445 		.mpi_len = 36,
446 	},
447 };
448 
449 #define N_BN_CONVERT_TESTS \
450     (sizeof(bn_convert_tests) / sizeof(*bn_convert_tests))
451 
452 static int
453 test_bn_convert(void)
454 {
455 	const struct bn_convert_test *bct;
456 	uint8_t *mpi_out = NULL;
457 	char *out_str = NULL;
458 	uint8_t lebin[64];
459 	BIGNUM *bn = NULL;
460 	int mpi_len;
461 	size_t i, j;
462 	int failed = 1;
463 
464 	for (i = 0; i < N_BN_CONVERT_TESTS; i++) {
465 		bct = &bn_convert_tests[i];
466 
467 		BN_free(bn);
468 		if ((bn = BN_bin2bn(bct->bin, bct->bin_len, NULL)) == NULL) {
469 			fprintf(stderr, "FAIL: BN_bin2bn() failed\n");
470 			goto failure;
471 		}
472 		BN_set_negative(bn, bct->neg);
473 
474 		if (check_bin_output(i, "BN_bin2bn()", bct->bin, bct->bin_len,
475 		    bn) != 0)
476 			goto failure;
477 
478 		for (j = 0; j < bct->bin_len; j++)
479 			lebin[j] = bct->bin[bct->bin_len - j - 1];
480 
481 		BN_free(bn);
482 		if ((bn = BN_lebin2bn(lebin, bct->bin_len, NULL)) == NULL) {
483 			fprintf(stderr, "FAIL: BN_lebin2bn() failed\n");
484 			goto failure;
485 		}
486 		BN_set_negative(bn, bct->neg);
487 
488 		if (check_bin_output(i, "BN_lebin2bn()", bct->bin, bct->bin_len,
489 		    bn) != 0)
490 			goto failure;
491 
492 		free(out_str);
493 		if ((out_str = BN_bn2dec(bn)) == NULL) {
494 			fprintf(stderr, "FAIL: BN_bn2dec() failed\n");
495 			goto failure;
496 		}
497 		if (strcmp(out_str, bct->dec) != 0) {
498 			fprintf(stderr, "FAIL: Test %zu - BN_bn2dec() returned "
499 			    "'%s', want '%s'", i, out_str, bct->dec);
500 			goto failure;
501 		}
502 
503 		free(out_str);
504 		if ((out_str = BN_bn2hex(bn)) == NULL) {
505 			fprintf(stderr, "FAIL: BN_bn2hex() failed\n");
506 			goto failure;
507 		}
508 		if (strcmp(out_str, bct->hex) != 0) {
509 			fprintf(stderr, "FAIL: Test %zu - BN_bn2hex() returned "
510 			    "'%s', want '%s'", i, out_str, bct->hex);
511 			goto failure;
512 		}
513 
514 		free(mpi_out);
515 		mpi_out = NULL;
516 
517 		if ((mpi_len = BN_bn2mpi(bn, NULL)) != bct->mpi_len) {
518 			fprintf(stderr, "FAIL: Test %zu - BN_bn2mpi() returned "
519 			    "%d, want %d", i, mpi_len, bct->mpi_len);
520 			goto failure;
521 		}
522 		if ((mpi_out = calloc(1, bct->mpi_len)) == NULL)
523 			goto failure;
524 		if ((mpi_len = BN_bn2mpi(bn, mpi_out)) != bct->mpi_len) {
525 			fprintf(stderr, "FAIL: Test %zu - BN_bn2mpi() returned "
526 			    "%d, want %d", i, mpi_len, bct->mpi_len);
527 			goto failure;
528 		}
529 		if (memcmp(mpi_out, bct->mpi, bct->mpi_len) != 0) {
530 			fprintf(stderr, "FAIL: Test %zu - BN_bn2mpi() "
531 			    "generated:\n", i);
532 			hexdump(mpi_out, bct->mpi_len);
533 			fprintf(stderr, "Want:\n");
534 			hexdump(bct->mpi, bct->mpi_len);
535 			goto failure;
536 		}
537 
538 		if (BN_dec2bn(&bn, bct->dec) != (int)strlen(bct->dec)) {
539 			fprintf(stderr, "FAIL: BN_dec2bn() failed\n");
540 			goto failure;
541 		}
542 		if (BN_is_negative(bn) != bct->neg) {
543 			fprintf(stderr, "FAIL: Test %zu - BN_dec2bn() resulted "
544 			    "in negative %d, want %d", i, BN_is_negative(bn),
545 			    bct->neg);
546 			goto failure;
547 		}
548 		if (check_bin_output(i, "BN_dec2bn()", bct->bin, bct->bin_len,
549 		    bn) != 0)
550 			goto failure;
551 
552 		if (BN_hex2bn(&bn, bct->hex) != (int)strlen(bct->hex)) {
553 			fprintf(stderr, "FAIL: BN_hex2bn() failed\n");
554 			goto failure;
555 		}
556 		if (BN_is_negative(bn) != bct->neg) {
557 			fprintf(stderr, "FAIL: Test %zu - BN_hex2bn() resulted "
558 			    "in negative %d, want %d", i, BN_is_negative(bn),
559 			    bct->neg);
560 			goto failure;
561 		}
562 		if (check_bin_output(i, "BN_hex2bn()", bct->bin, bct->bin_len,
563 		    bn) != 0)
564 			goto failure;
565 
566 		if (BN_mpi2bn(bct->mpi, bct->mpi_len, bn) == NULL) {
567 			fprintf(stderr, "FAIL: BN_mpi2bn() failed\n");
568 			goto failure;
569 		}
570 		if (BN_is_negative(bn) != bct->neg) {
571 			fprintf(stderr, "FAIL: Test %zu - BN_mpi2bn() resulted "
572 			    "in negative %d, want %d", i, BN_is_negative(bn),
573 			    bct->neg);
574 			goto failure;
575 		}
576 		if (check_bin_output(i, "BN_mpi2bn()", bct->bin, bct->bin_len,
577 		    bn) != 0)
578 			goto failure;
579 	}
580 
581 	failed = 0;
582 
583  failure:
584 	free(mpi_out);
585 	free(out_str);
586 	BN_free(bn);
587 
588 	return failed;
589 }
590 
591 static int
592 test_bn_dec2bn(void)
593 {
594 	BIGNUM *bn = NULL;
595 	BN_ULONG w;
596 	int ret;
597 	int failed = 1;
598 
599 	/* An empty string fails to parse, as does NULL. */
600 	if (BN_dec2bn(&bn, "") != 0) {
601 		fprintf(stderr, "FAIL: BN_dec2bn(_, \"\") succeeded\n");
602 		goto failure;
603 	}
604 	if (bn != NULL) {
605 		fprintf(stderr, "FAIL: BN_dec2bn(_, \"\") succeeded\n");
606 		goto failure;
607 	}
608 	if (BN_dec2bn(&bn, NULL) != 0) {
609 		fprintf(stderr, "FAIL: BN_dec2bn(_, NULL) succeeded\n");
610 		goto failure;
611 	}
612 	if (bn != NULL) {
613 		fprintf(stderr, "FAIL: BN_dec2bn(_, NULL) succeeded\n");
614 		goto failure;
615 	}
616 
617 	/* A minus sign parses as 0. */
618 	if (BN_dec2bn(&bn, "-") != 1) {
619 		fprintf(stderr, "FAIL: BN_dec2bn(_, \"-\") failed\n");
620 		goto failure;
621 	}
622 	if (bn == NULL) {
623 		fprintf(stderr, "FAIL: BN_dec2bn(_, \"-\") failed\n");
624 		goto failure;
625 	}
626 	if (!BN_is_zero(bn)) {
627 		fprintf(stderr, "FAIL: BN_dec2bn(_, \"-\") is non-zero\n");
628 		goto failure;
629 	}
630 	if (BN_is_negative(bn)) {
631 		fprintf(stderr, "FAIL: BN_dec2bn(_, \"-\") resulted in "
632 		    "negative zero\n");
633 		goto failure;
634 	}
635 
636 	/* Ensure that -0 results in 0. */
637 	if (BN_dec2bn(&bn, "-0") != 2) {
638 		fprintf(stderr, "FAIL: BN_dec2bn(_, \"-0\") failed\n");
639 		goto failure;
640 	}
641 	if (!BN_is_zero(bn)) {
642 		fprintf(stderr, "FAIL: BN_dec2bn(_, \"-0\") is non-zero\n");
643 		goto failure;
644 	}
645 	if (BN_is_negative(bn)) {
646 		fprintf(stderr, "FAIL: BN_dec2bn(_, \"-0\") resulted in "
647 		    "negative zero\n");
648 		goto failure;
649 	}
650 
651 	/* BN_dec2bn() is the new atoi()... */
652 	if ((ret = BN_dec2bn(&bn, "0123456789abcdef")) != 10) {
653 		fprintf(stderr, "FAIL: BN_dec2bn() returned %d, want 10\n", ret);
654 		goto failure;
655 	}
656 	if ((w = BN_get_word(bn)) != 0x75bcd15) {
657 		fprintf(stderr, "FAIL: BN_dec2bn() resulted in %llx, want %llx\n",
658 		    (unsigned long long)w, 0x75bcd15ULL);
659 		goto failure;
660 	}
661 
662 	/* And we can call BN_dec2bn() without actually converting to a BIGNUM. */
663 	if ((ret = BN_dec2bn(NULL, "0123456789abcdef")) != 10) {
664 		fprintf(stderr, "FAIL: BN_dec2bn() returned %d, want 10\n", ret);
665 		goto failure;
666 	}
667 
668 	failed = 0;
669 
670  failure:
671 	BN_free(bn);
672 
673 	return failed;
674 }
675 
676 static int
677 test_bn_hex2bn(void)
678 {
679 	BIGNUM *bn = NULL;
680 	BN_ULONG w;
681 	int ret;
682 	int failed = 1;
683 
684 	/* An empty string fails to parse, as does NULL. */
685 	if (BN_hex2bn(&bn, "") != 0) {
686 		fprintf(stderr, "FAIL: BN_hex2bn(_, \"\") succeeded\n");
687 		goto failure;
688 	}
689 	if (bn != NULL) {
690 		fprintf(stderr, "FAIL: BN_hex2bn(_, \"\") succeeded\n");
691 		goto failure;
692 	}
693 	if (BN_hex2bn(&bn, NULL) != 0) {
694 		fprintf(stderr, "FAIL: BN_hex2bn(_, NULL) succeeded\n");
695 		goto failure;
696 	}
697 	if (bn != NULL) {
698 		fprintf(stderr, "FAIL: BN_hex2bn(_, NULL) succeeded\n");
699 		goto failure;
700 	}
701 
702 	/* A minus sign parses as 0. */
703 	if (BN_hex2bn(&bn, "-") != 1) {
704 		fprintf(stderr, "FAIL: BN_hex2bn(_, \"-\") failed\n");
705 		goto failure;
706 	}
707 	if (bn == NULL) {
708 		fprintf(stderr, "FAIL: BN_hex2bn(_, \"-\") failed\n");
709 		goto failure;
710 	}
711 	if (!BN_is_zero(bn)) {
712 		fprintf(stderr, "FAIL: BN_hex2bn(_, \"-\") returned non-zero\n");
713 		goto failure;
714 	}
715 	if (BN_is_negative(bn)) {
716 		fprintf(stderr, "FAIL: BN_hex2bn(_, \"-\") returned negative zero\n");
717 		goto failure;
718 	}
719 
720 	/* Ensure that -0 results in 0. */
721 	if (BN_hex2bn(&bn, "-0") != 2) {
722 		fprintf(stderr, "FAIL: BN_hex2bn(_, \"-0\") failed\n");
723 		goto failure;
724 	}
725 	if (!BN_is_zero(bn)) {
726 		fprintf(stderr, "FAIL: BN_hex2bn(_, \"-0\") is non-zero\n");
727 		goto failure;
728 	}
729 	if (BN_is_negative(bn)) {
730 		fprintf(stderr, "FAIL: BN_hex2bn(_, \"-0\") resulted in "
731 		    "negative zero\n");
732 		goto failure;
733 	}
734 
735 	/* BN_hex2bn() is the new atoi()... */
736 	if ((ret = BN_hex2bn(&bn, "9abcdefz")) != 7) {
737 		fprintf(stderr, "FAIL: BN_hex2bn() returned %d, want 7\n", ret);
738 		goto failure;
739 	}
740 	if ((w = BN_get_word(bn)) != 0x9abcdef) {
741 		fprintf(stderr, "FAIL: BN_hex2bn() resulted in %llx, want %llx\n",
742 		    (unsigned long long)w, 0x9abcdefULL);
743 		goto failure;
744 	}
745 
746 	/* A 0x prefix fails to parse without BN_asc2bn() (instead we get 0!). */
747 	if (BN_hex2bn(&bn, "0x1") != 1) {
748 		fprintf(stderr, "FAIL: BN_hex2bn() parsed a 0x prefix\n");
749 		goto failure;
750 	}
751 
752 	/* And we can call BN_hex2bn() without actually converting to a BIGNUM. */
753 	if ((ret = BN_hex2bn(NULL, "9abcdefz")) != 7) {
754 		fprintf(stderr, "FAIL: BN_hex2bn() returned %d, want 7\n", ret);
755 		goto failure;
756 	}
757 
758 	failed = 0;
759 
760  failure:
761 	BN_free(bn);
762 
763 	return failed;
764 }
765 
766 static int
767 test_bn_binpad(void)
768 {
769 	const struct bn_convert_test *bct;
770 	BIGNUM *bn = NULL;
771 	uint8_t lebin[64];
772 	uint8_t buf[128];
773 	size_t i, j;
774 	int ret;
775 	int failed = 1;
776 
777 	for (i = 0; i < N_BN_CONVERT_TESTS; i++) {
778 		bct = &bn_convert_tests[i];
779 
780 		BN_free(bn);
781 		if ((bn = BN_bin2bn(bct->bin, bct->bin_len, NULL)) == NULL) {
782 			fprintf(stderr, "FAIL: BN_bin2bn() failed\n");
783 			goto failure;
784 		}
785 		BN_set_negative(bn, bct->neg);
786 
787 		for (j = 0; j < bct->bin_len; j++)
788 			lebin[j] = bct->bin[bct->bin_len - j - 1];
789 
790 		if ((ret = BN_bn2binpad(bn, buf, bct->bin_len)) < 0) {
791 			fprintf(stderr, "FAIL: BN_bn2binpad() failed\n");
792 			goto failure;
793 		}
794 		if ((size_t)ret != bct->bin_len) {
795 			fprintf(stderr, "FAIL: BN_bn2binpad() = %d, want %zu\n",
796 			    ret, bct->bin_len);
797 			goto failure;
798 		}
799 		if (memcmp(buf, bct->bin, bct->bin_len) != 0) {
800 			fprintf(stderr, "FAIL: Test %zu - output from "
801 			    "BN_bn2binpad() differs\n", i);
802 			fprintf(stderr, "Got:\n");
803 			hexdump(buf, bct->bin_len);
804 			fprintf(stderr, "Want:\n");
805 			hexdump(bct->bin, bct->bin_len);
806 			goto failure;
807 		}
808 		if (bct->bin_len > 0) {
809 			if ((ret = BN_bn2binpad(bn, buf, bct->bin_len - 1)) != -1) {
810 				fprintf(stderr, "FAIL: BN_bn2binpad() succeeded "
811 				    "with truncation\n");
812 				goto failure;
813 			}
814 		}
815 		if ((ret = BN_bn2binpad(bn, buf, 128)) < 0) {
816 			fprintf(stderr, "FAIL: BN_bn2binpad() failed\n");
817 			goto failure;
818 		}
819 		if (ret != 128) {
820 			fprintf(stderr, "FAIL: BN_bn2binpad() = %d, want 128\n",
821 			    ret);
822 			goto failure;
823 		}
824 		if (memcmp(&buf[128 - bct->bin_len], bct->bin, bct->bin_len) != 0) {
825 			fprintf(stderr, "FAIL: Test %zu - output from "
826 			    "BN_bn2binpad() differs\n", i);
827 			fprintf(stderr, "Got:\n");
828 			hexdump(&buf[128 - bct->bin_len], bct->bin_len);
829 			fprintf(stderr, "Want:\n");
830 			hexdump(bct->bin, bct->bin_len);
831 			goto failure;
832 		}
833 		for (j = 0; j < 128 - bct->bin_len; j++) {
834 			if (buf[j] != 0) {
835 				fprintf(stderr, "FAIL: BN_bn2binpad() is not "
836 				    "zero padded\n");
837 				goto failure;
838 			}
839 		}
840 
841 		if ((ret = BN_bn2lebinpad(bn, buf, bct->bin_len)) < 0) {
842 			fprintf(stderr, "FAIL: BN_bn2lebinpad() failed\n");
843 			goto failure;
844 		}
845 		if ((size_t)ret != bct->bin_len) {
846 			fprintf(stderr, "FAIL: BN_bn2lebinpad() = %d, want %zu\n",
847 			    ret, bct->bin_len);
848 			goto failure;
849 		}
850 		if (memcmp(buf, lebin, bct->bin_len) != 0) {
851 			fprintf(stderr, "FAIL: Test %zu - output from "
852 			    "BN_bn2lebinpad() differs\n", i);
853 			fprintf(stderr, "Got:\n");
854 			hexdump(buf, bct->bin_len);
855 			fprintf(stderr, "Want:\n");
856 			hexdump(lebin, bct->bin_len);
857 			goto failure;
858 		}
859 		if (bct->bin_len > 0) {
860 			if ((ret = BN_bn2lebinpad(bn, buf, bct->bin_len - 1)) != -1) {
861 				fprintf(stderr, "FAIL: BN_bn2lebinpad() succeeded "
862 				    "with truncation\n");
863 				goto failure;
864 			}
865 		}
866 		if ((ret = BN_bn2lebinpad(bn, buf, 128)) < 0) {
867 			fprintf(stderr, "FAIL: BN_bn2lebinpad() failed\n");
868 			goto failure;
869 		}
870 		if (ret != 128) {
871 			fprintf(stderr, "FAIL: BN_bn2lebinpad() = %d, want 128\n",
872 			    ret);
873 			goto failure;
874 		}
875 		if (memcmp(buf, lebin, bct->bin_len) != 0) {
876 			fprintf(stderr, "FAIL: Test %zu - output from "
877 			    "BN_bn2lebinpad() differs\n", i);
878 			fprintf(stderr, "Got:\n");
879 			hexdump(buf, bct->bin_len);
880 			fprintf(stderr, "Want:\n");
881 			hexdump(lebin, bct->bin_len);
882 			goto failure;
883 		}
884 		for (j = bct->bin_len; j < 128; j++) {
885 			if (buf[j] != 0) {
886 				fprintf(stderr, "FAIL: BN_bn2lebinpad() is not "
887 				    "zero padded\n");
888 				goto failure;
889 			}
890 		}
891 	}
892 
893 	failed = 0;
894 
895  failure:
896 	BN_free(bn);
897 
898 	return failed;
899 }
900 
901 int
902 main(int argc, char **argv)
903 {
904 	int failed = 0;
905 
906 	failed |= test_bn_asc2bn();
907 	failed |= test_bn_convert();
908 	failed |= test_bn_dec2bn();
909 	failed |= test_bn_hex2bn();
910 	failed |= test_bn_binpad();
911 
912 	return failed;
913 }
914