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@ --- ChangeLog | 4 ++ openbsd-compat/Makefile.in | 4 +- openbsd-compat/arc4random.c | 59 ++++++++++++---- openbsd-compat/bsd-arc4random.c | 150 ---------------------------------------- 4 files changed, 52 insertions(+), 165 deletions(-) delete mode 100644 openbsd-compat/bsd-arc4random.c diff --git a/ChangeLog b/ChangeLog index 34b6d17f9..78578cf19 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,10 @@ - (djm) [openbsd-compat/arc4random.c openbsd-compat/chacha_private.h] Pull in OpenBSD implementation of arc4random, shortly to replace the existing bsd-arc4random.c + - (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@ 20130922 - (dtucker) [platform.c platform.h sshd.c] bz#2156: restore Linux oom_adj diff --git a/openbsd-compat/Makefile.in b/openbsd-compat/Makefile.in index 365cf006d..a5f4a266c 100644 --- a/openbsd-compat/Makefile.in +++ b/openbsd-compat/Makefile.in @@ -1,4 +1,4 @@ -# $Id: Makefile.in,v 1.51 2013/05/10 06:28:56 dtucker Exp $ +# $Id: Makefile.in,v 1.52 2013/10/08 23:44:49 djm Exp $ sysconfdir=@sysconfdir@ piddir=@piddir@ @@ -18,7 +18,7 @@ LDFLAGS=-L. @LDFLAGS@ OPENBSD=base64.o basename.o bindresvport.o daemon.o dirname.o fmt_scaled.o getcwd.o getgrouplist.o getopt_long.o getrrsetbyname.o glob.o inet_aton.o inet_ntoa.o inet_ntop.o mktemp.o pwcache.o readpassphrase.o realpath.o rresvport.o setenv.o setproctitle.o sha2.o sigact.o strlcat.o strlcpy.o strmode.o strnlen.o strptime.o strsep.o strtonum.o strtoll.o strtoul.o strtoull.o timingsafe_bcmp.o vis.o -COMPAT=bsd-arc4random.o bsd-asprintf.o bsd-closefrom.o bsd-cray.o bsd-cygwin_util.o bsd-getpeereid.o getrrsetbyname-ldns.o bsd-misc.o bsd-nextstep.o bsd-openpty.o bsd-poll.o bsd-setres_id.o bsd-snprintf.o bsd-statvfs.o bsd-waitpid.o fake-rfc2553.o openssl-compat.o xmmap.o xcrypt.o +COMPAT=arc4random.o bsd-asprintf.o bsd-closefrom.o bsd-cray.o bsd-cygwin_util.o bsd-getpeereid.o getrrsetbyname-ldns.o bsd-misc.o bsd-nextstep.o bsd-openpty.o bsd-poll.o bsd-setres_id.o bsd-snprintf.o bsd-statvfs.o bsd-waitpid.o fake-rfc2553.o openssl-compat.o xmmap.o xcrypt.o PORTS=port-aix.o port-irix.o port-linux.o port-solaris.o port-tun.o port-uw.o 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 --------*/ diff --git a/openbsd-compat/bsd-arc4random.c b/openbsd-compat/bsd-arc4random.c deleted file mode 100644 index d7c586253..000000000 --- a/openbsd-compat/bsd-arc4random.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) 1999,2000,2004 Damien Miller - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "includes.h" - -#include - -#include -#include -#include - -#include "log.h" - -#ifndef HAVE_ARC4RANDOM - -#include -#include -#include - -/* Size of key to use */ -#define SEED_SIZE 20 - -/* Number of bytes to reseed after */ -#define REKEY_BYTES (1 << 24) - -static int rc4_ready = 0; -static RC4_KEY rc4; - -unsigned int -arc4random(void) -{ - unsigned int r = 0; - static int first_time = 1; - - if (rc4_ready <= 0) { - if (first_time) - seed_rng(); - first_time = 0; - arc4random_stir(); - } - - RC4(&rc4, sizeof(r), (unsigned char *)&r, (unsigned char *)&r); - - rc4_ready -= sizeof(r); - - return(r); -} - -void -arc4random_stir(void) -{ - unsigned char rand_buf[SEED_SIZE]; - int i; - - memset(&rc4, 0, sizeof(rc4)); - if (RAND_bytes(rand_buf, sizeof(rand_buf)) <= 0) - fatal("Couldn't obtain random bytes (error %ld)", - ERR_get_error()); - RC4_set_key(&rc4, sizeof(rand_buf), rand_buf); - - /* - * Discard early keystream, as per recommendations in: - * http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps - */ - for(i = 0; i <= 256; i += sizeof(rand_buf)) - RC4(&rc4, sizeof(rand_buf), rand_buf, rand_buf); - - memset(rand_buf, 0, sizeof(rand_buf)); - - rc4_ready = REKEY_BYTES; -} -#endif /* !HAVE_ARC4RANDOM */ - -#ifndef HAVE_ARC4RANDOM_BUF -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 /* !HAVE_ARC4RANDOM_BUF */ - -#ifndef HAVE_ARC4RANDOM_UNIFORM -/* - * Calculate a uniformly distributed random number less than upper_bound - * avoiding "modulo bias". - * - * Uniformity is achieved by generating new random numbers until the one - * returned is outside the range [0, 2**32 % upper_bound). This - * guarantees the selected random number will be inside - * [2**32 % upper_bound, 2**32) which maps back to [0, upper_bound) - * after reduction modulo upper_bound. - */ -u_int32_t -arc4random_uniform(u_int32_t upper_bound) -{ - u_int32_t r, min; - - if (upper_bound < 2) - return 0; - -#if (ULONG_MAX > 0xffffffffUL) - min = 0x100000000UL % upper_bound; -#else - /* Calculate (2**32 % upper_bound) avoiding 64-bit math */ - if (upper_bound > 0x80000000) - min = 1 + ~upper_bound; /* 2**32 - upper_bound */ - else { - /* (2**32 - (x * 2)) % x == 2**32 % x when x <= 2**31 */ - min = ((0xffffffff - (upper_bound * 2)) + 1) % upper_bound; - } -#endif - - /* - * This could theoretically loop forever but each retry has - * p > 0.5 (worst case, usually far better) of selecting a - * number inside the range we need, so it should rarely need - * to re-roll. - */ - for (;;) { - r = arc4random(); - if (r >= min) - break; - } - - return r % upper_bound; -} -#endif /* !HAVE_ARC4RANDOM_UNIFORM */ -- cgit v1.2.3