[PATCH v4 1/8] sysdep: Add wrapper to get random bytes
Toke Høiland-Jørgensen
toke at toke.dk
Fri Jan 15 16:52:50 CET 2021
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 6f64b5416c59..5f20f6ed5d82 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 eabb3d562e58..d27bb327b290 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 23036c1b1ea6..61098f929031 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 2c7e3ceff632..3903ecccb07a 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 b1f5086fea71..de81f3ca254b 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