summaryrefslogtreecommitdiff
path: root/lib/libcrypto/dsa
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libcrypto/dsa')
-rw-r--r--lib/libcrypto/dsa/dsa_key.c15
-rw-r--r--lib/libcrypto/dsa/dsa_lib.c8
-rw-r--r--lib/libcrypto/dsa/dsa_ossl.c64
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;
+ }