diff options
Diffstat (limited to 'recipes-support/gnutls/gnutls-3.5.3/0002-rng-split-initialization-in-preinit-and-init.patch')
-rw-r--r-- | recipes-support/gnutls/gnutls-3.5.3/0002-rng-split-initialization-in-preinit-and-init.patch | 261 |
1 files changed, 261 insertions, 0 deletions
diff --git a/recipes-support/gnutls/gnutls-3.5.3/0002-rng-split-initialization-in-preinit-and-init.patch b/recipes-support/gnutls/gnutls-3.5.3/0002-rng-split-initialization-in-preinit-and-init.patch new file mode 100644 index 0000000..29bcf5f --- /dev/null +++ b/recipes-support/gnutls/gnutls-3.5.3/0002-rng-split-initialization-in-preinit-and-init.patch @@ -0,0 +1,261 @@ +From 834e8fc03cb27ae437a2044cfaf265752c3e6a26 Mon Sep 17 00:00:00 2001 +From: Nikos Mavrogiannopoulos <nmav@redhat.com> +Date: Fri, 14 Oct 2016 14:16:51 +0200 +Subject: [PATCH 2/3] rng: split initialization in preinit and init + +This makes gnutls to initialize its random generator on the +first call to gnutls_rnd(). That prevents blocking due to +getrandom() on a constructor; that change allows to use gnutls-linked +applications even in early boot in systems where getrandom() blocks +waiting for entropy. + +Upstream-Status: Backport + +diff --git a/configure.ac b/configure.ac +index 0ba2230..f842e26 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -186,6 +186,7 @@ AM_SUBST_NOTMAKE([DEFINE_IOVEC_T]) + + dnl Need netinet/tcp.h for TCP_FASTOPEN + AC_CHECK_HEADERS([netinet/tcp.h]) ++AC_CHECK_HEADERS([stdatomic.h]) + + AC_ARG_ENABLE(padlock, + AS_HELP_STRING([--disable-padlock], [unconditionally disable padlock acceleration]), +diff --git a/lib/global.c b/lib/global.c +index d75cea8..bdc3c1f 100644 +--- a/lib/global.c ++++ b/lib/global.c +@@ -304,7 +304,7 @@ static int _gnutls_global_init(unsigned constructor) + } + + /* Initialize the random generator */ +- ret = _gnutls_rnd_init(); ++ ret = _gnutls_rnd_preinit(); + if (ret < 0) { + gnutls_assert(); + goto out; +diff --git a/lib/locks.h b/lib/locks.h +index 5807754..b1efbb5 100644 +--- a/lib/locks.h ++++ b/lib/locks.h +@@ -27,6 +27,10 @@ + #include "gnutls_int.h" + #include <system.h> + ++#ifdef HAVE_STDATOMIC_H ++# include <stdatomic.h> ++#endif ++ + extern mutex_init_func gnutls_mutex_init; + extern mutex_deinit_func gnutls_mutex_deinit; + extern mutex_lock_func gnutls_mutex_lock; +diff --git a/lib/nettle/rnd-fips.c b/lib/nettle/rnd-fips.c +index 59795a9..0807701 100644 +--- a/lib/nettle/rnd-fips.c ++++ b/lib/nettle/rnd-fips.c +@@ -172,10 +172,6 @@ static int _rngfips_init(void **_ctx) + struct fips_ctx *ctx; + int ret; + +- ret = _rnd_system_entropy_init(); +- if (ret < 0) +- return gnutls_assert_val(ret); +- + ctx = gnutls_calloc(1, sizeof(*ctx)); + if (ctx == NULL) + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); +diff --git a/lib/nettle/rnd.c b/lib/nettle/rnd.c +index 39b99e1..c4fbc48 100644 +--- a/lib/nettle/rnd.c ++++ b/lib/nettle/rnd.c +@@ -218,12 +218,6 @@ static int wrap_nettle_rnd_init(void **ctx) + return ret; + } + +- ret = _rnd_system_entropy_init(); +- if (ret < 0) { +- gnutls_assert(); +- return ret; +- } +- + /* initialize the main RNG */ + yarrow256_init(&rnd_ctx.yctx, SOURCES, rnd_ctx.ysources); + +diff --git a/lib/random.c b/lib/random.c +index d7f18f2..977d7aa 100644 +--- a/lib/random.c ++++ b/lib/random.c +@@ -26,30 +26,80 @@ + #include "gnutls_int.h" + #include "errors.h" + #include <random.h> ++#include "locks.h" + #include <fips.h> + + void *gnutls_rnd_ctx; ++GNUTLS_STATIC_MUTEX(gnutls_rnd_init_mutex); + +-int _gnutls_rnd_init(void) ++#ifdef HAVE_STDATOMIC_H ++static atomic_uint rnd_initialized = 0; ++ ++inline static int _gnutls_rnd_init(void) ++{ ++ if (unlikely(!rnd_initialized)) { ++ if (_gnutls_rnd_ops.init == NULL) { ++ rnd_initialized = 1; ++ return 0; ++ } ++ ++ GNUTLS_STATIC_MUTEX_LOCK(gnutls_rnd_init_mutex); ++ if (!rnd_initialized) { ++ if (_gnutls_rnd_ops.init(&gnutls_rnd_ctx) < 0) { ++ gnutls_assert(); ++ GNUTLS_STATIC_MUTEX_UNLOCK(gnutls_rnd_init_mutex); ++ return GNUTLS_E_RANDOM_FAILED; ++ } ++ rnd_initialized = 1; ++ } ++ GNUTLS_STATIC_MUTEX_UNLOCK(gnutls_rnd_init_mutex); ++ } ++ return 0; ++} ++#else ++static unsigned rnd_initialized = 0; ++ ++inline static int _gnutls_rnd_init(void) ++{ ++ GNUTLS_STATIC_MUTEX_LOCK(gnutls_rnd_init_mutex); ++ if (unlikely(!rnd_initialized)) { ++ if (_gnutls_rnd_ops.init == NULL) { ++ rnd_initialized = 1; ++ GNUTLS_STATIC_MUTEX_UNLOCK(gnutls_rnd_init_mutex); ++ return 0; ++ } ++ ++ if (_gnutls_rnd_ops.init(&gnutls_rnd_ctx) < 0) { ++ gnutls_assert(); ++ GNUTLS_STATIC_MUTEX_UNLOCK(gnutls_rnd_init_mutex); ++ return GNUTLS_E_RANDOM_FAILED; ++ } ++ rnd_initialized = 1; ++ } ++ GNUTLS_STATIC_MUTEX_UNLOCK(gnutls_rnd_init_mutex); ++ return 0; ++} ++#endif ++ ++int _gnutls_rnd_preinit(void) + { ++ int ret; ++ + #ifdef ENABLE_FIPS140 + /* The FIPS140 random generator is only enabled when we are compiled + * with FIPS support, _and_ the system requires FIPS140. + */ + if (_gnutls_fips_mode_enabled() == 1) { +- int ret; +- + ret = gnutls_crypto_rnd_register(100, &_gnutls_fips_rnd_ops); + if (ret < 0) + return ret; + } + #endif + +- if (_gnutls_rnd_ops.init != NULL) { +- if (_gnutls_rnd_ops.init(&gnutls_rnd_ctx) < 0) { +- gnutls_assert(); +- return GNUTLS_E_RANDOM_FAILED; +- } ++ ret = _rnd_system_entropy_init(); ++ if (ret < 0) { ++ gnutls_assert(); ++ return GNUTLS_E_RANDOM_FAILED; + } + + return 0; +@@ -57,9 +107,12 @@ int _gnutls_rnd_init(void) + + void _gnutls_rnd_deinit(void) + { +- if (_gnutls_rnd_ops.deinit != NULL) { ++ if (rnd_initialized && _gnutls_rnd_ops.deinit != NULL) { + _gnutls_rnd_ops.deinit(gnutls_rnd_ctx); + } ++ rnd_initialized = 0; ++ ++ _rnd_system_entropy_deinit(); + + return; + } +@@ -81,8 +134,17 @@ void _gnutls_rnd_deinit(void) + **/ + int gnutls_rnd(gnutls_rnd_level_t level, void *data, size_t len) + { ++ int ret; + FAIL_IF_LIB_ERROR; +- return _gnutls_rnd(level, data, len); ++ ++ if (unlikely((ret=_gnutls_rnd_init()) < 0)) ++ return gnutls_assert_val(ret); ++ ++ if (likely(len > 0)) { ++ return _gnutls_rnd_ops.rnd(gnutls_rnd_ctx, level, data, ++ len); ++ } ++ return 0; + } + + /** +@@ -98,5 +160,6 @@ int gnutls_rnd(gnutls_rnd_level_t level, void *data, size_t len) + **/ + void gnutls_rnd_refresh(void) + { +- _gnutls_rnd_refresh(); ++ if (rnd_initialized && _gnutls_rnd_ops.rnd_refresh) ++ _gnutls_rnd_ops.rnd_refresh(gnutls_rnd_ctx); + } +diff --git a/lib/random.h b/lib/random.h +index 1538ec8..2ef7bc4 100644 +--- a/lib/random.h ++++ b/lib/random.h +@@ -31,31 +31,15 @@ extern int crypto_rnd_prio; + extern void *gnutls_rnd_ctx; + extern gnutls_crypto_rnd_st _gnutls_rnd_ops; + +-inline static int +-_gnutls_rnd(gnutls_rnd_level_t level, void *data, size_t len) +-{ +- if (len > 0) { +- return _gnutls_rnd_ops.rnd(gnutls_rnd_ctx, level, data, +- len); +- } +- return 0; +-} +- +-inline static void _gnutls_rnd_refresh(void) +-{ +- _gnutls_rnd_ops.rnd_refresh(gnutls_rnd_ctx); +-} ++#define _gnutls_rnd gnutls_rnd ++#define _gnutls_rnd_refresh gnutls_rnd_refresh + + void _gnutls_rnd_deinit(void); +-int _gnutls_rnd_init(void); ++int _gnutls_rnd_preinit(void); + + inline static int _gnutls_rnd_check(void) + { + return _rnd_system_entropy_check(); + } + +-#ifndef _WIN32 +-extern int _gnutls_urandom_fd; +-#endif +- + #endif +-- +2.6.6 + |