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