On Wed, Jul 18, 2018 at 10:14:56AM +0100, Dean Rasheed wrote:
> OK, I guess that it is possible that an older version of OpenSSL
> requires RAND_poll() to be called multiple times. Here's an updated
> patch doing that (with up to 8 retries, based on the old OpenSSL
> code).

Thanks for the updated version.  This looks safer to me.  It is possible
to simplify the code by removing the external RAND_status() call and
check for RAND_status() first in the loop as per the attached.
--
Michael
diff --git a/src/port/pg_strong_random.c b/src/port/pg_strong_random.c
index bc7a8aacb9..8ed5c04459 100644
--- a/src/port/pg_strong_random.c
+++ b/src/port/pg_strong_random.c
@@ -103,6 +103,35 @@ pg_strong_random(void *buf, size_t len)
 	 * When built with OpenSSL, use OpenSSL's RAND_bytes function.
 	 */
 #if defined(USE_OPENSSL_RANDOM)
+	int			i;
+
+	/*
+	 * Check that OpenSSL's CSPRNG has been sufficiently seeded, and if not
+	 * add more seed data using RAND_poll().  With some older versions of
+	 * OpenSSL, it may be necessary to call RAND_poll() a number of times.
+	 */
+#define NUM_RAND_POLL_RETRIES 8
+
+	for (i = 0; i < NUM_RAND_POLL_RETRIES; i++)
+	{
+		if (RAND_status() == 1)
+		{
+			/* CSPRNG is sufficiently seeded */
+			break;
+		}
+
+		if (RAND_poll() == 0)
+		{
+			/*
+			 * RAND_poll() failed to generate any seed data, which means that
+			 * RAND_bytes() will probably fail.  For now, just fall through
+			 * and let that happen.  XXX: maybe we could seed it some other
+			 * way.
+			 */
+			break;
+		}
+	}
+
 	if (RAND_bytes(buf, len) == 1)
 		return true;
 	return false;

Attachment: signature.asc
Description: PGP signature

Reply via email to