From 5e1014de53008a1114fce1b7b86ba929f98d3261 Mon Sep 17 00:00:00 2001
From: Taylor R Campbell <riastradh@NetBSD.org>
Date: Mon, 22 Jul 2019 02:17:00 +0000
Subject: [PATCH] New system call getrandom(buf, len, flags).

Semantics matches Linux.  Usage:

	uint8_t buf[32];
	if (getrandom(buf, sizeof buf, GRND_NONBLOCK))
		err("unable to generate secrets");
	/* buf is now a 256-bit key fit for cryptography.  */

getrandom blocks (or fails with EWOULDBLOCK, with GRND_NONBLOCK) only
until the system has been seeded; then it never blocks (or fails with
EWOULDBLOCK) again.  Threat model excludes kernel memory disclosure.

Applications should use fault injection in tests to ensure the
blocking/EWOULDBLOCK code path is exercised, since most systems will be
seeded at boot.

No need for device nodes in a chroot like /dev/random in order to use
getrandom.
---
 lib/libc/sys/Makefile.inc |   7 +-
 lib/libc/sys/getrandom.2  | 207 ++++++++++++++++++++++++++++
 sys/kern/files.kern       |   1 +
 sys/kern/kern_rndq.c      |  33 +++++
 sys/kern/sys_getrandom.c  | 281 ++++++++++++++++++++++++++++++++++++++
 sys/kern/syscalls.master  |   2 +
 sys/sys/random.h          |  45 ++++++
 sys/sys/rnd.h             |   1 +
 8 files changed, 574 insertions(+), 3 deletions(-)
 create mode 100644 lib/libc/sys/getrandom.2
 create mode 100644 sys/kern/sys_getrandom.c
 create mode 100644 sys/sys/random.h

diff --git a/lib/libc/sys/Makefile.inc b/lib/libc/sys/Makefile.inc
index 398468f09734..ab68c4baba5e 100644
--- a/lib/libc/sys/Makefile.inc
+++ b/lib/libc/sys/Makefile.inc
@@ -110,7 +110,7 @@ ASM=	access.S acct.S \
 		fstatvfs1.S fstatat.S  __futimes50.S futimens.S \
 	__getcwd.S __getdents30.S __getfh30.S getvfsstat.S getgroups.S\
 		__getitimer50.S __getlogin.S getpeername.S getpgid.S getpgrp.S \
-		getpriority.S getrlimit.S __getrusage50.S getsid.S \
+		getpriority.S getrandom.S getrlimit.S __getrusage50.S getsid.S \
 		getsockname.S getsockopt.S getsockopt2.S __gettimeofday50.S \
 	ioctl.S \
 	kqueue.S kqueue1.S ktrace.S \
@@ -250,8 +250,9 @@ MAN+=	accept.2 access.2 acct.2 adjtime.2 bind.2 brk.2 chdir.2 \
 	flock.2 fork.2 fsync.2 getcontext.2 getdents.2 \
 	getfh.2 getvfsstat.2 getgid.2 getgroups.2 \
 	getitimer.2 getlogin.2 getpeername.2 getpgrp.2 getpid.2 \
-	getpriority.2 getrlimit.2 getrusage.2 getsid.2 getsockname.2 \
-	getsockopt.2 gettimeofday.2 getuid.2 intro.2 ioctl.2 issetugid.2 \
+	getpriority.2 getrandom.2 getrlimit.2 getrusage.2 getsid.2 \
+	getsockname.2 getsockopt.2 gettimeofday.2 getuid.2 \
+	intro.2 ioctl.2 issetugid.2 \
 	kill.2 kqueue.2 ktrace.2 _ksem.2 \
 	lfs_bmapv.2 lfs_markv.2 lfs_segclean.2 lfs_segwait.2 \
 	link.2 listen.2 lseek.2 \
