Home | History | Annotate | Download | only in bn
      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