diff options
Diffstat (limited to 'sysdep/unix')
-rw-r--r-- | sysdep/unix/random.c | 110 |
1 files changed, 48 insertions, 62 deletions
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 <stdlib.h> #include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> #include <unistd.h> #include <errno.h> #include "sysdep/config.h" +#include "nest/bird.h" -#ifdef HAVE_SYS_STAT_H -# include <sys/stat.h> -#endif -#ifdef HAVE_LINUX_RANDOM_H -# include <linux/random.h> -#endif -#if defined(HAVE_SYS_RANDOM_H) && (defined(HAVE_GETRANDOM) || defined(HAVE_GETENTROPY)) -# include <sys/random.h> +#ifdef HAVE_GETRANDOM +#include <sys/random.h> #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 |