[PATCH v3 1/7] sysdep: Add wrapper to get random bytes
Toke Høiland-Jørgensen
toke at toke.dk
Tue Nov 24 16:21:47 CET 2020
From: Toke Høiland-Jørgensen <toke at toke.dk>
The Babel authentication code added by a subsequent commit needs a way to
get random bytes for generating nonces.
This patch adds a wrapper function in sysdep to get random bytes, and the
required checks in configure.ac to select how to do it. The configure
script tries, in order, getrandom(), getentropy() and reading from
/dev/urandom.
Signed-off-by: Toke Høiland-Jørgensen <toke at toke.dk>
---
conf/conf.c | 1 +
configure.ac | 4 ++
lib/birdlib.h | 3 ++
sysdep/unix/main.c | 1 +
sysdep/unix/random.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 97 insertions(+)
diff --git a/conf/conf.c b/conf/conf.c
index 6f64b5416..5f20f6ed5 100644
--- a/conf/conf.c
+++ b/conf/conf.c
@@ -515,6 +515,7 @@ 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 eabb3d562..d27bb327b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -373,6 +373,10 @@ elif test "$bird_cv_lib_log" != yes ; then
LIBS="$LIBS $bird_cv_lib_log"
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])
LDFLAGS="$LDFLAGS -rdynamic"
diff --git a/lib/birdlib.h b/lib/birdlib.h
index 23036c1b1..61098f929 100644
--- a/lib/birdlib.h
+++ b/lib/birdlib.h
@@ -192,5 +192,8 @@ asm(
/* Pseudorandom numbers */
u32 random_u32(void);
+int random_bytes(char *buf, size_t size);
+void random_close(void);
+void random_init(void);
#endif
diff --git a/sysdep/unix/main.c b/sysdep/unix/main.c
index 2c7e3ceff..3903ecccb 100644
--- a/sysdep/unix/main.c
+++ b/sysdep/unix/main.c
@@ -851,6 +851,7 @@ main(int argc, char **argv)
parse_args(argc, argv);
log_switch(1, NULL, NULL);
+ random_init();
net_init();
resource_init();
timer_init();
diff --git a/sysdep/unix/random.c b/sysdep/unix/random.c
index b1f5086fe..de81f3ca2 100644
--- a/sysdep/unix/random.c
+++ b/sysdep/unix/random.c
@@ -7,6 +7,21 @@
*/
#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "sysdep/config.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>
+#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
More information about the Bird-users
mailing list