mirror of
https://github.com/libevent/libevent.git
synced 2025-01-31 09:12:55 +08:00
Merge branch 'arc4seed'
This commit is contained in:
commit
601a3ff98c
146
arc4random.c
146
arc4random.c
@ -1,5 +1,6 @@
|
|||||||
/* Portable arc4random.c based on arc4random.c from OpenBSD.
|
/* Portable arc4random.c based on arc4random.c from OpenBSD.
|
||||||
* Portable version by Chris Davis, adapted for Libevent by Nick Mathewson
|
* Portable version by Chris Davis, adapted for Libevent by Nick Mathewson
|
||||||
|
* Copyright (c) 2010 Chris Davis, Niels Provos, and Nick Mathewson
|
||||||
*
|
*
|
||||||
* Note that in Libevent, this file isn't compiled directly. Instead,
|
* Note that in Libevent, this file isn't compiled directly. Instead,
|
||||||
* it's included from evutil_rand.c
|
* it's included from evutil_rand.c
|
||||||
@ -56,6 +57,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#include <sys/sysctl.h>
|
||||||
#endif
|
#endif
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -135,29 +137,20 @@ read_all(int fd, unsigned char *buf, size_t count)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* This is adapted from Tor's crypto_seed_rng() */
|
|
||||||
static int
|
|
||||||
arc4_seed(void)
|
|
||||||
{
|
|
||||||
unsigned char buf[ADD_ENTROPY];
|
|
||||||
|
|
||||||
/* local variables */
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
|
#define TRY_SEED_WIN32
|
||||||
|
static int
|
||||||
|
arc4_seed_win32(void)
|
||||||
|
{
|
||||||
|
/* This is adapted from Tor's crypto_seed_rng() */
|
||||||
static int provider_set = 0;
|
static int provider_set = 0;
|
||||||
static HCRYPTPROV provider;
|
static HCRYPTPROV provider;
|
||||||
#else
|
unsigned char buf[ADD_ENTROPY];
|
||||||
static const char *filenames[] = {
|
|
||||||
"/dev/srandom", "/dev/urandom", "/dev/random", NULL
|
|
||||||
};
|
|
||||||
int fd, i;
|
|
||||||
size_t n;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
if (!provider_set) {
|
if (!provider_set) {
|
||||||
if (!CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL,
|
if (!CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL,
|
||||||
CRYPT_VERIFYCONTEXT)) {
|
CRYPT_VERIFYCONTEXT)) {
|
||||||
if ((unsigned long)GetLastError() != (unsigned long)NTE_BAD_KEYSET)
|
if (GetLastError() != (DWORD)NTE_BAD_KEYSET)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
provider_set = 1;
|
provider_set = 1;
|
||||||
@ -168,7 +161,100 @@ arc4_seed(void)
|
|||||||
memset(buf, 0, sizeof(buf));
|
memset(buf, 0, sizeof(buf));
|
||||||
arc4_seeded_ok = 1;
|
arc4_seeded_ok = 1;
|
||||||
return 0;
|
return 0;
|
||||||
#else
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_EVENT_HAVE_SYS_SYSCTL_H)
|
||||||
|
#if _EVENT_HAVE_DECL_CTL_KERN && _EVENT_HAVE_DECL_KERN_RANDOM && _EVENT_HAVE_DECL_RANDOM_UUID
|
||||||
|
#define TRY_SEED_SYSCTL_LINUX
|
||||||
|
static int
|
||||||
|
arc4_seed_sysctl_linux(void)
|
||||||
|
{
|
||||||
|
/* Based on code by William Ahern, this function tries to use the
|
||||||
|
* RANDOM_UUID sysctl to get entropy from the kernel. This can work
|
||||||
|
* even if /dev/urandom is inaccessible for some reason (e.g., we're
|
||||||
|
* running in a chroot). */
|
||||||
|
int mib[] = { CTL_KERN, KERN_RANDOM, RANDOM_UUID };
|
||||||
|
unsigned char buf[ADD_ENTROPY];
|
||||||
|
size_t len, n;
|
||||||
|
int i, any_set;
|
||||||
|
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
|
||||||
|
for (len = 0; len < sizeof(buf); len += n) {
|
||||||
|
n = sizeof(buf) - len;
|
||||||
|
|
||||||
|
if (0 != sysctl(mib, 3, &buf[len], &n, NULL, 0))
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* make sure that the buffer actually got set. */
|
||||||
|
for (i=any_set=0; i<sizeof(buf); ++i) {
|
||||||
|
any_set |= buf[i];
|
||||||
|
}
|
||||||
|
if (!any_set)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
arc4_addrandom(buf, sizeof(buf));
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
arc4_seeded_ok = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if _EVENT_HAVE_DECL_CTL_KERN && _EVENT_HAVE_DECL_KERN_ARND
|
||||||
|
#define TRY_SEED_SYSCTL_BSD
|
||||||
|
static int
|
||||||
|
arc4_seed_sysctl_bsd(void)
|
||||||
|
{
|
||||||
|
/* Based on code from William Ahern and from OpenBSD, this function
|
||||||
|
* tries to use the KERN_ARND syscall to get entropy from the kernel.
|
||||||
|
* This can work even if /dev/urandom is inaccessible for some reason
|
||||||
|
* (e.g., we're running in a chroot). */
|
||||||
|
int mib[] = { CTL_KERN, KERN_ARND };
|
||||||
|
unsigned char buf[ADD_ENTROPY];
|
||||||
|
size_t len, n;
|
||||||
|
int i, any_set;
|
||||||
|
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
|
||||||
|
len = sizeof(buf);
|
||||||
|
if (sysctl(mib, 2, buf, &len, NULL, 0) == -1) {
|
||||||
|
for (len = 0; len < sizeof(buf); len += sizeof(unsigned)) {
|
||||||
|
n = sizeof(unsigned);
|
||||||
|
if (n + len > sizeof(buf))
|
||||||
|
n = len - sizeof(buf);
|
||||||
|
if (sysctl(mib, 2, &buf[len], &n, NULL, 0) == -1)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* make sure that the buffer actually got set. */
|
||||||
|
for (i=any_set=0; i<sizeof(buf); ++i) {
|
||||||
|
any_set |= buf[i];
|
||||||
|
}
|
||||||
|
if (!any_set)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
arc4_addrandom(buf, sizeof(buf));
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
arc4_seeded_ok = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif /* defined(_EVENT_HAVE_SYS_SYSCTL_H) */
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
#define TRY_SEED_URANDOM
|
||||||
|
static int
|
||||||
|
arc4_seed_urandom(void)
|
||||||
|
{
|
||||||
|
/* This is adapted from Tor's crypto_seed_rng() */
|
||||||
|
static const char *filenames[] = {
|
||||||
|
"/dev/srandom", "/dev/urandom", "/dev/random", NULL
|
||||||
|
};
|
||||||
|
unsigned char buf[ADD_ENTROPY];
|
||||||
|
int fd, i;
|
||||||
|
size_t n;
|
||||||
|
|
||||||
for (i = 0; filenames[i]; ++i) {
|
for (i = 0; filenames[i]; ++i) {
|
||||||
fd = open(filenames[i], O_RDONLY, 0);
|
fd = open(filenames[i], O_RDONLY, 0);
|
||||||
if (fd<0)
|
if (fd<0)
|
||||||
@ -184,7 +270,33 @@ arc4_seed(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static int
|
||||||
|
arc4_seed(void)
|
||||||
|
{
|
||||||
|
int ok = 0;
|
||||||
|
/* We try every method that might work, and don't give up even if one
|
||||||
|
* does seem to work. There's no real harm in over-seeding, and if
|
||||||
|
* one of these sources turns out to be broken, that would be bad. */
|
||||||
|
#ifdef TRY_SEED_WIN32
|
||||||
|
if (0 == arc4_seed_win32())
|
||||||
|
ok = 1;
|
||||||
|
#endif
|
||||||
|
#ifdef TRY_SEED_SYSCTL_LINUX
|
||||||
|
if (0 == arc4_seed_sysctl_linux())
|
||||||
|
ok = 1;
|
||||||
|
#endif
|
||||||
|
#ifdef TRY_SEED_SYSCTL_BSD
|
||||||
|
if (0 == arc4_seed_sysctl_bsd())
|
||||||
|
ok = 1;
|
||||||
|
#endif
|
||||||
|
#ifdef TRY_SEED_URANDOM
|
||||||
|
if (0 == arc4_seed_urandom())
|
||||||
|
ok = 1;
|
||||||
|
#endif
|
||||||
|
return ok ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
11
configure.in
11
configure.in
@ -46,7 +46,7 @@ AC_ARG_ENABLE(debug-mode,
|
|||||||
AC_PROG_LIBTOOL
|
AC_PROG_LIBTOOL
|
||||||
|
|
||||||
dnl Uncomment "AC_DISABLE_SHARED" to make shared librraries not get
|
dnl Uncomment "AC_DISABLE_SHARED" to make shared librraries not get
|
||||||
dnl built by default. You can also turn shared libs on and off from
|
dnl built by default. You can also turn shared libs on and off from
|
||||||
dnl the command line with --enable-shared and --disable-shared.
|
dnl the command line with --enable-shared and --disable-shared.
|
||||||
dnl AC_DISABLE_SHARED
|
dnl AC_DISABLE_SHARED
|
||||||
AC_SUBST(LIBTOOL_DEPS)
|
AC_SUBST(LIBTOOL_DEPS)
|
||||||
@ -86,7 +86,7 @@ AC_SUBST(OPENSSL_LIBS)
|
|||||||
|
|
||||||
dnl Checks for header files.
|
dnl Checks for header files.
|
||||||
AC_HEADER_STDC
|
AC_HEADER_STDC
|
||||||
AC_CHECK_HEADERS(fcntl.h stdarg.h inttypes.h stdint.h stddef.h poll.h unistd.h sys/epoll.h sys/time.h sys/queue.h sys/event.h sys/param.h sys/ioctl.h sys/select.h sys/devpoll.h port.h netinet/in.h netinet/in6.h sys/socket.h sys/uio.h arpa/inet.h sys/eventfd.h sys/mman.h sys/sendfile.h netdb.h)
|
AC_CHECK_HEADERS(fcntl.h stdarg.h inttypes.h stdint.h stddef.h poll.h unistd.h sys/epoll.h sys/time.h sys/queue.h sys/event.h sys/param.h sys/ioctl.h sys/select.h sys/devpoll.h port.h netinet/in.h netinet/in6.h sys/socket.h sys/uio.h arpa/inet.h sys/eventfd.h sys/mman.h sys/sendfile.h netdb.h sys/sysctl.h)
|
||||||
if test "x$ac_cv_header_sys_queue_h" = "xyes"; then
|
if test "x$ac_cv_header_sys_queue_h" = "xyes"; then
|
||||||
AC_MSG_CHECKING(for TAILQ_FOREACH in sys/queue.h)
|
AC_MSG_CHECKING(for TAILQ_FOREACH in sys/queue.h)
|
||||||
AC_EGREP_CPP(yes,
|
AC_EGREP_CPP(yes,
|
||||||
@ -158,6 +158,13 @@ if test "x$ac_cv_header_sys_time_h" = "xyes"; then
|
|||||||
)
|
)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if test "x$ac_cv_header_sys_sysctl_h" = "xyes"; then
|
||||||
|
AC_CHECK_DECLS([CTL_KERN, KERN_RANDOM, RANDOM_UUID, KERN_ARND], [], [],
|
||||||
|
[[#include <sys/types.h>
|
||||||
|
#include <sys/sysctl.h>]]
|
||||||
|
)
|
||||||
|
fi
|
||||||
|
|
||||||
dnl - check if the macro WIN32 is defined on this compiler.
|
dnl - check if the macro WIN32 is defined on this compiler.
|
||||||
dnl - (this is how we check for a windows version of GCC)
|
dnl - (this is how we check for a windows version of GCC)
|
||||||
AC_MSG_CHECKING(for WIN32)
|
AC_MSG_CHECKING(for WIN32)
|
||||||
|
@ -43,6 +43,8 @@
|
|||||||
int
|
int
|
||||||
evutil_secure_rng_init(void)
|
evutil_secure_rng_init(void)
|
||||||
{
|
{
|
||||||
|
/* call arc4random() now to force it to self-initialize */
|
||||||
|
(void) arc4random();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -532,8 +532,38 @@ const char *evutil_gai_strerror(int err);
|
|||||||
*/
|
*/
|
||||||
void evutil_secure_rng_get_bytes(void *buf, size_t n);
|
void evutil_secure_rng_get_bytes(void *buf, size_t n);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Seed the secure random number generator if needed, and return 0 on
|
||||||
|
* success or -1 on failure.
|
||||||
|
*
|
||||||
|
* It is okay to call this function more than once; it will still return
|
||||||
|
* 0 if the RNG has been successfully seeded and -1 if it can't be
|
||||||
|
* seeded.
|
||||||
|
*
|
||||||
|
* Ordinarily you don't need to call this function from your own code;
|
||||||
|
* Libevent will seed the RNG itself the first time it needs good random
|
||||||
|
* numbers. You only need to call it if (a) you want to double-check
|
||||||
|
* that one of the seeding methods did succeed, or (b) you plan to drop
|
||||||
|
* the capability to seed (by chrooting, or dropping capabilities, or
|
||||||
|
* whatever), and you want to make sure that seeding happens before your
|
||||||
|
* program loses the ability to do it.
|
||||||
|
*/
|
||||||
int evutil_secure_rng_init(void);
|
int evutil_secure_rng_init(void);
|
||||||
|
|
||||||
|
/** Seed the random number generator with extra random bytes.
|
||||||
|
|
||||||
|
You should almost never need to call this function; it should be
|
||||||
|
sufficient to invoke evutil_secure_rng_init(), or let Libevent take
|
||||||
|
care of calling evutil_secure_rng_init() on its own.
|
||||||
|
|
||||||
|
If you call this function as a _replacement_ for the regular
|
||||||
|
entropy sources, then you need to be sure that your input
|
||||||
|
contains a fairly large amount of strong entropy. Doing so is
|
||||||
|
notoriously hard: most people who try get it wrong. Watch out!
|
||||||
|
|
||||||
|
@param dat a buffer full of a strong source of random numbers
|
||||||
|
@param datlen the number of bytes to read from datlen
|
||||||
|
*/
|
||||||
void evutil_secure_rng_add_bytes(const char *dat, size_t datlen);
|
void evutil_secure_rng_add_bytes(const char *dat, size_t datlen);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
Loading…
x
Reference in New Issue
Block a user