From e5724f71d2c054bc51d66092beb6af4da21e0c62 Mon Sep 17 00:00:00 2001 From: "Ondrej Zajicek (work)" Date: Thu, 8 Apr 2021 01:15:17 +0200 Subject: sysdep: Add wrapper to get random bytes - update Simplify the code and fix an issue with getentropy() return value. --- conf/conf.c | 1 - configure.ac | 1 - lib/birdlib.h | 3 +- sysdep/unix/random.c | 110 ++++++++++++++++++++++----------------------------- 4 files changed, 49 insertions(+), 66 deletions(-) diff --git a/conf/conf.c b/conf/conf.c index 0c355be4..58abcde1 100644 --- a/conf/conf.c +++ b/conf/conf.c @@ -524,7 +524,6 @@ order_shutdown(int gr) c->gr_down = gr; config_commit(c, RECONFIG_HARD, 0); - random_close(); shutting_down = 1; } diff --git a/configure.ac b/configure.ac index ded258d3..64181d29 100644 --- a/configure.ac +++ b/configure.ac @@ -376,7 +376,6 @@ fi AC_CHECK_FUNCS(getrandom) AC_CHECK_FUNCS(getentropy) -AC_CHECK_HEADERS(sys/random.h) if test "$enable_debug" = yes ; then AC_DEFINE([DEBUGGING], [1], [Define to 1 if debugging is enabled]) diff --git a/lib/birdlib.h b/lib/birdlib.h index 61098f92..fd20ef3a 100644 --- a/lib/birdlib.h +++ b/lib/birdlib.h @@ -192,8 +192,7 @@ asm( /* Pseudorandom numbers */ u32 random_u32(void); -int random_bytes(char *buf, size_t size); -void random_close(void); void random_init(void); +void random_bytes(void *buf, size_t size); #endif diff --git a/sysdep/unix/random.c b/sysdep/unix/random.c index de81f3ca..4e64e56b 100644 --- a/sysdep/unix/random.c +++ b/sysdep/unix/random.c @@ -8,22 +8,18 @@ #include #include +#include +#include #include #include #include "sysdep/config.h" +#include "nest/bird.h" -#ifdef HAVE_SYS_STAT_H -# include -#endif -#ifdef HAVE_LINUX_RANDOM_H -# include -#endif -#if defined(HAVE_SYS_RANDOM_H) && (defined(HAVE_GETRANDOM) || defined(HAVE_GETENTROPY)) -# include +#ifdef HAVE_GETRANDOM +#include #endif -#include "nest/bird.h" u32 random_u32(void) @@ -35,75 +31,65 @@ random_u32(void) return (rand_low & 0xffff) | ((rand_high & 0xffff) << 16); } -void -random_init() -{ - char buf; - /* get a single random byte to trip any errors early */ - random_bytes(&buf, sizeof(buf)); -} -#if defined(HAVE_GETRANDOM) || defined(HAVE_GENTROPY) +/* If there is no getrandom() / getentropy(), use /dev/urandom */ +#if !defined(HAVE_GETRANDOM) && !defined(HAVE_GETENTROPY) + +#define HAVE_URANDOM_FD 1 +static int urandom_fd = -1; + int -random_bytes(char *buf, size_t size) +read_urandom_fd(void *buf, uint count) { - int n; - int flags = 0; - while (0 < size) { -#if defined(HAVE_GETRANDOM) - n = getrandom(buf, size, flags); -#else - n = getentropy(buf, size); -#endif - if (n < 0) { - if (errno == EINTR) - continue; - die("Couldn't get random bytes: %m"); - } - buf += n; - size -= n; + if (urandom_fd < 0) + { + urandom_fd = open("/dev/urandom", O_RDONLY); + if (urandom_fd < 0) + die("Cannot open /dev/urandom: %m"); } - return 0; + return read(urandom_fd, buf, count); } +#endif -void random_close(void) {} -#else +void +random_init(void) +{ + uint seed; -static int urandom_fd = -1; -int random_bytes(char *buf, size_t size) + /* Get random bytes to trip any errors early and to seed random() */ + random_bytes(&seed, sizeof(seed)); + + srandom(seed); +} + +void +random_bytes(void *buf, size_t count) { - int n; + ASSERT(count <= 256); - if (urandom_fd < 0) + while (count > 0) { - urandom_fd = open("/dev/urandom", O_RDONLY); - if (urandom_fd < 0) - die("Couldn't open /dev/urandom: %m"); - } + int n = -1; - do - { - n = read(urandom_fd, buf, size); - if (n <= 0) { +#if defined(HAVE_GETRANDOM) + n = getrandom(buf, count, 0); +#elif defined(HAVE_GETENTROPY) + n = getentropy(buf, count); + n = !n ? (int) count : n; +#elif defined(HAVE_URANDOM_FD) + n = read_urandom_fd(buf, count); +#endif + + if (n < 0) + { if (errno == EINTR) continue; - die("Couldn't read from /dev/urandom: %m"); + die("Cannot get random bytes: %m"); } - buf += n; - size -= n; - } while (size > 0); - - return 0; -} -void -random_close(void) -{ - if (urandom_fd >= 0) { - close(urandom_fd); - urandom_fd = -1; + buf += n; + count -= n; } } -#endif -- cgit v1.2.3