1c43e99fdSEd Maste /* Portable arc4random.c based on arc4random.c from OpenBSD.
2c43e99fdSEd Maste * Portable version by Chris Davis, adapted for Libevent by Nick Mathewson
3c43e99fdSEd Maste * Copyright (c) 2010 Chris Davis, Niels Provos, and Nick Mathewson
4c43e99fdSEd Maste * Copyright (c) 2010-2012 Niels Provos and Nick Mathewson
5c43e99fdSEd Maste *
6c43e99fdSEd Maste * Note that in Libevent, this file isn't compiled directly. Instead,
7c43e99fdSEd Maste * it's included from evutil_rand.c
8c43e99fdSEd Maste */
9c43e99fdSEd Maste
10c43e99fdSEd Maste /*
11c43e99fdSEd Maste * Copyright (c) 1996, David Mazieres <dm@uun.org>
12c43e99fdSEd Maste * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
13c43e99fdSEd Maste *
14c43e99fdSEd Maste * Permission to use, copy, modify, and distribute this software for any
15c43e99fdSEd Maste * purpose with or without fee is hereby granted, provided that the above
16c43e99fdSEd Maste * copyright notice and this permission notice appear in all copies.
17c43e99fdSEd Maste *
18c43e99fdSEd Maste * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
19c43e99fdSEd Maste * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
20c43e99fdSEd Maste * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
21c43e99fdSEd Maste * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
22c43e99fdSEd Maste * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
23c43e99fdSEd Maste * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
24c43e99fdSEd Maste * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25c43e99fdSEd Maste */
26c43e99fdSEd Maste
27c43e99fdSEd Maste /*
28c43e99fdSEd Maste * Arc4 random number generator for OpenBSD.
29c43e99fdSEd Maste *
30c43e99fdSEd Maste * This code is derived from section 17.1 of Applied Cryptography,
31c43e99fdSEd Maste * second edition, which describes a stream cipher allegedly
32c43e99fdSEd Maste * compatible with RSA Labs "RC4" cipher (the actual description of
33c43e99fdSEd Maste * which is a trade secret). The same algorithm is used as a stream
34c43e99fdSEd Maste * cipher called "arcfour" in Tatu Ylonen's ssh package.
35c43e99fdSEd Maste *
36c43e99fdSEd Maste * Here the stream cipher has been modified always to include the time
37c43e99fdSEd Maste * when initializing the state. That makes it impossible to
38c43e99fdSEd Maste * regenerate the same random sequence twice, so this can't be used
39c43e99fdSEd Maste * for encryption, but will generate good random numbers.
40c43e99fdSEd Maste *
41c43e99fdSEd Maste * RC4 is a registered trademark of RSA Laboratories.
42c43e99fdSEd Maste */
43c43e99fdSEd Maste
44c43e99fdSEd Maste #ifndef ARC4RANDOM_EXPORT
45c43e99fdSEd Maste #define ARC4RANDOM_EXPORT
46c43e99fdSEd Maste #endif
47c43e99fdSEd Maste
48c43e99fdSEd Maste #ifndef ARC4RANDOM_UINT32
49c43e99fdSEd Maste #define ARC4RANDOM_UINT32 uint32_t
50c43e99fdSEd Maste #endif
51c43e99fdSEd Maste
52c43e99fdSEd Maste #ifndef ARC4RANDOM_NO_INCLUDES
53c43e99fdSEd Maste #include "evconfig-private.h"
54c43e99fdSEd Maste #ifdef _WIN32
55c43e99fdSEd Maste #include <wincrypt.h>
56c43e99fdSEd Maste #include <process.h>
57*b50261e2SCy Schubert #include <winerror.h>
58c43e99fdSEd Maste #else
59c43e99fdSEd Maste #include <fcntl.h>
60c43e99fdSEd Maste #include <unistd.h>
61c43e99fdSEd Maste #include <sys/param.h>
62c43e99fdSEd Maste #include <sys/time.h>
63c43e99fdSEd Maste #ifdef EVENT__HAVE_SYS_SYSCTL_H
64c43e99fdSEd Maste #include <sys/sysctl.h>
65c43e99fdSEd Maste #endif
66*b50261e2SCy Schubert #ifdef EVENT__HAVE_SYS_RANDOM_H
67*b50261e2SCy Schubert #include <sys/random.h>
68*b50261e2SCy Schubert #endif
69c43e99fdSEd Maste #endif
70c43e99fdSEd Maste #include <limits.h>
71c43e99fdSEd Maste #include <stdlib.h>
72c43e99fdSEd Maste #include <string.h>
73c43e99fdSEd Maste #endif
74c43e99fdSEd Maste
75c43e99fdSEd Maste /* Add platform entropy 32 bytes (256 bits) at a time. */
76c43e99fdSEd Maste #define ADD_ENTROPY 32
77c43e99fdSEd Maste
78c43e99fdSEd Maste /* Re-seed from the platform RNG after generating this many bytes. */
79c43e99fdSEd Maste #define BYTES_BEFORE_RESEED 1600000
80c43e99fdSEd Maste
81c43e99fdSEd Maste struct arc4_stream {
82c43e99fdSEd Maste unsigned char i;
83c43e99fdSEd Maste unsigned char j;
84c43e99fdSEd Maste unsigned char s[256];
85c43e99fdSEd Maste };
86c43e99fdSEd Maste
87c43e99fdSEd Maste #ifdef _WIN32
88c43e99fdSEd Maste #define getpid _getpid
89c43e99fdSEd Maste #define pid_t int
90c43e99fdSEd Maste #endif
91c43e99fdSEd Maste
92c43e99fdSEd Maste static int rs_initialized;
93c43e99fdSEd Maste static struct arc4_stream rs;
94c43e99fdSEd Maste static pid_t arc4_stir_pid;
95c43e99fdSEd Maste static int arc4_count;
96c43e99fdSEd Maste
97c43e99fdSEd Maste static inline unsigned char arc4_getbyte(void);
98c43e99fdSEd Maste
99c43e99fdSEd Maste static inline void
arc4_init(void)100c43e99fdSEd Maste arc4_init(void)
101c43e99fdSEd Maste {
102c43e99fdSEd Maste int n;
103c43e99fdSEd Maste
104c43e99fdSEd Maste for (n = 0; n < 256; n++)
105c43e99fdSEd Maste rs.s[n] = n;
106c43e99fdSEd Maste rs.i = 0;
107c43e99fdSEd Maste rs.j = 0;
108c43e99fdSEd Maste }
109c43e99fdSEd Maste
110c43e99fdSEd Maste static inline void
arc4_addrandom(const unsigned char * dat,int datlen)111c43e99fdSEd Maste arc4_addrandom(const unsigned char *dat, int datlen)
112c43e99fdSEd Maste {
113c43e99fdSEd Maste int n;
114c43e99fdSEd Maste unsigned char si;
115c43e99fdSEd Maste
116c43e99fdSEd Maste rs.i--;
117c43e99fdSEd Maste for (n = 0; n < 256; n++) {
118c43e99fdSEd Maste rs.i = (rs.i + 1);
119c43e99fdSEd Maste si = rs.s[rs.i];
120c43e99fdSEd Maste rs.j = (rs.j + si + dat[n % datlen]);
121c43e99fdSEd Maste rs.s[rs.i] = rs.s[rs.j];
122c43e99fdSEd Maste rs.s[rs.j] = si;
123c43e99fdSEd Maste }
124c43e99fdSEd Maste rs.j = rs.i;
125c43e99fdSEd Maste }
126c43e99fdSEd Maste
127c43e99fdSEd Maste #ifndef _WIN32
128c43e99fdSEd Maste static ssize_t
read_all(int fd,unsigned char * buf,size_t count)129c43e99fdSEd Maste read_all(int fd, unsigned char *buf, size_t count)
130c43e99fdSEd Maste {
131c43e99fdSEd Maste size_t numread = 0;
132c43e99fdSEd Maste ssize_t result;
133c43e99fdSEd Maste
134c43e99fdSEd Maste while (numread < count) {
135c43e99fdSEd Maste result = read(fd, buf+numread, count-numread);
136c43e99fdSEd Maste if (result<0)
137c43e99fdSEd Maste return -1;
138c43e99fdSEd Maste else if (result == 0)
139c43e99fdSEd Maste break;
140c43e99fdSEd Maste numread += result;
141c43e99fdSEd Maste }
142c43e99fdSEd Maste
143c43e99fdSEd Maste return (ssize_t)numread;
144c43e99fdSEd Maste }
145c43e99fdSEd Maste #endif
146c43e99fdSEd Maste
147c43e99fdSEd Maste #ifdef _WIN32
148c43e99fdSEd Maste #define TRY_SEED_WIN32
149c43e99fdSEd Maste static int
arc4_seed_win32(void)150c43e99fdSEd Maste arc4_seed_win32(void)
151c43e99fdSEd Maste {
152c43e99fdSEd Maste /* This is adapted from Tor's crypto_seed_rng() */
153c43e99fdSEd Maste static int provider_set = 0;
154c43e99fdSEd Maste static HCRYPTPROV provider;
155c43e99fdSEd Maste unsigned char buf[ADD_ENTROPY];
156c43e99fdSEd Maste
157c43e99fdSEd Maste if (!provider_set) {
158c43e99fdSEd Maste if (!CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL,
159c43e99fdSEd Maste CRYPT_VERIFYCONTEXT)) {
160c43e99fdSEd Maste if (GetLastError() != (DWORD)NTE_BAD_KEYSET)
161c43e99fdSEd Maste return -1;
162c43e99fdSEd Maste }
163c43e99fdSEd Maste provider_set = 1;
164c43e99fdSEd Maste }
165c43e99fdSEd Maste if (!CryptGenRandom(provider, sizeof(buf), buf))
166c43e99fdSEd Maste return -1;
167c43e99fdSEd Maste arc4_addrandom(buf, sizeof(buf));
168c43e99fdSEd Maste evutil_memclear_(buf, sizeof(buf));
169c43e99fdSEd Maste return 0;
170c43e99fdSEd Maste }
171c43e99fdSEd Maste #endif
172c43e99fdSEd Maste
173*b50261e2SCy Schubert #if defined(EVENT__HAVE_GETRANDOM)
174*b50261e2SCy Schubert #define TRY_SEED_GETRANDOM
175c43e99fdSEd Maste static int
arc4_seed_getrandom(void)176*b50261e2SCy Schubert arc4_seed_getrandom(void)
177c43e99fdSEd Maste {
178c43e99fdSEd Maste unsigned char buf[ADD_ENTROPY];
179c43e99fdSEd Maste size_t len, n;
180c43e99fdSEd Maste unsigned i;
181c43e99fdSEd Maste int any_set;
182c43e99fdSEd Maste
183c43e99fdSEd Maste memset(buf, 0, sizeof(buf));
184c43e99fdSEd Maste
185c43e99fdSEd Maste for (len = 0; len < sizeof(buf); len += n) {
186c43e99fdSEd Maste n = sizeof(buf) - len;
187c43e99fdSEd Maste
188*b50261e2SCy Schubert if (0 == getrandom(&buf[len], n, 0))
189c43e99fdSEd Maste return -1;
190c43e99fdSEd Maste }
191c43e99fdSEd Maste /* make sure that the buffer actually got set. */
192c43e99fdSEd Maste for (i=0,any_set=0; i<sizeof(buf); ++i) {
193c43e99fdSEd Maste any_set |= buf[i];
194c43e99fdSEd Maste }
195c43e99fdSEd Maste if (!any_set)
196c43e99fdSEd Maste return -1;
197c43e99fdSEd Maste
198c43e99fdSEd Maste arc4_addrandom(buf, sizeof(buf));
199c43e99fdSEd Maste evutil_memclear_(buf, sizeof(buf));
200c43e99fdSEd Maste return 0;
201c43e99fdSEd Maste }
202*b50261e2SCy Schubert #endif /* EVENT__HAVE_GETRANDOM */
203c43e99fdSEd Maste
204*b50261e2SCy Schubert #if defined(EVENT__HAVE_SYS_SYSCTL_H) && defined(EVENT__HAVE_SYSCTL)
205c43e99fdSEd Maste #if EVENT__HAVE_DECL_CTL_KERN && EVENT__HAVE_DECL_KERN_ARND
206c43e99fdSEd Maste #define TRY_SEED_SYSCTL_BSD
207c43e99fdSEd Maste static int
arc4_seed_sysctl_bsd(void)208c43e99fdSEd Maste arc4_seed_sysctl_bsd(void)
209c43e99fdSEd Maste {
210c43e99fdSEd Maste /* Based on code from William Ahern and from OpenBSD, this function
211c43e99fdSEd Maste * tries to use the KERN_ARND syscall to get entropy from the kernel.
212c43e99fdSEd Maste * This can work even if /dev/urandom is inaccessible for some reason
213c43e99fdSEd Maste * (e.g., we're running in a chroot). */
214c43e99fdSEd Maste int mib[] = { CTL_KERN, KERN_ARND };
215c43e99fdSEd Maste unsigned char buf[ADD_ENTROPY];
216c43e99fdSEd Maste size_t len, n;
217c43e99fdSEd Maste int i, any_set;
218c43e99fdSEd Maste
219c43e99fdSEd Maste memset(buf, 0, sizeof(buf));
220c43e99fdSEd Maste
221c43e99fdSEd Maste len = sizeof(buf);
222c43e99fdSEd Maste if (sysctl(mib, 2, buf, &len, NULL, 0) == -1) {
223c43e99fdSEd Maste for (len = 0; len < sizeof(buf); len += sizeof(unsigned)) {
224c43e99fdSEd Maste n = sizeof(unsigned);
225c43e99fdSEd Maste if (n + len > sizeof(buf))
226c43e99fdSEd Maste n = len - sizeof(buf);
227c43e99fdSEd Maste if (sysctl(mib, 2, &buf[len], &n, NULL, 0) == -1)
228c43e99fdSEd Maste return -1;
229c43e99fdSEd Maste }
230c43e99fdSEd Maste }
231c43e99fdSEd Maste /* make sure that the buffer actually got set. */
232c43e99fdSEd Maste for (i=any_set=0; i<sizeof(buf); ++i) {
233c43e99fdSEd Maste any_set |= buf[i];
234c43e99fdSEd Maste }
235c43e99fdSEd Maste if (!any_set)
236c43e99fdSEd Maste return -1;
237c43e99fdSEd Maste
238c43e99fdSEd Maste arc4_addrandom(buf, sizeof(buf));
239c43e99fdSEd Maste evutil_memclear_(buf, sizeof(buf));
240c43e99fdSEd Maste return 0;
241c43e99fdSEd Maste }
242c43e99fdSEd Maste #endif
243c43e99fdSEd Maste #endif /* defined(EVENT__HAVE_SYS_SYSCTL_H) */
244c43e99fdSEd Maste
245c43e99fdSEd Maste #ifdef __linux__
246c43e99fdSEd Maste #define TRY_SEED_PROC_SYS_KERNEL_RANDOM_UUID
247c43e99fdSEd Maste static int
arc4_seed_proc_sys_kernel_random_uuid(void)248c43e99fdSEd Maste arc4_seed_proc_sys_kernel_random_uuid(void)
249c43e99fdSEd Maste {
250c43e99fdSEd Maste /* Occasionally, somebody will make /proc/sys accessible in a chroot,
251c43e99fdSEd Maste * but not /dev/urandom. Let's try /proc/sys/kernel/random/uuid.
252c43e99fdSEd Maste * Its format is stupid, so we need to decode it from hex.
253c43e99fdSEd Maste */
254c43e99fdSEd Maste int fd;
255c43e99fdSEd Maste char buf[128];
256c43e99fdSEd Maste unsigned char entropy[64];
257c43e99fdSEd Maste int bytes, n, i, nybbles;
258c43e99fdSEd Maste for (bytes = 0; bytes<ADD_ENTROPY; ) {
259c43e99fdSEd Maste fd = evutil_open_closeonexec_("/proc/sys/kernel/random/uuid", O_RDONLY, 0);
260c43e99fdSEd Maste if (fd < 0)
261c43e99fdSEd Maste return -1;
262c43e99fdSEd Maste n = read(fd, buf, sizeof(buf));
263c43e99fdSEd Maste close(fd);
264c43e99fdSEd Maste if (n<=0)
265c43e99fdSEd Maste return -1;
266c43e99fdSEd Maste memset(entropy, 0, sizeof(entropy));
267c43e99fdSEd Maste for (i=nybbles=0; i<n; ++i) {
268c43e99fdSEd Maste if (EVUTIL_ISXDIGIT_(buf[i])) {
269c43e99fdSEd Maste int nyb = evutil_hex_char_to_int_(buf[i]);
270c43e99fdSEd Maste if (nybbles & 1) {
271c43e99fdSEd Maste entropy[nybbles/2] |= nyb;
272c43e99fdSEd Maste } else {
273c43e99fdSEd Maste entropy[nybbles/2] |= nyb<<4;
274c43e99fdSEd Maste }
275c43e99fdSEd Maste ++nybbles;
276c43e99fdSEd Maste }
277c43e99fdSEd Maste }
278c43e99fdSEd Maste if (nybbles < 2)
279c43e99fdSEd Maste return -1;
280c43e99fdSEd Maste arc4_addrandom(entropy, nybbles/2);
281c43e99fdSEd Maste bytes += nybbles/2;
282c43e99fdSEd Maste }
283c43e99fdSEd Maste evutil_memclear_(entropy, sizeof(entropy));
284c43e99fdSEd Maste evutil_memclear_(buf, sizeof(buf));
285c43e99fdSEd Maste return 0;
286c43e99fdSEd Maste }
287c43e99fdSEd Maste #endif
288c43e99fdSEd Maste
289c43e99fdSEd Maste #ifndef _WIN32
290c43e99fdSEd Maste #define TRY_SEED_URANDOM
291c43e99fdSEd Maste static char *arc4random_urandom_filename = NULL;
292c43e99fdSEd Maste
arc4_seed_urandom_helper_(const char * fname)293c43e99fdSEd Maste static int arc4_seed_urandom_helper_(const char *fname)
294c43e99fdSEd Maste {
295c43e99fdSEd Maste unsigned char buf[ADD_ENTROPY];
296c43e99fdSEd Maste int fd;
297c43e99fdSEd Maste size_t n;
298c43e99fdSEd Maste
299c43e99fdSEd Maste fd = evutil_open_closeonexec_(fname, O_RDONLY, 0);
300c43e99fdSEd Maste if (fd<0)
301c43e99fdSEd Maste return -1;
302c43e99fdSEd Maste n = read_all(fd, buf, sizeof(buf));
303c43e99fdSEd Maste close(fd);
304c43e99fdSEd Maste if (n != sizeof(buf))
305c43e99fdSEd Maste return -1;
306c43e99fdSEd Maste arc4_addrandom(buf, sizeof(buf));
307c43e99fdSEd Maste evutil_memclear_(buf, sizeof(buf));
308c43e99fdSEd Maste return 0;
309c43e99fdSEd Maste }
310c43e99fdSEd Maste
311c43e99fdSEd Maste static int
arc4_seed_urandom(void)312c43e99fdSEd Maste arc4_seed_urandom(void)
313c43e99fdSEd Maste {
314c43e99fdSEd Maste /* This is adapted from Tor's crypto_seed_rng() */
315c43e99fdSEd Maste static const char *filenames[] = {
316c43e99fdSEd Maste "/dev/srandom", "/dev/urandom", "/dev/random", NULL
317c43e99fdSEd Maste };
318c43e99fdSEd Maste int i;
319c43e99fdSEd Maste if (arc4random_urandom_filename)
320c43e99fdSEd Maste return arc4_seed_urandom_helper_(arc4random_urandom_filename);
321c43e99fdSEd Maste
322c43e99fdSEd Maste for (i = 0; filenames[i]; ++i) {
323c43e99fdSEd Maste if (arc4_seed_urandom_helper_(filenames[i]) == 0) {
324c43e99fdSEd Maste return 0;
325c43e99fdSEd Maste }
326c43e99fdSEd Maste }
327c43e99fdSEd Maste
328c43e99fdSEd Maste return -1;
329c43e99fdSEd Maste }
330c43e99fdSEd Maste #endif
331c43e99fdSEd Maste
332c43e99fdSEd Maste static int
arc4_seed(void)333c43e99fdSEd Maste arc4_seed(void)
334c43e99fdSEd Maste {
335c43e99fdSEd Maste int ok = 0;
336c43e99fdSEd Maste /* We try every method that might work, and don't give up even if one
337c43e99fdSEd Maste * does seem to work. There's no real harm in over-seeding, and if
338c43e99fdSEd Maste * one of these sources turns out to be broken, that would be bad. */
339c43e99fdSEd Maste #ifdef TRY_SEED_WIN32
340c43e99fdSEd Maste if (0 == arc4_seed_win32())
341c43e99fdSEd Maste ok = 1;
342c43e99fdSEd Maste #endif
343*b50261e2SCy Schubert #ifdef TRY_SEED_GETRANDOM
344*b50261e2SCy Schubert if (0 == arc4_seed_getrandom())
345*b50261e2SCy Schubert ok = 1;
346*b50261e2SCy Schubert #endif
347c43e99fdSEd Maste #ifdef TRY_SEED_URANDOM
348c43e99fdSEd Maste if (0 == arc4_seed_urandom())
349c43e99fdSEd Maste ok = 1;
350c43e99fdSEd Maste #endif
351c43e99fdSEd Maste #ifdef TRY_SEED_PROC_SYS_KERNEL_RANDOM_UUID
352c43e99fdSEd Maste if (arc4random_urandom_filename == NULL &&
353c43e99fdSEd Maste 0 == arc4_seed_proc_sys_kernel_random_uuid())
354c43e99fdSEd Maste ok = 1;
355c43e99fdSEd Maste #endif
356c43e99fdSEd Maste #ifdef TRY_SEED_SYSCTL_BSD
357c43e99fdSEd Maste if (0 == arc4_seed_sysctl_bsd())
358c43e99fdSEd Maste ok = 1;
359c43e99fdSEd Maste #endif
360c43e99fdSEd Maste return ok ? 0 : -1;
361c43e99fdSEd Maste }
362c43e99fdSEd Maste
363c43e99fdSEd Maste static int
arc4_stir(void)364c43e99fdSEd Maste arc4_stir(void)
365c43e99fdSEd Maste {
366c43e99fdSEd Maste int i;
367c43e99fdSEd Maste
368c43e99fdSEd Maste if (!rs_initialized) {
369c43e99fdSEd Maste arc4_init();
370c43e99fdSEd Maste rs_initialized = 1;
371c43e99fdSEd Maste }
372c43e99fdSEd Maste
373*b50261e2SCy Schubert if (0 != arc4_seed())
374c43e99fdSEd Maste return -1;
375c43e99fdSEd Maste
376c43e99fdSEd Maste /*
377c43e99fdSEd Maste * Discard early keystream, as per recommendations in
378c43e99fdSEd Maste * "Weaknesses in the Key Scheduling Algorithm of RC4" by
379c43e99fdSEd Maste * Scott Fluhrer, Itsik Mantin, and Adi Shamir.
380c43e99fdSEd Maste * http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps
381c43e99fdSEd Maste *
382c43e99fdSEd Maste * Ilya Mironov's "(Not So) Random Shuffles of RC4" suggests that
383c43e99fdSEd Maste * we drop at least 2*256 bytes, with 12*256 as a conservative
384c43e99fdSEd Maste * value.
385c43e99fdSEd Maste *
386c43e99fdSEd Maste * RFC4345 says to drop 6*256.
387c43e99fdSEd Maste *
388c43e99fdSEd Maste * At least some versions of this code drop 4*256, in a mistaken
389c43e99fdSEd Maste * belief that "words" in the Fluhrer/Mantin/Shamir paper refers
390c43e99fdSEd Maste * to processor words.
391c43e99fdSEd Maste *
392c43e99fdSEd Maste * We add another sect to the cargo cult, and choose 12*256.
393c43e99fdSEd Maste */
394c43e99fdSEd Maste for (i = 0; i < 12*256; i++)
395c43e99fdSEd Maste (void)arc4_getbyte();
396c43e99fdSEd Maste
397c43e99fdSEd Maste arc4_count = BYTES_BEFORE_RESEED;
398c43e99fdSEd Maste
399c43e99fdSEd Maste return 0;
400c43e99fdSEd Maste }
401c43e99fdSEd Maste
402c43e99fdSEd Maste
403c43e99fdSEd Maste static void
arc4_stir_if_needed(void)404c43e99fdSEd Maste arc4_stir_if_needed(void)
405c43e99fdSEd Maste {
406c43e99fdSEd Maste pid_t pid = getpid();
407c43e99fdSEd Maste
408c43e99fdSEd Maste if (arc4_count <= 0 || !rs_initialized || arc4_stir_pid != pid)
409c43e99fdSEd Maste {
410c43e99fdSEd Maste arc4_stir_pid = pid;
411c43e99fdSEd Maste arc4_stir();
412c43e99fdSEd Maste }
413c43e99fdSEd Maste }
414c43e99fdSEd Maste
415c43e99fdSEd Maste static inline unsigned char
arc4_getbyte(void)416c43e99fdSEd Maste arc4_getbyte(void)
417c43e99fdSEd Maste {
418c43e99fdSEd Maste unsigned char si, sj;
419c43e99fdSEd Maste
420c43e99fdSEd Maste rs.i = (rs.i + 1);
421c43e99fdSEd Maste si = rs.s[rs.i];
422c43e99fdSEd Maste rs.j = (rs.j + si);
423c43e99fdSEd Maste sj = rs.s[rs.j];
424c43e99fdSEd Maste rs.s[rs.i] = sj;
425c43e99fdSEd Maste rs.s[rs.j] = si;
426c43e99fdSEd Maste return (rs.s[(si + sj) & 0xff]);
427c43e99fdSEd Maste }
428c43e99fdSEd Maste
429c43e99fdSEd Maste static inline unsigned int
arc4_getword(void)430c43e99fdSEd Maste arc4_getword(void)
431c43e99fdSEd Maste {
432c43e99fdSEd Maste unsigned int val;
433c43e99fdSEd Maste
434c43e99fdSEd Maste val = arc4_getbyte() << 24;
435c43e99fdSEd Maste val |= arc4_getbyte() << 16;
436c43e99fdSEd Maste val |= arc4_getbyte() << 8;
437c43e99fdSEd Maste val |= arc4_getbyte();
438c43e99fdSEd Maste
439c43e99fdSEd Maste return val;
440c43e99fdSEd Maste }
441c43e99fdSEd Maste
442c43e99fdSEd Maste #ifndef ARC4RANDOM_NOSTIR
443c43e99fdSEd Maste ARC4RANDOM_EXPORT int
arc4random_stir(void)444c43e99fdSEd Maste arc4random_stir(void)
445c43e99fdSEd Maste {
446c43e99fdSEd Maste int val;
447c43e99fdSEd Maste ARC4_LOCK_();
448c43e99fdSEd Maste val = arc4_stir();
449c43e99fdSEd Maste ARC4_UNLOCK_();
450c43e99fdSEd Maste return val;
451c43e99fdSEd Maste }
452c43e99fdSEd Maste #endif
453c43e99fdSEd Maste
454c43e99fdSEd Maste #ifndef ARC4RANDOM_NOADDRANDOM
455c43e99fdSEd Maste ARC4RANDOM_EXPORT void
arc4random_addrandom(const unsigned char * dat,int datlen)456c43e99fdSEd Maste arc4random_addrandom(const unsigned char *dat, int datlen)
457c43e99fdSEd Maste {
458c43e99fdSEd Maste int j;
459c43e99fdSEd Maste ARC4_LOCK_();
460c43e99fdSEd Maste if (!rs_initialized)
461c43e99fdSEd Maste arc4_stir();
462c43e99fdSEd Maste for (j = 0; j < datlen; j += 256) {
463c43e99fdSEd Maste /* arc4_addrandom() ignores all but the first 256 bytes of
464c43e99fdSEd Maste * its input. We want to make sure to look at ALL the
465c43e99fdSEd Maste * data in 'dat', just in case the user is doing something
466c43e99fdSEd Maste * crazy like passing us all the files in /var/log. */
467c43e99fdSEd Maste arc4_addrandom(dat + j, datlen - j);
468c43e99fdSEd Maste }
469c43e99fdSEd Maste ARC4_UNLOCK_();
470c43e99fdSEd Maste }
471c43e99fdSEd Maste #endif
472c43e99fdSEd Maste
473c43e99fdSEd Maste #ifndef ARC4RANDOM_NORANDOM
474c43e99fdSEd Maste ARC4RANDOM_EXPORT ARC4RANDOM_UINT32
arc4random(void)475c43e99fdSEd Maste arc4random(void)
476c43e99fdSEd Maste {
477c43e99fdSEd Maste ARC4RANDOM_UINT32 val;
478c43e99fdSEd Maste ARC4_LOCK_();
479c43e99fdSEd Maste arc4_count -= 4;
480c43e99fdSEd Maste arc4_stir_if_needed();
481c43e99fdSEd Maste val = arc4_getword();
482c43e99fdSEd Maste ARC4_UNLOCK_();
483c43e99fdSEd Maste return val;
484c43e99fdSEd Maste }
485c43e99fdSEd Maste #endif
486c43e99fdSEd Maste
487c43e99fdSEd Maste ARC4RANDOM_EXPORT void
arc4random_buf(void * buf_,size_t n)488c43e99fdSEd Maste arc4random_buf(void *buf_, size_t n)
489c43e99fdSEd Maste {
490c43e99fdSEd Maste unsigned char *buf = buf_;
491c43e99fdSEd Maste ARC4_LOCK_();
492c43e99fdSEd Maste arc4_stir_if_needed();
493c43e99fdSEd Maste while (n--) {
494c43e99fdSEd Maste if (--arc4_count <= 0)
495c43e99fdSEd Maste arc4_stir();
496c43e99fdSEd Maste buf[n] = arc4_getbyte();
497c43e99fdSEd Maste }
498c43e99fdSEd Maste ARC4_UNLOCK_();
499c43e99fdSEd Maste }
500c43e99fdSEd Maste
501c43e99fdSEd Maste #ifndef ARC4RANDOM_NOUNIFORM
502c43e99fdSEd Maste /*
503c43e99fdSEd Maste * Calculate a uniformly distributed random number less than upper_bound
504c43e99fdSEd Maste * avoiding "modulo bias".
505c43e99fdSEd Maste *
506c43e99fdSEd Maste * Uniformity is achieved by generating new random numbers until the one
507c43e99fdSEd Maste * returned is outside the range [0, 2**32 % upper_bound). This
508c43e99fdSEd Maste * guarantees the selected random number will be inside
509c43e99fdSEd Maste * [2**32 % upper_bound, 2**32) which maps back to [0, upper_bound)
510c43e99fdSEd Maste * after reduction modulo upper_bound.
511c43e99fdSEd Maste */
512c43e99fdSEd Maste ARC4RANDOM_EXPORT unsigned int
arc4random_uniform(unsigned int upper_bound)513c43e99fdSEd Maste arc4random_uniform(unsigned int upper_bound)
514c43e99fdSEd Maste {
515c43e99fdSEd Maste ARC4RANDOM_UINT32 r, min;
516c43e99fdSEd Maste
517c43e99fdSEd Maste if (upper_bound < 2)
518c43e99fdSEd Maste return 0;
519c43e99fdSEd Maste
520c43e99fdSEd Maste #if (UINT_MAX > 0xffffffffUL)
521c43e99fdSEd Maste min = 0x100000000UL % upper_bound;
522c43e99fdSEd Maste #else
523c43e99fdSEd Maste /* Calculate (2**32 % upper_bound) avoiding 64-bit math */
524c43e99fdSEd Maste if (upper_bound > 0x80000000)
525c43e99fdSEd Maste min = 1 + ~upper_bound; /* 2**32 - upper_bound */
526c43e99fdSEd Maste else {
527c43e99fdSEd Maste /* (2**32 - (x * 2)) % x == 2**32 % x when x <= 2**31 */
528c43e99fdSEd Maste min = ((0xffffffff - (upper_bound * 2)) + 1) % upper_bound;
529c43e99fdSEd Maste }
530c43e99fdSEd Maste #endif
531c43e99fdSEd Maste
532c43e99fdSEd Maste /*
533c43e99fdSEd Maste * This could theoretically loop forever but each retry has
534c43e99fdSEd Maste * p > 0.5 (worst case, usually far better) of selecting a
535c43e99fdSEd Maste * number inside the range we need, so it should rarely need
536c43e99fdSEd Maste * to re-roll.
537c43e99fdSEd Maste */
538c43e99fdSEd Maste for (;;) {
539c43e99fdSEd Maste r = arc4random();
540c43e99fdSEd Maste if (r >= min)
541c43e99fdSEd Maste break;
542c43e99fdSEd Maste }
543c43e99fdSEd Maste
544c43e99fdSEd Maste return r % upper_bound;
545c43e99fdSEd Maste }
546c43e99fdSEd Maste #endif
547