Index: openssl-3.1.4/Configurations/00-base-templates.conf =================================================================== --- openssl-3.1.4.orig/Configurations/00-base-templates.conf +++ openssl-3.1.4/Configurations/00-base-templates.conf @@ -71,9 +71,12 @@ my %targets=( lflags => sub { $withargs{zlib_lib} ? "-L".$withargs{zlib_lib} : () }, ex_libs => - sub { !defined($disabled{zlib}) - && defined($disabled{"zlib-dynamic"}) - ? "-lz" : () }, + sub { + my @libs = (); + push(@libs, "-lz") if !defined($disabled{zlib}) && defined($disabled{"zlib-dynamic"}); + push(@libs, "-ljitterentropy") if !defined($disabled{jitterentropy}); + return join(" ", @libs); + }, HASHBANGPERL => "/usr/bin/env perl", # Only Unix actually cares RANLIB => sub { which("$config{cross_compile_prefix}ranlib") ? "ranlib" : "" }, Index: openssl-3.1.4/crypto/rand/rand_jitter_entropy.c =================================================================== --- /dev/null +++ openssl-3.1.4/crypto/rand/rand_jitter_entropy.c @@ -0,0 +1,97 @@ +# include "jitterentropy.h" +# include "prov/jitter_entropy.h" + +struct rand_data* ec = NULL; +CRYPTO_RWLOCK *jent_lock = NULL; +int stop = 0; + +struct rand_data* FIPS_entropy_init(void) +{ + 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); + } else { + /* abort if jitter rng fails initialization */ + abort(); + } + if (ec == NULL) { + /* abort if jitter rng fails initialization */ + abort(); + } + CRYPTO_THREAD_unlock(jent_lock); + + return ec; +} + +/* + * The following error codes can be returned by jent_read_entropy_safe(): + * -1 entropy_collector is NULL + * -2 RCT failed + * -3 APT failed + * -4 The timer cannot be initialized + * -5 LAG failure + * -6 RCT permanent failure + * -7 APT permanent failure + * -8 LAG permanent failure + */ +ssize_t FIPS_jitter_entropy(unsigned char *buf, size_t buflen) +{ + ssize_t ent_bytes = -1; + + /* + * 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); + if (ent_bytes < 0) { + /* abort if jitter rng fails entropy gathering because health tests failed. */ + abort(); + } + CRYPTO_THREAD_unlock(jent_lock); + } + + return ent_bytes; +} + +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; +} Index: openssl-3.1.4/providers/implementations/rands/seeding/rand_unix.c =================================================================== --- openssl-3.1.4.orig/providers/implementations/rands/seeding/rand_unix.c +++ openssl-3.1.4/providers/implementations/rands/seeding/rand_unix.c @@ -20,6 +20,7 @@ #include "internal/dso.h" #include "internal/nelem.h" #include "prov/seeding.h" +#include "prov/jitter_entropy.h" #ifdef __linux # include @@ -631,6 +632,31 @@ size_t ossl_pool_acquire_entropy(RAND_PO (void)entropy_available; /* avoid compiler warning */ + /* Use jitter entropy in FIPS mode */ + if (EVP_default_properties_is_fips_enabled(NULL)) + { + size_t bytes_needed; + unsigned char *buffer; + ssize_t bytes; + /* Maximum allowed number of consecutive unsuccessful attempts */ + int attempts = 3; + + bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); + while (bytes_needed != 0 && attempts-- > 0) { + buffer = ossl_rand_pool_add_begin(pool, bytes_needed); + bytes = FIPS_jitter_entropy(buffer, bytes_needed); + if (bytes > 0) { + ossl_rand_pool_add_end(pool, bytes, 8 * bytes); + bytes_needed -= bytes; + attempts = 3; /* reset counter after successful attempt */ + } else if (bytes < 0) { + break; + } + } + entropy_available = ossl_rand_pool_entropy_available(pool); + return entropy_available; + } + # if defined(OPENSSL_RAND_SEED_GETRANDOM) { size_t bytes_needed; Index: openssl-3.1.4/providers/implementations/include/prov/jitter_entropy.h =================================================================== --- /dev/null +++ openssl-3.1.4/providers/implementations/include/prov/jitter_entropy.h @@ -0,0 +1,17 @@ +#ifndef OSSL_PROVIDERS_JITTER_ENTROPY_H +# define OSSL_PROVIDERS_JITTER_ENTROPY_H + +# include +# include +# include +# include + +extern struct rand_data* ec; +extern CRYPTO_RWLOCK *jent_lock; +extern int stop; + +struct rand_data* FIPS_entropy_init(void); +ssize_t FIPS_jitter_entropy(unsigned char *buf, size_t buflen); +void FIPS_entropy_cleanup(void); + +#endif Index: openssl-3.1.4/providers/fips/self_test.c =================================================================== --- openssl-3.1.4.orig/providers/fips/self_test.c +++ openssl-3.1.4/providers/fips/self_test.c @@ -20,6 +20,7 @@ #include "internal/tsan_assist.h" #include "prov/providercommon.h" #include "crypto/rand.h" +#include "prov/jitter_entropy.h" /* * We're cheating here. Normally we don't allow RUN_ONCE usage inside the FIPS @@ -392,6 +393,11 @@ int SELF_TEST_post(SELF_TEST_POST_PARAMS return 0; } + if (!FIPS_entropy_init()) { + ERR_raise(ERR_LIB_PROV, PROV_R_FIPS_ENTROPY_INIT_FAILED); + goto end; + } + if (st == NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_CONFIG_DATA); goto end; Index: openssl-3.1.4/include/openssl/proverr.h =================================================================== --- openssl-3.1.4.orig/include/openssl/proverr.h +++ openssl-3.1.4/include/openssl/proverr.h @@ -44,6 +44,7 @@ # define PROV_R_FAILED_TO_GET_PARAMETER 103 # define PROV_R_FAILED_TO_SET_PARAMETER 104 # define PROV_R_FAILED_TO_SIGN 175 +# define PROV_R_FIPS_ENTROPY_INIT_FAILED 234 # define PROV_R_FIPS_MODULE_CONDITIONAL_ERROR 227 # define PROV_R_FIPS_MODULE_ENTERING_ERROR_STATE 224 # define PROV_R_FIPS_MODULE_IN_ERROR_STATE 225 Index: openssl-3.1.4/providers/common/provider_err.c =================================================================== --- openssl-3.1.4.orig/providers/common/provider_err.c +++ openssl-3.1.4/providers/common/provider_err.c @@ -54,6 +54,8 @@ static const ERR_STRING_DATA PROV_str_re {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_FAILED_TO_SET_PARAMETER), "failed to set parameter"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_FAILED_TO_SIGN), "failed to sign"}, + {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_FIPS_ENTROPY_INIT_FAILED), + "fips module jitter entropy init failed"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_FIPS_MODULE_CONDITIONAL_ERROR), "fips module conditional error"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_FIPS_MODULE_ENTERING_ERROR_STATE), Index: openssl-3.1.4/crypto/rand/build.info =================================================================== --- openssl-3.1.4.orig/crypto/rand/build.info +++ openssl-3.1.4/crypto/rand/build.info @@ -1,6 +1,6 @@ LIBS=../../libcrypto -$COMMON=rand_lib.c +$COMMON=rand_lib.c rand_jitter_entropy.c $CRYPTO=randfile.c rand_err.c rand_deprecated.c prov_seed.c rand_pool.c IF[{- !$disabled{'egd'} -}] Index: openssl-3.1.4/providers/fips/fipsprov.c =================================================================== --- openssl-3.1.4.orig/providers/fips/fipsprov.c +++ openssl-3.1.4/providers/fips/fipsprov.c @@ -27,6 +27,7 @@ #include "crypto/context.h" #include "internal/core.h" #include "indicator.h" +#include "prov/jitter_entropy.h" static const char FIPS_DEFAULT_PROPERTIES[] = "provider=fips,fips=yes"; static const char FIPS_UNAPPROVED_PROPERTIES[] = "provider=fips,fips=no"; @@ -603,6 +604,7 @@ const OSSL_SUSE_FIPSINDICATOR_ALGORITHM static void fips_teardown(void *provctx) { + FIPS_entropy_cleanup(); OSSL_LIB_CTX_free(PROV_LIBCTX_OF(provctx)); ossl_prov_ctx_free(provctx); } Index: openssl-3.1.4/util/libcrypto.num =================================================================== --- openssl-3.1.4.orig/util/libcrypto.num +++ openssl-3.1.4/util/libcrypto.num @@ -5441,3 +5441,5 @@ X509_get_default_cert_path_env ossl_safe_getenv ? 3_0_0 EXIST::FUNCTION: ossl_ctx_legacy_digest_signatures_allowed ? 3_0_1 EXIST::FUNCTION: ossl_ctx_legacy_digest_signatures_allowed_set ? 3_0_1 EXIST::FUNCTION: +FIPS_entropy_init ? 3_1_4 EXIST::FUNCTION: +FIPS_entropy_cleanup ? 3_1_4 EXIST::FUNCTION: Index: openssl-3.1.4/Configure =================================================================== --- openssl-3.1.4.orig/Configure +++ openssl-3.1.4/Configure @@ -454,6 +454,7 @@ my @disablables = ( "fuzz-libfuzzer", "gost", "idea", + "jitterentropy", "ktls", "legacy", "loadereng", @@ -550,6 +551,7 @@ our %disabled = ( # "what" => "c "external-tests" => "default", "fuzz-afl" => "default", "fuzz-libfuzzer" => "default", + "jitterentropy" => "default", "ktls" => "default", "md2" => "default", "msan" => "default", @@ -763,7 +765,7 @@ my %cmdvars = (); # Stores my %unsupported_options = (); my %deprecated_options = (); # If you change this, update apps/version.c -my @known_seed_sources = qw(getrandom devrandom os egd none rdcpu librandom); +my @known_seed_sources = qw(getrandom devrandom os egd none rdcpu librandom jitterentropy); my @seed_sources = (); while (@argvcopy) { @@ -1231,6 +1233,9 @@ if (scalar(@seed_sources) == 0) { if (scalar(grep { $_ eq 'egd' } @seed_sources) > 0) { delete $disabled{'egd'}; } +if (scalar(grep { $_ eq 'jitterentropy' } @seed_sources) > 0) { + delete $disabled{'jitterentropy'}; +} if (scalar(grep { $_ eq 'none' } @seed_sources) > 0) { die "Cannot seed with none and anything else" if scalar(@seed_sources) > 1; warn <<_____ if scalar(@seed_sources) == 1; Index: openssl-3.1.4/crypto/info.c =================================================================== --- openssl-3.1.4.orig/crypto/info.c +++ openssl-3.1.4/crypto/info.c @@ -15,6 +15,9 @@ #include "internal/e_os.h" #include "buildinf.h" +# include +# include + #if defined(__arm__) || defined(__arm) || defined(__aarch64__) # include "arm_arch.h" # define CPU_INFO_STR_LEN 128 @@ -128,6 +131,14 @@ DEFINE_RUN_ONCE_STATIC(init_info_strings OPENSSL_strlcat(seeds, ")", sizeof(seeds)); \ } while (0) + /* In FIPS mode, only jitterentropy is used for seeding and + * reseeding the primary DRBG. + */ + if (EVP_default_properties_is_fips_enabled(NULL)) { + char jent_version_string[32]; + sprintf(jent_version_string, "jitterentropy (%d)", jent_version()); + add_seeds_string(jent_version_string); + } else { #ifdef OPENSSL_RAND_SEED_NONE add_seeds_string("none"); #endif @@ -156,6 +167,7 @@ DEFINE_RUN_ONCE_STATIC(init_info_strings #ifdef OPENSSL_RAND_SEED_OS add_seeds_string("os-specific"); #endif + } seed_sources = seeds; } return 1; Index: openssl-3.1.4/INSTALL.md =================================================================== --- openssl-3.1.4.orig/INSTALL.md +++ openssl-3.1.4/INSTALL.md @@ -463,6 +463,12 @@ if provided by the CPU. Use librandom (not implemented yet). This source is ignored by the FIPS provider. +### jitterentropy + +Use [jitterentropy-library](https://github.com/smuellerDD/jitterentropy-library) +dynamically linked. In FIPS mode, only the jitter RNG is used to seed and reseed +the primary DRBG. + ### none Disable automatic seeding. This is the default on some operating systems where