diff --git a/src/httpfetch.cpp b/src/httpfetch.cpp index ccb36b3f6..13daaefb6 100644 --- a/src/httpfetch.cpp +++ b/src/httpfetch.cpp @@ -16,14 +16,13 @@ #include "porting.h" #include "util/container.h" #include "util/thread.h" +#include "util/numeric.h" #include "version.h" #include "settings.h" -#include "noise.h" static std::mutex g_httpfetch_mutex; static std::unordered_map> g_httpfetch_results; -static PcgRandom g_callerid_randomness; static std::string default_user_agent() { @@ -78,18 +77,18 @@ u64 httpfetch_caller_alloc_secure() // Generate random caller IDs and make sure they're not // already used or reserved. // Give up after 100 tries to prevent infinite loop - size_t tries = 100; + int tries = 100; u64 caller; do { - caller = (((u64) g_callerid_randomness.next()) << 32) | - g_callerid_randomness.next(); + // Global RNG is seeded securely, so we can use it. + myrand_bytes(&caller, sizeof(caller)); if (--tries < 1) { FATAL_ERROR("httpfetch_caller_alloc_secure: ran out of caller IDs"); return HTTPFETCH_DISCARD; } - } while (caller >= HTTPFETCH_CID_START && + } while (caller < HTTPFETCH_CID_START || g_httpfetch_results.find(caller) != g_httpfetch_results.end()); verbosestream << "httpfetch_caller_alloc_secure: allocating " @@ -702,11 +701,6 @@ void httpfetch_init(int parallel_limit) FATAL_ERROR_IF(res != CURLE_OK, "cURL init failed"); g_httpfetch_thread = std::make_unique(parallel_limit); - - // Initialize g_callerid_randomness for httpfetch_caller_alloc_secure - u64 randbuf[2]; - porting::secure_rand_fill_buf(randbuf, sizeof(u64) * 2); - g_callerid_randomness = PcgRandom(randbuf[0], randbuf[1]); } void httpfetch_cleanup() diff --git a/src/main.cpp b/src/main.cpp index d3e698f33..d62ee1f21 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -700,12 +700,18 @@ static bool init_common(const Settings &cmd_args, int argc, char *argv[]) init_log_streams(cmd_args); // Initialize random seed - { - u32 seed = static_cast(time(nullptr)) << 16; - seed |= porting::getTimeUs() & 0xffff; - srand(seed); - mysrand(seed); + u64 seed; + if (!porting::secure_rand_fill_buf(&seed, sizeof(seed))) { + verbosestream << "Secure randomness not available to seed global RNG." << std::endl; + std::ostringstream oss; + // some stuff that's hard to predict: + oss << time(nullptr) << porting::getTimeUs() << argc << g_settings_path; + print_version(oss); + std::string data = oss.str(); + seed = murmur_hash_64_ua(data.c_str(), data.size(), 0xc0ffee); } + srand(seed); + mysrand(seed); // Initialize HTTP fetcher httpfetch_init(g_settings->getS32("curl_parallel_limit")); diff --git a/src/util/numeric.cpp b/src/util/numeric.cpp index ddc658cb3..59dd0a204 100644 --- a/src/util/numeric.cpp +++ b/src/util/numeric.cpp @@ -20,7 +20,7 @@ u32 myrand() return g_pcgrand.next(); } -void mysrand(unsigned int seed) +void mysrand(u64 seed) { g_pcgrand.seed(seed); } diff --git a/src/util/numeric.h b/src/util/numeric.h index cacb01621..b79ef2aef 100644 --- a/src/util/numeric.h +++ b/src/util/numeric.h @@ -244,7 +244,7 @@ inline float wrapDegrees_180(float f) */ #define MYRAND_RANGE 0xffffffff u32 myrand(); -void mysrand(unsigned int seed); +void mysrand(u64 seed); void myrand_bytes(void *out, size_t len); int myrand_range(int min, int max); float myrand_range(float min, float max);