From 2e9e758d1ecb52b73a43db79d326c18d7d94c8d7 Mon Sep 17 00:00:00 2001 From: Nick Wellnhofer Date: Sun, 24 Dec 2023 14:27:46 +0100 Subject: [PATCH] dict: Get random seed from system PRNG --- CMakeLists.txt | 6 +++++- config.h.cmake.in | 6 ++++++ configure.ac | 14 +++++++++++-- dict.c | 51 ++++++++++++++++++++++++++++++++++++++++------- 4 files changed, 67 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 53742945..e68f3684 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -137,6 +137,7 @@ if (NOT MSVC) check_include_files(fcntl.h HAVE_FCNTL_H) check_function_exists(fpclass HAVE_FPCLASS) check_function_exists(ftime HAVE_FTIME) + check_function_exists(getentropy HAVE_GETENTROPY) check_function_exists(gettimeofday HAVE_GETTIMEOFDAY) check_include_files(inttypes.h HAVE_INTTYPES_H) check_function_exists(isascii HAVE_ISASCII) @@ -151,6 +152,7 @@ if (NOT MSVC) check_function_exists(stat HAVE_STAT) check_include_files(stdint.h HAVE_STDINT_H) check_include_files(sys/mman.h HAVE_SYS_MMAN_H) + check_include_files(sys/random.h HAVE_SYS_RANDOM_H) check_include_files(sys/select.h HAVE_SYS_SELECT_H) check_include_files(sys/socket.h HAVE_SYS_SOCKET_H) check_include_files(sys/stat.h HAVE_SYS_STAT_H) @@ -358,6 +360,8 @@ endif() if(WIN32) target_link_libraries(LibXml2 PRIVATE ws2_32) set(WINSOCK_LIBS "-lws2_32") + target_link_libraries(LibXml2 PRIVATE bcrypt) + set(CRYPTO_LIBS "-lbcrypt") endif() if(LIBXML2_WITH_ICONV) @@ -641,7 +645,7 @@ if(LIBXML2_WITH_PYTHON) configure_file(python/setup.py.in setup.py @ONLY) endif() -set(NON_PC_LIBS "${THREAD_LIBS} ${ICONV_LIBS} ${LIBM} ${WINSOCK_LIBS}") +set(NON_PC_LIBS "${THREAD_LIBS} ${ICONV_LIBS} ${LIBM} ${WINSOCK_LIBS} ${CRYPTO_LIBS}") list(APPEND XML_PC_LIBS "${NON_PC_LIBS}") list(APPEND XML_PRIVATE_LIBS "${NON_PC_LIBS}") list(REMOVE_DUPLICATES XML_PC_LIBS) diff --git a/config.h.cmake.in b/config.h.cmake.in index 461e53a3..2c1f9117 100644 --- a/config.h.cmake.in +++ b/config.h.cmake.in @@ -22,6 +22,9 @@ /* Define to 1 if you have the `ftime' function. */ #cmakedefine HAVE_FTIME 1 +/* Define to 1 if you have the `getentropy' function. */ +#cmakedefine HAVE_GETENTROPY 1 + /* Define to 1 if you have the `gettimeofday' function. */ #cmakedefine HAVE_GETTIMEOFDAY 1 @@ -72,6 +75,9 @@ /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_MMAN_H 1 +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_RANDOM_H 1 + /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_SELECT_H 1 diff --git a/configure.ac b/configure.ac index 2326f9f0..15cc606f 100644 --- a/configure.ac +++ b/configure.ac @@ -300,6 +300,7 @@ AC_CHECK_HEADERS([sys/mman.h]) AC_CHECK_HEADERS([sys/socket.h netinet/in.h arpa/inet.h netdb.h]) AC_CHECK_HEADERS([sys/select.h poll.h]) AC_CHECK_HEADERS([sys/time.h sys/timeb.h]) +AC_CHECK_HEADERS([sys/random.h]) AC_CHECK_HEADERS([dl.h dlfcn.h]) AC_CHECK_HEADERS([glob.h]) AM_CONDITIONAL(WITH_GLOB, test "$ac_cv_header_glob_h" = "yes") @@ -310,7 +311,7 @@ dnl AC_TYPE_UINT32_T dnl Checks for library functions. -AC_CHECK_FUNCS([gettimeofday ftime stat isascii mmap munmap]) +AC_CHECK_FUNCS([getentropy gettimeofday ftime isascii stat mmap munmap]) AH_VERBATIM([HAVE_MUNMAP_AFTER],[/* mmap() is no good without munmap() */ #if defined(HAVE_MMAP) && !defined(HAVE_MUNMAP) @@ -1104,6 +1105,15 @@ else fi AC_SUBST(WITH_ICU) +dnl +dnl Crypto libraries +dnl +case "$host" in + *-*-mingw*) + CRYPTO_LIBS="-lbcrypt" + ;; +esac + if test "$with_coverage" = "yes" && test "${GCC}" = "yes" then echo Enabling code coverage for GCC @@ -1115,7 +1125,7 @@ fi XML_LIBS="-lxml2" XML_LIBTOOLLIBS="libxml2.la" -NON_PC_LIBS="${THREAD_LIBS} ${ICONV_LIBS} ${LIBM} ${NET_LIBS}" +NON_PC_LIBS="${THREAD_LIBS} ${ICONV_LIBS} ${LIBM} ${NET_LIBS} ${CRYPTO_LIBS}" XML_PC_LIBS="${XML_PC_LIBS} ${NON_PC_LIBS}" XML_PRIVATE_LIBS="${XML_PRIVATE_LIBS} ${NON_PC_LIBS}" XML_PRIVATE_CFLAGS="${XML_PRIVATE_CFLAGS} ${THREAD_CFLAGS} ${ICONV_CFLAGS}" diff --git a/dict.c b/dict.c index a0d311a2..fbfd2dfd 100644 --- a/dict.c +++ b/dict.c @@ -19,9 +19,20 @@ #define IN_LIBXML #include "libxml.h" +#include #include +#include #include #include +#ifdef HAVE_SYS_RANDOM_H +#include +#endif + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#include +#endif #include "private/dict.h" #include "private/threads.h" @@ -916,16 +927,42 @@ static XML_THREAD_LOCAL unsigned localRngState[2]; ATTRIBUTE_NO_SANITIZE_INTEGER void xmlInitRandom(void) { - int var; - xmlInitMutex(&xmlRngMutex); - /* TODO: Get seed values from system PRNG */ + { +#ifdef _WIN32 + NTSTATUS status; - globalRngState[0] = (unsigned) time(NULL) ^ - HASH_ROL((unsigned) ((size_t) &xmlInitRandom & 0xFFFFFFFF), 8); - globalRngState[1] = HASH_ROL((unsigned) ((size_t) &xmlRngMutex & 0xFFFFFFFF), 16) ^ - HASH_ROL((unsigned) ((size_t) &var & 0xFFFFFFFF), 24); + status = BCryptGenRandom(NULL, (unsigned char *) globalRngState, + sizeof(globalRngState), + BCRYPT_USE_SYSTEM_PREFERRED_RNG); + if (!BCRYPT_SUCCESS(status)) { + fprintf(stderr, "libxml2: BCryptGenRandom failed with " + "error code %lu\n", GetLastError()); + abort(); + } +#elif defined(HAVE_GETENTROPY) + while (1) { + if (getentropy(globalRngState, sizeof(globalRngState)) == 0) + break; + + if (errno != EINTR) { + fprintf(stderr, "libxml2: getentropy failed with " + "error code %d\n", errno); + abort(); + } + } +#else + int var; + + globalRngState[0] = + (unsigned) time(NULL) ^ + HASH_ROL((unsigned) ((size_t) &xmlInitRandom & 0xFFFFFFFF), 8); + globalRngState[1] = + HASH_ROL((unsigned) ((size_t) &xmlRngMutex & 0xFFFFFFFF), 16) ^ + HASH_ROL((unsigned) ((size_t) &var & 0xFFFFFFFF), 24); +#endif + } } void