New function BN_MONT_CTX_set_locked, to set montgomery parameters in a

threadsafe manner.

Modify or add calls to use it in rsa, dsa and dh algorithms.
This commit is contained in:
Dr. Stephen Henson 2005-04-22 13:17:49 +00:00
parent 145878ca29
commit 4ed56cba63
10 changed files with 114 additions and 221 deletions

View file

@ -4,6 +4,11 @@
Changes between 0.9.7g and 0.9.7h [XX xxx XXXX]
*) New function BN_MONT_CTX_set_locked() to set montgomery parameters in
a threadsafe manner. Modify rsa code to use new function and add calls
to dsa and dh code (which had race conditions before).
[Steve Henson]
*) Include the fixed error library code in the C error file definitions
instead of fixing them up at runtime. This keeps the error code
structures constant.

View file

@ -434,6 +434,8 @@ int BN_from_montgomery(BIGNUM *r,const BIGNUM *a,
void BN_MONT_CTX_free(BN_MONT_CTX *mont);
int BN_MONT_CTX_set(BN_MONT_CTX *mont,const BIGNUM *mod,BN_CTX *ctx);
BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to,BN_MONT_CTX *from);
BN_MONT_CTX *BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, int lock,
const BIGNUM *mod, BN_CTX *ctx);
BN_BLINDING *BN_BLINDING_new(BIGNUM *A,BIGNUM *Ai,BIGNUM *mod);
void BN_BLINDING_free(BN_BLINDING *b);

View file

@ -347,3 +347,23 @@ BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to, BN_MONT_CTX *from)
return(to);
}
BN_MONT_CTX *BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, int lock,
const BIGNUM *mod, BN_CTX *ctx)
{
if (*pmont)
return *pmont;
CRYPTO_w_lock(lock);
if (!*pmont)
{
*pmont = BN_MONT_CTX_new();
if (*pmont && !BN_MONT_CTX_set(*pmont, mod, ctx))
{
BN_MONT_CTX_free(*pmont);
*pmont = NULL;
}
}
CRYPTO_w_unlock(lock);
return *pmont;
}

View file

