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