Remove multi-thread support from arc4random.
Sudo is not multi-threaded so we don't need the added complexity.
This commit is contained in:
1
MANIFEST
1
MANIFEST
@@ -110,7 +110,6 @@ lib/logsrv/protobuf-c.c
|
|||||||
lib/util/Makefile.in
|
lib/util/Makefile.in
|
||||||
lib/util/aix.c
|
lib/util/aix.c
|
||||||
lib/util/arc4random.c
|
lib/util/arc4random.c
|
||||||
lib/util/arc4random.h
|
|
||||||
lib/util/arc4random_uniform.c
|
lib/util/arc4random_uniform.c
|
||||||
lib/util/cfmakeraw.c
|
lib/util/cfmakeraw.c
|
||||||
lib/util/chacha_private.h
|
lib/util/chacha_private.h
|
||||||
|
@@ -442,12 +442,12 @@ aix.i: $(srcdir)/aix.c $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
|
|||||||
aix.plog: aix.i
|
aix.plog: aix.i
|
||||||
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/aix.c --i-file $< --output-file $@
|
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/aix.c --i-file $< --output-file $@
|
||||||
arc4random.lo: $(srcdir)/arc4random.c $(incdir)/sudo_compat.h \
|
arc4random.lo: $(srcdir)/arc4random.c $(incdir)/sudo_compat.h \
|
||||||
$(incdir)/sudo_rand.h $(srcdir)/arc4random.h \
|
$(incdir)/sudo_rand.h $(srcdir)/chacha_private.h \
|
||||||
$(srcdir)/chacha_private.h $(top_builddir)/config.h
|
$(top_builddir)/config.h
|
||||||
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/arc4random.c
|
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/arc4random.c
|
||||||
arc4random.i: $(srcdir)/arc4random.c $(incdir)/sudo_compat.h \
|
arc4random.i: $(srcdir)/arc4random.c $(incdir)/sudo_compat.h \
|
||||||
$(incdir)/sudo_rand.h $(srcdir)/arc4random.h \
|
$(incdir)/sudo_rand.h $(srcdir)/chacha_private.h \
|
||||||
$(srcdir)/chacha_private.h $(top_builddir)/config.h
|
$(top_builddir)/config.h
|
||||||
$(CC) -E -o $@ $(CPPFLAGS) $<
|
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||||
arc4random.plog: arc4random.i
|
arc4random.plog: arc4random.i
|
||||||
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/arc4random.c --i-file $< --output-file $@
|
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/arc4random.c --i-file $< --output-file $@
|
||||||
|
@@ -60,32 +60,26 @@
|
|||||||
|
|
||||||
#define minimum(a, b) ((a) < (b) ? (a) : (b))
|
#define minimum(a, b) ((a) < (b) ? (a) : (b))
|
||||||
|
|
||||||
#if defined(__GNUC__) || defined(_MSC_VER)
|
#ifdef __GNUC__
|
||||||
#define inline __inline
|
# define inline __inline
|
||||||
#else /* __GNUC__ || _MSC_VER */
|
#else /* !__GNUC__ */
|
||||||
#define inline
|
# define inline
|
||||||
#endif /* !__GNUC__ && !_MSC_VER */
|
#endif /* !__GNUC__ */
|
||||||
|
|
||||||
|
/* Sudo isn't multithreaded */
|
||||||
|
#define _ARC4_LOCK()
|
||||||
|
#define _ARC4_UNLOCK()
|
||||||
|
|
||||||
#define KEYSZ 32
|
#define KEYSZ 32
|
||||||
#define IVSZ 8
|
#define IVSZ 8
|
||||||
#define BLOCKSZ 64
|
#define BLOCKSZ 64
|
||||||
#define RSBUFSZ (16*BLOCKSZ)
|
#define RSBUFSZ (16*BLOCKSZ)
|
||||||
|
static int rs_initialized;
|
||||||
/* Marked MAP_INHERIT_ZERO, so zero'd out in fork children. */
|
static pid_t rs_stir_pid;
|
||||||
static struct _rs {
|
static chacha_ctx rs; /* chacha context for random keystream */
|
||||||
size_t rs_have; /* valid bytes at end of rs_buf */
|
static u_char rs_buf[RSBUFSZ]; /* keystream blocks */
|
||||||
size_t rs_count; /* bytes till reseed */
|
static size_t rs_have; /* valid bytes at end of rs_buf */
|
||||||
} *rs;
|
static size_t rs_count; /* bytes till reseed */
|
||||||
|
|
||||||
/* Maybe be preserved in fork children, if _rs_allocate() decides. */
|
|
||||||
static struct _rsx {
|
|
||||||
chacha_ctx rs_chacha; /* chacha context for random keystream */
|
|
||||||
unsigned char rs_buf[RSBUFSZ]; /* keystream blocks */
|
|
||||||
} *rsx;
|
|
||||||
|
|
||||||
static inline int _rs_allocate(struct _rs **, struct _rsx **);
|
|
||||||
static inline void _rs_forkdetect(void);
|
|
||||||
#include "arc4random.h"
|
|
||||||
|
|
||||||
static inline void _rs_rekey(unsigned char *dat, size_t datlen);
|
static inline void _rs_rekey(unsigned char *dat, size_t datlen);
|
||||||
|
|
||||||
@@ -94,14 +88,8 @@ _rs_init(unsigned char *buf, size_t n)
|
|||||||
{
|
{
|
||||||
if (n < KEYSZ + IVSZ)
|
if (n < KEYSZ + IVSZ)
|
||||||
return;
|
return;
|
||||||
|
chacha_keysetup(&rs, buf, KEYSZ * 8, 0);
|
||||||
if (rs == NULL) {
|
chacha_ivsetup(&rs, buf + KEYSZ);
|
||||||
if (_rs_allocate(&rs, &rsx) == -1)
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
chacha_keysetup(&rsx->rs_chacha, buf, KEYSZ * 8, 0);
|
|
||||||
chacha_ivsetup(&rsx->rs_chacha, buf + KEYSZ);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -110,54 +98,54 @@ _rs_stir(void)
|
|||||||
unsigned char rnd[KEYSZ + IVSZ];
|
unsigned char rnd[KEYSZ + IVSZ];
|
||||||
|
|
||||||
if (getentropy(rnd, sizeof rnd) == -1)
|
if (getentropy(rnd, sizeof rnd) == -1)
|
||||||
_getentropy_fail();
|
raise(SIGKILL);
|
||||||
|
|
||||||
if (!rs)
|
if (!rs_initialized) {
|
||||||
|
rs_initialized = 1;
|
||||||
_rs_init(rnd, sizeof(rnd));
|
_rs_init(rnd, sizeof(rnd));
|
||||||
else
|
} else
|
||||||
_rs_rekey(rnd, sizeof(rnd));
|
_rs_rekey(rnd, sizeof(rnd));
|
||||||
memset_s(rnd, sizeof(rnd), 0, sizeof(rnd)); /* discard source seed */
|
memset_s(rnd, sizeof(rnd), 0, sizeof(rnd)); /* discard source seed */
|
||||||
|
|
||||||
/* invalidate rs_buf */
|
/* invalidate rs_buf */
|
||||||
rs->rs_have = 0;
|
rs_have = 0;
|
||||||
memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf));
|
memset(rs_buf, 0, sizeof(rs_buf));
|
||||||
|
|
||||||
rs->rs_count = 1600000;
|
rs_count = 1600000;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
_rs_stir_if_needed(size_t len)
|
_rs_stir_if_needed(size_t len)
|
||||||
{
|
{
|
||||||
_rs_forkdetect();
|
pid_t pid = getpid();
|
||||||
if (!rs || rs->rs_count <= len)
|
|
||||||
|
if (rs_count <= len || !rs_initialized || rs_stir_pid != pid) {
|
||||||
|
rs_stir_pid = pid;
|
||||||
_rs_stir();
|
_rs_stir();
|
||||||
if (rs->rs_count <= len)
|
} else
|
||||||
rs->rs_count = 0;
|
rs_count -= len;
|
||||||
else
|
|
||||||
rs->rs_count -= len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
_rs_rekey(unsigned char *dat, size_t datlen)
|
_rs_rekey(unsigned char *dat, size_t datlen)
|
||||||
{
|
{
|
||||||
#ifndef KEYSTREAM_ONLY
|
#ifndef KEYSTREAM_ONLY
|
||||||
memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf));
|
memset(rs_buf, 0, sizeof(rs_buf));
|
||||||
#endif
|
#endif
|
||||||
/* fill rs_buf with the keystream */
|
/* fill rs_buf with the keystream */
|
||||||
chacha_encrypt_bytes(&rsx->rs_chacha, rsx->rs_buf,
|
chacha_encrypt_bytes(&rs, rs_buf, rs_buf, sizeof(rs_buf));
|
||||||
rsx->rs_buf, sizeof(rsx->rs_buf));
|
|
||||||
/* mix in optional user provided data */
|
/* mix in optional user provided data */
|
||||||
if (dat) {
|
if (dat) {
|
||||||
size_t i, m;
|
size_t i, m;
|
||||||
|
|
||||||
m = minimum(datlen, KEYSZ + IVSZ);
|
m = minimum(datlen, KEYSZ + IVSZ);
|
||||||
for (i = 0; i < m; i++)
|
for (i = 0; i < m; i++)
|
||||||
rsx->rs_buf[i] ^= dat[i];
|
rs_buf[i] ^= dat[i];
|
||||||
}
|
}
|
||||||
/* immediately reinit for backtracking resistance */
|
/* immediately reinit for backtracking resistance */
|
||||||
_rs_init(rsx->rs_buf, KEYSZ + IVSZ);
|
_rs_init(rs_buf, KEYSZ + IVSZ);
|
||||||
memset(rsx->rs_buf, 0, KEYSZ + IVSZ);
|
memset(rs_buf, 0, KEYSZ + IVSZ);
|
||||||
rs->rs_have = sizeof(rsx->rs_buf) - KEYSZ - IVSZ;
|
rs_have = sizeof(rs_buf) - KEYSZ - IVSZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef notdef
|
#ifdef notdef
|
||||||
@@ -170,17 +158,16 @@ _rs_random_buf(void *_buf, size_t n)
|
|||||||
|
|
||||||
_rs_stir_if_needed(n);
|
_rs_stir_if_needed(n);
|
||||||
while (n > 0) {
|
while (n > 0) {
|
||||||
if (rs->rs_have > 0) {
|
if (rs_have > 0) {
|
||||||
m = minimum(n, rs->rs_have);
|
m = minimum(n, rs_have);
|
||||||
keystream = rsx->rs_buf + sizeof(rsx->rs_buf)
|
keystream = rs_buf + sizeof(rs_buf) - rs_have;
|
||||||
- rs->rs_have;
|
|
||||||
memcpy(buf, keystream, m);
|
memcpy(buf, keystream, m);
|
||||||
memset(keystream, 0, m);
|
memset(keystream, 0, m);
|
||||||
buf += m;
|
buf += m;
|
||||||
n -= m;
|
n -= m;
|
||||||
rs->rs_have -= m;
|
rs_have -= m;
|
||||||
}
|
}
|
||||||
if (rs->rs_have == 0)
|
if (rs_have == 0)
|
||||||
_rs_rekey(NULL, 0);
|
_rs_rekey(NULL, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -192,12 +179,12 @@ _rs_random_u32(uint32_t *val)
|
|||||||
unsigned char *keystream;
|
unsigned char *keystream;
|
||||||
|
|
||||||
_rs_stir_if_needed(sizeof(*val));
|
_rs_stir_if_needed(sizeof(*val));
|
||||||
if (rs->rs_have < sizeof(*val))
|
if (rs_have < sizeof(*val))
|
||||||
_rs_rekey(NULL, 0);
|
_rs_rekey(NULL, 0);
|
||||||
keystream = rsx->rs_buf + sizeof(rsx->rs_buf) - rs->rs_have;
|
keystream = rs_buf + sizeof(rs_buf) - rs_have;
|
||||||
memcpy(val, keystream, sizeof(*val));
|
memcpy(val, keystream, sizeof(*val));
|
||||||
memset(keystream, 0, sizeof(*val));
|
memset(keystream, 0, sizeof(*val));
|
||||||
rs->rs_have -= sizeof(*val);
|
rs_have -= sizeof(*val);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
|
@@ -1,109 +0,0 @@
|
|||||||
/* $OpenBSD: arc4random.h,v 1.4 2015/01/15 06:57:18 deraadt Exp $ */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* SPDX-License-Identifier: ISC
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Stub functions for portability.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/mman.h>
|
|
||||||
|
|
||||||
#include <signal.h>
|
|
||||||
#ifdef HAVE_PTHREAD_H
|
|
||||||
#include <pthread.h>
|
|
||||||
|
|
||||||
static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
|
|
||||||
#define _ARC4_LOCK() pthread_mutex_lock(&arc4random_mtx)
|
|
||||||
#define _ARC4_UNLOCK() pthread_mutex_unlock(&arc4random_mtx)
|
|
||||||
#else
|
|
||||||
#define _ARC4_LOCK()
|
|
||||||
#define _ARC4_UNLOCK()
|
|
||||||
#endif /* HAVE_PTHREAD_H */
|
|
||||||
|
|
||||||
#ifdef HAVE_PTHREAD_ATFORK
|
|
||||||
# define _ARC4_ATFORK(f) pthread_atfork(NULL, NULL, (f))
|
|
||||||
# else
|
|
||||||
# define _ARC4_ATFORK(f)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(MAP_ANON) && defined(MAP_ANONYMOUS)
|
|
||||||
# define MAP_ANON MAP_ANONYMOUS
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
_getentropy_fail(void)
|
|
||||||
{
|
|
||||||
raise(SIGKILL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static volatile sig_atomic_t _rs_forked;
|
|
||||||
|
|
||||||
#ifdef HAVE_PTHREAD_ATFORK
|
|
||||||
static inline void
|
|
||||||
_rs_forkhandler(void)
|
|
||||||
{
|
|
||||||
_rs_forked = 1;
|
|
||||||
}
|
|
||||||
#endif /* HAVE_PTHREAD_ATFORK */
|
|
||||||
|
|
||||||
static int wipeonfork;
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
_rs_forkdetect(void)
|
|
||||||
{
|
|
||||||
if (!wipeonfork) {
|
|
||||||
static pid_t _rs_pid = 0;
|
|
||||||
pid_t pid = getpid();
|
|
||||||
|
|
||||||
if (_rs_pid == 0 || _rs_pid != pid || _rs_forked) {
|
|
||||||
_rs_pid = pid;
|
|
||||||
_rs_forked = 0;
|
|
||||||
if (rs)
|
|
||||||
memset(rs, 0, sizeof(*rs));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int
|
|
||||||
_rs_allocate(struct _rs **rsp, struct _rsx **rsxp)
|
|
||||||
{
|
|
||||||
if ((*rsp = (void *)mmap(NULL, sizeof(**rsp), PROT_READ|PROT_WRITE,
|
|
||||||
MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
|
|
||||||
return (-1);
|
|
||||||
|
|
||||||
if ((*rsxp = (void *)mmap(NULL, sizeof(**rsxp), PROT_READ|PROT_WRITE,
|
|
||||||
MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) {
|
|
||||||
munmap((void *)*rsp, sizeof(**rsp));
|
|
||||||
*rsp = NULL;
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef MADV_WIPEONFORK
|
|
||||||
if (madvise (*rsp, sizeof(**rsp), MADV_WIPEONFORK) == 0 &&
|
|
||||||
madvise (*rsxp, sizeof(**rsxp), MADV_WIPEONFORK) == 0) {
|
|
||||||
wipeonfork = 1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
_ARC4_ATFORK(_rs_forkhandler);
|
|
||||||
return (0);
|
|
||||||
}
|
|
Reference in New Issue
Block a user