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