[BACK]Return to rnd.c CVS log [TXT][DIR] Up to [local] / sys / dev

Annotation of sys/dev/rnd.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: rnd.c,v 1.82 2007/06/17 21:22:04 jasper Exp $ */
        !             2:
        !             3: /*
        !             4:  * rnd.c -- A strong random number generator
        !             5:  *
        !             6:  * Copyright (c) 1996, 1997, 2000-2002 Michael Shalayeff.
        !             7:  *
        !             8:  * Version 1.89, last modified 19-Sep-99
        !             9:  *
        !            10:  * Copyright Theodore Ts'o, 1994, 1995, 1996, 1997, 1998, 1999.
        !            11:  * All rights reserved.
        !            12:  *
        !            13:  * Redistribution and use in source and binary forms, with or without
        !            14:  * modification, are permitted provided that the following conditions
        !            15:  * are met:
        !            16:  * 1. Redistributions of source code must retain the above copyright
        !            17:  *    notice, and the entire permission notice in its entirety,
        !            18:  *    including the disclaimer of warranties.
        !            19:  * 2. Redistributions in binary form must reproduce the above copyright
        !            20:  *    notice, this list of conditions and the following disclaimer in the
        !            21:  *    documentation and/or other materials provided with the distribution.
        !            22:  * 3. The name of the author may not be used to endorse or promote
        !            23:  *    products derived from this software without specific prior
        !            24:  *    written permission.
        !            25:  *
        !            26:  * ALTERNATIVELY, this product may be distributed under the terms of
        !            27:  * the GNU Public License, in which case the provisions of the GPL are
        !            28:  * required INSTEAD OF the above restrictions.  (This clause is
        !            29:  * necessary due to a potential bad interaction between the GPL and
        !            30:  * the restrictions contained in a BSD-style copyright.)
        !            31:  *
        !            32:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
        !            33:  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            34:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
        !            35:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
        !            36:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
        !            37:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
        !            38:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            39:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
        !            40:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            41:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
        !            42:  * OF THE POSSIBILITY OF SUCH DAMAGE.
        !            43:  */
        !            44: /*
        !            45:  * (now, with legal B.S. out of the way.....)
        !            46:  *
        !            47:  * This routine gathers environmental noise from device drivers, etc.,
        !            48:  * and returns good random numbers, suitable for cryptographic use.
        !            49:  * Besides the obvious cryptographic uses, these numbers are also good
        !            50:  * for seeding TCP sequence numbers, and other places where it is
        !            51:  * desirable to have numbers which are not only random, but hard to
        !            52:  * predict by an attacker.
        !            53:  *
        !            54:  * Theory of operation
        !            55:  * ===================
        !            56:  *
        !            57:  * Computers are very predictable devices.  Hence it is extremely hard
        !            58:  * to produce truly random numbers on a computer --- as opposed to
        !            59:  * pseudo-random numbers, which can be easily generated by using an
        !            60:  * algorithm.  Unfortunately, it is very easy for attackers to guess
        !            61:  * the sequence of pseudo-random number generators, and for some
        !            62:  * applications this is not acceptable.  Instead, we must try to
        !            63:  * gather "environmental noise" from the computer's environment, which
        !            64:  * must be hard for outside attackers to observe and use to
        !            65:  * generate random numbers.  In a Unix environment, this is best done
        !            66:  * from inside the kernel.
        !            67:  *
        !            68:  * Sources of randomness from the environment include inter-keyboard
        !            69:  * timings, inter-interrupt timings from some interrupts, and other
        !            70:  * events which are both (a) non-deterministic and (b) hard for an
        !            71:  * outside observer to measure.  Randomness from these sources is
        !            72:  * added to the "entropy pool", which is mixed using a CRC-like function.
        !            73:  * This is not cryptographically strong, but it is adequate assuming
        !            74:  * the randomness is not chosen maliciously, and it is fast enough that
        !            75:  * the overhead of doing it on every interrupt is very reasonable.
        !            76:  * As random bytes are mixed into the entropy pool, the routines keep
        !            77:  * an *estimate* of how many bits of randomness have been stored into
        !            78:  * the random number generator's internal state.
        !            79:  *
        !            80:  * When random bytes are desired, they are obtained by taking the MD5
        !            81:  * hash of the content of the entropy pool.  The MD5 hash avoids
        !            82:  * exposing the internal state of the entropy pool.  It is believed to
        !            83:  * be computationally infeasible to derive any useful information
        !            84:  * about the input of MD5 from its output.  Even if it is possible to
        !            85:  * analyze MD5 in some clever way, as long as the amount of data
        !            86:  * returned from the generator is less than the inherent entropy in
        !            87:  * the pool, the output data is totally unpredictable.  For this
        !            88:  * reason, the routine decreases its internal estimate of how many
        !            89:  * bits of "true randomness" are contained in the entropy pool as it
        !            90:  * outputs random numbers.
        !            91:  *
        !            92:  * If this estimate goes to zero, the routine can still generate
        !            93:  * random numbers; however, an attacker may (at least in theory) be
        !            94:  * able to infer the future output of the generator from prior
        !            95:  * outputs.  This requires successful cryptanalysis of MD5, which is
        !            96:  * believed to be not feasible, but there is a remote possibility.
        !            97:  * Nonetheless, these numbers should be useful for the vast majority
        !            98:  * of purposes.
        !            99:  *
        !           100:  * Exported interfaces ---- output
        !           101:  * ===============================
        !           102:  *
        !           103:  * There are three exported interfaces.
        !           104:  * The first one is designed to be used from within the kernel:
        !           105:  *
        !           106:  *     void get_random_bytes(void *buf, int nbytes);
        !           107:  *
        !           108:  * This interface will return the requested number of random bytes,
        !           109:  * and place it in the requested buffer.
        !           110:  *
        !           111:  * Two other interfaces are two character devices /dev/random and
        !           112:  * /dev/urandom.  /dev/random is suitable for use when very high
        !           113:  * quality randomness is desired (for example, for key generation or
        !           114:  * one-time pads), as it will only return a maximum of the number of
        !           115:  * bits of randomness (as estimated by the random number generator)
        !           116:  * contained in the entropy pool.
        !           117:  *
        !           118:  * The /dev/urandom device does not have this limit, and will return
        !           119:  * as many bytes as were requested.  As more and more random bytes
        !           120:  * requested without giving time for the entropy pool to recharge,
        !           121:  * this will result in random numbers that are merely cryptographically
        !           122:  * strong.  For many applications, however, this is acceptable.
        !           123:  *
        !           124:  * Exported interfaces ---- input
        !           125:  * ==============================
        !           126:  *
        !           127:  * The current exported interfaces for gathering environmental noise
        !           128:  * from the devices are:
        !           129:  *
        !           130:  *     void add_true_randomness(int data);
        !           131:  *     void add_timer_randomness(int data);
        !           132:  *     void add_mouse_randomness(int mouse_data);
        !           133:  *     void add_net_randomness(int isr);
        !           134:  *     void add_tty_randomness(int c);
        !           135:  *     void add_disk_randomness(int n);
        !           136:  *     void add_audio_randomness(int n);
        !           137:  *
        !           138:  * add_true_randomness() uses true random number generators present
        !           139:  * on some cryptographic and system chipsets.  Entropy accounting
        !           140:  * is not quitable, no timing is done, supplied 32 bits of pure entropy
        !           141:  * are hashed into the pool plain and blindly, increasing the counter.
        !           142:  *
        !           143:  * add_timer_randomness() uses the random driver itselves timing,
        !           144:  * measuring extract_entropy() and rndioctl() execution times.
        !           145:  *
        !           146:  * add_mouse_randomness() uses the mouse interrupt timing, as well as
        !           147:  * the reported position of the mouse from the hardware.
        !           148:  *
        !           149:  * add_net_randomness() times the finishing time of net input.
        !           150:  *
        !           151:  * add_tty_randomness() uses the inter-keypress timing, as well as the
        !           152:  * character as random inputs into the entropy pool.
        !           153:  *
        !           154:  * add_disk_randomness() times the finishing time of disk requests as well
        !           155:  * as feeding both xfer size & time into the entropy pool.
        !           156:  *
        !           157:  * add_audio_randomness() times the finishing of audio codec dma
        !           158:  * requests for both recording and playback, apparently supplies quite
        !           159:  * a lot of entropy. I'd blame it on low resolution audio clock generators.
        !           160:  *
        !           161:  * All of these routines (except for add_true_randomness() of course)
        !           162:  * try to estimate how many bits of randomness are in a particular
        !           163:  * randomness source.  They do this by keeping track of the first and
        !           164:  * second order deltas of the event timings.
        !           165:  *
        !           166:  * Ensuring unpredictability at system startup
        !           167:  * ============================================
        !           168:  *
        !           169:  * When any operating system starts up, it will go through a sequence
        !           170:  * of actions that are fairly predictable by an adversary, especially
        !           171:  * if the start-up does not involve interaction with a human operator.
        !           172:  * This reduces the actual number of bits of unpredictability in the
        !           173:  * entropy pool below the value in entropy_count.  In order to
        !           174:  * counteract this effect, it helps to carry information in the
        !           175:  * entropy pool across shut-downs and start-ups.  To do this, put the
        !           176:  * following lines in appropriate script which is run during the boot
        !           177:  * sequence:
        !           178:  *
        !           179:  *     echo "Initializing random number generator..."
        !           180:  *     # Carry a random seed from start-up to start-up
        !           181:  *     # Load and then save 512 bytes, which is the size of the entropy pool
        !           182:  *     if [ -f /etc/random-seed ]; then
        !           183:  *             cat /etc/random-seed >/dev/urandom
        !           184:  *     fi
        !           185:  *     dd if=/dev/urandom of=/etc/random-seed count=1
        !           186:  *
        !           187:  * and the following lines in appropriate script which is run when
        !           188:  * the system is shutting down:
        !           189:  *
        !           190:  *     # Carry a random seed from shut-down to start-up
        !           191:  *     # Save 512 bytes, which is the size of the entropy pool
        !           192:  *     echo "Saving random seed..."
        !           193:  *     dd if=/dev/urandom of=/etc/random-seed count=1
        !           194:  *
        !           195:  * For example, on OpenBSD systems, the appropriate scripts are
        !           196:  * usually /etc/rc.local and /etc/rc.shutdown, respectively.
        !           197:  *
        !           198:  * Effectively, these commands cause the contents of the entropy pool
        !           199:  * to be saved at shutdown time and reloaded into the entropy pool at
        !           200:  * start-up.  (The 'dd' in the addition to the bootup script is to
        !           201:  * make sure that /etc/random-seed is different for every start-up,
        !           202:  * even if the system crashes without executing rc.shutdown) Even with
        !           203:  * complete knowledge of the start-up activities, predicting the state
        !           204:  * of the entropy pool requires knowledge of the previous history of
        !           205:  * the system.
        !           206:  *
        !           207:  * Configuring the random(4) driver under OpenBSD
        !           208:  * ==============================================
        !           209:  *
        !           210:  * The special files for the random(4) driver should have been created
        !           211:  * during the installation process.  However, if your system does not have
        !           212:  * /dev/random and /dev/[s|u|p|a]random created already, they can be created
        !           213:  * by using the MAKEDEV(8) script in /dev:
        !           214:  *
        !           215:  *     /dev/MAKEDEV random
        !           216:  *
        !           217:  * Check MAKEDEV for information about major and minor numbers.
        !           218:  *
        !           219:  * Acknowledgements:
        !           220:  * =================
        !           221:  *
        !           222:  * Ideas for constructing this random number generator were derived
        !           223:  * from Pretty Good Privacy's random number generator, and from private
        !           224:  * discussions with Phil Karn.  Colin Plumb provided a faster random
        !           225:  * number generator, which speeds up the mixing function of the entropy
        !           226:  * pool, taken from PGPfone.  Dale Worley has also contributed many
        !           227:  * useful ideas and suggestions to improve this driver.
        !           228:  *
        !           229:  * Any flaws in the design are solely my responsibility, and should
        !           230:  * not be attributed to the Phil, Colin, or any of the authors of PGP.
        !           231:  *
        !           232:  * Further background information on this topic may be obtained from
        !           233:  * RFC 1750, "Randomness Recommendations for Security", by Donald
        !           234:  * Eastlake, Steve Crocker, and Jeff Schiller.
        !           235:  */
        !           236:
        !           237: #undef RNDEBUG
        !           238:
        !           239: #include <sys/param.h>
        !           240: #include <sys/systm.h>
        !           241: #include <sys/conf.h>
        !           242: #include <sys/disk.h>
        !           243: #include <sys/ioctl.h>
        !           244: #include <sys/malloc.h>
        !           245: #include <sys/fcntl.h>
        !           246: #include <sys/vnode.h>
        !           247: #include <sys/sysctl.h>
        !           248: #include <sys/timeout.h>
        !           249: #include <sys/poll.h>
        !           250:
        !           251: #include <crypto/md5.h>
        !           252:
        !           253: #include <dev/rndvar.h>
        !           254: #include <dev/rndioctl.h>
        !           255:
        !           256: #ifdef RNDEBUG
        !           257: int    rnd_debug = 0x0000;
        !           258: #define        RD_INPUT        0x000f  /* input data */
        !           259: #define        RD_OUTPUT       0x00f0  /* output data */
        !           260: #define        RD_WAIT         0x0100  /* sleep/wakeup for good data */
        !           261: #endif
        !           262:
        !           263: /*
        !           264:  * The pool is stirred with a primitive polynomial of degree 128
        !           265:  * over GF(2), namely x^128 + x^99 + x^59 + x^31 + x^9 + x^7 + 1.
        !           266:  * For a pool of size 64, try x^64+x^62+x^38+x^10+x^6+x+1.
        !           267:  */
        !           268: #define POOLBITS (POOLWORDS*32)
        !           269: #define POOLBYTES (POOLWORDS*4)
        !           270: #if POOLWORDS == 2048
        !           271: #define        TAP1    1638
        !           272: #define        TAP2    1231
        !           273: #define        TAP3    819
        !           274: #define        TAP4    411
        !           275: #define        TAP5    1
        !           276: #elif POOLWORDS == 1024        /* also (819, 616, 410, 207, 2) */
        !           277: #define        TAP1    817
        !           278: #define        TAP2    615
        !           279: #define        TAP3    412
        !           280: #define        TAP4    204
        !           281: #define        TAP5    1
        !           282: #elif POOLWORDS == 512 /* also (409,307,206,102,2), (409,309,205,103,2) */
        !           283: #define        TAP1    411
        !           284: #define        TAP2    308
        !           285: #define        TAP3    208
        !           286: #define        TAP4    104
        !           287: #define        TAP5    1
        !           288: #elif POOLWORDS == 256
        !           289: #define        TAP1    205
        !           290: #define        TAP2    155
        !           291: #define        TAP3    101
        !           292: #define        TAP4    52
        !           293: #define        TAP5    1
        !           294: #elif POOLWORDS == 128 /* also (103, 78, 51, 27, 2) */
        !           295: #define        TAP1    103
        !           296: #define        TAP2    76
        !           297: #define        TAP3    51
        !           298: #define        TAP4    25
        !           299: #define        TAP5    1
        !           300: #elif POOLWORDS == 64
        !           301: #define        TAP1    52
        !           302: #define        TAP2    39
        !           303: #define        TAP3    26
        !           304: #define        TAP4    14
        !           305: #define        TAP5    1
        !           306: #elif POOLWORDS == 32
        !           307: #define        TAP1    26
        !           308: #define        TAP2    20
        !           309: #define        TAP3    14
        !           310: #define        TAP4    7
        !           311: #define        TAP5    1
        !           312: #else
        !           313: #error No primitive polynomial available for chosen POOLWORDS
        !           314: #endif
        !           315:
        !           316: /*
        !           317:  * For the purposes of better mixing, we use the CRC-32 polynomial as
        !           318:  * well to make a twisted Generalized Feedback Shift Register
        !           319:  *
        !           320:  * (See M. Matsumoto & Y. Kurita, 1992.  Twisted GFSR generators.  ACM
        !           321:  * Transactions on Modeling and Computer Simulation 2(3):179-194.
        !           322:  * Also see M. Matsumoto & Y. Kurita, 1994.  Twisted GFSR generators
        !           323:  * II.  ACM Transactions on Mdeling and Computer Simulation 4:254-266)
        !           324:  *
        !           325:  * Thanks to Colin Plumb for suggesting this.
        !           326:  *
        !           327:  * We have not analyzed the resultant polynomial to prove it primitive;
        !           328:  * in fact it almost certainly isn't.  Nonetheless, the irreducible factors
        !           329:  * of a random large-degree polynomial over GF(2) are more than large enough
        !           330:  * that periodicity is not a concern.
        !           331:  *
        !           332:  * The input hash is much less sensitive than the output hash.  All
        !           333:  * we want from it is to be a good non-cryptographic hash -
        !           334:  * i.e. to not produce collisions when fed "random" data of the sort
        !           335:  * we expect to see.  As long as the pool state differs for different
        !           336:  * inputs, we have preserved the input entropy and done a good job.
        !           337:  * The fact that an intelligent attacker can construct inputs that
        !           338:  * will produce controlled alterations to the pool's state is not
        !           339:  * important because we don't consider such inputs to contribute any
        !           340:  * randomness.  The only property we need with respect to them is that
        !           341:  * the attacker can't increase his/her knowledge of the pool's state.
        !           342:  * Since all additions are reversible (knowing the final state and the
        !           343:  * input, you can reconstruct the initial state), if an attacker has
        !           344:  * any uncertainty about the initial state, he/she can only shuffle
        !           345:  * that uncertainty about, but never cause any collisions (which would
        !           346:  * decrease the uncertainty).
        !           347:  *
        !           348:  * The chosen system lets the state of the pool be (essentially) the input
        !           349:  * modulo the generator polynomial.  Now, for random primitive polynomials,
        !           350:  * this is a universal class of hash functions, meaning that the chance
        !           351:  * of a collision is limited by the attacker's knowledge of the generator
        !           352:  * polynomial, so if it is chosen at random, an attacker can never force
        !           353:  * a collision.  Here, we use a fixed polynomial, but we *can* assume that
        !           354:  * ###--> it is unknown to the processes generating the input entropy. <-###
        !           355:  * Because of this important property, this is a good, collision-resistant
        !           356:  * hash; hash collisions will occur no more often than chance.
        !           357:  */
        !           358:
        !           359: /* pIII/333 reported to have some drops w/ these numbers */
        !           360: #define QEVLEN (1024 / sizeof(struct rand_event))
        !           361: #define QEVSLOW (QEVLEN * 3 / 4) /* yet another 0.75 for 60-minutes hour /-; */
        !           362: #define QEVSBITS 10
        !           363:
        !           364: /* There is actually only one of these, globally. */
        !           365: struct random_bucket {
        !           366:        u_int   add_ptr;
        !           367:        u_int   entropy_count;
        !           368:        u_char  input_rotate;
        !           369:        u_int32_t pool[POOLWORDS];
        !           370:        u_int   asleep;
        !           371:        u_int   tmo;
        !           372: };
        !           373:
        !           374: /* There is one of these per entropy source */
        !           375: struct timer_rand_state {
        !           376:        u_int   last_time;
        !           377:        u_int   last_delta;
        !           378:        u_int   last_delta2;
        !           379:        u_int   dont_count_entropy : 1;
        !           380:        u_int   max_entropy : 1;
        !           381: };
        !           382:
        !           383: struct arc4_stream {
        !           384:        u_int8_t s[256];
        !           385:        u_int   cnt;
        !           386:        u_int8_t i;
        !           387:        u_int8_t j;
        !           388: };
        !           389:
        !           390: struct rand_event {
        !           391:        struct timer_rand_state *re_state;
        !           392:        u_int re_nbits;
        !           393:        u_int re_time;
        !           394:        u_int re_val;
        !           395: };
        !           396:
        !           397: struct timeout rnd_timeout, arc4_timeout;
        !           398: struct random_bucket random_state;
        !           399: struct arc4_stream arc4random_state;
        !           400: struct timer_rand_state rnd_states[RND_SRC_NUM];
        !           401: struct rand_event rnd_event_space[QEVLEN];
        !           402: struct rand_event *rnd_event_head = rnd_event_space;
        !           403: struct rand_event *rnd_event_tail = rnd_event_space;
        !           404: struct selinfo rnd_rsel, rnd_wsel;
        !           405:
        !           406: void filt_rndrdetach(struct knote *kn);
        !           407: int filt_rndread(struct knote *kn, long hint);
        !           408:
        !           409: struct filterops rndread_filtops =
        !           410:        { 1, NULL, filt_rndrdetach, filt_rndread};
        !           411:
        !           412: void filt_rndwdetach(struct knote *kn);
        !           413: int filt_rndwrite(struct knote *kn, long hint);
        !           414:
        !           415: struct filterops rndwrite_filtops =
        !           416:        { 1, NULL, filt_rndwdetach, filt_rndwrite};
        !           417:
        !           418: int rnd_attached;
        !           419: int arc4random_initialized;
        !           420: struct rndstats rndstats;
        !           421:
        !           422: static __inline u_int32_t roll(u_int32_t w, int i)
        !           423: {
        !           424: #ifdef i386
        !           425:        __asm ("roll %%cl, %0" : "+r" (w) : "c" (i));
        !           426: #else
        !           427:        w = (w << i) | (w >> (32 - i));
        !           428: #endif
        !           429:        return w;
        !           430: }
        !           431:
        !           432: /* must be called at a proper spl, returns ptr to the next event */
        !           433: static __inline struct rand_event *
        !           434: rnd_get(void)
        !           435: {
        !           436:        struct rand_event *p = rnd_event_tail;
        !           437:
        !           438:        if (p == rnd_event_head)
        !           439:                return NULL;
        !           440:
        !           441:        if (p + 1 >= &rnd_event_space[QEVLEN])
        !           442:                rnd_event_tail = rnd_event_space;
        !           443:        else
        !           444:                rnd_event_tail++;
        !           445:
        !           446:        return p;
        !           447: }
        !           448:
        !           449: /* must be called at a proper spl, returns next available item */
        !           450: static __inline struct rand_event *
        !           451: rnd_put(void)
        !           452: {
        !           453:        struct rand_event *p = rnd_event_head + 1;
        !           454:
        !           455:        if (p >= &rnd_event_space[QEVLEN])
        !           456:                p = rnd_event_space;
        !           457:
        !           458:        if (p == rnd_event_tail)
        !           459:                return NULL;
        !           460:
        !           461:        return rnd_event_head = p;
        !           462: }
        !           463:
        !           464: /* must be called at a proper spl, returns number of items in the queue */
        !           465: static __inline int
        !           466: rnd_qlen(void)
        !           467: {
        !           468:        int len = rnd_event_head - rnd_event_tail;
        !           469:        return (len < 0)? -len : len;
        !           470: }
        !           471:
        !           472: void dequeue_randomness(void *);
        !           473:
        !           474: static void add_entropy_words(const u_int32_t *, u_int n);
        !           475: void extract_entropy(u_int8_t *, int);
        !           476:
        !           477: static u_int8_t arc4_getbyte(void);
        !           478: void arc4_stir(void);
        !           479: void arc4_reinit(void *v);
        !           480: void arc4maybeinit(void);
        !           481:
        !           482: /* Arcfour random stream generator.  This code is derived from section
        !           483:  * 17.1 of Applied Cryptography, second edition, which describes a
        !           484:  * stream cipher allegedly compatible with RSA Labs "RC4" cipher (the
        !           485:  * actual description of which is a trade secret).  The same algorithm
        !           486:  * is used as a stream cipher called "arcfour" in Tatu Ylonen's ssh
        !           487:  * package.
        !           488:  *
        !           489:  * The initialization function here has been modified to not discard
        !           490:  * the old state, and its input always includes the time of day in
        !           491:  * microseconds.  Moreover, bytes from the stream may at any point be
        !           492:  * diverted to multiple processes or even kernel functions desiring
        !           493:  * random numbers.  This increases the strength of the random stream,
        !           494:  * but makes it impossible to use this code for encryption, since there
        !           495:  * is no way to ever reproduce the same stream of random bytes.
        !           496:  *
        !           497:  * RC4 is a registered trademark of RSA Laboratories.
        !           498:  */
        !           499:
        !           500: static u_int8_t
        !           501: arc4_getbyte(void)
        !           502: {
        !           503:        u_int8_t si, sj, ret;
        !           504:        int s;
        !           505:
        !           506:        s = splhigh();
        !           507:        rndstats.arc4_reads++;
        !           508:        arc4random_state.cnt++;
        !           509:        arc4random_state.i++;
        !           510:        si = arc4random_state.s[arc4random_state.i];
        !           511:        arc4random_state.j += si;
        !           512:        sj = arc4random_state.s[arc4random_state.j];
        !           513:        arc4random_state.s[arc4random_state.i] = sj;
        !           514:        arc4random_state.s[arc4random_state.j] = si;
        !           515:        ret = arc4random_state.s[(si + sj) & 0xff];
        !           516:        splx(s);
        !           517:        return (ret);
        !           518: }
        !           519:
        !           520: void
        !           521: arc4_stir(void)
        !           522: {
        !           523:        u_int8_t buf[256];
        !           524:        u_int8_t si;
        !           525:        int n, s;
        !           526:        int len;
        !           527:
        !           528:        nanotime((struct timespec *) buf);
        !           529:        len = random_state.entropy_count / 8; /* XXX maybe a half? */
        !           530:        if (len > sizeof(buf) - sizeof(struct timeval))
        !           531:                len = sizeof(buf) - sizeof(struct timeval);
        !           532:        get_random_bytes(buf + sizeof (struct timeval), len);
        !           533:        len += sizeof(struct timeval);
        !           534:
        !           535:        s = splhigh();
        !           536:        arc4random_state.i--;
        !           537:        for (n = 0; n < 256; n++) {
        !           538:                arc4random_state.i++;
        !           539:                si = arc4random_state.s[arc4random_state.i];
        !           540:                arc4random_state.j += si + buf[n % len];
        !           541:                arc4random_state.s[arc4random_state.i] =
        !           542:                    arc4random_state.s[arc4random_state.j];
        !           543:                arc4random_state.s[arc4random_state.j] = si;
        !           544:        }
        !           545:        arc4random_state.j = arc4random_state.i;
        !           546:        arc4random_state.cnt = 0;
        !           547:        rndstats.arc4_stirs += len;
        !           548:        rndstats.arc4_nstirs++;
        !           549:        splx(s);
        !           550:
        !           551:        /*
        !           552:         * Throw away the first N words of output, as suggested in the
        !           553:         * paper "Weaknesses in the Key Scheduling Algorithm of RC4"
        !           554:         * by Fluher, Mantin, and Shamir.  (N = 256 in our case.)
        !           555:         */
        !           556:        for (n = 0; n < 256 * 4; n++)
        !           557:                arc4_getbyte();
        !           558: }
        !           559:
        !           560: void
        !           561: arc4maybeinit(void)
        !           562: {
        !           563:        extern int hz;
        !           564:
        !           565:        if (!arc4random_initialized) {
        !           566: #ifdef DIAGNOSTIC
        !           567:                if (!rnd_attached)
        !           568:                        panic("arc4maybeinit: premature");
        !           569: #endif
        !           570:                arc4random_initialized++;
        !           571:                arc4_stir();
        !           572:                /* 10 minutes, per dm@'s suggestion */
        !           573:                timeout_add(&arc4_timeout, 10 * 60 * hz);
        !           574:        }
        !           575: }
        !           576:
        !           577: /*
        !           578:  * called by timeout to mark arc4 for stirring,
        !           579:  * actual stirring happens on any access attempt.
        !           580:  */
        !           581: void
        !           582: arc4_reinit(void *v)
        !           583: {
        !           584:        arc4random_initialized = 0;
        !           585: }
        !           586:
        !           587: u_int32_t
        !           588: arc4random(void)
        !           589: {
        !           590:        arc4maybeinit();
        !           591:        return ((arc4_getbyte() << 24) | (arc4_getbyte() << 16)
        !           592:                | (arc4_getbyte() << 8) | arc4_getbyte());
        !           593: }
        !           594:
        !           595: void
        !           596: arc4random_bytes(void *buf, size_t n)
        !           597: {
        !           598:        u_int8_t *cp = buf;
        !           599:        u_int8_t *end = cp + n;
        !           600:
        !           601:        arc4maybeinit();
        !           602:        while (cp < end)
        !           603:                *cp++ = arc4_getbyte();
        !           604: }
        !           605:
        !           606: void
        !           607: randomattach(void)
        !           608: {
        !           609:        int i;
        !           610:
        !           611:        if (rnd_attached) {
        !           612: #ifdef RNDEBUG
        !           613:                printf("random: second attach\n");
        !           614: #endif
        !           615:                return;
        !           616:        }
        !           617:
        !           618:        timeout_set(&rnd_timeout, dequeue_randomness, &random_state);
        !           619:        timeout_set(&arc4_timeout, arc4_reinit, NULL);
        !           620:
        !           621:        random_state.add_ptr = 0;
        !           622:        random_state.entropy_count = 0;
        !           623:        rnd_states[RND_SRC_TIMER].dont_count_entropy = 1;
        !           624:        rnd_states[RND_SRC_TRUE].dont_count_entropy = 1;
        !           625:        rnd_states[RND_SRC_TRUE].max_entropy = 1;
        !           626:
        !           627:        bzero(&rndstats, sizeof(rndstats));
        !           628:        bzero(&rnd_event_space, sizeof(rnd_event_space));
        !           629:
        !           630:        for (i = 0; i < 256; i++)
        !           631:                arc4random_state.s[i] = i;
        !           632:        arc4_reinit(NULL);
        !           633:
        !           634:        rnd_attached = 1;
        !           635: }
        !           636:
        !           637: int
        !           638: randomopen(dev_t dev, int flag, int mode, struct proc *p)
        !           639: {
        !           640:        return (minor (dev) < RND_NODEV) ? 0 : ENXIO;
        !           641: }
        !           642:
        !           643: int
        !           644: randomclose(dev_t dev, int flag, int mode, struct proc *p)
        !           645: {
        !           646:        return 0;
        !           647: }
        !           648:
        !           649: /*
        !           650:  * This function adds a byte into the entropy pool.  It does not
        !           651:  * update the entropy estimate.  The caller must do this if appropriate.
        !           652:  *
        !           653:  * The pool is stirred with a primitive polynomial of degree 128
        !           654:  * over GF(2), namely x^128 + x^99 + x^59 + x^31 + x^9 + x^7 + 1.
        !           655:  * For a pool of size 64, try x^64+x^62+x^38+x^10+x^6+x+1.
        !           656:  *
        !           657:  * We rotate the input word by a changing number of bits, to help
        !           658:  * assure that all bits in the entropy get toggled.  Otherwise, if we
        !           659:  * consistently feed the entropy pool small numbers (like jiffies and
        !           660:  * scancodes, for example), the upper bits of the entropy pool don't
        !           661:  * get affected. --- TYT, 10/11/95
        !           662:  */
        !           663: static void
        !           664: add_entropy_words(const u_int32_t *buf, u_int n)
        !           665: {
        !           666:        static const u_int32_t twist_table[8] = {
        !           667:                0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158,
        !           668:                0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278
        !           669:        };
        !           670:
        !           671:        for (; n--; buf++) {
        !           672:                u_int32_t w = roll(*buf, random_state.input_rotate);
        !           673:                u_int i = random_state.add_ptr =
        !           674:                    (random_state.add_ptr - 1) & (POOLWORDS - 1);
        !           675:                /*
        !           676:                 * Normally, we add 7 bits of rotation to the pool.
        !           677:                 * At the beginning of the pool, add an extra 7 bits
        !           678:                 * rotation, so that successive passes spread the
        !           679:                 * input bits across the pool evenly.
        !           680:                 */
        !           681:                random_state.input_rotate =
        !           682:                    (random_state.input_rotate + (i? 7 : 14)) & 31;
        !           683:
        !           684:                /* XOR in the various taps */
        !           685:                w ^= random_state.pool[(i+TAP1) & (POOLWORDS-1)] ^
        !           686:                     random_state.pool[(i+TAP2) & (POOLWORDS-1)] ^
        !           687:                     random_state.pool[(i+TAP3) & (POOLWORDS-1)] ^
        !           688:                     random_state.pool[(i+TAP4) & (POOLWORDS-1)] ^
        !           689:                     random_state.pool[(i+TAP5) & (POOLWORDS-1)] ^
        !           690:                     random_state.pool[i];
        !           691:                random_state.pool[i] = (w >> 3) ^ twist_table[w & 7];
        !           692:        }
        !           693: }
        !           694:
        !           695: /*
        !           696:  * This function adds entropy to the entropy pool by using timing
        !           697:  * delays.  It uses the timer_rand_state structure to make an estimate
        !           698:  * of how many bits of entropy this call has added to the pool.
        !           699:  *
        !           700:  * The number "val" is also added to the pool - it should somehow describe
        !           701:  * the type of event which just happened.  Currently the values of 0-255
        !           702:  * are for keyboard scan codes, 256 and upwards - for interrupts.
        !           703:  * On the i386, this is assumed to be at most 16 bits, and the high bits
        !           704:  * are used for a high-resolution timer.
        !           705:  *
        !           706:  */
        !           707: void
        !           708: enqueue_randomness(int state, int val)
        !           709: {
        !           710:        struct timer_rand_state *p;
        !           711:        struct rand_event *rep;
        !           712:        struct timespec tv;
        !           713:        u_int   time, nbits;
        !           714:        int s;
        !           715:
        !           716:        /* XXX on sparc we get here before randomattach() */
        !           717:        if (!rnd_attached)
        !           718:                return;
        !           719:
        !           720: #ifdef DIAGNOSTIC
        !           721:        if (state < 0 || state >= RND_SRC_NUM)
        !           722:                return;
        !           723: #endif
        !           724:
        !           725:        p = &rnd_states[state];
        !           726:        val += state << 13;
        !           727:
        !           728:        nanotime(&tv);
        !           729:        time = (tv.tv_nsec >> 10) + (tv.tv_sec << 20);
        !           730:        nbits = 0;
        !           731:
        !           732:        /*
        !           733:         * Calculate the number of bits of randomness that we probably
        !           734:         * added.  We take into account the first and second order
        !           735:         * deltas in order to make our estimate.
        !           736:         */
        !           737:        if (!p->dont_count_entropy) {
        !           738:                int     delta, delta2, delta3;
        !           739:                delta  = time   - p->last_time;
        !           740:                delta2 = delta  - p->last_delta;
        !           741:                delta3 = delta2 - p->last_delta2;
        !           742:
        !           743:                if (delta < 0) delta = -delta;
        !           744:                if (delta2 < 0) delta2 = -delta2;
        !           745:                if (delta3 < 0) delta3 = -delta3;
        !           746:                if (delta > delta2) delta = delta2;
        !           747:                if (delta > delta3) delta = delta3;
        !           748:                delta3 = delta >>= 1;
        !           749:                /*
        !           750:                 * delta &= 0xfff;
        !           751:                 * we don't do it since our time sheet is different from linux
        !           752:                 */
        !           753:
        !           754:                if (delta & 0xffff0000) {
        !           755:                        nbits = 16;
        !           756:                        delta >>= 16;
        !           757:                }
        !           758:                if (delta & 0xff00) {
        !           759:                        nbits += 8;
        !           760:                        delta >>= 8;
        !           761:                }
        !           762:                if (delta & 0xf0) {
        !           763:                        nbits += 4;
        !           764:                        delta >>= 4;
        !           765:                }
        !           766:                if (delta & 0xc) {
        !           767:                        nbits += 2;
        !           768:                        delta >>= 2;
        !           769:                }
        !           770:                if (delta & 2) {
        !           771:                        nbits += 1;
        !           772:                        delta >>= 1;
        !           773:                }
        !           774:                if (delta & 1)
        !           775:                        nbits++;
        !           776:
        !           777:                /*
        !           778:                 * the logic is to drop low-entropy entries,
        !           779:                 * in hope for dequeuing to be more randomfull
        !           780:                 */
        !           781:                if (rnd_qlen() > QEVSLOW && nbits < QEVSBITS) {
        !           782:                        rndstats.rnd_drople++;
        !           783:                        return;
        !           784:                }
        !           785:                p->last_time = time;
        !           786:                p->last_delta  = delta3;
        !           787:                p->last_delta2 = delta2;
        !           788:        } else if (p->max_entropy)
        !           789:                nbits = 8 * sizeof(val) - 1;
        !           790:
        !           791:        s = splhigh();
        !           792:        if ((rep = rnd_put()) == NULL) {
        !           793:                rndstats.rnd_drops++;
        !           794:                splx(s);
        !           795:                return;
        !           796:        }
        !           797:
        !           798:        rep->re_state = p;
        !           799:        rep->re_nbits = nbits;
        !           800:        rep->re_time = tv.tv_nsec ^ (tv.tv_sec << 20);
        !           801:        rep->re_val = val;
        !           802:
        !           803:        rndstats.rnd_enqs++;
        !           804:        rndstats.rnd_ed[nbits]++;
        !           805:        rndstats.rnd_sc[state]++;
        !           806:        rndstats.rnd_sb[state] += nbits;
        !           807:
        !           808:        if (rnd_qlen() > QEVSLOW/2 && !random_state.tmo) {
        !           809:                random_state.tmo++;
        !           810:                timeout_add(&rnd_timeout, 1);
        !           811:        }
        !           812:        splx(s);
        !           813: }
        !           814:
        !           815: void
        !           816: dequeue_randomness(void *v)
        !           817: {
        !           818:        struct random_bucket *rs = v;
        !           819:        struct rand_event *rep;
        !           820:        u_int32_t buf[2];
        !           821:        u_int nbits;
        !           822:        int s;
        !           823:
        !           824:        timeout_del(&rnd_timeout);
        !           825:        rndstats.rnd_deqs++;
        !           826:
        !           827:        s = splhigh();
        !           828:        while ((rep = rnd_get())) {
        !           829:
        !           830:                buf[0] = rep->re_time;
        !           831:                buf[1] = rep->re_val;
        !           832:                nbits = rep->re_nbits;
        !           833:                splx(s);
        !           834:
        !           835:                add_entropy_words(buf, 2);
        !           836:
        !           837:                rndstats.rnd_total += nbits;
        !           838:                rs->entropy_count += nbits;
        !           839:                if (rs->entropy_count > POOLBITS)
        !           840:                        rs->entropy_count = POOLBITS;
        !           841:
        !           842:                if (rs->asleep && rs->entropy_count > 8) {
        !           843: #ifdef RNDEBUG
        !           844:                        if (rnd_debug & RD_WAIT)
        !           845:                                printf("rnd: wakeup[%u]{%u}\n",
        !           846:                                    rs->asleep,
        !           847:                                    rs->entropy_count);
        !           848: #endif
        !           849:                        rs->asleep--;
        !           850:                        wakeup((void *)&rs->asleep);
        !           851:                        selwakeup(&rnd_rsel);
        !           852:                        KNOTE(&rnd_rsel.si_note, 0);
        !           853:                }
        !           854:
        !           855:                s = splhigh();
        !           856:        }
        !           857:
        !           858:        rs->tmo = 0;
        !           859:        splx(s);
        !           860: }
        !           861:
        !           862: #if POOLWORDS % 16
        !           863: #error extract_entropy() assumes that POOLWORDS is a multiple of 16 words.
        !           864: #endif
        !           865:
        !           866: /*
        !           867:  * This function extracts randomness from the entropy pool, and
        !           868:  * returns it in a buffer.  This function computes how many remaining
        !           869:  * bits of entropy are left in the pool, but it does not restrict the
        !           870:  * number of bytes that are actually obtained.
        !           871:  */
        !           872: void
        !           873: extract_entropy(u_int8_t *buf, int nbytes)
        !           874: {
        !           875:        struct random_bucket *rs = &random_state;
        !           876:        u_char buffer[16];
        !           877:        MD5_CTX tmp;
        !           878:        u_int i;
        !           879:        int s;
        !           880:
        !           881:        add_timer_randomness(nbytes);
        !           882:
        !           883:        while (nbytes) {
        !           884:                if (nbytes < sizeof(buffer) / 2)
        !           885:                        i = nbytes;
        !           886:                else
        !           887:                        i = sizeof(buffer) / 2;
        !           888:
        !           889:                /* Hash the pool to get the output */
        !           890:                MD5Init(&tmp);
        !           891:                s = splhigh();
        !           892:                MD5Update(&tmp, (u_int8_t*)rs->pool, sizeof(rs->pool));
        !           893:                if (rs->entropy_count / 8 > i)
        !           894:                        rs->entropy_count -= i * 8;
        !           895:                else
        !           896:                        rs->entropy_count = 0;
        !           897:                splx(s);
        !           898:                MD5Final(buffer, &tmp);
        !           899:
        !           900:                /*
        !           901:                 * In case the hash function has some recognizable
        !           902:                 * output pattern, we fold it in half.
        !           903:                 */
        !           904:                buffer[0] ^= buffer[15];
        !           905:                buffer[1] ^= buffer[14];
        !           906:                buffer[2] ^= buffer[13];
        !           907:                buffer[3] ^= buffer[12];
        !           908:                buffer[4] ^= buffer[11];
        !           909:                buffer[5] ^= buffer[10];
        !           910:                buffer[6] ^= buffer[ 9];
        !           911:                buffer[7] ^= buffer[ 8];
        !           912:
        !           913:                /* Copy data to destination buffer */
        !           914:                bcopy(buffer, buf, i);
        !           915:                nbytes -= i;
        !           916:                buf += i;
        !           917:
        !           918:                /* Modify pool so next hash will produce different results */
        !           919:                add_timer_randomness(nbytes);
        !           920:                dequeue_randomness(&random_state);
        !           921:        }
        !           922:
        !           923:        /* Wipe data from memory */
        !           924:        bzero(&tmp, sizeof(tmp));
        !           925:        bzero(&buffer, sizeof(buffer));
        !           926: }
        !           927:
        !           928: /*
        !           929:  * This function is the exported kernel interface.  It returns some
        !           930:  * number of good random numbers, suitable for seeding TCP sequence
        !           931:  * numbers, etc.
        !           932:  */
        !           933: void
        !           934: get_random_bytes(void *buf, size_t nbytes)
        !           935: {
        !           936:        extract_entropy((u_int8_t *) buf, nbytes);
        !           937:        rndstats.rnd_used += nbytes * 8;
        !           938: }
        !           939:
        !           940: int
        !           941: randomread(dev_t dev, struct uio *uio, int ioflag)
        !           942: {
        !           943:        int             ret = 0;
        !           944:        int             i;
        !           945:        u_int32_t       *buf;
        !           946:
        !           947:        if (uio->uio_resid == 0)
        !           948:                return 0;
        !           949:
        !           950:        MALLOC(buf, u_int32_t *, POOLBYTES, M_TEMP, M_WAITOK);
        !           951:
        !           952:        while (!ret && uio->uio_resid > 0) {
        !           953:                int     n = min(POOLBYTES, uio->uio_resid);
        !           954:
        !           955:                switch(minor(dev)) {
        !           956:                case RND_RND:
        !           957:                        ret = EIO;      /* no chip -- error */
        !           958:                        break;
        !           959:                case RND_SRND:
        !           960:                        if (random_state.entropy_count < 16 * 8) {
        !           961:                                if (ioflag & IO_NDELAY) {
        !           962:                                        ret = EWOULDBLOCK;
        !           963:                                        break;
        !           964:                                }
        !           965: #ifdef RNDEBUG
        !           966:                                if (rnd_debug & RD_WAIT)
        !           967:                                        printf("rnd: sleep[%u]\n",
        !           968:                                            random_state.asleep);
        !           969: #endif
        !           970:                                random_state.asleep++;
        !           971:                                rndstats.rnd_waits++;
        !           972:                                ret = tsleep(&random_state.asleep,
        !           973:                                    PWAIT | PCATCH, "rndrd", 0);
        !           974: #ifdef RNDEBUG
        !           975:                                if (rnd_debug & RD_WAIT)
        !           976:                                        printf("rnd: awakened(%d)\n", ret);
        !           977: #endif
        !           978:                                if (ret)
        !           979:                                        break;
        !           980:                        }
        !           981:                        if (n > random_state.entropy_count / 8)
        !           982:                                n = random_state.entropy_count / 8;
        !           983:                        rndstats.rnd_reads++;
        !           984: #ifdef RNDEBUG
        !           985:                        if (rnd_debug & RD_OUTPUT)
        !           986:                                printf("rnd: %u possible output\n", n);
        !           987: #endif
        !           988:                case RND_URND:
        !           989:                        get_random_bytes((char *)buf, n);
        !           990: #ifdef RNDEBUG
        !           991:                        if (rnd_debug & RD_OUTPUT)
        !           992:                                printf("rnd: %u bytes for output\n", n);
        !           993: #endif
        !           994:                        break;
        !           995:                case RND_PRND:
        !           996:                        i = (n + 3) / 4;
        !           997:                        while (i--)
        !           998:                                buf[i] = random() << 16 | (random() & 0xFFFF);
        !           999:                        break;
        !          1000:                case RND_ARND:
        !          1001:                {
        !          1002:                        u_int8_t *cp = (u_int8_t *) buf;
        !          1003:                        u_int8_t *end = cp + n;
        !          1004:                        arc4maybeinit();
        !          1005:                        while (cp < end)
        !          1006:                                *cp++ = arc4_getbyte();
        !          1007:                        break;
        !          1008:                }
        !          1009:                default:
        !          1010:                        ret = ENXIO;
        !          1011:                }
        !          1012:                if (n != 0 && ret == 0)
        !          1013:                        ret = uiomove((caddr_t)buf, n, uio);
        !          1014:        }
        !          1015:
        !          1016:        FREE(buf, M_TEMP);
        !          1017:        return ret;
        !          1018: }
        !          1019:
        !          1020: int
        !          1021: randompoll(dev_t dev, int events, struct proc *p)
        !          1022: {
        !          1023:        int revents;
        !          1024:
        !          1025:        revents = events & (POLLOUT | POLLWRNORM);      /* always writable */
        !          1026:        if (events & (POLLIN | POLLRDNORM)) {
        !          1027:                if (minor(dev) == RND_SRND && random_state.entropy_count <= 0)
        !          1028:                        selrecord(p, &rnd_rsel);
        !          1029:                else
        !          1030:                        revents |= events & (POLLIN | POLLRDNORM);
        !          1031:        }
        !          1032:
        !          1033:        return (revents);
        !          1034: }
        !          1035:
        !          1036: int
        !          1037: randomkqfilter(dev_t dev, struct knote *kn)
        !          1038: {
        !          1039:        struct klist *klist;
        !          1040:        int s;
        !          1041:
        !          1042:        switch (kn->kn_filter) {
        !          1043:        case EVFILT_READ:
        !          1044:                klist = &rnd_rsel.si_note;
        !          1045:                kn->kn_fop = &rndread_filtops;
        !          1046:                break;
        !          1047:        case EVFILT_WRITE:
        !          1048:                klist = &rnd_wsel.si_note;
        !          1049:                kn->kn_fop = &rndwrite_filtops;
        !          1050:                break;
        !          1051:        default:
        !          1052:                return (1);
        !          1053:        }
        !          1054:        kn->kn_hook = (void *)&random_state;
        !          1055:
        !          1056:        s = splhigh();
        !          1057:        SLIST_INSERT_HEAD(klist, kn, kn_selnext);
        !          1058:        splx(s);
        !          1059:
        !          1060:        return (0);
        !          1061: }
        !          1062:
        !          1063: void
        !          1064: filt_rndrdetach(struct knote *kn)
        !          1065: {
        !          1066:        int s = splhigh();
        !          1067:
        !          1068:        SLIST_REMOVE(&rnd_rsel.si_note, kn, knote, kn_selnext);
        !          1069:        splx(s);
        !          1070: }
        !          1071:
        !          1072: int
        !          1073: filt_rndread(struct knote *kn, long hint)
        !          1074: {
        !          1075:        struct random_bucket *rs = (struct random_bucket *)kn->kn_hook;
        !          1076:
        !          1077:        kn->kn_data = (int)rs->entropy_count;
        !          1078:        return rs->entropy_count > 0;
        !          1079: }
        !          1080:
        !          1081: void
        !          1082: filt_rndwdetach(struct knote *kn)
        !          1083: {
        !          1084:        int s = splhigh();
        !          1085:
        !          1086:        SLIST_REMOVE(&rnd_wsel.si_note, kn, knote, kn_selnext);
        !          1087:        splx(s);
        !          1088: }
        !          1089:
        !          1090: int
        !          1091: filt_rndwrite(struct knote *kn, long hint)
        !          1092: {
        !          1093:        return (1);
        !          1094: }
        !          1095:
        !          1096: int
        !          1097: randomwrite(dev_t dev, struct uio *uio, int flags)
        !          1098: {
        !          1099:        int             ret = 0;
        !          1100:        u_int32_t       *buf;
        !          1101:
        !          1102:        if (minor(dev) == RND_RND || minor(dev) == RND_PRND)
        !          1103:                return ENXIO;
        !          1104:
        !          1105:        if (uio->uio_resid == 0)
        !          1106:                return 0;
        !          1107:
        !          1108:        MALLOC(buf, u_int32_t *, POOLBYTES, M_TEMP, M_WAITOK);
        !          1109:
        !          1110:        while (!ret && uio->uio_resid > 0) {
        !          1111:                u_short n = min(POOLBYTES, uio->uio_resid);
        !          1112:
        !          1113:                ret = uiomove((caddr_t)buf, n, uio);
        !          1114:                if (!ret) {
        !          1115:                        while (n % sizeof(u_int32_t))
        !          1116:                                ((u_int8_t *) buf)[n++] = 0;
        !          1117:                        add_entropy_words(buf, n / 4);
        !          1118:                }
        !          1119:        }
        !          1120:
        !          1121:        if (minor(dev) == RND_ARND && !ret)
        !          1122:                arc4random_initialized = 0;
        !          1123:
        !          1124:        FREE(buf, M_TEMP);
        !          1125:        return ret;
        !          1126: }
        !          1127:
        !          1128: int
        !          1129: randomioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
        !          1130: {
        !          1131:        int     s, ret = 0;
        !          1132:        u_int   cnt;
        !          1133:
        !          1134:        add_timer_randomness((u_long)p ^ (u_long)data ^ cmd);
        !          1135:
        !          1136:        switch (cmd) {
        !          1137:        case FIOASYNC:
        !          1138:                /* rnd has no async flag in softc so this is really a no-op. */
        !          1139:                break;
        !          1140:
        !          1141:        case FIONBIO:
        !          1142:                /* Handled in the upper FS layer. */
        !          1143:                break;
        !          1144:
        !          1145:        case RNDGETENTCNT:
        !          1146:                s = splhigh();
        !          1147:                *(u_int *)data = random_state.entropy_count;
        !          1148:                splx(s);
        !          1149:                break;
        !          1150:        case RNDADDTOENTCNT:
        !          1151:                if (suser(p, 0) != 0)
        !          1152:                        ret = EPERM;
        !          1153:                else {
        !          1154:                        cnt = *(u_int *)data;
        !          1155:                        s = splhigh();
        !          1156:                        random_state.entropy_count += cnt;
        !          1157:                        if (random_state.entropy_count > POOLBITS)
        !          1158:                                random_state.entropy_count = POOLBITS;
        !          1159:                        splx(s);
        !          1160:                }
        !          1161:                break;
        !          1162:        case RNDZAPENTCNT:
        !          1163:                if (suser(p, 0) != 0)
        !          1164:                        ret = EPERM;
        !          1165:                else {
        !          1166:                        s = splhigh();
        !          1167:                        random_state.entropy_count = 0;
        !          1168:                        splx(s);
        !          1169:                }
        !          1170:                break;
        !          1171:        case RNDSTIRARC4:
        !          1172:                if (suser(p, 0) != 0)
        !          1173:                        ret = EPERM;
        !          1174:                else if (random_state.entropy_count < 64)
        !          1175:                        ret = EAGAIN;
        !          1176:                else {
        !          1177:                        s = splhigh();
        !          1178:                        arc4random_initialized = 0;
        !          1179:                        splx(s);
        !          1180:                }
        !          1181:                break;
        !          1182:        case RNDCLRSTATS:
        !          1183:                if (suser(p, 0) != 0)
        !          1184:                        ret = EPERM;
        !          1185:                else {
        !          1186:                        s = splhigh();
        !          1187:                        bzero(&rndstats, sizeof(rndstats));
        !          1188:                        splx(s);
        !          1189:                }
        !          1190:                break;
        !          1191:        default:
        !          1192:                ret = ENOTTY;
        !          1193:        }
        !          1194:
        !          1195:        add_timer_randomness((u_long)p ^ (u_long)data ^ cmd);
        !          1196:        return ret;
        !          1197: }

CVSweb