1 /* Copyright (C) 1995-1998 Eric Young (eay (at) cryptsoft.com) 2 * All rights reserved. 3 * 4 * This package is an SSL implementation written 5 * by Eric Young (eay (at) cryptsoft.com). 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 (tjh (at) cryptsoft.com). 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 (eay (at) cryptsoft.com)" 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 (tjh (at) cryptsoft.com)" 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 /* ==================================================================== 58 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. 59 * 60 * Portions of the attached software ("Contribution") are developed by 61 * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. 62 * 63 * The Contribution is licensed pursuant to the Eric Young open source 64 * license provided above. 65 * 66 * The binary polynomial arithmetic software is originally written by 67 * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems 68 * Laboratories. */ 69 70 /* For BIGNUM format macros. */ 71 #if !defined(__STDC_FORMAT_MACROS) 72 #define __STDC_FORMAT_MACROS 73 #endif 74 75 #include <errno.h> 76 #include <stdio.h> 77 #include <string.h> 78 79 #include <utility> 80 81 #include <openssl/bn.h> 82 #include <openssl/crypto.h> 83 #include <openssl/err.h> 84 #include <openssl/mem.h> 85 86 #include "../crypto/test/scoped_types.h" 87 #include "../crypto/test/test_util.h" 88 89 90 // This program tests the BIGNUM implementation. It takes an optional -bc 91 // argument to write a transcript compatible with the UNIX bc utility. 92 // 93 // TODO(davidben): Rather than generate random inputs and depend on bc to check 94 // the results, most of these tests should use known answers. 95 96 static const int num0 = 100; // number of tests 97 static const int num1 = 50; // additional tests for some functions 98 static const int num2 = 5; // number of tests for slow functions 99 100 static bool test_add(FILE *fp); 101 static bool test_sub(FILE *fp); 102 static bool test_lshift1(FILE *fp); 103 static bool test_lshift(FILE *fp, BN_CTX *ctx, ScopedBIGNUM a); 104 static bool test_rshift1(FILE *fp); 105 static bool test_rshift(FILE *fp, BN_CTX *ctx); 106 static bool test_sqr(FILE *fp, BN_CTX *ctx); 107 static bool test_mul(FILE *fp); 108 static bool test_div(FILE *fp, BN_CTX *ctx); 109 static int rand_neg(); 110 111 static bool test_div_word(FILE *fp); 112 static bool test_mont(FILE *fp, BN_CTX *ctx); 113 static bool test_mod(FILE *fp, BN_CTX *ctx); 114 static bool test_mod_mul(FILE *fp, BN_CTX *ctx); 115 static bool test_mod_exp(FILE *fp, BN_CTX *ctx); 116 static bool test_mod_exp_mont_consttime(FILE *fp, BN_CTX *ctx); 117 static bool test_exp(FILE *fp, BN_CTX *ctx); 118 static bool test_mod_sqrt(FILE *fp, BN_CTX *ctx); 119 static bool test_exp_mod_zero(void); 120 static bool test_small_prime(FILE *fp, BN_CTX *ctx); 121 static bool test_mod_exp_mont5(FILE *fp, BN_CTX *ctx); 122 static bool test_sqrt(FILE *fp, BN_CTX *ctx); 123 static bool test_bn2bin_padded(BN_CTX *ctx); 124 static bool test_dec2bn(BN_CTX *ctx); 125 static bool test_hex2bn(BN_CTX *ctx); 126 static bool test_asc2bn(BN_CTX *ctx); 127 static bool test_mpi(); 128 static bool test_rand(); 129 static bool test_asn1(); 130 131 static const uint8_t kSample[] = 132 "\xC6\x4F\x43\x04\x2A\xEA\xCA\x6E\x58\x36\x80\x5B\xE8\xC9" 133 "\x9B\x04\x5D\x48\x36\xC2\xFD\x16\xC9\x64\xF0"; 134 135 // A wrapper around puts that takes its arguments in the same order as our *_fp 136 // functions. 137 static void puts_fp(FILE *out, const char *m) { 138 if (out != nullptr) { 139 fputs(m, out); 140 } 141 } 142 143 static void flush_fp(FILE *out) { 144 if (out != nullptr) { 145 fflush(out); 146 } 147 } 148 149 static void message(FILE *out, const char *m) { 150 puts_fp(out, "print \"test "); 151 puts_fp(out, m); 152 puts_fp(out, "\\n\"\n"); 153 } 154 155 int main(int argc, char *argv[]) { 156 CRYPTO_library_init(); 157 158 ScopedFILE bc_file; 159 argc--; 160 argv++; 161 while (argc >= 1) { 162 if (strcmp(*argv, "-bc") == 0) { 163 if (argc < 2) { 164 fprintf(stderr, "Missing parameter to -bc\n"); 165 return 1; 166 } 167 bc_file.reset(fopen(argv[1], "w+")); 168 if (!bc_file) { 169 fprintf(stderr, "Failed to open %s: %s\n", argv[1], strerror(errno)); 170 } 171 argc--; 172 argv++; 173 } else { 174 fprintf(stderr, "Unknown option: %s\n", argv[0]); 175 return 1; 176 } 177 argc--; 178 argv++; 179 } 180 181 182 ScopedBN_CTX ctx(BN_CTX_new()); 183 if (!ctx) { 184 return 1; 185 } 186 187 puts_fp(bc_file.get(), "/* This script, when run through the UNIX bc utility, " 188 "should produce a sequence of zeros. */\n"); 189 puts_fp(bc_file.get(), "/* tr a-f A-F < bn_test.out | sed s/BAsE/base/ | bc " 190 "| grep -v 0 */\n"); 191 puts_fp(bc_file.get(), "obase=16\nibase=16\n"); 192 193 message(bc_file.get(), "BN_add"); 194 if (!test_add(bc_file.get())) { 195 return 1; 196 } 197 flush_fp(bc_file.get()); 198 199 message(bc_file.get(), "BN_sub"); 200 if (!test_sub(bc_file.get())) { 201 return 1; 202 } 203 flush_fp(bc_file.get()); 204 205 message(bc_file.get(), "BN_lshift1"); 206 if (!test_lshift1(bc_file.get())) { 207 return 1; 208 } 209 flush_fp(bc_file.get()); 210 211 message(bc_file.get(), "BN_lshift (fixed)"); 212 ScopedBIGNUM sample(BN_bin2bn(kSample, sizeof(kSample) - 1, NULL)); 213 if (!sample) { 214 return 1; 215 } 216 if (!test_lshift(bc_file.get(), ctx.get(), std::move(sample))) { 217 return 1; 218 } 219 flush_fp(bc_file.get()); 220 221 message(bc_file.get(), "BN_lshift"); 222 if (!test_lshift(bc_file.get(), ctx.get(), nullptr)) { 223 return 1; 224 } 225 flush_fp(bc_file.get()); 226 227 message(bc_file.get(), "BN_rshift1"); 228 if (!test_rshift1(bc_file.get())) { 229 return 1; 230 } 231 flush_fp(bc_file.get()); 232 233 message(bc_file.get(), "BN_rshift"); 234 if (!test_rshift(bc_file.get(), ctx.get())) { 235 return 1; 236 } 237 flush_fp(bc_file.get()); 238 239 message(bc_file.get(), "BN_sqr"); 240 if (!test_sqr(bc_file.get(), ctx.get())) { 241 return 1; 242 } 243 flush_fp(bc_file.get()); 244 245 message(bc_file.get(), "BN_mul"); 246 if (!test_mul(bc_file.get())) { 247 return 1; 248 } 249 flush_fp(bc_file.get()); 250 251 message(bc_file.get(), "BN_div"); 252 if (!test_div(bc_file.get(), ctx.get())) { 253 return 1; 254 } 255 flush_fp(bc_file.get()); 256 257 message(bc_file.get(), "BN_div_word"); 258 if (!test_div_word(bc_file.get())) { 259 return 1; 260 } 261 flush_fp(bc_file.get()); 262 263 message(bc_file.get(), "BN_mod"); 264 if (!test_mod(bc_file.get(), ctx.get())) { 265 return 1; 266 } 267 flush_fp(bc_file.get()); 268 269 message(bc_file.get(), "BN_mod_mul"); 270 if (!test_mod_mul(bc_file.get(), ctx.get())) { 271 return 1; 272 } 273 flush_fp(bc_file.get()); 274 275 message(bc_file.get(), "BN_mont"); 276 if (!test_mont(bc_file.get(), ctx.get())) { 277 return 1; 278 } 279 flush_fp(bc_file.get()); 280 281 message(bc_file.get(), "BN_mod_exp"); 282 if (!test_mod_exp(bc_file.get(), ctx.get())) { 283 return 1; 284 } 285 flush_fp(bc_file.get()); 286 287 message(bc_file.get(), "BN_mod_exp_mont_consttime"); 288 if (!test_mod_exp_mont_consttime(bc_file.get(), ctx.get()) || 289 !test_mod_exp_mont5(bc_file.get(), ctx.get())) { 290 return 1; 291 } 292 flush_fp(bc_file.get()); 293 294 message(bc_file.get(), "BN_exp"); 295 if (!test_exp(bc_file.get(), ctx.get()) || 296 !test_exp_mod_zero()) { 297 return 1; 298 } 299 flush_fp(bc_file.get()); 300 301 message(bc_file.get(), "BN_mod_sqrt"); 302 if (!test_mod_sqrt(bc_file.get(), ctx.get())) { 303 return 1; 304 } 305 flush_fp(bc_file.get()); 306 307 message(bc_file.get(), "Small prime generation"); 308 if (!test_small_prime(bc_file.get(), ctx.get())) { 309 return 1; 310 } 311 flush_fp(bc_file.get()); 312 313 message(bc_file.get(), "BN_sqrt"); 314 if (!test_sqrt(bc_file.get(), ctx.get())) { 315 return 1; 316 } 317 flush_fp(bc_file.get()); 318 319 if (!test_bn2bin_padded(ctx.get()) || 320 !test_dec2bn(ctx.get()) || 321 !test_hex2bn(ctx.get()) || 322 !test_asc2bn(ctx.get()) || 323 !test_mpi() || 324 !test_rand() || 325 !test_asn1()) { 326 return 1; 327 } 328 329 printf("PASS\n"); 330 return 0; 331 } 332 333 static int HexToBIGNUM(ScopedBIGNUM *out, const char *in) { 334 BIGNUM *raw = NULL; 335 int ret = BN_hex2bn(&raw, in); 336 out->reset(raw); 337 return ret; 338 } 339 340 static bool test_add(FILE *fp) { 341 ScopedBIGNUM a(BN_new()); 342 ScopedBIGNUM b(BN_new()); 343 ScopedBIGNUM c(BN_new()); 344 if (!a || !b || !c || !BN_rand(a.get(), 512, 0, 0)) { 345 return false; 346 } 347 348 for (int i = 0; i < num0; i++) { 349 if (!BN_rand(b.get(), 450 + i, 0, 0)) { 350 return false; 351 } 352 a->neg = rand_neg(); 353 b->neg = rand_neg(); 354 if (!BN_add(c.get(), a.get(), b.get())) { 355 return false; 356 } 357 if (fp != NULL) { 358 BN_print_fp(fp, a.get()); 359 puts_fp(fp, " + "); 360 BN_print_fp(fp, b.get()); 361 puts_fp(fp, " - "); 362 BN_print_fp(fp, c.get()); 363 puts_fp(fp, "\n"); 364 } 365 a->neg = !a->neg; 366 b->neg = !b->neg; 367 if (!BN_add(c.get(), c.get(), b.get()) || 368 !BN_add(c.get(), c.get(), a.get())) { 369 return false; 370 } 371 if (!BN_is_zero(c.get())) { 372 fprintf(stderr, "Add test failed!\n"); 373 return false; 374 } 375 } 376 return true; 377 } 378 379 static bool test_sub(FILE *fp) { 380 ScopedBIGNUM a(BN_new()); 381 ScopedBIGNUM b(BN_new()); 382 ScopedBIGNUM c(BN_new()); 383 if (!a || !b || !c) { 384 return false; 385 } 386 387 for (int i = 0; i < num0 + num1; i++) { 388 if (i < num1) { 389 if (!BN_rand(a.get(), 512, 0, 0) || 390 !BN_copy(b.get(), a.get()) || 391 !BN_set_bit(a.get(), i) || 392 !BN_add_word(b.get(), i)) { 393 return false; 394 } 395 } else { 396 if (!BN_rand(b.get(), 400 + i - num1, 0, 0)) { 397 return false; 398 } 399 a->neg = rand_neg(); 400 b->neg = rand_neg(); 401 } 402 if (!BN_sub(c.get(), a.get(), b.get())) { 403 return false; 404 } 405 if (fp != NULL) { 406 BN_print_fp(fp, a.get()); 407 puts_fp(fp, " - "); 408 BN_print_fp(fp, b.get()); 409 puts_fp(fp, " - "); 410 BN_print_fp(fp, c.get()); 411 puts_fp(fp, "\n"); 412 } 413 if (!BN_add(c.get(), c.get(), b.get()) || 414 !BN_sub(c.get(), c.get(), a.get())) { 415 return false; 416 } 417 if (!BN_is_zero(c.get())) { 418 fprintf(stderr, "Subtract test failed!\n"); 419 return false; 420 } 421 } 422 return true; 423 } 424 425 static bool test_div(FILE *fp, BN_CTX *ctx) { 426 ScopedBIGNUM a(BN_new()); 427 ScopedBIGNUM b(BN_new()); 428 ScopedBIGNUM c(BN_new()); 429 ScopedBIGNUM d(BN_new()); 430 ScopedBIGNUM e(BN_new()); 431 if (!a || !b || !c || !d || !e) { 432 return false; 433 } 434 435 if (!BN_one(a.get())) { 436 return false; 437 } 438 BN_zero(b.get()); 439 if (BN_div(d.get(), c.get(), a.get(), b.get(), ctx)) { 440 fprintf(stderr, "Division by zero succeeded!\n"); 441 return false; 442 } 443 ERR_clear_error(); 444 445 for (int i = 0; i < num0 + num1; i++) { 446 if (i < num1) { 447 if (!BN_rand(a.get(), 400, 0, 0) || 448 !BN_copy(b.get(), a.get()) || 449 !BN_lshift(a.get(), a.get(), i) || 450 !BN_add_word(a.get(), i)) { 451 return false; 452 } 453 } else if (!BN_rand(b.get(), 50 + 3 * (i - num1), 0, 0)) { 454 return false; 455 } 456 a->neg = rand_neg(); 457 b->neg = rand_neg(); 458 if (!BN_div(d.get(), c.get(), a.get(), b.get(), ctx)) { 459 return false; 460 } 461 if (fp != NULL) { 462 BN_print_fp(fp, a.get()); 463 puts_fp(fp, " / "); 464 BN_print_fp(fp, b.get()); 465 puts_fp(fp, " - "); 466 BN_print_fp(fp, d.get()); 467 puts_fp(fp, "\n"); 468 469 BN_print_fp(fp, a.get()); 470 puts_fp(fp, " % "); 471 BN_print_fp(fp, b.get()); 472 puts_fp(fp, " - "); 473 BN_print_fp(fp, c.get()); 474 puts_fp(fp, "\n"); 475 } 476 if (!BN_mul(e.get(), d.get(), b.get(), ctx) || 477 !BN_add(d.get(), e.get(), c.get()) || 478 !BN_sub(d.get(), d.get(), a.get())) { 479 return false; 480 } 481 if (!BN_is_zero(d.get())) { 482 fprintf(stderr, "Division test failed!\n"); 483 return false; 484 } 485 } 486 487 // Test that BN_div never gives negative zero in the quotient. 488 if (!BN_set_word(a.get(), 1) || 489 !BN_set_word(b.get(), 2)) { 490 return false; 491 } 492 BN_set_negative(a.get(), 1); 493 if (!BN_div(d.get(), c.get(), a.get(), b.get(), ctx)) { 494 return false; 495 } 496 if (!BN_is_zero(d.get()) || BN_is_negative(d.get())) { 497 fprintf(stderr, "Division test failed!\n"); 498 return false; 499 } 500 501 // Test that BN_div never gives negative zero in the remainder. 502 if (!BN_set_word(b.get(), 1)) { 503 return false; 504 } 505 if (!BN_div(d.get(), c.get(), a.get(), b.get(), ctx)) { 506 return false; 507 } 508 if (!BN_is_zero(c.get()) || BN_is_negative(c.get())) { 509 fprintf(stderr, "Division test failed!\n"); 510 return false; 511 } 512 513 return true; 514 } 515 516 static bool test_lshift1(FILE *fp) { 517 ScopedBIGNUM a(BN_new()); 518 ScopedBIGNUM b(BN_new()); 519 ScopedBIGNUM c(BN_new()); 520 if (!a || !b || !c || !BN_rand(a.get(), 200, 0, 0)) { 521 return false; 522 } 523 a->neg = rand_neg(); 524 for (int i = 0; i < num0; i++) { 525 if (!BN_lshift1(b.get(), a.get())) { 526 return false; 527 } 528 if (fp != NULL) { 529 BN_print_fp(fp, a.get()); 530 puts_fp(fp, " * 2"); 531 puts_fp(fp, " - "); 532 BN_print_fp(fp, b.get()); 533 puts_fp(fp, "\n"); 534 } 535 if (!BN_add(c.get(), a.get(), a.get()) || 536 !BN_sub(a.get(), b.get(), c.get())) { 537 return false; 538 } 539 if (!BN_is_zero(a.get())) { 540 fprintf(stderr, "Left shift one test failed!\n"); 541 return false; 542 } 543 544 if (!BN_copy(a.get(), b.get())) { 545 return false; 546 } 547 } 548 return true; 549 } 550 551 static bool test_rshift(FILE *fp, BN_CTX *ctx) { 552 ScopedBIGNUM a(BN_new()); 553 ScopedBIGNUM b(BN_new()); 554 ScopedBIGNUM c(BN_new()); 555 ScopedBIGNUM d(BN_new()); 556 ScopedBIGNUM e(BN_new()); 557 if (!a || !b || !c || !d || !e || !BN_one(c.get()) || 558 !BN_rand(a.get(), 200, 0, 0)) { 559 return false; 560 } 561 a->neg = rand_neg(); 562 for (int i = 0; i < num0; i++) { 563 if (!BN_rshift(b.get(), a.get(), i + 1) || 564 !BN_add(c.get(), c.get(), c.get())) { 565 return false; 566 } 567 if (fp != NULL) { 568 BN_print_fp(fp, a.get()); 569 puts_fp(fp, " / "); 570 BN_print_fp(fp, c.get()); 571 puts_fp(fp, " - "); 572 BN_print_fp(fp, b.get()); 573 puts_fp(fp, "\n"); 574 } 575 if (!BN_div(d.get(), e.get(), a.get(), c.get(), ctx) || 576 !BN_sub(d.get(), d.get(), b.get())) { 577 return false; 578 } 579 if (!BN_is_zero(d.get())) { 580 fprintf(stderr, "Right shift test failed!\n"); 581 return false; 582 } 583 } 584 return true; 585 } 586 587 static bool test_rshift1(FILE *fp) { 588 ScopedBIGNUM a(BN_new()); 589 ScopedBIGNUM b(BN_new()); 590 ScopedBIGNUM c(BN_new()); 591 if (!a || !b || !c || !BN_rand(a.get(), 200, 0, 0)) { 592 return false; 593 } 594 a->neg = rand_neg(); 595 596 for (int i = 0; i < num0; i++) { 597 if (!BN_rshift1(b.get(), a.get())) { 598 return false; 599 } 600 if (fp != NULL) { 601 BN_print_fp(fp, a.get()); 602 puts_fp(fp, " / 2"); 603 puts_fp(fp, " - "); 604 BN_print_fp(fp, b.get()); 605 puts_fp(fp, "\n"); 606 } 607 if (!BN_sub(c.get(), a.get(), b.get()) || 608 !BN_sub(c.get(), c.get(), b.get())) { 609 return false; 610 } 611 if (!BN_is_zero(c.get()) && !BN_abs_is_word(c.get(), 1)) { 612 fprintf(stderr, "Right shift one test failed!\n"); 613 return false; 614 } 615 if (!BN_copy(a.get(), b.get())) { 616 return false; 617 } 618 } 619 return true; 620 } 621 622 static bool test_lshift(FILE *fp, BN_CTX *ctx, ScopedBIGNUM a) { 623 if (!a) { 624 a.reset(BN_new()); 625 if (!a || !BN_rand(a.get(), 200, 0, 0)) { 626 return false; 627 } 628 a->neg = rand_neg(); 629 } 630 631 ScopedBIGNUM b(BN_new()); 632 ScopedBIGNUM c(BN_new()); 633 ScopedBIGNUM d(BN_new()); 634 if (!b || !c || !d || !BN_one(c.get())) { 635 return false; 636 } 637 638 for (int i = 0; i < num0; i++) { 639 if (!BN_lshift(b.get(), a.get(), i + 1) || 640 !BN_add(c.get(), c.get(), c.get())) { 641 return false; 642 } 643 if (fp != NULL) { 644 BN_print_fp(fp, a.get()); 645 puts_fp(fp, " * "); 646 BN_print_fp(fp, c.get()); 647 puts_fp(fp, " - "); 648 BN_print_fp(fp, b.get()); 649 puts_fp(fp, "\n"); 650 } 651 if (!BN_mul(d.get(), a.get(), c.get(), ctx) || 652 !BN_sub(d.get(), d.get(), b.get())) { 653 return false; 654 } 655 if (!BN_is_zero(d.get())) { 656 fprintf(stderr, "Left shift test failed!\n"); 657 fprintf(stderr, "a="); 658 BN_print_fp(stderr, a.get()); 659 fprintf(stderr, "\nb="); 660 BN_print_fp(stderr, b.get()); 661 fprintf(stderr, "\nc="); 662 BN_print_fp(stderr, c.get()); 663 fprintf(stderr, "\nd="); 664 BN_print_fp(stderr, d.get()); 665 fprintf(stderr, "\n"); 666 return false; 667 } 668 } 669 return true; 670 } 671 672 static bool test_mul(FILE *fp) { 673 ScopedBN_CTX ctx(BN_CTX_new()); 674 ScopedBIGNUM a(BN_new()); 675 ScopedBIGNUM b(BN_new()); 676 ScopedBIGNUM c(BN_new()); 677 ScopedBIGNUM d(BN_new()); 678 ScopedBIGNUM e(BN_new()); 679 if (!ctx || !a || !b || !c || !d || !e) { 680 return false; 681 } 682 683 for (int i = 0; i < num0 + num1; i++) { 684 if (i <= num1) { 685 if (!BN_rand(a.get(), 100, 0, 0) || 686 !BN_rand(b.get(), 100, 0, 0)) { 687 return false; 688 } 689 } else if (!BN_rand(b.get(), i - num1, 0, 0)) { 690 return false; 691 } 692 a->neg = rand_neg(); 693 b->neg = rand_neg(); 694 if (!BN_mul(c.get(), a.get(), b.get(), ctx.get())) { 695 return false; 696 } 697 if (fp != NULL) { 698 BN_print_fp(fp, a.get()); 699 puts_fp(fp, " * "); 700 BN_print_fp(fp, b.get()); 701 puts_fp(fp, " - "); 702 BN_print_fp(fp, c.get()); 703 puts_fp(fp, "\n"); 704 } 705 if (!BN_div(d.get(), e.get(), c.get(), a.get(), ctx.get()) || 706 !BN_sub(d.get(), d.get(), b.get())) { 707 return false; 708 } 709 if (!BN_is_zero(d.get()) || !BN_is_zero(e.get())) { 710 fprintf(stderr, "Multiplication test failed!\n"); 711 return false; 712 } 713 } 714 715 // Test that BN_mul never gives negative zero. 716 if (!BN_set_word(a.get(), 1)) { 717 return false; 718 } 719 BN_set_negative(a.get(), 1); 720 BN_zero(b.get()); 721 if (!BN_mul(c.get(), a.get(), b.get(), ctx.get())) { 722 return false; 723 } 724 if (!BN_is_zero(c.get()) || BN_is_negative(c.get())) { 725 fprintf(stderr, "Multiplication test failed!\n"); 726 return false; 727 } 728 729 return true; 730 } 731 732 static bool test_sqr(FILE *fp, BN_CTX *ctx) { 733 ScopedBIGNUM a(BN_new()); 734 ScopedBIGNUM c(BN_new()); 735 ScopedBIGNUM d(BN_new()); 736 ScopedBIGNUM e(BN_new()); 737 if (!a || !c || !d || !e) { 738 return false; 739 } 740 741 for (int i = 0; i < num0; i++) { 742 if (!BN_rand(a.get(), 40 + i * 10, 0, 0)) { 743 return false; 744 } 745 a->neg = rand_neg(); 746 if (!BN_sqr(c.get(), a.get(), ctx)) { 747 return false; 748 } 749 if (fp != NULL) { 750 BN_print_fp(fp, a.get()); 751 puts_fp(fp, " * "); 752 BN_print_fp(fp, a.get()); 753 puts_fp(fp, " - "); 754 BN_print_fp(fp, c.get()); 755 puts_fp(fp, "\n"); 756 } 757 if (!BN_div(d.get(), e.get(), c.get(), a.get(), ctx) || 758 !BN_sub(d.get(), d.get(), a.get())) { 759 return false; 760 } 761 if (!BN_is_zero(d.get()) || !BN_is_zero(e.get())) { 762 fprintf(stderr, "Square test failed!\n"); 763 return false; 764 } 765 } 766 767 // Regression test for a BN_sqr overflow bug. 768 BIGNUM *a_raw = a.get(); 769 if (!BN_hex2bn( 770 &a_raw, 771 "80000000000000008000000000000001FFFFFFFFFFFFFFFE0000000000000000") || 772 !BN_sqr(c.get(), a.get(), ctx)) { 773 return false; 774 } 775 if (fp != NULL) { 776 BN_print_fp(fp, a.get()); 777 puts_fp(fp, " * "); 778 BN_print_fp(fp, a.get()); 779 puts_fp(fp, " - "); 780 BN_print_fp(fp, c.get()); 781 puts_fp(fp, "\n"); 782 } 783 if (!BN_mul(d.get(), a.get(), a.get(), ctx)) { 784 return false; 785 } 786 if (BN_cmp(c.get(), d.get())) { 787 fprintf(stderr, 788 "Square test failed: BN_sqr and BN_mul produce " 789 "different results!\n"); 790 return false; 791 } 792 793 // Regression test for a BN_sqr overflow bug. 794 a_raw = a.get(); 795 if (!BN_hex2bn( 796 &a_raw, 797 "80000000000000000000000080000001FFFFFFFE000000000000000000000000") || 798 !BN_sqr(c.get(), a.get(), ctx)) { 799 return false; 800 } 801 if (fp != NULL) { 802 BN_print_fp(fp, a.get()); 803 puts_fp(fp, " * "); 804 BN_print_fp(fp, a.get()); 805 puts_fp(fp, " - "); 806 BN_print_fp(fp, c.get()); 807 puts_fp(fp, "\n"); 808 } 809 if (!BN_mul(d.get(), a.get(), a.get(), ctx)) { 810 return false; 811 } 812 if (BN_cmp(c.get(), d.get())) { 813 fprintf(stderr, 814 "Square test failed: BN_sqr and BN_mul produce " 815 "different results!\n"); 816 return false; 817 } 818 819 return true; 820 } 821 822 823 static int rand_neg() { 824 static unsigned int neg = 0; 825 static const int sign[8] = {0, 0, 0, 1, 1, 0, 1, 1}; 826 827 return sign[(neg++) % 8]; 828 } 829 830 static void print_word(FILE *fp, BN_ULONG w) { 831 fprintf(fp, BN_HEX_FMT1, w); 832 } 833 834 static bool test_div_word(FILE *fp) { 835 ScopedBIGNUM a(BN_new()); 836 ScopedBIGNUM b(BN_new()); 837 if (!a || !b) { 838 return false; 839 } 840 841 for (int i = 0; i < num0; i++) { 842 do { 843 if (!BN_rand(a.get(), 512, -1, 0) || 844 !BN_rand(b.get(), BN_BITS2, -1, 0)) { 845 return false; 846 } 847 } while (BN_is_zero(b.get())); 848 849 if (!BN_copy(b.get(), a.get())) { 850 return false; 851 } 852 BN_ULONG s = b->d[0]; 853 BN_ULONG r = BN_div_word(b.get(), s); 854 if (r == (BN_ULONG)-1) { 855 return false; 856 } 857 858 if (fp != NULL) { 859 BN_print_fp(fp, a.get()); 860 puts_fp(fp, " / "); 861 print_word(fp, s); 862 puts_fp(fp, " - "); 863 BN_print_fp(fp, b.get()); 864 puts_fp(fp, "\n"); 865 866 BN_print_fp(fp, a.get()); 867 puts_fp(fp, " % "); 868 print_word(fp, s); 869 puts_fp(fp, " - "); 870 print_word(fp, r); 871 puts_fp(fp, "\n"); 872 } 873 if (!BN_mul_word(b.get(), s) || 874 !BN_add_word(b.get(), r) || 875 !BN_sub(b.get(), a.get(), b.get())) { 876 return false; 877 } 878 if (!BN_is_zero(b.get())) { 879 fprintf(stderr, "Division (word) test failed!\n"); 880 return false; 881 } 882 } 883 return true; 884 } 885 886 static bool test_mont(FILE *fp, BN_CTX *ctx) { 887 ScopedBIGNUM a(BN_new()); 888 ScopedBIGNUM b(BN_new()); 889 ScopedBIGNUM c(BN_new()); 890 ScopedBIGNUM d(BN_new()); 891 ScopedBIGNUM A(BN_new()); 892 ScopedBIGNUM B(BN_new()); 893 ScopedBIGNUM n(BN_new()); 894 ScopedBN_MONT_CTX mont(BN_MONT_CTX_new()); 895 if (!a || !b || !c || !d || !A || !B || !n || !mont) { 896 return false; 897 } 898 899 BN_zero(n.get()); 900 if (BN_MONT_CTX_set(mont.get(), n.get(), ctx)) { 901 fprintf(stderr, "BN_MONT_CTX_set succeeded for zero modulus!\n"); 902 return false; 903 } 904 ERR_clear_error(); 905 906 if (!BN_set_word(n.get(), 16)) { 907 return false; 908 } 909 if (BN_MONT_CTX_set(mont.get(), n.get(), ctx)) { 910 fprintf(stderr, "BN_MONT_CTX_set succeeded for even modulus!\n"); 911 return false; 912 } 913 ERR_clear_error(); 914 915 if (!BN_rand(a.get(), 100, 0, 0) || 916 !BN_rand(b.get(), 100, 0, 0)) { 917 return false; 918 } 919 920 for (int i = 0; i < num2; i++) { 921 int bits = (200 * (i + 1)) / num2; 922 923 if (bits == 0) { 924 continue; 925 } 926 if (!BN_rand(n.get(), bits, 0, 1) || 927 !BN_MONT_CTX_set(mont.get(), n.get(), ctx) || 928 !BN_nnmod(a.get(), a.get(), n.get(), ctx) || 929 !BN_nnmod(b.get(), b.get(), n.get(), ctx) || 930 !BN_to_montgomery(A.get(), a.get(), mont.get(), ctx) || 931 !BN_to_montgomery(B.get(), b.get(), mont.get(), ctx) || 932 !BN_mod_mul_montgomery(c.get(), A.get(), B.get(), mont.get(), ctx) || 933 !BN_from_montgomery(A.get(), c.get(), mont.get(), ctx)) { 934 return false; 935 } 936 if (fp != NULL) { 937 BN_print_fp(fp, a.get()); 938 puts_fp(fp, " * "); 939 BN_print_fp(fp, b.get()); 940 puts_fp(fp, " % "); 941 BN_print_fp(fp, &mont->N); 942 puts_fp(fp, " - "); 943 BN_print_fp(fp, A.get()); 944 puts_fp(fp, "\n"); 945 } 946 if (!BN_mod_mul(d.get(), a.get(), b.get(), n.get(), ctx) || 947 !BN_sub(d.get(), d.get(), A.get())) { 948 return false; 949 } 950 if (!BN_is_zero(d.get())) { 951 fprintf(stderr, "Montgomery multiplication test failed!\n"); 952 return false; 953 } 954 } 955 956 return true; 957 } 958 959 static bool test_mod(FILE *fp, BN_CTX *ctx) { 960 ScopedBIGNUM a(BN_new()); 961 ScopedBIGNUM b(BN_new()); 962 ScopedBIGNUM c(BN_new()); 963 ScopedBIGNUM d(BN_new()); 964 ScopedBIGNUM e(BN_new()); 965 if (!a || !b || !c || !d || !e || 966 !BN_rand(a.get(), 1024, 0, 0)) { 967 return false; 968 } 969 970 for (int i = 0; i < num0; i++) { 971 if (!BN_rand(b.get(), 450 + i * 10, 0, 0)) { 972 return false; 973 } 974 a->neg = rand_neg(); 975 b->neg = rand_neg(); 976 if (!BN_mod(c.get(), a.get(), b.get(), ctx)) { 977 return false; 978 } 979 if (fp != NULL) { 980 BN_print_fp(fp, a.get()); 981 puts_fp(fp, " % "); 982 BN_print_fp(fp, b.get()); 983 puts_fp(fp, " - "); 984 BN_print_fp(fp, c.get()); 985 puts_fp(fp, "\n"); 986 } 987 if (!BN_div(d.get(), e.get(), a.get(), b.get(), ctx) || 988 !BN_sub(e.get(), e.get(), c.get())) { 989 return false; 990 } 991 if (!BN_is_zero(e.get())) { 992 fprintf(stderr, "Modulo test failed!\n"); 993 return false; 994 } 995 } 996 return true; 997 } 998 999 static bool test_mod_mul(FILE *fp, BN_CTX *ctx) { 1000 ScopedBIGNUM a(BN_new()); 1001 ScopedBIGNUM b(BN_new()); 1002 ScopedBIGNUM c(BN_new()); 1003 ScopedBIGNUM d(BN_new()); 1004 ScopedBIGNUM e(BN_new()); 1005 if (!a || !b || !c || !d || !e) { 1006 return false; 1007 } 1008 1009 if (!BN_one(a.get()) || !BN_one(b.get())) { 1010 return false; 1011 } 1012 BN_zero(c.get()); 1013 if (BN_mod_mul(e.get(), a.get(), b.get(), c.get(), ctx)) { 1014 fprintf(stderr, "BN_mod_mul with zero modulus succeeded!\n"); 1015 return false; 1016 } 1017 ERR_clear_error(); 1018 1019 for (int j = 0; j < 3; j++) { 1020 if (!BN_rand(c.get(), 1024, 0, 0)) { 1021 return false; 1022 } 1023 for (int i = 0; i < num0; i++) { 1024 if (!BN_rand(a.get(), 475 + i * 10, 0, 0) || 1025 !BN_rand(b.get(), 425 + i * 11, 0, 0)) { 1026 return false; 1027 } 1028 a->neg = rand_neg(); 1029 b->neg = rand_neg(); 1030 if (!BN_mod_mul(e.get(), a.get(), b.get(), c.get(), ctx)) { 1031 ERR_print_errors_fp(stderr); 1032 return false; 1033 } 1034 if (fp != NULL) { 1035 BN_print_fp(fp, a.get()); 1036 puts_fp(fp, " * "); 1037 BN_print_fp(fp, b.get()); 1038 puts_fp(fp, " % "); 1039 BN_print_fp(fp, c.get()); 1040 if (a->neg != b->neg && !BN_is_zero(e.get())) { 1041 // If (a*b) % c is negative, c must be added 1042 // in order to obtain the normalized remainder 1043 // (new with OpenSSL 0.9.7, previous versions of 1044 // BN_mod_mul could generate negative results) 1045 puts_fp(fp, " + "); 1046 BN_print_fp(fp, c.get()); 1047 } 1048 puts_fp(fp, " - "); 1049 BN_print_fp(fp, e.get()); 1050 puts_fp(fp, "\n"); 1051 } 1052 if (!BN_mul(d.get(), a.get(), b.get(), ctx) || 1053 !BN_sub(d.get(), d.get(), e.get()) || 1054 !BN_div(a.get(), b.get(), d.get(), c.get(), ctx)) { 1055 return false; 1056 } 1057 if (!BN_is_zero(b.get())) { 1058 fprintf(stderr, "Modulo multiply test failed!\n"); 1059 ERR_print_errors_fp(stderr); 1060 return false; 1061 } 1062 } 1063 } 1064 return true; 1065 } 1066 1067 static bool test_mod_exp(FILE *fp, BN_CTX *ctx) { 1068 ScopedBIGNUM a(BN_new()); 1069 ScopedBIGNUM b(BN_new()); 1070 ScopedBIGNUM c(BN_new()); 1071 ScopedBIGNUM d(BN_new()); 1072 ScopedBIGNUM e(BN_new()); 1073 if (!a || !b || !c || !d || !e) { 1074 return false; 1075 } 1076 1077 if (!BN_one(a.get()) || !BN_one(b.get())) { 1078 return false; 1079 } 1080 BN_zero(c.get()); 1081 if (BN_mod_exp(d.get(), a.get(), b.get(), c.get(), ctx)) { 1082 fprintf(stderr, "BN_mod_exp with zero modulus succeeded!\n"); 1083 return 0; 1084 } 1085 ERR_clear_error(); 1086 1087 if (!BN_rand(c.get(), 30, 0, 1)) { // must be odd for montgomery 1088 return false; 1089 } 1090 for (int i = 0; i < num2; i++) { 1091 if (!BN_rand(a.get(), 20 + i * 5, 0, 0) || 1092 !BN_rand(b.get(), 2 + i, 0, 0) || 1093 !BN_mod_exp(d.get(), a.get(), b.get(), c.get(), ctx)) { 1094 return false; 1095 } 1096 1097 if (fp != NULL) { 1098 BN_print_fp(fp, a.get()); 1099 puts_fp(fp, " ^ "); 1100 BN_print_fp(fp, b.get()); 1101 puts_fp(fp, " % "); 1102 BN_print_fp(fp, c.get()); 1103 puts_fp(fp, " - "); 1104 BN_print_fp(fp, d.get()); 1105 puts_fp(fp, "\n"); 1106 } 1107 if (!BN_exp(e.get(), a.get(), b.get(), ctx) || 1108 !BN_sub(e.get(), e.get(), d.get()) || 1109 !BN_div(a.get(), b.get(), e.get(), c.get(), ctx)) { 1110 return false; 1111 } 1112 if (!BN_is_zero(b.get())) { 1113 fprintf(stderr, "Modulo exponentiation test failed!\n"); 1114 return false; 1115 } 1116 } 1117 1118 // Regression test for carry propagation bug in sqr8x_reduction. 1119 if (!HexToBIGNUM(&a, "050505050505") || 1120 !HexToBIGNUM(&b, "02") || 1121 !HexToBIGNUM( 1122 &c, 1123 "4141414141414141414141274141414141414141414141414141414141414141" 1124 "4141414141414141414141414141414141414141414141414141414141414141" 1125 "4141414141414141414141800000000000000000000000000000000000000000" 1126 "0000000000000000000000000000000000000000000000000000000000000000" 1127 "0000000000000000000000000000000000000000000000000000000000000000" 1128 "0000000000000000000000000000000000000000000000000000000001") || 1129 !BN_mod_exp(d.get(), a.get(), b.get(), c.get(), ctx) || 1130 !BN_mul(e.get(), a.get(), a.get(), ctx)) { 1131 return false; 1132 } 1133 if (BN_cmp(d.get(), e.get()) != 0) { 1134 fprintf(stderr, "BN_mod_exp and BN_mul produce different results!\n"); 1135 return false; 1136 } 1137 1138 return true; 1139 } 1140 1141 static bool test_mod_exp_mont_consttime(FILE *fp, BN_CTX *ctx) { 1142 ScopedBIGNUM a(BN_new()); 1143 ScopedBIGNUM b(BN_new()); 1144 ScopedBIGNUM c(BN_new()); 1145 ScopedBIGNUM d(BN_new()); 1146 ScopedBIGNUM e(BN_new()); 1147 if (!a || !b || !c || !d || !e) { 1148 return false; 1149 } 1150 1151 if (!BN_one(a.get()) || !BN_one(b.get())) { 1152 return false; 1153 } 1154 BN_zero(c.get()); 1155 if (BN_mod_exp_mont_consttime(d.get(), a.get(), b.get(), c.get(), ctx, 1156 nullptr)) { 1157 fprintf(stderr, "BN_mod_exp_mont_consttime with zero modulus succeeded!\n"); 1158 return 0; 1159 } 1160 ERR_clear_error(); 1161 1162 if (!BN_set_word(c.get(), 16)) { 1163 return false; 1164 } 1165 if (BN_mod_exp_mont_consttime(d.get(), a.get(), b.get(), c.get(), ctx, 1166 nullptr)) { 1167 fprintf(stderr, "BN_mod_exp_mont_consttime with even modulus succeeded!\n"); 1168 return 0; 1169 } 1170 ERR_clear_error(); 1171 1172 if (!BN_rand(c.get(), 30, 0, 1)) { // must be odd for montgomery 1173 return false; 1174 } 1175 for (int i = 0; i < num2; i++) { 1176 if (!BN_rand(a.get(), 20 + i * 5, 0, 0) || 1177 !BN_rand(b.get(), 2 + i, 0, 0) || 1178 !BN_mod_exp_mont_consttime(d.get(), a.get(), b.get(), c.get(), ctx, 1179 NULL)) { 1180 return false; 1181 } 1182 1183 if (fp != NULL) { 1184 BN_print_fp(fp, a.get()); 1185 puts_fp(fp, " ^ "); 1186 BN_print_fp(fp, b.get()); 1187 puts_fp(fp, " % "); 1188 BN_print_fp(fp, c.get()); 1189 puts_fp(fp, " - "); 1190 BN_print_fp(fp, d.get()); 1191 puts_fp(fp, "\n"); 1192 } 1193 if (!BN_exp(e.get(), a.get(), b.get(), ctx) || 1194 !BN_sub(e.get(), e.get(), d.get()) || 1195 !BN_div(a.get(), b.get(), e.get(), c.get(), ctx)) { 1196 return false; 1197 } 1198 if (!BN_is_zero(b.get())) { 1199 fprintf(stderr, "Modulo exponentiation test failed!\n"); 1200 return false; 1201 } 1202 } 1203 return true; 1204 } 1205 1206 // Test constant-time modular exponentiation with 1024-bit inputs, 1207 // which on x86_64 cause a different code branch to be taken. 1208 static bool test_mod_exp_mont5(FILE *fp, BN_CTX *ctx) { 1209 ScopedBIGNUM a(BN_new()); 1210 ScopedBIGNUM p(BN_new()); 1211 ScopedBIGNUM m(BN_new()); 1212 ScopedBIGNUM d(BN_new()); 1213 ScopedBIGNUM e(BN_new()); 1214 if (!a || !p || !m || !d || !e || 1215 !BN_rand(m.get(), 1024, 0, 1) || // must be odd for montgomery 1216 !BN_rand(a.get(), 1024, 0, 0)) { 1217 return false; 1218 } 1219 // Zero exponent. 1220 BN_zero(p.get()); 1221 if (!BN_mod_exp_mont_consttime(d.get(), a.get(), p.get(), m.get(), ctx, 1222 NULL)) { 1223 return false; 1224 } 1225 if (!BN_is_one(d.get())) { 1226 fprintf(stderr, "Modular exponentiation test failed!\n"); 1227 return false; 1228 } 1229 if (!BN_rand(p.get(), 1024, 0, 0)) { 1230 return false; 1231 } 1232 // Zero input. 1233 BN_zero(a.get()); 1234 if (!BN_mod_exp_mont_consttime(d.get(), a.get(), p.get(), m.get(), ctx, 1235 NULL)) { 1236 return false; 1237 } 1238 if (!BN_is_zero(d.get())) { 1239 fprintf(stderr, "Modular exponentiation test failed!\n"); 1240 return false; 1241 } 1242 // Craft an input whose Montgomery representation is 1, i.e., shorter than the 1243 // modulus m, in order to test the const time precomputation 1244 // scattering/gathering. 1245 ScopedBN_MONT_CTX mont(BN_MONT_CTX_new()); 1246 if (!mont || !BN_one(a.get()) || 1247 !BN_MONT_CTX_set(mont.get(), m.get(), ctx) || 1248 !BN_from_montgomery(e.get(), a.get(), mont.get(), ctx) || 1249 !BN_mod_exp_mont_consttime(d.get(), e.get(), p.get(), m.get(), ctx, 1250 NULL) || 1251 !BN_mod_exp(a.get(), e.get(), p.get(), m.get(), ctx)) { 1252 return false; 1253 } 1254 if (BN_cmp(a.get(), d.get()) != 0) { 1255 fprintf(stderr, "Modular exponentiation test failed!\n"); 1256 return false; 1257 } 1258 // Finally, some regular test vectors. 1259 if (!BN_rand(e.get(), 1024, 0, 0) || 1260 !BN_mod_exp_mont_consttime(d.get(), e.get(), p.get(), m.get(), ctx, 1261 NULL) || 1262 !BN_mod_exp(a.get(), e.get(), p.get(), m.get(), ctx)) { 1263 return false; 1264 } 1265 if (BN_cmp(a.get(), d.get()) != 0) { 1266 fprintf(stderr, "Modular exponentiation test failed!\n"); 1267 return false; 1268 } 1269 1270 return true; 1271 } 1272 1273 static bool test_exp(FILE *fp, BN_CTX *ctx) { 1274 ScopedBIGNUM a(BN_new()); 1275 ScopedBIGNUM b(BN_new()); 1276 ScopedBIGNUM d(BN_new()); 1277 ScopedBIGNUM e(BN_new()); 1278 if (!a || !b || !d || !e) { 1279 return false; 1280 } 1281 1282 for (int i = 0; i < num2; i++) { 1283 if (!BN_rand(a.get(), 20 + i * 5, 0, 0) || 1284 !BN_rand(b.get(), 2 + i, 0, 0) || 1285 !BN_exp(d.get(), a.get(), b.get(), ctx)) { 1286 return false; 1287 } 1288 1289 if (fp != NULL) { 1290 BN_print_fp(fp, a.get()); 1291 puts_fp(fp, " ^ "); 1292 BN_print_fp(fp, b.get()); 1293 puts_fp(fp, " - "); 1294 BN_print_fp(fp, d.get()); 1295 puts_fp(fp, "\n"); 1296 } 1297 if (!BN_one(e.get())) { 1298 return false; 1299 } 1300 while (!BN_is_zero(b.get())) { 1301 if (!BN_mul(e.get(), e.get(), a.get(), ctx) || 1302 !BN_sub(b.get(), b.get(), BN_value_one())) { 1303 return false; 1304 } 1305 } 1306 if (!BN_sub(e.get(), e.get(), d.get())) { 1307 return false; 1308 } 1309 if (!BN_is_zero(e.get())) { 1310 fprintf(stderr, "Exponentiation test failed!\n"); 1311 return false; 1312 } 1313 } 1314 return true; 1315 } 1316 1317 // test_exp_mod_zero tests that 1**0 mod 1 == 0. 1318 static bool test_exp_mod_zero(void) { 1319 ScopedBIGNUM zero(BN_new()), a(BN_new()), r(BN_new()); 1320 if (!zero || !a || !r || !BN_rand(a.get(), 1024, 0, 0)) { 1321 return false; 1322 } 1323 BN_zero(zero.get()); 1324 1325 if (!BN_mod_exp(r.get(), a.get(), zero.get(), BN_value_one(), nullptr) || 1326 !BN_is_zero(r.get()) || 1327 !BN_mod_exp_mont(r.get(), a.get(), zero.get(), BN_value_one(), nullptr, 1328 nullptr) || 1329 !BN_is_zero(r.get()) || 1330 !BN_mod_exp_mont_consttime(r.get(), a.get(), zero.get(), BN_value_one(), 1331 nullptr, nullptr) || 1332 !BN_is_zero(r.get()) || 1333 !BN_mod_exp_mont_word(r.get(), 42, zero.get(), BN_value_one(), nullptr, 1334 nullptr) || 1335 !BN_is_zero(r.get())) { 1336 return false; 1337 } 1338 1339 return true; 1340 } 1341 1342 static bool test_mod_sqrt(FILE *fp, BN_CTX *ctx) { 1343 ScopedBIGNUM a(BN_new()); 1344 ScopedBIGNUM p(BN_new()); 1345 ScopedBIGNUM r(BN_new()); 1346 if (!a || !p || !r) { 1347 return false; 1348 } 1349 1350 for (int i = 0; i < 16; i++) { 1351 if (i < 8) { 1352 const unsigned kPrimes[8] = {2, 3, 5, 7, 11, 13, 17, 19}; 1353 if (!BN_set_word(p.get(), kPrimes[i])) { 1354 return false; 1355 } 1356 } else { 1357 if (!BN_set_word(a.get(), 32) || 1358 !BN_set_word(r.get(), 2 * i + 1) || 1359 !BN_generate_prime_ex(p.get(), 256, 0, a.get(), r.get(), nullptr)) { 1360 return false; 1361 } 1362 } 1363 p->neg = rand_neg(); 1364 1365 for (int j = 0; j < num2; j++) { 1366 // construct 'a' such that it is a square modulo p, but in general not a 1367 // proper square and not reduced modulo p 1368 if (!BN_rand(r.get(), 256, 0, 3) || 1369 !BN_nnmod(r.get(), r.get(), p.get(), ctx) || 1370 !BN_mod_sqr(r.get(), r.get(), p.get(), ctx) || 1371 !BN_rand(a.get(), 256, 0, 3) || 1372 !BN_nnmod(a.get(), a.get(), p.get(), ctx) || 1373 !BN_mod_sqr(a.get(), a.get(), p.get(), ctx) || 1374 !BN_mul(a.get(), a.get(), r.get(), ctx)) { 1375 return false; 1376 } 1377 if (rand_neg() && !BN_sub(a.get(), a.get(), p.get())) { 1378 return false; 1379 } 1380 1381 if (!BN_mod_sqrt(r.get(), a.get(), p.get(), ctx) || 1382 !BN_mod_sqr(r.get(), r.get(), p.get(), ctx) || 1383 !BN_nnmod(a.get(), a.get(), p.get(), ctx)) { 1384 return false; 1385 } 1386 1387 if (BN_cmp(a.get(), r.get()) != 0) { 1388 fprintf(stderr, "BN_mod_sqrt failed: a = "); 1389 BN_print_fp(stderr, a.get()); 1390 fprintf(stderr, ", r = "); 1391 BN_print_fp(stderr, r.get()); 1392 fprintf(stderr, ", p = "); 1393 BN_print_fp(stderr, p.get()); 1394 fprintf(stderr, "\n"); 1395 return false; 1396 } 1397 } 1398 } 1399 return true; 1400 } 1401 1402 static bool test_small_prime(FILE *fp, BN_CTX *ctx) { 1403 static const unsigned kBits = 10; 1404 1405 ScopedBIGNUM r(BN_new()); 1406 if (!r || !BN_generate_prime_ex(r.get(), static_cast<int>(kBits), 0, NULL, 1407 NULL, NULL)) { 1408 return false; 1409 } 1410 if (BN_num_bits(r.get()) != kBits) { 1411 fprintf(fp, "Expected %u bit prime, got %u bit number\n", kBits, 1412 BN_num_bits(r.get())); 1413 return false; 1414 } 1415 1416 return true; 1417 } 1418 1419 static bool test_sqrt(FILE *fp, BN_CTX *ctx) { 1420 ScopedBIGNUM n(BN_new()); 1421 ScopedBIGNUM nn(BN_new()); 1422 ScopedBIGNUM sqrt(BN_new()); 1423 if (!n || !nn || !sqrt) { 1424 return false; 1425 } 1426 1427 // Test some random squares. 1428 for (int i = 0; i < 100; i++) { 1429 if (!BN_rand(n.get(), 1024 /* bit length */, 1430 -1 /* no modification of top bits */, 1431 0 /* don't modify bottom bit */) || 1432 !BN_mul(nn.get(), n.get(), n.get(), ctx) || 1433 !BN_sqrt(sqrt.get(), nn.get(), ctx)) { 1434 ERR_print_errors_fp(stderr); 1435 return false; 1436 } 1437 if (BN_cmp(n.get(), sqrt.get()) != 0) { 1438 fprintf(stderr, "Bad result from BN_sqrt.\n"); 1439 return false; 1440 } 1441 } 1442 1443 // Test some non-squares. 1444 for (int i = 0; i < 100; i++) { 1445 if (!BN_rand(n.get(), 1024 /* bit length */, 1446 -1 /* no modification of top bits */, 1447 0 /* don't modify bottom bit */) || 1448 !BN_mul(nn.get(), n.get(), n.get(), ctx) || 1449 !BN_add(nn.get(), nn.get(), BN_value_one())) { 1450 ERR_print_errors_fp(stderr); 1451 return false; 1452 } 1453 1454 if (BN_sqrt(sqrt.get(), nn.get(), ctx)) { 1455 char *nn_str = BN_bn2dec(nn.get()); 1456 fprintf(stderr, "BIO_sqrt didn't fail on a non-square: %s\n", nn_str); 1457 OPENSSL_free(nn_str); 1458 } 1459 } 1460 1461 return true; 1462 } 1463 1464 static bool test_bn2bin_padded(BN_CTX *ctx) { 1465 uint8_t zeros[256], out[256], reference[128]; 1466 1467 memset(zeros, 0, sizeof(zeros)); 1468 1469 // Test edge case at 0. 1470 ScopedBIGNUM n(BN_new()); 1471 if (!n || !BN_bn2bin_padded(NULL, 0, n.get())) { 1472 fprintf(stderr, 1473 "BN_bn2bin_padded failed to encode 0 in an empty buffer.\n"); 1474 return false; 1475 } 1476 memset(out, -1, sizeof(out)); 1477 if (!BN_bn2bin_padded(out, sizeof(out), n.get())) { 1478 fprintf(stderr, 1479 "BN_bn2bin_padded failed to encode 0 in a non-empty buffer.\n"); 1480 return false; 1481 } 1482 if (memcmp(zeros, out, sizeof(out))) { 1483 fprintf(stderr, "BN_bn2bin_padded did not zero buffer.\n"); 1484 return false; 1485 } 1486 1487 // Test a random numbers at various byte lengths. 1488 for (size_t bytes = 128 - 7; bytes <= 128; bytes++) { 1489 if (!BN_rand(n.get(), bytes * 8, 0 /* make sure top bit is 1 */, 1490 0 /* don't modify bottom bit */)) { 1491 ERR_print_errors_fp(stderr); 1492 return false; 1493 } 1494 if (BN_num_bytes(n.get()) != bytes || 1495 BN_bn2bin(n.get(), reference) != bytes) { 1496 fprintf(stderr, "Bad result from BN_rand; bytes.\n"); 1497 return false; 1498 } 1499 // Empty buffer should fail. 1500 if (BN_bn2bin_padded(NULL, 0, n.get())) { 1501 fprintf(stderr, 1502 "BN_bn2bin_padded incorrectly succeeded on empty buffer.\n"); 1503 return false; 1504 } 1505 // One byte short should fail. 1506 if (BN_bn2bin_padded(out, bytes - 1, n.get())) { 1507 fprintf(stderr, "BN_bn2bin_padded incorrectly succeeded on short.\n"); 1508 return false; 1509 } 1510 // Exactly right size should encode. 1511 if (!BN_bn2bin_padded(out, bytes, n.get()) || 1512 memcmp(out, reference, bytes) != 0) { 1513 fprintf(stderr, "BN_bn2bin_padded gave a bad result.\n"); 1514 return false; 1515 } 1516 // Pad up one byte extra. 1517 if (!BN_bn2bin_padded(out, bytes + 1, n.get()) || 1518 memcmp(out + 1, reference, bytes) || memcmp(out, zeros, 1)) { 1519 fprintf(stderr, "BN_bn2bin_padded gave a bad result.\n"); 1520 return false; 1521 } 1522 // Pad up to 256. 1523 if (!BN_bn2bin_padded(out, sizeof(out), n.get()) || 1524 memcmp(out + sizeof(out) - bytes, reference, bytes) || 1525 memcmp(out, zeros, sizeof(out) - bytes)) { 1526 fprintf(stderr, "BN_bn2bin_padded gave a bad result.\n"); 1527 return false; 1528 } 1529 } 1530 1531 return true; 1532 } 1533 1534 static int DecimalToBIGNUM(ScopedBIGNUM *out, const char *in) { 1535 BIGNUM *raw = NULL; 1536 int ret = BN_dec2bn(&raw, in); 1537 out->reset(raw); 1538 return ret; 1539 } 1540 1541 static bool test_dec2bn(BN_CTX *ctx) { 1542 ScopedBIGNUM bn; 1543 int ret = DecimalToBIGNUM(&bn, "0"); 1544 if (ret != 1 || !BN_is_zero(bn.get()) || BN_is_negative(bn.get())) { 1545 fprintf(stderr, "BN_dec2bn gave a bad result.\n"); 1546 return false; 1547 } 1548 1549 ret = DecimalToBIGNUM(&bn, "256"); 1550 if (ret != 3 || !BN_is_word(bn.get(), 256) || BN_is_negative(bn.get())) { 1551 fprintf(stderr, "BN_dec2bn gave a bad result.\n"); 1552 return false; 1553 } 1554 1555 ret = DecimalToBIGNUM(&bn, "-42"); 1556 if (ret != 3 || !BN_abs_is_word(bn.get(), 42) || !BN_is_negative(bn.get())) { 1557 fprintf(stderr, "BN_dec2bn gave a bad result.\n"); 1558 return false; 1559 } 1560 1561 ret = DecimalToBIGNUM(&bn, "-0"); 1562 if (ret != 2 || !BN_is_zero(bn.get()) || BN_is_negative(bn.get())) { 1563 fprintf(stderr, "BN_dec2bn gave a bad result.\n"); 1564 return false; 1565 } 1566 1567 ret = DecimalToBIGNUM(&bn, "42trailing garbage is ignored"); 1568 if (ret != 2 || !BN_abs_is_word(bn.get(), 42) || BN_is_negative(bn.get())) { 1569 fprintf(stderr, "BN_dec2bn gave a bad result.\n"); 1570 return false; 1571 } 1572 1573 return true; 1574 } 1575 1576 static bool test_hex2bn(BN_CTX *ctx) { 1577 ScopedBIGNUM bn; 1578 int ret = HexToBIGNUM(&bn, "0"); 1579 if (ret != 1 || !BN_is_zero(bn.get()) || BN_is_negative(bn.get())) { 1580 fprintf(stderr, "BN_hex2bn gave a bad result.\n"); 1581 return false; 1582 } 1583 1584 ret = HexToBIGNUM(&bn, "256"); 1585 if (ret != 3 || !BN_is_word(bn.get(), 0x256) || BN_is_negative(bn.get())) { 1586 fprintf(stderr, "BN_hex2bn gave a bad result.\n"); 1587 return false; 1588 } 1589 1590 ret = HexToBIGNUM(&bn, "-42"); 1591 if (ret != 3 || !BN_abs_is_word(bn.get(), 0x42) || !BN_is_negative(bn.get())) { 1592 fprintf(stderr, "BN_hex2bn gave a bad result.\n"); 1593 return false; 1594 } 1595 1596 ret = HexToBIGNUM(&bn, "-0"); 1597 if (ret != 2 || !BN_is_zero(bn.get()) || BN_is_negative(bn.get())) { 1598 fprintf(stderr, "BN_hex2bn gave a bad result.\n"); 1599 return false; 1600 } 1601 1602 ret = HexToBIGNUM(&bn, "abctrailing garbage is ignored"); 1603 if (ret != 3 || !BN_is_word(bn.get(), 0xabc) || BN_is_negative(bn.get())) { 1604 fprintf(stderr, "BN_hex2bn gave a bad result.\n"); 1605 return false; 1606 } 1607 1608 return true; 1609 } 1610 1611 static ScopedBIGNUM ASCIIToBIGNUM(const char *in) { 1612 BIGNUM *raw = NULL; 1613 if (!BN_asc2bn(&raw, in)) { 1614 return nullptr; 1615 } 1616 return ScopedBIGNUM(raw); 1617 } 1618 1619 static bool test_asc2bn(BN_CTX *ctx) { 1620 ScopedBIGNUM bn = ASCIIToBIGNUM("0"); 1621 if (!bn || !BN_is_zero(bn.get()) || BN_is_negative(bn.get())) { 1622 fprintf(stderr, "BN_asc2bn gave a bad result.\n"); 1623 return false; 1624 } 1625 1626 bn = ASCIIToBIGNUM("256"); 1627 if (!bn || !BN_is_word(bn.get(), 256) || BN_is_negative(bn.get())) { 1628 fprintf(stderr, "BN_asc2bn gave a bad result.\n"); 1629 return false; 1630 } 1631 1632 bn = ASCIIToBIGNUM("-42"); 1633 if (!bn || !BN_abs_is_word(bn.get(), 42) || !BN_is_negative(bn.get())) { 1634 fprintf(stderr, "BN_asc2bn gave a bad result.\n"); 1635 return false; 1636 } 1637 1638 bn = ASCIIToBIGNUM("0x1234"); 1639 if (!bn || !BN_is_word(bn.get(), 0x1234) || BN_is_negative(bn.get())) { 1640 fprintf(stderr, "BN_asc2bn gave a bad result.\n"); 1641 return false; 1642 } 1643 1644 bn = ASCIIToBIGNUM("0X1234"); 1645 if (!bn || !BN_is_word(bn.get(), 0x1234) || BN_is_negative(bn.get())) { 1646 fprintf(stderr, "BN_asc2bn gave a bad result.\n"); 1647 return false; 1648 } 1649 1650 bn = ASCIIToBIGNUM("-0xabcd"); 1651 if (!bn || !BN_abs_is_word(bn.get(), 0xabcd) || !BN_is_negative(bn.get())) { 1652 fprintf(stderr, "BN_asc2bn gave a bad result.\n"); 1653 return false; 1654 } 1655 1656 bn = ASCIIToBIGNUM("-0"); 1657 if (!bn || !BN_is_zero(bn.get()) || BN_is_negative(bn.get())) { 1658 fprintf(stderr, "BN_asc2bn gave a bad result.\n"); 1659 return false; 1660 } 1661 1662 bn = ASCIIToBIGNUM("123trailing garbage is ignored"); 1663 if (!bn || !BN_is_word(bn.get(), 123) || BN_is_negative(bn.get())) { 1664 fprintf(stderr, "BN_asc2bn gave a bad result.\n"); 1665 return false; 1666 } 1667 1668 return true; 1669 } 1670 1671 struct MPITest { 1672 const char *base10; 1673 const char *mpi; 1674 size_t mpi_len; 1675 }; 1676 1677 static const MPITest kMPITests[] = { 1678 { "0", "\x00\x00\x00\x00", 4 }, 1679 { "1", "\x00\x00\x00\x01\x01", 5 }, 1680 { "-1", "\x00\x00\x00\x01\x81", 5 }, 1681 { "128", "\x00\x00\x00\x02\x00\x80", 6 }, 1682 { "256", "\x00\x00\x00\x02\x01\x00", 6 }, 1683 { "-256", "\x00\x00\x00\x02\x81\x00", 6 }, 1684 }; 1685 1686 static bool test_mpi() { 1687 uint8_t scratch[8]; 1688 1689 for (size_t i = 0; i < sizeof(kMPITests) / sizeof(kMPITests[0]); i++) { 1690 const MPITest &test = kMPITests[i]; 1691 ScopedBIGNUM bn(ASCIIToBIGNUM(test.base10)); 1692 const size_t mpi_len = BN_bn2mpi(bn.get(), NULL); 1693 if (mpi_len > sizeof(scratch)) { 1694 fprintf(stderr, "MPI test #%u: MPI size is too large to test.\n", 1695 (unsigned)i); 1696 return false; 1697 } 1698 1699 const size_t mpi_len2 = BN_bn2mpi(bn.get(), scratch); 1700 if (mpi_len != mpi_len2) { 1701 fprintf(stderr, "MPI test #%u: length changes.\n", (unsigned)i); 1702 return false; 1703 } 1704 1705 if (mpi_len != test.mpi_len || 1706 memcmp(test.mpi, scratch, mpi_len) != 0) { 1707 fprintf(stderr, "MPI test #%u failed:\n", (unsigned)i); 1708 hexdump(stderr, "Expected: ", test.mpi, test.mpi_len); 1709 hexdump(stderr, "Got: ", scratch, mpi_len); 1710 return false; 1711 } 1712 1713 ScopedBIGNUM bn2(BN_mpi2bn(scratch, mpi_len, NULL)); 1714 if (bn2.get() == nullptr) { 1715 fprintf(stderr, "MPI test #%u: failed to parse\n", (unsigned)i); 1716 return false; 1717 } 1718 1719 if (BN_cmp(bn.get(), bn2.get()) != 0) { 1720 fprintf(stderr, "MPI test #%u: wrong result\n", (unsigned)i); 1721 return false; 1722 } 1723 } 1724 1725 return true; 1726 } 1727 1728 static bool test_rand() { 1729 ScopedBIGNUM bn(BN_new()); 1730 if (!bn) { 1731 return false; 1732 } 1733 1734 // Test BN_rand accounts for degenerate cases with |top| and |bottom| 1735 // parameters. 1736 if (!BN_rand(bn.get(), 0, 0 /* top */, 0 /* bottom */) || 1737 !BN_is_zero(bn.get())) { 1738 fprintf(stderr, "BN_rand gave a bad result.\n"); 1739 return false; 1740 } 1741 if (!BN_rand(bn.get(), 0, 1 /* top */, 1 /* bottom */) || 1742 !BN_is_zero(bn.get())) { 1743 fprintf(stderr, "BN_rand gave a bad result.\n"); 1744 return false; 1745 } 1746 1747 if (!BN_rand(bn.get(), 1, 0 /* top */, 0 /* bottom */) || 1748 !BN_is_word(bn.get(), 1)) { 1749 fprintf(stderr, "BN_rand gave a bad result.\n"); 1750 return false; 1751 } 1752 if (!BN_rand(bn.get(), 1, 1 /* top */, 0 /* bottom */) || 1753 !BN_is_word(bn.get(), 1)) { 1754 fprintf(stderr, "BN_rand gave a bad result.\n"); 1755 return false; 1756 } 1757 if (!BN_rand(bn.get(), 1, -1 /* top */, 1 /* bottom */) || 1758 !BN_is_word(bn.get(), 1)) { 1759 fprintf(stderr, "BN_rand gave a bad result.\n"); 1760 return false; 1761 } 1762 1763 if (!BN_rand(bn.get(), 2, 1 /* top */, 0 /* bottom */) || 1764 !BN_is_word(bn.get(), 3)) { 1765 fprintf(stderr, "BN_rand gave a bad result.\n"); 1766 return false; 1767 } 1768 1769 return true; 1770 } 1771 1772 struct ASN1Test { 1773 const char *value_ascii; 1774 const char *der; 1775 size_t der_len; 1776 }; 1777 1778 static const ASN1Test kASN1Tests[] = { 1779 {"0", "\x02\x01\x00", 3}, 1780 {"1", "\x02\x01\x01", 3}, 1781 {"127", "\x02\x01\x7f", 3}, 1782 {"128", "\x02\x02\x00\x80", 4}, 1783 {"0xdeadbeef", "\x02\x05\x00\xde\xad\xbe\xef", 7}, 1784 {"0x0102030405060708", 1785 "\x02\x08\x01\x02\x03\x04\x05\x06\x07\x08", 10}, 1786 {"0xffffffffffffffff", 1787 "\x02\x09\x00\xff\xff\xff\xff\xff\xff\xff\xff", 11}, 1788 }; 1789 1790 struct ASN1InvalidTest { 1791 const char *der; 1792 size_t der_len; 1793 }; 1794 1795 static const ASN1InvalidTest kASN1InvalidTests[] = { 1796 // Bad tag. 1797 {"\x03\x01\x00", 3}, 1798 // Empty contents. 1799 {"\x02\x00", 2}, 1800 }; 1801 1802 // kASN1BuggyTests are incorrect encodings and how |BN_cbs2unsigned_buggy| 1803 // should interpret them. 1804 static const ASN1Test kASN1BuggyTests[] = { 1805 // Negative numbers. 1806 {"128", "\x02\x01\x80", 3}, 1807 {"255", "\x02\x01\xff", 3}, 1808 // Unnecessary leading zeros. 1809 {"1", "\x02\x02\x00\x01", 4}, 1810 }; 1811 1812 static bool test_asn1() { 1813 for (const ASN1Test &test : kASN1Tests) { 1814 ScopedBIGNUM bn = ASCIIToBIGNUM(test.value_ascii); 1815 if (!bn) { 1816 return false; 1817 } 1818 1819 // Test that the input is correctly parsed. 1820 ScopedBIGNUM bn2(BN_new()); 1821 if (!bn2) { 1822 return false; 1823 } 1824 CBS cbs; 1825 CBS_init(&cbs, reinterpret_cast<const uint8_t*>(test.der), test.der_len); 1826 if (!BN_cbs2unsigned(&cbs, bn2.get()) || CBS_len(&cbs) != 0) { 1827 fprintf(stderr, "Parsing ASN.1 INTEGER failed.\n"); 1828 return false; 1829 } 1830 if (BN_cmp(bn.get(), bn2.get()) != 0) { 1831 fprintf(stderr, "Bad parse.\n"); 1832 return false; 1833 } 1834 1835 // Test the value serializes correctly. 1836 CBB cbb; 1837 uint8_t *der; 1838 size_t der_len; 1839 CBB_zero(&cbb); 1840 if (!CBB_init(&cbb, 0) || 1841 !BN_bn2cbb(&cbb, bn.get()) || 1842 !CBB_finish(&cbb, &der, &der_len)) { 1843 CBB_cleanup(&cbb); 1844 return false; 1845 } 1846 ScopedOpenSSLBytes delete_der(der); 1847 if (der_len != test.der_len || 1848 memcmp(der, reinterpret_cast<const uint8_t*>(test.der), der_len) != 0) { 1849 fprintf(stderr, "Bad serialization.\n"); 1850 return false; 1851 } 1852 1853 // |BN_cbs2unsigned_buggy| parses all valid input. 1854 CBS_init(&cbs, reinterpret_cast<const uint8_t*>(test.der), test.der_len); 1855 if (!BN_cbs2unsigned_buggy(&cbs, bn2.get()) || CBS_len(&cbs) != 0) { 1856 fprintf(stderr, "Parsing ASN.1 INTEGER failed.\n"); 1857 return false; 1858 } 1859 if (BN_cmp(bn.get(), bn2.get()) != 0) { 1860 fprintf(stderr, "Bad parse.\n"); 1861 return false; 1862 } 1863 } 1864 1865 for (const ASN1InvalidTest &test : kASN1InvalidTests) { 1866 ScopedBIGNUM bn(BN_new()); 1867 if (!bn) { 1868 return false; 1869 } 1870 CBS cbs; 1871 CBS_init(&cbs, reinterpret_cast<const uint8_t*>(test.der), test.der_len); 1872 if (BN_cbs2unsigned(&cbs, bn.get())) { 1873 fprintf(stderr, "Parsed invalid input.\n"); 1874 return false; 1875 } 1876 ERR_clear_error(); 1877 1878 // All tests in kASN1InvalidTests are also rejected by 1879 // |BN_cbs2unsigned_buggy|. 1880 CBS_init(&cbs, reinterpret_cast<const uint8_t*>(test.der), test.der_len); 1881 if (BN_cbs2unsigned_buggy(&cbs, bn.get())) { 1882 fprintf(stderr, "Parsed invalid input.\n"); 1883 return false; 1884 } 1885 ERR_clear_error(); 1886 } 1887 1888 for (const ASN1Test &test : kASN1BuggyTests) { 1889 // These broken encodings are rejected by |BN_cbs2unsigned|. 1890 ScopedBIGNUM bn(BN_new()); 1891 if (!bn) { 1892 return false; 1893 } 1894 1895 CBS cbs; 1896 CBS_init(&cbs, reinterpret_cast<const uint8_t*>(test.der), test.der_len); 1897 if (BN_cbs2unsigned(&cbs, bn.get())) { 1898 fprintf(stderr, "Parsed invalid input.\n"); 1899 return false; 1900 } 1901 ERR_clear_error(); 1902 1903 // However |BN_cbs2unsigned_buggy| accepts them. 1904 ScopedBIGNUM bn2 = ASCIIToBIGNUM(test.value_ascii); 1905 if (!bn2) { 1906 return false; 1907 } 1908 1909 CBS_init(&cbs, reinterpret_cast<const uint8_t*>(test.der), test.der_len); 1910 if (!BN_cbs2unsigned_buggy(&cbs, bn.get()) || CBS_len(&cbs) != 0) { 1911 fprintf(stderr, "Parsing (invalid) ASN.1 INTEGER failed.\n"); 1912 return false; 1913 } 1914 1915 if (BN_cmp(bn.get(), bn2.get()) != 0) { 1916 fprintf(stderr, "\"Bad\" parse.\n"); 1917 return false; 1918 } 1919 } 1920 1921 // Serializing negative numbers is not supported. 1922 ScopedBIGNUM bn = ASCIIToBIGNUM("-1"); 1923 if (!bn) { 1924 return false; 1925 } 1926 CBB cbb; 1927 CBB_zero(&cbb); 1928 if (!CBB_init(&cbb, 0) || 1929 BN_bn2cbb(&cbb, bn.get())) { 1930 fprintf(stderr, "Serialized negative number.\n"); 1931 CBB_cleanup(&cbb); 1932 return false; 1933 } 1934 CBB_cleanup(&cbb); 1935 1936 return true; 1937 } 1938