@ -128,13 +128,15 @@ static int generate_key(DH *dh)
else
pub_key=dh->pub_key;
if ((dh->method_mont_p == NULL) && (dh->flags & DH_FLAG_CACHE_MONT_P))
if (dh->flags & DH_FLAG_CACHE_MONT_P)
{
if ((dh->method_mont_p=(char *)BN_MONT_CTX_new()) != NULL)
if (!BN_MONT_CTX_set((BN_MONT_CTX *)dh->method_mont_p,
dh->p,ctx)) goto err;
mont = BN_MONT_CTX_set_locked(
(BN_MONT_CTX **)&dh->method_mont_p,
CRYPTO_LOCK_DH, dh->p, ctx);
if (!mont)
goto err;
}
mont=(BN_MONT_CTX *)dh->method_mont_p;
if (generate_new_key)
{
@ -174,14 +176,16 @@ static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
DHerr(DH_F_DH_COMPUTE_KEY,DH_R_NO_PRIVATE_VALUE);
goto err;
}
if ((dh->method_mont_p == NULL) && (dh->flags & DH_FLAG_CACHE_MONT_P))
if (dh->flags & DH_FLAG_CACHE_MONT_P)
{
if ((dh->method_mont_p=(char *)BN_MONT_CTX_new()) != NULL)
if (!BN_MONT_CTX_set((BN_MONT_CTX *)dh->method_mont_p,
dh->p,ctx)) goto err;
mont = BN_MONT_CTX_set_locked(
(BN_MONT_CTX **)&dh->method_mont_p,
CRYPTO_LOCK_DH, dh->p, ctx);
if (!mont)
goto err;
}
mont=(BN_MONT_CTX *)dh->method_mont_p;
if (!dh->meth->bn_mod_exp(dh, tmp, pub_key, dh->priv_key,dh->p,ctx,mont))
{
DHerr(DH_F_DH_COMPUTE_KEY,ERR_R_BN_LIB);

View file

@ -198,11 +198,12 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp)
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))
if (dsa->flags & DSA_FLAG_CACHE_MONT_P)
{
if ((dsa->method_mont_p=(char *)BN_MONT_CTX_new()) != NULL)
if (!BN_MONT_CTX_set((BN_MONT_CTX *)dsa->method_mont_p,
dsa->p,ctx)) goto err;
if (!BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_p,
CRYPTO_LOCK_DSA,
dsa->p, ctx))
goto err;
}
/* Compute r = (g^k mod p) mod q */
@ -275,13 +276,15 @@ static int dsa_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig,
/* u2 = r * w mod q */
if (!BN_mod_mul(&u2,sig->r,&u2,dsa->q,ctx)) goto err;
if ((dsa->method_mont_p == NULL) && (dsa->flags & DSA_FLAG_CACHE_MONT_P))
if (dsa->flags & DSA_FLAG_CACHE_MONT_P)
{
if ((dsa->method_mont_p=(char *)BN_MONT_CTX_new()) != NULL)
if (!BN_MONT_CTX_set((BN_MONT_CTX *)dsa->method_mont_p,
dsa->p,ctx)) goto err;
mont = BN_MONT_CTX_set_locked(
(BN_MONT_CTX **)&dsa->method_mont_p,
CRYPTO_LOCK_DSA, dsa->p, ctx));
if (!mont)
goto err;
}
mont=(BN_MONT_CTX *)dsa->method_mont_p;
#if 0
{

View file

@ -145,30 +145,13 @@ static int RSA_eay_public_encrypt(int flen, const unsigned char *from,
goto err;
}
if ((rsa->_method_mod_n == NULL) && (rsa->flags & RSA_FLAG_CACHE_PUBLIC))
if (rsa->flags & RSA_FLAG_CACHE_PUBLIC)
{
BN_MONT_CTX* bn_mont_ctx;
if ((bn_mont_ctx=BN_MONT_CTX_new()) == NULL)
if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n,
CRYPTO_LOCK_RSA, rsa->n, ctx)
goto err;
if (!BN_MONT_CTX_set(bn_mont_ctx,rsa->n,ctx))
{
BN_MONT_CTX_free(bn_mont_ctx);
goto err;
}
if (rsa->_method_mod_n == NULL) /* other thread may have finished first */
{
CRYPTO_w_lock(CRYPTO_LOCK_RSA);
if (rsa->_method_mod_n == NULL)
{
rsa->_method_mod_n = bn_mont_ctx;
bn_mont_ctx = NULL;
}
CRYPTO_w_unlock(CRYPTO_LOCK_RSA);
}
if (bn_mont_ctx)
BN_MONT_CTX_free(bn_mont_ctx);
}
if (!rsa->meth->bn_mod_exp(&ret,&f,rsa->e,rsa->n,ctx,
rsa->_method_mod_n)) goto err;
@ -534,30 +517,14 @@ static int RSA_eay_public_decrypt(int flen, const unsigned char *from,
}
/* do the decrypt */
if ((rsa->_method_mod_n == NULL) && (rsa->flags & RSA_FLAG_CACHE_PUBLIC))
if (rsa->flags & RSA_FLAG_CACHE_PUBLIC)
{
BN_MONT_CTX* bn_mont_ctx;
if ((bn_mont_ctx=BN_MONT_CTX_new()) == NULL)
if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n,
CRYPTO_LOCK_RSA, rsa->n, ctx)
goto err;
if (!BN_MONT_CTX_set(bn_mont_ctx,rsa->n,ctx))
{
BN_MONT_CTX_free(bn_mont_ctx);
goto err;
}
if (rsa->_method_mod_n == NULL) /* other thread may have finished first */
{
CRYPTO_w_lock(CRYPTO_LOCK_RSA);
if (rsa->_method_mod_n == NULL)
{
rsa->_method_mod_n = bn_mont_ctx;
bn_mont_ctx = NULL;
}
CRYPTO_w_unlock(CRYPTO_LOCK_RSA);
}
if (bn_mont_ctx)
BN_MONT_CTX_free(bn_mont_ctx);
}
if (!rsa->meth->bn_mod_exp(&ret,&f,rsa->e,rsa->n,ctx,
rsa->_method_mod_n)) goto err;
@ -604,55 +571,14 @@ static int RSA_eay_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa)
if (rsa->flags & RSA_FLAG_CACHE_PRIVATE)
{
if (rsa->_method_mod_p == NULL)
{
BN_MONT_CTX* bn_mont_ctx;
if ((bn_mont_ctx=BN_MONT_CTX_new()) == NULL)
goto err;
if (!BN_MONT_CTX_set(bn_mont_ctx,rsa->p,ctx))
{
BN_MONT_CTX_free(bn_mont_ctx);
goto err;
}
if (rsa->_method_mod_p == NULL) /* other thread may have finished first */
{
CRYPTO_w_lock(CRYPTO_LOCK_RSA);
if (rsa->_method_mod_p == NULL)
{
rsa->_method_mod_p = bn_mont_ctx;
bn_mont_ctx = NULL;
}
CRYPTO_w_unlock(CRYPTO_LOCK_RSA);
}
if (bn_mont_ctx)
BN_MONT_CTX_free(bn_mont_ctx);
}
if (rsa->_method_mod_q == NULL)
{
BN_MONT_CTX* bn_mont_ctx;
if ((bn_mont_ctx=BN_MONT_CTX_new()) == NULL)
goto err;
if (!BN_MONT_CTX_set(bn_mont_ctx,rsa->q,ctx))
{
BN_MONT_CTX_free(bn_mont_ctx);
goto err;
}
if (rsa->_method_mod_q == NULL) /* other thread may have finished first */
{
CRYPTO_w_lock(CRYPTO_LOCK_RSA);
if (rsa->_method_mod_q == NULL)
{
rsa->_method_mod_q = bn_mont_ctx;
bn_mont_ctx = NULL;
}
CRYPTO_w_unlock(CRYPTO_LOCK_RSA);
}
if (bn_mont_ctx)
BN_MONT_CTX_free(bn_mont_ctx);
}
if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_p,
CRYPTO_LOCK_RSA, rsa->p, ctx)
goto err;
if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_q,
CRYPTO_LOCK_RSA, rsa->q, ctx)
goto err;
}
if (!BN_mod(&r1,I,rsa->q,ctx)) goto err;
if (!rsa->meth->bn_mod_exp(&m1,&r1,rsa->dmq1,rsa->q,ctx,
rsa->_method_mod_q)) goto err;

