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 <pro...@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 <d...@uun.org>
  * Copyright (c) 2008, Damien Miller <d...@openbsd.org>
+ * Copyright (c) 2013, Markus Friedl <mar...@openbsd.org>
+ * Copyright (c) 2014, Theo de Raadt <dera...@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 <d...@uun.org>
+ * Copyright (c) 2008, Damien Miller <d...@openbsd.org>
+ * Copyright (c) 2013, Markus Friedl <mar...@openbsd.org>
+ * Copyright (c) 2014, Theo de Raadt <dera...@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 */
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to