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