From a4be7c23fdcf8a1da5420068dc4bd4db45af9c9c Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Mon, 19 May 2008 14:47:37 +1000 Subject: - (djm) [openbsd-compat/bsd-arc4random.c openbsd-compat/openbsd-compat.c] [configure.ac] Implement arc4random_buf(), import implementation of arc4random_uniform() from OpenBSD --- ChangeLog | 5 +++- configure.ac | 6 ++-- openbsd-compat/bsd-arc4random.c | 65 +++++++++++++++++++++++++++++++++++++++++ openbsd-compat/openbsd-compat.h | 10 ++++++- 4 files changed, 82 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index f466f481e..66145e52a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -11,6 +11,9 @@ - djm@cvs.openbsd.org 2008/04/05 02:46:02 [sshd_config.5] HostbasedAuthentication is supported under Match too + - (djm) [openbsd-compat/bsd-arc4random.c openbsd-compat/openbsd-compat.c] + [configure.ac] Implement arc4random_buf(), import implementation of + arc4random_uniform() from OpenBSD 20080403 - (djm) [openbsd-compat/bsd-poll.c] Include stdlib.h to avoid compile- @@ -3871,4 +3874,4 @@ OpenServer 6 and add osr5bigcrypt support so when someone migrates passwords between UnixWare and OpenServer they will still work. OK dtucker@ -$Id: ChangeLog,v 1.4908 2008/05/19 04:29:08 djm Exp $ +$Id: ChangeLog,v 1.4909 2008/05/19 04:47:37 djm Exp $ diff --git a/configure.ac b/configure.ac index 7b92bad1d..e6e916e82 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -# $Id: configure.ac,v 1.397 2008/03/27 01:33:07 djm Exp $ +# $Id: configure.ac,v 1.398 2008/05/19 04:47:37 djm Exp $ # # Copyright (c) 1999-2004 Damien Miller # @@ -15,7 +15,7 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. AC_INIT(OpenSSH, Portable, openssh-unix-dev@mindrot.org) -AC_REVISION($Revision: 1.397 $) +AC_REVISION($Revision: 1.398 $) AC_CONFIG_SRCDIR([ssh.c]) AC_CONFIG_HEADER(config.h) @@ -1288,6 +1288,8 @@ AC_ARG_WITH(audit, dnl Checks for library functions. Please keep in alphabetical order AC_CHECK_FUNCS( \ arc4random \ + arc4random_buf \ + arc4random_uniform \ asprintf \ b64_ntop \ __b64_ntop \ diff --git a/openbsd-compat/bsd-arc4random.c b/openbsd-compat/bsd-arc4random.c index d45fb182a..8bf31e5d3 100644 --- a/openbsd-compat/bsd-arc4random.c +++ b/openbsd-compat/bsd-arc4random.c @@ -82,3 +82,68 @@ arc4random_stir(void) rc4_ready = REKEY_BYTES; } #endif /* !HAVE_ARC4RANDOM */ + +#ifndef ARC4RANDOM_BUF +void +arc4random_buf(void *_buf, size_t n) +{ + size_t i; + u_int32_t r; + 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 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 */ diff --git a/openbsd-compat/openbsd-compat.h b/openbsd-compat/openbsd-compat.h index 6406af19d..eb48b362b 100644 --- a/openbsd-compat/openbsd-compat.h +++ b/openbsd-compat/openbsd-compat.h @@ -1,4 +1,4 @@ -/* $Id: openbsd-compat.h,v 1.43 2007/06/25 12:15:13 dtucker Exp $ */ +/* $Id: openbsd-compat.h,v 1.44 2008/05/19 04:47:37 djm Exp $ */ /* * Copyright (c) 1999-2003 Damien Miller. All rights reserved. @@ -151,6 +151,14 @@ unsigned int arc4random(void); void arc4random_stir(void); #endif /* !HAVE_ARC4RANDOM */ +#ifndef HAVE_ARC4RANDOM_BUF +void arc4random_buf(void *, size_t); +#endif + +#ifndef HAVE_ARC4RANDOM_UNIFORM +u_int32_t arc4random_uniform(u_int32_t); +#endif + #ifndef HAVE_ASPRINTF int asprintf(char **, const char *, ...); #endif -- cgit v1.2.3