File openssl-fipslocking.patch of Package openssl-1_1.14217

Index: openssl-1.1.0i/crypto/fips/fips_drbg_rand.c
===================================================================
--- openssl-1.1.0i.orig/crypto/fips/fips_drbg_rand.c
+++ openssl-1.1.0i/crypto/fips/fips_drbg_rand.c
@@ -95,7 +95,8 @@ static int fips_drbg_bytes(unsigned char
     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, 0);
     do {
         size_t rcnt;
         if (count > (int)dctx->max_request)
@@ -124,7 +125,8 @@ static int fips_drbg_bytes(unsigned char
     while (count);
     rv = 1;
  err:
-    CRYPTO_THREAD_unlock(fips_rand_lock);
+    if (locked)
+      private_RAND_lock(0, 0);
     return rv;
 }
 
@@ -139,39 +141,47 @@ 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, 0);
     rv = dctx->status == DRBG_STATUS_READY ? 1 : 0;
-    CRYPTO_THREAD_unlock(fips_rand_lock);
+    if (locked)
+      private_RAND_lock(0, 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, 0);
     FIPS_drbg_uninstantiate(dctx);
-    CRYPTO_THREAD_unlock(fips_rand_lock);
+    if (locked)
+      private_RAND_lock(0, 0);
 }
 
 static int fips_drbg_seed(const void *seed, int seedlen)
 {
     DRBG_CTX *dctx = &ossl_dctx;
+    int locked;
     int ret = 1;
-    CRYPTO_THREAD_write_lock(fips_rand_lock);
+    locked = private_RAND_lock(1, 0);
     if (dctx->rand_seed_cb)
-        ret = dctx->rand_seed_cb(dctx, seed, seedlen);
-    CRYPTO_THREAD_unlock(fips_rand_lock);
+      ret = dctx->rand_seed_cb(dctx, seed, seedlen);
+    if (locked)
+      private_RAND_lock(0, 0);
     return ret;
 }
 
 static int fips_drbg_add(const void *seed, int seedlen, double add_entropy)
 {
     DRBG_CTX *dctx = &ossl_dctx;
+    int locked;
     int ret = 1;
-    CRYPTO_THREAD_write_lock(fips_rand_lock);
+    locked = private_RAND_lock(1, 0);
     if (dctx->rand_add_cb)
-        ret = dctx->rand_add_cb(dctx, seed, seedlen, add_entropy);
-    CRYPTO_THREAD_unlock(fips_rand_lock);
+      ret = dctx->rand_add_cb(dctx, seed, seedlen, add_entropy);
+    if (locked)
+      private_RAND_lock(0, 0);
     return ret;
 }
 
Index: openssl-1.1.0i/crypto/rand/md_rand.c
===================================================================
--- openssl-1.1.0i.orig/crypto/rand/md_rand.c
+++ openssl-1.1.0i/crypto/rand/md_rand.c
@@ -100,6 +100,43 @@ RAND_METHOD *RAND_OpenSSL(void)
     return (&rand_meth);
 }
 
