summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXin LI <delphij@FreeBSD.org>2018-08-19 17:40:50 +0000
committerXin LI <delphij@FreeBSD.org>2018-08-19 17:40:50 +0000
commitc1e80940f3b4030df0aaed73028053af057e476d (patch)
treeee75152b4a830a9a9cc43935fc322da1c1241897
parent38a13e9002540152964435700f0f2a73ad5e2e62 (diff)
downloadsrc-test2-c1e80940f3b4030df0aaed73028053af057e476d.tar.gz
src-test2-c1e80940f3b4030df0aaed73028053af057e476d.zip
Notes
-rw-r--r--ObsoleteFiles.inc3
-rw-r--r--contrib/ntp/lib/isc/random.c2
-rw-r--r--contrib/ntp/sntp/libevent/evutil_rand.c2
-rw-r--r--crypto/heimdal/lib/roken/rand.c1
-rw-r--r--crypto/openssh/config.h2
-rw-r--r--include/stdlib.h9
-rw-r--r--lib/libc/gen/Makefile.inc7
-rw-r--r--lib/libc/gen/Symbol.map2
-rw-r--r--lib/libc/gen/arc4random-compat.c72
-rw-r--r--lib/libc/gen/arc4random.3110
-rw-r--r--lib/libc/gen/arc4random.c310
-rw-r--r--lib/libc/gen/arc4random.h74
-rw-r--r--lib/libc/gen/getentropy.c27
-rw-r--r--lib/libc/include/libc_private.h2
-rw-r--r--sys/crypto/chacha20/chacha.c11
-rw-r--r--sys/crypto/chacha20/chacha.h12
16 files changed, 390 insertions, 256 deletions
diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc
index 1493f1c9899a..414be14d1fe7 100644
--- a/ObsoleteFiles.inc
+++ b/ObsoleteFiles.inc
@@ -38,6 +38,9 @@
# xargs -n1 | sort | uniq -d;
# done
+# 20180819: Remove deprecated arc4random(3) stir/addrandom interfaces
+OLD_FILES+=usr/share/man/man3/arc4random_addrandom.3.gz
+OLD_FILES+=usr/share/man/man3/arc4random_stir.3.gz
# 20180819: send-pr(1) placeholder removal
OLD_FILES+=usr/bin/send-pr
# 20180725: Cleanup old libcasper.so.0
diff --git a/contrib/ntp/lib/isc/random.c b/contrib/ntp/lib/isc/random.c
index 8b73ed56927d..c433f478a837 100644
--- a/contrib/ntp/lib/isc/random.c
+++ b/contrib/ntp/lib/isc/random.c
@@ -67,8 +67,6 @@ isc_random_seed(isc_uint32_t seed)
#ifndef HAVE_ARC4RANDOM
srand(seed);
-#else
- arc4random_addrandom((u_char *) &seed, sizeof(isc_uint32_t));
#endif
}
diff --git a/contrib/ntp/sntp/libevent/evutil_rand.c b/contrib/ntp/sntp/libevent/evutil_rand.c
index 046a14b07a9a..24efa69288da 100644
--- a/contrib/ntp/sntp/libevent/evutil_rand.c
+++ b/contrib/ntp/sntp/libevent/evutil_rand.c
@@ -195,8 +195,6 @@ evutil_secure_rng_get_bytes(void *buf, size_t n)
void
evutil_secure_rng_add_bytes(const char *buf, size_t n)
{
- arc4random_addrandom((unsigned char*)buf,
- n>(size_t)INT_MAX ? INT_MAX : (int)n);
}
void
diff --git a/crypto/heimdal/lib/roken/rand.c b/crypto/heimdal/lib/roken/rand.c
index ef92c2052b78..3172756daf79 100644
--- a/crypto/heimdal/lib/roken/rand.c
+++ b/crypto/heimdal/lib/roken/rand.c
@@ -37,7 +37,6 @@ void ROKEN_LIB_FUNCTION
rk_random_init(void)
{
#if defined(HAVE_ARC4RANDOM)
- arc4random_stir();
#elif defined(HAVE_SRANDOMDEV)
srandomdev();
#elif defined(HAVE_RANDOM)
diff --git a/crypto/openssh/config.h b/crypto/openssh/config.h
index 2dc0c296d447..f76727418c61 100644
--- a/crypto/openssh/config.h
+++ b/crypto/openssh/config.h
@@ -191,7 +191,7 @@
#define HAVE_ARC4RANDOM_BUF 1
/* Define to 1 if you have the `arc4random_stir' function. */
-#define HAVE_ARC4RANDOM_STIR 1
+/* #undef HAVE_ARC4RANDOM_STIR */
/* Define to 1 if you have the `arc4random_uniform' function. */
#define HAVE_ARC4RANDOM_UNIFORM 1
diff --git a/include/stdlib.h b/include/stdlib.h
index d38952e15629..51f003171451 100644
--- a/include/stdlib.h
+++ b/include/stdlib.h
@@ -250,11 +250,16 @@ extern void (*malloc_message)(void *, const char *);
void abort2(const char *, int, void **) __dead2;
__uint32_t
arc4random(void);
-void arc4random_addrandom(unsigned char *, int);
void arc4random_buf(void *, size_t);
-void arc4random_stir(void);
__uint32_t
arc4random_uniform(__uint32_t);
+
+#if !defined(BURN_BRIDGES)
+/* Deprecated arc4random() functions */
+#define arc4random_stir()
+#define arc4random_addrandom(a,b)
+#endif
+
#ifdef __BLOCKS__
int atexit_b(void (^ _Nonnull)(void));
void *bsearch_b(const void *, const void *, size_t,
diff --git a/lib/libc/gen/Makefile.inc b/lib/libc/gen/Makefile.inc
index c6defe88cc96..d6eb1075dbfa 100644
--- a/lib/libc/gen/Makefile.inc
+++ b/lib/libc/gen/Makefile.inc
@@ -16,6 +16,7 @@ SRCS+= __getosreldate.c \
_thread_init.c \
alarm.c \
arc4random.c \
+ arc4random-compat.c \
arc4random_uniform.c \
assert.c \
auxv.c \
@@ -166,6 +167,8 @@ SRCS+= devname-compat11.c \
unvis-compat.c
.endif
+CFLAGS.arc4random.c= -I${SRCTOP}/sys -I${SRCTOP}/sys/crypto/chacha20
+
.PATH: ${SRCTOP}/contrib/libc-pwcache
SRCS+= pwcache.c pwcache.h
@@ -316,9 +319,7 @@ MAN+= alarm.3 \
vis.3 \
wordexp.3
-MLINKS+=arc4random.3 arc4random_addrandom.3 \
- arc4random.3 arc4random_stir.3 \
- arc4random.3 arc4random_buf.3 \
+MLINKS+=arc4random.3 arc4random_buf.3 \
arc4random.3 arc4random_uniform.3
MLINKS+=ctermid.3 ctermid_r.3
MLINKS+=devname.3 devname_r.3
diff --git a/lib/libc/gen/Symbol.map b/lib/libc/gen/Symbol.map
index cd81e96eeb5c..010358ba9bc5 100644
--- a/lib/libc/gen/Symbol.map
+++ b/lib/libc/gen/Symbol.map
@@ -65,8 +65,6 @@ FBSD_1.0 {
pthread_testcancel;
alarm;
arc4random;
- arc4random_addrandom;
- arc4random_stir;
__assert;
check_utility_compat;
clock;
diff --git a/lib/libc/gen/arc4random-compat.c b/lib/libc/gen/arc4random-compat.c
new file mode 100644
index 000000000000..065998e80553
--- /dev/null
+++ b/lib/libc/gen/arc4random-compat.c
@@ -0,0 +1,72 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2018 Google LLC
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <stdbool.h>
+#include <syslog.h>
+
+/*
+ * The following functions were removed from OpenBSD for good reasons:
+ *
+ * - arc4random_stir()
+ * - arc4random_addrandom()
+ *
+ * On FreeBSD, for backward ABI compatibility, we provide two wrapper which
+ * logs this event and returns.
+ */
+
+void __arc4random_stir_fbsd11(void);
+void __arc4random_addrandom_fbsd11(u_char *, int);
+
+void
+__arc4random_stir_fbsd11(void)
+{
+ static bool warned = false;
+
+ if (!warned)
+ syslog(LOG_DEBUG, "Deprecated function arc4random_stir() called");
+ warned = true;
+}
+
+void
+__arc4random_addrandom_fbsd11(u_char * dummy1 __unused, int dummy2 __unused)
+{
+ static bool warned = false;
+
+ if (!warned)
+ syslog(LOG_DEBUG, "Deprecated function arc4random_addrandom() called");
+ warned = true;
+}
+
+__sym_compat(arc4random_stir, __arc4random_stir_fbsd11, FBSD_1.0);
+__sym_compat(arc4random_addrandom, __arc4random_addrandom_fbsd11, FBSD_1.0);
diff --git a/lib/libc/gen/arc4random.3 b/lib/libc/gen/arc4random.3
index e1124c622e77..77ad24f9a570 100644
--- a/lib/libc/gen/arc4random.3
+++ b/lib/libc/gen/arc4random.3
@@ -1,4 +1,5 @@
-.\" $OpenBSD: arc4random.3,v 1.2 1997/04/27 22:40:25 angelos Exp $
+.\" $OpenBSD: arc4random.3,v 1.35 2014/11/25 16:45:24 millert Exp $
+.\"
.\" Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
.\" All rights reserved.
.\"
@@ -30,16 +31,14 @@
.\" Manual page, using -mandoc macros
.\" $FreeBSD$
.\"
-.Dd April 15, 1997
+.Dd July 19, 2014
.Dt ARC4RANDOM 3
.Os
.Sh NAME
.Nm arc4random ,
.Nm arc4random_buf ,
-.Nm arc4random_uniform ,
-.Nm arc4random_stir ,
-.Nm arc4random_addrandom
-.Nd arc4 random number generator
+.Nm arc4random_uniform
+.Nd random number generator
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
@@ -50,20 +49,36 @@
.Fn arc4random_buf "void *buf" "size_t nbytes"
.Ft uint32_t
.Fn arc4random_uniform "uint32_t upper_bound"
-.Ft void
-.Fn arc4random_stir "void"
-.Ft void
-.Fn arc4random_addrandom "unsigned char *dat" "int datlen"
.Sh DESCRIPTION
+This family of functions provides higher quality data than those
+described in
+.Xr rand 3 ,
+.Xr random 3 ,
+and
+.Xr rand48 3 .
+.Pp
+Use of these functions is encouraged for almost all random number
+consumption because the other interfaces are deficient in either
+quality, portability, standardization, or availability.
+These functions can be called in almost all coding environments,
+including
+.Xr pthreads 3
+and
+.Xr chroot 2 .
+.Pp
+High quality 32-bit pseudo-random numbers are generated very quickly.
+On each call, a cryptographic pseudo-random number generator is used
+to generate a new result.
+One data pool is used for all consumers in a process, so that consumption
+under program flow can act as additional stirring.
+The subsystem is re-seeded from the kernel random number subsystem using
+.Xr getentropy 2
+on a regular basis, and also upon
+.Xr fork 2 .
+.Pp
The
.Fn arc4random
-function uses the key stream generator employed by the
-arc4 cipher, which uses 8*8 8 bit S-Boxes.
-The S-Boxes
-can be in about
-.if t 2\u\s71700\s10\d
-.if n (2**1700)
-states.
+function returns a single 32-bit value.
The
.Fn arc4random
function returns pseudo-random numbers in the range of 0 to
@@ -75,33 +90,24 @@ and
.Xr random 3 .
.Pp
.Fn arc4random_buf
-function fills the region
+fills the region
.Fa buf
of length
.Fa nbytes
-with ARC4-derived random data.
+with random data.
.Pp
.Fn arc4random_uniform
-will return a uniformly distributed random number less than
+will return a single 32-bit value, uniformly distributed but less than
.Fa upper_bound .
-.Fn arc4random_uniform
-is recommended over constructions like
+This is recommended over constructions like
.Dq Li arc4random() % upper_bound
as it avoids "modulo bias" when the upper bound is not a power of two.
-.Pp
-The
-.Fn arc4random_stir
-function reads data from
-.Pa /dev/urandom
-and uses it to permute the S-Boxes via
-.Fn arc4random_addrandom .
-.Pp
-There is no need to call
-.Fn arc4random_stir
-before using
-.Fn arc4random
-functions family, since
-they automatically initialize themselves.
+In the worst case, this function may consume multiple iterations
+to ensure uniformity; see the source code to understand the problem
+and solution.
+.Sh RETURN VALUES
+These functions are always successful, and no return value is
+reserved to indicate an error.
.Sh EXAMPLES
The following produces a drop-in replacement for the traditional
.Fn rand
@@ -113,15 +119,25 @@ functions using
.Dl "#define foo4random() (arc4random() % ((unsigned)RAND_MAX + 1))"
.Sh SEE ALSO
.Xr rand 3 ,
-.Xr random 3 ,
-.Xr srandomdev 3
+.Xr rand48 3 ,
+.Xr random 3
.Sh HISTORY
-.Pa RC4
-has been designed by RSA Data Security, Inc.
-It was posted anonymously
-to the USENET and was confirmed to be equivalent by several sources who
-had access to the original cipher.
-Since
-.Pa RC4
-used to be a trade secret, the cipher is now referred to as
-.Pa ARC4 .
+These functions first appeared in
+.Ox 2.1 .
+.Pp
+The original version of this random number generator used the
+RC4 (also known as ARC4) algorithm.
+In
+.Ox 5.5
+it was replaced with the ChaCha20 cipher, and it may be replaced
+again in the future as cryptographic techniques advance.
+A good mnemonic is
+.Dq A Replacement Call for Random .
+.Pp
+The
+.Fn arc4random
+random number generator was first introduced in
+.Fx 2.2.6 .
+The ChaCha20 based implementation was introduced in
+.Fx 12.0 ,
+with obsolete stir and addrandom interfaces removed at the same time.
diff --git a/lib/libc/gen/arc4random.c b/lib/libc/gen/arc4random.c
index 4c20680d305c..3a884fa8ace4 100644
--- a/lib/libc/gen/arc4random.c
+++ b/lib/libc/gen/arc4random.c
@@ -1,8 +1,10 @@
-/* $OpenBSD: arc4random.c,v 1.24 2013/06/11 16:59:50 deraadt Exp $ */
+/* $OpenBSD: arc4random.c,v 1.54 2015/09/13 08:31:47 guenther Exp $ */
/*
* Copyright (c) 1996, David Mazieres <dm@uun.org>
* Copyright (c) 2008, Damien Miller <djm@openbsd.org>
+ * Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
+ * Copyright (c) 2014, Theo de Raadt <deraadt@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -18,15 +20,7 @@
*/
/*
- * Arc4 random number generator for OpenBSD.
- *
- * This code is derived from section 17.1 of Applied Cryptography,
- * second edition, which describes a stream cipher allegedly
- * compatible with RSA Labs "RC4" cipher (the actual description of
- * which is a trade secret). The same algorithm is used as a stream
- * cipher called "arcfour" in Tatu Ylonen's ssh package.
- *
- * RC4 is a registered trademark of RSA Laboratories.
+ * ChaCha based random number generator for OpenBSD.
*/
#include <sys/cdefs.h>
@@ -35,232 +29,176 @@ __FBSDID("$FreeBSD$");
#include "namespace.h"
#include <fcntl.h>
#include <limits.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdint.h>
#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
-#include <sys/param.h>
-#include <sys/sysctl.h>
+#include <sys/types.h>
#include <sys/time.h>
-#include <pthread.h>
-
+
#include "libc_private.h"
#include "un-namespace.h"
-#ifdef __GNUC__
-#define inline __inline
-#else /* !__GNUC__ */
-#define inline
-#endif /* !__GNUC__ */
+#define KEYSTREAM_ONLY
+#include "chacha.c"
-struct arc4_stream {
- u_int8_t i;
- u_int8_t j;
- u_int8_t s[256];
-};
+#define minimum(a, b) ((a) < (b) ? (a) : (b))
-static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
-
-#define KEYSIZE 128
-#define _ARC4_LOCK() \
- do { \
- if (__isthreaded) \
- _pthread_mutex_lock(&arc4random_mtx); \
- } while (0)
-
-#define _ARC4_UNLOCK() \
- do { \
- if (__isthreaded) \
- _pthread_mutex_unlock(&arc4random_mtx); \
- } while (0)
+#if defined(__GNUC__) || defined(_MSC_VER)
+#define inline __inline
+#else /* __GNUC__ || _MSC_VER */
+#define inline
+#endif /* !__GNUC__ && !_MSC_VER */
-static int rs_initialized;
-static struct arc4_stream rs;
-static pid_t arc4_stir_pid;
-static int arc4_count;
+#define KEYSZ 32
+#define IVSZ 8
+#define BLOCKSZ 64
+#define RSBUFSZ (16*BLOCKSZ)
-extern int __sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
- void *newp, size_t newlen);
+/* Marked INHERIT_ZERO, so zero'd out in fork children. */
+static struct _rs {
+ size_t rs_have; /* valid bytes at end of rs_buf */
+ size_t rs_count; /* bytes till reseed */
+} *rs;
-static inline u_int8_t arc4_getbyte(void);
-static void arc4_stir(void);
+/* Maybe be preserved in fork children, if _rs_allocate() decides. */
+static struct _rsx {
+ chacha_ctx rs_chacha; /* chacha context for random keystream */
+ u_char rs_buf[RSBUFSZ]; /* keystream blocks */
+} *rsx;
-static inline void
-arc4_init(void)
-{
- int n;
+static inline int _rs_allocate(struct _rs **, struct _rsx **);
+static inline void _rs_forkdetect(void);
+#include "arc4random.h"
- for (n = 0; n < 256; n++)
- rs.s[n] = n;
- rs.i = 0;
- rs.j = 0;
-}
+static inline void _rs_rekey(u_char *dat, size_t datlen);
static inline void
-arc4_addrandom(u_char *dat, int datlen)
+_rs_init(u_char *buf, size_t n)
{
- int n;
- u_int8_t si;
+ if (n < KEYSZ + IVSZ)
+ return;
- rs.i--;
- for (n = 0; n < 256; n++) {
- rs.i = (rs.i + 1);
- si = rs.s[rs.i];
- rs.j = (rs.j + si + dat[n % datlen]);
- rs.s[rs.i] = rs.s[rs.j];
- rs.s[rs.j] = si;
+ if (rs == NULL) {
+ if (_rs_allocate(&rs, &rsx) == -1)
+ abort();
}
- rs.j = rs.i;
-}
-
-size_t
-__arc4_sysctl(u_char *buf, size_t size)
-{
- int mib[2];
- size_t len, done;
- mib[0] = CTL_KERN;
- mib[1] = KERN_ARND;
- done = 0;
-
- do {
- len = size;
- if (__sysctl(mib, 2, buf, &len, NULL, 0) == -1)
- return (done);
- done += len;
- buf += len;
- size -= len;
- } while (size > 0);
-
- return (done);
+ chacha_keysetup(&rsx->rs_chacha, buf, KEYSZ * 8);
+ chacha_ivsetup(&rsx->rs_chacha, buf + KEYSZ, NULL);
}
static void
-arc4_stir(void)
+_rs_stir(void)
{
- u_char rdat[KEYSIZE];
- int i;
+ u_char rnd[KEYSZ + IVSZ];
- if (!rs_initialized) {
- arc4_init();
- rs_initialized = 1;
- }
- if (__arc4_sysctl(rdat, KEYSIZE) != KEYSIZE) {
- /*
- * The sysctl cannot fail. If it does fail on some FreeBSD
- * derivative or after some future change, just abort so that
- * the problem will be found and fixed. abort is not normally
- * suitable for a library but makes sense here.
- */
- abort();
- }
-
- arc4_addrandom(rdat, KEYSIZE);
+ if (getentropy(rnd, sizeof rnd) == -1)
+ _getentropy_fail();
- /*
- * Discard early keystream, as per recommendations in:
- * "(Not So) Random Shuffles of RC4" by Ilya Mironov.
- */
- for (i = 0; i < 3072; i++)
- (void)arc4_getbyte();
- arc4_count = 1600000;
-}
+ if (!rs)
+ _rs_init(rnd, sizeof(rnd));
+ else
+ _rs_rekey(rnd, sizeof(rnd));
+ explicit_bzero(rnd, sizeof(rnd)); /* discard source seed */
-static void
-arc4_stir_if_needed(void)
-{
- pid_t pid = getpid();
+ /* invalidate rs_buf */
+ rs->rs_have = 0;
+ memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf));
- if (arc4_count <= 0 || !rs_initialized || arc4_stir_pid != pid) {
- arc4_stir_pid = pid;
- arc4_stir();
- }
+ rs->rs_count = 1600000;
}
-static inline u_int8_t
-arc4_getbyte(void)
+static inline void
+_rs_stir_if_needed(size_t len)
{
- u_int8_t si, sj;
-
- rs.i = (rs.i + 1);
- si = rs.s[rs.i];
- rs.j = (rs.j + si);
- sj = rs.s[rs.j];
- rs.s[rs.i] = sj;
- rs.s[rs.j] = si;
- return (rs.s[(si + sj) & 0xff]);
+ _rs_forkdetect();
+ if (!rs || rs->rs_count <= len)
+ _rs_stir();
+ if (rs->rs_count <= len)
+ rs->rs_count = 0;
+ else
+ rs->rs_count -= len;
}
-static inline u_int32_t
-arc4_getword(void)
+static inline void
+_rs_rekey(u_char *dat, size_t datlen)
{
- u_int32_t val;
- val = arc4_getbyte() << 24;
- val |= arc4_getbyte() << 16;
- val |= arc4_getbyte() << 8;
- val |= arc4_getbyte();
- return val;
+#ifndef KEYSTREAM_ONLY
+ memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf));
+#endif
+ /* fill rs_buf with the keystream */
+ chacha_encrypt_bytes(&rsx->rs_chacha, rsx->rs_buf,
+ rsx->rs_buf, sizeof(rsx->rs_buf));
+ /* mix in optional user provided data */
+ if (dat) {
+ size_t i, m;
+
+ m = minimum(datlen, KEYSZ + IVSZ);
+ for (i = 0; i < m; i++)
+ rsx->rs_buf[i] ^= dat[i];
+ }
+ /* immediately reinit for backtracking resistance */
+ _rs_init(rsx->rs_buf, KEYSZ + IVSZ);
+ memset(rsx->rs_buf, 0, KEYSZ + IVSZ);
+ rs->rs_have = sizeof(rsx->rs_buf) - KEYSZ - IVSZ;
}
-void
-arc4random_stir(void)
+static inline void
+_rs_random_buf(void *_buf, size_t n)
{
- _ARC4_LOCK();
- arc4_stir();
- _ARC4_UNLOCK();
+ u_char *buf = (u_char *)_buf;
+ u_char *keystream;
+ size_t m;
+
+ _rs_stir_if_needed(n);
+ while (n > 0) {
+ if (rs->rs_have > 0) {
+ m = minimum(n, rs->rs_have);
+ keystream = rsx->rs_buf + sizeof(rsx->rs_buf)
+ - rs->rs_have;
+ memcpy(buf, keystream, m);
+ memset(keystream, 0, m);
+ buf += m;
+ n -= m;
+ rs->rs_have -= m;
+ }
+ if (rs->rs_have == 0)
+ _rs_rekey(NULL, 0);
+ }
}
-void
-arc4random_addrandom(u_char *dat, int datlen)
+static inline void
+_rs_random_u32(uint32_t *val)
{
- _ARC4_LOCK();
- if (!rs_initialized)
- arc4_stir();
- arc4_addrandom(dat, datlen);
- _ARC4_UNLOCK();
+ u_char *keystream;
+
+ _rs_stir_if_needed(sizeof(*val));
+ if (rs->rs_have < sizeof(*val))
+ _rs_rekey(NULL, 0);
+ keystream = rsx->rs_buf + sizeof(rsx->rs_buf) - rs->rs_have;
+ memcpy(val, keystream, sizeof(*val));
+ memset(keystream, 0, sizeof(*val));
+ rs->rs_have -= sizeof(*val);
}
-u_int32_t
+uint32_t
arc4random(void)
{
- u_int32_t val;
+ uint32_t val;
+
_ARC4_LOCK();
- arc4_count -= 4;
- arc4_stir_if_needed();
- val = arc4_getword();
+ _rs_random_u32(&val);
_ARC4_UNLOCK();
return val;
}
void
-arc4random_buf(void *_buf, size_t n)
+arc4random_buf(void *buf, size_t n)
{
- u_char *buf = (u_char *)_buf;
_ARC4_LOCK();
- arc4_stir_if_needed();
- while (n--) {
- if (--arc4_count <= 0)
- arc4_stir();
- buf[n] = arc4_getbyte();
- }
+ _rs_random_buf(buf, n);
_ARC4_UNLOCK();
}
-
-#if 0
-/*-------- Test code for i386 --------*/
-#include <stdio.h>
-#include <machine/pctr.h>
-int
-main(int argc, char **argv)
-{
- const int iter = 1000000;
- int i;
- pctrval v;
-
- v = rdtsc();
- for (i = 0; i < iter; i++)
- arc4random();
- v = rdtsc() - v;
- v /= iter;
-
- printf("%qd cycles\n", v);
-}
-#endif
diff --git a/lib/libc/gen/arc4random.h b/lib/libc/gen/arc4random.h
new file mode 100644
index 000000000000..a83b7a2e8861
--- /dev/null
+++ b/lib/libc/gen/arc4random.h
@@ -0,0 +1,74 @@
+/* $OpenBSD: arc4random.h,v 1.4 2015/01/15 06:57:18 deraadt Exp $ */
+
+/*
+ * Copyright (c) 1996, David Mazieres <dm@uun.org>
+ * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
+ * Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
+ * Copyright (c) 2014, Theo de Raadt <deraadt@openbsd.org>
+ *
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Stub functions for portability.
+ */
+#include <sys/mman.h>
+
+#include <signal.h>
+
+static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
+#define _ARC4_LOCK() \
+ do { \
+ if (__isthreaded) \
+ _pthread_mutex_lock(&arc4random_mtx); \
+ } while (0)
+
+#define _ARC4_UNLOCK() \
+ do { \
+ if (__isthreaded) \
+ _pthread_mutex_unlock(&arc4random_mtx); \
+ } while (0)
+
+static inline void
+_getentropy_fail(void)
+{
+ raise(SIGKILL);
+}
+
+static inline int
+_rs_allocate(struct _rs **rsp, struct _rsx **rsxp)
+{
+ struct {
+ struct _rs rs;
+ struct _rsx rsx;
+ } *p;
+
+ if ((p = mmap(NULL, sizeof(*p), PROT_READ|PROT_WRITE,
+ MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
+ return (-1);
+ if (minherit(p, sizeof(*p), INHERIT_ZERO) == -1) {
+ munmap(p, sizeof(*p));
+ return (-1);
+ }
+
+ *rsp = &p->rs;
+ *rsxp = &p->rsx;
+ return (0);
+}
+
+static inline void
+_rs_forkdetect(void)
+{
+}
diff --git a/lib/libc/gen/getentropy.c b/lib/libc/gen/getentropy.c
index bf7f18b3fd52..2e0f649a15be 100644
--- a/lib/libc/gen/getentropy.c
+++ b/lib/libc/gen/getentropy.c
@@ -31,12 +31,37 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/random.h>
+#include <sys/sysctl.h>
#include <errno.h>
#include <stdlib.h>
#include "libc_private.h"
+extern int __sysctl(int *, u_int, void *, size_t *, void *, size_t);
+
+static size_t
+arnd_sysctl(u_char *buf, size_t size)
+{
+ int mib[2];
+ size_t len, done;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_ARND;
+ done = 0;
+
+ do {
+ len = size;
+ if (__sysctl(mib, 2, buf, &len, NULL, 0) == -1)
+ return (done);
+ done += len;
+ buf += len;
+ size -= len;
+ } while (size > 0);
+
+ return (done);
+}
+
/*
* If a newer libc is accidentally installed on an older kernel, provide high
* quality random data anyway. The sysctl interface is not as fast and does
@@ -54,7 +79,7 @@ getentropy_fallback(void *buf, size_t buflen)
errno = EFAULT;
return (-1);
}
- if (__arc4_sysctl(buf, buflen) != buflen) {
+ if (arnd_sysctl(buf, buflen) != buflen) {
if (errno == EFAULT)
return (-1);
/*
diff --git a/lib/libc/include/libc_private.h b/lib/libc/include/libc_private.h
index 0985b5ed8741..aaa40deeb083 100644
--- a/lib/libc/include/libc_private.h
+++ b/lib/libc/include/libc_private.h
@@ -405,8 +405,6 @@ int __sys_futimens(int fd, const struct timespec *times) __hidden;
int __sys_utimensat(int fd, const char *path,
const struct timespec *times, int flag) __hidden;
-__size_t __arc4_sysctl(unsigned char *, __size_t);
-
/* execve() with PATH processing to implement posix_spawnp() */
int _execvpe(const char *, char * const *, char * const *);
diff --git a/sys/crypto/chacha20/chacha.c b/sys/crypto/chacha20/chacha.c
index b3566087aee6..ac4eef222115 100644
--- a/sys/crypto/chacha20/chacha.c
+++ b/sys/crypto/chacha20/chacha.c
@@ -14,7 +14,6 @@ __FBSDID("$FreeBSD$");
#include <crypto/chacha20/chacha.h>
-
typedef uint8_t u8;
typedef uint32_t u32;
@@ -57,7 +56,7 @@ typedef struct chacha_ctx chacha_ctx;
static const char sigma[16] = "expand 32-byte k";
static const char tau[16] = "expand 16-byte k";
-void
+LOCAL void
chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits)
{
const char *constants;
@@ -82,7 +81,7 @@ chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits)
x->input[3] = U8TO32_LITTLE(constants + 12);
}
-void
+LOCAL void
chacha_ivsetup(chacha_ctx *x, const u8 *iv, const u8 *counter)
{
x->input[12] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 0);
@@ -91,7 +90,7 @@ chacha_ivsetup(chacha_ctx *x, const u8 *iv, const u8 *counter)
x->input[15] = U8TO32_LITTLE(iv + 4);
}
-void
+LOCAL void
chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 *c,u32 bytes)
{
u32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
@@ -169,6 +168,7 @@ chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 *c,u32 bytes)
x14 = PLUS(x14,j14);
x15 = PLUS(x15,j15);
+#ifndef KEYSTREAM_ONLY
x0 = XOR(x0,U8TO32_LITTLE(m + 0));
x1 = XOR(x1,U8TO32_LITTLE(m + 4));
x2 = XOR(x2,U8TO32_LITTLE(m + 8));
@@ -185,6 +185,7 @@ chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 *c,u32 bytes)
x13 = XOR(x13,U8TO32_LITTLE(m + 52));
x14 = XOR(x14,U8TO32_LITTLE(m + 56));
x15 = XOR(x15,U8TO32_LITTLE(m + 60));
+#endif
j12 = PLUSONE(j12);
if (!j12) {
@@ -219,6 +220,8 @@ chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 *c,u32 bytes)
}
bytes -= 64;
c += 64;
+#ifndef KEYSTREAM_ONLY
m += 64;
+#endif
}
}
diff --git a/sys/crypto/chacha20/chacha.h b/sys/crypto/chacha20/chacha.h
index 02106eaa250d..e67cc81264cd 100644
--- a/sys/crypto/chacha20/chacha.h
+++ b/sys/crypto/chacha20/chacha.h
@@ -23,9 +23,15 @@ struct chacha_ctx {
#define CHACHA_STATELEN (CHACHA_NONCELEN+CHACHA_CTRLEN)
#define CHACHA_BLOCKLEN 64
-void chacha_keysetup(struct chacha_ctx *x, const u_char *k, u_int kbits);
-void chacha_ivsetup(struct chacha_ctx *x, const u_char *iv, const u_char *ctr);
-void chacha_encrypt_bytes(struct chacha_ctx *x, const u_char *m,
+#ifdef _KERNEL
+#define LOCAL
+#else
+#define LOCAL static
+#endif
+
+LOCAL void chacha_keysetup(struct chacha_ctx *x, const u_char *k, u_int kbits);
+LOCAL void chacha_ivsetup(struct chacha_ctx *x, const u_char *iv, const u_char *ctr);
+LOCAL void chacha_encrypt_bytes(struct chacha_ctx *x, const u_char *m,
u_char *c, u_int bytes);
#endif /* CHACHA_H */