Avoid multiple locks in FIPS mode.
authorDr. Stephen Henson <steve@openssl.org>
Wed, 4 Dec 2013 13:39:04 +0000 (13:39 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Sun, 8 Dec 2013 13:23:14 +0000 (13:23 +0000)
PR: 3176.

In FIPS mode ssleay_rand_bytes is only used for PRNG seeding and is
performed in either a single threaded context (when the PRNG is first
initialised) or under a lock (reseeding). To avoid multiple locks disable
use of CRYPTO_LOCK_RAND in FIPS mode in ssleay_rand_bytes.
(cherry picked from commit 53142f72c9b9c9bad2f39ca6200a4f04f5c8001c)

crypto/rand/md_rand.c

index 1e3bcb9..2dd22d2 100644 (file)
@@ -380,8 +380,11 @@ static int ssleay_rand_bytes(unsigned char *buf, int num, int pseudo)
         * are fed into the hash function and the results are kept in the
         * global 'md'.
         */
-
-       CRYPTO_w_lock(CRYPTO_LOCK_RAND);
+#ifdef OPENSSL_FIPS
+       /* NB: in FIPS mode we are already under a lock */
+       if (FIPS_mode())
+#endif
+               CRYPTO_w_lock(CRYPTO_LOCK_RAND);
 
        /* prevent ssleay_rand_bytes() from trying to obtain the lock again */
        CRYPTO_w_lock(CRYPTO_LOCK_RAND2);
@@ -460,7 +463,10 @@ static int ssleay_rand_bytes(unsigned char *buf, int num, int pseudo)
 
        /* before unlocking, we must clear 'crypto_lock_rand' */
        crypto_lock_rand = 0;
-       CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
+#ifdef OPENSSL_FIPS
+       if (FIPS_mode())
+#endif
+               CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
 
        while (num > 0)
                {
@@ -512,10 +518,16 @@ static int ssleay_rand_bytes(unsigned char *buf, int num, int pseudo)
        MD_Init(&m);
        MD_Update(&m,(unsigned char *)&(md_c[0]),sizeof(md_c));
        MD_Update(&m,local_md,MD_DIGEST_LENGTH);
-       CRYPTO_w_lock(CRYPTO_LOCK_RAND);
+#ifdef OPENSSL_FIPS
+       if (FIPS_mode())
+#endif
+               CRYPTO_w_lock(CRYPTO_LOCK_RAND);
        MD_Update(&m,md,MD_DIGEST_LENGTH);
        MD_Final(&m,md);
-       CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
+#ifdef OPENSSL_FIPS
+       if (FIPS_mode())
+#endif
+               CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
 
        EVP_MD_CTX_cleanup(&m);
        if (ok)