diff options
-rw-r--r-- | lib/nettle/rnd-common.c | 53 |
1 files changed, 48 insertions, 5 deletions
diff --git a/lib/nettle/rnd-common.c b/lib/nettle/rnd-common.c index 680126033a..0c27a1e3aa 100644 --- a/lib/nettle/rnd-common.c +++ b/lib/nettle/rnd-common.c @@ -37,11 +37,6 @@ #include <rnd-common.h> #include <hash-pjw-bare.h> -#if defined(HAVE_LINUX_GETRANDOM) -# include <linux/random.h> -# define getentropy(x, size) getrandom(x, size, 0) -# define HAVE_GETENTROPY -#endif #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> @@ -178,6 +173,41 @@ void _rnd_system_entropy_deinit(void) #else /* /dev/urandom - egd approach */ +#if defined(__linux) + +#ifdef HAVE_LINUX_GETRANDOM +# include <linux/random.h> +#else +# include <sys/syscall.h> +# undef getrandom +# define getrandom(dst,s,flags) syscall(__NR_getrandom, (void*)dst, (size_t)s, (unsigned int)flags) +#endif + +static unsigned have_getrandom(void) +{ + char c; + if (getrandom(&c, 1, 0) == 1) + return 1; + return 0; +} + +static int _rnd_get_system_entropy_getrandom(void* _rnd, size_t size) +{ + int ret; + ret = getrandom(_rnd, size, 0); + if (ret == -1) { + gnutls_assert(); + _gnutls_debug_log + ("Failed to use getrandom: %s\n", + strerror(errno)); + return GNUTLS_E_RANDOM_DEVICE_ERROR; + } + return 0; +} +#else +# define have_getrandom() 0 +#endif + static int _rnd_get_system_entropy_urandom(void* _rnd, size_t size) { uint8_t* rnd = _rnd; @@ -238,6 +268,9 @@ int _rnd_system_entropy_check(void) int ret; struct stat st; + if (_gnutls_urandom_fd == -1) /* not using urandom */ + return 0; + ret = fstat(_gnutls_urandom_fd, &st); if (ret < 0 || st.st_mode != _gnutls_urandom_fd_mode) { return _rnd_system_entropy_init(); @@ -250,6 +283,14 @@ int _rnd_system_entropy_init(void) int old; struct stat st; + /* Enable getrandom() usage if available */ + if (have_getrandom()) { + _rnd_get_system_entropy = _rnd_get_system_entropy_getrandom; + _gnutls_debug_log("getrandom random generator was detected\n"); + return 0; + } + + /* First fallback: /dev/unrandom */ _gnutls_urandom_fd = open("/dev/urandom", O_RDONLY); if (_gnutls_urandom_fd < 0) { _gnutls_debug_log("Cannot open urandom!\n"); @@ -268,6 +309,7 @@ int _rnd_system_entropy_init(void) return 0; fallback: + /* Third fallback: EGD */ _gnutls_urandom_fd = _rndegd_connect_socket(); if (_gnutls_urandom_fd < 0) { _gnutls_debug_log("Cannot open egd socket!\n"); @@ -280,6 +322,7 @@ fallback: _gnutls_urandom_fd_mode = st.st_mode; } + _gnutls_debug_log("EGD random generator was detected\n"); _rnd_get_system_entropy = _rnd_get_system_entropy_egd; return 0; |