Home | History | Annotate | Line # | Download | only in kern
subr_cprng.c revision 1.43.4.1
      1  1.43.4.1    martin /*	$NetBSD: subr_cprng.c,v 1.43.4.1 2023/08/11 14:35:25 martin Exp $	*/
      2       1.1       tls 
      3       1.1       tls /*-
      4      1.36  riastrad  * Copyright (c) 2019 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.36  riastrad  * by 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.36  riastrad /*
     33      1.36  riastrad  * cprng_strong
     34      1.36  riastrad  *
     35      1.36  riastrad  *	Per-CPU NIST Hash_DRBG, reseeded automatically from the entropy
     36      1.36  riastrad  *	pool when we transition to full entropy, never blocking.  This
     37      1.36  riastrad  *	is slightly different from the old cprng_strong API, but the
     38      1.36  riastrad  *	only users of the old one fell into three categories:
     39      1.36  riastrad  *
     40      1.36  riastrad  *	1. never-blocking, oughta-be-per-CPU (kern_cprng, sysctl_prng)
     41      1.36  riastrad  *	2. never-blocking, used per-CPU anyway (/dev/urandom short reads)
     42      1.36  riastrad  *	3. /dev/random
     43      1.36  riastrad  *
     44      1.36  riastrad  *	This code serves the first two categories without having extra
     45      1.36  riastrad  *	logic for /dev/random.
     46      1.36  riastrad  *
     47      1.42  riastrad  *	kern_cprng - available at IPL_SOFTSERIAL or lower
     48      1.36  riastrad  *	user_cprng - available only at IPL_NONE in thread context
     49      1.36  riastrad  *
     50      1.36  riastrad  *	The name kern_cprng is for hysterical raisins.  The name
     51      1.36  riastrad  *	user_cprng serves only to contrast with kern_cprng.
     52      1.36  riastrad  */
     53      1.36  riastrad 
     54      1.18  riastrad #include <sys/cdefs.h>
     55  1.43.4.1    martin __KERNEL_RCSID(0, "$NetBSD: subr_cprng.c,v 1.43.4.1 2023/08/11 14:35:25 martin Exp $");
     56      1.18  riastrad 
     57      1.41     skrll #include <sys/param.h>
     58       1.1       tls #include <sys/types.h>
     59      1.18  riastrad #include <sys/cprng.h>
     60      1.36  riastrad #include <sys/cpu.h>
     61      1.36  riastrad #include <sys/entropy.h>
     62      1.18  riastrad #include <sys/errno.h>
     63      1.36  riastrad #include <sys/evcnt.h>
     64      1.36  riastrad #include <sys/intr.h>
     65      1.18  riastrad #include <sys/kmem.h>
     66      1.24       tls #include <sys/percpu.h>
     67      1.36  riastrad #include <sys/sysctl.h>
     68       1.1       tls #include <sys/systm.h>
     69      1.18  riastrad 
     70      1.31  riastrad #include <crypto/nist_hash_drbg/nist_hash_drbg.h>
     71       1.1       tls 
     72      1.36  riastrad /*
     73      1.36  riastrad  * struct cprng_strong
     74      1.36  riastrad  */
     75      1.18  riastrad struct cprng_strong {
     76      1.36  riastrad 	struct percpu		*cs_percpu; /* struct cprng_cpu */
     77      1.36  riastrad 	ipl_cookie_t		cs_iplcookie;
     78      1.36  riastrad };
     79      1.21  riastrad 
     80      1.36  riastrad /*
     81      1.36  riastrad  * struct cprng_cpu
     82      1.36  riastrad  *
     83      1.36  riastrad  *	Per-CPU state for a cprng_strong.  The DRBG and evcnt are
     84      1.36  riastrad  *	allocated separately because percpu(9) sometimes moves per-CPU
     85      1.36  riastrad  *	objects around without zeroing them.
     86      1.36  riastrad  */
     87      1.36  riastrad struct cprng_cpu {
     88      1.36  riastrad 	struct nist_hash_drbg	*cc_drbg;
     89      1.36  riastrad 	struct {
     90      1.36  riastrad 		struct evcnt	reseed;
     91      1.36  riastrad 	}			*cc_evcnt;
     92      1.36  riastrad 	unsigned		cc_epoch;
     93      1.18  riastrad };
     94      1.18  riastrad 
     95      1.36  riastrad static int	sysctl_kern_urandom(SYSCTLFN_ARGS);
     96      1.36  riastrad static int	sysctl_kern_arandom(SYSCTLFN_ARGS);
     97      1.36  riastrad static void	cprng_init_cpu(void *, void *, struct cpu_info *);
     98      1.36  riastrad static void	cprng_fini_cpu(void *, void *, struct cpu_info *);
     99      1.36  riastrad 
    100      1.36  riastrad /* Well-known CPRNG instances */
    101      1.42  riastrad struct cprng_strong *kern_cprng __read_mostly; /* IPL_SOFTSERIAL */
    102      1.36  riastrad struct cprng_strong *user_cprng __read_mostly; /* IPL_NONE */
    103      1.18  riastrad 
    104      1.36  riastrad static struct sysctllog *cprng_sysctllog __read_mostly;
    105      1.18  riastrad 
    106      1.18  riastrad void
    107      1.36  riastrad cprng_init(void)
    108       1.8       tls {
    109       1.8       tls 
    110      1.36  riastrad 	if (__predict_false(nist_hash_drbg_initialize() != 0))
    111      1.36  riastrad 		panic("NIST Hash_DRBG failed self-test");
    112      1.36  riastrad 
    113      1.18  riastrad 	/*
    114      1.42  riastrad 	 * Create CPRNG instances at two IPLs: IPL_SOFTSERIAL for
    115      1.42  riastrad 	 * kernel use that may occur inside soft interrupt handlers,
    116      1.36  riastrad 	 * and IPL_NONE for userland use which need not block
    117      1.36  riastrad 	 * interrupts.
    118      1.18  riastrad 	 */
    119      1.42  riastrad 	kern_cprng = cprng_strong_create("kern", IPL_SOFTSERIAL, 0);
    120      1.36  riastrad 	user_cprng = cprng_strong_create("user", IPL_NONE, 0);
    121       1.8       tls 
    122      1.36  riastrad 	/* Create kern.urandom and kern.arandom sysctl nodes.  */
    123      1.36  riastrad 	sysctl_createv(&cprng_sysctllog, 0, NULL, NULL,
    124      1.36  riastrad 	    CTLFLAG_PERMANENT|CTLFLAG_READONLY, CTLTYPE_INT, "urandom",
    125      1.36  riastrad 	    SYSCTL_DESCR("Independent uniform random 32-bit integer"),
    126      1.36  riastrad 	    sysctl_kern_urandom, 0, NULL, 0, CTL_KERN, KERN_URND, CTL_EOL);
    127      1.36  riastrad 	sysctl_createv(&cprng_sysctllog, 0, NULL, NULL,
    128      1.36  riastrad 	    CTLFLAG_PERMANENT|CTLFLAG_READONLY, CTLTYPE_INT /*lie*/, "arandom",
    129      1.36  riastrad 	    SYSCTL_DESCR("Independent uniform random bytes, up to 256 bytes"),
    130      1.36  riastrad 	    sysctl_kern_arandom, 0, NULL, 0, CTL_KERN, KERN_ARND, CTL_EOL);
    131       1.8       tls }
    132       1.8       tls 
    133      1.18  riastrad /*
    134      1.36  riastrad  * sysctl kern.urandom
    135      1.36  riastrad  *
    136      1.36  riastrad  *	Independent uniform random 32-bit integer.  Read-only.
    137      1.18  riastrad  */
    138      1.18  riastrad static int
    139      1.36  riastrad sysctl_kern_urandom(SYSCTLFN_ARGS)
    140      1.18  riastrad {
    141      1.36  riastrad 	struct sysctlnode node = *rnode;
    142      1.36  riastrad 	int v;
    143      1.36  riastrad 	int error;
    144       1.1       tls 
    145      1.36  riastrad 	/* Generate an int's worth of data.  */
    146      1.36  riastrad 	cprng_strong(user_cprng, &v, sizeof v, 0);
    147       1.7       tls 
    148      1.36  riastrad 	/* Do the sysctl dance.  */
    149      1.36  riastrad 	node.sysctl_data = &v;
    150      1.36  riastrad 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
    151      1.36  riastrad 
    152      1.36  riastrad 	/* Clear the buffer before returning the sysctl error.  */
    153      1.36  riastrad 	explicit_memset(&v, 0, sizeof v);
    154      1.36  riastrad 	return error;
    155       1.1       tls }
    156       1.1       tls 
    157      1.36  riastrad /*
    158      1.36  riastrad  * sysctl kern.arandom
    159      1.36  riastrad  *
    160      1.36  riastrad  *	Independent uniform random bytes, up to 256 bytes.  Read-only.
    161      1.36  riastrad  */
    162      1.29  christos static int
    163      1.36  riastrad sysctl_kern_arandom(SYSCTLFN_ARGS)
    164      1.29  christos {
    165      1.36  riastrad 	struct sysctlnode node = *rnode;
    166      1.36  riastrad 	uint8_t buf[256];
    167      1.36  riastrad 	int error;
    168      1.29  christos 
    169      1.36  riastrad 	/*
    170      1.36  riastrad 	 * Clamp to a reasonably small size.  256 bytes is kind of
    171      1.36  riastrad 	 * arbitrary; 32 would be more reasonable, but we used 256 in
    172      1.36  riastrad 	 * the past, so let's not break compatibility.
    173      1.36  riastrad 	 */
    174      1.36  riastrad 	if (*oldlenp > 256)	/* size_t, so never negative */
    175      1.37       nia 		*oldlenp = 256;
    176      1.29  christos 
    177      1.36  riastrad 	/* Generate data.  */
    178      1.36  riastrad 	cprng_strong(user_cprng, buf, *oldlenp, 0);
    179      1.29  christos 
    180      1.36  riastrad 	/* Do the sysctl dance.  */
    181      1.36  riastrad 	node.sysctl_data = buf;
    182      1.36  riastrad 	node.sysctl_size = *oldlenp;
    183      1.36  riastrad 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
    184      1.36  riastrad 
    185      1.36  riastrad 	/* Clear the buffer before returning the sysctl error.  */
    186      1.36  riastrad 	explicit_memset(buf, 0, sizeof buf);
    187      1.36  riastrad 	return error;
    188      1.29  christos }
    189      1.29  christos 
    190      1.36  riastrad struct cprng_strong *
    191      1.36  riastrad cprng_strong_create(const char *name, int ipl, int flags)
    192      1.29  christos {
    193      1.36  riastrad 	struct cprng_strong *cprng;
    194      1.29  christos 
    195      1.36  riastrad 	cprng = kmem_alloc(sizeof(*cprng), KM_SLEEP);
    196      1.36  riastrad 	cprng->cs_iplcookie = makeiplcookie(ipl);
    197      1.36  riastrad 	cprng->cs_percpu = percpu_create(sizeof(struct cprng_cpu),
    198      1.36  riastrad 	    cprng_init_cpu, cprng_fini_cpu, __UNCONST(name));
    199      1.29  christos 
    200      1.36  riastrad 	return cprng;
    201      1.29  christos }
    202      1.29  christos 
    203      1.36  riastrad void
    204      1.36  riastrad cprng_strong_destroy(struct cprng_strong *cprng)
    205      1.15       tls {
    206      1.18  riastrad 
    207      1.36  riastrad 	percpu_free(cprng->cs_percpu, sizeof(struct cprng_cpu));
    208      1.36  riastrad 	kmem_free(cprng, sizeof(*cprng));
    209      1.15       tls }
    210      1.15       tls 
    211      1.18  riastrad static void
    212      1.36  riastrad cprng_init_cpu(void *ptr, void *cookie, struct cpu_info *ci)
    213      1.18  riastrad {
    214      1.36  riastrad 	struct cprng_cpu *cc = ptr;
    215      1.36  riastrad 	const char *name = cookie;
    216      1.39  riastrad 	const char *cpuname;
    217      1.36  riastrad 	uint8_t zero[NIST_HASH_DRBG_SEEDLEN_BYTES] = {0};
    218      1.36  riastrad 	char namebuf[64];	/* XXX size? */
    219      1.18  riastrad 
    220      1.18  riastrad 	/*
    221      1.36  riastrad 	 * Format the name as, e.g., kern/8 if we're on cpu8.  This
    222      1.36  riastrad 	 * doesn't get displayed anywhere; it just ensures that if
    223      1.36  riastrad 	 * there were a bug causing us to use the same otherwise secure
    224      1.36  riastrad 	 * seed on multiple CPUs, we would still get independent output
    225      1.36  riastrad 	 * from the NIST Hash_DRBG.
    226      1.18  riastrad 	 */
    227      1.36  riastrad 	snprintf(namebuf, sizeof namebuf, "%s/%u", name, cpu_index(ci));
    228       1.1       tls 
    229      1.18  riastrad 	/*
    230      1.36  riastrad 	 * Allocate the struct nist_hash_drbg and struct evcnt
    231      1.36  riastrad 	 * separately, since percpu(9) may move objects around in
    232      1.36  riastrad 	 * memory without zeroing.
    233      1.18  riastrad 	 */
    234      1.36  riastrad 	cc->cc_drbg = kmem_zalloc(sizeof(*cc->cc_drbg), KM_SLEEP);
    235      1.36  riastrad 	cc->cc_evcnt = kmem_alloc(sizeof(*cc->cc_evcnt), KM_SLEEP);
    236       1.1       tls 
    237      1.18  riastrad 	/*
    238      1.36  riastrad 	 * Initialize the DRBG with no seed.  We do this in order to
    239      1.36  riastrad 	 * defer reading from the entropy pool as long as possible.
    240      1.18  riastrad 	 */
    241      1.36  riastrad 	if (__predict_false(nist_hash_drbg_instantiate(cc->cc_drbg,
    242      1.36  riastrad 		    zero, sizeof zero, NULL, 0, namebuf, strlen(namebuf))))
    243      1.36  riastrad 		panic("nist_hash_drbg_instantiate");
    244      1.36  riastrad 
    245      1.36  riastrad 	/* Attach the event counters.  */
    246      1.39  riastrad 	/* XXX ci_cpuname may not be initialized early enough.  */
    247      1.39  riastrad 	cpuname = ci->ci_cpuname[0] == '\0' ? "cpu0" : ci->ci_cpuname;
    248      1.36  riastrad 	evcnt_attach_dynamic(&cc->cc_evcnt->reseed, EVCNT_TYPE_MISC, NULL,
    249      1.39  riastrad 	    cpuname, "cprng_strong reseed");
    250      1.36  riastrad 
    251      1.36  riastrad 	/* Set the epoch uninitialized so we reseed on first use.  */
    252      1.36  riastrad 	cc->cc_epoch = 0;
    253      1.18  riastrad }
    254       1.1       tls 
    255      1.18  riastrad static void
    256      1.36  riastrad cprng_fini_cpu(void *ptr, void *cookie, struct cpu_info *ci)
    257      1.18  riastrad {
    258      1.36  riastrad 	struct cprng_cpu *cc = ptr;
    259       1.5       tls 
    260      1.36  riastrad 	evcnt_detach(&cc->cc_evcnt->reseed);
    261      1.36  riastrad 	if (__predict_false(nist_hash_drbg_destroy(cc->cc_drbg)))
    262      1.36  riastrad 		panic("nist_hash_drbg_destroy");
    263       1.1       tls 
    264      1.36  riastrad 	kmem_free(cc->cc_evcnt, sizeof(*cc->cc_evcnt));
    265      1.36  riastrad 	kmem_free(cc->cc_drbg, sizeof(*cc->cc_drbg));
    266       1.1       tls }
    267       1.1       tls 
    268  1.43.4.1    martin static void
    269  1.43.4.1    martin cprng_strong_reseed(struct cprng_strong *cprng, unsigned epoch,
    270  1.43.4.1    martin     struct cprng_cpu **ccp, int *sp)
    271  1.43.4.1    martin {
    272  1.43.4.1    martin 	uint8_t seed[NIST_HASH_DRBG_SEEDLEN_BYTES];
    273  1.43.4.1    martin 
    274  1.43.4.1    martin 	/*
    275  1.43.4.1    martin 	 * Drop everything to extract a fresh seed from the entropy
    276  1.43.4.1    martin 	 * pool.  entropy_extract may sleep on an adaptive lock, which
    277  1.43.4.1    martin 	 * invalidates our percpu(9) reference.
    278  1.43.4.1    martin 	 *
    279  1.43.4.1    martin 	 * This may race with reseeding in another thread, which is no
    280  1.43.4.1    martin 	 * big deal -- worst case, we rewind the entropy epoch here and
    281  1.43.4.1    martin 	 * cause the next caller to reseed again, and in the end we
    282  1.43.4.1    martin 	 * just reseed a couple more times than necessary.
    283  1.43.4.1    martin 	 */
    284  1.43.4.1    martin 	splx(*sp);
    285  1.43.4.1    martin 	percpu_putref(cprng->cs_percpu);
    286  1.43.4.1    martin 	entropy_extract(seed, sizeof seed, 0);
    287  1.43.4.1    martin 	*ccp = percpu_getref(cprng->cs_percpu);
    288  1.43.4.1    martin 	*sp = splraiseipl(cprng->cs_iplcookie);
    289  1.43.4.1    martin 
    290  1.43.4.1    martin 	(*ccp)->cc_evcnt->reseed.ev_count++;
    291  1.43.4.1    martin 	if (__predict_false(nist_hash_drbg_reseed((*ccp)->cc_drbg,
    292  1.43.4.1    martin 		    seed, sizeof seed, NULL, 0)))
    293  1.43.4.1    martin 		panic("nist_hash_drbg_reseed");
    294  1.43.4.1    martin 	explicit_memset(seed, 0, sizeof seed);
    295  1.43.4.1    martin 	(*ccp)->cc_epoch = epoch;
    296  1.43.4.1    martin }
    297  1.43.4.1    martin 
    298      1.36  riastrad size_t
    299      1.36  riastrad cprng_strong(struct cprng_strong *cprng, void *buf, size_t len, int flags)
    300       1.1       tls {
    301      1.36  riastrad 	struct cprng_cpu *cc;
    302      1.36  riastrad 	unsigned epoch;
    303      1.36  riastrad 	int s;
    304       1.1       tls 
    305      1.42  riastrad 	/* Not allowed in hard interrupt context.  */
    306      1.42  riastrad 	KASSERT(!cpu_intr_p());
    307      1.42  riastrad 
    308       1.1       tls 	/*
    309      1.36  riastrad 	 * Verify maximum request length.  Caller should really limit
    310      1.36  riastrad 	 * their requests to 32 bytes to avoid spending much time with
    311      1.36  riastrad 	 * preemption disabled -- use the 32 bytes to seed a private
    312      1.36  riastrad 	 * DRBG instance if you need more data.
    313       1.1       tls 	 */
    314      1.36  riastrad 	KASSERT(len <= CPRNG_MAX_LEN);
    315      1.18  riastrad 
    316      1.36  riastrad 	/* Verify legacy API use.  */
    317      1.36  riastrad 	KASSERT(flags == 0);
    318       1.1       tls 
    319      1.36  riastrad 	/* Acquire per-CPU state and block interrupts.  */
    320      1.36  riastrad 	cc = percpu_getref(cprng->cs_percpu);
    321      1.36  riastrad 	s = splraiseipl(cprng->cs_iplcookie);
    322      1.36  riastrad 
    323      1.36  riastrad 	/* If the entropy epoch has changed, (re)seed.  */
    324      1.36  riastrad 	epoch = entropy_epoch();
    325  1.43.4.1    martin 	if (__predict_false(epoch != cc->cc_epoch))
    326  1.43.4.1    martin 		cprng_strong_reseed(cprng, epoch, &cc, &s);
    327       1.1       tls 
    328      1.36  riastrad 	/* Generate data.  Failure here means it's time to reseed.  */
    329      1.36  riastrad 	if (__predict_false(nist_hash_drbg_generate(cc->cc_drbg, buf, len,
    330      1.36  riastrad 		    NULL, 0))) {
    331  1.43.4.1    martin 		cprng_strong_reseed(cprng, epoch, &cc, &s);
    332      1.36  riastrad 		if (__predict_false(nist_hash_drbg_generate(cc->cc_drbg,
    333      1.36  riastrad 			    buf, len, NULL, 0)))
    334      1.36  riastrad 			panic("nist_hash_drbg_generate");
    335      1.36  riastrad 	}
    336      1.23     pooka 
    337      1.36  riastrad 	/* Release state and interrupts.  */
    338      1.36  riastrad 	splx(s);
    339      1.36  riastrad 	percpu_putref(cprng->cs_percpu);
    340      1.23     pooka 
    341      1.36  riastrad 	/* Return the number of bytes generated, for hysterical raisins.  */
    342      1.36  riastrad 	return len;
    343      1.23     pooka }
    344      1.23     pooka 
    345      1.36  riastrad uint32_t
    346      1.36  riastrad cprng_strong32(void)
    347      1.23     pooka {
    348      1.36  riastrad 	uint32_t r;
    349      1.36  riastrad 	cprng_strong(kern_cprng, &r, sizeof(r), 0);
    350      1.36  riastrad 	return r;
    351      1.23     pooka }
    352      1.23     pooka 
    353      1.36  riastrad uint64_t
    354      1.36  riastrad cprng_strong64(void)
    355      1.23     pooka {
    356      1.36  riastrad 	uint64_t r;
    357      1.36  riastrad 	cprng_strong(kern_cprng, &r, sizeof(r), 0);
    358      1.36  riastrad 	return r;
    359      1.23     pooka }
    360