Date: Sun, 19 Aug 2018 17:40:50 +0000 (UTC) From: Xin LI <delphij@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r338059 - in head: . contrib/ntp/lib/isc contrib/ntp/sntp/libevent crypto/heimdal/lib/roken crypto/openssh include lib/libc/gen lib/libc/include sys/crypto/chacha20 Message-ID: <201808191740.w7JHeoSj052259@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: delphij Date: Sun Aug 19 17:40:50 2018 New Revision: 338059 URL: https://svnweb.freebsd.org/changeset/base/338059 Log: Update userland arc4random() with OpenBSD's Chacha20 based arc4random(). ObsoleteFiles.inc: Remove manual pages for arc4random_addrandom(3) and arc4random_stir(3). contrib/ntp/lib/isc/random.c: contrib/ntp/sntp/libevent/evutil_rand.c: Eliminate in-tree usage of arc4random_addrandom(). crypto/heimdal/lib/roken/rand.c: crypto/openssh/config.h: Eliminate in-tree usage of arc4random_stir(). include/stdlib.h: Remove arc4random_stir() and arc4random_addrandom() prototypes, provide temporary shims for transistion period. lib/libc/gen/Makefile.inc: Hook arc4random-compat.c to build, add hint for Chacha20 source for kernel, and remove arc4random_addrandom(3) and arc4random_stir(3) links. lib/libc/gen/arc4random.c: Adopt OpenBSD arc4random.c,v 1.54 with bare minimum changes, use the sys/crypto/chacha20 implementation of keystream. lib/libc/gen/Symbol.map: Remove arc4random_stir and arc4random_addrandom interfaces. lib/libc/gen/arc4random.h: Adopt OpenBSD arc4random.h,v 1.4 but provide _ARC4_LOCK of our own. lib/libc/gen/arc4random.3: Adopt OpenBSD arc4random.3,v 1.35 but keep FreeBSD r114444 and r118247. lib/libc/gen/arc4random-compat.c: Compatibility shims for arc4random_stir and arc4random_addrandom functions to preserve ABI. Log once when called but do nothing otherwise. lib/libc/gen/getentropy.c: lib/libc/include/libc_private.h: Fold __arc4_sysctl into getentropy.c (renamed to arnd_sysctl). Remove from libc_private.h as a result. sys/crypto/chacha20/chacha.c: sys/crypto/chacha20/chacha.h: Make it possible to use the kernel implementation in libc. PR: 182610 Reviewed by: cem, markm Obtained from: OpenBSD Relnotes: yes Differential Revision: https://reviews.freebsd.org/D16760 Added: head/lib/libc/gen/arc4random-compat.c (contents, props changed) head/lib/libc/gen/arc4random.h (contents, props changed) Modified: head/ObsoleteFiles.inc head/contrib/ntp/lib/isc/random.c head/contrib/ntp/sntp/libevent/evutil_rand.c head/crypto/heimdal/lib/roken/rand.c head/crypto/openssh/config.h head/include/stdlib.h head/lib/libc/gen/Makefile.inc head/lib/libc/gen/Symbol.map head/lib/libc/gen/arc4random.3 head/lib/libc/gen/arc4random.c (contents, props changed) head/lib/libc/gen/getentropy.c head/lib/libc/include/libc_private.h head/sys/crypto/chacha20/chacha.c head/sys/crypto/chacha20/chacha.h Modified: head/ObsoleteFiles.inc ============================================================================== --- head/ObsoleteFiles.inc Sun Aug 19 17:36:50 2018 (r338058) +++ head/ObsoleteFiles.inc Sun Aug 19 17:40:50 2018 (r338059) @@ -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 Modified: head/contrib/ntp/lib/isc/random.c ============================================================================== --- head/contrib/ntp/lib/isc/random.c Sun Aug 19 17:36:50 2018 (r338058) +++ head/contrib/ntp/lib/isc/random.c Sun Aug 19 17:40:50 2018 (r338059) @@ -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 } Modified: head/contrib/ntp/sntp/libevent/evutil_rand.c ============================================================================== --- head/contrib/ntp/sntp/libevent/evutil_rand.c Sun Aug 19 17:36:50 2018 (r338058) +++ head/contrib/ntp/sntp/libevent/evutil_rand.c Sun Aug 19 17:40:50 2018 (r338059) @@ -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 Modified: head/crypto/heimdal/lib/roken/rand.c ============================================================================== --- head/crypto/heimdal/lib/roken/rand.c Sun Aug 19 17:36:50 2018 (r338058) +++ head/crypto/heimdal/lib/roken/rand.c Sun Aug 19 17:40:50 2018 (r338059) @@ -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) Modified: head/crypto/openssh/config.h ============================================================================== --- head/crypto/openssh/config.h Sun Aug 19 17:36:50 2018 (r338058) +++ head/crypto/openssh/config.h Sun Aug 19 17:40:50 2018 (r338059) @@ -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 Modified: head/include/stdlib.h ============================================================================== --- head/include/stdlib.h Sun Aug 19 17:36:50 2018 (r338058) +++ head/include/stdlib.h Sun Aug 19 17:40:50 2018 (r338059) @@ -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, Modified: head/lib/libc/gen/Makefile.inc ============================================================================== --- head/lib/libc/gen/Makefile.inc Sun Aug 19 17:36:50 2018 (r338058) +++ head/lib/libc/gen/Makefile.inc Sun Aug 19 17:40:50 2018 (r338059) @@ -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 Modified: head/lib/libc/gen/Symbol.map ============================================================================== --- head/lib/libc/gen/Symbol.map Sun Aug 19 17:36:50 2018 (r338058) +++ head/lib/libc/gen/Symbol.map Sun Aug 19 17:40:50 2018 (r338059) @@ -65,8 +65,6 @@ FBSD_1.0 { pthread_testcancel; alarm; arc4random; - arc4random_addrandom; - arc4random_stir; __assert; check_utility_compat; clock; Added: head/lib/libc/gen/arc4random-compat.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/lib/libc/gen/arc4random-compat.c Sun Aug 19 17:40:50 2018 (r338059) @@ -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); Modified: head/lib/libc/gen/arc4random.3 ============================================================================== --- head/lib/libc/gen/arc4random.3 Sun Aug 19 17:36:50 2018 (r338058) +++ head/lib/libc/gen/arc4random.3 Sun Aug 19 17:40:50 2018 (r338059) @@ -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. Modified: head/lib/libc/gen/arc4random.c ============================================================================== --- head/lib/libc/gen/arc4random.c Sun Aug 19 17:36:50 2018 (r338058) +++ head/lib/libc/gen/arc4random.c Sun Aug 19 17:40:50 2018 (r338059) @@ -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 KEYSTREAM_ONLY +#include "chacha.c" + +#define minimum(a, b) ((a) < (b) ? (a) : (b)) + +#if defined(__GNUC__) || defined(_MSC_VER) #define inline __inline -#else /* !__GNUC__ */ +#else /* __GNUC__ || _MSC_VER */ #define inline -#endif /* !__GNUC__ */ +#endif /* !__GNUC__ && !_MSC_VER */ -struct arc4_stream { - u_int8_t i; - u_int8_t j; - u_int8_t s[256]; -}; +#define KEYSZ 32 +#define IVSZ 8 +#define BLOCKSZ 64 +#define RSBUFSZ (16*BLOCKSZ) -static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER; +/* 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; -#define KEYSIZE 128 -#define _ARC4_LOCK() \ - do { \ - if (__isthreaded) \ - _pthread_mutex_lock(&arc4random_mtx); \ - } while (0) +/* 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; -#define _ARC4_UNLOCK() \ - do { \ - if (__isthreaded) \ - _pthread_mutex_unlock(&arc4random_mtx); \ - } while (0) +static inline int _rs_allocate(struct _rs **, struct _rsx **); +static inline void _rs_forkdetect(void); +#include "arc4random.h" -static int rs_initialized; -static struct arc4_stream rs; -static pid_t arc4_stir_pid; -static int arc4_count; +static inline void _rs_rekey(u_char *dat, size_t datlen); -extern int __sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, - void *newp, size_t newlen); - -static inline u_int8_t arc4_getbyte(void); -static void arc4_stir(void); - static inline void -arc4_init(void) +_rs_init(u_char *buf, size_t n) { - int n; + if (n < KEYSZ + IVSZ) + return; - for (n = 0; n < 256; n++) - rs.s[n] = n; - rs.i = 0; - rs.j = 0; -} - -static inline void -arc4_addrandom(u_char *dat, int datlen) -{ - int n; - u_int8_t si; - - 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; + + chacha_keysetup(&rsx->rs_chacha, buf, KEYSZ * 8); + chacha_ivsetup(&rsx->rs_chacha, buf + KEYSZ, NULL); } -size_t -__arc4_sysctl(u_char *buf, size_t size) +static void +_rs_stir(void) { - int mib[2]; - size_t len, done; + u_char rnd[KEYSZ + IVSZ]; - mib[0] = CTL_KERN; - mib[1] = KERN_ARND; - done = 0; + if (getentropy(rnd, sizeof rnd) == -1) + _getentropy_fail(); - do { - len = size; - if (__sysctl(mib, 2, buf, &len, NULL, 0) == -1) - return (done); - done += len; - buf += len; - size -= len; - } while (size > 0); + if (!rs) + _rs_init(rnd, sizeof(rnd)); + else + _rs_rekey(rnd, sizeof(rnd)); + explicit_bzero(rnd, sizeof(rnd)); /* discard source seed */ - return (done); + /* invalidate rs_buf */ + rs->rs_have = 0; + memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf)); + + rs->rs_count = 1600000; } -static void -arc4_stir(void) +static inline void +_rs_stir_if_needed(size_t len) { - u_char rdat[KEYSIZE]; - int i; - - 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); - - /* - * 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; + _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 void -arc4_stir_if_needed(void) +static inline void +_rs_rekey(u_char *dat, size_t datlen) { - pid_t pid = getpid(); +#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; - if (arc4_count <= 0 || !rs_initialized || arc4_stir_pid != pid) { - arc4_stir_pid = pid; - arc4_stir(); + 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; } -static inline u_int8_t -arc4_getbyte(void) +static inline void +_rs_random_buf(void *_buf, size_t n) { - u_int8_t si, sj; + u_char *buf = (u_char *)_buf; + u_char *keystream; + size_t m; - 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_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); + } } -static inline u_int32_t -arc4_getword(void) +static inline void +_rs_random_u32(uint32_t *val) { - u_int32_t val; - val = arc4_getbyte() << 24; - val |= arc4_getbyte() << 16; - val |= arc4_getbyte() << 8; - val |= arc4_getbyte(); - return val; -} + u_char *keystream; -void -arc4random_stir(void) -{ - _ARC4_LOCK(); - arc4_stir(); - _ARC4_UNLOCK(); + _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); } -void -arc4random_addrandom(u_char *dat, int datlen) -{ - _ARC4_LOCK(); - if (!rs_initialized) - arc4_stir(); - arc4_addrandom(dat, datlen); - _ARC4_UNLOCK(); -} - -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 Added: head/lib/libc/gen/arc4random.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/lib/libc/gen/arc4random.h Sun Aug 19 17:40:50 2018 (r338059) @@ -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) +{ +} Modified: head/lib/libc/gen/getentropy.c ============================================================================== --- head/lib/libc/gen/getentropy.c Sun Aug 19 17:36:50 2018 (r338058) +++ head/lib/libc/gen/getentropy.c Sun Aug 19 17:40:50 2018 (r338059) @@ -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); /* Modified: head/lib/libc/include/libc_private.h ============================================================================== --- head/lib/libc/include/libc_private.h Sun Aug 19 17:36:50 2018 (r338058) +++ head/lib/libc/include/libc_private.h Sun Aug 19 17:40:50 2018 (r338059) @@ -405,8 +405,6 @@ int __sys_futimens(int fd, const struct timespec *tim 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 *); Modified: head/sys/crypto/chacha20/chacha.c ============================================================================== --- head/sys/crypto/chacha20/chacha.c Sun Aug 19 17:36:50 2018 (r338058) +++ head/sys/crypto/chacha20/chacha.c Sun Aug 19 17:40:50 2018 (r338059) @@ -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 * 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,u 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,u 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,u } bytes -= 64; c += 64; +#ifndef KEYSTREAM_ONLY m += 64; +#endif } } Modified: head/sys/crypto/chacha20/chacha.h ============================================================================== --- head/sys/crypto/chacha20/chacha.h Sun Aug 19 17:36:50 2018 (r338058) +++ head/sys/crypto/chacha20/chacha.h Sun Aug 19 17:40:50 2018 (r338059) @@ -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 */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201808191740.w7JHeoSj052259>