From e5724f71d2c054bc51d66092beb6af4da21e0c62 Mon Sep 17 00:00:00 2001 From: "Ondrej Zajicek (work)" Date: Thu, 8 Apr 2021 01:15:17 +0200 Subject: [PATCH] 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 | 118 +++++++++++++++++++------------------------ 4 files changed, 53 insertions(+), 70 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,23 +8,19 @@ #include #include +#include +#include #include #include #include "sysdep/config.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 -#endif - #include "nest/bird.h" +#ifdef HAVE_GETRANDOM +#include +#endif + + 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) -int -random_bytes(char *buf, size_t size) -{ - 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; - } - - return 0; -} - -void random_close(void) {} - -#else +/* 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) -{ - int n; +int +read_urandom_fd(void *buf, uint count) +{ if (urandom_fd < 0) { urandom_fd = open("/dev/urandom", O_RDONLY); if (urandom_fd < 0) - die("Couldn't open /dev/urandom: %m"); + die("Cannot open /dev/urandom: %m"); } - do - { - n = read(urandom_fd, buf, size); - if (n <= 0) { - if (errno == EINTR) - continue; - die("Couldn't read from /dev/urandom: %m"); - } - buf += n; - size -= n; - } while (size > 0); + return read(urandom_fd, buf, count); +} +#endif - return 0; + +void +random_init(void) +{ + uint seed; + + /* Get random bytes to trip any errors early and to seed random() */ + random_bytes(&seed, sizeof(seed)); + + srandom(seed); } void -random_close(void) +random_bytes(void *buf, size_t count) { - if (urandom_fd >= 0) { - close(urandom_fd); - urandom_fd = -1; + ASSERT(count <= 256); + + while (count > 0) + { + int n = -1; + +#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("Cannot get random bytes: %m"); + } + + buf += n; + count -= n; } } -#endif