xref: /freebsd-14.2/sys/dev/random/randomdev.c (revision 13774e82)
1 /*-
2  * Copyright (c) 2017 Oliver Pinter
3  * Copyright (c) 2000-2015 Mark R V Murray
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer
11  *    in this position and unchanged.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  */
28 
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31 
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/bus.h>
35 #include <sys/conf.h>
36 #include <sys/fcntl.h>
37 #include <sys/filio.h>
38 #include <sys/kernel.h>
39 #include <sys/kthread.h>
40 #include <sys/lock.h>
41 #include <sys/module.h>
42 #include <sys/malloc.h>
43 #include <sys/poll.h>
44 #include <sys/proc.h>
45 #include <sys/random.h>
46 #include <sys/sbuf.h>
47 #include <sys/selinfo.h>
48 #include <sys/sysctl.h>
49 #include <sys/systm.h>
50 #include <sys/uio.h>
51 #include <sys/unistd.h>
52 
53 #include <crypto/rijndael/rijndael-api-fst.h>
54 #include <crypto/sha2/sha256.h>
55 
56 #include <dev/random/hash.h>
57 #include <dev/random/randomdev.h>
58 #include <dev/random/random_harvestq.h>
59 
60 #define	RANDOM_UNIT	0
61 
62 #if defined(RANDOM_LOADABLE)
63 #define READ_RANDOM_UIO	_read_random_uio
64 #define READ_RANDOM	_read_random
65 static int READ_RANDOM_UIO(struct uio *, bool);
66 static void READ_RANDOM(void *, u_int);
67 #else
68 #define READ_RANDOM_UIO	read_random_uio
69 #define READ_RANDOM	read_random
70 #endif
71 
72 static d_read_t randomdev_read;
73 static d_write_t randomdev_write;
74 static d_poll_t randomdev_poll;
75 static d_ioctl_t randomdev_ioctl;
76 
77 static struct cdevsw random_cdevsw = {
78 	.d_name = "random",
79 	.d_version = D_VERSION,
80 	.d_read = randomdev_read,
81 	.d_write = randomdev_write,
82 	.d_poll = randomdev_poll,
83 	.d_ioctl = randomdev_ioctl,
84 };
85 
86 /* For use with make_dev(9)/destroy_dev(9). */
87 static struct cdev *random_dev;
88 
89 static void
90 random_alg_context_ra_init_alg(void *data)
91 {
92 
93 	p_random_alg_context = &random_alg_context;
94 	p_random_alg_context->ra_init_alg(data);
95 #if defined(RANDOM_LOADABLE)
96 	random_infra_init(READ_RANDOM_UIO, READ_RANDOM);
97 #endif
98 }
99 
100 static void
101 random_alg_context_ra_deinit_alg(void *data)
102 {
103 
104 #if defined(RANDOM_LOADABLE)
105 	random_infra_uninit();
106 #endif
107 	p_random_alg_context->ra_deinit_alg(data);
108 	p_random_alg_context = NULL;
109 }
110 
111 SYSINIT(random_device, SI_SUB_RANDOM, SI_ORDER_THIRD, random_alg_context_ra_init_alg, NULL);
112 SYSUNINIT(random_device, SI_SUB_RANDOM, SI_ORDER_THIRD, random_alg_context_ra_deinit_alg, NULL);
113 
114 static struct selinfo rsel;
115 
116 /*
117  * This is the read uio(9) interface for random(4).
118  */
119 /* ARGSUSED */
120 static int
121 randomdev_read(struct cdev *dev __unused, struct uio *uio, int flags)
122 {
123 
124 	return (READ_RANDOM_UIO(uio, (flags & O_NONBLOCK) != 0));
125 }
126 
127 /*
128  * If the random device is not seeded, blocks until it is seeded.
129  *
130  * Returns zero when the random device is seeded.
131  *
132  * If the 'interruptible' parameter is true, and the device is unseeded, this
133  * routine may be interrupted.  If interrupted, it will return either ERESTART
134  * or EINTR.
135  */
136 #define SEEDWAIT_INTERRUPTIBLE		true
137 #define SEEDWAIT_UNINTERRUPTIBLE	false
138 static int
139 randomdev_wait_until_seeded(bool interruptible)
140 {
141 	int error, spamcount, slpflags;
142 
143 	slpflags = interruptible ? PCATCH : 0;
144 
145 	error = 0;
146 	spamcount = 0;
147 	while (!p_random_alg_context->ra_seeded()) {
148 		/* keep tapping away at the pre-read until we seed/unblock. */
149 		p_random_alg_context->ra_pre_read();
150 		/* Only bother the console every 10 seconds or so */
151 		if (spamcount == 0)
152 			printf("random: %s unblock wait\n", __func__);
153 		spamcount = (spamcount + 1) % 100;
154 		error = tsleep(&random_alg_context, slpflags, "randseed",
155 		    hz / 10);
156 		if (error == ERESTART || error == EINTR) {
157 			KASSERT(interruptible,
158 			    ("unexpected wake of non-interruptible sleep"));
159 			break;
160 		}
161 		/* Squash tsleep timeout condition */
162 		if (error == EWOULDBLOCK)
163 			error = 0;
164 		KASSERT(error == 0, ("unexpected tsleep error %d", error));
165 	}
166 	return (error);
167 }
168 
169 int
170 READ_RANDOM_UIO(struct uio *uio, bool nonblock)
171 {
172 	uint8_t *random_buf;
173 	int error;
174 	ssize_t read_len, total_read, c;
175 	/* 16 MiB takes about 0.08 s CPU time on my 2017 AMD Zen CPU */
176 #define SIGCHK_PERIOD (16 * 1024 * 1024)
177 	const size_t sigchk_period = SIGCHK_PERIOD;
178 
179 	CTASSERT(SIGCHK_PERIOD % PAGE_SIZE == 0);
180 #undef SIGCHK_PERIOD
181 
182 	random_buf = malloc(PAGE_SIZE, M_ENTROPY, M_WAITOK);
183 	p_random_alg_context->ra_pre_read();
184 	error = 0;
185 	/* (Un)Blocking logic */
186 	if (!p_random_alg_context->ra_seeded()) {
187 		if (nonblock)
188 			error = EWOULDBLOCK;
189 		else
190 			error = randomdev_wait_until_seeded(
191 			    SEEDWAIT_INTERRUPTIBLE);
192 	}
193 	if (error == 0) {
194 		read_rate_increment((uio->uio_resid + sizeof(uint32_t))/sizeof(uint32_t));
195 		total_read = 0;
196 		while (uio->uio_resid && !error) {
197 			read_len = uio->uio_resid;
198 			/*
199 			 * Belt-and-braces.
200 			 * Round up the read length to a crypto block size multiple,
201 			 * which is what the underlying generator is expecting.
202 			 * See the random_buf size requirements in the Fortuna code.
203 			 */
204 			read_len = roundup(read_len, RANDOM_BLOCKSIZE);
205 			/* Work in chunks page-sized or less */
206 			read_len = MIN(read_len, PAGE_SIZE);
207 			p_random_alg_context->ra_read(random_buf, read_len);
208 			c = MIN(uio->uio_resid, read_len);
209 			/*
210 			 * uiomove() may yield the CPU before each 'c' bytes
211 			 * (up to PAGE_SIZE) are copied out.
212 			 */
213 			error = uiomove(random_buf, c, uio);
214 			total_read += c;
215 			/*
216 			 * Poll for signals every few MBs to avoid very long
217 			 * uninterruptible syscalls.
218 			 */
219 			if (error == 0 && uio->uio_resid != 0 &&
220 			    total_read % sigchk_period == 0) {
221 				error = tsleep_sbt(&random_alg_context, PCATCH,
222 				    "randrd", SBT_1NS, 0, C_HARDCLOCK);
223 				/* Squash tsleep timeout condition */
224 				if (error == EWOULDBLOCK)
225 					error = 0;
226 			}
227 		}
228 		if (error == ERESTART || error == EINTR)
229 			error = 0;
230 	}
231 	free(random_buf, M_ENTROPY);
232 	return (error);
233 }
234 
235 /*-
236  * Kernel API version of read_random().
237  * This is similar to random_alg_read(),
238  * except it doesn't interface with uio(9).
239  * It cannot assumed that random_buf is a multiple of
240  * RANDOM_BLOCKSIZE bytes.
241  */
242 void
243 READ_RANDOM(void *random_buf, u_int len)
244 {
245 	u_int read_directly_len;
246 
247 	KASSERT(random_buf != NULL, ("No suitable random buffer in %s", __func__));
248 	p_random_alg_context->ra_pre_read();
249 	/* (Un)Blocking logic */
250 	if (!p_random_alg_context->ra_seeded())
251 		(void)randomdev_wait_until_seeded(SEEDWAIT_UNINTERRUPTIBLE);
252 	read_rate_increment(roundup2(len, sizeof(uint32_t)));
253 	if (len == 0)
254 		return;
255 	/*
256 	 * The underlying generator expects multiples of
257 	 * RANDOM_BLOCKSIZE.
258 	 */
259 	read_directly_len = rounddown(len, RANDOM_BLOCKSIZE);
260 	if (read_directly_len > 0)
261 		p_random_alg_context->ra_read(random_buf, read_directly_len);
262 	if (read_directly_len < len) {
263 		uint8_t remainder_buf[RANDOM_BLOCKSIZE];
264 
265 		p_random_alg_context->ra_read(remainder_buf,
266 		    sizeof(remainder_buf));
267 		memcpy((char *)random_buf + read_directly_len, remainder_buf,
268 		    len - read_directly_len);
269 
270 		explicit_bzero(remainder_buf, sizeof(remainder_buf));
271 	}
272 }
273 
274 static __inline void
275 randomdev_accumulate(uint8_t *buf, u_int count)
276 {
277 	static u_int destination = 0;
278 	static struct harvest_event event;
279 	static struct randomdev_hash hash;
280 	static uint32_t entropy_data[RANDOM_KEYSIZE_WORDS];
281 	uint32_t timestamp;
282 	int i;
283 
284 	/* Extra timing here is helpful to scrape scheduler jitter entropy */
285 	randomdev_hash_init(&hash);
286 	timestamp = (uint32_t)get_cyclecount();
287 	randomdev_hash_iterate(&hash, &timestamp, sizeof(timestamp));
288 	randomdev_hash_iterate(&hash, buf, count);
289 	timestamp = (uint32_t)get_cyclecount();
290 	randomdev_hash_iterate(&hash, &timestamp, sizeof(timestamp));
291 	randomdev_hash_finish(&hash, entropy_data);
292 	explicit_bzero(&hash, sizeof(hash));
293 	for (i = 0; i < RANDOM_KEYSIZE_WORDS; i += sizeof(event.he_entropy)/sizeof(event.he_entropy[0])) {
294 		event.he_somecounter = (uint32_t)get_cyclecount();
295 		event.he_size = sizeof(event.he_entropy);
296 		event.he_source = RANDOM_CACHED;
297 		event.he_destination = destination++; /* Harmless cheating */
298 		memcpy(event.he_entropy, entropy_data + i, sizeof(event.he_entropy));
299 		p_random_alg_context->ra_event_processor(&event);
300 	}
301 	explicit_bzero(entropy_data, sizeof(entropy_data));
302 }
303 
304 /* ARGSUSED */
305 static int
306 randomdev_write(struct cdev *dev __unused, struct uio *uio, int flags __unused)
307 {
308 	uint8_t *random_buf;
309 	int c, error = 0;
310 	ssize_t nbytes;
311 
312 	random_buf = malloc(PAGE_SIZE, M_ENTROPY, M_WAITOK);
313 	nbytes = uio->uio_resid;
314 	while (uio->uio_resid > 0 && error == 0) {
315 		c = MIN(uio->uio_resid, PAGE_SIZE);
316 		error = uiomove(random_buf, c, uio);
317 		if (error)
318 			break;
319 		randomdev_accumulate(random_buf, c);
320 		tsleep(&random_alg_context, 0, "randwr", hz/10);
321 	}
322 	if (nbytes != uio->uio_resid && (error == ERESTART || error == EINTR))
323 		/* Partial write, not error. */
324 		error = 0;
325 	free(random_buf, M_ENTROPY);
326 	return (error);
327 }
328 
329 /* ARGSUSED */
330 static int
331 randomdev_poll(struct cdev *dev __unused, int events, struct thread *td __unused)
332 {
333 
334 	if (events & (POLLIN | POLLRDNORM)) {
335 		if (p_random_alg_context->ra_seeded())
336 			events &= (POLLIN | POLLRDNORM);
337 		else
338 			selrecord(td, &rsel);
339 	}
340 	return (events);
341 }
342 
343 /* This will be called by the entropy processor when it seeds itself and becomes secure */
344 void
345 randomdev_unblock(void)
346 {
347 
348 	selwakeuppri(&rsel, PUSER);
349 	wakeup(&random_alg_context);
350 	printf("random: unblocking device.\n");
351 	/* Do random(9) a favour while we are about it. */
352 	(void)atomic_cmpset_int(&arc4rand_iniseed_state, ARC4_ENTR_NONE, ARC4_ENTR_HAVE);
353 }
354 
355 /* ARGSUSED */
356 static int
357 randomdev_ioctl(struct cdev *dev __unused, u_long cmd, caddr_t addr __unused,
358     int flags __unused, struct thread *td __unused)
359 {
360 	int error = 0;
361 
362 	switch (cmd) {
363 		/* Really handled in upper layer */
364 	case FIOASYNC:
365 	case FIONBIO:
366 		break;
367 	default:
368 		error = ENOTTY;
369 	}
370 
371 	return (error);
372 }
373 
374 void
375 random_source_register(struct random_source *rsource)
376 {
377 	struct random_sources *rrs;
378 
379 	KASSERT(rsource != NULL, ("invalid input to %s", __func__));
380 
381 	rrs = malloc(sizeof(*rrs), M_ENTROPY, M_WAITOK);
382 	rrs->rrs_source = rsource;
383 
384 	random_harvest_register_source(rsource->rs_source);
385 
386 	printf("random: registering fast source %s\n", rsource->rs_ident);
387 	LIST_INSERT_HEAD(&source_list, rrs, rrs_entries);
388 }
389 
390 void
391 random_source_deregister(struct random_source *rsource)
392 {
393 	struct random_sources *rrs = NULL;
394 
395 	KASSERT(rsource != NULL, ("invalid input to %s", __func__));
396 
397 	random_harvest_deregister_source(rsource->rs_source);
398 
399 	LIST_FOREACH(rrs, &source_list, rrs_entries)
400 		if (rrs->rrs_source == rsource) {
401 			LIST_REMOVE(rrs, rrs_entries);
402 			break;
403 		}
404 	if (rrs != NULL)
405 		free(rrs, M_ENTROPY);
406 }
407 
408 static int
409 random_source_handler(SYSCTL_HANDLER_ARGS)
410 {
411 	struct random_sources *rrs;
412 	struct sbuf sbuf;
413 	int error, count;
414 
415 	sbuf_new_for_sysctl(&sbuf, NULL, 64, req);
416 	count = 0;
417 	LIST_FOREACH(rrs, &source_list, rrs_entries) {
418 		sbuf_cat(&sbuf, (count++ ? ",'" : "'"));
419 		sbuf_cat(&sbuf, rrs->rrs_source->rs_ident);
420 		sbuf_cat(&sbuf, "'");
421 	}
422 	error = sbuf_finish(&sbuf);
423 	sbuf_delete(&sbuf);
424 	return (error);
425 }
426 SYSCTL_PROC(_kern_random, OID_AUTO, random_sources, CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
427 	    NULL, 0, random_source_handler, "A",
428 	    "List of active fast entropy sources.");
429 
430 /* ARGSUSED */
431 static int
432 randomdev_modevent(module_t mod __unused, int type, void *data __unused)
433 {
434 	int error = 0;
435 
436 	switch (type) {
437 	case MOD_LOAD:
438 		printf("random: entropy device external interface\n");
439 		random_dev = make_dev_credf(MAKEDEV_ETERNAL_KLD, &random_cdevsw,
440 		    RANDOM_UNIT, NULL, UID_ROOT, GID_WHEEL, 0644, "random");
441 		make_dev_alias(random_dev, "urandom"); /* compatibility */
442 		break;
443 	case MOD_UNLOAD:
444 		destroy_dev(random_dev);
445 		break;
446 	case MOD_SHUTDOWN:
447 		break;
448 	default:
449 		error = EOPNOTSUPP;
450 		break;
451 	}
452 	return (error);
453 }
454 
455 static moduledata_t randomdev_mod = {
456 	"random_device",
457 	randomdev_modevent,
458 	0
459 };
460 
461 DECLARE_MODULE(random_device, randomdev_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);
462 MODULE_VERSION(random_device, 1);
463 MODULE_DEPEND(random_device, crypto, 1, 1, 1);
464 MODULE_DEPEND(random_device, random_harvestq, 1, 1, 1);
465