Home | History | Annotate | Line # | Download | only in kern
subr_cprng.c revision 1.24.2.1.6.2
      1  1.24.2.1.6.2    martin /*	$NetBSD: subr_cprng.c,v 1.24.2.1.6.2 2019/11/25 15:47:44 martin Exp $ */
      2           1.1       tls 
      3           1.1       tls /*-
      4          1.18  riastrad  * Copyright (c) 2011-2013 The NetBSD Foundation, Inc.
      5           1.1       tls  * All rights reserved.
      6           1.1       tls  *
      7           1.1       tls  * This code is derived from software contributed to The NetBSD Foundation
      8          1.18  riastrad  * by Thor Lancelot Simon and Taylor R. Campbell.
      9           1.1       tls  *
     10           1.1       tls  * Redistribution and use in source and binary forms, with or without
     11           1.1       tls  * modification, are permitted provided that the following conditions
     12           1.1       tls  * are met:
     13           1.1       tls  * 1. Redistributions of source code must retain the above copyright
     14           1.1       tls  *    notice, this list of conditions and the following disclaimer.
     15           1.1       tls  * 2. Redistributions in binary form must reproduce the above copyright
     16           1.1       tls  *    notice, this list of conditions and the following disclaimer in the
     17           1.1       tls  *    documentation and/or other materials provided with the distribution.
     18           1.1       tls  *
     19           1.1       tls  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20           1.1       tls  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21           1.1       tls  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22           1.1       tls  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23           1.1       tls  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24           1.1       tls  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25           1.1       tls  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26           1.1       tls  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27           1.1       tls  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28           1.1       tls  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29           1.1       tls  * POSSIBILITY OF SUCH DAMAGE.
     30           1.1       tls  */
     31           1.1       tls 
     32          1.18  riastrad #include <sys/cdefs.h>
     33  1.24.2.1.6.2    martin __KERNEL_RCSID(0, "$NetBSD: subr_cprng.c,v 1.24.2.1.6.2 2019/11/25 15:47:44 martin Exp $");
     34          1.18  riastrad 
     35          1.18  riastrad #include <sys/param.h>
     36           1.1       tls #include <sys/types.h>
     37          1.18  riastrad #include <sys/condvar.h>
     38          1.18  riastrad #include <sys/cprng.h>
     39          1.18  riastrad #include <sys/errno.h>
     40          1.18  riastrad #include <sys/event.h>		/* XXX struct knote */
     41          1.18  riastrad #include <sys/fcntl.h>		/* XXX FNONBLOCK */
     42           1.1       tls #include <sys/kernel.h>
     43          1.18  riastrad #include <sys/kmem.h>
     44          1.19  riastrad #include <sys/lwp.h>
     45          1.23     pooka #include <sys/once.h>
     46          1.24       tls #include <sys/percpu.h>
     47          1.18  riastrad #include <sys/poll.h>		/* XXX POLLIN/POLLOUT/&c. */
     48          1.18  riastrad #include <sys/select.h>
     49           1.1       tls #include <sys/systm.h>
     50          1.23     pooka #include <sys/sysctl.h>
     51          1.18  riastrad #include <sys/rnd.h>
     52          1.18  riastrad #include <sys/rndsink.h>
     53          1.18  riastrad #if DEBUG
     54           1.1       tls #include <sys/rngtest.h>
     55          1.18  riastrad #endif
     56          1.18  riastrad 
     57  1.24.2.1.6.1    martin #include <crypto/nist_hash_drbg/nist_hash_drbg.h>
     58           1.1       tls 
     59           1.2   tsutsui #if defined(__HAVE_CPU_COUNTER)
     60           1.1       tls #include <machine/cpu_counter.h>
     61           1.2   tsutsui #endif
     62           1.1       tls 
     63          1.23     pooka static int sysctl_kern_urnd(SYSCTLFN_PROTO);
     64          1.23     pooka static int sysctl_kern_arnd(SYSCTLFN_PROTO);
     65          1.23     pooka 
     66          1.18  riastrad static void	cprng_strong_generate(struct cprng_strong *, void *, size_t);
     67          1.18  riastrad static void	cprng_strong_reseed(struct cprng_strong *);
     68          1.18  riastrad static void	cprng_strong_reseed_from(struct cprng_strong *, const void *,
     69          1.18  riastrad 		    size_t, bool);
     70          1.18  riastrad #if DEBUG
     71          1.18  riastrad static void	cprng_strong_rngtest(struct cprng_strong *);
     72          1.18  riastrad #endif
     73           1.1       tls 
     74          1.18  riastrad static rndsink_callback_t	cprng_strong_rndsink_callback;
     75           1.1       tls 
     76           1.1       tls void
     77           1.1       tls cprng_init(void)
     78           1.1       tls {
     79          1.23     pooka 	static struct sysctllog *random_sysctllog;
     80          1.23     pooka 
     81  1.24.2.1.6.1    martin 	if (nist_hash_drbg_initialize() != 0)
     82  1.24.2.1.6.1    martin 		panic("NIST Hash_DRBG failed self-test");
     83          1.23     pooka 
     84          1.23     pooka 	sysctl_createv(&random_sysctllog, 0, NULL, NULL,
     85          1.23     pooka 		       CTLFLAG_PERMANENT,
     86          1.23     pooka 		       CTLTYPE_INT, "urandom",
     87          1.23     pooka 		       SYSCTL_DESCR("Random integer value"),
     88          1.23     pooka 		       sysctl_kern_urnd, 0, NULL, 0,
     89          1.23     pooka 		       CTL_KERN, KERN_URND, CTL_EOL);
     90          1.23     pooka 	sysctl_createv(&random_sysctllog, 0, NULL, NULL,
     91          1.23     pooka 		       CTLFLAG_PERMANENT,
     92          1.23     pooka 		       CTLTYPE_INT, "arandom",
     93          1.23     pooka 		       SYSCTL_DESCR("n bytes of random data"),
     94          1.23     pooka 		       sysctl_kern_arnd, 0, NULL, 0,
     95          1.23     pooka 		       CTL_KERN, KERN_ARND, CTL_EOL);
     96           1.1       tls }
     97           1.1       tls 
     98           1.1       tls static inline uint32_t
     99           1.1       tls cprng_counter(void)
    100           1.1       tls {
    101           1.1       tls 	struct timeval tv;
    102           1.1       tls 
    103           1.1       tls #if defined(__HAVE_CPU_COUNTER)
    104           1.1       tls 	if (cpu_hascounter())
    105           1.1       tls 		return cpu_counter32();
    106           1.1       tls #endif
    107           1.1       tls 	if (__predict_false(cold)) {
    108          1.24       tls 		static int ctr;
    109           1.1       tls 		/* microtime unsafe if clock not running yet */
    110          1.24       tls 		return ctr++;
    111           1.1       tls 	}
    112          1.24       tls 	getmicrotime(&tv);
    113           1.1       tls 	return (tv.tv_sec * 1000000 + tv.tv_usec);
    114           1.1       tls }
    115           1.1       tls 
    116          1.18  riastrad struct cprng_strong {
    117          1.18  riastrad 	char		cs_name[16];
    118          1.18  riastrad 	int		cs_flags;
    119          1.18  riastrad 	kmutex_t	cs_lock;
    120          1.24       tls 	percpu_t	*cs_percpu;
    121          1.18  riastrad 	kcondvar_t	cs_cv;
    122          1.18  riastrad 	struct selinfo	cs_selq;
    123          1.18  riastrad 	struct rndsink	*cs_rndsink;
    124          1.18  riastrad 	bool		cs_ready;
    125  1.24.2.1.6.1    martin 	NIST_HASH_DRBG	cs_drbg;
    126          1.21  riastrad 
    127          1.21  riastrad 	/* XXX Kludge for /dev/random `information-theoretic' properties.   */
    128          1.21  riastrad 	unsigned int	cs_remaining;
    129          1.18  riastrad };
    130          1.18  riastrad 
    131          1.18  riastrad struct cprng_strong *
    132          1.18  riastrad cprng_strong_create(const char *name, int ipl, int flags)
    133          1.18  riastrad {
    134          1.18  riastrad 	const uint32_t cc = cprng_counter();
    135          1.18  riastrad 	struct cprng_strong *const cprng = kmem_alloc(sizeof(*cprng),
    136          1.18  riastrad 	    KM_SLEEP);
    137          1.18  riastrad 
    138          1.18  riastrad 	/*
    139          1.18  riastrad 	 * rndsink_request takes a spin lock at IPL_VM, so we can be no
    140          1.18  riastrad 	 * higher than that.
    141          1.18  riastrad 	 */
    142          1.22     skrll 	KASSERT(ipl != IPL_SCHED && ipl != IPL_HIGH);
    143          1.18  riastrad 
    144          1.18  riastrad 	/* Initialize the easy fields.  */
    145          1.18  riastrad 	(void)strlcpy(cprng->cs_name, name, sizeof(cprng->cs_name));
    146          1.18  riastrad 	cprng->cs_flags = flags;
    147          1.18  riastrad 	mutex_init(&cprng->cs_lock, MUTEX_DEFAULT, ipl);
    148          1.18  riastrad 	cv_init(&cprng->cs_cv, cprng->cs_name);
    149          1.18  riastrad 	selinit(&cprng->cs_selq);
    150  1.24.2.1.6.1    martin 	cprng->cs_rndsink = rndsink_create(NIST_HASH_DRBG_MIN_SEEDLEN_BYTES,
    151          1.18  riastrad 	    &cprng_strong_rndsink_callback, cprng);
    152          1.18  riastrad 
    153          1.18  riastrad 	/* Get some initial entropy.  Record whether it is full entropy.  */
    154  1.24.2.1.6.1    martin 	uint8_t seed[NIST_HASH_DRBG_MIN_SEEDLEN_BYTES];
    155      1.24.2.1    martin 	mutex_enter(&cprng->cs_lock);
    156          1.18  riastrad 	cprng->cs_ready = rndsink_request(cprng->cs_rndsink, seed,
    157          1.18  riastrad 	    sizeof(seed));
    158  1.24.2.1.6.1    martin 	if (nist_hash_drbg_instantiate(&cprng->cs_drbg, seed, sizeof(seed),
    159          1.18  riastrad 		&cc, sizeof(cc), cprng->cs_name, sizeof(cprng->cs_name)))
    160  1.24.2.1.6.1    martin 		/* XXX Fix nist_hash_drbg API so this can't happen.  */
    161  1.24.2.1.6.1    martin 		panic("cprng %s: NIST Hash_DRBG instantiation failed",
    162          1.18  riastrad 		    cprng->cs_name);
    163          1.20  riastrad 	explicit_memset(seed, 0, sizeof(seed));
    164          1.18  riastrad 
    165          1.21  riastrad 	if (ISSET(flags, CPRNG_HARD))
    166  1.24.2.1.6.1    martin 		cprng->cs_remaining = NIST_HASH_DRBG_MIN_SEEDLEN_BYTES;
    167          1.21  riastrad 	else
    168          1.21  riastrad 		cprng->cs_remaining = 0;
    169          1.21  riastrad 
    170          1.18  riastrad 	if (!cprng->cs_ready && !ISSET(flags, CPRNG_INIT_ANY))
    171          1.18  riastrad 		printf("cprng %s: creating with partial entropy\n",
    172          1.18  riastrad 		    cprng->cs_name);
    173      1.24.2.1    martin 	mutex_exit(&cprng->cs_lock);
    174          1.18  riastrad 
    175          1.18  riastrad 	return cprng;
    176          1.18  riastrad }
    177          1.18  riastrad 
    178          1.18  riastrad void
    179          1.18  riastrad cprng_strong_destroy(struct cprng_strong *cprng)
    180           1.8       tls {
    181           1.8       tls 
    182          1.18  riastrad 	/*
    183          1.18  riastrad 	 * Destroy the rndsink first to prevent calls to the callback.
    184          1.18  riastrad 	 */
    185          1.18  riastrad 	rndsink_destroy(cprng->cs_rndsink);
    186           1.8       tls 
    187          1.18  riastrad 	KASSERT(!cv_has_waiters(&cprng->cs_cv));
    188          1.18  riastrad #if 0
    189          1.18  riastrad 	KASSERT(!select_has_waiters(&cprng->cs_selq)) /* XXX ? */
    190          1.18  riastrad #endif
    191          1.15       tls 
    192  1.24.2.1.6.1    martin 	nist_hash_drbg_destroy(&cprng->cs_drbg);
    193          1.18  riastrad 	seldestroy(&cprng->cs_selq);
    194          1.18  riastrad 	cv_destroy(&cprng->cs_cv);
    195          1.18  riastrad 	mutex_destroy(&cprng->cs_lock);
    196          1.18  riastrad 
    197          1.20  riastrad 	explicit_memset(cprng, 0, sizeof(*cprng)); /* paranoia */
    198          1.18  riastrad 	kmem_free(cprng, sizeof(*cprng));
    199           1.8       tls }
    200           1.8       tls 
    201          1.18  riastrad /*
    202          1.18  riastrad  * Generate some data from cprng.  Block or return zero bytes,
    203          1.18  riastrad  * depending on flags & FNONBLOCK, if cprng was created without
    204          1.18  riastrad  * CPRNG_REKEY_ANY.
    205          1.18  riastrad  */
    206          1.18  riastrad size_t
    207          1.18  riastrad cprng_strong(struct cprng_strong *cprng, void *buffer, size_t bytes, int flags)
    208           1.5       tls {
    209          1.18  riastrad 	size_t result;
    210          1.18  riastrad 
    211          1.18  riastrad 	/* Caller must loop for more than CPRNG_MAX_LEN bytes.  */
    212          1.18  riastrad 	bytes = MIN(bytes, CPRNG_MAX_LEN);
    213          1.18  riastrad 
    214          1.18  riastrad 	mutex_enter(&cprng->cs_lock);
    215          1.18  riastrad 
    216          1.18  riastrad 	if (ISSET(cprng->cs_flags, CPRNG_REKEY_ANY)) {
    217          1.18  riastrad 		if (!cprng->cs_ready)
    218          1.18  riastrad 			cprng_strong_reseed(cprng);
    219          1.18  riastrad 	} else {
    220          1.18  riastrad 		while (!cprng->cs_ready) {
    221          1.18  riastrad 			if (ISSET(flags, FNONBLOCK) ||
    222          1.18  riastrad 			    !ISSET(cprng->cs_flags, CPRNG_USE_CV) ||
    223          1.18  riastrad 			    cv_wait_sig(&cprng->cs_cv, &cprng->cs_lock)) {
    224          1.18  riastrad 				result = 0;
    225          1.18  riastrad 				goto out;
    226           1.8       tls 			}
    227           1.8       tls 		}
    228           1.5       tls 	}
    229          1.18  riastrad 
    230          1.21  riastrad 	/*
    231          1.21  riastrad 	 * Debit the entropy if requested.
    232          1.21  riastrad 	 *
    233          1.21  riastrad 	 * XXX Kludge for /dev/random `information-theoretic' properties.
    234          1.21  riastrad 	 */
    235          1.21  riastrad 	if (__predict_false(ISSET(cprng->cs_flags, CPRNG_HARD))) {
    236          1.21  riastrad 		KASSERT(0 < cprng->cs_remaining);
    237  1.24.2.1.6.1    martin 		KASSERT(cprng->cs_remaining <=
    238  1.24.2.1.6.1    martin 		    NIST_HASH_DRBG_MIN_SEEDLEN_BYTES);
    239          1.21  riastrad 		if (bytes < cprng->cs_remaining) {
    240          1.21  riastrad 			cprng->cs_remaining -= bytes;
    241          1.21  riastrad 		} else {
    242          1.21  riastrad 			bytes = cprng->cs_remaining;
    243  1.24.2.1.6.1    martin 			cprng->cs_remaining = NIST_HASH_DRBG_MIN_SEEDLEN_BYTES;
    244          1.21  riastrad 			cprng->cs_ready = false;
    245          1.21  riastrad 			rndsink_schedule(cprng->cs_rndsink);
    246          1.21  riastrad 		}
    247  1.24.2.1.6.1    martin 		KASSERT(bytes <= NIST_HASH_DRBG_MIN_SEEDLEN_BYTES);
    248          1.21  riastrad 		KASSERT(0 < cprng->cs_remaining);
    249  1.24.2.1.6.1    martin 		KASSERT(cprng->cs_remaining <=
    250  1.24.2.1.6.1    martin 		    NIST_HASH_DRBG_MIN_SEEDLEN_BYTES);
    251          1.21  riastrad 	}
    252          1.21  riastrad 
    253          1.18  riastrad 	cprng_strong_generate(cprng, buffer, bytes);
    254          1.18  riastrad 	result = bytes;
    255          1.18  riastrad 
    256          1.18  riastrad out:	mutex_exit(&cprng->cs_lock);
    257          1.18  riastrad 	return result;
    258          1.18  riastrad }
    259          1.18  riastrad 
    260          1.18  riastrad static void	filt_cprng_detach(struct knote *);
    261          1.18  riastrad static int	filt_cprng_event(struct knote *, long);
    262          1.18  riastrad 
    263          1.18  riastrad static const struct filterops cprng_filtops =
    264          1.18  riastrad 	{ 1, NULL, filt_cprng_detach, filt_cprng_event };
    265          1.18  riastrad 
    266          1.18  riastrad int
    267          1.18  riastrad cprng_strong_kqfilter(struct cprng_strong *cprng, struct knote *kn)
    268          1.18  riastrad {
    269          1.18  riastrad 
    270          1.18  riastrad 	switch (kn->kn_filter) {
    271          1.18  riastrad 	case EVFILT_READ:
    272          1.18  riastrad 		kn->kn_fop = &cprng_filtops;
    273          1.18  riastrad 		kn->kn_hook = cprng;
    274          1.18  riastrad 		mutex_enter(&cprng->cs_lock);
    275          1.18  riastrad 		SLIST_INSERT_HEAD(&cprng->cs_selq.sel_klist, kn, kn_selnext);
    276          1.18  riastrad 		mutex_exit(&cprng->cs_lock);
    277          1.18  riastrad 		return 0;
    278          1.18  riastrad 
    279          1.18  riastrad 	case EVFILT_WRITE:
    280          1.18  riastrad 	default:
    281          1.18  riastrad 		return EINVAL;
    282           1.8       tls 	}
    283           1.5       tls }
    284           1.5       tls 
    285           1.5       tls static void
    286          1.18  riastrad filt_cprng_detach(struct knote *kn)
    287           1.1       tls {
    288          1.18  riastrad 	struct cprng_strong *const cprng = kn->kn_hook;
    289          1.18  riastrad 
    290          1.18  riastrad 	mutex_enter(&cprng->cs_lock);
    291          1.18  riastrad 	SLIST_REMOVE(&cprng->cs_selq.sel_klist, kn, knote, kn_selnext);
    292          1.18  riastrad 	mutex_exit(&cprng->cs_lock);
    293          1.18  riastrad }
    294           1.8       tls 
    295          1.18  riastrad static int
    296          1.18  riastrad filt_cprng_event(struct knote *kn, long hint)
    297          1.18  riastrad {
    298          1.18  riastrad 	struct cprng_strong *const cprng = kn->kn_hook;
    299          1.18  riastrad 	int ret;
    300           1.1       tls 
    301          1.18  riastrad 	if (hint == NOTE_SUBMIT)
    302          1.18  riastrad 		KASSERT(mutex_owned(&cprng->cs_lock));
    303          1.18  riastrad 	else
    304          1.18  riastrad 		mutex_enter(&cprng->cs_lock);
    305          1.18  riastrad 	if (cprng->cs_ready) {
    306          1.18  riastrad 		kn->kn_data = CPRNG_MAX_LEN; /* XXX Too large?  */
    307          1.18  riastrad 		ret = 1;
    308          1.18  riastrad 	} else {
    309          1.18  riastrad 		ret = 0;
    310           1.7       tls 	}
    311          1.18  riastrad 	if (hint == NOTE_SUBMIT)
    312          1.18  riastrad 		KASSERT(mutex_owned(&cprng->cs_lock));
    313          1.18  riastrad 	else
    314          1.18  riastrad 		mutex_exit(&cprng->cs_lock);
    315           1.7       tls 
    316          1.18  riastrad 	return ret;
    317           1.1       tls }
    318           1.1       tls 
    319          1.18  riastrad int
    320          1.18  riastrad cprng_strong_poll(struct cprng_strong *cprng, int events)
    321          1.15       tls {
    322          1.18  riastrad 	int revents;
    323          1.18  riastrad 
    324          1.18  riastrad 	if (!ISSET(events, (POLLIN | POLLRDNORM)))
    325          1.18  riastrad 		return 0;
    326          1.18  riastrad 
    327          1.18  riastrad 	mutex_enter(&cprng->cs_lock);
    328          1.18  riastrad 	if (cprng->cs_ready) {
    329          1.18  riastrad 		revents = (events & (POLLIN | POLLRDNORM));
    330          1.18  riastrad 	} else {
    331          1.18  riastrad 		selrecord(curlwp, &cprng->cs_selq);
    332          1.18  riastrad 		revents = 0;
    333          1.15       tls 	}
    334          1.18  riastrad 	mutex_exit(&cprng->cs_lock);
    335          1.18  riastrad 
    336          1.18  riastrad 	return revents;
    337          1.18  riastrad }
    338          1.18  riastrad 
    339          1.18  riastrad /*
    340  1.24.2.1.6.1    martin  * XXX Move nist_hash_drbg_reseed_advised_p and
    341  1.24.2.1.6.1    martin  * nist_hash_drbg_reseed_needed_p into the nist_hash_drbg API and make
    342  1.24.2.1.6.1    martin  * the NIST_HASH_DRBG structure opaque.
    343          1.18  riastrad  */
    344          1.18  riastrad static bool
    345  1.24.2.1.6.1    martin nist_hash_drbg_reseed_advised_p(NIST_HASH_DRBG *drbg)
    346          1.18  riastrad {
    347          1.18  riastrad 
    348  1.24.2.1.6.1    martin 	return (drbg->reseed_counter > (NIST_HASH_DRBG_RESEED_INTERVAL / 2));
    349          1.15       tls }
    350          1.15       tls 
    351          1.18  riastrad static bool
    352  1.24.2.1.6.1    martin nist_hash_drbg_reseed_needed_p(NIST_HASH_DRBG *drbg)
    353           1.1       tls {
    354           1.1       tls 
    355  1.24.2.1.6.1    martin 	return (drbg->reseed_counter >= NIST_HASH_DRBG_RESEED_INTERVAL);
    356          1.18  riastrad }
    357          1.18  riastrad 
    358          1.18  riastrad /*
    359          1.18  riastrad  * Generate some data from the underlying generator.
    360          1.18  riastrad  */
    361          1.18  riastrad static void
    362          1.21  riastrad cprng_strong_generate(struct cprng_strong *cprng, void *buffer, size_t bytes)
    363          1.18  riastrad {
    364          1.18  riastrad 	const uint32_t cc = cprng_counter();
    365          1.18  riastrad 
    366          1.18  riastrad 	KASSERT(bytes <= CPRNG_MAX_LEN);
    367          1.18  riastrad 	KASSERT(mutex_owned(&cprng->cs_lock));
    368          1.18  riastrad 
    369          1.18  riastrad 	/*
    370  1.24.2.1.6.1    martin 	 * Generate some data from the NIST Hash_DRBG.  Caller
    371          1.18  riastrad 	 * guarantees reseed if we're not ready, and if we exhaust the
    372          1.18  riastrad 	 * generator, we mark ourselves not ready.  Consequently, this
    373  1.24.2.1.6.1    martin 	 * call to the Hash_DRBG should not fail.
    374          1.18  riastrad 	 */
    375  1.24.2.1.6.1    martin 	if (__predict_false(nist_hash_drbg_generate(&cprng->cs_drbg, buffer,
    376          1.18  riastrad 		    bytes, &cc, sizeof(cc))))
    377  1.24.2.1.6.1    martin 		panic("cprng %s: NIST Hash_DRBG failed", cprng->cs_name);
    378           1.1       tls 
    379          1.18  riastrad 	/*
    380          1.18  riastrad 	 * If we've been seeing a lot of use, ask for some fresh
    381          1.18  riastrad 	 * entropy soon.
    382          1.18  riastrad 	 */
    383  1.24.2.1.6.1    martin 	if (__predict_false(nist_hash_drbg_reseed_advised_p(&cprng->cs_drbg)))
    384          1.18  riastrad 		rndsink_schedule(cprng->cs_rndsink);
    385           1.1       tls 
    386          1.18  riastrad 	/*
    387          1.18  riastrad 	 * If we just exhausted the generator, inform the next user
    388          1.18  riastrad 	 * that we need a reseed.
    389          1.18  riastrad 	 */
    390  1.24.2.1.6.1    martin 	if (__predict_false(nist_hash_drbg_reseed_needed_p(&cprng->cs_drbg))) {
    391          1.18  riastrad 		cprng->cs_ready = false;
    392          1.18  riastrad 		rndsink_schedule(cprng->cs_rndsink); /* paranoia */
    393           1.1       tls 	}
    394          1.18  riastrad }
    395           1.1       tls 
    396          1.18  riastrad /*
    397          1.18  riastrad  * Reseed with whatever we can get from the system entropy pool right now.
    398          1.18  riastrad  */
    399          1.18  riastrad static void
    400          1.18  riastrad cprng_strong_reseed(struct cprng_strong *cprng)
    401          1.18  riastrad {
    402  1.24.2.1.6.1    martin 	uint8_t seed[NIST_HASH_DRBG_MIN_SEEDLEN_BYTES];
    403           1.5       tls 
    404          1.18  riastrad 	KASSERT(mutex_owned(&cprng->cs_lock));
    405           1.1       tls 
    406          1.18  riastrad 	const bool full_entropy = rndsink_request(cprng->cs_rndsink, seed,
    407          1.18  riastrad 	    sizeof(seed));
    408          1.18  riastrad 	cprng_strong_reseed_from(cprng, seed, sizeof(seed), full_entropy);
    409          1.20  riastrad 	explicit_memset(seed, 0, sizeof(seed));
    410           1.1       tls }
    411           1.1       tls 
    412          1.18  riastrad /*
    413          1.18  riastrad  * Reseed with the given seed.  If we now have full entropy, notify waiters.
    414          1.18  riastrad  */
    415          1.18  riastrad static void
    416          1.18  riastrad cprng_strong_reseed_from(struct cprng_strong *cprng,
    417          1.18  riastrad     const void *seed, size_t bytes, bool full_entropy)
    418           1.1       tls {
    419          1.18  riastrad 	const uint32_t cc = cprng_counter();
    420           1.1       tls 
    421  1.24.2.1.6.1    martin 	KASSERT(bytes == NIST_HASH_DRBG_MIN_SEEDLEN_BYTES);
    422          1.18  riastrad 	KASSERT(mutex_owned(&cprng->cs_lock));
    423           1.1       tls 
    424           1.1       tls 	/*
    425          1.18  riastrad 	 * Notify anyone interested in the partiality of entropy in our
    426          1.18  riastrad 	 * seed -- anyone waiting for full entropy, or any system
    427          1.18  riastrad 	 * operators interested in knowing when the entropy pool is
    428          1.18  riastrad 	 * running on fumes.
    429           1.1       tls 	 */
    430          1.18  riastrad 	if (full_entropy) {
    431          1.18  riastrad 		if (!cprng->cs_ready) {
    432          1.18  riastrad 			cprng->cs_ready = true;
    433          1.18  riastrad 			cv_broadcast(&cprng->cs_cv);
    434          1.18  riastrad 			selnotify(&cprng->cs_selq, (POLLIN | POLLRDNORM),
    435          1.18  riastrad 			    NOTE_SUBMIT);
    436          1.18  riastrad 		}
    437          1.18  riastrad 	} else {
    438          1.18  riastrad 		/*
    439          1.18  riastrad 		 * XXX Is there is any harm in reseeding with partial
    440          1.18  riastrad 		 * entropy when we had full entropy before?  If so,
    441          1.18  riastrad 		 * remove the conditional on this message.
    442          1.18  riastrad 		 */
    443          1.18  riastrad 		if (!cprng->cs_ready &&
    444          1.18  riastrad 		    !ISSET(cprng->cs_flags, CPRNG_REKEY_ANY))
    445          1.18  riastrad 			printf("cprng %s: reseeding with partial entropy\n",
    446          1.18  riastrad 			    cprng->cs_name);
    447          1.18  riastrad 	}
    448          1.18  riastrad 
    449  1.24.2.1.6.1    martin 	if (nist_hash_drbg_reseed(&cprng->cs_drbg, seed, bytes, &cc,
    450  1.24.2.1.6.1    martin 		sizeof(cc)))
    451  1.24.2.1.6.1    martin 		/* XXX Fix nist_hash_drbg API so this can't happen.  */
    452  1.24.2.1.6.1    martin 		panic("cprng %s: NIST Hash_DRBG reseed failed",
    453  1.24.2.1.6.1    martin 		    cprng->cs_name);
    454           1.5       tls 
    455          1.18  riastrad #if DEBUG
    456          1.18  riastrad 	cprng_strong_rngtest(cprng);
    457           1.8       tls #endif
    458           1.1       tls }
    459           1.1       tls 
    460          1.18  riastrad #if DEBUG
    461          1.18  riastrad /*
    462          1.18  riastrad  * Generate some output and apply a statistical RNG test to it.
    463          1.18  riastrad  */
    464          1.18  riastrad static void
    465          1.18  riastrad cprng_strong_rngtest(struct cprng_strong *cprng)
    466           1.1       tls {
    467           1.5       tls 
    468          1.18  riastrad 	KASSERT(mutex_owned(&cprng->cs_lock));
    469          1.18  riastrad 
    470          1.18  riastrad 	/* XXX Switch to a pool cache instead?  */
    471          1.18  riastrad 	rngtest_t *const rt = kmem_intr_alloc(sizeof(*rt), KM_NOSLEEP);
    472          1.18  riastrad 	if (rt == NULL)
    473          1.18  riastrad 		/* XXX Warn?  */
    474          1.18  riastrad 		return;
    475           1.1       tls 
    476          1.18  riastrad 	(void)strlcpy(rt->rt_name, cprng->cs_name, sizeof(rt->rt_name));
    477           1.6       tls 
    478  1.24.2.1.6.1    martin 	if (nist_hash_drbg_generate(&cprng->cs_drbg, rt->rt_b,
    479  1.24.2.1.6.1    martin 		sizeof(rt->rt_b), NULL, 0))
    480  1.24.2.1.6.1    martin 		panic("cprng %s: NIST Hash_DRBG failed after reseed",
    481          1.18  riastrad 		    cprng->cs_name);
    482           1.5       tls 
    483          1.18  riastrad 	if (rngtest(rt)) {
    484          1.18  riastrad 		printf("cprng %s: failed statistical RNG test\n",
    485          1.18  riastrad 		    cprng->cs_name);
    486          1.18  riastrad 		/* XXX Not clear that this does any good...  */
    487          1.18  riastrad 		cprng->cs_ready = false;
    488          1.18  riastrad 		rndsink_schedule(cprng->cs_rndsink);
    489          1.18  riastrad 	}
    490           1.5       tls 
    491          1.20  riastrad 	explicit_memset(rt, 0, sizeof(*rt)); /* paranoia */
    492          1.18  riastrad 	kmem_intr_free(rt, sizeof(*rt));
    493           1.1       tls }
    494          1.18  riastrad #endif
    495           1.1       tls 
    496          1.18  riastrad /*
    497          1.18  riastrad  * Feed entropy from an rndsink request into the CPRNG for which the
    498          1.18  riastrad  * request was issued.
    499          1.18  riastrad  */
    500          1.18  riastrad static void
    501          1.18  riastrad cprng_strong_rndsink_callback(void *context, const void *seed, size_t bytes)
    502           1.1       tls {
    503          1.18  riastrad 	struct cprng_strong *const cprng = context;
    504           1.1       tls 
    505          1.18  riastrad 	mutex_enter(&cprng->cs_lock);
    506          1.18  riastrad 	/* Assume that rndsinks provide only full-entropy output.  */
    507          1.18  riastrad 	cprng_strong_reseed_from(cprng, seed, bytes, true);
    508          1.18  riastrad 	mutex_exit(&cprng->cs_lock);
    509           1.1       tls }
    510          1.23     pooka 
    511  1.24.2.1.6.2    martin static ONCE_DECL(sysctl_prng_once);
    512          1.23     pooka static cprng_strong_t *sysctl_prng;
    513          1.23     pooka 
    514          1.23     pooka static int
    515          1.23     pooka makeprng(void)
    516          1.23     pooka {
    517          1.23     pooka 
    518          1.23     pooka 	/* can't create in cprng_init(), too early */
    519          1.23     pooka 	sysctl_prng = cprng_strong_create("sysctl", IPL_NONE,
    520          1.23     pooka 					  CPRNG_INIT_ANY|CPRNG_REKEY_ANY);
    521          1.23     pooka 	return 0;
    522          1.23     pooka }
    523          1.23     pooka 
    524          1.23     pooka /*
    525          1.23     pooka  * sysctl helper routine for kern.urandom node. Picks a random number
    526          1.23     pooka  * for you.
    527          1.23     pooka  */
    528          1.23     pooka static int
    529          1.23     pooka sysctl_kern_urnd(SYSCTLFN_ARGS)
    530          1.23     pooka {
    531          1.23     pooka 	int v, rv;
    532          1.23     pooka 
    533  1.24.2.1.6.2    martin 	RUN_ONCE(&sysctl_prng_once, makeprng);
    534          1.23     pooka 	rv = cprng_strong(sysctl_prng, &v, sizeof(v), 0);
    535          1.23     pooka 	if (rv == sizeof(v)) {
    536          1.23     pooka 		struct sysctlnode node = *rnode;
    537          1.23     pooka 		node.sysctl_data = &v;
    538          1.23     pooka 		return (sysctl_lookup(SYSCTLFN_CALL(&node)));
    539          1.23     pooka 	}
    540          1.23     pooka 	else
    541          1.23     pooka 		return (EIO);	/*XXX*/
    542          1.23     pooka }
    543          1.23     pooka 
    544          1.23     pooka /*
    545          1.24       tls  * sysctl helper routine for kern.arandom node.  Fills the supplied
    546          1.24       tls  * structure with random data for you.
    547          1.24       tls  *
    548          1.24       tls  * This node was originally declared as type "int" but its implementation
    549          1.24       tls  * in OpenBSD, whence it came, would happily return up to 8K of data if
    550          1.24       tls  * requested.  Evidently this was used to key RC4 in userspace.
    551          1.24       tls  *
    552          1.24       tls  * In NetBSD, the libc stack-smash-protection code reads 64 bytes
    553          1.24       tls  * from here at every program startup.  So though it would be nice
    554          1.24       tls  * to make this node return only 32 or 64 bits, we can't.  Too bad!
    555          1.23     pooka  */
    556          1.23     pooka static int
    557          1.23     pooka sysctl_kern_arnd(SYSCTLFN_ARGS)
    558          1.23     pooka {
    559          1.23     pooka 	int error;
    560          1.23     pooka 	void *v;
    561          1.23     pooka 	struct sysctlnode node = *rnode;
    562  1.24.2.1.6.2    martin 	size_t n __diagused;
    563          1.23     pooka 
    564          1.24       tls 	switch (*oldlenp) {
    565          1.24       tls 	    case 0:
    566          1.23     pooka 		return 0;
    567          1.24       tls 	    default:
    568          1.24       tls 		if (*oldlenp > 256) {
    569          1.24       tls 			return E2BIG;
    570          1.24       tls 		}
    571  1.24.2.1.6.2    martin 		RUN_ONCE(&sysctl_prng_once, makeprng);
    572          1.24       tls 		v = kmem_alloc(*oldlenp, KM_SLEEP);
    573  1.24.2.1.6.2    martin 		n = cprng_strong(sysctl_prng, v, *oldlenp, 0);
    574  1.24.2.1.6.2    martin 		KASSERT(n == *oldlenp);
    575          1.24       tls 		node.sysctl_data = v;
    576          1.24       tls 		node.sysctl_size = *oldlenp;
    577          1.24       tls 		error = sysctl_lookup(SYSCTLFN_CALL(&node));
    578          1.24       tls 		kmem_free(v, *oldlenp);
    579          1.24       tls 		return error;
    580          1.24       tls 	}
    581          1.23     pooka }
    582