Index: gnutls-3.8.1/lib/nettle/sysrng-linux.c =================================================================== --- gnutls-3.8.1.orig/lib/nettle/sysrng-linux.c +++ gnutls-3.8.1/lib/nettle/sysrng-linux.c @@ -49,6 +49,15 @@ get_entropy_func _rnd_get_system_entropy = NULL; #if defined(__linux__) +# if defined(ENABLE_FIPS140) +# define HAVE_JENT +# include +/* Per thread context of random generator, and a flag to indicate initialization */ +static _Thread_local struct rand_data* ec = NULL; +static _Thread_local int jent_initialized = 0; +/* Declare function to fix a missing-prototypes compilation warning */ +void FIPS_jent_entropy_deinit(void); +# endif #ifdef HAVE_GETRANDOM #include #else @@ -68,6 +77,101 @@ static ssize_t _getrandom0(void *buf, si #endif #endif +# if defined(ENABLE_FIPS140) +# if defined(HAVE_JENT) +/* check whether the CPU Jitter entropy collector is available. */ +static unsigned FIPS_jent_entropy_init(void) +{ + unsigned int rv = 1; + unsigned int osr = 1; /* Oversampling rate */ + unsigned int flags = 0; /* JENT_FORCE_FIPS + * JENT_DISABLE_MEMORY_ACCESS + * JENT_DISABLE_INTERNAL_TIMER + * JENT_FORCE_INTERNAL_TIMER + * JENT_MAX_MEMSIZE_{32,64,128,256,512}kB + * JENT_MAX_MEMSIZE_{1,2,4,8,16,32,64,128,256,512}MB + */ + + /* Set the FIPS flag. */ + flags |= JENT_FORCE_FIPS; + + /* Do not re-initialize jent. */ + if (jent_initialized == 0) { + if (jent_entropy_init_ex(osr, flags)) + return 0; + jent_initialized = 1; + } + + /* Allocate the entropy collector. */ + if (ec == NULL) { + ec = jent_entropy_collector_alloc(osr, flags); + if (ec == NULL) { + rv = 0; + } + } + + return rv; +} + +void FIPS_jent_entropy_deinit(void) +{ + /* Free the entropy collector. */ + if (ec != NULL) { + jent_entropy_collector_free(ec); + ec = NULL; + } + + jent_initialized = 0; + + return; +} + +/* returns exactly the amount of bytes requested */ +static int force_jent(void *buf, size_t buflen, unsigned int flags, + unsigned int osr) +{ + static int jent_bytes = -1; + + if (buf == NULL || buflen == 0) { + return -1; + } + + /* Ensure the entropy source has been fully initiated. */ + if (jent_initialized == 0 || ec == NULL) { + if (!FIPS_jent_entropy_init()) { + return -1; + } + } + + /* Get entropy bytes. */ + jent_bytes = jent_read_entropy_safe(&ec, (char *)buf, buflen); + + return jent_bytes; +} + +static int _rnd_get_system_entropy_jent(void* _rnd, size_t size) +{ + int ret; + unsigned int osr = 1; + unsigned int flags = 0; + + /* Set the FIPS flag. */ + flags |= JENT_FORCE_FIPS; + + ret = force_jent(_rnd, size, flags, osr); + if (ret < 0) { + int e = errno; + gnutls_assert(); + _gnutls_debug_log("Failed to use jent: %s\n", strerror(e)); + FIPS_jent_entropy_deinit(); + return GNUTLS_E_RANDOM_DEVICE_ERROR; + } + + return 0; +} +# endif +# endif + static unsigned have_getrandom(void) { char c; @@ -163,6 +267,24 @@ int _rnd_system_entropy_init(void) int urandom_fd; #if defined(__linux__) +# if defined(ENABLE_FIPS140) +# if defined(HAVE_JENT) + /* Enable jitterentropy usage if available */ + if (FIPS_jent_entropy_init()) { + _rnd_get_system_entropy = _rnd_get_system_entropy_jent; + _gnutls_debug_log("jitterentropy random generator was selected\n"); + return 0; + } else { + _gnutls_debug_log("jitterentropy is not available\n"); + /* Set error state when FIPS_jent_entropy_init failed and FIPS mode is enabled */ + if (_gnutls_fips_mode_enabled()) { + _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR); + _gnutls_switch_lib_state(LIB_STATE_ERROR); + return gnutls_assert_val(GNUTLS_E_RANDOM_DEVICE_ERROR); + } + } +# endif +# endif /* Enable getrandom() usage if available */ if (have_getrandom()) { _rnd_get_system_entropy = _rnd_get_system_entropy_getrandom; @@ -193,5 +315,12 @@ int _rnd_system_entropy_init(void) void _rnd_system_entropy_deinit(void) { /* A no-op now when we open and close /dev/urandom every time */ +#if defined(__linux__) +# if defined(ENABLE_FIPS140) +# if defined(HAVE_JENT) + FIPS_jent_entropy_deinit(); +# endif +# endif +#endif return; } Index: gnutls-3.8.1/lib/nettle/Makefile.in =================================================================== --- gnutls-3.8.1.orig/lib/nettle/Makefile.in +++ gnutls-3.8.1/lib/nettle/Makefile.in @@ -402,7 +402,7 @@ am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(AM_LDFLAGS) $(LDFLAGS) -o $@ + $(AM_LDFLAGS) $(LDFLAGS) -ljitterentropy -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; Index: gnutls-3.8.1/lib/nettle/Makefile.am =================================================================== --- gnutls-3.8.1.orig/lib/nettle/Makefile.am +++ gnutls-3.8.1/lib/nettle/Makefile.am @@ -20,7 +20,7 @@ include $(top_srcdir)/lib/common.mk -AM_CFLAGS += $(HOGWEED_CFLAGS) $(GMP_CFLAGS) +AM_CFLAGS += $(HOGWEED_CFLAGS) $(GMP_CFLAGS) -ljitterentropy AM_CPPFLAGS = \ -I$(srcdir)/int \ Index: gnutls-3.8.1/lib/nettle/rnd-fips.c =================================================================== --- gnutls-3.8.1.orig/lib/nettle/rnd-fips.c +++ gnutls-3.8.1/lib/nettle/rnd-fips.c @@ -129,6 +129,10 @@ static int drbg_init(struct fips_ctx *fc uint8_t buffer[DRBG_AES_SEED_SIZE]; int ret; + ret = _rnd_get_system_entropy(buffer, sizeof(buffer)); + if (ret < 0) + return gnutls_assert_val(ret); + ret = get_entropy(fctx, buffer, sizeof(buffer)); if (ret < 0) { _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR); @@ -153,6 +157,10 @@ static int drbg_reseed(struct fips_ctx * uint8_t buffer[DRBG_AES_SEED_SIZE]; int ret; + ret = _rnd_get_system_entropy(buffer, sizeof(buffer)); + if (ret < 0) + return gnutls_assert_val(ret); + ret = get_entropy(fctx, buffer, sizeof(buffer)); if (ret < 0) { _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR); Index: gnutls-3.8.1/tests/Makefile.am =================================================================== --- gnutls-3.8.1.orig/tests/Makefile.am +++ gnutls-3.8.1/tests/Makefile.am @@ -208,7 +208,7 @@ ctests += mini-record-2 simple gnutls_hm dtls12-cert-key-exchange dtls10-cert-key-exchange x509-cert-callback-legacy \ keylog-env ssl2-hello tlsfeature-ext dtls-rehandshake-cert-2 dtls-session-ticket-lost \ tlsfeature-crt dtls-rehandshake-cert-3 resume-with-false-start \ - set_x509_key_file_ocsp client-fastopen rng-sigint srp rng-pthread \ + set_x509_key_file_ocsp client-fastopen srp rng-pthread \ safe-renegotiation/srn0 safe-renegotiation/srn1 safe-renegotiation/srn2 \ safe-renegotiation/srn3 safe-renegotiation/srn4 safe-renegotiation/srn5 \ rsa-illegal-import set_x509_ocsp_multi_invalid set_key set_x509_key_file_ocsp_multi2 \