openssl/0076-FIPS-140-3-DRBG.patch

318 lines
13 KiB
Diff
Raw Normal View History

From 0329eb6523363705946887d4f145dd77c741ae4a Mon Sep 17 00:00:00 2001
From: rpm-build <rpm-build>
Date: Wed, 6 Mar 2024 19:17:16 +0100
Subject: [PATCH 30/49] 0076-FIPS-140-3-DRBG.patch
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/crngt.c | 6 +-
providers/implementations/rands/drbg.c | 11 ++-
providers/implementations/rands/drbg_local.h | 2 +-
.../implementations/rands/seeding/rand_unix.c | 68 ++-----------------
5 files changed, 28 insertions(+), 68 deletions(-)
diff -up openssl-3.0.1/crypto/rand/prov_seed.c.fipsrand openssl-3.0.1/crypto/rand/prov_seed.c
--- openssl-3.0.1/crypto/rand/prov_seed.c.fipsrand 2022-08-04 12:17:52.148556301 +0200
+++ openssl-3.0.1/crypto/rand/prov_seed.c 2022-08-04 12:19:41.783533552 +0200
@@ -20,7 +20,14 @@ size_t ossl_rand_get_entropy(ossl_unused
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 -up openssl-3.0.1/providers/implementations/rands/crngt.c.fipsrand openssl-3.0.1/providers/implementations/rands/crngt.c
--- openssl-3.0.1/providers/implementations/rands/crngt.c.fipsrand 2022-08-04 11:56:10.100950299 +0200
+++ openssl-3.0.1/providers/implementations/rands/crngt.c 2022-08-04 11:59:11.241564925 +0200
@@ -139,7 +139,11 @@ size_t ossl_crngt_get_entropy(PROV_DRBG
* to the nearest byte. If the entropy is of less than full quality,
* the amount required should be scaled up appropriately here.
*/
- bytes_needed = (entropy + 7) / 8;
+ /*
+ * FIPS 140-3: the yet draft SP800-90C requires requested entropy
+ * + 128 bits during initial seeding
+ */
+ bytes_needed = (entropy + 128 + 7) / 8;
if (bytes_needed < min_len)
bytes_needed = min_len;
if (bytes_needed > max_len)
diff -up openssl-3.0.1/providers/implementations/rands/drbg.c.fipsrand openssl-3.0.1/providers/implementations/rands/drbg.c
--- openssl-3.0.1/providers/implementations/rands/drbg.c.fipsrand 2022-08-03 12:14:39.409370134 +0200
+++ openssl-3.0.1/providers/implementations/rands/drbg.c 2022-08-03 12:19:06.320700346 +0200
@@ -575,6 +575,9 @@ int ossl_prov_drbg_reseed(PROV_DRBG *drb
#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,
@@ -669,8 +669,14 @@ int ossl_prov_drbg_generate(PROV_DRBG *d
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 -up openssl-3.0.7/providers/implementations/rands/drbg_local.h.drbg openssl-3.0.7/providers/implementations/rands/drbg_local.h
--- openssl-3.0.7/providers/implementations/rands/drbg_local.h.drbg 2023-03-13 12:17:47.705538612 +0100
+++ openssl-3.0.7/providers/implementations/rands/drbg_local.h 2023-03-13 12:18:03.060702092 +0100
@@ -38,7 +38,7 @@
*
* The value is in bytes.
*/
-#define CRNGT_BUFSIZ 16
+#define CRNGT_BUFSIZ 32
/*
* Maximum input size for the DRBG (entropy, nonce, personalization string)
diff -up openssl-3.0.1/providers/implementations/rands/seeding/rand_unix.c.fipsrand openssl-3.0.1/providers/implementations/rands/seeding/rand_unix.c
--- openssl-3.0.1/providers/implementations/rands/seeding/rand_unix.c.fipsrand 2022-08-03 11:09:01.301637515 +0200
+++ openssl-3.0.1/providers/implementations/rands/seeding/rand_unix.c 2022-08-03 11:13:00.058688605 +0200
@@ -48,6 +48,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
- * - FreeBSD since 12.0 (1200061)
- *
- * Note: Sometimes getentropy() can be provided but not implemented
- * internally. So we need to check errno for ENOSYS
- */
-# if !defined(__DragonFly__) && !defined(__NetBSD__)
-# 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__ */
-
- /* Linux supports this since version 3.17 */
-# if defined(__linux) && defined(__NR_getrandom)
- return syscall(__NR_getrandom, buf, buflen, 0);
-# elif (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(KERN_ARND)
- return sysctl_random(buf, buflen);
-# elif (defined(__DragonFly__) && __DragonFly_version >= 500700) \
- || (defined(__NetBSD__) && __NetBSD_Version >= 1000000000)
- return getrandom(buf, buflen, 0);
-# elif defined(__wasi__)
- if (getentropy(buf, buflen) == 0)
- return (ssize_t)buflen;
- return -1;
-# else
- errno = ENOSYS;
- return -1;
-# endif
+ int realbuflen = buflen > 32 ? 32 : buflen; /* Red Hat uses downstream patch to always seed from getrandom() */
+ return EVP_default_properties_is_fips_enabled(NULL) ? getrandom(buf, realbuflen, GRND_RANDOM) : getrandom(buf, buflen, 0);
}
# endif /* defined(OPENSSL_RAND_SEED_GETRANDOM) */
diff -up openssl-3.2.1/providers/implementations/rands/seed_src.c.xxx openssl-3.2.1/providers/implementations/rands/seed_src.c
--- openssl-3.2.1/providers/implementations/rands/seed_src.c.xxx 2024-04-10 13:14:38.984033920 +0200
+++ openssl-3.2.1/providers/implementations/rands/seed_src.c 2024-04-10 13:15:20.565045748 +0200
@@ -102,7 +102,14 @@ static int seed_src_generate(void *vseed
return 0;
}
- pool = ossl_rand_pool_new(strength, 1, outlen, outlen);
+ /*
+ * 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(strength + 64, 1, outlen, outlen);
if (pool == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_RAND_LIB);
return 0;
@@ -189,7 +189,14 @@ static size_t seed_get_seed(void *vseed,
size_t i;
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_PROV, ERR_R_RAND_LIB);
return 0;
diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c
index 14999540ab..b05b84717b 100644
--- a/crypto/rand/rand_lib.c
+++ b/crypto/rand/rand_lib.c
@@ -11,6 +11,7 @@
#define OPENSSL_SUPPRESS_DEPRECATED
#include <openssl/err.h>
+#include <openssl/evp.h>
#include <openssl/opensslconf.h>
#include <openssl/core_names.h>
#include "internal/cryptlib.h"
@@ -723,15 +723,7 @@ EVP_RAND_CTX *RAND_get0_primary(OSSL_LIB_CTX *ctx)
return ret;
}
-#ifndef FIPS_MODULE
- if (dgbl->seed == NULL) {
- ERR_set_mark();
- dgbl->seed = rand_new_seed(ctx);
- ERR_pop_to_mark();
- }
-#endif
-
- ret = dgbl->primary = rand_new_drbg(ctx, dgbl->seed,
+ ret = dgbl->primary = rand_new_drbg(ctx, NULL,
PRIMARY_RESEED_INTERVAL,
PRIMARY_RESEED_TIME_INTERVAL, 1);
/*
@@ -766,7 +766,7 @@ EVP_RAND_CTX *RAND_get0_public(OSSL_LIB_
if (CRYPTO_THREAD_get_local(&dgbl->private) == NULL
&& !ossl_init_thread_start(NULL, ctx, rand_delete_thread_state))
return NULL;
- rand = rand_new_drbg(ctx, primary, SECONDARY_RESEED_INTERVAL,
+ rand = rand_new_drbg(ctx, NULL, SECONDARY_RESEED_INTERVAL,
SECONDARY_RESEED_TIME_INTERVAL, 0);
CRYPTO_THREAD_set_local(&dgbl->public, rand);
}
@@ -799,7 +799,7 @@ EVP_RAND_CTX *RAND_get0_private(OSSL_LIB
if (CRYPTO_THREAD_get_local(&dgbl->public) == NULL
&& !ossl_init_thread_start(NULL, ctx, rand_delete_thread_state))
return NULL;
- rand = rand_new_drbg(ctx, primary, SECONDARY_RESEED_INTERVAL,
+ rand = rand_new_drbg(ctx, NULL, SECONDARY_RESEED_INTERVAL,
SECONDARY_RESEED_TIME_INTERVAL, 0);
CRYPTO_THREAD_set_local(&dgbl->private, rand);
}
diff -up openssl-3.2.1/test/drbgtest.c.xxx openssl-3.2.1/test/drbgtest.c
--- openssl-3.2.1/test/drbgtest.c.xxx 2024-05-02 15:37:23.550979597 +0200
+++ openssl-3.2.1/test/drbgtest.c 2024-05-02 15:45:37.189979881 +0200
@@ -218,7 +218,7 @@ static int test_drbg_reseed(int expect_s
reseed_when = time(NULL);
/* Generate random output from the public and private DRBG */
- before_reseed = expect_primary_reseed == 1 ? reseed_when : 0;
+ before_reseed = 0;
if (!TEST_int_eq(rand_bytes((unsigned char*)public_random,
RANDOM_SIZE), expect_success)
|| !TEST_int_eq(rand_priv_bytes((unsigned char*) private_random,
@@ -232,8 +232,8 @@ static int test_drbg_reseed(int expect_s
*/
/* Test whether reseeding succeeded as expected */
- if (!TEST_int_eq(state(primary), expected_state)
- || !TEST_int_eq(state(public), expected_state)
+ if (/*!TEST_int_eq(state(primary), expected_state)
+ ||*/ !TEST_int_eq(state(public), expected_state)
|| !TEST_int_eq(state(private), expected_state))
return 0;
@@ -246,16 +246,16 @@ static int test_drbg_reseed(int expect_s
if (expect_public_reseed >= 0) {
/* Test whether public DRBG was reseeded as expected */
if (!TEST_int_ge(reseed_counter(public), public_reseed)
- || !TEST_uint_ge(reseed_counter(public),
- reseed_counter(primary)))
+ /*|| !TEST_uint_ge(reseed_counter(public),
+ reseed_counter(primary))*/)
return 0;
}
if (expect_private_reseed >= 0) {
/* Test whether public DRBG was reseeded as expected */
if (!TEST_int_ge(reseed_counter(private), private_reseed)
- || !TEST_uint_ge(reseed_counter(private),
- reseed_counter(primary)))
+ /*|| !TEST_uint_ge(reseed_counter(private),
+ reseed_counter(primary))*/)
return 0;
}
@@ -577,8 +577,8 @@ static int test_rand_reseed(void)
if (!TEST_ptr_ne(public, private)
|| !TEST_ptr_ne(public, primary)
|| !TEST_ptr_ne(private, primary)
- || !TEST_ptr_eq(prov_rand(public)->parent, prov_rand(primary))
- || !TEST_ptr_eq(prov_rand(private)->parent, prov_rand(primary)))
+ /*|| !TEST_ptr_eq(prov_rand(public)->parent, prov_rand(primary))
+ || !TEST_ptr_eq(prov_rand(private)->parent, prov_rand(primary))*/)
return 0;
/* Disable CRNG testing for the primary DRBG */