View file

@ -131,13 +131,14 @@ static int generate_key(DH *dh)
else
pub_key=dh->pub_key;
if ((dh->method_mont_p == NULL) && (dh->flags & DH_FLAG_CACHE_MONT_P))
if (dh->flags & DH_FLAG_CACHE_MONT_P)
{
if ((dh->method_mont_p=(char *)BN_MONT_CTX_new()) != NULL)
if (!BN_MONT_CTX_set((BN_MONT_CTX *)dh->method_mont_p,
dh->p,ctx)) goto err;
mont = BN_MONT_CTX_set_locked(
(BN_MONT_CTX **)&dh->method_mont_p,
CRYPTO_LOCK_DH, dh->p, ctx);
if (!mont)
goto err;
}
mont=(BN_MONT_CTX *)dh->method_mont_p;
if (generate_new_key)
{
@ -177,14 +178,16 @@ static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
DHerr(DH_F_DH_COMPUTE_KEY,DH_R_NO_PRIVATE_VALUE);
goto err;
}
if ((dh->method_mont_p == NULL) && (dh->flags & DH_FLAG_CACHE_MONT_P))
if (dh->flags & DH_FLAG_CACHE_MONT_P)
{
if ((dh->method_mont_p=(char *)BN_MONT_CTX_new()) != NULL)
if (!BN_MONT_CTX_set((BN_MONT_CTX *)dh->method_mont_p,
dh->p,ctx)) goto err;
mont = BN_MONT_CTX_set_locked(
(BN_MONT_CTX **)&dh->method_mont_p,
CRYPTO_LOCK_DH, dh->p, ctx);
if (!mont)
goto err;
}
mont=(BN_MONT_CTX *)dh->method_mont_p;
if (!dh->meth->bn_mod_exp(dh, tmp, pub_key, dh->priv_key,dh->p,ctx,mont))
{
DHerr(DH_F_DH_COMPUTE_KEY,ERR_R_BN_LIB);

View file

@ -223,11 +223,12 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp)
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))
if (dsa->flags & DSA_FLAG_CACHE_MONT_P)
{
if ((dsa->method_mont_p=(char *)BN_MONT_CTX_new()) != NULL)
if (!BN_MONT_CTX_set((BN_MONT_CTX *)dsa->method_mont_p,
dsa->p,ctx)) goto err;
if (!BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_p,
CRYPTO_LOCK_DSA,
dsa->p, ctx))
goto err;
}
/* Compute r = (g^k mod p) mod q */
@ -307,13 +308,15 @@ static int dsa_do_verify(const unsigned char *dgst, FIPS_DSA_SIZE_T dgst_len, DS
/* u2 = r * w mod q */
if (!BN_mod_mul(&u2,sig->r,&u2,dsa->q,ctx)) goto err;
if ((dsa->method_mont_p == NULL) && (dsa->flags & DSA_FLAG_CACHE_MONT_P))
if (dsa->flags & DSA_FLAG_CACHE_MONT_P)
{
if ((dsa->method_mont_p=(char *)BN_MONT_CTX_new()) != NULL)
if (!BN_MONT_CTX_set((BN_MONT_CTX *)dsa->method_mont_p,
dsa->p,ctx)) goto err;
mont = BN_MONT_CTX_set_locked(
(BN_MONT_CTX **)&dsa->method_mont_p,
CRYPTO_LOCK_DSA, dsa->p, ctx);
if (!mont)
goto err;
}
mont=(BN_MONT_CTX *)dsa->method_mont_p;
#if 0
{

View file

@ -14,13 +14,13 @@ const char * const FIPS_source_hashes[] = {
"HMAC-SHA1(des/fips_des_locl.h)= e008da40dc6913e374edd66a20d44e1752f00583",
"HMAC-SHA1(dh/fips_dh_check.c)= 63347e2007e224381d4a7b6d871633889de72cf3",
"HMAC-SHA1(dh/fips_dh_gen.c)= 93fe69b758ca9d70d70cda1c57fff4eb5c668e85",
"HMAC-SHA1(dh/fips_dh_key.c)= a84970913f0eaa098fc4e48d4487b45ebe27bcc3",
"HMAC-SHA1(dsa/fips_dsa_ossl.c)= e02fac446e5f89d22ffa0468fbc97d8dab7a5da8",
"HMAC-SHA1(dh/fips_dh_key.c)= 90bdc0c2c55aea2feecd16bf9b4bc3717d4c32f4",
"HMAC-SHA1(dsa/fips_dsa_ossl.c)= 0ff7c3aa1cb111f14ff253870fc2eddfd2224d06",
"HMAC-SHA1(dsa/fips_dsa_gen.c)= c252db14699f3ff641db052311da7d7521569c53",
"HMAC-SHA1(dsa/fips_dsa_selftest.c)= 7c2ba8d82feda2aadc8b769a3b6c4c25a6356e01",
"HMAC-SHA1(rand/fips_rand.c)= 29139e29f56f3ecd99f527af8742d5afb12f409a",
"HMAC-SHA1(rand/fips_rand.h)= bf009ea8963e79b1e414442ede9ae7010a03160b",
"HMAC-SHA1(rsa/fips_rsa_eay.c)= dc0c262df0a218b290192edb21639ced4532e857",
"HMAC-SHA1(rsa/fips_rsa_eay.c)= 2596773a7af8f037427217b79f56858296961d66",
"HMAC-SHA1(rsa/fips_rsa_gen.c)= 713d2e0d7a1a682b1794f1224b7afe01272ba755",
"HMAC-SHA1(rsa/fips_rsa_selftest.c)= 8c915b5a4e354dcede93ba08c42858d4dd884e67",
"HMAC-SHA1(sha1/fips_sha1dgst.c)= 867e990149be16fe9e758b916b5ffc9d9fa61afb",

View file

@ -153,30 +153,13 @@ static int RSA_eay_public_encrypt(FIPS_RSA_SIZE_T flen, const unsigned char *fro
goto err;
}
if ((rsa->_method_mod_n == NULL) && (rsa->flags & RSA_FLAG_CACHE_PUBLIC))
if (rsa->flags & RSA_FLAG_CACHE_PUBLIC)
{
BN_MONT_CTX* bn_mont_ctx;
if ((bn_mont_ctx=BN_MONT_CTX_new()) == NULL)
if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n,
CRYPTO_LOCK_RSA, rsa->n, ctx))
goto err;
if (!BN_MONT_CTX_set(bn_mont_ctx,rsa->n,ctx))
{
BN_MONT_CTX_free(bn_mont_ctx);
goto err;
}
if (rsa->_method_mod_n == NULL) /* other thread may have finished first */
{
CRYPTO_w_lock(CRYPTO_LOCK_RSA);
if (rsa->_method_mod_n == NULL)
{
rsa->_method_mod_n = bn_mont_ctx;
bn_mont_ctx = NULL;
}
CRYPTO_w_unlock(CRYPTO_LOCK_RSA);
}
if (bn_mont_ctx)
BN_MONT_CTX_free(bn_mont_ctx);
}
if (!rsa->meth->bn_mod_exp(&ret,&f,rsa->e,rsa->n,ctx,
rsa->_method_mod_n)) goto err;
@ -542,30 +525,14 @@ static int RSA_eay_public_decrypt(FIPS_RSA_SIZE_T flen, const unsigned char *fro
}
/* do the decrypt */
if ((rsa->_method_mod_n == NULL) && (rsa->flags & RSA_FLAG_CACHE_PUBLIC))
if (rsa->flags & RSA_FLAG_CACHE_PUBLIC)
{
BN_MONT_CTX* bn_mont_ctx;
if ((bn_mont_ctx=BN_MONT_CTX_new()) == NULL)
if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n,
CRYPTO_LOCK_RSA, rsa->n, ctx))
goto err;
if (!BN_MONT_CTX_set(bn_mont_ctx,rsa->n,ctx))
{
BN_MONT_CTX_free(bn_mont_ctx);
goto err;
}
if (rsa->_method_mod_n == NULL) /* other thread may have finished first */
{
CRYPTO_w_lock(CRYPTO_LOCK_RSA);
if (rsa->_method_mod_n == NULL)
{
rsa->_method_mod_n = bn_mont_ctx;
bn_mont_ctx = NULL;
}
CRYPTO_w_unlock(CRYPTO_LOCK_RSA);
}
if (bn_mont_ctx)
BN_MONT_CTX_free(bn_mont_ctx);
}
if (!rsa->meth->bn_mod_exp(&ret,&f,rsa->e,rsa->n,ctx,
rsa->_method_mod_n)) goto err;
@ -610,57 +577,17 @@ static int RSA_eay_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa)
BN_init(&vrfy);
if ((ctx=BN_CTX_new()) == NULL) goto err;
if (rsa->flags & RSA_FLAG_CACHE_PRIVATE)
{
if (rsa->_method_mod_p == NULL)
{
BN_MONT_CTX* bn_mont_ctx;
if ((bn_mont_ctx=BN_MONT_CTX_new()) == NULL)
goto err;
if (!BN_MONT_CTX_set(bn_mont_ctx,rsa->p,ctx))
{
BN_MONT_CTX_free(bn_mont_ctx);
goto err;
}
if (rsa->_method_mod_p == NULL) /* other thread may have finished first */
{
CRYPTO_w_lock(CRYPTO_LOCK_RSA);
if (rsa->_method_mod_p == NULL)
{
rsa->_method_mod_p = bn_mont_ctx;
bn_mont_ctx = NULL;
}
CRYPTO_w_unlock(CRYPTO_LOCK_RSA);
}
if (bn_mont_ctx)
BN_MONT_CTX_free(bn_mont_ctx);
}
if (rsa->_method_mod_q == NULL)
{
BN_MONT_CTX* bn_mont_ctx;
if ((bn_mont_ctx=BN_MONT_CTX_new()) == NULL)
goto err;
if (!BN_MONT_CTX_set(bn_mont_ctx,rsa->q,ctx))
{
BN_MONT_CTX_free(bn_mont_ctx);
goto err;
}
if (rsa->_method_mod_q == NULL) /* other thread may have finished first */
{
CRYPTO_w_lock(CRYPTO_LOCK_RSA);
if (rsa->_method_mod_q == NULL)
{
rsa->_method_mod_q = bn_mont_ctx;
bn_mont_ctx = NULL;
}
CRYPTO_w_unlock(CRYPTO_LOCK_RSA);
}
if (bn_mont_ctx)
BN_MONT_CTX_free(bn_mont_ctx);
}
if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_p,
CRYPTO_LOCK_RSA, rsa->p, ctx))
goto err;
if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_q,
CRYPTO_LOCK_RSA, rsa->q, ctx))
goto err;
}
if (!BN_mod(&r1,I,rsa->q,ctx)) goto err;
if (!rsa->meth->bn_mod_exp(&m1,&r1,rsa->dmq1,rsa->q,ctx,
rsa->_method_mod_q)) goto err;