From 79d0a2c53a87bbf6207fc10c8e2345f27188143d Mon Sep 17 00:00:00 2001
From: David Carlier <devnexen@gmail.com>
Date: Tue, 21 Nov 2017 11:59:16 +0000
Subject: [PATCH] Using arc4random API for strong randomness if available and
 with implementation not using RC4 stream cipher.

---
 configure                   | 12 ++++++++++--
 configure.in                |  9 +++++++--
 src/include/pg_config.h.in  |  3 +++
 src/port/pg_strong_random.c |  9 +++++++++
 4 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/configure b/configure
index b31134832e..dcfe94ec84 100755
--- a/configure
+++ b/configure
@@ -15618,11 +15618,13 @@ fi
 # in the template or configure command line.
 
 # If not selected manually, try to select a source automatically.
-if test "$enable_strong_random" = "yes" && test x"$USE_OPENSSL_RANDOM" = x"" && test x"$USE_WIN32_RANDOM" = x"" && test x"$USE_DEV_URANDOM" = x"" ; then
+if test "$enable_strong_random" = "yes" && test x"$USE_OPENSSL_RANDOM" = x"" && test x"$USE_WIN32_RANDOM" = x"" && test x"$USE_ARC4_RANDOM" = x"" && test x"$USE_DEV_URANDOM" = x"" ; then
   if test x"$with_openssl" = x"yes" ; then
     USE_OPENSSL_RANDOM=1
   elif test "$PORTNAME" = "win32" ; then
     USE_WIN32_RANDOM=1
+  elif test "$PORTNAME" = "freebsd" || test "$PORTNAME" = "openbsd" || test "$PORTNAME" = "netbsd" || test "$PORTNAME" = "darwin" ; then
+    USE_ARC4_RANDOM=1
   else
     { $as_echo "$as_me:${as_lineno-$LINENO}: checking for /dev/urandom" >&5
 $as_echo_n "checking for /dev/urandom... " >&6; }
@@ -15665,6 +15667,12 @@ $as_echo "#define USE_WIN32_RANDOM 1" >>confdefs.h
 
     { $as_echo "$as_me:${as_lineno-$LINENO}: result: Windows native" >&5
 $as_echo "Windows native" >&6; }
+  elif test x"$USE_ARC4_RANDOM" = x"1" ; then
+
+$as_echo "#define USE_ARC4_RANDOM 1" >>confdefs.h
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: arc4random" >&5
+$as_echo "arc4random" >&6; }
   elif test x"$USE_DEV_URANDOM" = x"1" ; then
 
 $as_echo "#define USE_DEV_URANDOM 1" >>confdefs.h
@@ -15674,7 +15682,7 @@ $as_echo "/dev/urandom" >&6; }
   else
     as_fn_error $? "
 no source of strong random numbers was found
-PostgreSQL can use OpenSSL or /dev/urandom as a source of random numbers,
+PostgreSQL can use OpenSSL or arc4random or /dev/urandom as a source of random numbers,
 for authentication protocols. You can use --disable-strong-random to use a
 built-in pseudo random number generator, but that may be insecure." "$LINENO" 5
   fi
diff --git a/configure.in b/configure.in
index 3f26f038d6..bffde1deef 100644
--- a/configure.in
+++ b/configure.in
@@ -1989,11 +1989,13 @@ fi
 # in the template or configure command line.
 
 # If not selected manually, try to select a source automatically.
-if test "$enable_strong_random" = "yes" && test x"$USE_OPENSSL_RANDOM" = x"" && test x"$USE_WIN32_RANDOM" = x"" && test x"$USE_DEV_URANDOM" = x"" ; then
+if test "$enable_strong_random" = "yes" && test x"$USE_OPENSSL_RANDOM" = x"" && test x"$USE_WIN32_RANDOM" = x"" && test x"$USE_ARC4_RANDOM" = x"" && test x"$USE_DEV_URANDOM" = x"" ; then
   if test x"$with_openssl" = x"yes" ; then
     USE_OPENSSL_RANDOM=1
   elif test "$PORTNAME" = "win32" ; then
     USE_WIN32_RANDOM=1
+  elif test "$PORTNAME" = "freebsd" || test "$PORTNAME" = "openbsd" || test "$PORTNAME" = "netbsd" || test "$PORTNAME" = "darwin" ; then
+    USE_ARC4_RANDOM=1
   else
     AC_CHECK_FILE([/dev/urandom], [], [])
 
@@ -2011,13 +2013,16 @@ if test "$enable_strong_random" = yes ; then
   elif test x"$USE_WIN32_RANDOM" = x"1" ; then
     AC_DEFINE(USE_WIN32_RANDOM, 1, [Define to use native Windows API for random number generation])
     AC_MSG_RESULT([Windows native])
+  elif test x"$USE_ARC4_RANDOM" = x"1" ; then
+    AC_DEFINE(USE_ARC4_RANDOM, 1, [Define to use arc4random API for random number generation])
+    AC_MSG_RESULT([arc4random])
   elif test x"$USE_DEV_URANDOM" = x"1" ; then
     AC_DEFINE(USE_DEV_URANDOM, 1, [Define to use /dev/urandom for random number generation])
     AC_MSG_RESULT([/dev/urandom])
   else
     AC_MSG_ERROR([
 no source of strong random numbers was found
-PostgreSQL can use OpenSSL or /dev/urandom as a source of random numbers,
+PostgreSQL can use OpenSSL or arc4random or /dev/urandom as a source of random numbers,
 for authentication protocols. You can use --disable-strong-random to use a
 built-in pseudo random number generator, but that may be insecure.])
   fi
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 84d59f12b2..20373bf587 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -805,6 +805,9 @@
 /* Define to 1 if your <sys/time.h> declares `struct tm'. */
 #undef TM_IN_SYS_TIME
 
+/* Define to use arc4random API for random number generation */
+#undef USE_ARC4_RANDOM
+
 /* Define to 1 to build with assertion checks. (--enable-cassert) */
 #undef USE_ASSERT_CHECKING
 
diff --git a/src/port/pg_strong_random.c b/src/port/pg_strong_random.c
index c6ee5ea1d4..e3e6804ee2 100644
--- a/src/port/pg_strong_random.c
+++ b/src/port/pg_strong_random.c
@@ -134,6 +134,15 @@ pg_strong_random(void *buf, size_t len)
 	}
 	return false;
 
+	/*
+	 * Using arc4random call to fill the buffer
+	 * with strong randomness which never fails
+	 * not needs a file descriptor
+	 */
+#elif defined(USE_ARC4_RANDOM)
+	arc4random_buf(buf, len);
+	return true;
+
 	/*
 	 * Read /dev/urandom ourselves.
 	 */
-- 
2.15.0

