summaryrefslogtreecommitdiff
path: root/sysdep/unix/random.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysdep/unix/random.c')
-rw-r--r--sysdep/unix/random.c110
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