[PATCH 1/4] sysdep: Add wrapper to get random bytes
Toke Høiland-Jørgensen
toke at toke.dk
Sun Feb 23 23:56:34 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(), syscall(SYS_getrandom), getentropy()
and reading from /dev/urandom.
The order and methods corresponds to how CPython implements its
corresponding randomness functions.
Signed-off-by: Toke Høiland-Jørgensen <toke at toke.dk>
---
aclocal.m4 | 49 +++++++++++++++++++++++++++++++
conf/conf.c | 1 +
configure.ac | 15 ++++++++++
lib/birdlib.h | 2 +
sysdep/unix/random.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 145 insertions(+)
diff --git a/aclocal.m4 b/aclocal.m4
index 1613d680..0a1608cb 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -239,3 +239,52 @@ AC_DEFUN([BIRD_CHECK_BISON_VERSION],
;;
esac
])
+
+# BIRD_CHECK_GETRANDOM_SYSCALL
+# Check for the getrandom syscall - borrowed from Python
+AC_DEFUN([BIRD_CHECK_GETRANDOM_SYSCALL], [{
+ # check if the Linux getrandom() syscall is available
+ # borrowed from the Python sources
+ AC_MSG_CHECKING(for the Linux getrandom() syscall)
+ AC_LINK_IFELSE(
+ [
+ AC_LANG_SOURCE([[
+ #include <unistd.h>
+ #include <sys/syscall.h>
+ #include <linux/random.h>
+
+ int main() {
+ char buffer[1];
+ const size_t buflen = sizeof(buffer);
+ const int flags = GRND_NONBLOCK;
+ int res = syscall(SYS_getrandom, buffer, buflen, flags);
+ return res == 0 ? 0 : 1;
+ }
+ ]])
+ ],[have_getrandom_syscall=yes],[have_getrandom_syscall=no])
+ AC_MSG_RESULT($have_getrandom_syscall)
+}])
+
+# BIRD_CHECK_GETRANDOM
+# Check for the getrandom function - borrowed from Python
+AC_DEFUN([BIRD_CHECK_GETRANDOM], [{
+ # check if the Linux getrandom() syscall is available
+ # borrowed from the Python sources
+ AC_MSG_CHECKING(for the getrandom() function)
+ AC_LINK_IFELSE(
+ [
+ AC_LANG_SOURCE([[
+ #include <sys/random.h>
+
+ int main() {
+ char buffer[1];
+ const size_t buflen = sizeof(buffer);
+ const int flags = 0;
+ int res = getrandom(buffer, buflen, flags);
+ return res == 0 ? 0 : 1;
+ }
+ ]])
+ ],[have_getrandom=yes],[have_getrandom=no])
+ AC_MSG_RESULT($have_getrandom)
+}])
+
diff --git a/conf/conf.c b/conf/conf.c
index b21d5213..65445579 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);
+ close_urandom();
shutting_down = 1;
}
diff --git a/configure.ac b/configure.ac
index da8546a6..4ebddfc3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -364,6 +364,21 @@ elif test "$bird_cv_lib_log" != yes ; then
LIBS="$LIBS $bird_cv_lib_log"
fi
+BIRD_CHECK_GETRANDOM_SYSCALL
+if test "$have_getrandom_syscall" = yes; then
+ AC_DEFINE(HAVE_GETRANDOM_SYSCALL, 1,
+ [Define to 1 if the Linux getrandom() syscall is available])
+fi
+
+BIRD_CHECK_GETRANDOM
+if test "$have_getrandom" = yes; then
+ AC_DEFINE(HAVE_GETRANDOM, 1,
+ [Define to 1 if the getrandom() function is available])
+fi
+
+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 5202b0c8..7ce5fe3c 100644
--- a/lib/birdlib.h
+++ b/lib/birdlib.h
@@ -180,5 +180,7 @@ asm(
/* Pseudorandom numbers */
u32 random_u32(void);
+int random_bytes(char *buf, size_t size);
+void close_urandom(void);
#endif
diff --git a/sysdep/unix/random.c b/sysdep/unix/random.c
index b1f5086f..6c8945fc 100644
--- a/sysdep/unix/random.c
+++ b/sysdep/unix/random.c
@@ -7,6 +7,23 @@
*/
#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.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
+#if !defined(HAVE_GETRANDOM) && defined(HAVE_GETRANDOM_SYSCALL)
+# include <sys/syscall.h>
+#endif
#include "nest/bird.h"
@@ -19,3 +36,64 @@ random_u32(void)
rand_high = random();
return (rand_low & 0xffff) | ((rand_high & 0xffff) << 16);
}
+
+#if defined(HAVE_GETRANDOM) || defined(HAVE_GETRANDOM_SYSCALL) || 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);
+#elif defined(HAVE_GETRANDOM_SYSCALL)
+ n = syscall(SYS_getrandom, buf, size, flags);
+#else
+ n = getentropy(buf, size);
+#endif
+ if (n < 0)
+ return -1;
+ buf += n;
+ size -= n;
+ }
+
+ return 0;
+}
+
+void close_urandom(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)
+ return -1;
+ }
+
+ do
+ {
+ n = read(urandom_fd, buf, size);
+ if (n <= 0)
+ return -1;
+ buf += n;
+ size -= n;
+ } while (size > 0);
+
+ return 0;
+}
+
+void
+close_urandom(void)
+{
+ if (urandom_fd >= 0) {
+ close(urandom_fd);
+ urandom_fd = -1;
+ }
+}
+#endif
More information about the Bird-users
mailing list