X-Git-Url: https://git.openssl.org/gitweb/?a=blobdiff_plain;f=crypto%2Fbn%2Fbntest.c;h=869ae05a901d51ee69ad4d181337ba1d8c34e7a4;hb=a7a44ba55cb4f884c6bc9ceac90072dea38e66d;hp=7a2f0b8d6d9bbb70ea94b5f8bcd17f8ff63f605f;hpb=b7896b3cb86d80206af14a14d69b0717786f2729;p=openssl.git diff --git a/crypto/bn/bntest.c b/crypto/bn/bntest.c index 7a2f0b8d6d..869ae05a90 100644 --- a/crypto/bn/bntest.c +++ b/crypto/bn/bntest.c @@ -1,5 +1,5 @@ /* crypto/bn/bntest.c */ -/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * * This package is an SSL implementation written @@ -55,67 +55,94 @@ * copied and put under another distribution licence * [including the GNU Public Licence.] */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * + * Portions of the attached software ("Contribution") are developed by + * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. + * + * The Contribution is licensed pursuant to the Eric Young open source + * license provided above. + * + * The binary polynomial arithmetic software is originally written by + * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories. + * + */ #include #include #include -#ifdef WIN16 -#define APPS_WIN16 -#endif -#include "bio.h" -#include "bn.h" -#include "rand.h" -#include "x509.h" -#include "err.h" - -#ifndef NOPROTO -int test_add (BIO *bp); -int test_sub (BIO *bp); -int test_lshift1 (BIO *bp); -int test_lshift (BIO *bp); -int test_rshift1 (BIO *bp); -int test_rshift (BIO *bp); -int test_div (BIO *bp,BN_CTX *ctx); -int test_mul (BIO *bp); -int test_sqr (BIO *bp,BN_CTX *ctx); -int test_mont (BIO *bp,BN_CTX *ctx); -int test_mod (BIO *bp,BN_CTX *ctx); -int test_mod_mul (BIO *bp,BN_CTX *ctx); -int test_mod_exp (BIO *bp,BN_CTX *ctx); -int rand_neg(void); -#else -int test_add (); -int test_sub (); -int test_lshift1 (); -int test_lshift (); -int test_rshift1 (); -int test_rshift (); -int test_div (); -int test_mul (); -int test_sqr (); -int test_mont (); -int test_mod (); -int test_mod_mul (); -int test_mod_exp (); -int rand_neg(); -#endif +#include "e_os.h" + +#include +#include +#include +#include +#include + +#include "../crypto/bn/bn_lcl.h" + +const int num0 = 100; /* number of tests */ +const int num1 = 50; /* additional tests for some functions */ +const int num2 = 5; /* number of tests for slow functions */ + +int test_add(BIO *bp); +int test_sub(BIO *bp); +int test_lshift1(BIO *bp); +int test_lshift(BIO *bp,BN_CTX *ctx,BIGNUM *a_); +int test_rshift1(BIO *bp); +int test_rshift(BIO *bp,BN_CTX *ctx); +int test_div(BIO *bp,BN_CTX *ctx); +int test_div_word(BIO *bp); +int test_div_recp(BIO *bp,BN_CTX *ctx); +int test_mul(BIO *bp); +int test_sqr(BIO *bp,BN_CTX *ctx); +int test_mont(BIO *bp,BN_CTX *ctx); +int test_mod(BIO *bp,BN_CTX *ctx); +int test_mod_mul(BIO *bp,BN_CTX *ctx); +int test_mod_exp(BIO *bp,BN_CTX *ctx); +int test_mod_exp_mont_consttime(BIO *bp,BN_CTX *ctx); +int test_mod_exp_mont5(BIO *bp, BN_CTX *ctx); +int test_exp(BIO *bp,BN_CTX *ctx); +int test_gf2m_add(BIO *bp); +int test_gf2m_mod(BIO *bp); +int test_gf2m_mod_mul(BIO *bp,BN_CTX *ctx); +int test_gf2m_mod_sqr(BIO *bp,BN_CTX *ctx); +int test_gf2m_mod_inv(BIO *bp,BN_CTX *ctx); +int test_gf2m_mod_div(BIO *bp,BN_CTX *ctx); +int test_gf2m_mod_exp(BIO *bp,BN_CTX *ctx); +int test_gf2m_mod_sqrt(BIO *bp,BN_CTX *ctx); +int test_gf2m_mod_solve_quad(BIO *bp,BN_CTX *ctx); +int test_kron(BIO *bp,BN_CTX *ctx); +int test_sqrt(BIO *bp,BN_CTX *ctx); +int test_small_prime(BIO *bp,BN_CTX *ctx); +int test_probable_prime_coprime(BIO *bp,BN_CTX *ctx); +int rand_neg(void); static int results=0; -#ifdef WIN16 -#define APPS_WIN16 -#include "../bio/bss_file.c" -#endif +static unsigned char lst[]="\xC6\x4F\x43\x04\x2A\xEA\xCA\x6E\x58\x36\x80\x5B\xE8\xC9" +"\x9B\x04\x5D\x48\x36\xC2\xFD\x16\xC9\x64\xF0"; + +static const char rnd_seed[] = "string to make the random number generator think it has entropy"; -int main(argc,argv) -int argc; -char *argv[]; +static void message(BIO *out, char *m) + { + fprintf(stderr, "test %s\n", m); + BIO_puts(out, "print \"test "); + BIO_puts(out, m); + BIO_puts(out, "\\n\"\n"); + } + +int main(int argc, char *argv[]) { BN_CTX *ctx; BIO *out; char *outfile=NULL; - srand((unsigned int)time(NULL)); + results = 0; + + RAND_seed(rnd_seed, sizeof rnd_seed); /* or BN_generate_prime may fail */ argc--; argv++; @@ -134,10 +161,10 @@ char *argv[]; ctx=BN_CTX_new(); - if (ctx == NULL) exit(1); + if (ctx == NULL) EXIT(1); out=BIO_new(BIO_s_file()); - if (out == NULL) exit(1); + if (out == NULL) EXIT(1); if (outfile == NULL) { BIO_set_fp(out,stdout,BIO_NOCLOSE); @@ -147,266 +174,537 @@ char *argv[]; if (!BIO_write_filename(out,outfile)) { perror(outfile); - exit(1); + EXIT(1); } } if (!results) BIO_puts(out,"obase=16\nibase=16\n"); - fprintf(stderr,"test BN_add\n"); + message(out,"BN_add"); if (!test_add(out)) goto err; - fflush(stdout); + (void)BIO_flush(out); - fprintf(stderr,"test BN_sub\n"); + message(out,"BN_sub"); if (!test_sub(out)) goto err; - fflush(stdout); + (void)BIO_flush(out); - fprintf(stderr,"test BN_lshift1\n"); + message(out,"BN_lshift1"); if (!test_lshift1(out)) goto err; - fflush(stdout); + (void)BIO_flush(out); - fprintf(stderr,"test BN_lshift\n"); - if (!test_lshift(out)) goto err; - fflush(stdout); + message(out,"BN_lshift (fixed)"); + if (!test_lshift(out,ctx,BN_bin2bn(lst,sizeof(lst)-1,NULL))) + goto err; + (void)BIO_flush(out); - fprintf(stderr,"test BN_rshift1\n"); + message(out,"BN_lshift"); + if (!test_lshift(out,ctx,NULL)) goto err; + (void)BIO_flush(out); + + message(out,"BN_rshift1"); if (!test_rshift1(out)) goto err; - fflush(stdout); + (void)BIO_flush(out); + + message(out,"BN_rshift"); + if (!test_rshift(out,ctx)) goto err; + (void)BIO_flush(out); + + message(out,"BN_sqr"); + if (!test_sqr(out,ctx)) goto err; + (void)BIO_flush(out); - fprintf(stderr,"test BN_rshift\n"); - if (!test_rshift(out)) goto err; - fflush(stdout); + message(out,"BN_mul"); + if (!test_mul(out)) goto err; + (void)BIO_flush(out); - fprintf(stderr,"test BN_div\n"); + message(out,"BN_div"); if (!test_div(out,ctx)) goto err; - fflush(stdout); + (void)BIO_flush(out); - fprintf(stderr,"test BN_mod\n"); - if (!test_mod(out,ctx)) goto err; - fflush(stdout); + message(out,"BN_div_word"); + if (!test_div_word(out)) goto err; + (void)BIO_flush(out); - fprintf(stderr,"test BN_mul\n"); - if (!test_mul(out)) goto err; - fflush(stdout); + message(out,"BN_div_recp"); + if (!test_div_recp(out,ctx)) goto err; + (void)BIO_flush(out); - fprintf(stderr,"test BN_sqr\n"); - if (!test_sqr(out,ctx)) goto err; - fflush(stdout); + message(out,"BN_mod"); + if (!test_mod(out,ctx)) goto err; + (void)BIO_flush(out); - fprintf(stderr,"test BN_mod_mul\n"); + message(out,"BN_mod_mul"); if (!test_mod_mul(out,ctx)) goto err; - fflush(stdout); + (void)BIO_flush(out); -/* - fprintf(stderr,"test BN_mont\n"); + message(out,"BN_mont"); if (!test_mont(out,ctx)) goto err; - fflush(stdout); -*/ - fprintf(stderr,"test BN_mod_exp\n"); + (void)BIO_flush(out); + + message(out,"BN_mod_exp"); if (!test_mod_exp(out,ctx)) goto err; - fflush(stdout); + (void)BIO_flush(out); + + message(out,"BN_mod_exp_mont_consttime"); + if (!test_mod_exp_mont_consttime(out,ctx)) goto err; + if (!test_mod_exp_mont5(out,ctx)) goto err; + (void)BIO_flush(out); + + message(out,"BN_exp"); + if (!test_exp(out,ctx)) goto err; + (void)BIO_flush(out); + + message(out,"BN_kronecker"); + if (!test_kron(out,ctx)) goto err; + (void)BIO_flush(out); + + message(out,"BN_mod_sqrt"); + if (!test_sqrt(out,ctx)) goto err; + (void)BIO_flush(out); + + message(out,"Small prime generation"); + if (!test_small_prime(out,ctx)) goto err; + (void)BIO_flush(out); + +#ifdef OPENSSL_SYS_WIN32 + message(out,"Probable prime generation with coprimes disabled"); +#else + message(out,"Probable prime generation with coprimes"); + if (!test_probable_prime_coprime(out,ctx)) goto err; +#endif + (void)BIO_flush(out); + +#ifndef OPENSSL_NO_EC2M + message(out,"BN_GF2m_add"); + if (!test_gf2m_add(out)) goto err; + (void)BIO_flush(out); + + message(out,"BN_GF2m_mod"); + if (!test_gf2m_mod(out)) goto err; + (void)BIO_flush(out); + + message(out,"BN_GF2m_mod_mul"); + if (!test_gf2m_mod_mul(out,ctx)) goto err; + (void)BIO_flush(out); + + message(out,"BN_GF2m_mod_sqr"); + if (!test_gf2m_mod_sqr(out,ctx)) goto err; + (void)BIO_flush(out); + + message(out,"BN_GF2m_mod_inv"); + if (!test_gf2m_mod_inv(out,ctx)) goto err; + (void)BIO_flush(out); + + message(out,"BN_GF2m_mod_div"); + if (!test_gf2m_mod_div(out,ctx)) goto err; + (void)BIO_flush(out); + + message(out,"BN_GF2m_mod_exp"); + if (!test_gf2m_mod_exp(out,ctx)) goto err; + (void)BIO_flush(out); + + message(out,"BN_GF2m_mod_sqrt"); + if (!test_gf2m_mod_sqrt(out,ctx)) goto err; + (void)BIO_flush(out); + + message(out,"BN_GF2m_mod_solve_quad"); + if (!test_gf2m_mod_solve_quad(out,ctx)) goto err; + (void)BIO_flush(out); +#endif + BN_CTX_free(ctx); + BIO_free(out); /**/ - exit(0); + EXIT(0); err: + BIO_puts(out,"1\n"); /* make sure the Perl script fed by bc notices + * the failure, see test_bn in test/Makefile.ssl*/ + (void)BIO_flush(out); ERR_load_crypto_strings(); - ERR_print_errors(out); - exit(1); + ERR_print_errors_fp(stderr); + EXIT(1); return(1); } -int test_add(bp) -BIO *bp; +int test_add(BIO *bp) { - BIGNUM *a,*b,*c; + BIGNUM a,b,c; int i; - int j; - a=BN_new(); - b=BN_new(); - c=BN_new(); + BN_init(&a); + BN_init(&b); + BN_init(&c); - BN_rand(a,512,0,0); - for (i=0; i<100; i++) + BN_bntest_rand(&a,512,0,0); + for (i=0; ineg=rand_neg(); - b->neg=rand_neg(); - if (bp == NULL) - for (j=0; j<10000; j++) - BN_add(c,a,b); - BN_add(c,a,b); + BN_bntest_rand(&b,450+i,0,0); + a.neg=rand_neg(); + b.neg=rand_neg(); + BN_add(&c,&a,&b); if (bp != NULL) { if (!results) { - BN_print(bp,a); + BN_print(bp,&a); BIO_puts(bp," + "); - BN_print(bp,b); + BN_print(bp,&b); BIO_puts(bp," - "); } - BN_print(bp,c); + BN_print(bp,&c); BIO_puts(bp,"\n"); } + a.neg=!a.neg; + b.neg=!b.neg; + BN_add(&c,&c,&b); + BN_add(&c,&c,&a); + if(!BN_is_zero(&c)) + { + fprintf(stderr,"Add test failed!\n"); + return 0; + } } - BN_free(a); - BN_free(b); - BN_free(c); + BN_free(&a); + BN_free(&b); + BN_free(&c); return(1); } -int test_sub(bp) -BIO *bp; +int test_sub(BIO *bp) { - BIGNUM *a,*b,*c; + BIGNUM a,b,c; int i; - int j; - a=BN_new(); - b=BN_new(); - c=BN_new(); + BN_init(&a); + BN_init(&b); + BN_init(&c); - BN_rand(a,512,0,0); - for (i=0; i<100; i++) + for (i=0; ineg=rand_neg(); - b->neg=rand_neg(); - if (bp == NULL) - for (j=0; j<10000; j++) - BN_sub(c,a,b); - BN_sub(c,a,b); + if (i < num1) + { + BN_bntest_rand(&a,512,0,0); + BN_copy(&b,&a); + if (BN_set_bit(&a,i)==0) return(0); + BN_add_word(&b,i); + } + else + { + BN_bntest_rand(&b,400+i-num1,0,0); + a.neg=rand_neg(); + b.neg=rand_neg(); + } + BN_sub(&c,&a,&b); if (bp != NULL) { if (!results) { - BN_print(bp,a); + BN_print(bp,&a); BIO_puts(bp," - "); - BN_print(bp,b); + BN_print(bp,&b); BIO_puts(bp," - "); } - BN_print(bp,c); + BN_print(bp,&c); BIO_puts(bp,"\n"); } + BN_add(&c,&c,&b); + BN_sub(&c,&c,&a); + if(!BN_is_zero(&c)) + { + fprintf(stderr,"Subtract test failed!\n"); + return 0; + } } - BN_free(a); - BN_free(b); - BN_free(c); + BN_free(&a); + BN_free(&b); + BN_free(&c); return(1); } -int test_div(bp,ctx) -BIO *bp; -BN_CTX *ctx; +int test_div(BIO *bp, BN_CTX *ctx) { - BIGNUM *a,*b,*c,*d; + BIGNUM a,b,c,d,e; int i; - int j; - a=BN_new(); - b=BN_new(); - c=BN_new(); - d=BN_new(); + BN_init(&a); + BN_init(&b); + BN_init(&c); + BN_init(&d); + BN_init(&e); - BN_rand(a,400,0,0); - for (i=0; i<100; i++) + for (i=0; ineg=rand_neg(); - b->neg=rand_neg(); - if (bp == NULL) - for (j=0; j<100; j++) - BN_div(d,c,a,b,ctx); - BN_div(d,c,a,b,ctx); + if (i < num1) + { + BN_bntest_rand(&a,400,0,0); + BN_copy(&b,&a); + BN_lshift(&a,&a,i); + BN_add_word(&a,i); + } + else + BN_bntest_rand(&b,50+3*(i-num1),0,0); + a.neg=rand_neg(); + b.neg=rand_neg(); + BN_div(&d,&c,&a,&b,ctx); if (bp != NULL) { if (!results) { - BN_print(bp,a); + BN_print(bp,&a); BIO_puts(bp," / "); - BN_print(bp,b); + BN_print(bp,&b); BIO_puts(bp," - "); } - BN_print(bp,d); + BN_print(bp,&d); BIO_puts(bp,"\n"); if (!results) { - BN_print(bp,a); + BN_print(bp,&a); BIO_puts(bp," % "); - BN_print(bp,b); + BN_print(bp,&b); BIO_puts(bp," - "); } - BN_print(bp,c); + BN_print(bp,&c); BIO_puts(bp,"\n"); } + BN_mul(&e,&d,&b,ctx); + BN_add(&d,&e,&c); + BN_sub(&d,&d,&a); + if(!BN_is_zero(&d)) + { + fprintf(stderr,"Division test failed!\n"); + return 0; + } } - BN_free(a); - BN_free(b); - BN_free(c); - BN_free(d); + BN_free(&a); + BN_free(&b); + BN_free(&c); + BN_free(&d); + BN_free(&e); return(1); } -int test_mul(bp) -BIO *bp; +static void print_word(BIO *bp,BN_ULONG w) { - BIGNUM *a,*b,*c; +#ifdef SIXTY_FOUR_BIT + if (sizeof(w) > sizeof(unsigned long)) + { + unsigned long h=(unsigned long)(w>>32), + l=(unsigned long)(w); + + if (h) BIO_printf(bp,"%lX%08lX",h,l); + else BIO_printf(bp,"%lX",l); + return; + } +#endif + BIO_printf(bp,BN_HEX_FMT1,w); + } + +int test_div_word(BIO *bp) + { + BIGNUM a,b; + BN_ULONG r,s; int i; - int j; - a=BN_new(); - b=BN_new(); - c=BN_new(); + BN_init(&a); + BN_init(&b); - BN_rand(a,200,0,0); - for (i=0; i<100; i++) + for (i=0; ineg=rand_neg(); - b->neg=rand_neg(); - if (bp == NULL) - for (j=0; j<100; j++) - BN_mul(c,a,b); - BN_mul(c,a,b); + do { + BN_bntest_rand(&a,512,-1,0); + BN_bntest_rand(&b,BN_BITS2,-1,0); + s = b.d[0]; + } while (!s); + + BN_copy(&b, &a); + r = BN_div_word(&b, s); + if (bp != NULL) { if (!results) { - BN_print(bp,a); - BIO_puts(bp," * "); - BN_print(bp,b); + BN_print(bp,&a); + BIO_puts(bp," / "); + print_word(bp,s); BIO_puts(bp," - "); } - BN_print(bp,c); + BN_print(bp,&b); + BIO_puts(bp,"\n"); + + if (!results) + { + BN_print(bp,&a); + BIO_puts(bp," % "); + print_word(bp,s); + BIO_puts(bp," - "); + } + print_word(bp,r); BIO_puts(bp,"\n"); } + BN_mul_word(&b,s); + BN_add_word(&b,r); + BN_sub(&b,&a,&b); + if(!BN_is_zero(&b)) + { + fprintf(stderr,"Division (word) test failed!\n"); + return 0; + } } - BN_free(a); - BN_free(b); - BN_free(c); + BN_free(&a); + BN_free(&b); return(1); } -int test_sqr(bp,ctx) -BIO *bp; -BN_CTX *ctx; +int test_div_recp(BIO *bp, BN_CTX *ctx) { - BIGNUM *a,*c; + BIGNUM a,b,c,d,e; + BN_RECP_CTX recp; int i; - int j; - a=BN_new(); - c=BN_new(); + BN_RECP_CTX_init(&recp); + BN_init(&a); + BN_init(&b); + BN_init(&c); + BN_init(&d); + BN_init(&e); + + for (i=0; ineg=rand_neg(); - if (bp == NULL) - for (j=0; j<100; j++) - BN_sqr(c,a,ctx); BN_sqr(c,a,ctx); if (bp != NULL) { @@ -420,95 +718,165 @@ BN_CTX *ctx; BN_print(bp,c); BIO_puts(bp,"\n"); } + BN_div(d,e,c,a,ctx); + BN_sub(d,d,a); + if(!BN_is_zero(d) || !BN_is_zero(e)) + { + fprintf(stderr,"Square test failed!\n"); + goto err; + } } - BN_free(a); - BN_free(c); - return(1); + + /* Regression test for a BN_sqr overflow bug. */ + BN_hex2bn(&a, + "80000000000000008000000000000001FFFFFFFFFFFFFFFE0000000000000000"); + BN_sqr(c, a, ctx); + if (bp != NULL) + { + if (!results) + { + BN_print(bp,a); + BIO_puts(bp," * "); + BN_print(bp,a); + BIO_puts(bp," - "); + } + BN_print(bp,c); + BIO_puts(bp,"\n"); + } + BN_mul(d, a, a, ctx); + if (BN_cmp(c, d)) + { + fprintf(stderr, "Square test failed: BN_sqr and BN_mul produce " + "different results!\n"); + goto err; + } + + /* Regression test for a BN_sqr overflow bug. */ + BN_hex2bn(&a, + "80000000000000000000000080000001FFFFFFFE000000000000000000000000"); + BN_sqr(c, a, ctx); + if (bp != NULL) + { + if (!results) + { + BN_print(bp,a); + BIO_puts(bp," * "); + BN_print(bp,a); + BIO_puts(bp," - "); + } + BN_print(bp,c); + BIO_puts(bp,"\n"); + } + BN_mul(d, a, a, ctx); + if (BN_cmp(c, d)) + { + fprintf(stderr, "Square test failed: BN_sqr and BN_mul produce " + "different results!\n"); + goto err; + } + ret = 1; +err: + if (a != NULL) BN_free(a); + if (c != NULL) BN_free(c); + if (d != NULL) BN_free(d); + if (e != NULL) BN_free(e); + return ret; } -int test_mont(bp,ctx) -BIO *bp; -BN_CTX *ctx; +int test_mont(BIO *bp, BN_CTX *ctx) { - BIGNUM *a,*b,*c,*A,*B; - BIGNUM *n; + BIGNUM a,b,c,d,A,B; + BIGNUM n; int i; - int j; BN_MONT_CTX *mont; - a=BN_new(); - b=BN_new(); - c=BN_new(); - A=BN_new(); - B=BN_new(); - n=BN_new(); + BN_init(&a); + BN_init(&b); + BN_init(&c); + BN_init(&d); + BN_init(&A); + BN_init(&B); + BN_init(&n); mont=BN_MONT_CTX_new(); + if (mont == NULL) + return 0; - BN_rand(a,100,0,0); /**/ - BN_rand(b,100,0,0); /**/ - for (i=0; i<10; i++) + BN_bntest_rand(&a,100,0,0); /**/ + BN_bntest_rand(&b,100,0,0); /**/ + for (i=0; iN)); #endif - BN_print(bp,a); + BN_print(bp,&a); BIO_puts(bp," * "); - BN_print(bp,b); + BN_print(bp,&b); BIO_puts(bp," % "); - BN_print(bp,mont->N); + BN_print(bp,&(mont->N)); BIO_puts(bp," - "); } - BN_print(bp,A); + BN_print(bp,&A); BIO_puts(bp,"\n"); } + BN_mod_mul(&d,&a,&b,&n,ctx); + BN_sub(&d,&d,&A); + if(!BN_is_zero(&d)) + { + fprintf(stderr,"Montgomery multiplication test failed!\n"); + return 0; + } } BN_MONT_CTX_free(mont); - BN_free(a); - BN_free(b); - BN_free(c); + BN_free(&a); + BN_free(&b); + BN_free(&c); + BN_free(&d); + BN_free(&A); + BN_free(&B); + BN_free(&n); return(1); } -int test_mod(bp,ctx) -BIO *bp; -BN_CTX *ctx; +int test_mod(BIO *bp, BN_CTX *ctx) { - BIGNUM *a,*b,*c; + BIGNUM *a,*b,*c,*d,*e; int i; - int j; a=BN_new(); b=BN_new(); c=BN_new(); + d=BN_new(); + e=BN_new(); - BN_rand(a,1024,0,0); /**/ - for (i=0; i<20; i++) + BN_bntest_rand(a,1024,0,0); /**/ + for (i=0; ineg=rand_neg(); b->neg=rand_neg(); - if (bp == NULL) - for (j=0; j<100; j++) - BN_mod(c,a,b,ctx);/**/ BN_mod(c,a,b,ctx);/**/ if (bp != NULL) { @@ -522,19 +890,26 @@ BN_CTX *ctx; BN_print(bp,c); BIO_puts(bp,"\n"); } + BN_div(d,e,a,b,ctx); + BN_sub(e,e,c); + if(!BN_is_zero(e)) + { + fprintf(stderr,"Modulo test failed!\n"); + return 0; + } } BN_free(a); BN_free(b); BN_free(c); + BN_free(d); + BN_free(e); return(1); } -int test_mod_mul(bp,ctx) -BIO *bp; -BN_CTX *ctx; +int test_mod_mul(BIO *bp, BN_CTX *ctx) { BIGNUM *a,*b,*c,*d,*e; - int i; + int i,j; a=BN_new(); b=BN_new(); @@ -542,17 +917,14 @@ BN_CTX *ctx; d=BN_new(); e=BN_new(); - BN_rand(c,1024,0,0); /**/ - for (i=0; i<10; i++) + for (j=0; j<3; j++) { + BN_bntest_rand(c,1024,0,0); /**/ + for (i=0; ineg=rand_neg(); b->neg=rand_neg(); - /* if (bp == NULL) - for (j=0; j<100; j++) - BN_mod_mul(d,a,b,c,ctx);*/ /**/ - if (!BN_mod_mul(e,a,b,c,ctx)) { unsigned long l; @@ -560,7 +932,7 @@ BN_CTX *ctx; while ((l=ERR_get_error())) fprintf(stderr,"ERROR:%s\n", ERR_error_string(l,NULL)); - exit(1); + EXIT(1); } if (bp != NULL) { @@ -571,12 +943,32 @@ BN_CTX *ctx; BN_print(bp,b); BIO_puts(bp," % "); BN_print(bp,c); + if ((a->neg ^ b->neg) && !BN_is_zero(e)) + { + /* If (a*b) % c is negative, c must be added + * in order to obtain the normalized remainder + * (new with OpenSSL 0.9.7, previous versions of + * BN_mod_mul could generate negative results) + */ + BIO_puts(bp," + "); + BN_print(bp,c); + } BIO_puts(bp," - "); } BN_print(bp,e); BIO_puts(bp,"\n"); } + BN_mul(d,a,b,ctx); + BN_sub(d,d,e); + BN_div(a,b,d,c,ctx); + if(!BN_is_zero(b)) + { + fprintf(stderr,"Modulo multiply test failed!\n"); + ERR_print_errors_fp(stderr); + return 0; + } } + } BN_free(a); BN_free(b); BN_free(c); @@ -585,9 +977,7 @@ BN_CTX *ctx; return(1); } -int test_mod_exp(bp,ctx) -BIO *bp; -BN_CTX *ctx; +int test_mod_exp(BIO *bp, BN_CTX *ctx) { BIGNUM *a,*b,*c,*d,*e; int i; @@ -598,14 +988,14 @@ BN_CTX *ctx; d=BN_new(); e=BN_new(); - BN_rand(c,30,0,1); /* must be odd for montgomery */ - for (i=0; i<6; i++) + BN_bntest_rand(c,30,0,1); /* must be odd for montgomery */ + for (i=0; ineg=rand_neg(); - for (i=0; i<70; i++) + BN_bntest_rand(c,30,0,1); /* must be odd for montgomery */ + for (i=0; ineg=rand_neg(); - for (i=0; i<70; i++) + mont = BN_MONT_CTX_new(); + + BN_bntest_rand(m,1024,0,1); /* must be odd for montgomery */ + /* Zero exponent */ + BN_bntest_rand(a,1024,0,0); + BN_zero(p); + if(!BN_mod_exp_mont_consttime(d,a,p,m,ctx,NULL)) + return 0; + if(!BN_is_one(d)) { - BN_lshift1(b,a); - if (bp != NULL) - { - if (!results) - { - BN_print(bp,a); - BIO_puts(bp," * 2"); - BIO_puts(bp," - "); - } - BN_print(bp,b); - BIO_puts(bp,"\n"); - } - BN_copy(a,b); + fprintf(stderr, "Modular exponentiation test failed!\n"); + return 0; } - BN_free(a); - BN_free(b); - return(1); + /* Zero input */ + BN_bntest_rand(p,1024,0,0); + BN_zero(a); + if(!BN_mod_exp_mont_consttime(d,a,p,m,ctx,NULL)) + return 0; + if(!BN_is_zero(d)) + { + fprintf(stderr, "Modular exponentiation test failed!\n"); + return 0; + } + /* Craft an input whose Montgomery representation is 1, + * i.e., shorter than the modulus m, in order to test + * the const time precomputation scattering/gathering. + */ + BN_one(a); + BN_MONT_CTX_set(mont,m,ctx); + if(!BN_from_montgomery(e,a,mont,ctx)) + return 0; + if(!BN_mod_exp_mont_consttime(d,e,p,m,ctx,NULL)) + return 0; + if(!BN_mod_exp_simple(a,e,p,m,ctx)) + return 0; + if(BN_cmp(a,d) != 0) + { + fprintf(stderr,"Modular exponentiation test failed!\n"); + return 0; + } + /* Finally, some regular test vectors. */ + BN_bntest_rand(e,1024,0,0); + if(!BN_mod_exp_mont_consttime(d,e,p,m,ctx,NULL)) + return 0; + if(!BN_mod_exp_simple(a,e,p,m,ctx)) + return 0; + if(BN_cmp(a,d) != 0) + { + fprintf(stderr,"Modular exponentiation test failed!\n"); + return 0; + } + BN_free(a); + BN_free(p); + BN_free(m); + BN_free(d); + BN_free(e); + return(1); + } + +int test_exp(BIO *bp, BN_CTX *ctx) + { + BIGNUM *a,*b,*d,*e,*one; + int i; + + a=BN_new(); + b=BN_new(); + d=BN_new(); + e=BN_new(); + one=BN_new(); + BN_one(one); + + for (i=0; ineg = rand_neg(); + putc('\n', stderr); + + for (i = 0; i < num0; i++) + { + if (!BN_bntest_rand(a, 512, 0, 0)) goto err; + a->neg = rand_neg(); + + /* t := (|b|-1)/2 (note that b is odd) */ + if (!BN_copy(t, b)) goto err; + t->neg = 0; + if (!BN_sub_word(t, 1)) goto err; + if (!BN_rshift1(t, t)) goto err; + /* r := a^t mod b */ + b->neg=0; + + if (!BN_mod_exp_recp(r, a, t, b, ctx)) goto err; + b->neg=1; + + if (BN_is_word(r, 1)) + legendre = 1; + else if (BN_is_zero(r)) + legendre = 0; + else + { + if (!BN_add_word(r, 1)) goto err; + if (0 != BN_ucmp(r, b)) + { + fprintf(stderr, "Legendre symbol computation failed\n"); + goto err; + } + legendre = -1; + } + + kronecker = BN_kronecker(a, b, ctx); + if (kronecker < -1) goto err; + /* we actually need BN_kronecker(a, |b|) */ + if (a->neg && b->neg) + kronecker = -kronecker; + + if (legendre != kronecker) + { + fprintf(stderr, "legendre != kronecker; a = "); + BN_print_fp(stderr, a); + fprintf(stderr, ", b = "); + BN_print_fp(stderr, b); + fprintf(stderr, "\n"); + goto err; + } + + putc('.', stderr); + fflush(stderr); + } + + putc('\n', stderr); + fflush(stderr); + ret = 1; + err: + if (a != NULL) BN_free(a); + if (b != NULL) BN_free(b); + if (r != NULL) BN_free(r); + if (t != NULL) BN_free(t); + return ret; + } + +int test_sqrt(BIO *bp, BN_CTX *ctx) + { + BN_GENCB cb; + BIGNUM *a,*p,*r; + int i, j; + int ret = 0; + + a = BN_new(); + p = BN_new(); + r = BN_new(); + if (a == NULL || p == NULL || r == NULL) goto err; + + BN_GENCB_set(&cb, genprime_cb, NULL); + + for (i = 0; i < 16; i++) + { + if (i < 8) + { + unsigned primes[8] = { 2, 3, 5, 7, 11, 13, 17, 19 }; + + if (!BN_set_word(p, primes[i])) goto err; + } + else + { + if (!BN_set_word(a, 32)) goto err; + if (!BN_set_word(r, 2*i + 1)) goto err; + + if (!BN_generate_prime_ex(p, 256, 0, a, r, &cb)) goto err; + putc('\n', stderr); + } + p->neg = rand_neg(); + + for (j = 0; j < num2; j++) + { + /* construct 'a' such that it is a square modulo p, + * but in general not a proper square and not reduced modulo p */ + if (!BN_bntest_rand(r, 256, 0, 3)) goto err; + if (!BN_nnmod(r, r, p, ctx)) goto err; + if (!BN_mod_sqr(r, r, p, ctx)) goto err; + if (!BN_bntest_rand(a, 256, 0, 3)) goto err; + if (!BN_nnmod(a, a, p, ctx)) goto err; + if (!BN_mod_sqr(a, a, p, ctx)) goto err; + if (!BN_mul(a, a, r, ctx)) goto err; + if (rand_neg()) + if (!BN_sub(a, a, p)) goto err; + + if (!BN_mod_sqrt(r, a, p, ctx)) goto err; + if (!BN_mod_sqr(r, r, p, ctx)) goto err; + + if (!BN_nnmod(a, a, p, ctx)) goto err; + + if (BN_cmp(a, r) != 0) + { + fprintf(stderr, "BN_mod_sqrt failed: a = "); + BN_print_fp(stderr, a); + fprintf(stderr, ", r = "); + BN_print_fp(stderr, r); + fprintf(stderr, ", p = "); + BN_print_fp(stderr, p); + fprintf(stderr, "\n"); + goto err; + } + + putc('.', stderr); + fflush(stderr); + } + + putc('\n', stderr); + fflush(stderr); + } + ret = 1; + err: + if (a != NULL) BN_free(a); + if (p != NULL) BN_free(p); + if (r != NULL) BN_free(r); + return ret; + } + +int test_small_prime(BIO *bp,BN_CTX *ctx) + { + static const int bits = 10; + int ret = 0; + BIGNUM r; + + BN_init(&r); + if (!BN_generate_prime_ex(&r, bits, 0, NULL, NULL, NULL)) + goto err; + if (BN_num_bits(&r) != bits) + { + BIO_printf(bp, "Expected %d bit prime, got %d bit number\n", bits, BN_num_bits(&r)); + goto err; + } + + ret = 1; + +err: + BN_clear(&r); + return ret; + } +#ifndef OPENSSL_SYS_WIN32 +int test_probable_prime_coprime(BIO *bp, BN_CTX *ctx) + { + int i, j, ret = 0; + BIGNUM r; + BN_ULONG primes[5] = { 2, 3, 5, 7, 11 }; + + BN_init(&r); + + for (i = 0; i < 1000; i++) + { + if (!bn_probable_prime_dh_coprime(&r, 1024, ctx)) goto err; + + for (j = 0; j < 5; j++) + { + if (BN_mod_word(&r, primes[j]) == 0) + { + BIO_printf(bp, "Number generated is not coprime to %ld:\n", primes[j]); + BN_print_fp(stdout, &r); + BIO_printf(bp, "\n"); + goto err; + } + } + } + + ret = 1; + +err: + BN_clear(&r); + return ret; + } +#endif +int test_lshift(BIO *bp,BN_CTX *ctx,BIGNUM *a_) + { + BIGNUM *a,*b,*c,*d; + int i; + + b=BN_new(); + c=BN_new(); + d=BN_new(); + BN_one(c); + + if(a_) + a=a_; + else + { + a=BN_new(); + BN_bntest_rand(a,200,0,0); /**/ + a->neg=rand_neg(); + } + for (i=0; ineg=rand_neg(); + for (i=0; ineg=rand_neg(); - for (i=0; i<70; i++) + for (i=0; ineg=rand_neg(); - for (i=0; i<70; i++) + for (i=0; i