diff options
Diffstat (limited to 'lib/libcrypto/dsa')
-rw-r--r-- | lib/libcrypto/dsa/dsa_key.c | 15 | ||||
-rw-r--r-- | lib/libcrypto/dsa/dsa_lib.c | 8 | ||||
-rw-r--r-- | lib/libcrypto/dsa/dsa_ossl.c | 64 |
3 files changed, 66 insertions, 21 deletions
diff --git a/lib/libcrypto/dsa/dsa_key.c b/lib/libcrypto/dsa/dsa_key.c index af3c56d770e..a68d236e05d 100644 --- a/lib/libcrypto/dsa/dsa_key.c +++ b/lib/libcrypto/dsa/dsa_key.c @@ -65,10 +65,11 @@ #include <openssl/dsa.h> #include <openssl/rand.h> +extern int __BN_rand_range(BIGNUM *r, BIGNUM *range); + int DSA_generate_key(DSA *dsa) { int ok=0; - unsigned int i; BN_CTX *ctx=NULL; BIGNUM *pub_key=NULL,*priv_key=NULL; @@ -81,15 +82,9 @@ int DSA_generate_key(DSA *dsa) else priv_key=dsa->priv_key; - i=BN_num_bits(dsa->q); - for (;;) - { - if (!BN_rand(priv_key,i,0,0)) - goto err; - if (BN_cmp(priv_key,dsa->q) >= 0) - BN_sub(priv_key,priv_key,dsa->q); - if (!BN_is_zero(priv_key)) break; - } + do + if (!__BN_rand_range(priv_key,dsa->q)) goto err; + while (BN_is_zero(priv_key)); if (dsa->pub_key == NULL) { diff --git a/lib/libcrypto/dsa/dsa_lib.c b/lib/libcrypto/dsa/dsa_lib.c index b31b946ad3b..15f667a203d 100644 --- a/lib/libcrypto/dsa/dsa_lib.c +++ b/lib/libcrypto/dsa/dsa_lib.c @@ -173,13 +173,13 @@ DSA *DSA_new_method(ENGINE *engine) ret->references=1; ret->flags=meth->flags; + CRYPTO_new_ex_data(dsa_meth,ret,&ret->ex_data); if ((meth->init != NULL) && !meth->init(ret)) { + CRYPTO_free_ex_data(dsa_meth,ret,&ret->ex_data); OPENSSL_free(ret); ret=NULL; } - else - CRYPTO_new_ex_data(dsa_meth,ret,&ret->ex_data); return(ret); } @@ -204,12 +204,12 @@ void DSA_free(DSA *r) } #endif - CRYPTO_free_ex_data(dsa_meth, r, &r->ex_data); - meth = ENGINE_get_DSA(r->engine); if(meth->finish) meth->finish(r); ENGINE_finish(r->engine); + CRYPTO_free_ex_data(dsa_meth, r, &r->ex_data); + if (r->p != NULL) BN_clear_free(r->p); if (r->q != NULL) BN_clear_free(r->q); if (r->g != NULL) BN_clear_free(r->g); diff --git a/lib/libcrypto/dsa/dsa_ossl.c b/lib/libcrypto/dsa/dsa_ossl.c index 96295dc24f7..5cbbdddfb96 100644 --- a/lib/libcrypto/dsa/dsa_ossl.c +++ b/lib/libcrypto/dsa/dsa_ossl.c @@ -66,6 +66,8 @@ #include <openssl/asn1.h> #include <openssl/engine.h> +int __BN_rand_range(BIGNUM *r, BIGNUM *range); + static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa); static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp); static int dsa_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig, @@ -180,13 +182,9 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp) kinv=NULL; /* Get random k */ - for (;;) - { - if (!BN_rand(&k, BN_num_bits(dsa->q), 0, 0)) goto err; - if (BN_cmp(&k,dsa->q) >= 0) - BN_sub(&k,&k,dsa->q); - if (!BN_is_zero(&k)) break; - } + do + if (!__BN_rand_range(&k, dsa->q)) goto err; + while (BN_is_zero(&k)); if ((dsa->method_mont_p == NULL) && (dsa->flags & DSA_FLAG_CACHE_MONT_P)) { @@ -320,3 +318,55 @@ static int dsa_bn_mod_exp(DSA *dsa, BIGNUM *r, BIGNUM *a, const BIGNUM *p, { return BN_mod_exp_mont(r, a, p, m, ctx, m_ctx); } + + +/* random number r: 0 <= r < range */ +int __BN_rand_range(BIGNUM *r, BIGNUM *range) + { + int n; + + if (range->neg || BN_is_zero(range)) + { + /* BNerr(BN_F_BN_RAND_RANGE, BN_R_INVALID_RANGE); */ + return 0; + } + + n = BN_num_bits(range); /* n > 0 */ + + if (n == 1) + { + if (!BN_zero(r)) return 0; + } + else if (BN_is_bit_set(range, n - 2)) + { + do + { + /* range = 11..._2, so each iteration succeeds with probability >= .75 */ + if (!BN_rand(r, n, -1, 0)) return 0; + } + while (BN_cmp(r, range) >= 0); + } + else + { + /* range = 10..._2, + * so 3*range (= 11..._2) is exactly one bit longer than range */ + do + { + if (!BN_rand(r, n + 1, -1, 0)) return 0; + /* If r < 3*range, use r := r MOD range + * (which is either r, r - range, or r - 2*range). + * Otherwise, iterate once more. + * Since 3*range = 11..._2, each iteration succeeds with + * probability >= .75. */ + if (BN_cmp(r ,range) >= 0) + { + if (!BN_sub(r, r, range)) return 0; + if (BN_cmp(r, range) >= 0) + if (!BN_sub(r, r, range)) return 0; + } + } + while (BN_cmp(r, range) >= 0); + } + + return 1; + } |