random: Use getentropy when available for not GNU/Linux.
authorNIIBE Yutaka <gniibe@fsij.org>
Tue, 15 Jan 2019 04:53:45 +0000 (13:53 +0900)
committerNIIBE Yutaka <gniibe@fsij.org>
Tue, 15 Jan 2019 04:53:45 +0000 (13:53 +0900)
* configure.ac: Detect getentropy.
* random/rndlinux.c [__linux__] (getentropy): Macro defined.
[HAVE_GETENTROPY] (_gcry_rndlinux_gather_random): Use getentropy.

--

GnuPG-bug-id: 4288
Reported-by: David Carlier
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
configure.ac
random/rndlinux.c

index 5843884..67cf1f7 100644 (file)
@@ -1772,7 +1772,7 @@ AC_CHECK_FUNCS(strtoul memmove stricmp atexit raise)
 AC_CHECK_FUNCS(strerror rand mmap getpagesize sysconf waitpid wait4)
 AC_CHECK_FUNCS(gettimeofday getrusage gethrtime clock_gettime syslog)
 AC_CHECK_FUNCS(syscall fcntl ftruncate flockfile)
-AC_CHECK_FUNCS(explicit_bzero)
+AC_CHECK_FUNCS(explicit_bzero getentropy)
 
 GNUPG_CHECK_MLOCK
 
index 3d41cd3..d71261c 100644 (file)
 #include <string.h>
 #include <unistd.h>
 #include <fcntl.h>
-#if defined(__linux__) && defined(HAVE_SYSCALL)
+#if defined(__linux__) || !defined(HAVE_GETENTROPY)
+#ifdef HAVE_SYSCALL
 # include <sys/syscall.h>
+# ifdef __NR_getrandom
+# define getentropy(buf,buflen) syscall (__NR_getrandom, buf, buflen, 0)
+# endif
+#endif
 #endif
 
 #include "types.h"
@@ -247,16 +252,14 @@ _gcry_rndlinux_gather_random (void (*add)(const void*, size_t,
       struct timeval tv;
       int rc;
 
-      /* If we have a modern Linux kernel, we first try to use the new
-       * getrandom syscall.  That call guarantees that the kernel's
+      /* If we have a modern operating system, we first try to use the new
+       * getentropy function.  That call guarantees that the kernel's
        * RNG has been properly seeded before returning any data.  This
        * is different from /dev/urandom which may, due to its
        * non-blocking semantics, return data even if the kernel has
        * not been properly seeded.  And it differs from /dev/random by never
-       * blocking once the kernel is seeded. Unfortunately we need to use a
-       * syscall and not a new device and thus we are not able to use
-       * select(2) to have a timeout. */
-#if defined(__linux__) && defined(HAVE_SYSCALL) && defined(__NR_getrandom)
+       * blocking once the kernel is seeded.  */
+#if defined(HAVE_GETENTROPY) || defined(__NR_getrandom)
         {
           long ret;
           size_t nbytes;
@@ -267,20 +270,19 @@ _gcry_rndlinux_gather_random (void (*add)(const void*, size_t,
               if (nbytes > 256)
                 nbytes = 256;
               _gcry_pre_syscall ();
-              ret = syscall (__NR_getrandom,
-                             (void*)buffer, (size_t)nbytes, (unsigned int)0);
+              ret = getentropy (buffer, nbytes);
               _gcry_post_syscall ();
             }
           while (ret == -1 && errno == EINTR);
           if (ret == -1 && errno == ENOSYS)
-            ; /* The syscall is not supported - fallback to pulling from fd.  */
+            ; /* getentropy is not supported - fallback to pulling from fd.  */
           else
-            { /* The syscall is supported.  Some sanity checks.  */
+            { /* getentropy is supported.  Some sanity checks.  */
               if (ret == -1)
-                log_fatal ("unexpected error from getrandom: %s\n",
+                log_fatal ("unexpected error from getentropy: %s\n",
                            strerror (errno));
               else if (ret != nbytes)
-                log_fatal ("getrandom returned only"
+                log_fatal ("getentropy returned only"
                            " %ld of %zu requested bytes\n", ret, nbytes);
 
               (*add)(buffer, nbytes, origin);