diff --git a/lib/libc/sys/getrandom.2 b/lib/libc/sys/getrandom.2
new file mode 100644
index 000000000000..7f052881cfe6
--- /dev/null
+++ b/lib/libc/sys/getrandom.2
@@ -0,0 +1,207 @@
+.\"	$NetBSD$
+.\"
+.\" Copyright (c) 2019 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to The NetBSD Foundation
+.\" by Taylor R. Campbell.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd July 21, 2019
+.Dt GETRANDOM 2
+.Os
+.Sh NAME
+.Nm getrandom
+.Nd wait for system entropy to be seeded and randomly fill buffer
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/random.h
+.Ft int
+.Fn getrandom "void *buf" "size_t len" "int flags"
+.Sh DESCRIPTION
+The
+.Fn getrandom
+function blocks until the system has been seeded with entropy, and then
+fills the buffer starting at
+.Fa buf
+with
+.Fa len
+bytes chosen uniformly at random, which are unpredictable secrets fit
+for use in cryptography.
+.Pp
+The following flags may be
+.Em or Ns 'ed
+together to form the
+.Fa flags
+argument:
+.Bl -tag -width GRND_NONBLOCK
+.It Dv GRND_NONBLOCK
+If the buffer cannot be filled immediately, fail with
+.Er EWOULDBLOCK
+instead of blocking.
+The buffer may be partially initialized in this case, but the caller
+has no way to ascertain how much of it was initialized.
+.Pp
+The length
+.Fa len
+must not exceed 33554431; however, callers should limit their requests
+to 32 bytes and use a stream cipher to expand 32-byte keys into longer
+pads, like the increasingly inaccurately named
+.Xr arc4random 3
+does with ChaCha.
+.It Dv GRND_RANDOM
+Enable compatibility with legacy and Linux applications by blocking
+more often.
+.Pp
+The length
+.Fa len
+must not exceed 512; however, callers should limit their requests
+to 32 bytes and use a stream cipher to expand 32-byte keys into longer
+pads.
+.El
+.Sh SECURITY MODEL
+The
+.Fn getrandom
+system call assumes the operating system has access to a hardware
+entropy source, such as a human flipping coins without surveillance or
+a seed file managed by
+.Xr rndctl 8 .
+After enough coin flips (256 is enough) have been written by root to
+.Pa /dev/random
+once, or after the seed file has been read once,
+.Fn getrandom
+will consider the system to be unpredictable and will never block
+again.
+.Pp
+Once the system is seeded, the output of
+.Fn getrandom
+is indistinguishable from uniform random with more than negligible
+advantage by standards of modern cryptography.
+.Pp
+The
+.Fn getrandom
+system call
+.Em does not
+protect against an adversary who can find a kernel memory disclosure
+bug in
+.Nx
+and use it to dump the operating system's seed.
+Absent such an adversary, entropy does not
+.Dq run out .
+.Sh RETURN VALUES
+.Rv -std getrandom
+.Sh EXAMPLES
+Generate a key, but abort immediately if the system is not yet seeded:
+.Bd -literal
+	uint8_t key[32];
+
+	if (getrandom(key, sizeof key, GRND_NONBLOCK))
+		err("getrandom");
+
+	... do cryptography using key ...
+.Ed
+.Pp
+Generate a key, or block until the system has been seeded, if the
+application can tolerate indefinite blocking:
+.Bd -literal
+	uint8_t key[32];
+
+	printf("if this hangs get out a coin and start flipping\en");
+	printf("and then do `echo ththhh... >> /dev/random'\en");
+	fflush(stdout);
+	if (ferror(stdout))
+		err("printf");
+
+	if (getrandom(key, sizeof key, 0))
+		err("getrandom");
+
+	... do cryptography using key ....
+.Ed
+.Pp
+Beware that the blocking code path is unlikely to be exercised, and
+may need special attention like fault injection to test it.
+Consider aborting without blocking instead.
+.Sh ERRORS
+.Fn getrandom
+will fail if:
+.Bl -tag -width [EFAULT]
+.It Bq Er EFAULT
+Part of
+.Fa buf
+points outside the process's allocated address space.
+.It Bq Er EINTR
+A signal was delivered before
+.Fn getrandom
+could complete.
+.It Bq Er EINVAL
+The
+.Fa len
+argument was too large or the
+.Fa flags
+argument was invalid.
+.It Bq Er EWOULDBLOCK
+The request cannot be served immediately and
+.Fa GRND_NONBLOCK
+was specified.
+.El
+.Sh SEE ALSO
+.Xr arc4random 3 ,
+.Xr rnd 4 ,
+.Xr boot.cfg 5 ,
+.Xr cprng 9 ,
+.Xr rnd 9
+.Sh HISTORY
+The
+.Fn getrandom
+function first appeared in Linux 3.17 and
+.Nx 10.0 .
+.Sh CAVEATS
+Applications cannot generate secrets before the system has been
+seeded.
+If
+.Fn getrandom
+fails because the system is not yet seeded, applications can either
+abort or block until the system has been seeded (or proceed without
+secrets, e.g. by disabling networking functionality).
+.Pp
+Since many systems are seeded automatically by
+.Xr sysinst 8
+and
+.Xr rndctl 8 ,
+or have hardware entropy sources built-in, the failure is unlikely to
+happen during what are otherwise extensive tests.
+Applications should therefore be careful to test
+.Fn getrandom
+failure with fault injection simulating failure or blocking.
+.Sh BUGS
+There is no way to do a multiplexed wait for the system to be seeded,
+like with
+.Xr select 2 ,
+.Xr kqueue 2 ,
+etc.
+Applications can read a single byte from
+.Pa /dev/random ,
+but like
+.Dv GRND_RANDOM
+it may block indefinitely even if the system has been seeded.
diff --git a/sys/kern/files.kern b/sys/kern/files.kern
index 63dca2a29579..4175655c1790 100644
--- a/sys/kern/files.kern
+++ b/sys/kern/files.kern
@@ -154,6 +154,7 @@ file	kern/subr_xcall.c		kern
 file	kern/sys_aio.c			aio
 file	kern/sys_descrip.c		kern
 file	kern/sys_generic.c		kern