+int private_RAND_lock(int lock, int check_ASYNC_up)
+{
+  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 deadlocks if we end up in an async engine */
+    if (check_ASYNC_up)
+      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;
+  }
+  return do_lock;
+}
+
 static void rand_cleanup(void)
 {
     OPENSSL_cleanse(state, sizeof(state));
@@ -120,7 +157,7 @@ static int rand_add(const void *buf, int
     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 +185,8 @@ static int rand_add(const void *buf, int
     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;
+    locked = private_RAND_lock(1, 0);
 
-    if (!do_not_lock)
-        CRYPTO_THREAD_write_lock(rand_lock);
     st_idx = state_index;
 
     /*
@@ -189,8 +217,8 @@ static int rand_add(const void *buf, int
 
     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, 0);
 
     for (i = 0; i < num; i += MD_DIGEST_LENGTH) {
         j = (num - i);
@@ -243,8 +271,7 @@ static int rand_add(const void *buf, int
         }
     }
 
-    if (!do_not_lock)
-        CRYPTO_THREAD_write_lock(rand_lock);
+    locked = private_RAND_lock(1, 0);
     /*
      * 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 +283,8 @@ static int rand_add(const void *buf, int
     }
     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, 0);
 
     rv = 1;
  err:
@@ -284,6 +311,7 @@ static int rand_bytes(unsigned char *buf
 #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,7 +378,7 @@ static int rand_bytes(unsigned char *buf
     if (!RUN_ONCE(&rand_lock_init, do_rand_lock_init))
         goto err_mem;
 
-    CRYPTO_THREAD_write_lock(rand_lock);
+    locked = private_RAND_lock(1, 0);
     /*
      * We could end up in an async engine while holding this lock so ensure
      * we don't pause and cause a deadlock
@@ -358,9 +386,10 @@ static int rand_bytes(unsigned char *buf
     ASYNC_block_pause();
 
     /* prevent rand_bytes() from trying to obtain the lock again */
-    CRYPTO_THREAD_write_lock(rand_tmp_lock);
+    locked = private_RAND_lock(1, 0);
     locking_threadid = CRYPTO_THREAD_get_current_id();
-    CRYPTO_THREAD_unlock(rand_tmp_lock);
+    if (locked)
+      private_RAND_lock(0, 0);
     crypto_lock_rand = 1;
 
     if (!initialized || FIPS_mode()) {
@@ -433,9 +462,10 @@ static int rand_bytes(unsigned char *buf
     md_count[0] += 1;
 
     /* before unlocking, we must clear 'crypto_lock_rand' */
-    crypto_lock_rand = 0;
+    //crypto_lock_rand = 0;
     ASYNC_unblock_pause();
-    CRYPTO_THREAD_unlock(rand_lock);
+    if (locked)
+      private_RAND_lock(0, 0);
 
     while (num > 0) {
         /* num_ceil -= MD_DIGEST_LENGTH/2 */
@@ -489,18 +519,19 @@ static int rand_bytes(unsigned char *buf
         || !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, 0);
     /*
      * 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);
+	locked = private_RAND_lock(0, 1);
         goto err;
     }
     ASYNC_unblock_pause();
-    CRYPTO_THREAD_unlock(rand_lock);
+    if (locked)
+      private_RAND_lock(0, 0);
 
     EVP_MD_CTX_free(m);
     if (ok)
@@ -541,40 +572,13 @@ static int rand_pseudo_bytes(unsigned ch
 
 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, 1);
 
     if (!initialized) {
         RAND_poll();
@@ -583,13 +587,13 @@ 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)
+    {
+      /* before unlocking, we must clear 'crypto_lock_rand' */
+      //crypto_lock_rand = 0;
+      ASYNC_unblock_pause();
+      private_RAND_lock(0, 0);
+     }
 
     return ret;
 }
Index: openssl-1.1.0i/crypto/rand/rand_lib.c
===================================================================
--- openssl-1.1.0i.orig/crypto/rand/rand_lib.c
+++ openssl-1.1.0i/crypto/rand/rand_lib.c
@@ -293,10 +293,13 @@ static int drbg_rand_add(DRBG_CTX *ctx,
 {
     RAND_OpenSSL()->add(in, inlen, entropy);
     if (FIPS_rand_status()) {
+        int locked = private_RAND_lock(1, 0);
         /* 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, 0);
     }
     return 1;
 }
@@ -305,7 +308,10 @@ static int drbg_rand_seed(DRBG_CTX *ctx,
 {
     RAND_OpenSSL()->seed(in, inlen);
     if (FIPS_rand_status()) {
+	int locked = private_RAND_lock(1, 0);
         FIPS_drbg_reseed(ctx, NULL, 0);
+	if (locked)
+	  private_RAND_lock(0, 0);
     }
     return 1;
 }
Index: openssl-1.1.0i/include/openssl/rand.h
===================================================================
--- openssl-1.1.0i.orig/include/openssl/rand.h
+++ openssl-1.1.0i/include/openssl/rand.h
@@ -72,6 +72,8 @@ void RAND_set_fips_drbg_type(int type, i
 int RAND_init_fips(void);
 # endif
 
+int private_RAND_lock(int lock, int check_ASYNC_up);
+
 /* BEGIN ERROR CODES */
 /*
  * The following lines are auto generated by the script mkerr.pl. Any changes
openSUSE Build Service is sponsored by