Common: Add Random utilities
This makes it easier to generate random numbers or fill a buffer with random data in a cryptographically secure way. This also replaces existing usages of RNG functions in the codebase: * <random> is pretty hard to use correctly, and std::random_device does not give enough guarantees about its results (it's implementation-defined, non cryptographically secure and could be deterministic on some platforms). Doing things correctly is error prone and verbose. * rand() is terrible and should not be used especially in crypto code.
This commit is contained in:
parent
dd77ace56a
commit
fff1db9730
|
@ -34,6 +34,7 @@ add_library(common
|
||||||
PerformanceCounter.cpp
|
PerformanceCounter.cpp
|
||||||
Profiler.cpp
|
Profiler.cpp
|
||||||
QoSSession.cpp
|
QoSSession.cpp
|
||||||
|
Random.cpp
|
||||||
SDCardUtil.cpp
|
SDCardUtil.cpp
|
||||||
SettingsHandler.cpp
|
SettingsHandler.cpp
|
||||||
StringUtil.cpp
|
StringUtil.cpp
|
||||||
|
@ -156,6 +157,7 @@ endif()
|
||||||
if(UNIX)
|
if(UNIX)
|
||||||
# Posix networking code needs to be fixed for Windows
|
# Posix networking code needs to be fixed for Windows
|
||||||
add_executable(traversal_server TraversalServer.cpp)
|
add_executable(traversal_server TraversalServer.cpp)
|
||||||
|
target_link_libraries(traversal_server PRIVATE common)
|
||||||
if(SYSTEMD_FOUND)
|
if(SYSTEMD_FOUND)
|
||||||
target_link_libraries(traversal_server ${SYSTEMD_LIBRARIES})
|
target_link_libraries(traversal_server ${SYSTEMD_LIBRARIES})
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -142,6 +142,7 @@
|
||||||
<ClInclude Include="PcapFile.h" />
|
<ClInclude Include="PcapFile.h" />
|
||||||
<ClInclude Include="Profiler.h" />
|
<ClInclude Include="Profiler.h" />
|
||||||
<ClInclude Include="QoSSession.h" />
|
<ClInclude Include="QoSSession.h" />
|
||||||
|
<ClInclude Include="Random.h" />
|
||||||
<ClInclude Include="Result.h" />
|
<ClInclude Include="Result.h" />
|
||||||
<ClInclude Include="ScopeGuard.h" />
|
<ClInclude Include="ScopeGuard.h" />
|
||||||
<ClInclude Include="SDCardUtil.h" />
|
<ClInclude Include="SDCardUtil.h" />
|
||||||
|
@ -206,6 +207,7 @@
|
||||||
<ClCompile Include="PcapFile.cpp" />
|
<ClCompile Include="PcapFile.cpp" />
|
||||||
<ClCompile Include="Profiler.cpp" />
|
<ClCompile Include="Profiler.cpp" />
|
||||||
<ClCompile Include="QoSSession.cpp" />
|
<ClCompile Include="QoSSession.cpp" />
|
||||||
|
<ClCompile Include="Random.cpp" />
|
||||||
<ClCompile Include="SDCardUtil.cpp" />
|
<ClCompile Include="SDCardUtil.cpp" />
|
||||||
<ClCompile Include="SettingsHandler.cpp" />
|
<ClCompile Include="SettingsHandler.cpp" />
|
||||||
<ClCompile Include="StringUtil.cpp" />
|
<ClCompile Include="StringUtil.cpp" />
|
||||||
|
@ -250,4 +252,4 @@
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -63,6 +63,7 @@
|
||||||
<ClInclude Include="PcapFile.h" />
|
<ClInclude Include="PcapFile.h" />
|
||||||
<ClInclude Include="Profiler.h" />
|
<ClInclude Include="Profiler.h" />
|
||||||
<ClInclude Include="QoSSession.h" />
|
<ClInclude Include="QoSSession.h" />
|
||||||
|
<ClInclude Include="Random.h" />
|
||||||
<ClInclude Include="Result.h" />
|
<ClInclude Include="Result.h" />
|
||||||
<ClInclude Include="ScopeGuard.h" />
|
<ClInclude Include="ScopeGuard.h" />
|
||||||
<ClInclude Include="SDCardUtil.h" />
|
<ClInclude Include="SDCardUtil.h" />
|
||||||
|
@ -295,6 +296,7 @@
|
||||||
<ClCompile Include="Network.cpp" />
|
<ClCompile Include="Network.cpp" />
|
||||||
<ClCompile Include="PcapFile.cpp" />
|
<ClCompile Include="PcapFile.cpp" />
|
||||||
<ClCompile Include="Profiler.cpp" />
|
<ClCompile Include="Profiler.cpp" />
|
||||||
|
<ClCompile Include="Random.cpp" />
|
||||||
<ClCompile Include="SDCardUtil.cpp" />
|
<ClCompile Include="SDCardUtil.cpp" />
|
||||||
<ClCompile Include="SettingsHandler.cpp" />
|
<ClCompile Include="SettingsHandler.cpp" />
|
||||||
<ClCompile Include="StringUtil.cpp" />
|
<ClCompile Include="StringUtil.cpp" />
|
||||||
|
@ -357,4 +359,4 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Natvis Include="BitField.natvis" />
|
<Natvis Include="BitField.natvis" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
#include "Common/Common.h"
|
#include "Common/Common.h"
|
||||||
#include "Common/Crypto/bn.h"
|
#include "Common/Crypto/bn.h"
|
||||||
#include "Common/Crypto/ec.h"
|
#include "Common/Crypto/ec.h"
|
||||||
|
#include "Common/Random.h"
|
||||||
|
#include "Common/StringUtil.h"
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma warning(push)
|
#pragma warning(push)
|
||||||
|
@ -230,30 +232,18 @@ static Point operator*(const u8* a, const Point& b)
|
||||||
return d;
|
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)
|
Signature Sign(const u8* key, const u8* hash)
|
||||||
{
|
{
|
||||||
u8 e[30]{};
|
u8 e[30]{};
|
||||||
memcpy(e + 10, hash, 20);
|
memcpy(e + 10, hash, 20);
|
||||||
|
|
||||||
// Changing random number generator to a lame one...
|
|
||||||
u8 m[30];
|
u8 m[30];
|
||||||
silly_random(m, sizeof(m));
|
do
|
||||||
// fp = fopen("/dev/random", "rb");
|
{
|
||||||
// if (fread(m, sizeof m, 1, fp) != 1)
|
// Generate 240 bits and keep 233.
|
||||||
// fatal("reading random");
|
Common::Random::Generate(m, sizeof(m));
|
||||||
// fclose(fp);
|
m[0] &= 1;
|
||||||
m[0] = 0;
|
} while (bn_compare(m, ec_N, sizeof(m)) >= 0);
|
||||||
|
|
||||||
Elt r = (m * ec_G).X();
|
Elt r = (m * ec_G).X();
|
||||||
if (bn_compare(r.data.data(), ec_N, 30) >= 0)
|
if (bn_compare(r.data.data(), ec_N, 30) >= 0)
|
||||||
|
|
|
@ -5,11 +5,10 @@
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <random>
|
|
||||||
|
|
||||||
#include "Common/Network.h"
|
#include "Common/Network.h"
|
||||||
|
#include "Common/Random.h"
|
||||||
#include "Common/StringUtil.h"
|
#include "Common/StringUtil.h"
|
||||||
#include "Common/Timer.h"
|
|
||||||
|
|
||||||
namespace Common
|
namespace Common
|
||||||
{
|
{
|
||||||
|
@ -31,11 +30,7 @@ void GenerateMacAddress(const MACConsumer type, u8* mac)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate the 24-bit NIC-specific portion of the MAC address.
|
// Generate the 24-bit NIC-specific portion of the MAC address.
|
||||||
std::default_random_engine generator(Common::Timer::GetTimeMs());
|
Common::Random::Generate(&mac[3], 3);
|
||||||
std::uniform_int_distribution<int> distribution(0x00, 0xFF);
|
|
||||||
mac[3] = static_cast<u8>(distribution(generator));
|
|
||||||
mac[4] = static_cast<u8>(distribution(generator));
|
|
||||||
mac[5] = static_cast<u8>(distribution(generator));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string MacAddressToString(const u8* mac)
|
std::string MacAddressToString(const u8* mac)
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
// Copyright 2018 Dolphin Emulator Project
|
||||||
|
// Licensed under GPLv2+
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include "Common/Random.h"
|
||||||
|
|
||||||
|
#include <mbedtls/entropy.h>
|
||||||
|
#include <mbedtls/hmac_drbg.h>
|
||||||
|
|
||||||
|
#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<u8*>(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
|
|
@ -0,0 +1,15 @@
|
||||||
|
// Copyright 2018 Dolphin Emulator Project
|
||||||
|
// Licensed under GPLv2+
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
#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
|
|
@ -4,22 +4,12 @@
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <random>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
#include "Common/MsgHandler.h"
|
#include "Common/MsgHandler.h"
|
||||||
|
#include "Common/Random.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<unsigned int> u8_distribution(0, 255);
|
|
||||||
for (size_t i = 0; i < size; i++)
|
|
||||||
buf[i] = u8_distribution(prng);
|
|
||||||
}
|
|
||||||
|
|
||||||
TraversalClient::TraversalClient(ENetHost* netHost, const std::string& server, const u16 port)
|
TraversalClient::TraversalClient(ENetHost* netHost, const std::string& server, const u16 port)
|
||||||
: m_NetHost(netHost), m_Server(server), m_port(port)
|
: m_NetHost(netHost), m_Server(server), m_port(port)
|
||||||
|
@ -280,7 +270,7 @@ TraversalRequestId TraversalClient::SendTraversalPacket(const TraversalPacket& p
|
||||||
{
|
{
|
||||||
OutgoingTraversalPacketInfo info;
|
OutgoingTraversalPacketInfo info;
|
||||||
info.packet = packet;
|
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;
|
info.tries = 0;
|
||||||
m_OutgoingTraversalPackets.push_back(info);
|
m_OutgoingTraversalPackets.push_back(info);
|
||||||
ResendPacket(&m_OutgoingTraversalPackets.back());
|
ResendPacket(&m_OutgoingTraversalPackets.back());
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include <systemd/sd-daemon.h>
|
#include <systemd/sd-daemon.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "Common/Random.h"
|
||||||
#include "Common/TraversalProto.h"
|
#include "Common/TraversalProto.h"
|
||||||
|
|
||||||
#define DEBUG 0
|
#define DEBUG 0
|
||||||
|
@ -114,7 +115,6 @@ struct hash<TraversalHostId>
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sock;
|
static int sock;
|
||||||
static int urandomFd;
|
|
||||||
static std::unordered_map<TraversalRequestId, OutgoingPacketInfo> outgoingPackets;
|
static std::unordered_map<TraversalRequestId, OutgoingPacketInfo> outgoingPackets;
|
||||||
static std::unordered_map<TraversalHostId, EvictEntry<TraversalInetAddress>> connectedClients;
|
static std::unordered_map<TraversalHostId, EvictEntry<TraversalInetAddress>> connectedClients;
|
||||||
|
|
||||||
|
@ -166,28 +166,11 @@ static sockaddr_in6 MakeSinAddr(const TraversalInetAddress& addr)
|
||||||
return result;
|
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)
|
static void GetRandomHostId(TraversalHostId* hostId)
|
||||||
{
|
{
|
||||||
char buf[9];
|
char buf[9];
|
||||||
u32 num;
|
u32 num;
|
||||||
GetRandomBytes(&num, sizeof(num));
|
Common::Random::Generate(&num, sizeof(num));
|
||||||
sprintf(buf, "%08x", num);
|
sprintf(buf, "%08x", num);
|
||||||
memcpy(hostId->data(), buf, 8);
|
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)
|
static TraversalPacket* AllocPacket(const sockaddr_in6& dest, TraversalRequestId misc = 0)
|
||||||
{
|
{
|
||||||
TraversalRequestId requestId;
|
TraversalRequestId requestId;
|
||||||
GetRandomBytes(&requestId, sizeof(requestId));
|
Common::Random::Generate(&requestId, sizeof(requestId));
|
||||||
OutgoingPacketInfo* info = &outgoingPackets[requestId];
|
OutgoingPacketInfo* info = &outgoingPackets[requestId];
|
||||||
info->dest = dest;
|
info->dest = dest;
|
||||||
info->misc = misc;
|
info->misc = misc;
|
||||||
|
@ -376,14 +359,6 @@ static void HandlePacket(TraversalPacket* packet, sockaddr_in6* addr)
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
urandomFd = open("/dev/urandom", O_RDONLY);
|
|
||||||
if (urandomFd < 0)
|
|
||||||
{
|
|
||||||
perror("open /dev/urandom");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
sock = socket(PF_INET6, SOCK_DGRAM, 0);
|
sock = socket(PF_INET6, SOCK_DGRAM, 0);
|
||||||
if (sock == -1)
|
if (sock == -1)
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
#include <mbedtls/sha1.h>
|
#include <mbedtls/sha1.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <random>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
@ -16,6 +15,7 @@
|
||||||
#include "Common/Analytics.h"
|
#include "Common/Analytics.h"
|
||||||
#include "Common/CPUDetect.h"
|
#include "Common/CPUDetect.h"
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
|
#include "Common/Random.h"
|
||||||
#include "Common/StringUtil.h"
|
#include "Common/StringUtil.h"
|
||||||
#include "Common/Version.h"
|
#include "Common/Version.h"
|
||||||
#include "Core/ConfigManager.h"
|
#include "Core/ConfigManager.h"
|
||||||
|
@ -73,9 +73,9 @@ void DolphinAnalytics::ReloadConfig()
|
||||||
|
|
||||||
void DolphinAnalytics::GenerateNewIdentity()
|
void DolphinAnalytics::GenerateNewIdentity()
|
||||||
{
|
{
|
||||||
std::random_device rd;
|
u64 id_high, id_low;
|
||||||
u64 id_high = (static_cast<u64>(rd()) << 32) | rd();
|
Common::Random::Generate(&id_high, sizeof(id_high));
|
||||||
u64 id_low = (static_cast<u64>(rd()) << 32) | rd();
|
Common::Random::Generate(&id_low, sizeof(id_low));
|
||||||
m_unique_id = StringFromFormat("%016" PRIx64 "%016" PRIx64, id_high, id_low);
|
m_unique_id = StringFromFormat("%016" PRIx64 "%016" PRIx64, id_high, id_low);
|
||||||
|
|
||||||
// Save the new id in the configuration.
|
// Save the new id in the configuration.
|
||||||
|
|
Loading…
Reference in New Issue