+file	kern/sys_getrandom.c		kern
 file	kern/sys_module.c		kern
 file	kern/sys_mqueue.c		mqueue
 file	kern/sys_lwp.c			kern
diff --git a/sys/kern/kern_rndq.c b/sys/kern/kern_rndq.c
index 7135a07b481d..54c718c35d50 100644
--- a/sys/kern/kern_rndq.c
+++ b/sys/kern/kern_rndq.c
@@ -1723,3 +1723,36 @@ rnd_system_ioctl(struct file *fp, u_long cmd, void *addr)
 
 	return ret;
 }
+
+/*
+ * rnd_wait_for_initial_entropy()
+ *
+ *	Wait until the entropy pool has been seeded, or until
+ *	interruption.  Return 0 on success, or EINTR/ERESTART on
+ *	interruption.  Never fails any other way.
+ *
+ *	WARNING: This function may almost never block, so care must be
+ *	taken to avoid relying on it not to block in a code path that
+ *	uses it.
+ */
+int
+rnd_wait_for_initial_entropy(void)
+{
+	int error = 0;
+
+	/*
+	 * If the pool has not yet been seeded, wait for it under the
+	 * lock.  (Someone else may have concurrently seeded it and
+	 * already signalled the condvar by the time we acquire the
+	 * lock.)
+	 */
+	mutex_spin_enter(&rnd_global.lock);
+	while (!rnd_initial_entropy) {
+		error = cv_wait_sig(&rnd_global.cv, &rnd_global.lock);
+		if (error)
+			break;
+	}
+	mutex_spin_exit(&rnd_global.lock);
+
+	return error;
+}
diff --git a/sys/kern/sys_getrandom.c b/sys/kern/sys_getrandom.c
new file mode 100644
index 000000000000..1c2234713f4e
--- /dev/null
+++ b/sys/kern/sys_getrandom.c
@@ -0,0 +1,281 @@
+/*	$NetBSD$	*/
+
+/*-
+ * Copyright (c) 2019 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Taylor R. Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/cprng.h>
+#include <sys/errno.h>
+#include <sys/fcntl.h>
+#include <sys/proc.h>
+#include <sys/random.h>
+#include <sys/rnd.h>
+#include <sys/syscallargs.h>
+#include <sys/systm.h>
+
+/*
+ * getrandom_sensible(ubuf, len, block)
+ *
+ *	If the entropy pool has been seeded, copy len uniform random
+ *	bytes into ubuf, or return EINTR if interrupted.  If the
+ *	entropy pool has not yet been seeded, then block, or return
+ *	EWOULDBLOCK if block=false.
+ *
+ *	Limited to 33554431 bytes, but callers should only ever read at
+ *	most 32 bytes as a key for a stream cipher to expand them into
+ *	a longer pad.
+ */
+static int
+getrandom_sensible(void *ubuf, size_t len, bool block)
+{
+	char name[16];
+	struct cprng_strong *cprng;
+	uint8_t buf[32];
+	uint8_t *p = ubuf;
+	size_t n = len;
+	int cflags;
+	int error;
+
+	CTASSERT(sizeof buf <= CPRNG_MAX_LEN);
+
+	/*
+	 * Reject overly large requests to limit time spent in kernel.
+	 * This number is from Linux; it is unreasonably high -- 32 is
+	 * sufficient for any modern cryptography.
+	 */
+	if (len > 33554431)
+		return EIO;
+
+	/* Check whether we have been seeded.  */
+	if (!rnd_initial_entropy) {
+		/*
+		 * If we have not been seeded, either return
+		 * EWOULDBLOCK, or block until we have been.
+		 */
+		if (!block)
+			return EWOULDBLOCK;
+		error = rnd_wait_for_initial_entropy();
+		if (error)
+			return error;
+	}
+
+	/* We have now been seeded.  */
+	KASSERT(rnd_initial_entropy);
+
+	/*
+	 * Flags:
+	 *
+	 *	- CPRNG_HARD: Compute AES128_k0(0) || AES128_k1(0) ||
+	 *	  ..., rather than AES128_k(0) || AES128_k(1) || ...,
+	 *	  where the the 128-bit keys k, k0, k1 are drawn
+	 *	  independently from the >>128-bit entropy pool.
+	 *	  (Alternative: Change CPRNG to just use AES-256, or,
+	 *	  better, ChaCha, instead of AES-128.)
+	 *
+	 *	- CPRNG_INIT_ANY: Suppress warning message if pool is
+	 *	  not yet seeded during cprng_strong_create --
+	 *	  shouldn't happen anyway because we just waited for
+	 *	  the pool to be seeded.
+	 *
+	 *	- CPRNG_REKEY_ANY: Generate k0, k1, ..., as needed
+	 *	  without waiting.  Suppress warning message on reseed
+	 *	  during cprng_strong -- we just waited for the pool to
+	 *	  be seeded.
+	 */
+	cflags = 0;
+	cflags |= CPRNG_HARD;
+	cflags |= CPRNG_INIT_ANY;
+	cflags |= CPRNG_REKEY_ANY;
+
+	/*
+	 * Create a private CPRNG instance named `grndu1234' in pid
+	 * 1234.
+	 *
+	 * XXX cprng_strong_create may block for allocation, silly.
+	 */
+	(void)snprintf(name, sizeof name, "grndu%jd",
+	    (intmax_t)curproc->p_pid);
+	cprng = cprng_strong_create(name, IPL_NONE, cflags);
+
+	/* Generate data.  */
+	while (n) {
+		size_t m = cprng_strong(cprng, buf, MIN(n, sizeof buf), 0);
+
+		KASSERT(0 < m);
+		KASSERT(m <= MIN(n, sizeof buf));
+		error = copyout(buf, p, m);
+		p += m;
+		n -= m;
+
+		/* Check for interruption if this is a large request.  */
+		if (__predict_false(len > 256) &&
+		    __predict_false(curlwp->l_flag & LW_PENDSIG) &&
+		    sigispending(curlwp, 0)) {
+			error = EINTR;
+			break;
+		}
+	}
+
+	/* Destroy the private CPRNG instance.  */
+	cprng_strong_destroy(cprng);
+
+	return error;
+}
+
+/*
+ * getrandom_silly(ubuf, len, block)
+ *
+ *	Copy len uniform random bytes into ubuf, or return EINTR if
+ *	interrupted.  Block, or return EWOULDBLOCK if block=false, if
+ *	the system hasn't been seeded or if there's `not enough
+ *	entropy' because of `entropy depletion'.
+ *
+ *	This silly concept of `entropy depletion' has no place in
+ *	modern cryptography, with which a secret 32-byte key can be
+ *	expanded into an arbitrarily long bit string that cannot be
+ *	distinguished from uniform random by anyone without the key.
+ *
+ *	Limited to 512 bytes, but callers should only ever read at most
+ *	32 bytes as a key for a stream cipher to expand them into a
+ *	longer pad.
+ */
+static int
+getrandom_silly(void *ubuf, size_t len, bool block)
+{
+	char name[16];
+	struct cprng_strong *cprng;
+	uint8_t buf[32];
+	uint8_t *p = ubuf;
+	size_t n = len;
+	int cflags;
+	int error;
+
+	CTASSERT(sizeof buf <= CPRNG_MAX_LEN);
+
+	if (len > 512)
+		return EIO;
+
+	/*
+	 * Flags:
+	 *
+	 *	- CPRNG_HARD: Compute AES128_k0(0) || AES128_k1(0) ||
+	 *	  ..., rather than AES128_k(0) || AES128_k(1) || ...,
+	 *	  where the the 128-bit keys k, k0, k1 are drawn
+	 *	  independently from the >>128-bit entropy pool.
+	 *	  (Alternative: Change CPRNG to just use AES-256, or,
+	 *	  better, ChaCha, instead of AES-128.)
+	 *
+	 *	- CPRNG_INIT_ANY: Suppress warning message if pool is
+	 *	  not yet seeded during cprng_strong_create --
+	 *	  shouldn't happen anyway because we just waited for
+	 *	  the pool to be seeded.
+	 *
+	 *	- CPRNG_USE_CV: Block in cprng_strong when we don't
+	 *	  pass FNONBLOCK.
+	 */
+	cflags = 0;
+	cflags |= CPRNG_HARD;
+	cflags |= CPRNG_INIT_ANY;
+	if (block)
+		cflags |= CPRNG_USE_CV;
+
+	/*
+	 * Create a private CPRNG instance named `grnd1234' in pid
+	 * 1234.
+	 *
+	 * XXX cprng_strong_create may block for allocation, silly.
+	 */
+	(void)snprintf(name, sizeof name, "grnd%jd",
+	    (intmax_t)curproc->p_pid);
+	cprng = cprng_strong_create(name, IPL_NONE, cflags);
+
+	/* Generate data.  */
+	while (n) {
+		size_t m = cprng_strong(cprng, buf, MIN(n, sizeof buf),
+		    (block ? 0 : FNONBLOCK));
+
+		if (m == 0) {
+			/*
+			 * If we're blocking, infer that a short read
+			 * means interruption.  If we're not blocking,
+			 * infer that a short read means we would have
+			 * blocked.
+			 */
+			error = (block ? EINTR : EWOULDBLOCK);
+			break;
+		}
+
+		KASSERT(0 < m);
+		KASSERT(m <= MIN(n, sizeof buf));
+		error = copyout(buf, p, m);
+		if (error)
+			break;
+		p += m;
+		n -= m;
+
+		/*
+		 * Don't bother checking for interruption; the request
+		 * is limited to 512 bytes, and we're not to get that
+		 * much without blocking anyway.
+		 */
+	}
+
+	/* Destroy the private CPRNG instance.  */
+	cprng_strong_destroy(cprng);
+
+	return error;
+}
+
+/*
+ * getrandom(buf, len, flags)
+ *
+ *	Fill buf with len uniform random bytes fit for use in
+ *	cryptography if possible; fail or block if not, according to
+ *	flags.
+ */
+int
+sys_getrandom(struct lwp *l, const struct sys_getrandom_args *uap,
+    register_t *retval)
+{
+	/* {
+		syscallarg(void *)	buf;
+		syscallarg(size_t)	len;
+		syscallarg(int)		flags;
+	} */
+	void *ubuf = SCARG(uap, buf);
+	size_t len = SCARG(uap, len);
+	int flags = SCARG(uap, flags);
+	bool block = !(flags & GRND_NONBLOCK);
+
+	/* Discriminate between the sensible and silly versions.  */
+	if (flags & GRND_RANDOM)
+		return getrandom_silly(ubuf, len, block);
+	else
+		return getrandom_sensible(ubuf, len, block);
+}
diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master
index 4703e37b0ee6..26c05994ea25 100644
--- a/sys/kern/syscalls.master
+++ b/sys/kern/syscalls.master
@@ -1001,3 +1001,5 @@
 			    siginfo_t *info); }
 482	STD		{ int|sys||clock_getcpuclockid2(idtype_t idtype, \
 			    id_t id, clockid_t *clock_id); }
