From 23d07dae3815879cfdeae63e93613c6e00054a81 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Adrien=20B=C3=A9raud?= <>
Date: Sun, 10 Dec 2023 15:15:27 -0500
Subject: [PATCH] rng: drop custom random_device implementation for
 MinGW/Windows

MinGW now has std::random_device support on Windows:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85494
---
 include/opendht/crypto.h   |  2 +-
 include/opendht/infohash.h |  2 +-
 include/opendht/rng.h      | 87 +-------------------------------------
 src/crypto.cpp             | 10 ++---
 src/dht_proxy_client.cpp   |  2 +-
 src/securedht.cpp          |  2 +-
 tools/dhtchat.cpp          |  2 +-
 7 files changed, 12 insertions(+), 95 deletions(-)

diff --git a/include/opendht/crypto.h b/include/opendht/crypto.h
index c93129cd..67c95f1b 100644
--- a/include/opendht/crypto.h
+++ b/include/opendht/crypto.h
@@ -685,7 +685,7 @@ public:
 
     static secure_vector<T> getRandom(size_t size) {
         secure_vector<T> ret(size);
-        crypto::random_device rdev;
+        std::random_device rdev;
 #ifdef _WIN32
         std::uniform_int_distribution<int> rand_byte{ 0, std::numeric_limits<uint8_t>::max() };
 #else
diff --git a/include/opendht/infohash.h b/include/opendht/infohash.h
index fda05222..29e152a3 100644
--- a/include/opendht/infohash.h
+++ b/include/opendht/infohash.h
@@ -323,7 +323,7 @@ Hash<N>
 Hash<N>::getRandom()
 {
     Hash h;
-    crypto::random_device rdev;
+    std::random_device rdev;
     std::uniform_int_distribution<uint32_t> rand_int;
     auto a = reinterpret_cast<uint32_t*>(h.data());
     auto b = reinterpret_cast<uint32_t*>(h.data() + h.size());
diff --git a/include/opendht/rng.h b/include/opendht/rng.h
index 356c56b9..5c5414e1 100644
--- a/include/opendht/rng.h
+++ b/include/opendht/rng.h
@@ -27,96 +27,13 @@
 namespace dht {
 namespace crypto {
 
-#ifndef _MSC_VER
-#ifdef _WIN32
-
-/**
- * Hardware random number generator using Intel RDRAND/RDSEED,
- * API-compatible with std::random_device.
- */
-class random_device {
-public:
-    using result_type = std::random_device::result_type;
-    using pseudo_engine = std::mt19937_64;
-
-    /**
-     * Current implementation assumption : result_type must be of a size
-     * supported by Intel RDRAND/RDSEED.
-     * result_type is unsigned int so this is currently safe.
-     */
-    static_assert(
-        sizeof(result_type) == 2 ||
-        sizeof(result_type) == 4 ||
-        sizeof(result_type) == 8,
-        "result_type must be 16, 32 or 64 bits");
-
-    random_device();
-
-    result_type operator()();
-
-    static constexpr result_type min() {
-        return std::numeric_limits<result_type>::lowest();
-    }
-
-    static constexpr result_type max() {
-        return std::numeric_limits<result_type>::max();
-    }
-
-    double entropy() const {
-        if (hasRdrand() or hasRdseed())
-            return 1.;
-        return 0.;
-    }
-
-    static bool hasRdrand() {
-        static const bool hasrdrand = _hasRdrand();
-        return hasrdrand;
-    }
-
-    static bool hasRdseed() {
-        static const bool hasrdseed = _hasRdseed();
-        return hasrdseed;
-    }
-
-private:
-    random_device& operator=(random_device&) = delete;
-
-    pseudo_engine gen;
-    std::uniform_int_distribution<result_type> dis {};
-
-    static bool hasIntelCpu();
-    static bool _hasRdrand();
-    static bool _hasRdseed();
-
-    struct CPUIDinfo {
-        unsigned int EAX;
-        unsigned int EBX;
-        unsigned int ECX;
-        unsigned int EDX;
-        CPUIDinfo(const unsigned int func, const unsigned int subfunc);
-    };
-    bool rdrandStep(result_type* r);
-    bool rdrand(result_type* r);
-    bool rdseedStep(result_type* r);
-    bool rdseed(result_type* r);
-};
-
-#else
-
-using random_device = std::random_device;
-
-#endif
-#else
-using random_device = std::random_device;
-#endif
-
 /** 
  * Generate a seeded random engine.
  */
 template<class T = std::mt19937, std::size_t N = T::state_size+1>
 auto getSeededRandomEngine() -> typename std::enable_if<!!N, T>::type {
     std::array<typename T::result_type, N> random_data;
-    constexpr auto gen = [](random_device& source) -> typename T::result_type {
+    constexpr auto gen = [](std::random_device& source) -> typename T::result_type {
         for (unsigned j=0; j<64; j++) {
             try {
                 return source();
@@ -128,7 +45,7 @@ auto getSeededRandomEngine() -> typename std::enable_if<!!N, T>::type {
     };
     for (unsigned i=0; i<8; i++) {
         try {
-            random_device source;
+            std::random_device source;
             for (auto& r : random_data)
                 r = gen(source);
             std::seed_seq seed(
diff --git a/src/crypto.cpp b/src/crypto.cpp
index e097a2d9..4b6ee226 100644
--- a/src/crypto.cpp
+++ b/src/crypto.cpp
@@ -92,7 +92,7 @@ Blob aesEncrypt(const uint8_t* data, size_t data_length, const Blob& key)
 
     Blob ret(data_length + GCM_IV_SIZE + GCM_DIGEST_SIZE);
     {
-        crypto::random_device rdev;
+        std::random_device rdev;
         std::generate_n(ret.begin(), GCM_IV_SIZE, std::bind(rand_byte, std::ref(rdev)));
     }
     struct gcm_aes_ctx aes;
@@ -191,7 +191,7 @@ Blob stretchKey(std::string_view password, Blob& salt, size_t key_length)
 {
     if (salt.empty()) {
         salt.resize(PASSWORD_SALT_LENGTH);
-        crypto::random_device rdev;
+        std::random_device rdev;
         std::generate_n(salt.begin(), salt.size(), std::bind(rand_byte, std::ref(rdev)));
     }
     Blob res;
@@ -539,7 +539,7 @@ PublicKey::encrypt(const uint8_t* data, size_t data_len) const
         throw CryptoException("Key is not long enough for AES128");
     Blob key(aes_key_sz);
     {
-        crypto::random_device rdev;
+        std::random_device rdev;
         std::generate_n(key.begin(), key.size(), std::bind(rand_byte, std::ref(rdev)));
     }
     auto data_encrypted = aesEncrypt(data, data_len, key);
@@ -1193,7 +1193,7 @@ setValidityPeriod(gnutls_x509_crt_t cert, int64_t validity)
 void
 setRandomSerial(gnutls_x509_crt_t cert)
 {
-    random_device rdev;
+    std::random_device rdev;
     std::uniform_int_distribution<int64_t> dist{1};
     int64_t cert_serial = dist(rdev);
     gnutls_x509_crt_set_serial(cert, &cert_serial, sizeof(cert_serial));
@@ -1666,7 +1666,7 @@ RevocationList::sign(const PrivateKey& key, const Certificate& ca, duration vali
     if (number == 0) {
         // initialize to a random number
         number_sz = sizeof(number);
-        random_device rdev;
+        std::random_device rdev;
         std::generate_n((uint8_t*)&number, sizeof(number), std::bind(rand_byte, std::ref(rdev)));
     } else
         number = endian(endian(number) + 1);
diff --git a/src/dht_proxy_client.cpp b/src/dht_proxy_client.cpp
index e70615fd..d054423a 100644
--- a/src/dht_proxy_client.cpp
+++ b/src/dht_proxy_client.cpp
@@ -98,7 +98,7 @@ std::string
 getRandomSessionId(size_t length = 8) {
     static constexpr const char chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!#$%&()*+,./:;<=>?@[]^_`{|}~";
     std::string str(length, 0);
-    crypto::random_device rdev;
+    std::random_device rdev;
     std::uniform_int_distribution<> dist(0, (sizeof(chars)/sizeof(char)) - 2);
     std::generate_n( str.begin(), length, [&]{ return chars[dist(rdev)]; } );
     return str;
diff --git a/src/securedht.cpp b/src/securedht.cpp
index f7e145ad..9aca9fb4 100644
--- a/src/securedht.cpp
+++ b/src/securedht.cpp
@@ -337,7 +337,7 @@ SecureDht::putSigned(const InfoHash& hash, Sp<Value> val, DoneCallback callback,
         return;
     }
     if (val->id == Value::INVALID_ID) {
-        crypto::random_device rdev;
+        std::random_device rdev;
         std::uniform_int_distribution<Value::Id> rand_id;
         val->id = rand_id(rdev);
     }
diff --git a/tools/dhtchat.cpp b/tools/dhtchat.cpp
index c4590026..a1c6d8d4 100644
--- a/tools/dhtchat.cpp
+++ b/tools/dhtchat.cpp
@@ -30,7 +30,7 @@ extern "C" {
 
 using namespace dht;
 
-static std::mt19937_64 rd {dht::crypto::random_device{}()};
+static std::mt19937_64 rd {dht::crypto::getSeededRandomEngine<std::mt19937_64>()};
 static std::uniform_int_distribution<dht::Value::Id> rand_id;
 
 const std::string printTime(const std::time_t& now) {
-- 
GitLab