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