From c48ebde5ce6db3da8cd571d213d1a1f265de8983 Mon Sep 17 00:00:00 2001 From: Toke Høiland-Jørgensen Date: Thu, 1 Apr 2021 19:20:13 +0200 Subject: sysdep: Add wrapper to get random bytes Add a wrapper function in sysdep to get random bytes, and required checks in configure.ac to select how to do it. The configure script tries, in order, getrandom(), getentropy() and reading from /dev/urandom. --- sysdep/unix/random.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) (limited to 'sysdep/unix/random.c') diff --git a/sysdep/unix/random.c b/sysdep/unix/random.c index b1f5086f..de81f3ca 100644 --- a/sysdep/unix/random.c +++ b/sysdep/unix/random.c @@ -7,6 +7,21 @@ */ #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" @@ -19,3 +34,76 @@ random_u32(void) rand_high = random(); 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 + +static int urandom_fd = -1; +int random_bytes(char *buf, size_t size) +{ + int n; + + if (urandom_fd < 0) + { + urandom_fd = open("/dev/urandom", O_RDONLY); + if (urandom_fd < 0) + die("Couldn't 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 0; +} + +void +random_close(void) +{ + if (urandom_fd >= 0) { + close(urandom_fd); + urandom_fd = -1; + } +} +#endif -- cgit v1.2.3