1 /* $FreeBSD: src/lib/libc/gen/arc4random.c,v 1.4 2000/01/27 23:06:13 jasone Exp $ */
4 * Arc4 random number generator for OpenBSD.
5 * Copyright 1996 David Mazieres <dm@lcs.mit.edu>.
7 * Modification and redistribution in source and binary forms is
8 * permitted provided that due credit is given to the author and the
9 * OpenBSD project (for instance by leaving this copyright notice
14 * This code is derived from section 17.1 of Applied Cryptography,
15 * second edition, which describes a stream cipher allegedly
16 * compatible with RSA Labs "RC4" cipher (the actual description of
17 * which is a trade secret). The same algorithm is used as a stream
18 * cipher called "arcfour" in Tatu Ylonen's ssh package.
20 * Here the stream cipher has been modified always to include the time
21 * when initializing the state. That makes it impossible to
22 * regenerate the same random sequence twice, so this can't be used
23 * for encryption, but will generate good random numbers.
25 * RC4 is a registered trademark of RSA Laboratories.
31 #include <sys/types.h>
40 static int rs_initialized;
41 static struct arc4_stream rs;
45 struct arc4_stream *as;
49 for (n = 0; n < 256; n++)
56 arc4_addrandom(as, dat, datlen)
57 struct arc4_stream *as;
65 for (n = 0; n < 256; n++) {
68 as->j = (as->j + si + dat[n % datlen]);
69 as->s[as->i] = as->s[as->j];
76 struct arc4_stream *as;
82 u_int8_t rnd[128 - sizeof(struct timeval) - sizeof(pid_t)];
85 gettimeofday(&rdat.tv, NULL);
87 fd = _open("/dev/urandom", O_RDONLY, 0);
89 (void) _read(fd, rdat.rnd, sizeof(rdat.rnd));
92 /* fd < 0? Ah, what the heck. We'll just take whatever was on the
95 arc4_addrandom(as, (void *) &rdat, sizeof(rdat));
98 static inline u_int8_t
100 struct arc4_stream *as;
106 as->j = (as->j + si);
110 return (as->s[(si + sj) & 0xff]);
113 static inline u_int32_t
115 struct arc4_stream *as;
118 val = arc4_getbyte(as) << 24;
119 val |= arc4_getbyte(as) << 16;
120 val |= arc4_getbyte(as) << 8;
121 val |= arc4_getbyte(as);
128 if (!rs_initialized) {
136 arc4random_addrandom(dat, datlen)
142 arc4_addrandom(&rs, dat, datlen);
150 return arc4_getword(&rs);
154 /*-------- Test code for i386 --------*/
156 #include <machine/pctr.h>
158 main(int argc, char **argv)
160 const int iter = 1000000;
165 for (i = 0; i < iter; i++)
170 printf("%qd cycles\n", v);