Page MenuHomeFreeBSD

D19944.id56360.diff
No OneTemporary

D19944.id56360.diff

Index: UPDATING
===================================================================
--- UPDATING
+++ UPDATING
@@ -31,6 +31,30 @@
disable the most expensive debugging functionality run
"ln -s 'abort:false,junk:false' /etc/malloc.conf".)
+20190417:
+ The following knobs have been added related to tradeoffs between
+ safe use of the random device and availability in the absence of
+ entropy:
+
+ kern.random.initial_seeding.bypass_before_seeding: tunable; set
+ non-zero to bypass the random device prior to seeding, or zero to
+ block random requests until the random device is initially seeded.
+ For now, set to 1 (unsafe) by default to restore pre-r346250 boot
+ availability properties.
+
+ kern.random.initial_seeding.read_random_bypassed_before_seeding:
+ read-only diagnostic sysctl that is set when bypass is enabled and
+ read_random(9) is bypassed, to enable programmatic handling of this
+ initial condition, if desired.
+
+ kern.random.initial_seeding.arc4random_bypassed_before_seeding:
+ Similar to the above, but for for arc4random(9) initial seeding.
+
+ kern.random.initial_seeding.disable_bypass_warnings: tunable; set
+ non-zero to disable warnings in dmesg when the same conditions are
+ met as for the diagnostic sysctls above. Defaults to zero, i.e.,
+ produce warnings in dmesg when the conditions are met.
+
20190416:
The tunable "security.stack_protect.permit_nonrandom_cookies" may be
set to a non-zero value to boot systems that do not provide early
Index: sys/dev/random/random_infra.c
===================================================================
--- sys/dev/random/random_infra.c
+++ sys/dev/random/random_infra.c
@@ -43,7 +43,61 @@
#include <dev/random/randomdev.h>
/* Set up the sysctl root node for the entropy device */
-SYSCTL_NODE(_kern, OID_AUTO, random, CTLFLAG_RW, 0, "Cryptographically Secure Random Number Generator");
+SYSCTL_NODE(_kern, OID_AUTO, random, CTLFLAG_RW, 0,
+ "Cryptographically Secure Random Number Generator");
+SYSCTL_NODE(_kern_random, OID_AUTO, initial_seeding, CTLFLAG_RW, 0,
+ "Initial seeding control and information");
+
+/*
+ * N.B., this is a dangerous default, but it matches the behavior prior to
+ * r346250 (and, say, OpenBSD -- although they get some guaranteed saved
+ * entropy from the prior boot because of their KARL system, on RW media).
+ */
+bool random_bypass_before_seeding = true;
+SYSCTL_BOOL(_kern_random_initial_seeding, OID_AUTO,
+ bypass_before_seeding, CTLFLAG_RDTUN, &random_bypass_before_seeding,
+ 0, "If set non-zero, bypass the random device in requests for random "
+ "data when the random device is not yet seeded. This is considered "
+ "dangerous. Ordinarily, the random device will block requests until "
+ "it is seeded by sufficient entropy.");
+
+/*
+ * This is a read-only diagnostic that reports the combination of the former
+ * tunable and actual bypass. It is intended for programmatic inspection by
+ * userspace administrative utilities after boot.
+ */
+bool read_random_bypassed_before_seeding = false;
+SYSCTL_BOOL(_kern_random_initial_seeding, OID_AUTO,
+ read_random_bypassed_before_seeding, CTLFLAG_RD,
+ &read_random_bypassed_before_seeding, 0, "If non-zero, the random device "
+ "was bypassed because the 'bypass_before_seeding' knob was enabled and a "
+ "request was submitted prior to initial seeding.");
+
+/*
+ * This is a read-only diagnostic that reports the combination of the former
+ * tunable and actual bypass for arc4random initial seeding. It is intended
+ * for programmatic inspection by userspace administrative utilities after
+ * boot.
+ */
+bool arc4random_bypassed_before_seeding = false;
+SYSCTL_BOOL(_kern_random_initial_seeding, OID_AUTO,
+ arc4random_bypassed_before_seeding, CTLFLAG_RD,
+ &arc4random_bypassed_before_seeding, 0, "If non-zero, the random device "
+ "was bypassed when initially seeding the kernel arc4random(9), because "
+ "the 'bypass_before_seeding' knob was enabled and a request was submitted "
+ "prior to initial seeding.");
+
+/*
+ * This knob is for users who do not want additional warnings in their logs
+ * because they intend to handle bypass by inspecting the status of the
+ * diagnostic sysctls.
+ */
+bool random_bypass_disable_warnings = false;
+SYSCTL_BOOL(_kern_random_initial_seeding, OID_AUTO,
+ disable_bypass_warnings, CTLFLAG_RDTUN,
+ &random_bypass_disable_warnings, 0, "If non-zero, do not log a warning "
+ "if the 'bypass_before_seeding' knob is enabled and a request is "
+ "submitted prior to initial seeding.");
MALLOC_DEFINE(M_ENTROPY, "entropy", "Entropy harvesting buffers and data structures");
Index: sys/dev/random/randomdev.h
===================================================================
--- sys/dev/random/randomdev.h
+++ sys/dev/random/randomdev.h
@@ -37,6 +37,7 @@
#ifdef SYSCTL_DECL /* from sysctl.h */
SYSCTL_DECL(_kern_random);
+SYSCTL_DECL(_kern_random_initial_seeding);
#define RANDOM_CHECK_UINT(name, min, max) \
static int \
@@ -55,6 +56,11 @@
MALLOC_DECLARE(M_ENTROPY);
+extern bool random_bypass_before_seeding;
+extern bool read_random_bypassed_before_seeding;
+extern bool arc4random_bypassed_before_seeding;
+extern bool random_bypass_disable_warnings;
+
#endif /* _KERNEL */
struct harvest_event;
Index: sys/dev/random/randomdev.c
===================================================================
--- sys/dev/random/randomdev.c
+++ sys/dev/random/randomdev.c
@@ -236,11 +236,15 @@
}
/*-
- * Kernel API version of read_random().
- * This is similar to random_alg_read(),
- * except it doesn't interface with uio(9).
- * It cannot assumed that random_buf is a multiple of
- * RANDOM_BLOCKSIZE bytes.
+ * Kernel API version of read_random(). This is similar to read_random_uio(),
+ * except it doesn't interface with uio(9). It cannot assumed that random_buf
+ * is a multiple of RANDOM_BLOCKSIZE bytes.
+ *
+ * If the tunable 'kern.random.initial_seeding.bypass_before_seeding' is set
+ * non-zero, silently fail to emit random data (matching the pre-r346250
+ * behavior). If read_random is called prior to seeding and bypassed because
+ * of this tunable, the condition is reported in the read-only sysctl
+ * 'kern.random.initial_seeding.read_random_bypassed_before_seeding'.
*/
void
READ_RANDOM(void *random_buf, u_int len)
@@ -249,12 +253,31 @@
KASSERT(random_buf != NULL, ("No suitable random buffer in %s", __func__));
p_random_alg_context->ra_pre_read();
+
+ if (len == 0)
+ return;
+
/* (Un)Blocking logic */
- if (!p_random_alg_context->ra_seeded())
+ if (__predict_false(!p_random_alg_context->ra_seeded())) {
+ if (random_bypass_before_seeding) {
+ if (!read_random_bypassed_before_seeding) {
+ if (!random_bypass_disable_warnings)
+ printf("read_random: WARNING: bypassing"
+ " request for random data because "
+ "the random device is not yet "
+ "seeded and the knob "
+ "'bypass_before_seeding' was "
+ "enabled.\n");
+ read_random_bypassed_before_seeding = true;
+ }
+ /* Avoid potentially leaking stack garbage */
+ memset(random_buf, 0, len);
+ return;
+ }
+
(void)randomdev_wait_until_seeded(SEEDWAIT_UNINTERRUPTIBLE);
+ }
read_rate_increment(roundup2(len, sizeof(uint32_t)));
- if (len == 0)
- return;
/*
* The underlying generator expects multiples of
* RANDOM_BLOCKSIZE.
Index: sys/libkern/arc4random.c
===================================================================
--- sys/libkern/arc4random.c
+++ sys/libkern/arc4random.c
@@ -41,6 +41,9 @@
#include <sys/time.h>
#include <crypto/chacha20/chacha.h>
+#include <crypto/sha2/sha256.h>
+#include <dev/random/randomdev.h>
+#include <machine/cpu.h>
#define CHACHA20_RESEED_BYTES 65536
#define CHACHA20_RESEED_SECONDS 300
@@ -77,12 +80,43 @@
struct timeval tv_now;
u_int8_t key[CHACHA20_KEYBYTES];
- /*
- * If the loader(8) did not have an entropy stash from the previous
- * shutdown to load, then we will block. The answer is to make sure
- * there is an entropy stash at shutdown time.
- */
- read_random(key, CHACHA20_KEYBYTES);
+ if (__predict_false(random_bypass_before_seeding && !is_random_seeded())) {
+ SHA256_CTX ctx;
+ uint64_t cc;
+ uint32_t fver;
+
+ if (!arc4random_bypassed_before_seeding) {
+ arc4random_bypassed_before_seeding = true;
+ if (!random_bypass_disable_warnings)
+ printf("arc4random: WARNING: initial seeding "
+ "bypassed the cryptographic random device "
+ "because it was not yet seeded and the "
+ "knob 'bypass_before_seeding' was "
+ "enabled.\n");
+ }
+
+ /* Last ditch effort to inject something in a bad condition. */
+ cc = get_cyclecount();
+ SHA256_Init(&ctx);
+ SHA256_Update(&ctx, key, sizeof(key));
+ SHA256_Update(&ctx, &cc, sizeof(cc));
+ fver = __FreeBSD_version;
+ SHA256_Update(&ctx, &fver, sizeof(fver));
+ _Static_assert(sizeof(key) == SHA256_DIGEST_LENGTH,
+ "make sure 256 bits is still 256 bits");
+ SHA256_Final(key, &ctx);
+ } else {
+ /*
+ * If the loader(8) did not have an entropy stash from the
+ * previous shutdown to load, then we will block. The answer is
+ * to make sure there is an entropy stash at shutdown time.
+ *
+ * On the other hand, if the random_bypass_before_seeding knob
+ * was set and we landed in this branch, we know this won't
+ * block because we know the random device is seeded.
+ */
+ read_random(key, CHACHA20_KEYBYTES);
+ }
getmicrouptime(&tv_now);
mtx_lock(&chacha20->mtx);
chacha_keysetup(&chacha20->ctx, key, CHACHA20_KEYBYTES*8);
Index: sys/mips/conf/PB92
===================================================================
--- sys/mips/conf/PB92
+++ sys/mips/conf/PB92
@@ -133,5 +133,5 @@
device ether
#device md
#device bpf
-#device random
+device random
#device if_bridge
Index: sys/sys/param.h
===================================================================
--- sys/sys/param.h
+++ sys/sys/param.h
@@ -60,7 +60,7 @@
* in the range 5 to 9.
*/
#undef __FreeBSD_version
-#define __FreeBSD_version 1300019 /* Master, propagated to newvers */
+#define __FreeBSD_version 1300020 /* Master, propagated to newvers */
/*
* __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,

File Metadata

Mime Type
text/plain
Expires
Fri, Nov 28, 9:42 AM (10 h, 32 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
26280258
Default Alt Text
D19944.id56360.diff (10 KB)

Event Timeline