Blob Blame History Raw
From 3a8bf57bd3008b2f5338bbd8ba1db5e9e2622c92 Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Wed, 14 Sep 2016 16:10:34 -0400
Subject: [PATCH] Add getrandom to k5_get_os_entropy() using syscall

ticket: 8499
(cherry picked from commit a9a48392c088b53d8dd86b8008b4059ab78a3679)
---
 src/lib/crypto/krb/prng.c | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/src/lib/crypto/krb/prng.c b/src/lib/crypto/krb/prng.c
index 9ad24c1..22948a4 100644
--- a/src/lib/crypto/krb/prng.c
+++ b/src/lib/crypto/krb/prng.c
@@ -58,6 +58,9 @@ k5_get_os_entropy(unsigned char *buf, size_t len, int strong)
 #ifdef HAVE_SYS_STAT_H
 #include <sys/stat.h>
 #endif
+#ifdef __linux__
+#include <sys/syscall.h>
+#endif /* __linux__ */
 
 /* Open device, ensure that it is not a regular file, and read entropy.  Return
  * true on success, false on failure. */
@@ -96,6 +99,33 @@ krb5_boolean
 k5_get_os_entropy(unsigned char *buf, size_t len, int strong)
 {
     const char *device;
+#if defined(__linux__) && defined(SYS_getrandom)
+    int r;
+
+    while (len > 0) {
+        /*
+         * Pull from the /dev/urandom pool, but it to have been seeded.  This
+         * ensures strong randomness while only blocking during first system
+         * boot.
+         *
+         * glibc does not currently provide a binding for getrandom:
+         * https://sourceware.org/bugzilla/show_bug.cgi?id=17252
+         */
+        errno = 0;
+        r = syscall(SYS_getrandom, buf, len, 0);
+        if (r <= 0) {
+            if (errno == EINTR)
+                continue;
+
+            /* ENOSYS or other unrecoverable failure */
+            break;
+        }
+        len -= r;
+        buf += r;
+    }
+    if (len == 0)
+        return TRUE;
+#endif /* defined(__linux__) && defined(SYS_getrandom) */
 
     device = strong ? "/dev/random" : "/dev/urandom";
     return read_entropy_from_device(device, buf, len);
-- 
2.9.3