2 * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
6 #pragma ident "%Z%%M% %I% %E% SMI"
8 /* $OpenBSD: arc4random.c,v 1.6 2001/06/05 05:05:38 pvalchev Exp $ */
11 * Arc4 random number generator for OpenBSD.
12 * Copyright 1996 David Mazieres <dm@lcs.mit.edu>.
14 * Modification and redistribution in source and binary forms is
15 * permitted provided that due credit is given to the author and the
16 * OpenBSD project by leaving this copyright notice intact.
20 * This code is derived from section 17.1 of Applied Cryptography,
21 * second edition, which describes a stream cipher allegedly
22 * compatible with RSA Labs "RC4" cipher (the actual description of
23 * which is a trade secret). The same algorithm is used as a stream
24 * cipher called "arcfour" in Tatu Ylonen's ssh package.
26 * Here the stream cipher has been modified always to include the time
27 * when initializing the state. That makes it impossible to
28 * regenerate the same random sequence twice, so this can't be used
29 * for encryption, but will generate good random numbers.
31 * RC4 is a registered trademark of RSA Laboratories.
37 #include <sys/types.h>
38 #include <sys/param.h>
42 #define inline __inline
45 #endif /* !__GNUC__ */
54 static struct arc4_stream rs
;
58 struct arc4_stream
*as
;
62 for (n
= 0; n
< 256; n
++)
69 arc4_addrandom(as
, dat
, datlen
)
70 struct arc4_stream
*as
;
78 for (n
= 0; n
< 256; n
++) {
81 as
->j
= (as
->j
+ si
+ dat
[n
% datlen
]);
82 as
->s
[as
->i
] = as
->s
[as
->j
];
90 struct arc4_stream
*as
;
95 uint rnd
[(128 - sizeof(struct timeval
)) / sizeof(uint
)];
98 (void) gettimeofday(&rdat
.tv
, NULL
);
99 fd
= open("/dev/urandom", O_RDONLY
);
101 (void) read(fd
, rdat
.rnd
, sizeof(rdat
.rnd
));
104 /* fd < 0 ? Ah, what the heck. We'll just take
105 * whatever was on the stack... */
107 arc4_addrandom(as
, (void *) &rdat
, sizeof(rdat
));
110 static inline uint8_t
112 struct arc4_stream
*as
;
118 as
->j
= (as
->j
+ si
);
122 return (as
->s
[(si
+ sj
) & 0xff]);
125 static inline uint32_t
127 struct arc4_stream
*as
;
130 val
= arc4_getbyte(as
) << 24;
131 val
|= arc4_getbyte(as
) << 16;
132 val
|= arc4_getbyte(as
) << 8;
133 val
|= arc4_getbyte(as
);
140 if (!rs_initialized
) {
148 arc4random_addrandom(dat
, datlen
)
154 arc4_addrandom(&rs
, dat
, datlen
);
162 return arc4_getword(&rs
);
166 /*-------- Test code for i386 --------*/
168 #include <machine/pctr.h>
170 main(int argc
, char **argv
)
172 const int iter
= 1000000;
177 for (i
= 0; i
< iter
; i
++)
182 printf("%qd cycles\n", v
);