From 87765bace9be7d8105b3d148dd389a612299275b Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Sun, 3 Sep 2023 09:35:28 -0400 Subject: [PATCH] Move random number device check to runtime (fixes #1022) Having it at compile time breaks cross-compilation and isn't really right anyway. --- ChangeLog | 7 +++++++ libqpdf/CMakeLists.txt | 2 -- libqpdf/SecureRandomDataProvider.cc | 29 ++++++++++++++++------------- libqpdf/qpdf/qpdf-config.h.in | 3 --- 4 files changed, 23 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2c2bb836..8362c189 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2023-09-03 Jay Berkenbilt + + * Move check for random number device to runtime instead of + compile time. Since, by default, the crypto provider provides + random numbers, runtime determinination of a random number device + is usually not needed. Fixes #1022. + 2023-09-02 Jay Berkenbilt * Bug fix from M. Holger: allow fix-qdf to read from pipe. Fixes #1010. diff --git a/libqpdf/CMakeLists.txt b/libqpdf/CMakeLists.txt index fbe85cf9..c6a122c6 100644 --- a/libqpdf/CMakeLists.txt +++ b/libqpdf/CMakeLists.txt @@ -320,8 +320,6 @@ check_symbol_exists(fseeko "stdio.h" HAVE_FSEEKO) check_symbol_exists(fseeko64 "stdio.h" HAVE_FSEEKO64) check_symbol_exists(localtime_r "time.h" HAVE_LOCALTIME_R) check_symbol_exists(random "stdlib.h" HAVE_RANDOM) -find_file(RANDOM_DEVICE - "urandom" "arandom" "arandom" PATHS "/dev" NO_DEFAULT_PATH) check_c_source_compiles( "#include diff --git a/libqpdf/SecureRandomDataProvider.cc b/libqpdf/SecureRandomDataProvider.cc index 64199903..e5007d62 100644 --- a/libqpdf/SecureRandomDataProvider.cc +++ b/libqpdf/SecureRandomDataProvider.cc @@ -87,24 +87,27 @@ SecureRandomDataProvider::provideRandomData(unsigned char* data, size_t len) throw std::runtime_error("unable to generate secure random data"); } -# elif defined(RANDOM_DEVICE) +# else + static std::unique_ptr random_device = []() { + FILE* f = fopen("/dev/urandom", "rb"); + if (f == nullptr) { + f = fopen("/dev/arandom", "rb"); + } + if (f == nullptr) { + f = fopen("/dev/random", "rb"); + } + if (f == nullptr) { + throw std::runtime_error("unable to find device in /dev for generating random numbers"); + } + return std::make_unique(f); + }(); - // Optimization: wrap the file open and close in a class so that the file is closed in a - // destructor, then make this static to keep the file handle open. Only do this if it can be - // done in a thread-safe fashion. - FILE* f = QUtil::safe_fopen(RANDOM_DEVICE, "rb"); - size_t fr = fread(data, 1, len, f); - fclose(f); + size_t fr = fread(data, 1, len, random_device->f); if (fr != len) { throw std::runtime_error( - "unable to read " + std::to_string(len) + " bytes from " + std::string(RANDOM_DEVICE)); + "unable to read " + std::to_string(len) + " bytes from random number device"); } -# else - -# error \ - "Don't know how to generate secure random numbers on this platform. See random number generation in the top-level README.md" - # endif } diff --git a/libqpdf/qpdf/qpdf-config.h.in b/libqpdf/qpdf/qpdf-config.h.in index 691a27e6..ff054788 100644 --- a/libqpdf/qpdf/qpdf-config.h.in +++ b/libqpdf/qpdf/qpdf-config.h.in @@ -24,8 +24,5 @@ #cmakedefine HAVE_MALLOC_INFO 1 #cmakedefine HAVE_OPEN_MEMSTREAM 1 -/* system random device (e.g. /dev/random) if any */ -#cmakedefine RANDOM_DEVICE "${RANDOM_DEVICE}" - /* bytes in the size_t type */ #cmakedefine SIZEOF_SIZE_T ${SIZEOF_SIZE_T}