1*cbd9e74cStb /* $OpenBSD: bn_test.c,v 1.22 2025/01/22 13:02:14 tb Exp $ */ 2b8d22d11Stb /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3b8d22d11Stb * All rights reserved. 4b8d22d11Stb * 5b8d22d11Stb * This package is an SSL implementation written 6b8d22d11Stb * by Eric Young (eay@cryptsoft.com). 7b8d22d11Stb * The implementation was written so as to conform with Netscapes SSL. 8b8d22d11Stb * 9b8d22d11Stb * This library is free for commercial and non-commercial use as long as 10b8d22d11Stb * the following conditions are aheared to. The following conditions 11b8d22d11Stb * apply to all code found in this distribution, be it the RC4, RSA, 12b8d22d11Stb * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13b8d22d11Stb * included with this distribution is covered by the same copyright terms 14b8d22d11Stb * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15b8d22d11Stb * 16b8d22d11Stb * Copyright remains Eric Young's, and as such any Copyright notices in 17b8d22d11Stb * the code are not to be removed. 18b8d22d11Stb * If this package is used in a product, Eric Young should be given attribution 19b8d22d11Stb * as the author of the parts of the library used. 20b8d22d11Stb * This can be in the form of a textual message at program startup or 21b8d22d11Stb * in documentation (online or textual) provided with the package. 22b8d22d11Stb * 23b8d22d11Stb * Redistribution and use in source and binary forms, with or without 24b8d22d11Stb * modification, are permitted provided that the following conditions 25b8d22d11Stb * are met: 26b8d22d11Stb * 1. Redistributions of source code must retain the copyright 27b8d22d11Stb * notice, this list of conditions and the following disclaimer. 28b8d22d11Stb * 2. Redistributions in binary form must reproduce the above copyright 29b8d22d11Stb * notice, this list of conditions and the following disclaimer in the 30b8d22d11Stb * documentation and/or other materials provided with the distribution. 31b8d22d11Stb * 3. All advertising materials mentioning features or use of this software 32b8d22d11Stb * must display the following acknowledgement: 33b8d22d11Stb * "This product includes cryptographic software written by 34b8d22d11Stb * Eric Young (eay@cryptsoft.com)" 35b8d22d11Stb * The word 'cryptographic' can be left out if the rouines from the library 36b8d22d11Stb * being used are not cryptographic related :-). 37b8d22d11Stb * 4. If you include any Windows specific code (or a derivative thereof) from 38b8d22d11Stb * the apps directory (application code) you must include an acknowledgement: 39b8d22d11Stb * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40b8d22d11Stb * 41b8d22d11Stb * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42b8d22d11Stb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43b8d22d11Stb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44b8d22d11Stb * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45b8d22d11Stb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46b8d22d11Stb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47b8d22d11Stb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48b8d22d11Stb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49b8d22d11Stb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50b8d22d11Stb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51b8d22d11Stb * SUCH DAMAGE. 52b8d22d11Stb * 53b8d22d11Stb * The licence and distribution terms for any publically available version or 54b8d22d11Stb * derivative of this code cannot be changed. i.e. this code cannot simply be 55b8d22d11Stb * copied and put under another distribution licence 56b8d22d11Stb * [including the GNU Public Licence.] 57b8d22d11Stb */ 58b8d22d11Stb /* ==================================================================== 59b8d22d11Stb * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. 60b8d22d11Stb * 61b8d22d11Stb * Portions of the attached software ("Contribution") are developed by 62b8d22d11Stb * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. 63b8d22d11Stb * 64b8d22d11Stb * The Contribution is licensed pursuant to the Eric Young open source 65b8d22d11Stb * license provided above. 66b8d22d11Stb * 67b8d22d11Stb * The binary polynomial arithmetic software is originally written by 68b8d22d11Stb * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories. 69b8d22d11Stb * 70b8d22d11Stb */ 71b8d22d11Stb 72b8d22d11Stb #include <stdio.h> 73b8d22d11Stb #include <stdlib.h> 74b8d22d11Stb #include <string.h> 75b8d22d11Stb 76b8d22d11Stb #include <openssl/bio.h> 77b8d22d11Stb #include <openssl/bn.h> 78b8d22d11Stb #include <openssl/err.h> 79b8d22d11Stb 8020c8b67dStb #include "bn_local.h" 81b8d22d11Stb 82b8d22d11Stb const int num0 = 100; /* number of tests */ 83b8d22d11Stb const int num1 = 50; /* additional tests for some functions */ 84b8d22d11Stb const int num2 = 5; /* number of tests for slow functions */ 85b8d22d11Stb 860edabd22Stb int test_add(BIO *bp, BN_CTX *ctx); 870edabd22Stb int test_sub(BIO *bp, BN_CTX *ctx); 880edabd22Stb int test_lshift1(BIO *bp, BN_CTX *ctx); 894bbad1a5Stb int test_lshift(BIO *bp, BN_CTX *ctx, int use_lst); 900edabd22Stb int test_rshift1(BIO *bp, BN_CTX *ctx); 91b8d22d11Stb int test_rshift(BIO *bp, BN_CTX *ctx); 92b8d22d11Stb int test_div(BIO *bp, BN_CTX *ctx); 930edabd22Stb int test_div_word(BIO *bp, BN_CTX *ctx); 94b8d22d11Stb int test_div_recp(BIO *bp, BN_CTX *ctx); 950edabd22Stb int test_mul(BIO *bp, BN_CTX *ctx); 96b8d22d11Stb int test_sqr(BIO *bp, BN_CTX *ctx); 97b8d22d11Stb int test_mont(BIO *bp, BN_CTX *ctx); 98b8d22d11Stb int test_mod(BIO *bp, BN_CTX *ctx); 99b8d22d11Stb int test_mod_mul(BIO *bp, BN_CTX *ctx); 100b8d22d11Stb int test_mod_exp(BIO *bp, BN_CTX *ctx); 101b8d22d11Stb int test_mod_exp_mont_consttime(BIO *bp, BN_CTX *ctx); 102b8d22d11Stb int test_mod_exp_mont5(BIO *bp, BN_CTX *ctx); 103b8d22d11Stb int test_mod_exp_sizes(BIO *bp, BN_CTX *ctx); 104b8d22d11Stb int test_exp(BIO *bp, BN_CTX *ctx); 105b8d22d11Stb int test_kron(BIO *bp, BN_CTX *ctx); 106b8d22d11Stb int test_sqrt(BIO *bp, BN_CTX *ctx); 107b8d22d11Stb int rand_neg(void); 108b8d22d11Stb static int results = 0; 109b8d22d11Stb 110b8d22d11Stb #define PRINT_ERROR printf("Error in %s [%s:%d]\n", __func__, __FILE__, \ 111b8d22d11Stb __LINE__) 112b8d22d11Stb 113b8d22d11Stb #define CHECK_GOTO(a) do { \ 114b8d22d11Stb if (!(a)) { \ 115b8d22d11Stb PRINT_ERROR; \ 116b8d22d11Stb goto err; \ 117b8d22d11Stb } \ 118b8d22d11Stb } while (0) 119b8d22d11Stb 120b8d22d11Stb static void 121b8d22d11Stb message(BIO *out, char *m) 122b8d22d11Stb { 1235550240dStb ERR_print_errors_fp(stderr); 1245550240dStb ERR_clear_error(); 1255550240dStb 126b8d22d11Stb fprintf(stderr, "test %s\n", m); 127b8d22d11Stb BIO_puts(out, "print \"test "); 128b8d22d11Stb BIO_puts(out, m); 129b8d22d11Stb BIO_puts(out, "\\n\"\n"); 130b8d22d11Stb } 131b8d22d11Stb 132b8d22d11Stb int 133b8d22d11Stb main(int argc, char *argv[]) 134b8d22d11Stb { 135b8d22d11Stb BN_CTX *ctx; 136b8d22d11Stb BIO *out; 137b8d22d11Stb char *outfile = NULL; 138b8d22d11Stb 139b8d22d11Stb results = 0; 140b8d22d11Stb 141b8d22d11Stb argc--; 142b8d22d11Stb argv++; 143b8d22d11Stb while (argc >= 1) { 144b8d22d11Stb if (strcmp(*argv, "-results") == 0) 145b8d22d11Stb results = 1; 146b8d22d11Stb else if (strcmp(*argv, "-out") == 0) { 147b8d22d11Stb if (--argc < 1) 148b8d22d11Stb break; 149b8d22d11Stb outfile= *(++argv); 150b8d22d11Stb } 151b8d22d11Stb argc--; 152b8d22d11Stb argv++; 153b8d22d11Stb } 154b8d22d11Stb 1551604cb40Stb if ((ctx = BN_CTX_new()) == NULL) 156b8d22d11Stb exit(1); 157b8d22d11Stb 1581604cb40Stb if ((out = BIO_new(BIO_s_file())) == NULL) 159b8d22d11Stb exit(1); 160b8d22d11Stb if (outfile == NULL) { 161b8d22d11Stb BIO_set_fp(out, stdout, BIO_NOCLOSE); 162b8d22d11Stb } else { 163b8d22d11Stb if (!BIO_write_filename(out, outfile)) { 164b8d22d11Stb perror(outfile); 165b8d22d11Stb exit(1); 166b8d22d11Stb } 167b8d22d11Stb } 168b8d22d11Stb 169b8d22d11Stb if (!results) 170b8d22d11Stb BIO_puts(out, "obase=16\nibase=16\n"); 171b8d22d11Stb 172b8d22d11Stb message(out, "BN_add"); 1730edabd22Stb if (!test_add(out, ctx)) 174b8d22d11Stb goto err; 175b8d22d11Stb (void)BIO_flush(out); 176b8d22d11Stb 177b8d22d11Stb message(out, "BN_sub"); 1780edabd22Stb if (!test_sub(out, ctx)) 179b8d22d11Stb goto err; 180b8d22d11Stb (void)BIO_flush(out); 181b8d22d11Stb 182b8d22d11Stb message(out, "BN_lshift1"); 1830edabd22Stb if (!test_lshift1(out, ctx)) 184b8d22d11Stb goto err; 185b8d22d11Stb (void)BIO_flush(out); 186b8d22d11Stb 187b8d22d11Stb message(out, "BN_lshift (fixed)"); 1884bbad1a5Stb if (!test_lshift(out, ctx, 0)) 189b8d22d11Stb goto err; 190b8d22d11Stb (void)BIO_flush(out); 191b8d22d11Stb 1920edabd22Stb message(out, "BN_lshift"); 1930edabd22Stb if (!test_lshift(out, ctx, 1)) 1940edabd22Stb goto err; 1950edabd22Stb (void)BIO_flush(out); 1960edabd22Stb 197b8d22d11Stb message(out, "BN_rshift1"); 1980edabd22Stb if (!test_rshift1(out, ctx)) 199b8d22d11Stb goto err; 200b8d22d11Stb (void)BIO_flush(out); 201b8d22d11Stb 202b8d22d11Stb message(out, "BN_rshift"); 203b8d22d11Stb if (!test_rshift(out, ctx)) 204b8d22d11Stb goto err; 205b8d22d11Stb (void)BIO_flush(out); 206b8d22d11Stb 207b8d22d11Stb message(out, "BN_sqr"); 208b8d22d11Stb if (!test_sqr(out, ctx)) 209b8d22d11Stb goto err; 210b8d22d11Stb (void)BIO_flush(out); 211b8d22d11Stb 212b8d22d11Stb message(out, "BN_mul"); 2130edabd22Stb if (!test_mul(out, ctx)) 214b8d22d11Stb goto err; 215b8d22d11Stb (void)BIO_flush(out); 216b8d22d11Stb 217b8d22d11Stb message(out, "BN_div"); 218b8d22d11Stb if (!test_div(out, ctx)) 219b8d22d11Stb goto err; 220b8d22d11Stb (void)BIO_flush(out); 221b8d22d11Stb 222b8d22d11Stb message(out, "BN_div_word"); 2230edabd22Stb if (!test_div_word(out, ctx)) 224b8d22d11Stb goto err; 225b8d22d11Stb (void)BIO_flush(out); 226b8d22d11Stb 2272d506d2eStb message(out, "BN_div_reciprocal"); 228b8d22d11Stb if (!test_div_recp(out, ctx)) 229b8d22d11Stb goto err; 230b8d22d11Stb (void)BIO_flush(out); 231b8d22d11Stb 232b8d22d11Stb message(out, "BN_mod"); 233b8d22d11Stb if (!test_mod(out, ctx)) 234b8d22d11Stb goto err; 235b8d22d11Stb (void)BIO_flush(out); 236b8d22d11Stb 237b8d22d11Stb message(out, "BN_mod_mul"); 238b8d22d11Stb if (!test_mod_mul(out, ctx)) 239b8d22d11Stb goto err; 240b8d22d11Stb (void)BIO_flush(out); 241b8d22d11Stb 242b8d22d11Stb message(out, "BN_mont"); 243b8d22d11Stb if (!test_mont(out, ctx)) 244b8d22d11Stb goto err; 245b8d22d11Stb (void)BIO_flush(out); 246b8d22d11Stb 247b8d22d11Stb message(out, "BN_mod_exp"); 248b8d22d11Stb if (!test_mod_exp(out, ctx)) 249b8d22d11Stb goto err; 250b8d22d11Stb (void)BIO_flush(out); 251b8d22d11Stb 252b8d22d11Stb message(out, "BN_mod_exp_mont_consttime"); 253b8d22d11Stb if (!test_mod_exp_mont_consttime(out, ctx)) 254b8d22d11Stb goto err; 255b8d22d11Stb (void)BIO_flush(out); 256b8d22d11Stb 257b8d22d11Stb message(out, "BN_mod_exp_mont5"); 258b8d22d11Stb if (!test_mod_exp_mont5(out, ctx)) 259b8d22d11Stb goto err; 260b8d22d11Stb (void)BIO_flush(out); 261b8d22d11Stb 262b8d22d11Stb message(out, "BN_exp"); 263b8d22d11Stb if (!test_exp(out, ctx)) 264b8d22d11Stb goto err; 265b8d22d11Stb (void)BIO_flush(out); 266b8d22d11Stb 267b8d22d11Stb message(out, "BN_kronecker"); 268b8d22d11Stb if (!test_kron(out, ctx)) 269b8d22d11Stb goto err; 270b8d22d11Stb (void)BIO_flush(out); 271b8d22d11Stb 272b8d22d11Stb message(out, "BN_mod_sqrt"); 273b8d22d11Stb if (!test_sqrt(out, ctx)) 274b8d22d11Stb goto err; 275b8d22d11Stb (void)BIO_flush(out); 276b8d22d11Stb 277b8d22d11Stb message(out, "Modexp with different sizes"); 278b8d22d11Stb if (!test_mod_exp_sizes(out, ctx)) 279b8d22d11Stb goto err; 280b8d22d11Stb (void)BIO_flush(out); 281b8d22d11Stb 282b8d22d11Stb BN_CTX_free(ctx); 283b8d22d11Stb BIO_free(out); 284b8d22d11Stb 285b8d22d11Stb exit(0); 286b8d22d11Stb err: 287b8d22d11Stb BIO_puts(out, "1\n"); /* make sure the Perl script fed by bc notices 288b8d22d11Stb * the failure, see test_bn in test/Makefile.ssl*/ 289b8d22d11Stb 290b8d22d11Stb (void)BIO_flush(out); 291b8d22d11Stb ERR_load_crypto_strings(); 292b8d22d11Stb ERR_print_errors_fp(stderr); 293b8d22d11Stb exit(1); 294b8d22d11Stb } 295b8d22d11Stb 296b8d22d11Stb int 2970edabd22Stb test_add(BIO *bp, BN_CTX *ctx) 298b8d22d11Stb { 2990edabd22Stb BIGNUM *a, *b, *c; 300b8d22d11Stb int i; 301f7264475Stb int ret = 0; 302b8d22d11Stb 3030edabd22Stb BN_CTX_start(ctx); 3040edabd22Stb 3050edabd22Stb if ((a = BN_CTX_get(ctx)) == NULL) 306b8d22d11Stb goto err; 3070edabd22Stb if ((b = BN_CTX_get(ctx)) == NULL) 308b8d22d11Stb goto err; 3090edabd22Stb if ((c = BN_CTX_get(ctx)) == NULL) 310b8d22d11Stb goto err; 311b8d22d11Stb 312b8d22d11Stb CHECK_GOTO(BN_bntest_rand(a, 512, 0, 0)); 313b8d22d11Stb for (i = 0; i < num0; i++) { 314b8d22d11Stb CHECK_GOTO(BN_bntest_rand(b, 450 + i, 0, 0)); 315b8d22d11Stb BN_set_negative(a, rand_neg()); 316b8d22d11Stb BN_set_negative(b, rand_neg()); 317b8d22d11Stb CHECK_GOTO(BN_add(c, a, b)); 318b8d22d11Stb if (bp != NULL) { 319b8d22d11Stb if (!results) { 320b8d22d11Stb CHECK_GOTO(BN_print(bp, a)); 321b8d22d11Stb BIO_puts(bp, " + "); 322b8d22d11Stb CHECK_GOTO(BN_print(bp, b)); 323b8d22d11Stb BIO_puts(bp, " - "); 324b8d22d11Stb } 325b8d22d11Stb CHECK_GOTO(BN_print(bp, c)); 326b8d22d11Stb BIO_puts(bp, "\n"); 327b8d22d11Stb } 328b8d22d11Stb BN_set_negative(a, !BN_is_negative(a)); 329b8d22d11Stb BN_set_negative(b, !BN_is_negative(b)); 330b8d22d11Stb CHECK_GOTO(BN_add(c, c, b)); 331b8d22d11Stb CHECK_GOTO(BN_add(c, c, a)); 332b8d22d11Stb if (!BN_is_zero(c)) { 333b8d22d11Stb fprintf(stderr, "Add test failed!\n"); 3342e7cce5eStb goto err; 335b8d22d11Stb } 336b8d22d11Stb } 337b8d22d11Stb 338f7264475Stb ret = 1; 339b8d22d11Stb err: 3400edabd22Stb BN_CTX_end(ctx); 341b8d22d11Stb 342f7264475Stb return ret; 343b8d22d11Stb } 344b8d22d11Stb 345b8d22d11Stb int 3460edabd22Stb test_sub(BIO *bp, BN_CTX *ctx) 347b8d22d11Stb { 3480edabd22Stb BIGNUM *a, *b, *c; 349b8d22d11Stb int i; 350f7264475Stb int ret = 0; 351b8d22d11Stb 3520edabd22Stb BN_CTX_start(ctx); 3530edabd22Stb 3540edabd22Stb if ((a = BN_CTX_get(ctx)) == NULL) 355b8d22d11Stb goto err; 3560edabd22Stb if ((b = BN_CTX_get(ctx)) == NULL) 357b8d22d11Stb goto err; 3580edabd22Stb if ((c = BN_CTX_get(ctx)) == NULL) 359b8d22d11Stb goto err; 360b8d22d11Stb 361b8d22d11Stb for (i = 0; i < num0 + num1; i++) { 362b8d22d11Stb if (i < num1) { 363b8d22d11Stb CHECK_GOTO(BN_bntest_rand(a, 512, 0, 0)); 3648e84e241Stb CHECK_GOTO(bn_copy(b, a)); 365457e5092Stb if (BN_set_bit(a, i) == 0) 3662e7cce5eStb goto err; 367b8d22d11Stb CHECK_GOTO(BN_add_word(b, i)); 368b8d22d11Stb } else { 369b8d22d11Stb CHECK_GOTO(BN_bntest_rand(b, 400 + i - num1, 0, 0)); 370b8d22d11Stb BN_set_negative(a, rand_neg()); 371b8d22d11Stb BN_set_negative(b, rand_neg()); 372b8d22d11Stb } 373b8d22d11Stb CHECK_GOTO(BN_sub(c, a, b)); 374b8d22d11Stb if (bp != NULL) { 375b8d22d11Stb if (!results) { 376b8d22d11Stb CHECK_GOTO(BN_print(bp, a)); 377b8d22d11Stb BIO_puts(bp, " - "); 378b8d22d11Stb CHECK_GOTO(BN_print(bp, b)); 379b8d22d11Stb BIO_puts(bp, " - "); 380b8d22d11Stb } 381b8d22d11Stb CHECK_GOTO(BN_print(bp, c)); 382b8d22d11Stb BIO_puts(bp, "\n"); 383b8d22d11Stb } 384b8d22d11Stb CHECK_GOTO(BN_add(c, c, b)); 385b8d22d11Stb CHECK_GOTO(BN_sub(c, c, a)); 386b8d22d11Stb if (!BN_is_zero(c)) { 387b8d22d11Stb fprintf(stderr, "Subtract test failed!\n"); 3882e7cce5eStb goto err; 389b8d22d11Stb } 390b8d22d11Stb } 3912e7cce5eStb 392f7264475Stb ret = 1; 393b8d22d11Stb err: 3940edabd22Stb BN_CTX_end(ctx); 3952e7cce5eStb 396f7264475Stb return ret; 397b8d22d11Stb } 398b8d22d11Stb 399b8d22d11Stb int 400b8d22d11Stb test_div(BIO *bp, BN_CTX *ctx) 401b8d22d11Stb { 4020edabd22Stb BIGNUM *a, *b, *c, *d, *e; 403b8d22d11Stb int i; 404f7264475Stb int ret = 0; 405b8d22d11Stb 4060edabd22Stb BN_CTX_start(ctx); 4070edabd22Stb 4080edabd22Stb if ((a = BN_CTX_get(ctx)) == NULL) 409b8d22d11Stb goto err; 4100edabd22Stb if ((b = BN_CTX_get(ctx)) == NULL) 411b8d22d11Stb goto err; 4120edabd22Stb if ((c = BN_CTX_get(ctx)) == NULL) 413b8d22d11Stb goto err; 4140edabd22Stb if ((d = BN_CTX_get(ctx)) == NULL) 415b8d22d11Stb goto err; 4160edabd22Stb if ((e = BN_CTX_get(ctx)) == NULL) 417b8d22d11Stb goto err; 418b8d22d11Stb 419b8d22d11Stb CHECK_GOTO(BN_one(a)); 42030ad135cStb BN_zero(b); 421b8d22d11Stb 422b8d22d11Stb if (BN_div(d, c, a, b, ctx)) { 423b8d22d11Stb fprintf(stderr, "Division by zero succeeded!\n"); 424bb44b87cStb goto err; 425b8d22d11Stb } 4265550240dStb ERR_clear_error(); 427b8d22d11Stb 428b8d22d11Stb for (i = 0; i < num0 + num1; i++) { 429b8d22d11Stb if (i < num1) { 430b8d22d11Stb CHECK_GOTO(BN_bntest_rand(a, 400, 0, 0)); 4318e84e241Stb CHECK_GOTO(bn_copy(b, a)); 432b8d22d11Stb CHECK_GOTO(BN_lshift(a, a, i)); 433b8d22d11Stb CHECK_GOTO(BN_add_word(a, i)); 434b8d22d11Stb } else 435b8d22d11Stb CHECK_GOTO(BN_bntest_rand(b, 50 + 3 * (i - num1), 0, 0)); 436b8d22d11Stb BN_set_negative(a, rand_neg()); 437b8d22d11Stb BN_set_negative(b, rand_neg()); 438b8d22d11Stb CHECK_GOTO(BN_div(d, c, a, b, ctx)); 439b8d22d11Stb if (bp != NULL) { 440b8d22d11Stb if (!results) { 441b8d22d11Stb CHECK_GOTO(BN_print(bp, a)); 442b8d22d11Stb BIO_puts(bp, " / "); 443b8d22d11Stb CHECK_GOTO(BN_print(bp, b)); 444b8d22d11Stb BIO_puts(bp, " - "); 445b8d22d11Stb } 446b8d22d11Stb CHECK_GOTO(BN_print(bp, d)); 447b8d22d11Stb BIO_puts(bp, "\n"); 448b8d22d11Stb 449b8d22d11Stb if (!results) { 450b8d22d11Stb CHECK_GOTO(BN_print(bp, a)); 451b8d22d11Stb BIO_puts(bp, " % "); 452b8d22d11Stb CHECK_GOTO(BN_print(bp, b)); 453b8d22d11Stb BIO_puts(bp, " - "); 454b8d22d11Stb } 455b8d22d11Stb CHECK_GOTO(BN_print(bp, c)); 456b8d22d11Stb BIO_puts(bp, "\n"); 457b8d22d11Stb } 458b8d22d11Stb CHECK_GOTO(BN_mul(e, d, b, ctx)); 459b8d22d11Stb CHECK_GOTO(BN_add(d, e, c)); 460b8d22d11Stb CHECK_GOTO(BN_sub(d, d, a)); 461b8d22d11Stb if (!BN_is_zero(d)) { 462b8d22d11Stb fprintf(stderr, "Division test failed!\n"); 4632e7cce5eStb goto err; 464b8d22d11Stb } 465b8d22d11Stb } 4662e7cce5eStb 467f7264475Stb ret = 1; 468b8d22d11Stb err: 4690edabd22Stb BN_CTX_end(ctx); 4702e7cce5eStb 471f7264475Stb return ret; 472b8d22d11Stb } 473b8d22d11Stb 474b8d22d11Stb static void 475b8d22d11Stb print_word(BIO *bp, BN_ULONG w) 476b8d22d11Stb { 477b8d22d11Stb #ifdef SIXTY_FOUR_BIT 478b8d22d11Stb if (sizeof(w) > sizeof(unsigned long)) { 479b8d22d11Stb unsigned long h = (unsigned long)(w >> 32), l = (unsigned long)(w); 480b8d22d11Stb 481b8d22d11Stb if (h) 482b8d22d11Stb BIO_printf(bp, "%lX%08lX", h, l); 483b8d22d11Stb else 484b8d22d11Stb BIO_printf(bp, "%lX", l); 485b8d22d11Stb return; 486b8d22d11Stb } 487b8d22d11Stb #endif 488b8d22d11Stb BIO_printf(bp, BN_HEX_FMT1, w); 489b8d22d11Stb } 490b8d22d11Stb 491b8d22d11Stb int 4920edabd22Stb test_div_word(BIO *bp, BN_CTX *ctx) 493b8d22d11Stb { 4940edabd22Stb BIGNUM *a, *b; 495b8d22d11Stb BN_ULONG r, rmod, s = 0; 496b8d22d11Stb int i; 497f7264475Stb int ret = 0; 498b8d22d11Stb 4990edabd22Stb BN_CTX_start(ctx); 5000edabd22Stb 5010edabd22Stb if ((a = BN_CTX_get(ctx)) == NULL) 502b8d22d11Stb goto err; 5030edabd22Stb if ((b = BN_CTX_get(ctx)) == NULL) 504b8d22d11Stb goto err; 505b8d22d11Stb 506b8d22d11Stb for (i = 0; i < num0; i++) { 507b8d22d11Stb do { 508b8d22d11Stb if (!BN_bntest_rand(a, 512, -1, 0) || 509457e5092Stb !BN_bntest_rand(b, BN_BITS2, -1, 0)) 5102e7cce5eStb goto err; 511b8d22d11Stb s = BN_get_word(b); 512b8d22d11Stb } while (!s); 513b8d22d11Stb 514457e5092Stb if (!bn_copy(b, a)) 5152e7cce5eStb goto err; 516b8d22d11Stb 517b8d22d11Stb rmod = BN_mod_word(b, s); 518b8d22d11Stb r = BN_div_word(b, s); 519b8d22d11Stb 520457e5092Stb if (r == (BN_ULONG)-1 || rmod == (BN_ULONG)-1) 5212e7cce5eStb goto err; 522b8d22d11Stb 523b8d22d11Stb if (rmod != r) { 524b8d22d11Stb fprintf(stderr, "Mod (word) test failed!\n"); 5252e7cce5eStb goto err; 526b8d22d11Stb } 527b8d22d11Stb 528b8d22d11Stb if (bp != NULL) { 529b8d22d11Stb if (!results) { 530b8d22d11Stb CHECK_GOTO(BN_print(bp, a)); 531b8d22d11Stb BIO_puts(bp, " / "); 532b8d22d11Stb print_word(bp, s); 533b8d22d11Stb BIO_puts(bp, " - "); 534b8d22d11Stb } 535b8d22d11Stb CHECK_GOTO(BN_print(bp, b)); 536b8d22d11Stb BIO_puts(bp, "\n"); 537b8d22d11Stb 538b8d22d11Stb if (!results) { 539b8d22d11Stb CHECK_GOTO(BN_print(bp, a)); 540b8d22d11Stb BIO_puts(bp, " % "); 541b8d22d11Stb print_word(bp, s); 542b8d22d11Stb BIO_puts(bp, " - "); 543b8d22d11Stb } 544b8d22d11Stb print_word(bp, r); 545b8d22d11Stb BIO_puts(bp, "\n"); 546b8d22d11Stb } 547b8d22d11Stb CHECK_GOTO(BN_mul_word(b, s)); 548b8d22d11Stb CHECK_GOTO(BN_add_word(b, r)); 549b8d22d11Stb CHECK_GOTO(BN_sub(b, a, b)); 550b8d22d11Stb if (!BN_is_zero(b)) { 551b8d22d11Stb fprintf(stderr, "Division (word) test failed!\n"); 5522e7cce5eStb goto err; 553b8d22d11Stb } 554b8d22d11Stb } 5552e7cce5eStb 556f7264475Stb ret = 1; 557b8d22d11Stb err: 5580edabd22Stb BN_CTX_end(ctx); 559b8d22d11Stb 560f7264475Stb return ret; 561b8d22d11Stb } 562b8d22d11Stb 563b8d22d11Stb int 564b8d22d11Stb test_div_recp(BIO *bp, BN_CTX *ctx) 565b8d22d11Stb { 566b8d22d11Stb BN_RECP_CTX *recp = NULL; 5670edabd22Stb BIGNUM *a, *b, *c, *d, *e; 568b8d22d11Stb int i; 569f7264475Stb int ret = 0; 570b8d22d11Stb 5710edabd22Stb BN_CTX_start(ctx); 5720edabd22Stb 5730edabd22Stb if ((a = BN_CTX_get(ctx)) == NULL) 574b8d22d11Stb goto err; 5750edabd22Stb if ((b = BN_CTX_get(ctx)) == NULL) 576b8d22d11Stb goto err; 5770edabd22Stb if ((c = BN_CTX_get(ctx)) == NULL) 578b8d22d11Stb goto err; 5790edabd22Stb if ((d = BN_CTX_get(ctx)) == NULL) 580b8d22d11Stb goto err; 5810edabd22Stb if ((e = BN_CTX_get(ctx)) == NULL) 582b8d22d11Stb goto err; 583b8d22d11Stb 584b8d22d11Stb for (i = 0; i < num0 + num1; i++) { 585b8d22d11Stb if (i < num1) { 586b8d22d11Stb CHECK_GOTO(BN_bntest_rand(a, 400, 0, 0)); 5878e84e241Stb CHECK_GOTO(bn_copy(b, a)); 588b8d22d11Stb CHECK_GOTO(BN_lshift(a, a, i)); 589b8d22d11Stb CHECK_GOTO(BN_add_word(a, i)); 590b8d22d11Stb } else 591b8d22d11Stb CHECK_GOTO(BN_bntest_rand(b, 50 + 3 * (i - num1), 0, 0)); 5926a951d55Stb BN_RECP_CTX_free(recp); 5936a951d55Stb CHECK_GOTO(recp = BN_RECP_CTX_create(b)); 5942d506d2eStb CHECK_GOTO(BN_div_reciprocal(d, c, a, recp, ctx)); 595b8d22d11Stb if (bp != NULL) { 596b8d22d11Stb if (!results) { 597b8d22d11Stb CHECK_GOTO(BN_print(bp, a)); 598b8d22d11Stb BIO_puts(bp, " / "); 599b8d22d11Stb CHECK_GOTO(BN_print(bp, b)); 600b8d22d11Stb BIO_puts(bp, " - "); 601b8d22d11Stb } 602b8d22d11Stb CHECK_GOTO(BN_print(bp, d)); 603b8d22d11Stb BIO_puts(bp, "\n"); 604b8d22d11Stb 605b8d22d11Stb if (!results) { 606b8d22d11Stb CHECK_GOTO(BN_print(bp, a)); 607b8d22d11Stb BIO_puts(bp, " % "); 608b8d22d11Stb CHECK_GOTO(BN_print(bp, b)); 609b8d22d11Stb BIO_puts(bp, " - "); 610b8d22d11Stb } 611b8d22d11Stb CHECK_GOTO(BN_print(bp, c)); 612b8d22d11Stb BIO_puts(bp, "\n"); 613b8d22d11Stb } 614b8d22d11Stb CHECK_GOTO(BN_mul(e, d, b, ctx)); 615b8d22d11Stb CHECK_GOTO(BN_add(d, e, c)); 616b8d22d11Stb CHECK_GOTO(BN_sub(d, d, a)); 617b8d22d11Stb if (!BN_is_zero(d)) { 618b8d22d11Stb fprintf(stderr, "Reciprocal division test failed!\n"); 619b8d22d11Stb fprintf(stderr, "a="); 620b8d22d11Stb CHECK_GOTO(BN_print_fp(stderr, a)); 621b8d22d11Stb fprintf(stderr, "\nb="); 622b8d22d11Stb CHECK_GOTO(BN_print_fp(stderr, b)); 623b8d22d11Stb fprintf(stderr, "\n"); 6242e7cce5eStb goto err; 625b8d22d11Stb } 626b8d22d11Stb } 6272e7cce5eStb 628f7264475Stb ret = 1; 629b8d22d11Stb err: 6300edabd22Stb BN_CTX_end(ctx); 631b8d22d11Stb BN_RECP_CTX_free(recp); 6322e7cce5eStb 633f7264475Stb return ret; 634b8d22d11Stb } 635b8d22d11Stb 636b8d22d11Stb int 6370edabd22Stb test_mul(BIO *bp, BN_CTX *ctx) 638b8d22d11Stb { 6390edabd22Stb BIGNUM *a, *b, *c, *d, *e; 640b8d22d11Stb int i; 641f7264475Stb int ret = 0; 642b8d22d11Stb 6430edabd22Stb BN_CTX_start(ctx); 644b8d22d11Stb 6450edabd22Stb if ((a = BN_CTX_get(ctx)) == NULL) 646b8d22d11Stb goto err; 6470edabd22Stb if ((b = BN_CTX_get(ctx)) == NULL) 648b8d22d11Stb goto err; 6490edabd22Stb if ((c = BN_CTX_get(ctx)) == NULL) 650b8d22d11Stb goto err; 6510edabd22Stb if ((d = BN_CTX_get(ctx)) == NULL) 652b8d22d11Stb goto err; 6530edabd22Stb if ((e = BN_CTX_get(ctx)) == NULL) 654b8d22d11Stb goto err; 655b8d22d11Stb 656b8d22d11Stb for (i = 0; i < num0 + num1; i++) { 657b8d22d11Stb if (i <= num1) { 658b8d22d11Stb CHECK_GOTO(BN_bntest_rand(a, 100, 0, 0)); 659b8d22d11Stb CHECK_GOTO(BN_bntest_rand(b, 100, 0, 0)); 660b8d22d11Stb } else 661b8d22d11Stb CHECK_GOTO(BN_bntest_rand(b, i - num1, 0, 0)); 662b8d22d11Stb BN_set_negative(a, rand_neg()); 663b8d22d11Stb BN_set_negative(b, rand_neg()); 664b8d22d11Stb CHECK_GOTO(BN_mul(c, a, b, ctx)); 665b8d22d11Stb if (bp != NULL) { 666b8d22d11Stb if (!results) { 667b8d22d11Stb CHECK_GOTO(BN_print(bp, a)); 668b8d22d11Stb BIO_puts(bp, " * "); 669b8d22d11Stb CHECK_GOTO(BN_print(bp, b)); 670b8d22d11Stb BIO_puts(bp, " - "); 671b8d22d11Stb } 672b8d22d11Stb CHECK_GOTO(BN_print(bp, c)); 673b8d22d11Stb BIO_puts(bp, "\n"); 674b8d22d11Stb } 675b8d22d11Stb CHECK_GOTO(BN_div(d, e, c, a, ctx)); 676b8d22d11Stb CHECK_GOTO(BN_sub(d, d, b)); 677b8d22d11Stb if (!BN_is_zero(d) || !BN_is_zero(e)) { 678b8d22d11Stb fprintf(stderr, "Multiplication test failed!\n"); 6792e7cce5eStb goto err; 680b8d22d11Stb } 681b8d22d11Stb } 6822e7cce5eStb 683f7264475Stb ret = 1; 684b8d22d11Stb err: 6850edabd22Stb BN_CTX_end(ctx); 6862e7cce5eStb 687f7264475Stb return ret; 688b8d22d11Stb } 689b8d22d11Stb 690b8d22d11Stb int 691b8d22d11Stb test_sqr(BIO *bp, BN_CTX *ctx) 692b8d22d11Stb { 6930edabd22Stb BIGNUM *a, *c, *d, *e; 694568ce9ecStb int i; 695f7264475Stb int ret = 0; 696b8d22d11Stb 6970edabd22Stb BN_CTX_start(ctx); 6980edabd22Stb 6990edabd22Stb if ((a = BN_CTX_get(ctx)) == NULL) 700b8d22d11Stb goto err; 7010edabd22Stb if ((c = BN_CTX_get(ctx)) == NULL) 702b8d22d11Stb goto err; 7030edabd22Stb if ((d = BN_CTX_get(ctx)) == NULL) 704b8d22d11Stb goto err; 7050edabd22Stb if ((e = BN_CTX_get(ctx)) == NULL) 706b8d22d11Stb goto err; 707b8d22d11Stb 708b8d22d11Stb for (i = 0; i < num0; i++) { 709b8d22d11Stb CHECK_GOTO(BN_bntest_rand(a, 40 + i * 10, 0, 0)); 710b8d22d11Stb BN_set_negative(a, rand_neg()); 711b8d22d11Stb CHECK_GOTO(BN_sqr(c, a, ctx)); 712b8d22d11Stb if (bp != NULL) { 713b8d22d11Stb if (!results) { 714b8d22d11Stb CHECK_GOTO(BN_print(bp, a)); 715b8d22d11Stb BIO_puts(bp, " * "); 716b8d22d11Stb CHECK_GOTO(BN_print(bp, a)); 717b8d22d11Stb BIO_puts(bp, " - "); 718b8d22d11Stb } 719b8d22d11Stb CHECK_GOTO(BN_print(bp, c)); 720b8d22d11Stb BIO_puts(bp, "\n"); 721b8d22d11Stb } 722b8d22d11Stb CHECK_GOTO(BN_div(d, e, c, a, ctx)); 723b8d22d11Stb CHECK_GOTO(BN_sub(d, d, a)); 724b8d22d11Stb if (!BN_is_zero(d) || !BN_is_zero(e)) { 725b8d22d11Stb fprintf(stderr, "Square test failed!\n"); 726b8d22d11Stb goto err; 727b8d22d11Stb } 728b8d22d11Stb } 729b8d22d11Stb 730b8d22d11Stb /* Regression test for a BN_sqr overflow bug. */ 731b8d22d11Stb if (!BN_hex2bn(&a, "80000000000000008000000000000001" 732b8d22d11Stb "FFFFFFFFFFFFFFFE0000000000000000")) { 733b8d22d11Stb fprintf(stderr, "BN_hex2bn failed\n"); 734b8d22d11Stb goto err; 735b8d22d11Stb } 736b8d22d11Stb CHECK_GOTO(BN_sqr(c, a, ctx)); 737b8d22d11Stb if (bp != NULL) { 738b8d22d11Stb if (!results) { 739b8d22d11Stb CHECK_GOTO(BN_print(bp, a)); 740b8d22d11Stb BIO_puts(bp, " * "); 741b8d22d11Stb CHECK_GOTO(BN_print(bp, a)); 742b8d22d11Stb BIO_puts(bp, " - "); 743b8d22d11Stb } 744b8d22d11Stb CHECK_GOTO(BN_print(bp, c)); 745b8d22d11Stb BIO_puts(bp, "\n"); 746b8d22d11Stb } 747b8d22d11Stb CHECK_GOTO(BN_mul(d, a, a, ctx)); 748b8d22d11Stb if (BN_cmp(c, d)) { 749b8d22d11Stb fprintf(stderr, 750b8d22d11Stb "Square test failed: BN_sqr and BN_mul produce " 751b8d22d11Stb "different results!\n"); 752b8d22d11Stb goto err; 753b8d22d11Stb } 754b8d22d11Stb 755b8d22d11Stb /* Regression test for a BN_sqr overflow bug. */ 756b8d22d11Stb if (!BN_hex2bn(&a, "80000000000000000000000080000001" 757b8d22d11Stb "FFFFFFFE000000000000000000000000")) { 758b8d22d11Stb fprintf(stderr, "BN_hex2bn failed\n"); 759b8d22d11Stb goto err; 760b8d22d11Stb } 761b8d22d11Stb CHECK_GOTO(BN_sqr(c, a, ctx)); 762b8d22d11Stb if (bp != NULL) { 763b8d22d11Stb if (!results) { 764b8d22d11Stb CHECK_GOTO(BN_print(bp, a)); 765b8d22d11Stb BIO_puts(bp, " * "); 766b8d22d11Stb CHECK_GOTO(BN_print(bp, a)); 767b8d22d11Stb BIO_puts(bp, " - "); 768b8d22d11Stb } 769b8d22d11Stb CHECK_GOTO(BN_print(bp, c)); 770b8d22d11Stb BIO_puts(bp, "\n"); 771b8d22d11Stb } 772b8d22d11Stb CHECK_GOTO(BN_mul(d, a, a, ctx)); 773b8d22d11Stb if (BN_cmp(c, d)) { 774b8d22d11Stb fprintf(stderr, "Square test failed: BN_sqr and BN_mul produce " 775b8d22d11Stb "different results!\n"); 776b8d22d11Stb goto err; 777b8d22d11Stb } 7782e7cce5eStb 779f7264475Stb ret = 1; 780b8d22d11Stb err: 7810edabd22Stb BN_CTX_end(ctx); 7822e7cce5eStb 783f7264475Stb return ret; 784b8d22d11Stb } 785b8d22d11Stb 786b8d22d11Stb int 787b8d22d11Stb test_mont(BIO *bp, BN_CTX *ctx) 788b8d22d11Stb { 7890edabd22Stb BN_MONT_CTX *mont = NULL; 7900edabd22Stb BIGNUM *a, *b, *c, *d, *A, *B, *n; 791b8d22d11Stb int i; 792f7264475Stb int ret = 0; 793b8d22d11Stb 7940edabd22Stb BN_CTX_start(ctx); 795b8d22d11Stb 7960edabd22Stb if ((a = BN_CTX_get(ctx)) == NULL) 797b8d22d11Stb goto err; 7980edabd22Stb if ((b = BN_CTX_get(ctx)) == NULL) 799b8d22d11Stb goto err; 8000edabd22Stb if ((c = BN_CTX_get(ctx)) == NULL) 801b8d22d11Stb goto err; 8020edabd22Stb if ((d = BN_CTX_get(ctx)) == NULL) 803b8d22d11Stb goto err; 8040edabd22Stb if ((A = BN_CTX_get(ctx)) == NULL) 805b8d22d11Stb goto err; 8060edabd22Stb if ((B = BN_CTX_get(ctx)) == NULL) 807b8d22d11Stb goto err; 8080edabd22Stb if ((n = BN_CTX_get(ctx)) == NULL) 8090edabd22Stb goto err; 8100edabd22Stb 8110edabd22Stb if ((mont = BN_MONT_CTX_new()) == NULL) 812b8d22d11Stb goto err; 813b8d22d11Stb 81430ad135cStb BN_zero(n); 815b8d22d11Stb if (BN_MONT_CTX_set(mont, n, ctx)) { 816b8d22d11Stb fprintf(stderr, "BN_MONT_CTX_set succeeded for zero modulus!\n"); 817bb44b87cStb goto err; 818b8d22d11Stb } 8195550240dStb ERR_clear_error(); 820b8d22d11Stb 821b8d22d11Stb CHECK_GOTO(BN_set_word(n, 16)); 822b8d22d11Stb if (BN_MONT_CTX_set(mont, n, ctx)) { 823b8d22d11Stb fprintf(stderr, "BN_MONT_CTX_set succeeded for even modulus!\n"); 824bb44b87cStb goto err; 825b8d22d11Stb } 8265550240dStb ERR_clear_error(); 827b8d22d11Stb 828b8d22d11Stb CHECK_GOTO(BN_bntest_rand(a, 100, 0, 0)); 829b8d22d11Stb CHECK_GOTO(BN_bntest_rand(b, 100, 0, 0)); 830b8d22d11Stb for (i = 0; i < num2; i++) { 831b8d22d11Stb int bits = (200 * (i + 1)) / num2; 832b8d22d11Stb 833b8d22d11Stb if (bits == 0) 834b8d22d11Stb continue; 835b8d22d11Stb CHECK_GOTO(BN_bntest_rand(n, bits, 0, 1)); 836b8d22d11Stb CHECK_GOTO(BN_MONT_CTX_set(mont, n, ctx)); 837b8d22d11Stb 838b8d22d11Stb CHECK_GOTO(BN_nnmod(a, a, n, ctx)); 839b8d22d11Stb CHECK_GOTO(BN_nnmod(b, b, n, ctx)); 840b8d22d11Stb 841b8d22d11Stb CHECK_GOTO(BN_to_montgomery(A, a, mont, ctx)); 842b8d22d11Stb CHECK_GOTO(BN_to_montgomery(B, b, mont, ctx)); 843b8d22d11Stb 844b8d22d11Stb CHECK_GOTO(BN_mod_mul_montgomery(c, A, B, mont, ctx)); 845b8d22d11Stb CHECK_GOTO(BN_from_montgomery(A, c, mont, ctx)); 846b8d22d11Stb if (bp != NULL) { 847b8d22d11Stb if (!results) { 848b8d22d11Stb CHECK_GOTO(BN_print(bp, a)); 849b8d22d11Stb BIO_puts(bp, " * "); 850b8d22d11Stb CHECK_GOTO(BN_print(bp, b)); 851b8d22d11Stb BIO_puts(bp, " % "); 852b8d22d11Stb /* n == &mont->N */ 853b8d22d11Stb CHECK_GOTO(BN_print(bp, n)); 854b8d22d11Stb BIO_puts(bp, " - "); 855b8d22d11Stb } 856b8d22d11Stb CHECK_GOTO(BN_print(bp, A)); 857b8d22d11Stb BIO_puts(bp, "\n"); 858b8d22d11Stb } 859b8d22d11Stb CHECK_GOTO(BN_mod_mul(d, a, b, n, ctx)); 860b8d22d11Stb CHECK_GOTO(BN_sub(d, d, A)); 861b8d22d11Stb if (!BN_is_zero(d)) { 862b8d22d11Stb fprintf(stderr, "Montgomery multiplication test failed!\n"); 8632e7cce5eStb goto err; 864b8d22d11Stb } 865b8d22d11Stb } 8662e7cce5eStb 867f7264475Stb ret = 1; 868b8d22d11Stb err: 8690edabd22Stb BN_CTX_end(ctx); 870b8d22d11Stb BN_MONT_CTX_free(mont); 8712e7cce5eStb 872f7264475Stb return ret; 873b8d22d11Stb } 874b8d22d11Stb 875b8d22d11Stb int 876b8d22d11Stb test_mod(BIO *bp, BN_CTX *ctx) 877b8d22d11Stb { 8780edabd22Stb BIGNUM *a, *b, *c, *d, *e; 879b8d22d11Stb int i; 880f7264475Stb int ret = 0; 881b8d22d11Stb 8820edabd22Stb BN_CTX_start(ctx); 8830edabd22Stb 8840edabd22Stb if ((a = BN_CTX_get(ctx)) == NULL) 885b8d22d11Stb goto err; 8860edabd22Stb if ((b = BN_CTX_get(ctx)) == NULL) 887b8d22d11Stb goto err; 8880edabd22Stb if ((c = BN_CTX_get(ctx)) == NULL) 889b8d22d11Stb goto err; 8900edabd22Stb if ((d = BN_CTX_get(ctx)) == NULL) 891b8d22d11Stb goto err; 8920edabd22Stb if ((e = BN_CTX_get(ctx)) == NULL) 893b8d22d11Stb goto err; 894b8d22d11Stb 895b8d22d11Stb CHECK_GOTO(BN_bntest_rand(a, 1024, 0, 0)); 896b8d22d11Stb for (i = 0; i < num0; i++) { 897b8d22d11Stb CHECK_GOTO(BN_bntest_rand(b, 450 + i * 10, 0, 0)); 898b8d22d11Stb BN_set_negative(a, rand_neg()); 899b8d22d11Stb BN_set_negative(b, rand_neg()); 900b8d22d11Stb CHECK_GOTO(BN_mod(c, a, b, ctx)); 901b8d22d11Stb if (bp != NULL) { 902b8d22d11Stb if (!results) { 903b8d22d11Stb CHECK_GOTO(BN_print(bp, a)); 904b8d22d11Stb BIO_puts(bp, " % "); 905b8d22d11Stb CHECK_GOTO(BN_print(bp, b)); 906b8d22d11Stb BIO_puts(bp, " - "); 907b8d22d11Stb } 908b8d22d11Stb CHECK_GOTO(BN_print(bp, c)); 909b8d22d11Stb BIO_puts(bp, "\n"); 910b8d22d11Stb } 911b8d22d11Stb CHECK_GOTO(BN_div(d, e, a, b, ctx)); 912b8d22d11Stb CHECK_GOTO(BN_sub(e, e, c)); 913b8d22d11Stb if (!BN_is_zero(e)) { 914b8d22d11Stb fprintf(stderr, "Modulo test failed!\n"); 9152e7cce5eStb goto err; 916b8d22d11Stb } 917b8d22d11Stb } 9182e7cce5eStb 919f7264475Stb ret = 1; 920b8d22d11Stb err: 9210edabd22Stb BN_CTX_end(ctx); 9222e7cce5eStb 923f7264475Stb return ret; 924b8d22d11Stb } 925b8d22d11Stb 926b8d22d11Stb int 927b8d22d11Stb test_mod_mul(BIO *bp, BN_CTX *ctx) 928b8d22d11Stb { 9290edabd22Stb BIGNUM *a, *b, *c, *d, *e; 930b8d22d11Stb int i, j; 931f7264475Stb int ret = 0; 932b8d22d11Stb 9330edabd22Stb BN_CTX_start(ctx); 9340edabd22Stb 9350edabd22Stb if ((a = BN_CTX_get(ctx)) == NULL) 936b8d22d11Stb goto err; 9370edabd22Stb if ((b = BN_CTX_get(ctx)) == NULL) 938b8d22d11Stb goto err; 9390edabd22Stb if ((c = BN_CTX_get(ctx)) == NULL) 940b8d22d11Stb goto err; 9410edabd22Stb if ((d = BN_CTX_get(ctx)) == NULL) 942b8d22d11Stb goto err; 9430edabd22Stb if ((e = BN_CTX_get(ctx)) == NULL) 944b8d22d11Stb goto err; 945b8d22d11Stb 946b8d22d11Stb CHECK_GOTO(BN_one(a)); 947b8d22d11Stb CHECK_GOTO(BN_one(b)); 94830ad135cStb BN_zero(c); 949b8d22d11Stb if (BN_mod_mul(e, a, b, c, ctx)) { 950b8d22d11Stb fprintf(stderr, "BN_mod_mul with zero modulus succeeded!\n"); 951bb44b87cStb goto err; 952b8d22d11Stb } 9535550240dStb ERR_clear_error(); 954b8d22d11Stb 955b8d22d11Stb for (j = 0; j < 3; j++) { 956b8d22d11Stb CHECK_GOTO(BN_bntest_rand(c, 1024, 0, 0)); 957b8d22d11Stb for (i = 0; i < num0; i++) { 958b8d22d11Stb CHECK_GOTO(BN_bntest_rand(a, 475 + i * 10, 0, 0)); 959b8d22d11Stb CHECK_GOTO(BN_bntest_rand(b, 425 + i * 11, 0, 0)); 960b8d22d11Stb BN_set_negative(a, rand_neg()); 961b8d22d11Stb BN_set_negative(b, rand_neg()); 962b8d22d11Stb if (!BN_mod_mul(e, a, b, c, ctx)) { 963b8d22d11Stb unsigned long l; 964b8d22d11Stb 965b8d22d11Stb while ((l = ERR_get_error())) 966b8d22d11Stb fprintf(stderr, "ERROR:%s\n", 967b8d22d11Stb ERR_error_string(l, NULL)); 968b8d22d11Stb exit(1); 969b8d22d11Stb } 970b8d22d11Stb if (bp != NULL) { 971b8d22d11Stb if (!results) { 972b8d22d11Stb CHECK_GOTO(BN_print(bp, a)); 973b8d22d11Stb BIO_puts(bp, " * "); 974b8d22d11Stb CHECK_GOTO(BN_print(bp, b)); 975b8d22d11Stb BIO_puts(bp, " % "); 976b8d22d11Stb CHECK_GOTO(BN_print(bp, c)); 977b8d22d11Stb if ((BN_is_negative(a) ^ BN_is_negative(b)) && 978b8d22d11Stb !BN_is_zero(e)) { 979b8d22d11Stb /* If (a*b) % c is negative, c must be added 980b8d22d11Stb * in order to obtain the normalized remainder 981b8d22d11Stb * (new with OpenSSL 0.9.7, previous versions of 982b8d22d11Stb * BN_mod_mul could generate negative results) 983b8d22d11Stb */ 984b8d22d11Stb BIO_puts(bp, " + "); 985b8d22d11Stb CHECK_GOTO(BN_print(bp, c)); 986b8d22d11Stb } 987b8d22d11Stb BIO_puts(bp, " - "); 988b8d22d11Stb } 989b8d22d11Stb CHECK_GOTO(BN_print(bp, e)); 990b8d22d11Stb BIO_puts(bp, "\n"); 991b8d22d11Stb } 992b8d22d11Stb CHECK_GOTO(BN_mul(d, a, b, ctx)); 993b8d22d11Stb CHECK_GOTO(BN_sub(d, d, e)); 994b8d22d11Stb CHECK_GOTO(BN_div(a, b, d, c, ctx)); 995b8d22d11Stb if (!BN_is_zero(b)) { 996b8d22d11Stb fprintf(stderr, "Modulo multiply test failed!\n"); 997b8d22d11Stb ERR_print_errors_fp(stderr); 998b8d22d11Stb goto err; 999b8d22d11Stb } 1000b8d22d11Stb } 1001b8d22d11Stb } 10022e7cce5eStb 1003f7264475Stb ret = 1; 1004b8d22d11Stb err: 10050edabd22Stb BN_CTX_end(ctx); 10062e7cce5eStb 1007f7264475Stb return ret; 1008b8d22d11Stb } 1009b8d22d11Stb 1010b8d22d11Stb int 1011b8d22d11Stb test_mod_exp(BIO *bp, BN_CTX *ctx) 1012b8d22d11Stb { 10130edabd22Stb BIGNUM *a, *b, *c, *d, *e; 1014b8d22d11Stb int i; 1015f7264475Stb int ret = 0; 1016b8d22d11Stb 10170edabd22Stb BN_CTX_start(ctx); 10180edabd22Stb 10190edabd22Stb if ((a = BN_CTX_get(ctx)) == NULL) 1020b8d22d11Stb goto err; 10210edabd22Stb if ((b = BN_CTX_get(ctx)) == NULL) 1022b8d22d11Stb goto err; 10230edabd22Stb if ((c = BN_CTX_get(ctx)) == NULL) 1024b8d22d11Stb goto err; 10250edabd22Stb if ((d = BN_CTX_get(ctx)) == NULL) 1026b8d22d11Stb goto err; 10270edabd22Stb if ((e = BN_CTX_get(ctx)) == NULL) 1028b8d22d11Stb goto err; 1029b8d22d11Stb 1030b8d22d11Stb CHECK_GOTO(BN_one(a)); 1031b8d22d11Stb CHECK_GOTO(BN_one(b)); 103230ad135cStb BN_zero(c); 1033b8d22d11Stb if (BN_mod_exp(d, a, b, c, ctx)) { 1034b8d22d11Stb fprintf(stderr, "BN_mod_exp with zero modulus succeeded!\n"); 1035b8d22d11Stb goto err; 1036b8d22d11Stb } 10375550240dStb ERR_clear_error(); 1038b8d22d11Stb if (BN_mod_exp_ct(d, a, b, c, ctx)) { 1039b8d22d11Stb fprintf(stderr, "BN_mod_exp_ct with zero modulus succeeded!\n"); 1040b8d22d11Stb goto err; 1041b8d22d11Stb } 10425550240dStb ERR_clear_error(); 1043b8d22d11Stb if (BN_mod_exp_nonct(d, a, b, c, ctx)) { 1044b8d22d11Stb fprintf(stderr, "BN_mod_exp_nonct with zero modulus succeeded!\n"); 1045b8d22d11Stb goto err; 1046b8d22d11Stb } 10475550240dStb ERR_clear_error(); 1048b8d22d11Stb 1049b8d22d11Stb CHECK_GOTO(BN_bntest_rand(c, 30, 0, 1)); /* must be odd for montgomery */ 1050b8d22d11Stb for (i = 0; i < num2; i++) { 1051b8d22d11Stb CHECK_GOTO(BN_bntest_rand(a, 20 + i * 5, 0, 0)); 1052b8d22d11Stb CHECK_GOTO(BN_bntest_rand(b, 2 + i, 0, 0)); 1053b8d22d11Stb 1054457e5092Stb if (!BN_mod_exp(d, a, b, c, ctx)) 10552e7cce5eStb goto err; 1056b8d22d11Stb 1057b8d22d11Stb if (bp != NULL) { 1058b8d22d11Stb if (!results) { 1059b8d22d11Stb CHECK_GOTO(BN_print(bp, a)); 1060b8d22d11Stb BIO_puts(bp, " ^ "); 1061b8d22d11Stb CHECK_GOTO(BN_print(bp, b)); 1062b8d22d11Stb BIO_puts(bp, " % "); 1063b8d22d11Stb CHECK_GOTO(BN_print(bp, c)); 1064b8d22d11Stb BIO_puts(bp, " - "); 1065b8d22d11Stb } 1066b8d22d11Stb CHECK_GOTO(BN_print(bp, d)); 1067b8d22d11Stb BIO_puts(bp, "\n"); 1068b8d22d11Stb } 1069b8d22d11Stb CHECK_GOTO(BN_exp(e, a, b, ctx)); 1070b8d22d11Stb CHECK_GOTO(BN_sub(e, e, d)); 1071b8d22d11Stb CHECK_GOTO(BN_div(a, b, e, c, ctx)); 1072b8d22d11Stb if (!BN_is_zero(b)) { 1073b8d22d11Stb fprintf(stderr, "Modulo exponentiation test failed!\n"); 10742e7cce5eStb goto err; 1075b8d22d11Stb } 1076b8d22d11Stb } 1077b8d22d11Stb 1078b8d22d11Stb CHECK_GOTO(BN_bntest_rand(c, 30, 0, 1)); /* must be odd for montgomery */ 1079b8d22d11Stb for (i = 0; i < num2; i++) { 1080b8d22d11Stb CHECK_GOTO(BN_bntest_rand(a, 20 + i * 5, 0, 0)); 1081b8d22d11Stb CHECK_GOTO(BN_bntest_rand(b, 2 + i, 0, 0)); 1082b8d22d11Stb 1083457e5092Stb if (!BN_mod_exp_ct(d, a, b, c, ctx)) 10842e7cce5eStb goto err; 1085b8d22d11Stb 1086b8d22d11Stb if (bp != NULL) { 1087b8d22d11Stb if (!results) { 1088b8d22d11Stb CHECK_GOTO(BN_print(bp, a)); 1089b8d22d11Stb BIO_puts(bp, " ^ "); 1090b8d22d11Stb CHECK_GOTO(BN_print(bp, b)); 1091b8d22d11Stb BIO_puts(bp, " % "); 1092b8d22d11Stb CHECK_GOTO(BN_print(bp, c)); 1093b8d22d11Stb BIO_puts(bp, " - "); 1094b8d22d11Stb } 1095b8d22d11Stb CHECK_GOTO(BN_print(bp, d)); 1096b8d22d11Stb BIO_puts(bp, "\n"); 1097b8d22d11Stb } 1098b8d22d11Stb CHECK_GOTO(BN_exp(e, a, b, ctx)); 1099b8d22d11Stb CHECK_GOTO(BN_sub(e, e, d)); 1100b8d22d11Stb CHECK_GOTO(BN_div(a, b, e, c, ctx)); 1101b8d22d11Stb if (!BN_is_zero(b)) { 1102b8d22d11Stb fprintf(stderr, "Modulo exponentiation test failed!\n"); 11032e7cce5eStb goto err; 1104b8d22d11Stb } 1105b8d22d11Stb } 1106b8d22d11Stb 1107b8d22d11Stb CHECK_GOTO(BN_bntest_rand(c, 30, 0, 1)); /* must be odd for montgomery */ 1108b8d22d11Stb for (i = 0; i < num2; i++) { 1109b8d22d11Stb CHECK_GOTO(BN_bntest_rand(a, 20 + i * 5, 0, 0)); 1110b8d22d11Stb CHECK_GOTO(BN_bntest_rand(b, 2 + i, 0, 0)); 1111b8d22d11Stb 1112457e5092Stb if (!BN_mod_exp_nonct(d, a, b, c, ctx)) 11132e7cce5eStb goto err; 1114b8d22d11Stb 1115b8d22d11Stb if (bp != NULL) { 1116b8d22d11Stb if (!results) { 1117b8d22d11Stb CHECK_GOTO(BN_print(bp, a)); 1118b8d22d11Stb BIO_puts(bp, " ^ "); 1119b8d22d11Stb CHECK_GOTO(BN_print(bp, b)); 1120b8d22d11Stb BIO_puts(bp, " % "); 1121b8d22d11Stb CHECK_GOTO(BN_print(bp, c)); 1122b8d22d11Stb BIO_puts(bp, " - "); 1123b8d22d11Stb } 1124b8d22d11Stb CHECK_GOTO(BN_print(bp, d)); 1125b8d22d11Stb BIO_puts(bp, "\n"); 1126b8d22d11Stb } 1127b8d22d11Stb CHECK_GOTO(BN_exp(e, a, b, ctx)); 1128b8d22d11Stb CHECK_GOTO(BN_sub(e, e, d)); 1129b8d22d11Stb CHECK_GOTO(BN_div(a, b, e, c, ctx)); 1130b8d22d11Stb if (!BN_is_zero(b)) { 1131b8d22d11Stb fprintf(stderr, "Modulo exponentiation test failed!\n"); 11322e7cce5eStb goto err; 1133b8d22d11Stb } 1134b8d22d11Stb } 11352e7cce5eStb 1136f7264475Stb ret = 1; 1137b8d22d11Stb err: 11380edabd22Stb BN_CTX_end(ctx); 11392e7cce5eStb 1140f7264475Stb return ret; 1141b8d22d11Stb } 1142b8d22d11Stb 1143b8d22d11Stb int 1144b8d22d11Stb test_mod_exp_mont_consttime(BIO *bp, BN_CTX *ctx) 1145b8d22d11Stb { 11460edabd22Stb BIGNUM *a, *b, *c, *d, *e; 1147b8d22d11Stb int i; 1148f7264475Stb int ret = 0; 1149b8d22d11Stb 11500edabd22Stb BN_CTX_start(ctx); 11510edabd22Stb 11520edabd22Stb if ((a = BN_CTX_get(ctx)) == NULL) 1153b8d22d11Stb goto err; 11540edabd22Stb if ((b = BN_CTX_get(ctx)) == NULL) 1155b8d22d11Stb goto err; 11560edabd22Stb if ((c = BN_CTX_get(ctx)) == NULL) 1157b8d22d11Stb goto err; 11580edabd22Stb if ((d = BN_CTX_get(ctx)) == NULL) 1159b8d22d11Stb goto err; 11600edabd22Stb if ((e = BN_CTX_get(ctx)) == NULL) 1161b8d22d11Stb goto err; 1162b8d22d11Stb 1163b8d22d11Stb CHECK_GOTO(BN_one(a)); 1164b8d22d11Stb CHECK_GOTO(BN_one(b)); 116530ad135cStb BN_zero(c); 1166b8d22d11Stb if (BN_mod_exp_mont_consttime(d, a, b, c, ctx, NULL)) { 1167b8d22d11Stb fprintf(stderr, "BN_mod_exp_mont_consttime with zero modulus " 1168b8d22d11Stb "succeeded\n"); 1169b8d22d11Stb goto err; 1170b8d22d11Stb } 11715550240dStb ERR_clear_error(); 1172b8d22d11Stb 1173b8d22d11Stb CHECK_GOTO(BN_set_word(c, 16)); 1174b8d22d11Stb if (BN_mod_exp_mont_consttime(d, a, b, c, ctx, NULL)) { 1175b8d22d11Stb fprintf(stderr, "BN_mod_exp_mont_consttime with even modulus " 1176b8d22d11Stb "succeeded\n"); 1177b8d22d11Stb goto err; 1178b8d22d11Stb } 11795550240dStb ERR_clear_error(); 1180b8d22d11Stb 1181b8d22d11Stb CHECK_GOTO(BN_bntest_rand(c, 30, 0, 1)); /* must be odd for montgomery */ 1182b8d22d11Stb for (i = 0; i < num2; i++) { 1183b8d22d11Stb CHECK_GOTO(BN_bntest_rand(a, 20 + i * 5, 0, 0)); 1184b8d22d11Stb CHECK_GOTO(BN_bntest_rand(b, 2 + i, 0, 0)); 1185b8d22d11Stb 1186457e5092Stb if (!BN_mod_exp_mont_consttime(d, a, b, c, ctx, NULL)) 11872e7cce5eStb goto err; 1188b8d22d11Stb 1189b8d22d11Stb if (bp != NULL) { 1190b8d22d11Stb if (!results) { 1191b8d22d11Stb CHECK_GOTO(BN_print(bp, a)); 1192b8d22d11Stb BIO_puts(bp, " ^ "); 1193b8d22d11Stb CHECK_GOTO(BN_print(bp, b)); 1194b8d22d11Stb BIO_puts(bp, " % "); 1195b8d22d11Stb CHECK_GOTO(BN_print(bp, c)); 1196b8d22d11Stb BIO_puts(bp, " - "); 1197b8d22d11Stb } 1198b8d22d11Stb CHECK_GOTO(BN_print(bp, d)); 1199b8d22d11Stb BIO_puts(bp, "\n"); 1200b8d22d11Stb } 1201b8d22d11Stb CHECK_GOTO(BN_exp(e, a, b, ctx)); 1202b8d22d11Stb CHECK_GOTO(BN_sub(e, e, d)); 1203b8d22d11Stb CHECK_GOTO(BN_div(a, b, e, c, ctx)); 1204b8d22d11Stb if (!BN_is_zero(b)) { 1205b8d22d11Stb fprintf(stderr, "Modulo exponentiation test failed!\n"); 12062e7cce5eStb goto err; 1207b8d22d11Stb } 1208b8d22d11Stb } 12092e7cce5eStb 1210f7264475Stb ret = 1; 1211b8d22d11Stb err: 12120edabd22Stb BN_CTX_end(ctx); 12132e7cce5eStb 1214f7264475Stb return ret; 1215b8d22d11Stb } 1216b8d22d11Stb 1217b8d22d11Stb /* 1218b8d22d11Stb * Test constant-time modular exponentiation with 1024-bit inputs, which on 1219b8d22d11Stb * x86_64 cause a different code branch to be taken. 1220b8d22d11Stb */ 1221b8d22d11Stb int 1222b8d22d11Stb test_mod_exp_mont5(BIO *bp, BN_CTX *ctx) 1223b8d22d11Stb { 12240edabd22Stb BIGNUM *a, *p, *m, *d, *e; 12250edabd22Stb BIGNUM *b, *n, *c; 1226b8d22d11Stb BN_MONT_CTX *mont = NULL; 1227b8d22d11Stb int len; 1228f7264475Stb int ret = 0; 1229b8d22d11Stb 12300edabd22Stb BN_CTX_start(ctx); 12310edabd22Stb 12320edabd22Stb if ((a = BN_CTX_get(ctx)) == NULL) 1233b8d22d11Stb goto err; 12340edabd22Stb if ((p = BN_CTX_get(ctx)) == NULL) 1235b8d22d11Stb goto err; 12360edabd22Stb if ((m = BN_CTX_get(ctx)) == NULL) 1237b8d22d11Stb goto err; 12380edabd22Stb if ((d = BN_CTX_get(ctx)) == NULL) 1239b8d22d11Stb goto err; 12400edabd22Stb if ((e = BN_CTX_get(ctx)) == NULL) 1241b8d22d11Stb goto err; 12420edabd22Stb if ((b = BN_CTX_get(ctx)) == NULL) 1243b8d22d11Stb goto err; 12440edabd22Stb if ((n = BN_CTX_get(ctx)) == NULL) 1245b8d22d11Stb goto err; 12460edabd22Stb if ((c = BN_CTX_get(ctx)) == NULL) 1247b8d22d11Stb goto err; 1248b8d22d11Stb 1249b8d22d11Stb CHECK_GOTO(mont = BN_MONT_CTX_new()); 1250b8d22d11Stb 1251b8d22d11Stb CHECK_GOTO(BN_bntest_rand(m, 1024, 0, 1)); /* must be odd for montgomery */ 1252b8d22d11Stb /* Zero exponent */ 1253b8d22d11Stb CHECK_GOTO(BN_bntest_rand(a, 1024, 0, 0)); 125430ad135cStb BN_zero(p); 1255457e5092Stb if (!BN_mod_exp_mont_consttime(d, a, p, m, ctx, NULL)) 1256b8d22d11Stb goto err; 1257b8d22d11Stb if (!BN_is_one(d)) { 1258b8d22d11Stb fprintf(stderr, "Modular exponentiation test failed!\n"); 1259b8d22d11Stb goto err; 1260b8d22d11Stb } 1261b8d22d11Stb /* Regression test for carry bug in mulx4x_mont */ 1262b8d22d11Stb len = BN_hex2bn(&a, 1263b8d22d11Stb "7878787878787878787878787878787878787878787878787878787878787878" 1264b8d22d11Stb "7878787878787878787878787878787878787878787878787878787878787878" 1265b8d22d11Stb "7878787878787878787878787878787878787878787878787878787878787878" 1266b8d22d11Stb "7878787878787878787878787878787878787878787878787878787878787878"); 1267b8d22d11Stb CHECK_GOTO(len); 1268b8d22d11Stb len = BN_hex2bn(&b, 1269b8d22d11Stb "095D72C08C097BA488C5E439C655A192EAFB6380073D8C2664668EDDB4060744" 1270b8d22d11Stb "E16E57FB4EDB9AE10A0CEFCDC28A894F689A128379DB279D48A2E20849D68593" 1271b8d22d11Stb "9B7803BCF46CEBF5C533FB0DD35B080593DE5472E3FE5DB951B8BFF9B4CB8F03" 1272b8d22d11Stb "9CC638A5EE8CDD703719F8000E6A9F63BEED5F2FCD52FF293EA05A251BB4AB81"); 1273b8d22d11Stb CHECK_GOTO(len); 1274b8d22d11Stb len = BN_hex2bn(&n, 1275b8d22d11Stb "D78AF684E71DB0C39CFF4E64FB9DB567132CB9C50CC98009FEB820B26F2DED9B" 1276b8d22d11Stb "91B9B5E2B83AE0AE4EB4E0523CA726BFBE969B89FD754F674CE99118C3F2D1C5" 1277b8d22d11Stb "D81FDC7C54E02B60262B241D53C040E99E45826ECA37A804668E690E1AFC1CA4" 1278b8d22d11Stb "2C9A15D84D4954425F0B7642FC0BD9D7B24E2618D2DCC9B729D944BADACFDDAF"); 1279b8d22d11Stb CHECK_GOTO(len); 1280b8d22d11Stb CHECK_GOTO(BN_MONT_CTX_set(mont, n, ctx)); 1281b8d22d11Stb CHECK_GOTO(BN_mod_mul_montgomery(c, a, b, mont, ctx)); 1282b8d22d11Stb CHECK_GOTO(BN_mod_mul_montgomery(d, b, a, mont, ctx)); 1283b8d22d11Stb if (BN_cmp(c, d)) { 1284b8d22d11Stb fprintf(stderr, "Montgomery multiplication test failed:" 1285b8d22d11Stb " a*b != b*a.\n"); 1286b8d22d11Stb goto err; 1287b8d22d11Stb } 1288b8d22d11Stb /* Regression test for carry bug in sqr[x]8x_mont */ 1289b8d22d11Stb len = BN_hex2bn(&n, 1290b8d22d11Stb "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" 1291b8d22d11Stb "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" 1292b8d22d11Stb "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" 1293b8d22d11Stb "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" 1294b8d22d11Stb "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" 1295b8d22d11Stb "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" 1296b8d22d11Stb "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" 1297b8d22d11Stb "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000FFFFFFFF00" 1298b8d22d11Stb "0000000000000000000000000000000000000000000000000000000000000000" 1299b8d22d11Stb "0000000000000000000000000000000000000000000000000000000000000000" 1300b8d22d11Stb "0000000000000000000000000000000000000000000000000000000000000000" 1301b8d22d11Stb "0000000000000000000000000000000000000000000000000000000000000000" 1302b8d22d11Stb "0000000000000000000000000000000000000000000000000000000000000000" 1303b8d22d11Stb "0000000000000000000000000000000000000000000000000000000000000000" 1304b8d22d11Stb "0000000000000000000000000000000000000000000000000000000000000000" 1305b8d22d11Stb "00000000000000000000000000000000000000000000000000FFFFFFFFFFFFFF"); 1306b8d22d11Stb CHECK_GOTO(len); 1307b8d22d11Stb len = BN_hex2bn(&a, 1308b8d22d11Stb "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" 1309b8d22d11Stb "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" 1310b8d22d11Stb "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" 1311b8d22d11Stb "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" 1312b8d22d11Stb "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" 1313b8d22d11Stb "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" 1314b8d22d11Stb "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" 1315b8d22d11Stb "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000FFFFFFFF0000000000" 1316b8d22d11Stb "0000000000000000000000000000000000000000000000000000000000000000" 1317b8d22d11Stb "0000000000000000000000000000000000000000000000000000000000000000" 1318b8d22d11Stb "0000000000000000000000000000000000000000000000000000000000000000" 1319b8d22d11Stb "0000000000000000000000000000000000000000000000000000000000000000" 1320b8d22d11Stb "0000000000000000000000000000000000000000000000000000000000000000" 1321b8d22d11Stb "0000000000000000000000000000000000000000000000000000000000000000" 1322b8d22d11Stb "0000000000000000000000000000000000000000000000000000000000000000" 1323b8d22d11Stb "000000000000000000000000000000000000000000FFFFFFFFFFFFFF00000000"); 1324b8d22d11Stb CHECK_GOTO(len); 132580ef34bcStb CHECK_GOTO(bn_copy(b, a)); 1326b8d22d11Stb CHECK_GOTO(BN_MONT_CTX_set(mont, n, ctx)); 1327b8d22d11Stb CHECK_GOTO(BN_mod_mul_montgomery(c, a, a, mont, ctx)); 1328b8d22d11Stb CHECK_GOTO(BN_mod_mul_montgomery(d, a, b, mont, ctx)); 1329b8d22d11Stb if (BN_cmp(c, d)) { 1330b8d22d11Stb fprintf(stderr, "Montgomery multiplication test failed:" 1331b8d22d11Stb " a**2 != a*a.\n"); 1332b8d22d11Stb goto err; 1333b8d22d11Stb } 1334b8d22d11Stb /* Zero input */ 1335b8d22d11Stb CHECK_GOTO(BN_bntest_rand(p, 1024, 0, 0)); 133630ad135cStb BN_zero(a); 1337457e5092Stb if (!BN_mod_exp_mont_consttime(d, a, p, m, ctx, NULL)) 1338b8d22d11Stb goto err; 1339b8d22d11Stb if (!BN_is_zero(d)) { 1340b8d22d11Stb fprintf(stderr, "Modular exponentiation test failed!\n"); 1341b8d22d11Stb goto err; 1342b8d22d11Stb } 1343b8d22d11Stb /* 1344b8d22d11Stb * Craft an input whose Montgomery representation is 1, i.e., shorter 1345b8d22d11Stb * than the modulus m, in order to test the const time precomputation 1346b8d22d11Stb * scattering/gathering. 1347b8d22d11Stb */ 1348b8d22d11Stb CHECK_GOTO(BN_one(a)); 1349b8d22d11Stb CHECK_GOTO(BN_MONT_CTX_set(mont, m, ctx)); 1350457e5092Stb if (!BN_from_montgomery(e, a, mont, ctx)) 1351b8d22d11Stb goto err; 1352457e5092Stb if (!BN_mod_exp_mont_consttime(d, e, p, m, ctx, NULL)) 1353b8d22d11Stb goto err; 1354457e5092Stb if (!BN_mod_exp_simple(a, e, p, m, ctx)) 1355b8d22d11Stb goto err; 1356b8d22d11Stb if (BN_cmp(a, d) != 0) { 1357b8d22d11Stb fprintf(stderr, "Modular exponentiation test failed!\n"); 1358b8d22d11Stb goto err; 1359b8d22d11Stb } 1360b8d22d11Stb /* Finally, some regular test vectors. */ 1361b8d22d11Stb CHECK_GOTO(BN_bntest_rand(e, 1024, 0, 0)); 1362457e5092Stb if (!BN_mod_exp_mont_consttime(d, e, p, m, ctx, NULL)) 1363b8d22d11Stb goto err; 1364457e5092Stb if (!BN_mod_exp_simple(a, e, p, m, ctx)) 1365b8d22d11Stb goto err; 1366b8d22d11Stb if (BN_cmp(a, d) != 0) { 1367b8d22d11Stb fprintf(stderr, "Modular exponentiation test failed!\n"); 1368b8d22d11Stb goto err; 1369b8d22d11Stb } 13702e7cce5eStb 1371f7264475Stb ret = 1; 1372b8d22d11Stb err: 13730edabd22Stb BN_CTX_end(ctx); 1374b8d22d11Stb BN_MONT_CTX_free(mont); 13752e7cce5eStb 1376f7264475Stb return ret; 1377b8d22d11Stb } 1378b8d22d11Stb 1379b8d22d11Stb int 1380b8d22d11Stb test_exp(BIO *bp, BN_CTX *ctx) 1381b8d22d11Stb { 13820edabd22Stb BIGNUM *a, *b, *d, *e; 1383b8d22d11Stb int i; 1384f7264475Stb int ret = 0; 1385b8d22d11Stb 13860edabd22Stb BN_CTX_start(ctx); 13870edabd22Stb 13880edabd22Stb if ((a = BN_CTX_get(ctx)) == NULL) 1389b8d22d11Stb goto err; 13900edabd22Stb if ((b = BN_CTX_get(ctx)) == NULL) 1391b8d22d11Stb goto err; 13920edabd22Stb if ((d = BN_CTX_get(ctx)) == NULL) 1393b8d22d11Stb goto err; 13940edabd22Stb if ((e = BN_CTX_get(ctx)) == NULL) 1395b8d22d11Stb goto err; 1396b8d22d11Stb 1397b8d22d11Stb for (i = 0; i < num2; i++) { 1398b8d22d11Stb CHECK_GOTO(BN_bntest_rand(a, 20 + i * 5, 0, 0)); 1399b8d22d11Stb CHECK_GOTO(BN_bntest_rand(b, 2 + i, 0, 0)); 1400b8d22d11Stb 1401457e5092Stb if (BN_exp(d, a, b, ctx) <= 0) 14022e7cce5eStb goto err; 1403b8d22d11Stb 1404b8d22d11Stb if (bp != NULL) { 1405b8d22d11Stb if (!results) { 1406b8d22d11Stb CHECK_GOTO(BN_print(bp, a)); 1407b8d22d11Stb BIO_puts(bp, " ^ "); 1408b8d22d11Stb CHECK_GOTO(BN_print(bp, b)); 1409b8d22d11Stb BIO_puts(bp, " - "); 1410b8d22d11Stb } 1411b8d22d11Stb CHECK_GOTO(BN_print(bp, d)); 1412b8d22d11Stb BIO_puts(bp, "\n"); 1413b8d22d11Stb } 1414b8d22d11Stb CHECK_GOTO(BN_one(e)); 14150edabd22Stb for (; !BN_is_zero(b); BN_sub_word(b, 1)) 1416b8d22d11Stb CHECK_GOTO(BN_mul(e, e, a, ctx)); 1417b8d22d11Stb CHECK_GOTO(BN_sub(e, e, d)); 1418b8d22d11Stb if (!BN_is_zero(e)) { 1419b8d22d11Stb fprintf(stderr, "Exponentiation test failed!\n"); 14202e7cce5eStb goto err; 1421b8d22d11Stb } 1422b8d22d11Stb } 14232e7cce5eStb 1424f7264475Stb ret = 1; 1425b8d22d11Stb err: 14260edabd22Stb BN_CTX_end(ctx); 14272e7cce5eStb 1428f7264475Stb return ret; 1429b8d22d11Stb } 1430b8d22d11Stb 1431b8d22d11Stb static int 1432b8d22d11Stb genprime_cb(int p, int n, BN_GENCB *arg) 1433b8d22d11Stb { 1434b8d22d11Stb char c = '*'; 1435b8d22d11Stb 1436b8d22d11Stb if (p == 0) 1437b8d22d11Stb c = '.'; 1438b8d22d11Stb if (p == 1) 1439b8d22d11Stb c = '+'; 1440b8d22d11Stb if (p == 2) 1441b8d22d11Stb c = '*'; 1442b8d22d11Stb if (p == 3) 1443b8d22d11Stb c = '\n'; 1444b8d22d11Stb putc(c, stderr); 14452e7cce5eStb return 1; 1446b8d22d11Stb } 1447b8d22d11Stb 1448b8d22d11Stb int 1449b8d22d11Stb test_kron(BIO *bp, BN_CTX *ctx) 1450b8d22d11Stb { 14510edabd22Stb BIGNUM *a, *b, *r, *t; 1452b8d22d11Stb BN_GENCB *cb = NULL; 1453b8d22d11Stb int i; 1454b8d22d11Stb int legendre, kronecker; 1455f7264475Stb int ret = 0; 1456b8d22d11Stb 14570edabd22Stb BN_CTX_start(ctx); 14580edabd22Stb 14590edabd22Stb if ((a = BN_CTX_get(ctx)) == NULL) 1460b8d22d11Stb goto err; 14610edabd22Stb if ((b = BN_CTX_get(ctx)) == NULL) 1462b8d22d11Stb goto err; 14630edabd22Stb if ((r = BN_CTX_get(ctx)) == NULL) 1464b8d22d11Stb goto err; 14650edabd22Stb if ((t = BN_CTX_get(ctx)) == NULL) 1466b8d22d11Stb goto err; 1467b8d22d11Stb 1468b8d22d11Stb if ((cb = BN_GENCB_new()) == NULL) 1469b8d22d11Stb goto err; 1470b8d22d11Stb 1471b8d22d11Stb BN_GENCB_set(cb, genprime_cb, NULL); 1472b8d22d11Stb 1473b8d22d11Stb /* 1474b8d22d11Stb * We test BN_kronecker(a, b, ctx) just for b odd (Jacobi symbol). In 1475b8d22d11Stb * this case we know that if b is prime, then BN_kronecker(a, b, ctx) is 1476b8d22d11Stb * congruent to $a^{(b-1)/2}$, modulo $b$ (Legendre symbol). So we 1477b8d22d11Stb * generate a random prime b and compare these values for a number of 1478b8d22d11Stb * random a's. (That is, we run the Solovay-Strassen primality test to 1479b8d22d11Stb * confirm that b is prime, except that we don't want to test whether b 1480b8d22d11Stb * is prime but whether BN_kronecker works.) 1481b8d22d11Stb */ 1482b8d22d11Stb 1483b8d22d11Stb if (!BN_generate_prime_ex(b, 512, 0, NULL, NULL, cb)) 1484b8d22d11Stb goto err; 1485b8d22d11Stb BN_set_negative(b, rand_neg()); 1486b8d22d11Stb putc('\n', stderr); 1487b8d22d11Stb 1488b8d22d11Stb for (i = 0; i < num0; i++) { 1489b8d22d11Stb if (!BN_bntest_rand(a, 512, 0, 0)) 1490b8d22d11Stb goto err; 1491b8d22d11Stb BN_set_negative(a, rand_neg()); 1492b8d22d11Stb 1493b8d22d11Stb /* t := (|b|-1)/2 (note that b is odd) */ 14948e84e241Stb if (!bn_copy(t, b)) 1495b8d22d11Stb goto err; 1496b8d22d11Stb BN_set_negative(t, 0); 1497b8d22d11Stb if (!BN_sub_word(t, 1)) 1498b8d22d11Stb goto err; 1499b8d22d11Stb if (!BN_rshift1(t, t)) 1500b8d22d11Stb goto err; 1501b8d22d11Stb /* r := a^t mod b */ 1502b8d22d11Stb BN_set_negative(b, 0); 1503b8d22d11Stb 1504b8d22d11Stb if (!BN_mod_exp_recp(r, a, t, b, ctx)) 1505b8d22d11Stb goto err; 1506b8d22d11Stb BN_set_negative(b, 1); 1507b8d22d11Stb 1508b8d22d11Stb if (BN_is_word(r, 1)) 1509b8d22d11Stb legendre = 1; 1510b8d22d11Stb else if (BN_is_zero(r)) 1511b8d22d11Stb legendre = 0; 1512b8d22d11Stb else { 1513b8d22d11Stb if (!BN_add_word(r, 1)) 1514b8d22d11Stb goto err; 1515b8d22d11Stb if (0 != BN_ucmp(r, b)) { 1516b8d22d11Stb fprintf(stderr, "Legendre symbol computation failed\n"); 1517b8d22d11Stb goto err; 1518b8d22d11Stb } 1519b8d22d11Stb legendre = -1; 1520b8d22d11Stb } 1521b8d22d11Stb 1522b8d22d11Stb kronecker = BN_kronecker(a, b, ctx); 1523b8d22d11Stb if (kronecker < -1) 1524b8d22d11Stb goto err; 1525b8d22d11Stb /* we actually need BN_kronecker(a, |b|) */ 1526b8d22d11Stb if (BN_is_negative(a) && BN_is_negative(b)) 1527b8d22d11Stb kronecker = -kronecker; 1528b8d22d11Stb 1529b8d22d11Stb if (legendre != kronecker) { 1530b8d22d11Stb fprintf(stderr, "legendre != kronecker; a = "); 1531b8d22d11Stb CHECK_GOTO(BN_print_fp(stderr, a)); 1532b8d22d11Stb fprintf(stderr, ", b = "); 1533b8d22d11Stb CHECK_GOTO(BN_print_fp(stderr, b)); 1534b8d22d11Stb fprintf(stderr, "\n"); 1535b8d22d11Stb goto err; 1536b8d22d11Stb } 1537b8d22d11Stb 1538b8d22d11Stb putc('.', stderr); 1539b8d22d11Stb } 1540b8d22d11Stb 1541b8d22d11Stb putc('\n', stderr); 1542b8d22d11Stb 1543f7264475Stb ret = 1; 1544b8d22d11Stb err: 1545b8d22d11Stb BN_GENCB_free(cb); 15460edabd22Stb BN_CTX_end(ctx); 15472e7cce5eStb 1548f7264475Stb return ret; 1549b8d22d11Stb } 1550b8d22d11Stb 1551b8d22d11Stb int 1552b8d22d11Stb test_sqrt(BIO *bp, BN_CTX *ctx) 1553b8d22d11Stb { 15540edabd22Stb BIGNUM *a, *p, *r; 1555b8d22d11Stb BN_GENCB *cb = NULL; 1556b8d22d11Stb int i, j; 1557f7264475Stb int ret = 0; 1558b8d22d11Stb 15590edabd22Stb BN_CTX_start(ctx); 15600edabd22Stb 15610edabd22Stb if ((a = BN_CTX_get(ctx)) == NULL) 1562b8d22d11Stb goto err; 15630edabd22Stb if ((p = BN_CTX_get(ctx)) == NULL) 1564b8d22d11Stb goto err; 15650edabd22Stb if ((r = BN_CTX_get(ctx)) == NULL) 1566b8d22d11Stb goto err; 1567b8d22d11Stb 1568b8d22d11Stb if ((cb = BN_GENCB_new()) == NULL) 1569b8d22d11Stb goto err; 1570b8d22d11Stb 1571b8d22d11Stb BN_GENCB_set(cb, genprime_cb, NULL); 1572b8d22d11Stb 1573b8d22d11Stb for (i = 0; i < 16; i++) { 1574b8d22d11Stb if (i < 8) { 1575b8d22d11Stb unsigned primes[8] = { 2, 3, 5, 7, 11, 13, 17, 19 }; 1576b8d22d11Stb 1577b8d22d11Stb if (!BN_set_word(p, primes[i])) 1578b8d22d11Stb goto err; 1579b8d22d11Stb } else { 1580b8d22d11Stb if (!BN_set_word(a, 32)) 1581b8d22d11Stb goto err; 1582b8d22d11Stb if (!BN_set_word(r, 2 * i + 1)) 1583b8d22d11Stb goto err; 1584b8d22d11Stb 1585b8d22d11Stb if (!BN_generate_prime_ex(p, 256, 0, a, r, cb)) 1586b8d22d11Stb goto err; 1587b8d22d11Stb putc('\n', stderr); 1588b8d22d11Stb } 1589b8d22d11Stb BN_set_negative(p, rand_neg()); 1590b8d22d11Stb 1591b8d22d11Stb for (j = 0; j < num2; j++) { 1592b8d22d11Stb /* 1593b8d22d11Stb * construct 'a' such that it is a square modulo p, but in 1594b8d22d11Stb * general not a proper square and not reduced modulo p 1595b8d22d11Stb */ 1596b8d22d11Stb if (!BN_bntest_rand(r, 256, 0, 3)) 1597b8d22d11Stb goto err; 1598b8d22d11Stb if (!BN_nnmod(r, r, p, ctx)) 1599b8d22d11Stb goto err; 1600b8d22d11Stb if (!BN_mod_sqr(r, r, p, ctx)) 1601b8d22d11Stb goto err; 1602b8d22d11Stb if (!BN_bntest_rand(a, 256, 0, 3)) 1603b8d22d11Stb goto err; 1604b8d22d11Stb if (!BN_nnmod(a, a, p, ctx)) 1605b8d22d11Stb goto err; 1606b8d22d11Stb if (!BN_mod_sqr(a, a, p, ctx)) 1607b8d22d11Stb goto err; 1608b8d22d11Stb if (!BN_mul(a, a, r, ctx)) 1609b8d22d11Stb goto err; 1610b8d22d11Stb if (rand_neg()) 1611b8d22d11Stb if (!BN_sub(a, a, p)) 1612b8d22d11Stb goto err; 1613b8d22d11Stb 1614b8d22d11Stb if (!BN_mod_sqrt(r, a, p, ctx)) 1615b8d22d11Stb goto err; 1616b8d22d11Stb if (!BN_mod_sqr(r, r, p, ctx)) 1617b8d22d11Stb goto err; 1618b8d22d11Stb 1619b8d22d11Stb if (!BN_nnmod(a, a, p, ctx)) 1620b8d22d11Stb goto err; 1621b8d22d11Stb 1622b8d22d11Stb if (BN_cmp(a, r) != 0) { 1623b8d22d11Stb fprintf(stderr, "BN_mod_sqrt failed: a = "); 1624b8d22d11Stb CHECK_GOTO(BN_print_fp(stderr, a)); 1625b8d22d11Stb fprintf(stderr, ", r = "); 1626b8d22d11Stb CHECK_GOTO(BN_print_fp(stderr, r)); 1627b8d22d11Stb fprintf(stderr, ", p = "); 1628b8d22d11Stb CHECK_GOTO(BN_print_fp(stderr, p)); 1629b8d22d11Stb fprintf(stderr, "\n"); 1630b8d22d11Stb goto err; 1631b8d22d11Stb } 1632b8d22d11Stb 1633b8d22d11Stb putc('.', stderr); 1634b8d22d11Stb } 1635b8d22d11Stb 1636b8d22d11Stb putc('\n', stderr); 1637b8d22d11Stb } 1638b8d22d11Stb 1639f7264475Stb ret = 1; 1640b8d22d11Stb err: 1641b8d22d11Stb BN_GENCB_free(cb); 16420edabd22Stb BN_CTX_end(ctx); 16432e7cce5eStb 1644f7264475Stb return ret; 1645b8d22d11Stb } 1646b8d22d11Stb 1647b8d22d11Stb int 16484bbad1a5Stb test_lshift(BIO *bp, BN_CTX *ctx, int use_lst) 1649b8d22d11Stb { 16500edabd22Stb BIGNUM *a, *b, *c, *d; 1651b8d22d11Stb int i; 1652f7264475Stb int ret = 0; 1653b8d22d11Stb 16540edabd22Stb BN_CTX_start(ctx); 16550edabd22Stb 16560edabd22Stb if ((a = BN_CTX_get(ctx)) == NULL) 16574bbad1a5Stb goto err; 16580edabd22Stb if ((b = BN_CTX_get(ctx)) == NULL) 1659b8d22d11Stb goto err; 16600edabd22Stb if ((c = BN_CTX_get(ctx)) == NULL) 1661b8d22d11Stb goto err; 16620edabd22Stb if ((d = BN_CTX_get(ctx)) == NULL) 1663b8d22d11Stb goto err; 1664b8d22d11Stb CHECK_GOTO(BN_one(c)); 1665b8d22d11Stb 16664bbad1a5Stb if (use_lst) { 16674bbad1a5Stb if (!BN_hex2bn(&a, "C64F43042AEACA6E5836805BE8C99B04" 16684bbad1a5Stb "5D4836C2FD16C964F0")) 1669b8d22d11Stb goto err; 16704bbad1a5Stb } else { 1671b8d22d11Stb CHECK_GOTO(BN_bntest_rand(a, 200, 0, 0)); 1672b8d22d11Stb BN_set_negative(a, rand_neg()); 1673b8d22d11Stb } 1674b8d22d11Stb for (i = 0; i < num0; i++) { 1675b8d22d11Stb CHECK_GOTO(BN_lshift(b, a, i + 1)); 1676b8d22d11Stb CHECK_GOTO(BN_add(c, c, c)); 1677b8d22d11Stb if (bp != NULL) { 1678b8d22d11Stb if (!results) { 1679b8d22d11Stb CHECK_GOTO(BN_print(bp, a)); 1680b8d22d11Stb BIO_puts(bp, " * "); 1681b8d22d11Stb CHECK_GOTO(BN_print(bp, c)); 1682b8d22d11Stb BIO_puts(bp, " - "); 1683b8d22d11Stb } 1684b8d22d11Stb CHECK_GOTO(BN_print(bp, b)); 1685b8d22d11Stb BIO_puts(bp, "\n"); 1686b8d22d11Stb } 1687b8d22d11Stb CHECK_GOTO(BN_mul(d, a, c, ctx)); 1688b8d22d11Stb CHECK_GOTO(BN_sub(d, d, b)); 1689b8d22d11Stb if (!BN_is_zero(d)) { 1690b8d22d11Stb fprintf(stderr, "Left shift test failed!\n"); 1691b8d22d11Stb fprintf(stderr, "a="); 1692b8d22d11Stb CHECK_GOTO(BN_print_fp(stderr, a)); 1693b8d22d11Stb fprintf(stderr, "\nb="); 1694b8d22d11Stb CHECK_GOTO(BN_print_fp(stderr, b)); 1695b8d22d11Stb fprintf(stderr, "\nc="); 1696b8d22d11Stb CHECK_GOTO(BN_print_fp(stderr, c)); 1697b8d22d11Stb fprintf(stderr, "\nd="); 1698b8d22d11Stb CHECK_GOTO(BN_print_fp(stderr, d)); 1699b8d22d11Stb fprintf(stderr, "\n"); 17002e7cce5eStb goto err; 1701b8d22d11Stb } 1702b8d22d11Stb } 17032e7cce5eStb 1704f7264475Stb ret = 1; 1705b8d22d11Stb err: 17060edabd22Stb BN_CTX_end(ctx); 17072e7cce5eStb 1708f7264475Stb return ret; 1709b8d22d11Stb } 1710b8d22d11Stb 1711b8d22d11Stb int 17120edabd22Stb test_lshift1(BIO *bp, BN_CTX *ctx) 1713b8d22d11Stb { 17140edabd22Stb BIGNUM *a, *b, *c; 1715b8d22d11Stb int i; 1716f7264475Stb int ret = 0; 1717b8d22d11Stb 17180edabd22Stb BN_CTX_start(ctx); 17190edabd22Stb 17200edabd22Stb if ((a = BN_CTX_get(ctx)) == NULL) 1721b8d22d11Stb goto err; 17220edabd22Stb if ((b = BN_CTX_get(ctx)) == NULL) 1723b8d22d11Stb goto err; 17240edabd22Stb if ((c = BN_CTX_get(ctx)) == NULL) 1725b8d22d11Stb goto err; 1726b8d22d11Stb 1727b8d22d11Stb CHECK_GOTO(BN_bntest_rand(a, 200, 0, 0)); 1728b8d22d11Stb BN_set_negative(a, rand_neg()); 1729b8d22d11Stb for (i = 0; i < num0; i++) { 1730b8d22d11Stb CHECK_GOTO(BN_lshift1(b, a)); 1731b8d22d11Stb if (bp != NULL) { 1732b8d22d11Stb if (!results) { 1733b8d22d11Stb CHECK_GOTO(BN_print(bp, a)); 1734b8d22d11Stb BIO_puts(bp, " * 2"); 1735b8d22d11Stb BIO_puts(bp, " - "); 1736b8d22d11Stb } 1737b8d22d11Stb CHECK_GOTO(BN_print(bp, b)); 1738b8d22d11Stb BIO_puts(bp, "\n"); 1739b8d22d11Stb } 1740b8d22d11Stb CHECK_GOTO(BN_add(c, a, a)); 1741b8d22d11Stb CHECK_GOTO(BN_sub(a, b, c)); 1742b8d22d11Stb if (!BN_is_zero(a)) { 1743b8d22d11Stb fprintf(stderr, "Left shift one test failed!\n"); 17442e7cce5eStb goto err; 1745b8d22d11Stb } 1746b8d22d11Stb 17478e84e241Stb CHECK_GOTO(bn_copy(a, b)); 1748b8d22d11Stb } 17492e7cce5eStb 1750f7264475Stb ret = 1; 1751b8d22d11Stb err: 17520edabd22Stb BN_CTX_end(ctx); 17532e7cce5eStb 1754f7264475Stb return ret; 1755b8d22d11Stb } 1756b8d22d11Stb 1757b8d22d11Stb int 1758b8d22d11Stb test_rshift(BIO *bp, BN_CTX *ctx) 1759b8d22d11Stb { 17600edabd22Stb BIGNUM *a, *b, *c, *d, *e; 1761b8d22d11Stb int i; 1762f7264475Stb int ret = 0; 1763b8d22d11Stb 17640edabd22Stb BN_CTX_start(ctx); 17650edabd22Stb 17660edabd22Stb if ((a = BN_CTX_get(ctx)) == NULL) 1767b8d22d11Stb goto err; 17680edabd22Stb if ((b = BN_CTX_get(ctx)) == NULL) 1769b8d22d11Stb goto err; 17700edabd22Stb if ((c = BN_CTX_get(ctx)) == NULL) 1771b8d22d11Stb goto err; 17720edabd22Stb if ((d = BN_CTX_get(ctx)) == NULL) 1773b8d22d11Stb goto err; 17740edabd22Stb if ((e = BN_CTX_get(ctx)) == NULL) 1775b8d22d11Stb goto err; 1776b8d22d11Stb CHECK_GOTO(BN_one(c)); 1777b8d22d11Stb 1778b8d22d11Stb CHECK_GOTO(BN_bntest_rand(a, 200, 0, 0)); 1779b8d22d11Stb BN_set_negative(a, rand_neg()); 1780b8d22d11Stb for (i = 0; i < num0; i++) { 1781b8d22d11Stb CHECK_GOTO(BN_rshift(b, a, i + 1)); 1782b8d22d11Stb CHECK_GOTO(BN_add(c, c, c)); 1783b8d22d11Stb if (bp != NULL) { 1784b8d22d11Stb if (!results) { 1785b8d22d11Stb CHECK_GOTO(BN_print(bp, a)); 1786b8d22d11Stb BIO_puts(bp, " / "); 1787b8d22d11Stb CHECK_GOTO(BN_print(bp, c)); 1788b8d22d11Stb BIO_puts(bp, " - "); 1789b8d22d11Stb } 1790b8d22d11Stb CHECK_GOTO(BN_print(bp, b)); 1791b8d22d11Stb BIO_puts(bp, "\n"); 1792b8d22d11Stb } 1793b8d22d11Stb CHECK_GOTO(BN_div(d, e, a, c, ctx)); 1794b8d22d11Stb CHECK_GOTO(BN_sub(d, d, b)); 1795b8d22d11Stb if (!BN_is_zero(d)) { 1796b8d22d11Stb fprintf(stderr, "Right shift test failed!\n"); 17972e7cce5eStb goto err; 1798b8d22d11Stb } 1799b8d22d11Stb } 18002e7cce5eStb 1801f7264475Stb ret = 1; 1802b8d22d11Stb err: 18030edabd22Stb BN_CTX_end(ctx); 18042e7cce5eStb 1805f7264475Stb return ret; 1806b8d22d11Stb } 1807b8d22d11Stb 1808b8d22d11Stb int 18090edabd22Stb test_rshift1(BIO *bp, BN_CTX *ctx) 1810b8d22d11Stb { 18110edabd22Stb BIGNUM *a, *b, *c; 1812b8d22d11Stb int i; 1813f7264475Stb int ret = 0; 1814b8d22d11Stb 18150edabd22Stb BN_CTX_start(ctx); 18160edabd22Stb 18170edabd22Stb if ((a = BN_CTX_get(ctx)) == NULL) 1818b8d22d11Stb goto err; 18190edabd22Stb if ((b = BN_CTX_get(ctx)) == NULL) 1820b8d22d11Stb goto err; 18210edabd22Stb if ((c = BN_CTX_get(ctx)) == NULL) 1822b8d22d11Stb goto err; 1823b8d22d11Stb 1824b8d22d11Stb CHECK_GOTO(BN_bntest_rand(a, 200, 0, 0)); 1825b8d22d11Stb BN_set_negative(a, rand_neg()); 1826b8d22d11Stb for (i = 0; i < num0; i++) { 1827b8d22d11Stb CHECK_GOTO(BN_rshift1(b, a)); 1828b8d22d11Stb if (bp != NULL) { 1829b8d22d11Stb if (!results) { 1830b8d22d11Stb CHECK_GOTO(BN_print(bp, a)); 1831b8d22d11Stb BIO_puts(bp, " / 2"); 1832b8d22d11Stb BIO_puts(bp, " - "); 1833b8d22d11Stb } 1834b8d22d11Stb CHECK_GOTO(BN_print(bp, b)); 1835b8d22d11Stb BIO_puts(bp, "\n"); 1836b8d22d11Stb } 1837b8d22d11Stb CHECK_GOTO(BN_sub(c, a, b)); 1838b8d22d11Stb CHECK_GOTO(BN_sub(c, c, b)); 1839b8d22d11Stb if (!BN_is_zero(c) && !BN_abs_is_word(c, 1)) { 1840b8d22d11Stb fprintf(stderr, "Right shift one test failed!\n"); 18412e7cce5eStb goto err; 1842b8d22d11Stb } 18438e84e241Stb CHECK_GOTO(bn_copy(a, b)); 1844b8d22d11Stb } 18452e7cce5eStb 1846f7264475Stb ret = 1; 1847b8d22d11Stb err: 18480edabd22Stb BN_CTX_end(ctx); 18492e7cce5eStb 1850f7264475Stb return ret; 1851b8d22d11Stb } 1852b8d22d11Stb 1853b8d22d11Stb int 1854b8d22d11Stb rand_neg(void) 1855b8d22d11Stb { 1856b8d22d11Stb static unsigned int neg = 0; 1857b8d22d11Stb static int sign[8] = { 0, 0, 0, 1, 1, 0, 1, 1 }; 1858b8d22d11Stb 18590f386146Stb return sign[neg++ % 8]; 1860b8d22d11Stb } 1861b8d22d11Stb 1862b8d22d11Stb int 1863b8d22d11Stb test_mod_exp_sizes(BIO *bp, BN_CTX *ctx) 1864b8d22d11Stb { 1865b8d22d11Stb BN_MONT_CTX *mont_ctx = NULL; 18660edabd22Stb BIGNUM *p, *x, *y, *r, *r2; 1867b8d22d11Stb int size; 1868f7264475Stb int ret = 0; 1869b8d22d11Stb 1870b8d22d11Stb BN_CTX_start(ctx); 1871b8d22d11Stb CHECK_GOTO(p = BN_CTX_get(ctx)); 1872b8d22d11Stb CHECK_GOTO(x = BN_CTX_get(ctx)); 1873b8d22d11Stb CHECK_GOTO(y = BN_CTX_get(ctx)); 1874b8d22d11Stb CHECK_GOTO(r = BN_CTX_get(ctx)); 1875b8d22d11Stb CHECK_GOTO(r2 = BN_CTX_get(ctx)); 1876b8d22d11Stb mont_ctx = BN_MONT_CTX_new(); 1877b8d22d11Stb 1878b8d22d11Stb if (r2 == NULL || mont_ctx == NULL) 1879b8d22d11Stb goto err; 1880b8d22d11Stb 1881b8d22d11Stb if (!BN_generate_prime_ex(p, 32, 0, NULL, NULL, NULL) || 1882b8d22d11Stb !BN_MONT_CTX_set(mont_ctx, p, ctx)) 1883b8d22d11Stb goto err; 1884b8d22d11Stb 1885b8d22d11Stb for (size = 32; size < 1024; size += 8) { 1886b8d22d11Stb if (!BN_rand(x, size, -1, 0) || 1887b8d22d11Stb !BN_rand(y, size, -1, 0) || 1888b8d22d11Stb !BN_mod_exp_mont_consttime(r, x, y, p, ctx, mont_ctx) || 1889b8d22d11Stb !BN_mod_exp(r2, x, y, p, ctx)) 1890b8d22d11Stb goto err; 1891b8d22d11Stb 1892b8d22d11Stb if (BN_cmp(r, r2) != 0) { 1893b8d22d11Stb char *r_str = NULL; 1894b8d22d11Stb char *r2_str = NULL; 1895b8d22d11Stb CHECK_GOTO(r_str = BN_bn2hex(r)); 1896b8d22d11Stb CHECK_GOTO(r2_str = BN_bn2hex(r2)); 1897b8d22d11Stb 1898b8d22d11Stb printf("Incorrect answer at size %d: %s vs %s\n", 1899b8d22d11Stb size, r_str, r2_str); 1900b8d22d11Stb free(r_str); 1901b8d22d11Stb free(r2_str); 1902b8d22d11Stb goto err; 1903b8d22d11Stb } 1904b8d22d11Stb } 1905b8d22d11Stb 1906f7264475Stb ret = 1; 1907b8d22d11Stb err: 1908b8d22d11Stb BN_CTX_end(ctx); 19090edabd22Stb BN_MONT_CTX_free(mont_ctx); 19102e7cce5eStb 1911f7264475Stb return ret; 1912b8d22d11Stb } 1913