Avoid multiple lock using FIPS DRBG.
authorDr. Stephen Henson <steve@openssl.org>
Wed, 30 Jul 2014 14:13:08 +0000 (15:13 +0100)
committerDr. Stephen Henson <steve@openssl.org>
Wed, 30 Jul 2014 20:09:20 +0000 (21:09 +0100)
Don't use multiple locks when SP800-90 DRBG is used outside FIPS mode.

PR#3176
Reviewed-by: Rich Salz <rsalz@openssl.org>
(cherry picked from commit a3efe1b6e9d2aa2ce5661e4d4b97262eae743fa7)

crypto/rand/md_rand.c
crypto/rand/rand_lcl.h
crypto/rand/rand_lib.c

index aee1c30b0a9bb4a24cc1dd90694f25a0ed852c5b..5dd0a37d65203f769559063e84d8c39c626107c9 100644 (file)
@@ -335,6 +335,11 @@ static void ssleay_rand_seed(const void *buf, int num)
        }
 
 static int ssleay_rand_bytes(unsigned char *buf, int num, int pseudo)
+       {
+       return md_rand_bytes_lock(buf, num, pseudo, 1);
+       }
+
+int md_rand_bytes_lock(unsigned char *buf, int num, int pseudo, int lock)
        {
        static volatile int stirred_pool = 0;
        int i,j,k,st_num,st_idx;
@@ -383,10 +388,7 @@ 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'.
         */
-#ifdef OPENSSL_FIPS
-       /* NB: in FIPS mode we are already under a lock */
-       if (!FIPS_mode())
-#endif
+       if (lock)
                CRYPTO_w_lock(CRYPTO_LOCK_RAND);
 
        /* prevent ssleay_rand_bytes() from trying to obtain the lock again */
@@ -466,9 +468,7 @@ static int ssleay_rand_bytes(unsigned char *buf, int num, int pseudo)
 
        /* before unlocking, we must clear 'crypto_lock_rand' */
        crypto_lock_rand = 0;
-#ifdef OPENSSL_FIPS
-       if (!FIPS_mode())
-#endif
+       if (lock)
                CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
 
        while (num > 0)
@@ -521,15 +521,11 @@ 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);
-#ifdef OPENSSL_FIPS
-       if (!FIPS_mode())
-#endif
+       if (lock)
                CRYPTO_w_lock(CRYPTO_LOCK_RAND);
        MD_Update(&m,md,MD_DIGEST_LENGTH);
        MD_Final(&m,md);
-#ifdef OPENSSL_FIPS
-       if (!FIPS_mode())
-#endif
+       if (lock)
                CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
 
        EVP_MD_CTX_cleanup(&m);
index 618a8ec899cec833699fd3f3f5ac0be2caa4d3eb..725cdb31c242e37393190f8fded04542fa9cd781 100644 (file)
 #define        MD(a,b,c)               EVP_Digest(a,b,c,NULL,EVP_md2(), NULL)
 #endif
 
+int md_rand_bytes_lock(unsigned char *buf, int num, int pseudo, int lock);
 
 #endif
index 5ac0e14caf00bd36539b5180985117bd2f94b8fd..54f1d35c6c71cfd2493757f94d0360895b68a64f 100644 (file)
@@ -68,6 +68,7 @@
 #ifdef OPENSSL_FIPS
 #include <openssl/fips.h>
 #include <openssl/fips_rand.h>
+#include "rand_lcl.h"
 #endif
 
 #ifndef OPENSSL_NO_ENGINE
@@ -199,7 +200,7 @@ static size_t drbg_get_entropy(DRBG_CTX *ctx, unsigned char **pout,
        *pout = OPENSSL_malloc(min_len);
        if (!*pout)
                return 0;
-       if (RAND_SSLeay()->bytes(*pout, min_len) <= 0)
+       if (md_rand_bytes_lock(*pout, min_len, 0, 0) <= 0)
                {
                OPENSSL_free(*pout);
                *pout = NULL;