From 0e25cdf0be520bcca8e8673e015f938947217d28 Mon Sep 17 00:00:00 2001
From: rpm-build <rpm-build>
Date: Wed, 6 Mar 2024 19:17:16 +0100
Subject: [PATCH 32/59] FIPS: RAND: FIPS-140-3 DRBG - NEEDS REVIEW

providers/implementations/rands/crngt.c is gone

Patch-name: 0076-FIPS-140-3-DRBG.patch
Patch-id: 76
Patch-status: |
    # # Downstream only. Reseed DRBG using getrandom(GRND_RANDOM)
    # # https://bugzilla.redhat.com/show_bug.cgi?id=2102541
From-dist-git-commit: 4334bc837fbc64d14890fdc51679a80770d498ce
---
 crypto/rand/prov_seed.c                       |  9 ++-
 providers/implementations/rands/drbg.c        | 11 ++-
 .../implementations/rands/seeding/rand_unix.c | 68 ++-----------------
 3 files changed, 22 insertions(+), 66 deletions(-)

diff --git a/crypto/rand/prov_seed.c b/crypto/rand/prov_seed.c
index 2985c7f2d8..3202a28226 100644
--- a/crypto/rand/prov_seed.c
+++ b/crypto/rand/prov_seed.c
@@ -23,7 +23,14 @@ size_t ossl_rand_get_entropy(ossl_unused OSSL_LIB_CTX *ctx,
     size_t entropy_available;
     RAND_POOL *pool;
 
-    pool = ossl_rand_pool_new(entropy, 1, min_len, max_len);
+    /*
+     * OpenSSL still implements an internal entropy pool of
+     * some size that is hashed to get seed data.
+     * Note that this is a conditioning step for which SP800-90C requires
+     * 64 additional bits from the entropy source to claim the requested
+     * amount of entropy.
+     */
+    pool = ossl_rand_pool_new(entropy + 64, 1, min_len, max_len);
     if (pool == NULL) {
         ERR_raise(ERR_LIB_RAND, ERR_R_RAND_LIB);
         return 0;
diff --git a/providers/implementations/rands/drbg.c b/providers/implementations/rands/drbg.c
index 4925a3b400..1cdb67b22c 100644
--- a/providers/implementations/rands/drbg.c
+++ b/providers/implementations/rands/drbg.c
@@ -559,6 +559,9 @@ static int ossl_prov_drbg_reseed_unlocked(PROV_DRBG *drbg,
 #endif
     }
 
+#ifdef FIPS_MODULE
+    prediction_resistance = 1;
+#endif
     /* Reseed using our sources in addition */
     entropylen = get_entropy(drbg, &entropy, drbg->strength,
                              drbg->min_entropylen, drbg->max_entropylen,
@@ -680,8 +683,14 @@ int ossl_prov_drbg_generate(PROV_DRBG *drbg, unsigned char *out, size_t outlen,
             reseed_required = 1;
     }
     if (drbg->parent != NULL
-            && get_parent_reseed_count(drbg) != drbg->parent_reseed_counter)
+            && get_parent_reseed_count(drbg) != drbg->parent_reseed_counter) {
+#ifdef FIPS_MODULE
+        /* Red Hat patches provide chain reseeding when necessary so just sync counters*/
+        drbg->parent_reseed_counter = get_parent_reseed_count(drbg);
+#else
         reseed_required = 1;
+#endif
+        }
 
     if (reseed_required || prediction_resistance) {
         if (!ossl_prov_drbg_reseed_unlocked(drbg, prediction_resistance, NULL,
diff --git a/providers/implementations/rands/seeding/rand_unix.c b/providers/implementations/rands/seeding/rand_unix.c
index c3a5d8b3bf..b7b34a9345 100644
--- a/providers/implementations/rands/seeding/rand_unix.c
+++ b/providers/implementations/rands/seeding/rand_unix.c
@@ -53,6 +53,8 @@
 # include <fcntl.h>
 # include <unistd.h>
 # include <sys/time.h>
+# include <sys/random.h>
+# include <openssl/evp.h>
 
 static uint64_t get_time_stamp(void);
 
@@ -339,70 +341,8 @@ static ssize_t syscall_random(void *buf, size_t buflen)
      * which is way below the OSSL_SSIZE_MAX limit. Therefore sign conversion
      * between size_t and ssize_t is safe even without a range check.
      */
-
-    /*
-     * Do runtime detection to find getentropy().
-     *
-     * Known OSs that should support this:
-     * - Darwin since 16 (OSX 10.12, IOS 10.0).
-     * - Solaris since 11.3
-     * - OpenBSD since 5.6
-     * - Linux since 3.17 with glibc 2.25
-     *
-     * Note: Sometimes getentropy() can be provided but not implemented
-     * internally. So we need to check errno for ENOSYS
-     */
-#  if !defined(__DragonFly__) && !defined(__NetBSD__) && !defined(__FreeBSD__)
-#    if defined(__GNUC__) && __GNUC__>=2 && defined(__ELF__) && !defined(__hpux)
-    extern int getentropy(void *buffer, size_t length) __attribute__((weak));
-
-    if (getentropy != NULL) {
-        if (getentropy(buf, buflen) == 0)
-            return (ssize_t)buflen;
-        if (errno != ENOSYS)
-            return -1;
-    }
-#    elif defined(OPENSSL_APPLE_CRYPTO_RANDOM)
-
-    if (CCRandomGenerateBytes(buf, buflen) == kCCSuccess)
-	    return (ssize_t)buflen;
-
-    return -1;
-#    else
-    union {
-        void *p;
-        int (*f)(void *buffer, size_t length);
-    } p_getentropy;
-
-    /*
-     * We could cache the result of the lookup, but we normally don't
-     * call this function often.
-     */
-    ERR_set_mark();
-    p_getentropy.p = DSO_global_lookup("getentropy");
-    ERR_pop_to_mark();
-    if (p_getentropy.p != NULL)
-        return p_getentropy.f(buf, buflen) == 0 ? (ssize_t)buflen : -1;
-#    endif
-#  endif /* !__DragonFly__ && !__NetBSD__ && !__FreeBSD__ */
-
-    /* Linux supports this since version 3.17 */
-#  if defined(__linux) && defined(__NR_getrandom)
-    return syscall(__NR_getrandom, buf, buflen, 0);
-#  elif (defined(__DragonFly__)  && __DragonFly_version >= 500700) \
-     || (defined(__NetBSD__) && __NetBSD_Version >= 1000000000) \
-     || (defined(__FreeBSD__) && __FreeBSD_version >= 1200061)
-    return getrandom(buf, buflen, 0);
-#  elif (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(KERN_ARND)
-    return sysctl_random(buf, buflen);
-#  elif defined(__wasi__)
-    if (getentropy(buf, buflen) == 0)
-      return (ssize_t)buflen;
-    return -1;
-#  else
-    errno = ENOSYS;
-    return -1;
-#  endif
+    /* Red Hat uses downstream patch to always seed from getrandom() */
+    return EVP_default_properties_is_fips_enabled(NULL) ? getrandom(buf, buflen, GRND_RANDOM) : getrandom(buf, buflen, 0);
 }
 #  endif    /* defined(OPENSSL_RAND_SEED_GETRANDOM) */
 
-- 
2.51.0

