diff options
author | Xin LI <delphij@FreeBSD.org> | 2018-08-19 17:40:50 +0000 |
---|---|---|
committer | Xin LI <delphij@FreeBSD.org> | 2018-08-19 17:40:50 +0000 |
commit | c1e80940f3b4030df0aaed73028053af057e476d (patch) | |
tree | ee75152b4a830a9a9cc43935fc322da1c1241897 | |
parent | 38a13e9002540152964435700f0f2a73ad5e2e62 (diff) | |
download | src-test2-c1e80940f3b4030df0aaed73028053af057e476d.tar.gz src-test2-c1e80940f3b4030df0aaed73028053af057e476d.zip |
Notes
-rw-r--r-- | ObsoleteFiles.inc | 3 | ||||
-rw-r--r-- | contrib/ntp/lib/isc/random.c | 2 | ||||
-rw-r--r-- | contrib/ntp/sntp/libevent/evutil_rand.c | 2 | ||||
-rw-r--r-- | crypto/heimdal/lib/roken/rand.c | 1 | ||||
-rw-r--r-- | crypto/openssh/config.h | 2 | ||||
-rw-r--r-- | include/stdlib.h | 9 | ||||
-rw-r--r-- | lib/libc/gen/Makefile.inc | 7 | ||||
-rw-r--r-- | lib/libc/gen/Symbol.map | 2 | ||||
-rw-r--r-- | lib/libc/gen/arc4random-compat.c | 72 | ||||
-rw-r--r-- | lib/libc/gen/arc4random.3 | 110 | ||||
-rw-r--r-- | lib/libc/gen/arc4random.c | 310 | ||||
-rw-r--r-- | lib/libc/gen/arc4random.h | 74 | ||||
-rw-r--r-- | lib/libc/gen/getentropy.c | 27 | ||||
-rw-r--r-- | lib/libc/include/libc_private.h | 2 | ||||
-rw-r--r-- | sys/crypto/chacha20/chacha.c | 11 | ||||
-rw-r--r-- | sys/crypto/chacha20/chacha.h | 12 |
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 */ |