xref: /freebsd/sys/dev/random/randomdev.c (revision 4db9ae91ff0ef9de89fcba8928c9d81739a654f0)
14db9ae91SMark Murray /*-
24db9ae91SMark Murray  * Copyright (c) 2000 Mark Murray
34db9ae91SMark Murray  * All rights reserved.
44db9ae91SMark Murray  *
54db9ae91SMark Murray  * Redistribution and use in source and binary forms, with or without
64db9ae91SMark Murray  * modification, are permitted provided that the following conditions
74db9ae91SMark Murray  * are met:
84db9ae91SMark Murray  * 1. Redistributions of source code must retain the above copyright
94db9ae91SMark Murray  *    notice, this list of conditions and the following disclaimer
104db9ae91SMark Murray  *    in this position and unchanged.
114db9ae91SMark Murray  * 2. Redistributions in binary form must reproduce the above copyright
124db9ae91SMark Murray  *    notice, this list of conditions and the following disclaimer in the
134db9ae91SMark Murray  *    documentation and/or other materials provided with the distribution.
144db9ae91SMark Murray  *
154db9ae91SMark Murray  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
164db9ae91SMark Murray  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
174db9ae91SMark Murray  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
184db9ae91SMark Murray  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
194db9ae91SMark Murray  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
204db9ae91SMark Murray  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
214db9ae91SMark Murray  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
224db9ae91SMark Murray  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
234db9ae91SMark Murray  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
244db9ae91SMark Murray  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
254db9ae91SMark Murray  *
264db9ae91SMark Murray  * $FreeBSD$
274db9ae91SMark Murray  */
284db9ae91SMark Murray 
294db9ae91SMark Murray #include <sys/param.h>
304db9ae91SMark Murray #include <sys/systm.h>
314db9ae91SMark Murray #include <sys/conf.h>
324db9ae91SMark Murray #include <sys/fcntl.h>
334db9ae91SMark Murray #include <sys/uio.h>
344db9ae91SMark Murray #include <sys/kernel.h>
354db9ae91SMark Murray #include <sys/kobj.h>
364db9ae91SMark Murray #include <sys/malloc.h>
374db9ae91SMark Murray #include <sys/module.h>
384db9ae91SMark Murray #include <sys/bus.h>
394db9ae91SMark Murray #include <sys/random.h>
404db9ae91SMark Murray #include <machine/bus.h>
414db9ae91SMark Murray #include <machine/resource.h>
424db9ae91SMark Murray #include <sys/rman.h>
434db9ae91SMark Murray #include <sys/signalvar.h>
444db9ae91SMark Murray #include <sys/sysctl.h>
454db9ae91SMark Murray #include <crypto/blowfish/blowfish.h>
464db9ae91SMark Murray 
474db9ae91SMark Murray #include "yarrow.h"
484db9ae91SMark Murray 
494db9ae91SMark Murray static d_read_t randomread;
504db9ae91SMark Murray static d_write_t randomwrite;
514db9ae91SMark Murray 
524db9ae91SMark Murray #define CDEV_MAJOR	2
534db9ae91SMark Murray #define RANDOM_MINOR	3
544db9ae91SMark Murray 
554db9ae91SMark Murray static struct cdevsw random_cdevsw = {
564db9ae91SMark Murray 	/* open */	(d_open_t *)nullop,
574db9ae91SMark Murray 	/* close */	(d_close_t *)nullop,
584db9ae91SMark Murray 	/* read */	randomread,
594db9ae91SMark Murray 	/* write */	randomwrite,
604db9ae91SMark Murray 	/* ioctl */	noioctl,
614db9ae91SMark Murray 	/* poll */	nopoll,
624db9ae91SMark Murray 	/* mmap */	nommap,
634db9ae91SMark Murray 	/* strategy */	nostrategy,
644db9ae91SMark Murray 	/* name */	"random",
654db9ae91SMark Murray 	/* maj */	CDEV_MAJOR,
664db9ae91SMark Murray 	/* dump */	nodump,
674db9ae91SMark Murray 	/* psize */	nopsize,
684db9ae91SMark Murray 	/* flags */	0,
694db9ae91SMark Murray 	/* bmaj */	-1
704db9ae91SMark Murray };
714db9ae91SMark Murray 
724db9ae91SMark Murray /* For use with make_dev(9)/destroy_dev(9). */
734db9ae91SMark Murray static dev_t randomdev;
744db9ae91SMark Murray 
754db9ae91SMark Murray void *buf;
764db9ae91SMark Murray 
774db9ae91SMark Murray extern void randominit(void);
784db9ae91SMark Murray 
794db9ae91SMark Murray extern struct state state;
804db9ae91SMark Murray 
814db9ae91SMark Murray /* This is mostly academic at the moment; as Yarrow gets extended, it will
824db9ae91SMark Murray    become more relevant */
834db9ae91SMark Murray SYSCTL_NODE(_kern, OID_AUTO, random, CTLFLAG_RW, 0, "Random Number Generator");
844db9ae91SMark Murray SYSCTL_NODE(_kern_random, OID_AUTO, yarrow, CTLFLAG_RW, 0, "Yarrow Parameters");
854db9ae91SMark Murray SYSCTL_INT(_kern_random_yarrow, OID_AUTO, gengateinterval, CTLFLAG_RW, &state.gengateinterval, 10, "Generator Gate Interval");
864db9ae91SMark Murray 
874db9ae91SMark Murray static int
884db9ae91SMark Murray randomread(dev_t dev, struct uio *uio, int flag)
894db9ae91SMark Murray {
904db9ae91SMark Murray 	u_int c, ret;
914db9ae91SMark Murray 	int error = 0;
924db9ae91SMark Murray 
934db9ae91SMark Murray 	c = min(uio->uio_resid, PAGE_SIZE);
944db9ae91SMark Murray 	buf = (void *)malloc(c, M_TEMP, M_WAITOK);
954db9ae91SMark Murray 	while (uio->uio_resid > 0 && error == 0) {
964db9ae91SMark Murray 		ret = read_random(buf, c);
974db9ae91SMark Murray 		error = uiomove(buf, ret, uio);
984db9ae91SMark Murray 	}
994db9ae91SMark Murray 	free(buf, M_TEMP);
1004db9ae91SMark Murray 	return error;
1014db9ae91SMark Murray }
1024db9ae91SMark Murray 
1034db9ae91SMark Murray static int
1044db9ae91SMark Murray randomwrite(dev_t dev, struct uio *uio, int flag)
1054db9ae91SMark Murray {
1064db9ae91SMark Murray 	u_int c;
1074db9ae91SMark Murray 	int error = 0;
1084db9ae91SMark Murray 
1094db9ae91SMark Murray 	buf = (void *)malloc(PAGE_SIZE, M_TEMP, M_WAITOK);
1104db9ae91SMark Murray 	while (uio->uio_resid > 0) {
1114db9ae91SMark Murray 		c = min(uio->uio_resid, PAGE_SIZE);
1124db9ae91SMark Murray 		error = uiomove(buf, c, uio);
1134db9ae91SMark Murray 		if (error)
1144db9ae91SMark Murray 			break;
1154db9ae91SMark Murray 		/* write_random(buf, c); */
1164db9ae91SMark Murray 	}
1174db9ae91SMark Murray 	free(buf, M_TEMP);
1184db9ae91SMark Murray 	return error;
1194db9ae91SMark Murray }
1204db9ae91SMark Murray 
1214db9ae91SMark Murray static int
1224db9ae91SMark Murray random_modevent(module_t mod, int type, void *data)
1234db9ae91SMark Murray {
1244db9ae91SMark Murray 	switch(type) {
1254db9ae91SMark Murray 	case MOD_LOAD:
1264db9ae91SMark Murray 		if (bootverbose)
1274db9ae91SMark Murray 			printf("random: <entropy source>\n");
1284db9ae91SMark Murray 		randomdev = make_dev(&random_cdevsw, RANDOM_MINOR, UID_ROOT,
1294db9ae91SMark Murray 			GID_WHEEL, 0666, "zero");
1304db9ae91SMark Murray 		randominit();
1314db9ae91SMark Murray 		return 0;
1324db9ae91SMark Murray 
1334db9ae91SMark Murray 	case MOD_UNLOAD:
1344db9ae91SMark Murray 		destroy_dev(randomdev);
1354db9ae91SMark Murray 		return 0;
1364db9ae91SMark Murray 
1374db9ae91SMark Murray 	case MOD_SHUTDOWN:
1384db9ae91SMark Murray 		return 0;
1394db9ae91SMark Murray 
1404db9ae91SMark Murray 	default:
1414db9ae91SMark Murray 		return EOPNOTSUPP;
1424db9ae91SMark Murray 	}
1434db9ae91SMark Murray }
1444db9ae91SMark Murray 
1454db9ae91SMark Murray DEV_MODULE(random, random_modevent, NULL);
146