random.c revision 1.8
11.8Sriastrad/*	$NetBSD: random.c,v 1.8 2020/08/14 00:53:16 riastradh Exp $	*/
21.1Sriastrad
31.1Sriastrad/*-
41.1Sriastrad * Copyright (c) 2019 The NetBSD Foundation, Inc.
51.1Sriastrad * All rights reserved.
61.1Sriastrad *
71.1Sriastrad * This code is derived from software contributed to The NetBSD Foundation
81.1Sriastrad * by Taylor R. Campbell.
91.1Sriastrad *
101.1Sriastrad * Redistribution and use in source and binary forms, with or without
111.1Sriastrad * modification, are permitted provided that the following conditions
121.1Sriastrad * are met:
131.1Sriastrad * 1. Redistributions of source code must retain the above copyright
141.1Sriastrad *    notice, this list of conditions and the following disclaimer.
151.1Sriastrad * 2. Redistributions in binary form must reproduce the above copyright
161.1Sriastrad *    notice, this list of conditions and the following disclaimer in the
171.1Sriastrad *    documentation and/or other materials provided with the distribution.
181.1Sriastrad *
191.1Sriastrad * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
201.1Sriastrad * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
211.1Sriastrad * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
221.1Sriastrad * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
231.1Sriastrad * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
241.1Sriastrad * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
251.1Sriastrad * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
261.1Sriastrad * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
271.1Sriastrad * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
281.1Sriastrad * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
291.1Sriastrad * POSSIBILITY OF SUCH DAMAGE.
301.1Sriastrad */
311.1Sriastrad
321.1Sriastrad/*
331.1Sriastrad * /dev/random, /dev/urandom -- stateless version
341.1Sriastrad *
351.1Sriastrad *	For short reads from /dev/urandom, up to 256 bytes, read from a
361.1Sriastrad *	per-CPU NIST Hash_DRBG instance that is reseeded as soon as the
371.1Sriastrad *	system has enough entropy.
381.1Sriastrad *
391.1Sriastrad *	For all other reads, instantiate a fresh NIST Hash_DRBG from
401.1Sriastrad *	the global entropy pool, and draw from it.
411.1Sriastrad *
421.1Sriastrad *	Each read is independent; there is no per-open state.
431.1Sriastrad *	Concurrent reads from the same open run in parallel.
441.1Sriastrad *
451.1Sriastrad *	Reading from /dev/random may block until entropy is available.
461.1Sriastrad *	Either device may return short reads if interrupted.
471.1Sriastrad */
481.1Sriastrad
491.1Sriastrad#include <sys/cdefs.h>
501.8Sriastrad__KERNEL_RCSID(0, "$NetBSD: random.c,v 1.8 2020/08/14 00:53:16 riastradh Exp $");
511.1Sriastrad
521.1Sriastrad#include <sys/param.h>
531.1Sriastrad#include <sys/types.h>
541.2Sriastrad#include <sys/atomic.h>
551.1Sriastrad#include <sys/conf.h>
561.1Sriastrad#include <sys/cprng.h>
571.1Sriastrad#include <sys/entropy.h>
581.1Sriastrad#include <sys/errno.h>
591.1Sriastrad#include <sys/event.h>
601.1Sriastrad#include <sys/fcntl.h>
611.1Sriastrad#include <sys/kauth.h>
621.5Sriastrad#include <sys/kmem.h>
631.1Sriastrad#include <sys/lwp.h>
641.1Sriastrad#include <sys/poll.h>
651.8Sriastrad#include <sys/random.h>
661.1Sriastrad#include <sys/rnd.h>
671.1Sriastrad#include <sys/rndsource.h>
681.1Sriastrad#include <sys/signalvar.h>
691.1Sriastrad#include <sys/systm.h>
701.1Sriastrad
711.1Sriastrad#include "ioconf.h"
721.1Sriastrad
731.1Sriastradstatic dev_type_open(random_open);
741.1Sriastradstatic dev_type_close(random_close);
751.1Sriastradstatic dev_type_ioctl(random_ioctl);
761.1Sriastradstatic dev_type_poll(random_poll);
771.1Sriastradstatic dev_type_kqfilter(random_kqfilter);
781.1Sriastradstatic dev_type_read(random_read);
791.1Sriastradstatic dev_type_write(random_write);
801.1Sriastrad
811.1Sriastradconst struct cdevsw rnd_cdevsw = {
821.1Sriastrad	.d_open = random_open,
831.1Sriastrad	.d_close = random_close,
841.1Sriastrad	.d_read = random_read,
851.1Sriastrad	.d_write = random_write,
861.1Sriastrad	.d_ioctl = random_ioctl,
871.1Sriastrad	.d_stop = nostop,
881.1Sriastrad	.d_tty = notty,
891.1Sriastrad	.d_poll = random_poll,
901.1Sriastrad	.d_mmap = nommap,
911.1Sriastrad	.d_kqfilter = random_kqfilter,
921.1Sriastrad	.d_discard = nodiscard,
931.1Sriastrad	.d_flag = D_OTHER|D_MPSAFE,
941.1Sriastrad};
951.1Sriastrad
961.1Sriastrad#define	RANDOM_BUFSIZE	512	/* XXX pulled from arse */
971.1Sriastrad
981.1Sriastrad/* Entropy source for writes to /dev/random and /dev/urandom */
991.1Sriastradstatic krndsource_t	user_rndsource;
1001.1Sriastrad
1011.1Sriastradvoid
1021.1Sriastradrndattach(int num)
1031.1Sriastrad{
1041.1Sriastrad
1051.1Sriastrad	rnd_attach_source(&user_rndsource, "/dev/random", RND_TYPE_UNKNOWN,
1061.1Sriastrad	    RND_FLAG_COLLECT_VALUE);
1071.1Sriastrad}
1081.1Sriastrad
1091.1Sriastradstatic int
1101.1Sriastradrandom_open(dev_t dev, int flags, int fmt, struct lwp *l)
1111.1Sriastrad{
1121.1Sriastrad
1131.1Sriastrad	/* Validate minor.  */
1141.1Sriastrad	switch (minor(dev)) {
1151.1Sriastrad	case RND_DEV_RANDOM:
1161.1Sriastrad	case RND_DEV_URANDOM:
1171.1Sriastrad		break;
1181.1Sriastrad	default:
1191.1Sriastrad		return ENXIO;
1201.1Sriastrad	}
1211.1Sriastrad
1221.1Sriastrad	return 0;
1231.1Sriastrad}
1241.1Sriastrad
1251.1Sriastradstatic int
1261.1Sriastradrandom_close(dev_t dev, int flags, int fmt, struct lwp *l)
1271.1Sriastrad{
1281.1Sriastrad
1291.1Sriastrad	/* Success!  */
1301.1Sriastrad	return 0;
1311.1Sriastrad}
1321.1Sriastrad
1331.1Sriastradstatic int
1341.1Sriastradrandom_ioctl(dev_t dev, unsigned long cmd, void *data, int flag, struct lwp *l)
1351.1Sriastrad{
1361.1Sriastrad
1371.1Sriastrad	/*
1381.1Sriastrad	 * No non-blocking/async options; otherwise defer to
1391.1Sriastrad	 * entropy_ioctl.
1401.1Sriastrad	 */
1411.1Sriastrad	switch (cmd) {
1421.1Sriastrad	case FIONBIO:
1431.1Sriastrad	case FIOASYNC:
1441.1Sriastrad		return 0;
1451.1Sriastrad	default:
1461.1Sriastrad		return entropy_ioctl(cmd, data);
1471.1Sriastrad	}
1481.1Sriastrad}
1491.1Sriastrad
1501.1Sriastradstatic int
1511.1Sriastradrandom_poll(dev_t dev, int events, struct lwp *l)
1521.1Sriastrad{
1531.1Sriastrad
1541.1Sriastrad	/* /dev/random may block; /dev/urandom is always ready.  */
1551.1Sriastrad	switch (minor(dev)) {
1561.1Sriastrad	case RND_DEV_RANDOM:
1571.1Sriastrad		return entropy_poll(events);
1581.1Sriastrad	case RND_DEV_URANDOM:
1591.1Sriastrad		return events & (POLLIN|POLLRDNORM | POLLOUT|POLLWRNORM);
1601.1Sriastrad	default:
1611.1Sriastrad		return 0;
1621.1Sriastrad	}
1631.1Sriastrad}
1641.1Sriastrad
1651.1Sriastradstatic int
1661.1Sriastradrandom_kqfilter(dev_t dev, struct knote *kn)
1671.1Sriastrad{
1681.1Sriastrad
1691.1Sriastrad	/* Validate the event filter.  */
1701.1Sriastrad	switch (kn->kn_filter) {
1711.1Sriastrad	case EVFILT_READ:
1721.1Sriastrad	case EVFILT_WRITE:
1731.1Sriastrad		break;
1741.1Sriastrad	default:
1751.1Sriastrad		return EINVAL;
1761.1Sriastrad	}
1771.1Sriastrad
1781.1Sriastrad	/* /dev/random may block; /dev/urandom never does.  */
1791.1Sriastrad	switch (minor(dev)) {
1801.1Sriastrad	case RND_DEV_RANDOM:
1811.1Sriastrad		if (kn->kn_filter == EVFILT_READ)
1821.1Sriastrad			return entropy_kqfilter(kn);
1831.1Sriastrad		/* FALLTHROUGH */
1841.1Sriastrad	case RND_DEV_URANDOM:
1851.1Sriastrad		kn->kn_fop = &seltrue_filtops;
1861.1Sriastrad		return 0;
1871.1Sriastrad	default:
1881.1Sriastrad		return ENXIO;
1891.1Sriastrad	}
1901.1Sriastrad}
1911.1Sriastrad
1921.1Sriastrad/*
1931.1Sriastrad * random_read(dev, uio, flags)
1941.1Sriastrad *
1951.1Sriastrad *	Generate data from a PRNG seeded from the entropy pool.
1961.1Sriastrad *
1971.1Sriastrad *	- If /dev/random, block until we have full entropy, or fail
1981.1Sriastrad *	  with EWOULDBLOCK, and if `depleting' entropy, return at most
1991.1Sriastrad *	  the entropy pool's capacity at once.
2001.1Sriastrad *
2011.1Sriastrad *	- If /dev/urandom, generate data from whatever is in the
2021.1Sriastrad *	  entropy pool now.
2031.1Sriastrad *
2041.1Sriastrad *	On interrupt, return a short read, but not shorter than 256
2051.1Sriastrad *	bytes (actually, no shorter than RANDOM_BUFSIZE bytes, which is
2061.1Sriastrad *	512 for hysterical raisins).
2071.1Sriastrad */
2081.1Sriastradstatic int
2091.1Sriastradrandom_read(dev_t dev, struct uio *uio, int flags)
2101.1Sriastrad{
2111.8Sriastrad	int gflags;
2121.1Sriastrad
2131.8Sriastrad	/* Set the appropriate GRND_* mode.  */
2141.8Sriastrad	switch (minor(dev)) {
2151.8Sriastrad	case RND_DEV_RANDOM:
2161.8Sriastrad		gflags = GRND_RANDOM;
2171.8Sriastrad		break;
2181.8Sriastrad	case RND_DEV_URANDOM:
2191.8Sriastrad		gflags = GRND_INSECURE;
2201.8Sriastrad		break;
2211.8Sriastrad	default:
2221.8Sriastrad		return ENXIO;
2231.1Sriastrad	}
2241.1Sriastrad
2251.8Sriastrad	/* Set GRND_NONBLOCK if the user requested FNONBLOCK.  */
2261.8Sriastrad	if (flags & FNONBLOCK)
2271.8Sriastrad		gflags |= GRND_NONBLOCK;
2281.1Sriastrad
2291.8Sriastrad	/* Defer to getrandom.  */
2301.8Sriastrad	return dogetrandom(uio, gflags);
2311.1Sriastrad}
2321.1Sriastrad
2331.1Sriastrad/*
2341.1Sriastrad * random_write(dev, uio, flags)
2351.1Sriastrad *
2361.1Sriastrad *	Enter data from uio into the entropy pool.
2371.1Sriastrad *
2381.1Sriastrad *	Assume privileged users provide full entropy, and unprivileged
2391.1Sriastrad *	users provide no entropy.  If you have a nonuniform source of
2401.1Sriastrad *	data with n bytes of min-entropy, hash it with an XOF like
2411.1Sriastrad *	SHAKE128 into exactly n bytes first.
2421.1Sriastrad */
2431.1Sriastradstatic int
2441.1Sriastradrandom_write(dev_t dev, struct uio *uio, int flags)
2451.1Sriastrad{
2461.1Sriastrad	kauth_cred_t cred = kauth_cred_get();
2471.1Sriastrad	uint8_t *buf;
2481.3Sriastrad	bool privileged = false, any = false;
2491.1Sriastrad	int error = 0;
2501.1Sriastrad
2511.1Sriastrad	/* Verify user's authorization to affect the entropy pool.  */
2521.1Sriastrad	error = kauth_authorize_device(cred, KAUTH_DEVICE_RND_ADDDATA,
2531.1Sriastrad	    NULL, NULL, NULL, NULL);
2541.1Sriastrad	if (error)
2551.1Sriastrad		return error;
2561.1Sriastrad
2571.1Sriastrad	/*
2581.1Sriastrad	 * Check whether user is privileged.  If so, assume user
2591.1Sriastrad	 * furnishes full-entropy data; if not, accept user's data but
2601.1Sriastrad	 * assume it has zero entropy when we do accounting.  If you
2611.1Sriastrad	 * want to specify less entropy, use ioctl(RNDADDDATA).
2621.1Sriastrad	 */
2631.1Sriastrad	if (kauth_authorize_device(cred, KAUTH_DEVICE_RND_ADDDATA_ESTIMATE,
2641.1Sriastrad		NULL, NULL, NULL, NULL) == 0)
2651.1Sriastrad		privileged = true;
2661.1Sriastrad
2671.1Sriastrad	/* Get a buffer for transfers.  */
2681.5Sriastrad	buf = kmem_alloc(RANDOM_BUFSIZE, KM_SLEEP);
2691.1Sriastrad
2701.1Sriastrad	/* Consume data.  */
2711.1Sriastrad	while (uio->uio_resid) {
2721.6Sriastrad		size_t n = MIN(uio->uio_resid, RANDOM_BUFSIZE);
2731.1Sriastrad
2741.6Sriastrad		/* Transfer n bytes in and enter them into the pool.  */
2751.6Sriastrad		error = uiomove(buf, n, uio);
2761.6Sriastrad		if (error)
2771.6Sriastrad			break;
2781.6Sriastrad		rnd_add_data(&user_rndsource, buf, n, privileged ? n*NBBY : 0);
2791.6Sriastrad		any = true;
2801.1Sriastrad
2811.1Sriastrad		/* Yield if requested.  */
2821.1Sriastrad		if (curcpu()->ci_schedstate.spc_flags & SPCF_SHOULDYIELD)
2831.1Sriastrad			preempt();
2841.1Sriastrad
2851.1Sriastrad		/* Check for interruption.  */
2861.1Sriastrad		if (__predict_false(curlwp->l_flag & LW_PENDSIG) &&
2871.1Sriastrad		    sigispending(curlwp, 0)) {
2881.7Sriastrad			error = EINTR;
2891.1Sriastrad			break;
2901.1Sriastrad		}
2911.1Sriastrad	}
2921.1Sriastrad
2931.5Sriastrad	/* Zero the buffer and free it.  */
2941.1Sriastrad	explicit_memset(buf, 0, RANDOM_BUFSIZE);
2951.5Sriastrad	kmem_free(buf, RANDOM_BUFSIZE);
2961.3Sriastrad
2971.3Sriastrad	/* If we added anything, consolidate entropy now.  */
2981.3Sriastrad	if (any)
2991.3Sriastrad		entropy_consolidate();
3001.3Sriastrad
3011.1Sriastrad	return error;
3021.1Sriastrad}
303