File openssl-1_1-serialize-jitterentropy-calls.patch of Package openssl-1_1.31477

---
 crypto/fips/fips_entropy.c |   40 ++++++++++++++++++++++++++++++++++++++--
 1 file changed, 38 insertions(+), 2 deletions(-)

--- a/crypto/fips/fips_entropy.c
+++ b/crypto/fips/fips_entropy.c
@@ -4,35 +4,71 @@
 #include "jitterentropy.h"
 
 static struct rand_data* ec = NULL;
+static CRYPTO_RWLOCK *jent_lock = NULL;
+static int stop = 0;
 
 struct rand_data* FIPS_entropy_init(void)
 {
-    if (ec != NULL)
+    if (ec != NULL) {
         /* Entropy source has been initiated and collector allocated */
         return ec;
+    }
+    if (stop != 0) {
+        /* FIPS_entropy_cleanup() already called, don't initialize it again */
+        return NULL;
+    }
+    if (jent_lock == NULL) {
+        /* Allocates a new lock to serialize access to jent library */
+        jent_lock = CRYPTO_THREAD_lock_new();
+        if (jent_lock == NULL) {
+            return NULL;
+        }
+    }
+    if (CRYPTO_THREAD_write_lock(jent_lock) == 0) {
+        return NULL;
+    }
     /* If the initialization is successful, the call returns with 0 */
     if (jent_entropy_init_ex(1, JENT_FORCE_FIPS) == 0)
         /* Allocate entropy collector */
         ec = jent_entropy_collector_alloc(1, JENT_FORCE_FIPS);
+    CRYPTO_THREAD_unlock(jent_lock);
     return ec;
 }
 
 void FIPS_entropy_cleanup(void)
 {
+    if (jent_lock != NULL && stop == 0) {
+        CRYPTO_THREAD_write_lock(jent_lock);
+    }
+    /* Disable re-initialization in FIPS_entropy_init() */
+    stop = 1;
     /* Free entropy collector */
     if (ec != NULL) {
         jent_entropy_collector_free(ec);
         ec = NULL;
     }
+    CRYPTO_THREAD_lock_free(jent_lock);
+    jent_lock = NULL;
 }
 
 ssize_t FIPS_jitter_entropy(unsigned char *buf, size_t buflen)
 {
     ssize_t ent_bytes = -1;
 
-    if (buf != NULL && buflen != 0 && FIPS_entropy_init()) {
+    /*
+     * Order is important. We need to call FIPS_entropy_init() before we
+     * acquire jent_lock, otherwise it can lead to deadlock. Once we have
+     * jent_lock, we need to ensure that FIPS_entropy_cleanup() was not called
+     * in the meantime. Then it's safe to read entropy.
+     */
+    if (buf != NULL
+        && buflen != 0
+        && FIPS_entropy_init()
+        && CRYPTO_THREAD_write_lock(jent_lock) != 0
+        && stop == 0) {
         /* Get entropy */
         ent_bytes = jent_read_entropy_safe(&ec, (char *)buf, buflen);
+        CRYPTO_THREAD_unlock(jent_lock);
     }
     return ent_bytes;
 }
openSUSE Build Service is sponsored by