New function BN_MONT_CTX_set_locked, to set montgomery parameters in a
authorDr. Stephen Henson <steve@openssl.org>
Fri, 22 Apr 2005 13:17:49 +0000 (13:17 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Fri, 22 Apr 2005 13:17:49 +0000 (13:17 +0000)
threadsafe manner.

Modify or add calls to use it in rsa, dsa and dh algorithms.

CHANGES
crypto/bn/bn.h
crypto/bn/bn_mont.c
crypto/dh/dh_key.c
crypto/dsa/dsa_ossl.c
crypto/rsa/rsa_eay.c
fips/dh/fips_dh_key.c
fips/dsa/fips_dsa_ossl.c
fips/fipshashes.c
fips/rsa/fips_rsa_eay.c

diff --git a/CHANGES b/CHANGES
index 5644f50166ecdea97ca6e8a304e141ffdab72b0f..1a8cc26ada36a5ec940725bbadf934ad89e882e0 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -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.
index 3da6d8ced90b78011d87c791090b716541a6bf6f..ad42f2df7b8ae9e0960da9bd890edd7eaa2afcc8 100644 (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);
index b79b1b60da0b4385967f809da4f1846030975f5c..3572e5a6901e005e1ee4fb535a14146fe8f8f830 100644 (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;
+       }
+               
+
index ff125c2296fb2158d76b05d2051729d7be91a035..4254176ee2c3cdc81cd10454dce014acb689567a 100644 (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);
index f1a85afcde8656066338e3c4b7b45a3a091e9ef2..2bf83ca4195b35b2d2e29ab8915c0388cf0fc7ca 100644 (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
        {
index d4caab3f9538f8f4ee9c5c06aeea2b1fabed654b..143a25d2c415121b4dcb65915c4094cf54988ae7 100644 (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;
index 4d26bb1619e3b7e3ecf2d015c511a612f15815cb..d037b1e264bd104b83b56981f40e898eecd8926b 100644 (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);
index 2ed64c483e84456caac125da171eab0f9f9b8b36..fff3b8c4b7cd84d5ba3739843f463ee2db84563b 100644 (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
        {
index 816694480cc780800dfc38d43aed8c8535a73b46..fa51f31854d8b774284fe0398552e837c283d917 100644 (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",
index 7aa7e8ad41d919de7d7968573f8de6fe29ec8187..7613042ed80413a01e601a39f9d485341f11135a 100644 (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;