]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: Use best available random number generator
authorAki Tuomi <aki.tuomi@dovecot.fi>
Wed, 23 Aug 2017 09:49:03 +0000 (12:49 +0300)
committerTimo Sirainen <tss@dovecot.fi>
Thu, 7 Sep 2017 08:40:31 +0000 (11:40 +0300)
The best available method is used from short list of
getrandom, arc4random or reading /dev/urandom

src/lib/randgen.c
src/lib/randgen.h

index 332fc845975f732a314d8bddd28cbc83bcc42add..2b0410bf9a5d65c6a50f60606aee920faf5f6b3d 100644 (file)
@@ -6,28 +6,56 @@
 #include <unistd.h>
 #include <fcntl.h>
 
+/* get randomness from either getrandom, arc4random or /dev/urandom */
+
+#if defined(HAVE_GETRANDOM) && HAVE_DECL_GETRANDOM != 0
+#  include <sys/random.h>
+#  define USE_GETRANDOM
+#elif defined(HAVE_ARC4RANDOM)
+#  if defined(HAVE_LIBBSD)
+#    include <bsd/stdlib.h>
+#  endif
+#  define USE_ARC4RANDOM
+#else
+#  define USE_RANDOM_DEV
+#endif
+
 static int init_refcount = 0;
+#if defined(USE_RANDOM_DEV)
 static int urandom_fd;
+#endif
 
 void random_fill(void *buf, size_t size)
 {
-       size_t pos;
-       ssize_t ret;
-
        i_assert(init_refcount > 0);
        i_assert(size < SSIZE_T_MAX);
 
+#if defined(USE_ARC4RANDOM)
+       arc4random_buf(buf, size);
+#else
+       size_t pos;
+       ssize_t ret;
+
        for (pos = 0; pos < size; ) {
+#  if defined(USE_GETRANDOM)
+               ret = getrandom(buf, size - pos, 0);
+#  else
                ret = read(urandom_fd, (char *) buf + pos, size - pos);
+#  endif
                if (unlikely(ret <= 0)) {
                        if (ret == 0)
-                               i_fatal("EOF when reading from "DEV_URANDOM_PATH);
+                               i_fatal("read("DEV_URANDOM_PATH") failed: EOF");
                        else if (errno != EINTR)
+#  if defined(USE_RANDOM_DEV)
                                i_fatal("read("DEV_URANDOM_PATH") failed: %m");
+#  elif defined(USE_GETRANDOM)
+                               i_fatal("getrandom() failed: %m");
+#  endif
                } else {
                        pos += ret;
                }
        }
+#endif /* defined(USE_ARC4RANDOM) */
 }
 
 void random_init(void)
@@ -36,49 +64,27 @@ void random_init(void)
 
        if (init_refcount++ > 0)
                return;
-
+#if defined(USE_RANDOM_DEV)
        urandom_fd = open(DEV_URANDOM_PATH, O_RDONLY);
        if (urandom_fd == -1) {
                if (errno == ENOENT) {
-                       i_fatal(DEV_URANDOM_PATH" doesn't exist, "
+                       i_fatal("open("DEV_URANDOM_PATH") failed: doesn't exist,"
                                "currently we require it");
                } else {
-                       i_fatal("Can't open "DEV_URANDOM_PATH": %m");
+                       i_fatal("open("DEV_URANDOM_PATH") failed: %m");
                }
        }
-
+       fd_close_on_exec(urandom_fd, TRUE);
+#endif
        random_fill(&seed, sizeof(seed));
        srand(seed);
-
-       fd_close_on_exec(urandom_fd, TRUE);
 }
 
 void random_deinit(void)
 {
        if (--init_refcount > 0)
                return;
-
+#if defined(USE_RANDOM_DEV)
        i_close_fd(&urandom_fd);
-}
-
-#ifdef HAVE_ARC4RANDOM
-#ifdef HAVE_LIBBSD
-#include <bsd/stdlib.h>
 #endif
-
-void random_fill_weak(void *buf, size_t size)
-{
-       arc4random_buf(buf, size);
 }
-
-#else
-
-void random_fill_weak(void *buf, size_t size)
-{
-       unsigned char *cbuf = buf;
-
-       for (; size > 0; size--)
-               *cbuf++ = (unsigned char)rand();
-}
-
-#endif
index dc0a79863a081e900658814545fef45a53570ad1..c3b4dedcc81ef5184a41541547b512b96f5e9c32 100644 (file)
@@ -1,14 +1,12 @@
 #ifndef RANDGEN_H
 #define RANDGEN_H
 
-/* Fill given buffer with semi-strong randomness, usually from /dev/urandom. */
+/* Fill given buffer with semi-strong randomness */
 void random_fill(void *buf, size_t size);
-/* Fill given buffer with weak randomness, ie. with rand(). This is better if
-   no real randomness is required, as reading from /dev/urandom usually also
-   consumes /dev/random entropy, which may disturb other processes. */
-void random_fill_weak(void *buf, size_t size);
+#define random_fill_weak(buf,size) random_fill((buf), (size))
 
-/* may be called multiple times */
+/* may be called multiple times,
+   and are called by default in lib_init */
 void random_init(void);
 void random_deinit(void);