mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-11-14 21:37:52 -07:00
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
|
||||
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()
|
||||
|
@ -142,6 +142,7 @@
|
||||
<ClInclude Include="PcapFile.h" />
|
||||
<ClInclude Include="Profiler.h" />
|
||||
<ClInclude Include="QoSSession.h" />
|
||||
<ClInclude Include="Random.h" />
|
||||
<ClInclude Include="Result.h" />
|
||||
<ClInclude Include="ScopeGuard.h" />
|
||||
<ClInclude Include="SDCardUtil.h" />
|
||||
@ -206,6 +207,7 @@
|
||||
<ClCompile Include="PcapFile.cpp" />
|
||||
<ClCompile Include="Profiler.cpp" />
|
||||
<ClCompile Include="QoSSession.cpp" />
|
||||
<ClCompile Include="Random.cpp" />
|
||||
<ClCompile Include="SDCardUtil.cpp" />
|
||||
<ClCompile Include="SettingsHandler.cpp" />
|
||||
<ClCompile Include="StringUtil.cpp" />
|
||||
@ -250,4 +252,4 @@
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
@ -63,6 +63,7 @@
|
||||
<ClInclude Include="PcapFile.h" />
|
||||
<ClInclude Include="Profiler.h" />
|
||||
<ClInclude Include="QoSSession.h" />
|
||||
<ClInclude Include="Random.h" />
|
||||
<ClInclude Include="Result.h" />
|
||||
<ClInclude Include="ScopeGuard.h" />
|
||||
<ClInclude Include="SDCardUtil.h" />
|
||||
@ -295,6 +296,7 @@
|
||||
<ClCompile Include="Network.cpp" />
|
||||
<ClCompile Include="PcapFile.cpp" />
|
||||
<ClCompile Include="Profiler.cpp" />
|
||||
<ClCompile Include="Random.cpp" />
|
||||
<ClCompile Include="SDCardUtil.cpp" />
|
||||
<ClCompile Include="SettingsHandler.cpp" />
|
||||
<ClCompile Include="StringUtil.cpp" />
|
||||
@ -357,4 +359,4 @@
|
||||
<ItemGroup>
|
||||
<Natvis Include="BitField.natvis" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
@ -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)
|
||||
|
@ -5,11 +5,10 @@
|
||||
#include <cctype>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <random>
|
||||
|
||||
#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<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));
|
||||
Common::Random::Generate(&mac[3], 3);
|
||||
}
|
||||
|
||||
std::string MacAddressToString(const u8* mac)
|
||||
|
49
Source/Core/Common/Random.cpp
Normal file
49
Source/Core/Common/Random.cpp
Normal file
@ -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
|
15
Source/Core/Common/Random.h
Normal file
15
Source/Core/Common/Random.h
Normal file
@ -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 <cstring>
|
||||
#include <random>
|
||||
#include <string>
|
||||
|
||||
#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<unsigned int> 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());
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <systemd/sd-daemon.h>
|
||||
#endif
|
||||
|
||||
#include "Common/Random.h"
|
||||
#include "Common/TraversalProto.h"
|
||||
|
||||
#define DEBUG 0
|
||||
@ -114,7 +115,6 @@ struct hash<TraversalHostId>
|
||||
}
|
||||
|
||||
static int sock;
|
||||
static int urandomFd;
|
||||
static std::unordered_map<TraversalRequestId, OutgoingPacketInfo> outgoingPackets;
|
||||
static std::unordered_map<TraversalHostId, EvictEntry<TraversalInetAddress>> 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)
|
||||
{
|
||||
|
@ -4,7 +4,6 @@
|
||||
#include <mbedtls/sha1.h>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <random>
|
||||
#include <string>
|
||||
|
||||
#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<u64>(rd()) << 32) | rd();
|
||||
u64 id_low = (static_cast<u64>(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.
|
||||
|
Loading…
Reference in New Issue
Block a user