X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=crypto%2Fbn%2Fbn_prime.c;h=d03403a600d8ca7a2cd7c7ef3d06dde708a78f52;hb=e2f2a9af2c31680abcefadf5a77a430f1e4fcef7;hp=21d49affda6435a3b5110c0d2d8973a53821a499;hpb=e74231ed9e5b7a95fd7af625a09628d69eac76c3;p=oweals%2Fopenssl.git diff --git a/crypto/bn/bn_prime.c b/crypto/bn/bn_prime.c index 21d49affda..d03403a600 100644 --- a/crypto/bn/bn_prime.c +++ b/crypto/bn/bn_prime.c @@ -55,6 +55,59 @@ * copied and put under another distribution licence * [including the GNU Public Licence.] */ +/* ==================================================================== + * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ #include #include @@ -62,25 +115,51 @@ #include "bn_lcl.h" #include +/* NB: these functions have been "upgraded", the deprecated versions (which are + * compatibility wrappers using these functions) are in bn_depr.c. + * - Geoff + */ + /* The quick sieve algorithm approach to weeding out primes is * Philip Zimmermann's, as implemented in PGP. I have had a read of * his comments and implemented my own version. */ #include "bn_prime.h" -static int witness(BIGNUM *w, BIGNUM *a, BIGNUM *a1, BIGNUM *a1_odd, int k, - BN_CTX *ctx, BN_MONT_CTX *mont); +static int witness(BIGNUM *w, const BIGNUM *a, const BIGNUM *a1, + const BIGNUM *a1_odd, int k, BN_CTX *ctx, BN_MONT_CTX *mont); static int probable_prime(BIGNUM *rnd, int bits); static int probable_prime_dh(BIGNUM *rnd, int bits, - BIGNUM *add, BIGNUM *rem, BN_CTX *ctx); + const BIGNUM *add, const BIGNUM *rem, BN_CTX *ctx); static int probable_prime_dh_safe(BIGNUM *rnd, int bits, - BIGNUM *add, BIGNUM *rem, BN_CTX *ctx); + const BIGNUM *add, const BIGNUM *rem, BN_CTX *ctx); + +int BN_GENCB_call(BN_GENCB *cb, int a, int b) + { + /* No callback means continue */ + if(!cb) return 1; + switch(cb->ver) + { + case 1: + /* Deprecated-style callbacks */ + if(!cb->cb.cb_1) + return 1; + cb->cb.cb_1(a, b, cb->arg); + return 1; + case 2: + /* New-style callbacks */ + return cb->cb.cb_2(a, b, cb); + default: + break; + } + /* Unrecognised callback type */ + return 0; + } -BIGNUM *BN_generate_prime(BIGNUM *ret, int bits, int safe, BIGNUM *add, - BIGNUM *rem, void (*callback)(int,int,void *), void *cb_arg) +int BN_generate_prime_ex(BIGNUM *ret, int bits, int safe, + const BIGNUM *add, const BIGNUM *rem, BN_GENCB *cb) { - BIGNUM *rnd=NULL; - BIGNUM t; + BIGNUM *t; int found=0; int i,j,c1=0; BN_CTX *ctx; @@ -88,38 +167,36 @@ BIGNUM *BN_generate_prime(BIGNUM *ret, int bits, int safe, BIGNUM *add, ctx=BN_CTX_new(); if (ctx == NULL) goto err; - if (ret == NULL) - { - if ((rnd=BN_new()) == NULL) goto err; - } - else - rnd=ret; - BN_init(&t); + BN_CTX_start(ctx); + t = BN_CTX_get(ctx); + if(!t) goto err; loop: /* make a random number and set the top and bottom bits */ if (add == NULL) { - if (!probable_prime(rnd,bits)) goto err; + if (!probable_prime(ret,bits)) goto err; } else { if (safe) { - if (!probable_prime_dh_safe(rnd,bits,add,rem,ctx)) + if (!probable_prime_dh_safe(ret,bits,add,rem,ctx)) goto err; } else { - if (!probable_prime_dh(rnd,bits,add,rem,ctx)) + if (!probable_prime_dh(ret,bits,add,rem,ctx)) goto err; } } - /* if (BN_mod_word(rnd,(BN_ULONG)3) == 1) goto loop; */ - if (callback != NULL) callback(0,c1++,cb_arg); + /* if (BN_mod_word(ret,(BN_ULONG)3) == 1) goto loop; */ + if(!BN_GENCB_call(cb, 0, c1++)) + /* aborted */ + goto err; if (!safe) { - i=BN_is_prime_fasttest(rnd,checks,callback,ctx,cb_arg,0); + i=BN_is_prime_fasttest_ex(ret,checks,ctx,0,cb); if (i == -1) goto err; if (i == 0) goto loop; } @@ -129,63 +206,66 @@ loop: * check that (p-1)/2 is prime. * Since a prime is odd, We just * need to divide by 2 */ - if (!BN_rshift1(&t,rnd)) goto err; + if (!BN_rshift1(t,ret)) goto err; for (i=0; ineg) /* for now, refuse to handle negative numbers */ - return -1; - /* first look for small factors */ if (!BN_is_odd(a)) - return(0); + return 0; if (do_trial_division) { for (i = 1; i < NUMPRIMES; i++) if (BN_mod_word(a, primes[i]) == 0) return 0; - if (callback != NULL) callback(1, -1, cb_arg); + if(!BN_GENCB_call(cb, 1, -1)) + goto err; } if (ctx_passed != NULL) @@ -193,69 +273,83 @@ int BN_is_prime_fasttest(BIGNUM *a, int checks, else if ((ctx=BN_CTX_new()) == NULL) goto err; - a1 = &(ctx->bn[ctx->tos++]); - a1_odd = &(ctx->bn[ctx->tos++]); - check = &(ctx->bn[ctx->tos++]);; + BN_CTX_start(ctx); - /* compute a1 := a - 1 */ - if (!BN_copy(a1, a)) + /* A := abs(a) */ + if (a->neg) + { + BIGNUM *t; + if ((t = BN_CTX_get(ctx)) == NULL) goto err; + BN_copy(t, a); + t->neg = 0; + A = t; + } + else + A = a; + A1 = BN_CTX_get(ctx); + A1_odd = BN_CTX_get(ctx); + check = BN_CTX_get(ctx); + if (check == NULL) goto err; + + /* compute A1 := A - 1 */ + if (!BN_copy(A1, A)) goto err; - if (!BN_sub_word(a1, 1)) + if (!BN_sub_word(A1, 1)) goto err; - if (BN_is_zero(a1)) + if (BN_is_zero(A1)) { ret = 0; goto err; } - /* write a1 as a1_odd * 2^k */ + /* write A1 as A1_odd * 2^k */ k = 1; - while (!BN_is_bit_set(a1, k)) + while (!BN_is_bit_set(A1, k)) k++; - if (!BN_rshift(a1_odd, a1, k)) + if (!BN_rshift(A1_odd, A1, k)) goto err; - /* Montgomery setup for computations mod a */ + /* Montgomery setup for computations mod A */ mont = BN_MONT_CTX_new(); if (mont == NULL) goto err; - if (!BN_MONT_CTX_set(mont, a, ctx)) + if (!BN_MONT_CTX_set(mont, A, ctx)) goto err; for (i = 0; i < checks; i++) { - if (!BN_pseudo_rand(check, BN_num_bits(a1), 0, 0)) + if (!BN_pseudo_rand_range(check, A1)) goto err; - if (BN_cmp(check, a1) >= 0) - if (!BN_sub(check, check, a1)) - goto err; if (!BN_add_word(check, 1)) goto err; - /* now 1 <= check < a */ + /* now 1 <= check < A */ - j = witness(check, a, a1, a1_odd, k, ctx, mont); + j = witness(check, A, A1, A1_odd, k, ctx, mont); if (j == -1) goto err; if (j) { ret=0; goto err; } - if (callback != NULL) callback(1,i,cb_arg); + if(!BN_GENCB_call(cb, 1, i)) + goto err; } ret=1; err: - if (ctx_passed != NULL) - ctx_passed->tos -= 3; /* a1, a1_odd, check */ - else if (ctx != NULL) - BN_CTX_free(ctx); + if (ctx != NULL) + { + BN_CTX_end(ctx); + if (ctx_passed == NULL) + BN_CTX_free(ctx); + } if (mont != NULL) BN_MONT_CTX_free(mont); return(ret); } -static int witness(BIGNUM *w, BIGNUM *a, BIGNUM *a1, BIGNUM *a1_odd, int k, - BN_CTX *ctx, BN_MONT_CTX *mont) +static int witness(BIGNUM *w, const BIGNUM *a, const BIGNUM *a1, + const BIGNUM *a1_odd, int k, BN_CTX *ctx, BN_MONT_CTX *mont) { if (!BN_mod_exp_mont(w, w, a1_odd, a, ctx, mont)) /* w := w^a1_odd mod a */ return -1; @@ -275,6 +369,7 @@ static int witness(BIGNUM *w, BIGNUM *a, BIGNUM *a1, BIGNUM *a1_odd, int k, } /* If we get here, 'w' is the (a-1)/2-th power of the original 'w', * and it is neither -1 nor +1 -- so 'a' cannot be prime */ + bn_check_top(w); return 1; } @@ -299,23 +394,25 @@ again: d=delta; delta+=2; /* perhaps need to check for overflow of - * delta (but delta can be upto 2^32) + * delta (but delta can be up to 2^32) * 21-May-98 eay - added overflow check */ if (delta < d) goto again; goto loop; } } if (!BN_add_word(rnd,delta)) return(0); + bn_check_top(rnd); return(1); } -static int probable_prime_dh(BIGNUM *rnd, int bits, BIGNUM *add, BIGNUM *rem, - BN_CTX *ctx) +static int probable_prime_dh(BIGNUM *rnd, int bits, + const BIGNUM *add, const BIGNUM *rem, BN_CTX *ctx) { int i,ret=0; BIGNUM *t1; - t1= &(ctx->bn[ctx->tos++]); + BN_CTX_start(ctx); + if ((t1 = BN_CTX_get(ctx)) == NULL) goto err; if (!BN_rand(rnd,bits,0,1)) goto err; @@ -341,20 +438,23 @@ static int probable_prime_dh(BIGNUM *rnd, int bits, BIGNUM *add, BIGNUM *rem, } ret=1; err: - ctx->tos--; + BN_CTX_end(ctx); + bn_check_top(rnd); return(ret); } -static int probable_prime_dh_safe(BIGNUM *p, int bits, BIGNUM *padd, - BIGNUM *rem, BN_CTX *ctx) +static int probable_prime_dh_safe(BIGNUM *p, int bits, const BIGNUM *padd, + const BIGNUM *rem, BN_CTX *ctx) { int i,ret=0; - BIGNUM *t1,*qadd=NULL,*q=NULL; + BIGNUM *t1,*qadd,*q; bits--; - t1= &(ctx->bn[ctx->tos++]); - q= &(ctx->bn[ctx->tos++]); - qadd= &(ctx->bn[ctx->tos++]); + BN_CTX_start(ctx); + t1 = BN_CTX_get(ctx); + q = BN_CTX_get(ctx); + qadd = BN_CTX_get(ctx); + if (qadd == NULL) goto err; if (!BN_rshift1(qadd,padd)) goto err; @@ -390,6 +490,7 @@ static int probable_prime_dh_safe(BIGNUM *p, int bits, BIGNUM *padd, } ret=1; err: - ctx->tos-=3; + BN_CTX_end(ctx); + bn_check_top(p); return(ret); }