- (djm) [openbsd-compat/bsd-arc4random.c openbsd-compat/openbsd-compat.c]
     [configure.ac] Implement arc4random_buf(), import implementation of
     arc4random_uniform() from OpenBSD
diff --git a/ChangeLog b/ChangeLog
index f466f48..66145e5 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 7b92bad..e6e916e 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 @@
 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 d45fb18..8bf31e5 100644
--- a/openbsd-compat/bsd-arc4random.c
+++ b/openbsd-compat/bsd-arc4random.c
@@ -82,3 +82,68 @@
 	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 6406af1..eb48b36 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 @@
 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