File openssl-fipslocking.patch of Package openssl-1_1.21010
diff --git a/crypto/fips/fips_drbg_rand.c b/crypto/fips/fips_drbg_rand.c
index 7f230d3..2fd67ad 100644
--- a/crypto/fips/fips_drbg_rand.c
+++ b/crypto/fips/fips_drbg_rand.c
@@ -95,7 +95,8 @@ static int fips_drbg_bytes(unsigned char *out, int count)
if (count > dctx->min_entropy + dctx->min_nonce)
get_urandom(dctx->min_entropy + dctx->min_nonce);
- CRYPTO_THREAD_write_lock(fips_rand_lock);
+ int locked;
+ locked = private_RAND_lock(1);
do {
size_t rcnt;
if (count > (int)dctx->max_request)
@@ -124,7 +125,8 @@ static int fips_drbg_bytes(unsigned char *out, int count)
while (count);
rv = 1;
err:
- CRYPTO_THREAD_unlock(fips_rand_lock);
+ if (locked)
+ private_RAND_lock(0);
return rv;
}
@@ -139,38 +141,48 @@ static int fips_drbg_status(void)
{
DRBG_CTX *dctx = &ossl_dctx;
int rv;
- CRYPTO_THREAD_read_lock(fips_rand_lock);
+ int locked;
+ locked = private_RAND_lock(1);
rv = dctx->status == DRBG_STATUS_READY ? 1 : 0;
- CRYPTO_THREAD_unlock(fips_rand_lock);
+ if (locked)
+ private_RAND_lock(0);
return rv;
}
static void fips_drbg_cleanup(void)
{
DRBG_CTX *dctx = &ossl_dctx;
- CRYPTO_THREAD_write_lock(fips_rand_lock);
+ int locked;
+ locked = private_RAND_lock(1);
FIPS_drbg_uninstantiate(dctx);
- CRYPTO_THREAD_unlock(fips_rand_lock);
+ if (locked)
+ private_RAND_lock(0);
}
static int fips_drbg_seed(const void *seed, int seedlen)
{
DRBG_CTX *dctx = &ossl_dctx;
- CRYPTO_THREAD_write_lock(fips_rand_lock);
+ int locked;
+ int ret = 1;
+ locked = private_RAND_lock(1);
if (dctx->rand_seed_cb)
- return dctx->rand_seed_cb(dctx, seed, seedlen);
- CRYPTO_THREAD_unlock(fips_rand_lock);
- return 1;
+ ret = dctx->rand_seed_cb(dctx, seed, seedlen);
+ if (locked)
+ private_RAND_lock(0);
+ return ret;
}
static int fips_drbg_add(const void *seed, int seedlen, double add_entropy)
{
DRBG_CTX *dctx = &ossl_dctx;
- CRYPTO_THREAD_write_lock(fips_rand_lock);
+ int locked;
+ int ret = 1;
+ locked = private_RAND_lock(1);
if (dctx->rand_add_cb)
- return dctx->rand_add_cb(dctx, seed, seedlen, add_entropy);
- CRYPTO_THREAD_unlock(fips_rand_lock);
- return 1;
+ ret = dctx->rand_add_cb(dctx, seed, seedlen, add_entropy);
+ if (locked)
+ private_RAND_lock(0);
+ return ret;
}
static const RAND_METHOD rand_drbg_meth = {
diff --git a/crypto/rand/md_rand.c b/crypto/rand/md_rand.c
index b84da34..b8bc15f 100644
--- a/crypto/rand/md_rand.c
+++ b/crypto/rand/md_rand.c
@@ -100,6 +100,40 @@ RAND_METHOD *RAND_OpenSSL(void)
return (&rand_meth);
}
+int private_RAND_lock(int lock)
+{
+ int do_lock;
+
+ if (!lock)
+ {
+ crypto_lock_rand = 0;
+ CRYPTO_THREAD_unlock(rand_lock);
+ return 0;
+ }
+
+ /* check if we already have the lock */
+ if (crypto_lock_rand)
+ {
+ CRYPTO_THREAD_ID cur = CRYPTO_THREAD_get_current_id();
+ CRYPTO_THREAD_read_lock(rand_tmp_lock);
+ do_lock = !CRYPTO_THREAD_compare_id(locking_threadid, cur);
+ CRYPTO_THREAD_unlock(rand_tmp_lock);
+ }
+ else
+ do_lock = 1;
+
+ if (do_lock)
+ {
+ CRYPTO_THREAD_write_lock(rand_lock);
+ /* prevent from trying to obtain the lock again */
+ CRYPTO_THREAD_write_lock(rand_tmp_lock);
+ locking_threadid = CRYPTO_THREAD_get_current_id();
+ CRYPTO_THREAD_unlock(rand_tmp_lock);
+ crypto_lock_rand = 1;
+ }
+ return do_lock;
+}
+
static void rand_cleanup(void)
{
OPENSSL_cleanse(state, sizeof(state));
@@ -120,7 +154,7 @@ static int rand_add(const void *buf, int num, double add)
long md_c[2];
unsigned char local_md[MD_DIGEST_LENGTH];
EVP_MD_CTX *m;
- int do_not_lock;
+ int locked;
int rv = 0;
if (!num)
@@ -148,17 +182,8 @@ static int rand_add(const void *buf, int num, double add)
if (!RUN_ONCE(&rand_lock_init, do_rand_lock_init))
goto err;
- /* check if we already have the lock */
- if (crypto_lock_rand) {
- CRYPTO_THREAD_ID cur = CRYPTO_THREAD_get_current_id();
- CRYPTO_THREAD_read_lock(rand_tmp_lock);
- do_not_lock = CRYPTO_THREAD_compare_id(locking_threadid, cur);
- CRYPTO_THREAD_unlock(rand_tmp_lock);
- } else
- do_not_lock = 0;
-
- if (!do_not_lock)
- CRYPTO_THREAD_write_lock(rand_lock);
+ locked = private_RAND_lock(1);
+
st_idx = state_index;
/*
@@ -189,8 +214,8 @@ static int rand_add(const void *buf, int num, double add)
md_count[1] += (num / MD_DIGEST_LENGTH) + (num % MD_DIGEST_LENGTH > 0);
- if (!do_not_lock)
- CRYPTO_THREAD_unlock(rand_lock);
+ if (locked)
+ private_RAND_lock(0);
for (i = 0; i < num; i += MD_DIGEST_LENGTH) {
j = (num - i);
@@ -243,8 +268,7 @@ static int rand_add(const void *buf, int num, double add)
}
}
- if (!do_not_lock)
- CRYPTO_THREAD_write_lock(rand_lock);
+ locked = private_RAND_lock(1);
/*
* Don't just copy back local_md into md -- this could mean that other
* thread's seeding remains without effect (except for the incremented
@@ -256,8 +280,8 @@ static int rand_add(const void *buf, int num, double add)
}
if (entropy < ENTROPY_NEEDED) /* stop counting when we have enough */
entropy += add;
- if (!do_not_lock)
- CRYPTO_THREAD_unlock(rand_lock);
+ if (locked)
+ private_RAND_lock(0);
rv = 1;
err:
@@ -284,6 +308,7 @@ static int rand_bytes(unsigned char *buf, int num, int pseudo)
#endif
time_t curr_time = time(NULL);
int do_stir_pool = 0;
+ int locked;
/* time value for various platforms */
#ifdef OPENSSL_SYS_WIN32
FILETIME tv;
@@ -350,19 +375,13 @@ static int rand_bytes(unsigned char *buf, int num, int pseudo)
if (!RUN_ONCE(&rand_lock_init, do_rand_lock_init))
goto err_mem;
- CRYPTO_THREAD_write_lock(rand_lock);
+ locked = private_RAND_lock(1);
/*
* We could end up in an async engine while holding this lock so ensure
* we don't pause and cause a deadlock
*/
ASYNC_block_pause();
- /* prevent rand_bytes() from trying to obtain the lock again */
- CRYPTO_THREAD_write_lock(rand_tmp_lock);
- locking_threadid = CRYPTO_THREAD_get_current_id();
- CRYPTO_THREAD_unlock(rand_tmp_lock);
- crypto_lock_rand = 1;
-
if (!initialized || FIPS_mode()) {
RAND_poll();
initialized = 1;
@@ -432,10 +451,9 @@ static int rand_bytes(unsigned char *buf, int num, int pseudo)
md_count[0] += 1;
- /* before unlocking, we must clear 'crypto_lock_rand' */
- crypto_lock_rand = 0;
ASYNC_unblock_pause();
- CRYPTO_THREAD_unlock(rand_lock);
+ if (locked)
+ private_RAND_lock(0);
while (num > 0) {
/* num_ceil -= MD_DIGEST_LENGTH/2 */
@@ -489,18 +507,21 @@ static int rand_bytes(unsigned char *buf, int num, int pseudo)
|| !MD_Update(m, (unsigned char *)&(md_c[0]), sizeof(md_c))
|| !MD_Update(m, local_md, MD_DIGEST_LENGTH))
goto err;
- CRYPTO_THREAD_write_lock(rand_lock);
+
+ locked = private_RAND_lock(1);
/*
* Prevent deadlocks if we end up in an async engine
*/
ASYNC_block_pause();
if (!MD_Update(m, md, MD_DIGEST_LENGTH) || !MD_Final(m, md)) {
ASYNC_unblock_pause();
- CRYPTO_THREAD_unlock(rand_lock);
+ if (locked)
+ private_RAND_lock(0);
goto err;
}
ASYNC_unblock_pause();
- CRYPTO_THREAD_unlock(rand_lock);
+ if (locked)
+ private_RAND_lock(0);
EVP_MD_CTX_free(m);
if (ok)
@@ -541,39 +562,16 @@ static int rand_pseudo_bytes(unsigned char *buf, int num)
static int rand_status(void)
{
- CRYPTO_THREAD_ID cur;
int ret;
- int do_not_lock;
+ int locked;
if (!RUN_ONCE(&rand_lock_init, do_rand_lock_init))
return 0;
- cur = CRYPTO_THREAD_get_current_id();
- /*
- * check if we already have the lock (could happen if a RAND_poll()
- * implementation calls RAND_status())
- */
- if (crypto_lock_rand) {
- CRYPTO_THREAD_read_lock(rand_tmp_lock);
- do_not_lock = CRYPTO_THREAD_compare_id(locking_threadid, cur);
- CRYPTO_THREAD_unlock(rand_tmp_lock);
- } else
- do_not_lock = 0;
-
- if (!do_not_lock) {
- CRYPTO_THREAD_write_lock(rand_lock);
- /*
- * Prevent deadlocks in case we end up in an async engine
- */
- ASYNC_block_pause();
-
- /*
- * prevent rand_bytes() from trying to obtain the lock again
- */
- CRYPTO_THREAD_write_lock(rand_tmp_lock);
- locking_threadid = cur;
- CRYPTO_THREAD_unlock(rand_tmp_lock);
- crypto_lock_rand = 1;
+ locked = private_RAND_lock(1);
+ if (locked)
+ {
+ ASYNC_block_pause();
}
if (!initialized) {
@@ -583,13 +581,11 @@ static int rand_status(void)
ret = entropy >= ENTROPY_NEEDED;
- if (!do_not_lock) {
- /* before unlocking, we must clear 'crypto_lock_rand' */
- crypto_lock_rand = 0;
-
- ASYNC_unblock_pause();
- CRYPTO_THREAD_unlock(rand_lock);
- }
+ if (locked)
+ {
+ ASYNC_unblock_pause();
+ private_RAND_lock(0);
+ }
return ret;
}
diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c
index 84b0cac..9206f36 100644
--- a/crypto/rand/rand_lib.c
+++ b/crypto/rand/rand_lib.c
@@ -293,10 +293,13 @@ static int drbg_rand_add(DRBG_CTX *ctx, const void *in, int inlen,
{
RAND_OpenSSL()->add(in, inlen, entropy);
if (FIPS_rand_status()) {
+ int locked = private_RAND_lock(1);
/* OpenSSL uses the following seeding chain:
* /dev/urandom (via RAND_poll) -> SSLeay MD RNG -> DRBG.
* RAND_Add only updates SSLeay MD, not DRBG (bsc#908372) */
FIPS_drbg_reseed(ctx, in, inlen);
+ if (locked)
+ private_RAND_lock(0);
}
return 1;
}
@@ -305,7 +308,10 @@ static int drbg_rand_seed(DRBG_CTX *ctx, const void *in, int inlen)
{
RAND_OpenSSL()->seed(in, inlen);
if (FIPS_rand_status()) {
+ int locked = private_RAND_lock(1);
FIPS_drbg_reseed(ctx, NULL, 0);
+ if (locked)
+ private_RAND_lock(0);
}
return 1;
}
diff --git a/include/openssl/rand.h b/include/openssl/rand.h
index 6cce6ad..b5991d6 100644
--- a/include/openssl/rand.h
+++ b/include/openssl/rand.h
@@ -72,6 +72,8 @@ void RAND_set_fips_drbg_type(int type, int flags);
int RAND_init_fips(void);
# endif
+int private_RAND_lock(int lock);
+
/* BEGIN ERROR CODES */
/*
* The following lines are auto generated by the script mkerr.pl. Any changes