From 720711960b130d36dfdd3d50eb25ef482bdd000e Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Wed, 9 Oct 2013 10:44:47 +1100 Subject: - (djm) [openbsd-compat/Makefile.in openbsd-compat/arc4random.c] [openbsd-compat/bsd-arc4random.c] Replace old RC4-based arc4random implementation with recent OpenBSD's ChaCha-based PRNG. ok dtucker@, tested tim@ --- openbsd-compat/arc4random.c | 59 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 46 insertions(+), 13 deletions(-) (limited to 'openbsd-compat/arc4random.c') diff --git a/openbsd-compat/arc4random.c b/openbsd-compat/arc4random.c index 356e23181..eac073cc0 100644 --- a/openbsd-compat/arc4random.c +++ b/openbsd-compat/arc4random.c @@ -1,3 +1,5 @@ +/* OPENBSD ORIGINAL: lib/libc/crypto/arc4random.c */ + /* $OpenBSD: arc4random.c,v 1.25 2013/10/01 18:34:57 markus Exp $ */ /* @@ -22,16 +24,19 @@ * ChaCha based random number generator for OpenBSD. */ -#include -#include +#include "includes.h" + #include #include #include #include -#include -#include -#include -#include "thread_private.h" + +#ifndef HAVE_ARC4RANDOM + +#include +#include + +#include "log.h" #define KEYSTREAM_ONLY #include "chacha_private.h" @@ -42,6 +47,10 @@ #define inline #endif /* !__GNUC__ */ +/* OpenSSH isn't multithreaded */ +#define _ARC4_LOCK() +#define _ARC4_UNLOCK() + #define KEYSZ 32 #define IVSZ 8 #define BLOCKSZ 64 @@ -67,15 +76,11 @@ _rs_init(u_char *buf, size_t n) static void _rs_stir(void) { - int mib[2]; - size_t len; u_char rnd[KEYSZ + IVSZ]; - mib[0] = CTL_KERN; - mib[1] = KERN_ARND; - - len = sizeof(rnd); - sysctl(mib, 2, rnd, &len, NULL, 0); + if (RAND_bytes(rnd, sizeof(rnd)) <= 0) + fatal("Couldn't obtain random bytes (error %ld)", + ERR_get_error()); if (!rs_initialized) { rs_initialized = 1; @@ -194,6 +199,11 @@ arc4random(void) return val; } +/* + * If we are providing arc4random, then we can provide a more efficient + * arc4random_buf(). + */ +# ifndef HAVE_ARC4RANDOM_BUF void arc4random_buf(void *buf, size_t n) { @@ -201,7 +211,29 @@ arc4random_buf(void *buf, size_t n) _rs_random_buf(buf, n); _ARC4_UNLOCK(); } +# endif /* !HAVE_ARC4RANDOM_BUF */ +#endif /* !HAVE_ARC4RANDOM */ + +/* arc4random_buf() that uses platform arc4random() */ +#if !defined(HAVE_ARC4RANDOM_BUF) && defined(HAVE_ARC4RANDOM) +void +arc4random_buf(void *_buf, size_t n) +{ + size_t i; + u_int32_t r = 0; + char *buf = (char *)_buf; + + for (i = 0; i < n; i++) { + if (i % 4 == 0) + r = arc4random(); + buf[i] = r & 0xff; + r >>= 8; + } + i = r = 0; +} +#endif /* !defined(HAVE_ARC4RANDOM_BUF) && defined(HAVE_ARC4RANDOM) */ +#ifndef HAVE_ARC4RANDOM_UNIFORM /* * Calculate a uniformly distributed random number less than upper_bound * avoiding "modulo bias". @@ -237,6 +269,7 @@ arc4random_uniform(u_int32_t upper_bound) return r % upper_bound; } +#endif /* !HAVE_ARC4RANDOM_UNIFORM */ #if 0 /*-------- Test code for i386 --------*/ -- cgit v1.2.3