+483	STD		{ int|sys||getrandom(void *buf, size_t len, \
+			    int flags); }
diff --git a/sys/sys/random.h b/sys/sys/random.h
new file mode 100644
index 000000000000..93edd37af9de
--- /dev/null
+++ b/sys/sys/random.h
@@ -0,0 +1,45 @@
+/*	$NetBSD$	*/
+
+/*-
+ * Copyright (c) 2019 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Taylor R. Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef	_SYS_RANDOM_H
+#define	_SYS_RANDOM_H
+
+#include <sys/types.h>
+#include <sys/cdefs.h>
+
+#define	GRND_NONBLOCK	1
+#define	GRND_RANDOM	2
+
+__BEGIN_DECLS
+int	getrandom(void *, size_t, int);
+__END_DECLS
+
+#endif	/* _SYS_RANDOM_H */
diff --git a/sys/sys/rnd.h b/sys/sys/rnd.h
index 98df0b6f9908..f18b0b34d559 100644
--- a/sys/sys/rnd.h
+++ b/sys/sys/rnd.h
@@ -48,6 +48,7 @@ void		rnd_seed(void *, size_t);
 int		rnd_system_ioctl(struct file *, u_long, void *);
 
 extern int	rnd_initial_entropy;
+int		rnd_wait_for_initial_entropy(void);
 
 #endif /* _KERNEL */