randomdev.c revision 65686
162053Smarkm/*- 262765Smarkm * Copyright (c) 2000 Mark R V Murray 362053Smarkm * All rights reserved. 462053Smarkm * 562053Smarkm * Redistribution and use in source and binary forms, with or without 662053Smarkm * modification, are permitted provided that the following conditions 762053Smarkm * are met: 862053Smarkm * 1. Redistributions of source code must retain the above copyright 962053Smarkm * notice, this list of conditions and the following disclaimer 1062053Smarkm * in this position and unchanged. 1162053Smarkm * 2. Redistributions in binary form must reproduce the above copyright 1262053Smarkm * notice, this list of conditions and the following disclaimer in the 1362053Smarkm * documentation and/or other materials provided with the distribution. 1462053Smarkm * 1562053Smarkm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1662053Smarkm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1762053Smarkm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1862053Smarkm * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1962053Smarkm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2062053Smarkm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2162053Smarkm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2262053Smarkm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2362053Smarkm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2462053Smarkm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2562053Smarkm * 2662053Smarkm * $FreeBSD: head/sys/dev/random/randomdev.c 65686 2000-09-10 13:52:19Z markm $ 2762053Smarkm */ 2862053Smarkm 2962053Smarkm#include <sys/param.h> 3062765Smarkm#include <sys/queue.h> 3162053Smarkm#include <sys/systm.h> 3262053Smarkm#include <sys/conf.h> 3362053Smarkm#include <sys/fcntl.h> 3462053Smarkm#include <sys/uio.h> 3562053Smarkm#include <sys/kernel.h> 3662053Smarkm#include <sys/malloc.h> 3762053Smarkm#include <sys/module.h> 3862053Smarkm#include <sys/bus.h> 3962053Smarkm#include <sys/random.h> 4062053Smarkm#include <machine/bus.h> 4162053Smarkm#include <machine/resource.h> 4262053Smarkm#include <sys/rman.h> 4362053Smarkm#include <sys/signalvar.h> 4462053Smarkm#include <sys/sysctl.h> 4562053Smarkm#include <crypto/blowfish/blowfish.h> 4662053Smarkm 4765686Smarkm#include <dev/randomdev/hash.h> 4862117Smarkm#include <dev/randomdev/yarrow.h> 4962053Smarkm 5063855Smarkmstatic d_open_t random_open; 5162765Smarkmstatic d_read_t random_read; 5262765Smarkmstatic d_write_t random_write; 5365686Smarkmstatic d_ioctl_t random_ioctl; 5462053Smarkm 5562053Smarkm#define CDEV_MAJOR 2 5662053Smarkm#define RANDOM_MINOR 3 5762149Smarkm#define URANDOM_MINOR 4 5862053Smarkm 5962053Smarkmstatic struct cdevsw random_cdevsw = { 6063855Smarkm /* open */ random_open, 6162053Smarkm /* close */ (d_close_t *)nullop, 6262765Smarkm /* read */ random_read, 6362765Smarkm /* write */ random_write, 6465686Smarkm /* ioctl */ random_ioctl, 6562053Smarkm /* poll */ nopoll, 6662053Smarkm /* mmap */ nommap, 6762053Smarkm /* strategy */ nostrategy, 6862053Smarkm /* name */ "random", 6962053Smarkm /* maj */ CDEV_MAJOR, 7062053Smarkm /* dump */ nodump, 7162053Smarkm /* psize */ nopsize, 7262053Smarkm /* flags */ 0, 7362053Smarkm /* bmaj */ -1 7462053Smarkm}; 7562053Smarkm 7662053Smarkm/* For use with make_dev(9)/destroy_dev(9). */ 7762765Smarkmstatic dev_t random_dev; 7865686Smarkmstatic dev_t urandom_dev; /* XXX Temporary */ 7962053Smarkm 8062053SmarkmSYSCTL_NODE(_kern, OID_AUTO, random, CTLFLAG_RW, 0, "Random Number Generator"); 8162053SmarkmSYSCTL_NODE(_kern_random, OID_AUTO, yarrow, CTLFLAG_RW, 0, "Yarrow Parameters"); 8262840SmarkmSYSCTL_INT(_kern_random_yarrow, OID_AUTO, gengateinterval, CTLFLAG_RW, 8362840Smarkm &random_state.gengateinterval, 10, "Generator Gate Interval"); 8462840SmarkmSYSCTL_INT(_kern_random_yarrow, OID_AUTO, bins, CTLFLAG_RW, 8562840Smarkm &random_state.bins, 10, "Execution time tuner"); 8662840SmarkmSYSCTL_INT(_kern_random_yarrow, OID_AUTO, fastthresh, CTLFLAG_RW, 8762840Smarkm &random_state.pool[0].thresh, 100, "Fast pool reseed threshhold"); 8862840SmarkmSYSCTL_INT(_kern_random_yarrow, OID_AUTO, slowthresh, CTLFLAG_RW, 8963855Smarkm &random_state.pool[1].thresh, 160, "Slow pool reseed threshhold"); 9062840SmarkmSYSCTL_INT(_kern_random_yarrow, OID_AUTO, slowoverthresh, CTLFLAG_RW, 9162840Smarkm &random_state.slowoverthresh, 2, "Slow pool over-threshhold reseed"); 9262053Smarkm 9362053Smarkmstatic int 9463855Smarkmrandom_open(dev_t dev, int flags, int fmt, struct proc *p) 9563855Smarkm{ 9663855Smarkm if ((flags & FWRITE) && (securelevel > 0 || suser(p))) 9763855Smarkm return EPERM; 9863855Smarkm else 9963855Smarkm return 0; 10063855Smarkm} 10163855Smarkm 10263855Smarkmstatic int 10362765Smarkmrandom_read(dev_t dev, struct uio *uio, int flag) 10462053Smarkm{ 10562053Smarkm u_int c, ret; 10662053Smarkm int error = 0; 10762840Smarkm void *random_buf; 10862053Smarkm 10962053Smarkm c = min(uio->uio_resid, PAGE_SIZE); 11062765Smarkm random_buf = (void *)malloc(c, M_TEMP, M_WAITOK); 11162053Smarkm while (uio->uio_resid > 0 && error == 0) { 11265686Smarkm ret = read_random(uio->uio_procp, random_buf, c); 11362765Smarkm error = uiomove(random_buf, ret, uio); 11462053Smarkm } 11562765Smarkm free(random_buf, M_TEMP); 11662053Smarkm return error; 11762053Smarkm} 11862053Smarkm 11962053Smarkmstatic int 12062765Smarkmrandom_write(dev_t dev, struct uio *uio, int flag) 12162053Smarkm{ 12262053Smarkm u_int c; 12362053Smarkm int error = 0; 12462840Smarkm void *random_buf; 12562053Smarkm 12662765Smarkm random_buf = (void *)malloc(PAGE_SIZE, M_TEMP, M_WAITOK); 12762053Smarkm while (uio->uio_resid > 0) { 12862053Smarkm c = min(uio->uio_resid, PAGE_SIZE); 12962765Smarkm error = uiomove(random_buf, c, uio); 13062053Smarkm if (error) 13162053Smarkm break; 13263306Smarkm write_random(random_buf, c); 13362053Smarkm } 13462765Smarkm free(random_buf, M_TEMP); 13562053Smarkm return error; 13662053Smarkm} 13762053Smarkm 13862053Smarkmstatic int 13965686Smarkmrandom_ioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) 14065686Smarkm{ 14165686Smarkm return ENOTTY; 14265686Smarkm} 14365686Smarkm 14465686Smarkmstatic int 14562053Smarkmrandom_modevent(module_t mod, int type, void *data) 14662053Smarkm{ 14765686Smarkm int error; 14865686Smarkm 14962053Smarkm switch(type) { 15062053Smarkm case MOD_LOAD: 15165686Smarkm error = random_init(); 15265686Smarkm if (error != 0) 15365686Smarkm return error; 15462053Smarkm if (bootverbose) 15562053Smarkm printf("random: <entropy source>\n"); 15662765Smarkm random_dev = make_dev(&random_cdevsw, RANDOM_MINOR, UID_ROOT, 15762149Smarkm GID_WHEEL, 0666, "random"); 15862765Smarkm urandom_dev = make_dev(&random_cdevsw, URANDOM_MINOR, UID_ROOT, 15965686Smarkm GID_WHEEL, 0666, "urandom"); /* XXX Temporary */ 16062053Smarkm return 0; 16162053Smarkm 16262053Smarkm case MOD_UNLOAD: 16362765Smarkm random_deinit(); 16462765Smarkm destroy_dev(random_dev); 16565686Smarkm destroy_dev(urandom_dev); /* XXX Temporary */ 16662053Smarkm return 0; 16762053Smarkm 16862053Smarkm case MOD_SHUTDOWN: 16962053Smarkm return 0; 17062053Smarkm 17162053Smarkm default: 17262053Smarkm return EOPNOTSUPP; 17362053Smarkm } 17462053Smarkm} 17562053Smarkm 17662053SmarkmDEV_MODULE(random, random_modevent, NULL); 177