From 0329eb6523363705946887d4f145dd77c741ae4a Mon Sep 17 00:00:00 2001 From: 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 # include # include +# include +# include 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 +#include #include #include #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 */