Blob Blame History Raw
From 71dbb3a1a96a012683125a22e9bf263efb97df4d Mon Sep 17 00:00:00 2001
From: Evan Hunt <each@isc.org>
Date: Thu, 28 Sep 2017 10:09:22 -0700
Subject: [PATCH] [master] completed and corrected the crypto-random change

4724.	[func]		By default, BIND now uses the random number
			functions provided by the crypto library (i.e.,
			OpenSSL or a PKCS#11 provider) as a source of
			randomness rather than /dev/random.  This is
			suitable for virtual machine environments
			which have limited entropy pools and lack
			hardware random number generators.

			This can be overridden by specifying another
			entropy source via the "random-device" option
			in named.conf, or via the -r command line option;
			however, for functions requiring full cryptographic
			strength, such as DNSSEC key generation, this
			cannot be overridden. In particular, the -r
			command line option no longer has any effect on
			dnssec-keygen.

			This can be disabled by building with
			"configure --disable-crypto-rand".
			[RT #31459] [RT #46047]
---
 bin/confgen/keygen.c                     | 12 +++----
 bin/dnssec/dnssec-keygen.docbook         | 24 +++++++++-----
 bin/dnssec/dnssectool.c                  | 12 +++----
 bin/named/client.c                       |  3 +-
 bin/named/config.c                       |  4 ++-
 bin/named/controlconf.c                  | 19 +++++++----
 bin/named/include/named/server.h         |  2 ++
 bin/named/interfacemgr.c                 |  1 +
 bin/named/query.c                        |  1 +
 bin/named/server.c                       | 52 ++++++++++++++++++------------
 bin/nsupdate/nsupdate.c                  |  4 +--
 bin/tests/system/pipelined/pipequeries.c |  4 +--
 bin/tests/system/tkey/keycreate.c        |  4 +--
 bin/tests/system/tkey/keydelete.c        |  4 +--
 doc/arm/Bv9ARM-book.xml                  | 55 ++++++++++++++++++++++----------
 doc/arm/notes.xml                        | 26 +++++++++++++++
 lib/dns/dst_api.c                        |  7 ++--
 lib/dns/include/dst/dst.h                | 14 ++++++--
 lib/dns/openssl_link.c                   |  3 +-
 lib/isc/include/isc/entropy.h            | 50 +++++++++++++++++++++--------
 lib/isc/include/isc/random.h             | 28 ++++++++++------
 lib/isccfg/namedconf.c                   |  2 +-
 22 files changed, 222 insertions(+), 109 deletions(-)

diff --git a/bin/confgen/keygen.c b/bin/confgen/keygen.c
index fa439cc158..a7ad417a18 100644
--- a/bin/confgen/keygen.c
+++ b/bin/confgen/keygen.c
@@ -161,17 +161,15 @@ generate_key(isc_mem_t *mctx, const char *randomfile, dns_secalg_t alg,
 
 	DO("create entropy context", isc_entropy_create(mctx, &ectx));
 
-	if (randomfile != NULL && strcmp(randomfile, "keyboard") == 0) {
-		randomfile = NULL;
-		open_keyboard = ISC_ENTROPY_KEYBOARDYES;
-	}
 #ifdef ISC_PLATFORM_CRYPTORANDOM
-	if (randomfile != NULL &&
-	    strcmp(randomfile, ISC_PLATFORM_CRYPTORANDOM) == 0) {
-		randomfile = NULL;
+	if (randomfile == NULL) {
 		isc_entropy_usehook(ectx, ISC_TRUE);
 	}
 #endif
+	if (randomfile != NULL && strcmp(randomfile, "keyboard") == 0) {
+		randomfile = NULL;
+		open_keyboard = ISC_ENTROPY_KEYBOARDYES;
+	}
 	DO("start entropy source", isc_entropy_usebestsource(ectx,
 							     &entropy_source,
 							     randomfile,
diff --git a/bin/dnssec/dnssec-keygen.docbook b/bin/dnssec/dnssec-keygen.docbook
index 96dfef64b4..1c84b06126 100644
--- a/bin/dnssec/dnssec-keygen.docbook
+++ b/bin/dnssec/dnssec-keygen.docbook
@@ -349,15 +349,23 @@
 	<term>-r <replaceable class="parameter">randomdev</replaceable></term>
 	<listitem>
 	  <para>
-	    Specifies the source of randomness.  If the operating
-	    system does not provide a <filename>/dev/random</filename>
-	    or equivalent device, the default source of randomness
-	    is keyboard input.  <filename>randomdev</filename>
-	    specifies
+	    Specifies a source of randomness.  Normally, when generating
+	    DNSSEC keys, this option has no effect; the random number
+	    generation function provided by the cryptographic library will
+	    be used.
+	  </para>
+	  <para>
+	    If that behavior is disabled at compile time, however,
+	    the specified file will be used as entropy source
+	    for key generation.  <filename>randomdev</filename> is
 	    the name of a character device or file containing random
-	    data to be used instead of the default.  The special value
-	    <filename>keyboard</filename> indicates that keyboard
-	    input should be used.
+	    data to be used.  The special value <filename>keyboard</filename>
+	    indicates that keyboard input should be used.
+	  </para>
+	  <para>
+	    The default is <filename>/dev/random</filename> if the
+	    operating system provides it or an equivalent device;
+	    if not, the default source of randomness is keyboard input.
 	  </para>
 	</listitem>
       </varlistentry>
diff --git a/bin/dnssec/dnssectool.c b/bin/dnssec/dnssectool.c
index 4ea9eafa44..5dd9475dd3 100644
--- a/bin/dnssec/dnssectool.c
+++ b/bin/dnssec/dnssectool.c
@@ -239,18 +239,16 @@ setup_entropy(isc_mem_t *mctx, const char *randomfile, isc_entropy_t **ectx) {
 		ISC_LIST_INIT(sources);
 	}
 
+#ifdef ISC_PLATFORM_CRYPTORANDOM
+	if (randomfile == NULL) {
+		isc_entropy_usehook(*ectx, ISC_TRUE);
+	}
+#endif
 	if (randomfile != NULL && strcmp(randomfile, "keyboard") == 0) {
 		usekeyboard = ISC_ENTROPY_KEYBOARDYES;
 		randomfile = NULL;
 	}
 
-#ifdef ISC_PLATFORM_CRYPTORANDOM
-	if (randomfile != NULL &&
-	    strcmp(randomfile, ISC_PLATFORM_CRYPTORANDOM) == 0) {
-		randomfile = NULL;
-		isc_entropy_usehook(*ectx, ISC_TRUE);
-	}
-#endif
 	result = isc_entropy_usebestsource(*ectx, &source, randomfile,
 					   usekeyboard);
 
diff --git a/bin/named/client.c b/bin/named/client.c
index b9ebc93094..20e5f395d4 100644
--- a/bin/named/client.c
+++ b/bin/named/client.c
@@ -1605,7 +1605,8 @@ ns_client_addopt(ns_client_t *client, dns_message_t *message,
 
 		isc_buffer_init(&buf, cookie, sizeof(cookie));
 		isc_stdtime_get(&now);
-		isc_random_get(&nonce);
+		nonce = ((isc_rng_random(ns_g_server->rngctx) << 16) |
+			 isc_rng_random(ns_g_server->rngctx));
 
 		compute_cookie(client, now, nonce, ns_g_server->secret, &buf);
 
diff --git a/bin/named/config.c b/bin/named/config.c
index c50f759ddd..c1e72ef996 100644
--- a/bin/named/config.c
+++ b/bin/named/config.c
@@ -92,7 +92,9 @@ options {\n\
 #	pid-file \"" NS_LOCALSTATEDIR "/run/named/named.pid\"; /* or /lwresd.pid */\n\
 	port 53;\n\
 	prefetch 2 9;\n"
-#ifdef PATH_RANDOMDEV
+#if defined(ISC_PLATFORM_CRYPTORANDOM)
+"	random-device none;\n"
+#elif defined(PATH_RANDOMDEV)
 "	random-device \"" PATH_RANDOMDEV "\";\n"
 #endif
 "	recursing-file \"named.recursing\";\n\
diff --git a/bin/named/controlconf.c b/bin/named/controlconf.c
index 237e8dc31d..b905475890 100644
--- a/bin/named/controlconf.c
+++ b/bin/named/controlconf.c
@@ -322,9 +322,10 @@ log_invalid(isccc_ccmsg_t *ccmsg, isc_result_t result) {
 
 static void
 control_recvmessage(isc_task_t *task, isc_event_t *event) {
-	controlconnection_t *conn;
-	controllistener_t *listener;
-	controlkey_t *key;
+	controlconnection_t *conn = NULL;
+	controllistener_t *listener = NULL;
+	ns_server_t *server = NULL;
+	controlkey_t *key = NULL;
 	isccc_sexpr_t *request = NULL;
 	isccc_sexpr_t *response = NULL;
 	isc_uint32_t algorithm;
@@ -335,16 +336,17 @@ control_recvmessage(isc_task_t *task, isc_event_t *event) {
 	isc_buffer_t *text;
 	isc_result_t result;
 	isc_result_t eresult;
-	isccc_sexpr_t *_ctrl;
+	isccc_sexpr_t *_ctrl = NULL;
 	isccc_time_t sent;
 	isccc_time_t exp;
 	isc_uint32_t nonce;
-	isccc_sexpr_t *data;
+	isccc_sexpr_t *data = NULL;
 
 	REQUIRE(event->ev_type == ISCCC_EVENT_CCMSG);
 
 	conn = event->ev_arg;
 	listener = conn->listener;
+	server = listener->controls->server;
 	algorithm = DST_ALG_UNKNOWN;
 	secret.rstart = NULL;
 	text = NULL;
@@ -455,8 +457,11 @@ control_recvmessage(isc_task_t *task, isc_event_t *event) {
 	 * Establish nonce.
 	 */
 	if (conn->nonce == 0) {
-		while (conn->nonce == 0)
-			isc_random_get(&conn->nonce);
+		while (conn->nonce == 0) {
+			isc_uint16_t r1 = isc_rng_random(server->rngctx);
+			isc_uint16_t r2 = isc_rng_random(server->rngctx);
+			conn->nonce = (r1 << 16) | r2;
+		}
 		eresult = ISC_R_SUCCESS;
 	} else
 		eresult = ns_control_docommand(request, listener->readonly, &text);
diff --git a/bin/named/include/named/server.h b/bin/named/include/named/server.h
index d8179a60a0..e03d24d85d 100644
--- a/bin/named/include/named/server.h
+++ b/bin/named/include/named/server.h
@@ -17,6 +17,7 @@
 #include <isc/log.h>
 #include <isc/magic.h>
 #include <isc/quota.h>
+#include <isc/random.h>
 #include <isc/sockaddr.h>
 #include <isc/types.h>
 #include <isc/xml.h>
@@ -131,6 +132,7 @@ struct ns_server {
 	char *			lockfile;
 
 	isc_uint16_t		transfer_tcp_message_size;
+	isc_rng_t *		rngctx;
 };
 
 struct ns_altsecret {
diff --git a/bin/named/interfacemgr.c b/bin/named/interfacemgr.c
index d8c7188186..50f924eadb 100644
--- a/bin/named/interfacemgr.c
+++ b/bin/named/interfacemgr.c
@@ -15,6 +15,7 @@
 
 #include <isc/interfaceiter.h>
 #include <isc/os.h>
+#include <isc/random.h>
 #include <isc/string.h>
 #include <isc/task.h>
 #include <isc/util.h>
diff --git a/bin/named/query.c b/bin/named/query.c
index accbf3b24d..d89622d835 100644
--- a/bin/named/query.c
+++ b/bin/named/query.c
@@ -18,6 +18,7 @@
 #include <isc/hex.h>
 #include <isc/mem.h>
 #include <isc/print.h>
+#include <isc/random.h>
 #include <isc/rwlock.h>
 #include <isc/serial.h>
 #include <isc/stats.h>
diff --git a/bin/named/server.c b/bin/named/server.c
index ee5186c165..553e0f1ae6 100644
--- a/bin/named/server.c
+++ b/bin/named/server.c
@@ -8076,21 +8076,30 @@ load_configuration(const char *filename, ns_server_t *server,
 	 * Open the source of entropy.
 	 */
 	if (first_time) {
+		const char *randomdev = NULL;
+		int level = ISC_LOG_ERROR;
 		obj = NULL;
 		result = ns_config_get(maps, "random-device", &obj);
-		if (result != ISC_R_SUCCESS) {
-			isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
-				      NS_LOGMODULE_SERVER, ISC_LOG_INFO,
-				      "no source of entropy found");
-		} else {
-			const char *randomdev = cfg_obj_asstring(obj);
+		if (result == ISC_R_SUCCESS) {
+			if (!cfg_obj_isvoid(obj)) {
+				level = ISC_LOG_INFO;
+				randomdev = cfg_obj_asstring(obj);
+			}
+		}
+		if (randomdev == NULL) {
 #ifdef ISC_PLATFORM_CRYPTORANDOM
-			if (strcmp(randomdev, ISC_PLATFORM_CRYPTORANDOM) == 0)
-				isc_entropy_usehook(ns_g_entropy, ISC_TRUE);
+			isc_entropy_usehook(ns_g_entropy, ISC_TRUE);
 #else
-			int level = ISC_LOG_ERROR;
-			result = isc_entropy_createfilesource(ns_g_entropy,
-							      randomdev);
+			if ((obj != NULL) && !cfg_obj_isvoid(obj))
+				level = ISC_LOG_INFO;
+			isc_log_write(named_g_lctx, NS_LOGCATEGORY_GENERAL,
+				      NS_LOGMODULE_SERVER, level,
+				      "no source of entropy found");
+			if ((obj == NULL) || cfg_obj_isvoid(obj)) {
+				CHECK(ISC_R_FAILURE);
+			}
+#endif
+		} else {
 #ifdef PATH_RANDOMDEV
 			if (ns_g_fallbackentropy != NULL) {
 				level = ISC_LOG_INFO;
@@ -8101,8 +8110,8 @@ load_configuration(const char *filename, ns_server_t *server,
 					      NS_LOGCATEGORY_GENERAL,
 					      NS_LOGMODULE_SERVER,
 					      level,
-					      "could not open entropy source "
-					      "%s: %s",
+					      "could not open "
+					      "entropy source %s: %s",
 					      randomdev,
 					      isc_result_totext(result));
 			}
@@ -8122,7 +8131,6 @@ load_configuration(const char *filename, ns_server_t *server,
 				}
 				isc_entropy_detach(&ns_g_fallbackentropy);
 			}
-#endif
 #endif
 		}
 	}
@@ -8911,6 +8919,8 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) {
 	CHECKFATAL(dns_tkeyctx_create(ns_g_mctx, ns_g_entropy,
 				      &server->tkeyctx),
 		   "creating TKEY context");
+	CHECKFATAL(isc_rng_create(ns_g_mctx, ns_g_entropy, &server->rngctx),
+	           "creating random numbers context");
 
 	/*
 	 * Setup the server task, which is responsible for coordinating
@@ -9117,7 +9127,8 @@ ns_server_destroy(ns_server_t **serverp) {
 
 	if (server->zonemgr != NULL)
 		dns_zonemgr_detach(&server->zonemgr);
-
+	if (server->rngctx != NULL)
+		isc_rng_detach(&server->rngctx);
 	if (server->tkeyctx != NULL)
 		dns_tkeyctx_destroy(&server->tkeyctx);
 
@@ -13018,10 +13029,10 @@ newzone_cfgctx_destroy(void **cfgp) {
 
 static isc_result_t
 generate_salt(unsigned char *salt, size_t saltlen) {
-	int i, n;
+	size_t i, n;
 	union {
 		unsigned char rnd[256];
-		isc_uint32_t rnd32[64];
+		isc_uint16_t rnd16[128];
 	} rnd;
 	unsigned char text[512 + 1];
 	isc_region_t r;
@@ -13031,9 +13042,10 @@ generate_salt(unsigned char *salt, size_t saltlen) {
 	if (saltlen > 256U)
 		return (ISC_R_RANGE);
 
-	n = (int) (saltlen + sizeof(isc_uint32_t) - 1) / sizeof(isc_uint32_t);
-	for (i = 0; i < n; i++)
-		isc_random_get(&rnd.rnd32[i]);
+	n = (saltlen + sizeof(isc_uint16_t) - 1) / sizeof(isc_uint16_t);
+	for (i = 0; i < n; i++) {
+		rnd.rnd16[i] = isc_rng_random(ns_g_server->rngctx);
+	}
 
 	memmove(salt, rnd.rnd, saltlen);
 
diff --git a/bin/nsupdate/nsupdate.c b/bin/nsupdate/nsupdate.c
index 46c7acf4dc..a0d0278635 100644
--- a/bin/nsupdate/nsupdate.c
+++ b/bin/nsupdate/nsupdate.c
@@ -281,9 +281,7 @@ setup_entropy(isc_mem_t *mctx, const char *randomfile, isc_entropy_t **ectx) {
 	}
 
 #ifdef ISC_PLATFORM_CRYPTORANDOM
-	if (randomfile != NULL &&
-	    strcmp(randomfile, ISC_PLATFORM_CRYPTORANDOM) == 0) {
-		randomfile = NULL;
+	if (randomfile == NULL) {
 		isc_entropy_usehook(*ectx, ISC_TRUE);
 	}
 #endif
diff --git a/bin/tests/system/pipelined/pipequeries.c b/bin/tests/system/pipelined/pipequeries.c
index 810d99e267..d7d10e2e3c 100644
--- a/bin/tests/system/pipelined/pipequeries.c
+++ b/bin/tests/system/pipelined/pipequeries.c
@@ -279,9 +279,7 @@ main(int argc, char *argv[]) {
 	ectx = NULL;
 	RUNCHECK(isc_entropy_create(mctx, &ectx));
 #ifdef ISC_PLATFORM_CRYPTORANDOM
-	if (randomfile != NULL &&
-	    strcmp(randomfile, ISC_PLATFORM_CRYPTORANDOM) == 0) {
-		randomfile = NULL;
+	if (randomfile == NULL) {
 		isc_entropy_usehook(ectx, ISC_TRUE);
 	}
 #endif
diff --git a/bin/tests/system/tkey/keycreate.c b/bin/tests/system/tkey/keycreate.c
index 4f2f5b4cc5..0894db7066 100644
--- a/bin/tests/system/tkey/keycreate.c
+++ b/bin/tests/system/tkey/keycreate.c
@@ -255,9 +255,7 @@ main(int argc, char *argv[]) {
 	ectx = NULL;
 	RUNCHECK(isc_entropy_create(mctx, &ectx));
 #ifdef ISC_PLATFORM_CRYPTORANDOM
-	if (randomfile != NULL &&
-	    strcmp(randomfile, ISC_PLATFORM_CRYPTORANDOM) == 0) {
-		randomfile = NULL;
+	if (randomfile == NULL) {
 		isc_entropy_usehook(ectx, ISC_TRUE);
 	}
 #endif
diff --git a/bin/tests/system/tkey/keydelete.c b/bin/tests/system/tkey/keydelete.c
index 0975bbe4ea..5b8a4701a8 100644
--- a/bin/tests/system/tkey/keydelete.c
+++ b/bin/tests/system/tkey/keydelete.c
@@ -182,9 +182,7 @@ main(int argc, char **argv) {
 	ectx = NULL;
 	RUNCHECK(isc_entropy_create(mctx, &ectx));
 #ifdef ISC_PLATFORM_CRYPTORANDOM
-	if (randomfile != NULL &&
-	    strcmp(randomfile, ISC_PLATFORM_CRYPTORANDOM) == 0) {
-		randomfile = NULL;
+	if (randomfile == NULL) {
 		isc_entropy_usehook(ectx, ISC_TRUE);
 	}
 #endif
diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml
index 3ecdc046d0..34c9e85f52 100644
--- a/doc/arm/Bv9ARM-book.xml
+++ b/doc/arm/Bv9ARM-book.xml
@@ -5070,22 +5070,45 @@ badresp:1,adberr:0,findfail:0,valfail:0]
 	    <term><command>random-device</command></term>
 	    <listitem>
 	      <para>
-		The source of entropy to be used by the server.  Entropy is
-		primarily needed
-		for DNSSEC operations, such as TKEY transactions and dynamic
-		update of signed
-		zones.  This options specifies the device (or file) from which
-		to read
-		entropy.  If this is a file, operations requiring entropy will
-		fail when the
-		file has been exhausted.  If not specified, the default value
-		is
-		<filename>/dev/random</filename>
-		(or equivalent) when present, and none otherwise.  The
-		<command>random-device</command> option takes
-		effect during
-		the initial configuration load at server startup time and
-		is ignored on subsequent reloads.
+		Specifies a source of entropy to be used by the server.
+		This is a device or file from which to read entropy.
+		If it is a file, operations requiring entropy
+		will fail when the file has been exhausted.
+	      </para>
+	      <para>
+		Entropy is needed for cryptographic operations such as
+		TKEY transactions, dynamic update of signed zones, and
+		generation of TSIG session keys. It is also used for
+		seeding and stirring the pseudo-random number generator,
+		which is used for less critical functions requiring
+		randomness such as generation of DNS message transaction
+		ID's.
+	      </para>
+	      <para>
+		If <command>random-device</command> is not specified, or
+		if it is set to <literal>none</literal>, entropy will be
+		read from the random number generation function supplied
+		by the cryptographic library with which BIND was linked
+		(i.e.  OpenSSL or a PKCS#11 provider).
+	      </para>
+	      <para>
+		The <command>random-device</command> option takes
+		effect during the initial configuration load at server
+		startup time and is ignored on subsequent reloads.
+	      </para>
+	      <para>
+		If BIND is built with
+		<command>configure --disable-crypto-rand</command>, then
+		entropy is <emphasis>not</emphasis> sourced from the
+		cryptographic library. In this case, if
+		<command>random-device</command> is not specified, the
+		default value is the system random device,
+		<filename>/dev/random</filename> or the equivalent.
+		This default can be overridden with
+		<command>configure --with-randomdev</command>.
+		If no system random device exists, then no entropy source
+		will be configured, and <command>named</command> will only
+		be able to use pseudo-random numbers.
 	      </para>
 	    </listitem>
 	  </varlistentry>
diff --git a/doc/arm/notes.xml b/doc/arm/notes.xml
index 7b7475b58f..49fe0a413e 100644
--- a/doc/arm/notes.xml
+++ b/doc/arm/notes.xml
@@ -128,6 +128,32 @@
 	  necessary.
 	</para>
       </listitem>
+      <listitem>
+	<para>
+	  By default, BIND now uses the random number generation functions
+	  in the cryptographic library (i.e., OpenSSL or a PKCS#11
+	  provider) as a source of high-quality randomness rather than
+	  <filename>/dev/random</filename>.  This is suitable for virtual
+	  machine environments, which may have limited entropy pools and
+	  lack hardware random number generators.
+	</para>
+	<para>
+	  This can be overridden by specifying another entropy source via
+	  the <command>random-device</command> option in
+	  <filename>named.conf</filename>, or via the <command>-r</command>
+	  command line option.  However, for functions requiring full
+	  cryptographic strength, such as DNSSEC key generation, this
+	  <emphasis>cannot</emphasis> be overridden. In particular, the
+	  <command>-r</command> command line option no longer has any
+	  effect on <command>dnssec-keygen</command>.
+	</para>
+	<para>
+	  This can be disabled by building with
+	  <command>configure --disable-crypto-rand</command>, in which
+	  case <filename>/dev/random</filename> will be the default
+	  entropy source.  [RT #31459] [RT #46047]
+	</para>
+      </listitem>
     </itemizedlist>
   </section>
 
diff --git a/lib/dns/dst_api.c b/lib/dns/dst_api.c
index 803e7b3538..29a4fef44b 100644
--- a/lib/dns/dst_api.c
+++ b/lib/dns/dst_api.c
@@ -276,8 +276,9 @@ dst_lib_init2(isc_mem_t *mctx, isc_entropy_t *ectx,
 #endif
 #if defined(OPENSSL) || defined(PKCS11CRYPTO)
 #ifdef ISC_PLATFORM_CRYPTORANDOM
-	if (dst_entropy_pool != NULL)
+	if (dst_entropy_pool != NULL) {
 		isc_entropy_sethook(dst_random_getdata);
+	}
 #endif
 #endif /* defined(OPENSSL) || defined(PKCS11CRYPTO) */
 	dst_initialized = ISC_TRUE;
@@ -2015,10 +2016,12 @@ dst__entropy_getdata(void *buf, unsigned int len, isc_boolean_t pseudo) {
 	else
 		flags |= ISC_ENTROPY_BLOCKING;
 #ifdef ISC_PLATFORM_CRYPTORANDOM
+	/* get entropy directly from crypto provider */
 	return (dst_random_getdata(buf, len, NULL, flags));
 #else
+	/* get entropy from entropy source or hook function */
 	return (isc_entropy_getdata(dst_entropy_pool, buf, len, NULL, flags));
-#endif
+#endif /* ISC_PLATFORM_CRYPTORANDOM */
 #endif /* PKCS11CRYPTO */
 }
 
diff --git a/lib/dns/include/dst/dst.h b/lib/dns/include/dst/dst.h
index d9b6ab6bfb..e8c1a3c287 100644
--- a/lib/dns/include/dst/dst.h
+++ b/lib/dns/include/dst/dst.h
@@ -161,8 +161,18 @@ isc_result_t
 dst_random_getdata(void *data, unsigned int length,
 		   unsigned int *returned, unsigned int flags);
 /*%<
- * \brief Return data from the crypto random generator.
- * Specialization of isc_entropy_getdata().
+ * Gets random data from the random generator provided by the
+ * crypto library, if BIND was built with --enable-crypto-rand.
+ *
+ * See isc_entropy_getdata() for parameter usage. Normally when
+ * this function is available, it will be set up as a hook in the
+ * entropy context, so that isc_entropy_getdata() is a front-end to
+ * this function.
+ *
+ * Returns:
+ * \li	ISC_R_SUCCESS on success
+ * \li	ISC_R_NOTIMPLEMENTED if BIND is built with --disable-crypto-rand
+ * \li	DST_R_OPENSSLFAILURE, DST_R_CRYPTOFAILURE, or other codes on error
  */
 
 isc_boolean_t
diff --git a/lib/dns/openssl_link.c b/lib/dns/openssl_link.c
index c1e1bde95a..91e87d00b4 100644
--- a/lib/dns/openssl_link.c
+++ b/lib/dns/openssl_link.c
@@ -482,7 +482,8 @@ dst__openssl_getengine(const char *engine) {
 
 isc_result_t
 dst_random_getdata(void *data, unsigned int length,
-		   unsigned int *returned, unsigned int flags) {
+		   unsigned int *returned, unsigned int flags)
+{
 #ifdef ISC_PLATFORM_CRYPTORANDOM
 #ifndef DONT_REQUIRE_DST_LIB_INIT
 	INSIST(dst__memory_pool != NULL);
diff --git a/lib/isc/include/isc/entropy.h b/lib/isc/include/isc/entropy.h
index d9deb8ad9b..2d373630ae 100644
--- a/lib/isc/include/isc/entropy.h
+++ b/lib/isc/include/isc/entropy.h
@@ -9,8 +9,6 @@
  * information regarding copyright ownership.
  */
 
-/* $Id: entropy.h,v 1.35 2009/10/19 02:37:08 marka Exp $ */
-
 #ifndef ISC_ENTROPY_H
 #define ISC_ENTROPY_H 1
 
@@ -190,9 +188,8 @@ isc_entropy_createcallbacksource(isc_entropy_t *ent,
 /*!<
  * \brief Create an entropy source that is polled via a callback.
  *
- * This would
- * be used when keyboard input is used, or a GUI input method.  It can
- * also be used to hook in any external entropy source.
+ * This would be used when keyboard input is used, or a GUI input method.
+ * It can also be used to hook in any external entropy source.
  *
  * Samples are added via isc_entropy_addcallbacksample(), below.
  * _addcallbacksample() is the only function which may be called from
@@ -233,15 +230,32 @@ isc_result_t
 isc_entropy_getdata(isc_entropy_t *ent, void *data, unsigned int length,
 		    unsigned int *returned, unsigned int flags);
 /*!<
- * \brief Extract data from the entropy pool.  This may load the pool from various
- * sources.
+ * \brief Get random data from entropy pool 'ent'.
+ *
+ * If a hook has been set up using isc_entropy_sethook() and
+ * isc_entropy_usehook(), then the hook function will be called to get
+ * random data.
+ *
+ * Otherwise, randomness is extracted from the entropy pool set up in BIND.
+ * This may cause the pool to be loaded from various sources. Ths is done
+ * by stirring the pool and returning a part of hash as randomness.
+ * (Note that no secrets are given away here since parts of the hash are
+ * XORed together before returning.)
+ *
+ * 'flags' may contain ISC_ENTROPY_GOODONLY, ISC_ENTROPY_PARTIAL, or
+ * ISC_ENTROPY_BLOCKING. These will be honored if the hook function is
+ * not in use. If it is, the flags will be passed to the hook function
+ * but it may ignore them.
  *
- * Do this by stiring the pool and returning a part of hash as randomness.
- * Note that no secrets are given away here since parts of the hash are
- * xored together before returned.
+ * Up to 'length' bytes of randomness are retrieved and copied into 'data'.
+ * (If 'returned' is not NULL, and the number of bytes copied is less than
+ * 'length' - which may happen if ISC_ENTROPY_PARTIAL was used - then the
+ * number of bytes copied will be stored in *returned.)
  *
- * Honor the request from the caller to only return good data, any data,
- * etc.
+ * Returns:
+ * \li	ISC_R_SUCCESS on success
+ * \li	ISC_R_NOENTROPY if entropy pool is empty
+ * \li	other error codes are possible when a hook is in use
  */
 
 void
@@ -306,13 +320,21 @@ isc_entropy_usebestsource(isc_entropy_t *ectx, isc_entropysource_t **source,
 void
 isc_entropy_usehook(isc_entropy_t *ectx, isc_boolean_t onoff);
 /*!<
- * \brief Mark/unmark the given entropy structure as being hooked.
+ * \brief Configure entropy context 'ectx' to use the hook function
+ *
+ * Sets the entropy context to call the hook function for random number
+ * generation, if such a function has been configured via
+ * isc_entropy_sethook(), whenever isc_entropy_getdata() is called.
  */
 
 void
 isc_entropy_sethook(isc_entropy_getdata_t myhook);
 /*!<
- * \brief Set the getdata hook (e.g., for a crypto random generator).
+ * \brief Set the hook function.
+ *
+ * The hook function is a global value: only one hook function
+ * can be set in the system. Individual entropy contexts may be
+ * configured to use it, or not, by calling isc_entropy_usehook().
  */
 
 ISC_LANG_ENDDECLS
diff --git a/lib/isc/include/isc/random.h b/lib/isc/include/isc/random.h
index ba53ebf35c..b57572842c 100644
--- a/lib/isc/include/isc/random.h
+++ b/lib/isc/include/isc/random.h
@@ -9,8 +9,6 @@
  * information regarding copyright ownership.
  */
 
-/* $Id: random.h,v 1.20 2009/01/17 23:47:43 tbox Exp $ */
-
 #ifndef ISC_RANDOM_H
 #define ISC_RANDOM_H 1
 
@@ -21,13 +19,23 @@
 #include <isc/mutex.h>
 
 /*! \file isc/random.h
- * \brief Implements a random state pool which will let the caller return a
- * series of possibly non-reproducible random values.
+ * \brief Implements pseudo random number generators.
+ *
+ * Two pseudo-random number generators are implemented, in isc_random_*
+ * and isc_rng_*. Neither one is very strong; they should not be used
+ * in cryptography functions.
+ *
+ * isc_random_* is based on arc4random if it is available on the system.
+ * Otherwise it is based on the posix srand() and rand() functions.
+ * It is useful for jittering values a bit here and there, such as
+ * timeouts, etc, but should not be relied upon to generate
+ * unpredictable sequences (for example, when choosing transaction IDs).
  *
- * Note that the
- * strength of these numbers is not all that high, and should not be
- * used in cryptography functions.  It is useful for jittering values
- * a bit here and there, such as timeouts, etc.
+ * isc_rng_* is based on ChaCha20, and is seeded and stirred from the
+ * system entropy source. It is stronger than isc_random_* and can
+ * be used for generating unpredictable sequences. It is still not as
+ * good as using system entropy directly (see entropy.h) and should not
+ * be used for cryptographic functions such as key generation.
  */
 
 ISC_LANG_BEGINDECLS
@@ -115,8 +123,8 @@ isc_rng_random(isc_rng_t *rngctx);
 isc_uint16_t
 isc_rng_uniformrandom(isc_rng_t *rngctx, isc_uint16_t upper_bound);
 /*%<
- * Returns a uniformly distributed pseudo random 16-bit unsigned
- * integer.
+ * Returns a uniformly distributed pseudo-random 16-bit unsigned integer
+ * less than 'upper_bound'.
  */
 
 ISC_LANG_ENDDECLS
diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c
index 8d496ff9ce..dd08187312 100644
--- a/lib/isccfg/namedconf.c
+++ b/lib/isccfg/namedconf.c
@@ -1106,7 +1106,7 @@ options_clauses[] = {
 	{ "pid-file", &cfg_type_qstringornone, 0 },
 	{ "port", &cfg_type_uint32, 0 },
 	{ "querylog", &cfg_type_boolean, 0 },
-	{ "random-device", &cfg_type_qstring, 0 },
+	{ "random-device", &cfg_type_qstringornone, 0 },
 	{ "recursing-file", &cfg_type_qstring, 0 },
 	{ "recursive-clients", &cfg_type_uint32, 0 },
 	{ "reserved-sockets", &cfg_type_uint32, 0 },
-- 
2.14.4