diff --git a/Source/Core/Common/CMakeLists.txt b/Source/Core/Common/CMakeLists.txt
index 0feb950b91..4b32f97607 100644
--- a/Source/Core/Common/CMakeLists.txt
+++ b/Source/Core/Common/CMakeLists.txt
@@ -34,6 +34,7 @@ add_library(common
PerformanceCounter.cpp
Profiler.cpp
QoSSession.cpp
+ Random.cpp
SDCardUtil.cpp
SettingsHandler.cpp
StringUtil.cpp
@@ -156,6 +157,7 @@ endif()
if(UNIX)
# Posix networking code needs to be fixed for Windows
add_executable(traversal_server TraversalServer.cpp)
+ target_link_libraries(traversal_server PRIVATE common)
if(SYSTEMD_FOUND)
target_link_libraries(traversal_server ${SYSTEMD_LIBRARIES})
endif()
diff --git a/Source/Core/Common/Common.vcxproj b/Source/Core/Common/Common.vcxproj
index 995c6e733e..b1a7261f11 100644
--- a/Source/Core/Common/Common.vcxproj
+++ b/Source/Core/Common/Common.vcxproj
@@ -142,6 +142,7 @@
+
@@ -206,6 +207,7 @@
+
@@ -250,4 +252,4 @@
-
\ No newline at end of file
+
diff --git a/Source/Core/Common/Common.vcxproj.filters b/Source/Core/Common/Common.vcxproj.filters
index dd041d490b..a5163abff6 100644
--- a/Source/Core/Common/Common.vcxproj.filters
+++ b/Source/Core/Common/Common.vcxproj.filters
@@ -63,6 +63,7 @@
+
@@ -295,6 +296,7 @@
+
@@ -357,4 +359,4 @@
-
\ No newline at end of file
+
diff --git a/Source/Core/Common/Crypto/ec.cpp b/Source/Core/Common/Crypto/ec.cpp
index 9a57300f89..78cd346ebd 100644
--- a/Source/Core/Common/Crypto/ec.cpp
+++ b/Source/Core/Common/Crypto/ec.cpp
@@ -15,6 +15,8 @@
#include "Common/Common.h"
#include "Common/Crypto/bn.h"
#include "Common/Crypto/ec.h"
+#include "Common/Random.h"
+#include "Common/StringUtil.h"
#ifdef _MSC_VER
#pragma warning(push)
@@ -230,30 +232,18 @@ static Point operator*(const u8* a, const Point& b)
return d;
}
-static void silly_random(u8* rndArea, u8 count)
-{
- u16 i;
- srand((unsigned)(time(nullptr)));
-
- for (i = 0; i < count; i++)
- {
- rndArea[i] = rand();
- }
-}
-
Signature Sign(const u8* key, const u8* hash)
{
u8 e[30]{};
memcpy(e + 10, hash, 20);
- // Changing random number generator to a lame one...
u8 m[30];
- silly_random(m, sizeof(m));
- // fp = fopen("/dev/random", "rb");
- // if (fread(m, sizeof m, 1, fp) != 1)
- // fatal("reading random");
- // fclose(fp);
- m[0] = 0;
+ do
+ {
+ // Generate 240 bits and keep 233.
+ Common::Random::Generate(m, sizeof(m));
+ m[0] &= 1;
+ } while (bn_compare(m, ec_N, sizeof(m)) >= 0);
Elt r = (m * ec_G).X();
if (bn_compare(r.data.data(), ec_N, 30) >= 0)
diff --git a/Source/Core/Common/Network.cpp b/Source/Core/Common/Network.cpp
index f492efd5ae..1d95e0c8a4 100644
--- a/Source/Core/Common/Network.cpp
+++ b/Source/Core/Common/Network.cpp
@@ -5,11 +5,10 @@
#include
#include
#include
-#include
#include "Common/Network.h"
+#include "Common/Random.h"
#include "Common/StringUtil.h"
-#include "Common/Timer.h"
namespace Common
{
@@ -31,11 +30,7 @@ void GenerateMacAddress(const MACConsumer type, u8* mac)
}
// Generate the 24-bit NIC-specific portion of the MAC address.
- std::default_random_engine generator(Common::Timer::GetTimeMs());
- std::uniform_int_distribution distribution(0x00, 0xFF);
- mac[3] = static_cast(distribution(generator));
- mac[4] = static_cast(distribution(generator));
- mac[5] = static_cast(distribution(generator));
+ Common::Random::Generate(&mac[3], 3);
}
std::string MacAddressToString(const u8* mac)
diff --git a/Source/Core/Common/Random.cpp b/Source/Core/Common/Random.cpp
new file mode 100644
index 0000000000..c512e7695d
--- /dev/null
+++ b/Source/Core/Common/Random.cpp
@@ -0,0 +1,49 @@
+// Copyright 2018 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#include "Common/Random.h"
+
+#include
+#include
+
+#include "Common/Assert.h"
+
+namespace Common::Random
+{
+class CSPRNG final
+{
+public:
+ CSPRNG()
+ {
+ mbedtls_entropy_init(&m_entropy);
+ mbedtls_hmac_drbg_init(&m_context);
+ const int ret = mbedtls_hmac_drbg_seed(&m_context, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256),
+ mbedtls_entropy_func, &m_entropy, nullptr, 0);
+ ASSERT(ret == 0);
+ }
+
+ ~CSPRNG()
+ {
+ mbedtls_hmac_drbg_free(&m_context);
+ mbedtls_entropy_free(&m_entropy);
+ }
+
+ void Generate(void* buffer, std::size_t size)
+ {
+ const int ret = mbedtls_hmac_drbg_random(&m_context, static_cast(buffer), size);
+ ASSERT(ret == 0);
+ }
+
+private:
+ mbedtls_entropy_context m_entropy;
+ mbedtls_hmac_drbg_context m_context;
+};
+
+static thread_local CSPRNG s_csprng;
+
+void Generate(void* buffer, std::size_t size)
+{
+ s_csprng.Generate(buffer, size);
+}
+} // namespace Common::Random
diff --git a/Source/Core/Common/Random.h b/Source/Core/Common/Random.h
new file mode 100644
index 0000000000..430b24201c
--- /dev/null
+++ b/Source/Core/Common/Random.h
@@ -0,0 +1,15 @@
+// Copyright 2018 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include
+
+#include "Common/CommonTypes.h"
+
+namespace Common::Random
+{
+/// Fill `buffer` with random bytes using a cryptographically secure pseudo-random number generator.
+void Generate(void* buffer, std::size_t size);
+} // namespace Common::Random
diff --git a/Source/Core/Common/TraversalClient.cpp b/Source/Core/Common/TraversalClient.cpp
index 4c415b2c64..36eb431c7f 100644
--- a/Source/Core/Common/TraversalClient.cpp
+++ b/Source/Core/Common/TraversalClient.cpp
@@ -4,22 +4,12 @@
#include
#include
-#include
#include
#include "Common/CommonTypes.h"
#include "Common/Logging/Log.h"
#include "Common/MsgHandler.h"
-
-static void GetRandomishBytes(u8* buf, size_t size)
-{
- // We don't need high quality random numbers (which might not be available),
- // just non-repeating numbers!
- static std::mt19937 prng(enet_time_get());
- static std::uniform_int_distribution u8_distribution(0, 255);
- for (size_t i = 0; i < size; i++)
- buf[i] = u8_distribution(prng);
-}
+#include "Common/Random.h"
TraversalClient::TraversalClient(ENetHost* netHost, const std::string& server, const u16 port)
: m_NetHost(netHost), m_Server(server), m_port(port)
@@ -280,7 +270,7 @@ TraversalRequestId TraversalClient::SendTraversalPacket(const TraversalPacket& p
{
OutgoingTraversalPacketInfo info;
info.packet = packet;
- GetRandomishBytes((u8*)&info.packet.requestId, sizeof(info.packet.requestId));
+ Common::Random::Generate(&info.packet.requestId, sizeof(info.packet.requestId));
info.tries = 0;
m_OutgoingTraversalPackets.push_back(info);
ResendPacket(&m_OutgoingTraversalPackets.back());
diff --git a/Source/Core/Common/TraversalServer.cpp b/Source/Core/Common/TraversalServer.cpp
index 5da45a05fe..097418b143 100644
--- a/Source/Core/Common/TraversalServer.cpp
+++ b/Source/Core/Common/TraversalServer.cpp
@@ -20,6 +20,7 @@
#include
#endif
+#include "Common/Random.h"
#include "Common/TraversalProto.h"
#define DEBUG 0
@@ -114,7 +115,6 @@ struct hash
}
static int sock;
-static int urandomFd;
static std::unordered_map outgoingPackets;
static std::unordered_map> connectedClients;
@@ -166,28 +166,11 @@ static sockaddr_in6 MakeSinAddr(const TraversalInetAddress& addr)
return result;
}
-static void GetRandomBytes(void* output, size_t size)
-{
- static u8 bytes[8192];
- static size_t bytesLeft = 0;
- if (bytesLeft < size)
- {
- ssize_t rv = read(urandomFd, bytes, sizeof(bytes));
- if (rv != sizeof(bytes))
- {
- perror("read from /dev/urandom");
- exit(1);
- }
- bytesLeft = sizeof(bytes);
- }
- memcpy(output, bytes + (bytesLeft -= size), size);
-}
-
static void GetRandomHostId(TraversalHostId* hostId)
{
char buf[9];
u32 num;
- GetRandomBytes(&num, sizeof(num));
+ Common::Random::Generate(&num, sizeof(num));
sprintf(buf, "%08x", num);
memcpy(hostId->data(), buf, 8);
}
@@ -215,7 +198,7 @@ static void TrySend(const void* buffer, size_t size, sockaddr_in6* addr)
static TraversalPacket* AllocPacket(const sockaddr_in6& dest, TraversalRequestId misc = 0)
{
TraversalRequestId requestId;
- GetRandomBytes(&requestId, sizeof(requestId));
+ Common::Random::Generate(&requestId, sizeof(requestId));
OutgoingPacketInfo* info = &outgoingPackets[requestId];
info->dest = dest;
info->misc = misc;
@@ -376,14 +359,6 @@ static void HandlePacket(TraversalPacket* packet, sockaddr_in6* addr)
int main()
{
int rv;
-
- urandomFd = open("/dev/urandom", O_RDONLY);
- if (urandomFd < 0)
- {
- perror("open /dev/urandom");
- return 1;
- }
-
sock = socket(PF_INET6, SOCK_DGRAM, 0);
if (sock == -1)
{
diff --git a/Source/Core/Core/Analytics.cpp b/Source/Core/Core/Analytics.cpp
index 1cd746aa92..9c0608ef59 100644
--- a/Source/Core/Core/Analytics.cpp
+++ b/Source/Core/Core/Analytics.cpp
@@ -4,7 +4,6 @@
#include
#include
#include
-#include
#include
#if defined(_WIN32)
@@ -16,6 +15,7 @@
#include "Common/Analytics.h"
#include "Common/CPUDetect.h"
#include "Common/CommonTypes.h"
+#include "Common/Random.h"
#include "Common/StringUtil.h"
#include "Common/Version.h"
#include "Core/ConfigManager.h"
@@ -73,9 +73,9 @@ void DolphinAnalytics::ReloadConfig()
void DolphinAnalytics::GenerateNewIdentity()
{
- std::random_device rd;
- u64 id_high = (static_cast(rd()) << 32) | rd();
- u64 id_low = (static_cast(rd()) << 32) | rd();
+ u64 id_high, id_low;
+ Common::Random::Generate(&id_high, sizeof(id_high));
+ Common::Random::Generate(&id_low, sizeof(id_low));
m_unique_id = StringFromFormat("%016" PRIx64 "%016" PRIx64, id_high, id_low);
// Save the new id in the configuration.