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