mirror of
https://github.com/libexpat/libexpat.git
synced 2025-04-13 08:02:56 +00:00
Merge branch 'better-entropy' (pull request #30)
This commit is contained in:
commit
64f3cf982a
4 changed files with 184 additions and 17 deletions
|
@ -2,6 +2,13 @@ Release ??????????
|
|||
Security fixes:
|
||||
CVE-2016-9063 -- Detect integer overflow
|
||||
#25 More integer overflow detection (function poolGrow)
|
||||
Use high quality entropy for hash initialization:
|
||||
* arc4random_buf on BSD, systems with libbsd
|
||||
(when configured with --with-libbsd), CloudABI
|
||||
* RtlGenRandom on Windows XP / Server 2003 and later
|
||||
* getrandom on Linux 3.17+
|
||||
In a way, that's still part of CVE-2016-5300.
|
||||
For run-time debug output, EXPAT_ENTROPY_DEBUG=1 can be used.
|
||||
|
||||
Bug fixes:
|
||||
#539 Fix regression from fix to CVE-2016-0718 cutting off
|
||||
|
|
|
@ -124,7 +124,7 @@ LTFLAGS = --verbose
|
|||
COMPILE = $(CC) $(INCLUDES) $(CFLAGS) $(DEFS) $(CPPFLAGS)
|
||||
CXXCOMPILE = $(CXX) $(INCLUDES) $(CXXFLAGS) $(DEFS) $(CPPFLAGS)
|
||||
LTCOMPILE = $(LIBTOOL) $(LTFLAGS) --mode=compile $(COMPILE)
|
||||
LINK_LIB = $(LIBTOOL) $(LTFLAGS) --mode=link $(COMPILE) -no-undefined $(VSNFLAG) -rpath $(libdir) $(LDFLAGS) -o $@
|
||||
LINK_LIB = $(LIBTOOL) $(LTFLAGS) --mode=link $(COMPILE) -no-undefined $(VSNFLAG) -rpath $(libdir) $(LDFLAGS) @LIBS@ -o $@
|
||||
LINK_EXE = $(LIBTOOL) $(LTFLAGS) --mode=link $(COMPILE) $(LDFLAGS) -o $@
|
||||
LINK_CXX_EXE = $(LIBTOOL) $(LTFLAGS) --mode=link $(CXXCOMPILE) $(LDFLAGS) -o $@
|
||||
|
||||
|
|
|
@ -99,6 +99,69 @@ AC_C_CONST
|
|||
AC_TYPE_SIZE_T
|
||||
AC_CHECK_FUNCS(memmove bcopy)
|
||||
|
||||
|
||||
AC_ARG_WITH([libbsd], [
|
||||
AS_HELP_STRING([--with-libbsd], [utilize libbsd (for arc4random_buf)])
|
||||
], [], [with_libbsd=no])
|
||||
AS_IF([test "x${with_libbsd}" != xno], [
|
||||
AC_CHECK_LIB([bsd], [arc4random_buf], [], [
|
||||
AS_IF([test "x${with_libbsd}" = xyes], [
|
||||
AC_MSG_ERROR([Enforced use of libbsd cannot be satisfied.])
|
||||
])
|
||||
])
|
||||
])
|
||||
AC_MSG_CHECKING([for arc4random_buf (BSD or libbsd)])
|
||||
AC_LINK_IFELSE([AC_LANG_SOURCE([
|
||||
#include <stdlib.h> /* for arc4random_buf on BSD, for NULL */
|
||||
#if defined(HAVE_LIBBSD)
|
||||
# include <bsd/stdlib.h>
|
||||
#endif
|
||||
int main() {
|
||||
arc4random_buf(NULL, 0U);
|
||||
return 0;
|
||||
}
|
||||
])], [
|
||||
AC_DEFINE([HAVE_ARC4RANDOM_BUF], [1],
|
||||
[Define to 1 if you have the `arc4random_buf' function.])
|
||||
AC_MSG_RESULT([yes])
|
||||
], [
|
||||
AC_MSG_RESULT([no])
|
||||
])
|
||||
|
||||
|
||||
AC_MSG_CHECKING([for getrandom (Linux 3.17+, glibc 2.25+)])
|
||||
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
|
||||
#include <stdlib.h> /* for NULL */
|
||||
#include <sys/random.h>
|
||||
int main() {
|
||||
return getrandom(NULL, 0U, 0U);
|
||||
}
|
||||
])], [
|
||||
AC_DEFINE([HAVE_GETRANDOM], [1],
|
||||
[Define to 1 if you have the `getrandom' function.])
|
||||
AC_MSG_RESULT([yes])
|
||||
], [
|
||||
AC_MSG_RESULT([no])
|
||||
|
||||
AC_MSG_CHECKING([for syscall SYS_getrandom (Linux 3.17+)])
|
||||
AC_LINK_IFELSE([AC_LANG_SOURCE([
|
||||
#include <stdlib.h> /* for NULL */
|
||||
#include <unistd.h> /* for syscall */
|
||||
#include <sys/syscall.h> /* for SYS_getrandom */
|
||||
int main() {
|
||||
syscall(SYS_getrandom, NULL, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
])], [
|
||||
AC_DEFINE([HAVE_SYSCALL_GETRANDOM], [1],
|
||||
[Define to 1 if you have `syscall' and `SYS_getrandom'.])
|
||||
AC_MSG_RESULT([yes])
|
||||
], [
|
||||
AC_MSG_RESULT([no])
|
||||
])
|
||||
])
|
||||
|
||||
|
||||
dnl Only needed for xmlwf:
|
||||
AC_CHECK_HEADERS(fcntl.h unistd.h)
|
||||
AC_TYPE_OFF_T
|
||||
|
|
|
@ -2,10 +2,14 @@
|
|||
See the file COPYING for copying permission.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE /* syscall prototype */
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h> /* memset(), memcpy() */
|
||||
#include <assert.h>
|
||||
#include <limits.h> /* UINT_MAX */
|
||||
#include <stdio.h> /* fprintf */
|
||||
#include <stdlib.h> /* getenv */
|
||||
|
||||
#ifdef _WIN32
|
||||
#define getpid GetCurrentProcessId
|
||||
|
@ -697,6 +701,80 @@ static const XML_Char implicitContext[] = {
|
|||
ASCII_s, ASCII_p, ASCII_a, ASCII_c, ASCII_e, '\0'
|
||||
};
|
||||
|
||||
|
||||
#if defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
|
||||
# include <errno.h>
|
||||
|
||||
# if defined(HAVE_GETRANDOM)
|
||||
# include <sys/random.h> /* getrandom */
|
||||
# else
|
||||
# include <unistd.h> /* syscall */
|
||||
# include <sys/syscall.h> /* SYS_getrandom */
|
||||
# endif
|
||||
|
||||
/* Obtain entropy on Linux 3.17+ */
|
||||
static int
|
||||
writeRandomBytes_getrandom(void * target, size_t count) {
|
||||
int success = 0; /* full count bytes written? */
|
||||
size_t bytesWrittenTotal = 0;
|
||||
const unsigned int getrandomFlags = 0;
|
||||
|
||||
do {
|
||||
void * const currentTarget = (void*)((char*)target + bytesWrittenTotal);
|
||||
const size_t bytesToWrite = count - bytesWrittenTotal;
|
||||
|
||||
const int bytesWrittenMore =
|
||||
#if defined(HAVE_GETRANDOM)
|
||||
getrandom(currentTarget, bytesToWrite, getrandomFlags);
|
||||
#else
|
||||
syscall(SYS_getrandom, currentTarget, bytesToWrite, getrandomFlags);
|
||||
#endif
|
||||
|
||||
if (bytesWrittenMore > 0) {
|
||||
bytesWrittenTotal += bytesWrittenMore;
|
||||
if (bytesWrittenTotal >= count)
|
||||
success = 1;
|
||||
}
|
||||
} while (! success && (errno == EINTR || errno == EAGAIN));
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
#endif /* defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) */
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
typedef BOOLEAN (APIENTRY *RTLGENRANDOM_FUNC)(PVOID, ULONG);
|
||||
|
||||
/* Obtain entropy on Windows XP / Windows Server 2003 and later.
|
||||
* Hint on RtlGenRandom and the following article from libsodioum.
|
||||
*
|
||||
* Michael Howard: Cryptographically Secure Random number on Windows without using CryptoAPI
|
||||
* https://blogs.msdn.microsoft.com/michael_howard/2005/01/14/cryptographically-secure-random-number-on-windows-without-using-cryptoapi/
|
||||
*/
|
||||
static int
|
||||
writeRandomBytes_RtlGenRandom(void * target, size_t count) {
|
||||
int success = 0; /* full count bytes written? */
|
||||
const HMODULE advapi32 = LoadLibrary("ADVAPI32.DLL");
|
||||
|
||||
if (advapi32) {
|
||||
const RTLGENRANDOM_FUNC RtlGenRandom
|
||||
= (RTLGENRANDOM_FUNC)GetProcAddress(advapi32, "SystemFunction036");
|
||||
if (RtlGenRandom) {
|
||||
if (RtlGenRandom((PVOID)target, (ULONG)count) == TRUE) {
|
||||
success = 1;
|
||||
}
|
||||
}
|
||||
FreeLibrary(advapi32);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
||||
|
||||
static unsigned long
|
||||
gather_time_entropy(void)
|
||||
{
|
||||
|
@ -716,34 +794,53 @@ gather_time_entropy(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
#if defined(HAVE_ARC4RANDOM_BUF) && defined(HAVE_LIBBSD)
|
||||
# include <bsd/stdlib.h>
|
||||
#endif
|
||||
|
||||
static unsigned long
|
||||
ENTROPY_DEBUG(const char * label, unsigned long entropy) {
|
||||
const char * const EXPAT_ENTROPY_DEBUG = getenv("EXPAT_ENTROPY_DEBUG");
|
||||
if (EXPAT_ENTROPY_DEBUG && ! strcmp(EXPAT_ENTROPY_DEBUG, "1")) {
|
||||
fprintf(stderr, "Entropy: %s --> 0x%0*lx (%lu bytes)\n",
|
||||
label,
|
||||
(int)sizeof(unsigned long) * 2, entropy,
|
||||
sizeof(unsigned long));
|
||||
}
|
||||
return entropy;
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
generate_hash_secret_salt(XML_Parser parser)
|
||||
{
|
||||
#if defined(__UINTPTR_TYPE__)
|
||||
# define PARSER_CAST(p) (__UINTPTR_TYPE__)(p)
|
||||
#elif defined(_WIN64) && defined(_MSC_VER)
|
||||
# define PARSER_CAST(p) (unsigned __int64)(p)
|
||||
#else
|
||||
# define PARSER_CAST(p) (p)
|
||||
#endif
|
||||
|
||||
#ifdef __CloudABI__
|
||||
unsigned long entropy;
|
||||
(void)parser;
|
||||
#if defined(HAVE_ARC4RANDOM_BUF) || defined(__CloudABI__)
|
||||
(void)gather_time_entropy;
|
||||
arc4random_buf(&entropy, sizeof(entropy));
|
||||
return entropy;
|
||||
return ENTROPY_DEBUG("arc4random_buf", entropy);
|
||||
#else
|
||||
/* Process ID is 0 bits entropy if attacker has local access
|
||||
* XML_Parser address is few bits of entropy if attacker has local access */
|
||||
const unsigned long entropy =
|
||||
gather_time_entropy() ^ getpid() ^ (unsigned long)PARSER_CAST(parser);
|
||||
/* Try high quality providers first .. */
|
||||
#ifdef _WIN32
|
||||
if (writeRandomBytes_RtlGenRandom((void *)&entropy, sizeof(entropy))) {
|
||||
return ENTROPY_DEBUG("RtlGenRandom", entropy);
|
||||
}
|
||||
#elif defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
|
||||
if (writeRandomBytes_getrandom((void *)&entropy, sizeof(entropy))) {
|
||||
return ENTROPY_DEBUG("getrandom", entropy);
|
||||
}
|
||||
#endif
|
||||
/* .. and self-made low quality for backup: */
|
||||
|
||||
/* Process ID is 0 bits entropy if attacker has local access */
|
||||
entropy = gather_time_entropy() ^ getpid();
|
||||
|
||||
/* Factors are 2^31-1 and 2^61-1 (Mersenne primes M31 and M61) */
|
||||
if (sizeof(unsigned long) == 4) {
|
||||
return entropy * 2147483647;
|
||||
return ENTROPY_DEBUG("fallback(4)", entropy * 2147483647);
|
||||
} else {
|
||||
return entropy * (unsigned long)2305843009213693951;
|
||||
return ENTROPY_DEBUG("fallback(8)",
|
||||
entropy * (unsigned long)2305843009213693951);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue