--- Configurations/00-base-templates.conf | 2 - crypto/fips/build.info | 3 +- crypto/fips/fips.c | 8 +++++++ crypto/fips/fips_entropy.c | 38 ++++++++++++++++++++++++++++++++++ crypto/fips/fips_err.h | 1 crypto/init.c | 4 +++ crypto/rand/rand_unix.c | 30 +++++++++++++++++++++++++- include/crypto/fips_int.h | 2 + include/openssl/fips.h | 4 +++ util/libcrypto.num | 2 + 10 files changed, 91 insertions(+), 3 deletions(-) --- a/Configurations/00-base-templates.conf +++ b/Configurations/00-base-templates.conf @@ -96,7 +96,7 @@ my %targets=( ex_libs => sub { !defined($disabled{zlib}) && defined($disabled{"zlib-dynamic"}) - ? "-lz" : () }, + ? "-lz -ljitterentropy" : "-ljitterentropy" }, HASHBANGPERL => "/usr/bin/env perl", # Only Unix actually cares RANLIB => sub { which("$config{cross_compile_prefix}ranlib") ? "ranlib" : "" }, --- a/crypto/fips/build.info +++ b/crypto/fips/build.info @@ -5,7 +5,8 @@ SOURCE[../../libcrypto]=\ fips_post.c drbgtest.c fips_drbg_ctr.c fips_drbg_hash.c fips_drbg_hmac.c \ fips_drbg_lib.c fips_drbg_rand.c fips_drbg_selftest.c fips_rand_lib.c \ fips_cmac_selftest.c fips_ecdh_selftest.c fips_ecdsa_selftest.c \ - fips_dh_selftest.c fips_kdf_selftest.c fips_ers.c fips_sli.c + fips_dh_selftest.c fips_kdf_selftest.c fips_ers.c fips_sli.c \ + fips_entropy.c PROGRAMS=\ fips_standalone_hmac --- a/crypto/fips/fips.c +++ b/crypto/fips/fips.c @@ -461,6 +461,14 @@ int FIPS_module_mode_set(int onoff) fips_post = 1; + if (!FIPS_entropy_init()) { + FIPSerr(FIPS_F_FIPS_MODULE_MODE_SET, + FIPS_R_ENTROPY_INIT_FAILED); + fips_selftest_fail = 1; + ret = 0; + goto end; + } + /* Run the KATs before the HMAC verification for FIPS 140-3 compliance */ if (!FIPS_selftest()) { fips_selftest_fail = 1; --- /dev/null +++ b/crypto/fips/fips_entropy.c @@ -0,0 +1,38 @@ +#include + +#include "crypto/fips_int.h" +#include "jitterentropy.h" + +static struct rand_data* ec = NULL; + +struct rand_data* FIPS_entropy_init(void) +{ + if (ec != NULL) + /* Entropy source has been initiated and collector allocated */ + return ec; + /* 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); + return ec; +} + +void FIPS_entropy_cleanup(void) +{ + /* Free entropy collector */ + if (ec != NULL) { + jent_entropy_collector_free(ec); + ec = NULL; + } +} + +ssize_t FIPS_jitter_entropy(unsigned char *buf, size_t buflen) +{ + ssize_t ent_bytes = -1; + + if (buf != NULL && buflen != 0 && FIPS_entropy_init()) { + /* Get entropy */ + ent_bytes = jent_read_entropy_safe(&ec, (char *)buf, buflen); + } + return ent_bytes; +} --- a/crypto/fips/fips_err.h +++ b/crypto/fips/fips_err.h @@ -135,6 +135,7 @@ static ERR_STRING_DATA FIPS_str_reasons[ {ERR_REASON(FIPS_R_DRBG_NOT_INITIALISED), "drbg not initialised"}, {ERR_REASON(FIPS_R_DRBG_STUCK), "drbg stuck"}, {ERR_REASON(FIPS_R_ENTROPY_ERROR_UNDETECTED), "entropy error undetected"}, + {ERR_REASON(FIPS_R_ENTROPY_INIT_FAILED), "entropy init failed"}, {ERR_REASON(FIPS_R_ENTROPY_NOT_REQUESTED_FOR_RESEED), "entropy not requested for reseed"}, {ERR_REASON(FIPS_R_ENTROPY_SOURCE_STUCK), "entropy source stuck"}, --- a/crypto/init.c +++ b/crypto/init.c @@ -27,6 +27,7 @@ #include "crypto/dso_conf.h" #include "internal/dso.h" #include "crypto/store.h" +#include "openssl/fips.h" static int stopped = 0; @@ -597,6 +598,9 @@ void OPENSSL_cleanup(void) rand_cleanup_int(); rand_drbg_cleanup_int(); conf_modules_free_int(); +#ifdef OPENSSL_FIPS + FIPS_entropy_cleanup(); +#endif #ifndef OPENSSL_NO_ENGINE engine_cleanup_int(); #endif --- a/crypto/rand/rand_unix.c +++ b/crypto/rand/rand_unix.c @@ -642,9 +642,37 @@ size_t rand_pool_acquire_entropy(RAND_PO return rand_pool_entropy_available(pool); # else size_t entropy_available; + int in_post; + +# ifdef OPENSSL_FIPS + if (FIPS_mode()) { + /* Use jitter entropy in FIPS mode */ + for (in_post = fips_in_post(); in_post >= 0; --in_post) { + size_t bytes_needed; + unsigned char *buffer; + ssize_t bytes; + /* Maximum allowed number of consecutive unsuccessful attempts */ + int attempts = 3; + + bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); + while (bytes_needed != 0 && attempts-- > 0) { + buffer = rand_pool_add_begin(pool, bytes_needed); + bytes = FIPS_jitter_entropy(buffer, bytes_needed); + if (bytes > 0) { + 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 = rand_pool_entropy_available(pool); + return entropy_available; + } +# endif # if defined(OPENSSL_RAND_SEED_GETRANDOM) - int in_post; for (in_post = fips_in_post(); in_post >= 0; --in_post) { { --- a/include/crypto/fips_int.h +++ b/include/crypto/fips_int.h @@ -101,4 +101,6 @@ void fips_set_selftest_fail(void); void FIPS_get_timevec(unsigned char *buf, unsigned long *pctr); +ssize_t FIPS_jitter_entropy(unsigned char *buf, size_t buflen); + #endif --- a/include/openssl/fips.h +++ b/include/openssl/fips.h @@ -74,6 +74,9 @@ extern "C" { BN_GENCB *cb); int FIPS_dsa_paramgen_check_g(DSA *dsa); + struct rand_data* FIPS_entropy_init(void); + void FIPS_entropy_cleanup(void); + /* BEGIN ERROR CODES */ /* The following lines are auto generated by the script mkerr.pl. Any changes * made after this point may be overwritten when the script is next run. @@ -151,6 +154,7 @@ extern "C" { # define FIPS_R_DRBG_NOT_INITIALISED 152 # define FIPS_R_DRBG_STUCK 103 # define FIPS_R_ENTROPY_ERROR_UNDETECTED 104 +# define FIPS_R_ENTROPY_INIT_FAILED 161 # define FIPS_R_ENTROPY_NOT_REQUESTED_FOR_RESEED 105 # define FIPS_R_ENTROPY_SOURCE_STUCK 142 # define FIPS_R_ERROR_INITIALISING_DRBG 115 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -4647,3 +4647,5 @@ fips_sli_PKCS5_PBKDF2_HMAC_is_approved fips_sli_HMAC_is_approved 6608 1_1_1l EXIST::FUNCTION: fips_sli_RAND_bytes_is_approved 6609 1_1_1l EXIST::FUNCTION: fips_sli_RAND_priv_bytes_is_approved 6610 1_1_1l EXIST::FUNCTION: +FIPS_entropy_init 6611 1_1_1l EXIST::FUNCTION: +FIPS_entropy_cleanup 6612 1_1_1l EXIST::FUNCTION: