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
This commit is contained in:
Xin LI 2018-08-19 17:40:50 +00:00
parent 38a13e9002
commit c1e80940f3
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=338059
16 changed files with 413 additions and 279 deletions

View file

@ -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

View file

@ -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
}

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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,

View file

@ -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

View file

@ -65,8 +65,6 @@ FBSD_1.0 {
pthread_testcancel;
alarm;
arc4random;
arc4random_addrandom;
arc4random_stir;
__assert;
check_utility_compat;
clock;

View file

@ -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);

View file

@ -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.

View file

@ -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 <stdlib.h>
#include <unistd.h>
#include <sys/param.h>
#include <sys/sysctl.h>
#include <sys/time.h>
#include <pthread.h>
#include <signal.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.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;
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 _rs_rekey(u_char *dat, size_t datlen);
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;
}
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 (getentropy(rnd, sizeof rnd) == -1)
_getentropy_fail();
if (!rs)
_rs_init(rnd, sizeof(rnd));
else
_rs_rekey(rnd, sizeof(rnd));
explicit_bzero(rnd, sizeof(rnd)); /* discard source seed */
/* invalidate rs_buf */
rs->rs_have = 0;
memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf));
rs->rs_count = 1600000;
}
static inline void
_rs_stir_if_needed(size_t len)
{
_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 void
_rs_rekey(u_char *dat, size_t datlen)
{
#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];
}
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;
/* 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 void
arc4_stir_if_needed(void)
{
pid_t pid = getpid();
if (arc4_count <= 0 || !rs_initialized || arc4_stir_pid != pid) {
arc4_stir_pid = pid;
arc4_stir();
}
}
static inline u_int8_t
arc4_getbyte(void)
{
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]);
}
static inline u_int32_t
arc4_getword(void)
{
u_int32_t val;
val = arc4_getbyte() << 24;
val |= arc4_getbyte() << 16;
val |= arc4_getbyte() << 8;
val |= arc4_getbyte();
return val;
}
void
arc4random_stir(void)
{
_ARC4_LOCK();
arc4_stir();
_ARC4_UNLOCK();
}
void
arc4random_addrandom(u_char *dat, int datlen)
{
_ARC4_LOCK();
if (!rs_initialized)
arc4_stir();
arc4_addrandom(dat, datlen);
_ARC4_UNLOCK();
}
u_int32_t
arc4random(void)
{
u_int32_t val;
_ARC4_LOCK();
arc4_count -= 4;
arc4_stir_if_needed();
val = arc4_getword();
_ARC4_UNLOCK();
return val;
}
void
arc4random_buf(void *_buf, size_t n)
static inline void
_rs_random_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();
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);
}
}
static inline void
_rs_random_u32(uint32_t *val)
{
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);
}
uint32_t
arc4random(void)
{
uint32_t val;
_ARC4_LOCK();
_rs_random_u32(&val);
_ARC4_UNLOCK();
return val;
}
void
arc4random_buf(void *buf, size_t n)
{
_ARC4_LOCK();
_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

74
lib/libc/gen/arc4random.h Normal file
View file

@ -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)
{
}

View file

@ -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);
/*

View file

@ -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 *);

View file

@ -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
}
}

View file

@ -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 */