Index: source/lib/sysdep/os/unix/unix.cpp =================================================================== --- source/lib/sysdep/os/unix/unix.cpp +++ source/lib/sysdep/os/unix/unix.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2021 Wildfire Games. +/* Copyright (c) 2022 Wildfire Games. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -320,29 +320,6 @@ return L""; } -Status sys_generate_random_bytes(u8* buf, size_t count) -{ - FILE* f = fopen("/dev/urandom", "rb"); - if (!f) - WARN_RETURN(ERR::FAIL); - - while (count) - { - size_t numread = fread(buf, 1, count, f); - if (numread == 0) - { - fclose(f); - WARN_RETURN(ERR::FAIL); - } - buf += numread; - count -= numread; - } - - fclose(f); - - return INFO::OK; -} - Status sys_get_proxy_config(const std::wstring& UNUSED(url), std::wstring& UNUSED(proxy)) { return INFO::SKIPPED; Index: source/lib/sysdep/os/win/wsysdep.cpp =================================================================== --- source/lib/sysdep/os/win/wsysdep.cpp +++ source/lib/sysdep/os/win/wsysdep.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2020 Wildfire Games. +/* Copyright (C) 2022 Wildfire Games. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -503,23 +503,6 @@ } -Status sys_generate_random_bytes(u8* buffer, size_t size) -{ - HCRYPTPROV hCryptProv = 0; - if(!CryptAcquireContext(&hCryptProv, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) - WARN_RETURN(StatusFromWin()); - - memset(buffer, 0, size); - if(!CryptGenRandom(hCryptProv, (DWORD)size, (BYTE*)buffer)) - WARN_RETURN(StatusFromWin()); - - if(!CryptReleaseContext(hCryptProv, 0)) - WARN_RETURN(StatusFromWin()); - - return INFO::OK; -} - - #if CONFIG_ENABLE_BOOST /* Index: source/lib/sysdep/sysdep.h =================================================================== --- source/lib/sysdep/sysdep.h +++ source/lib/sysdep/sysdep.h @@ -157,14 +157,6 @@ **/ extern size_t sys_max_sector_size(); -/** - * generate high-quality random bytes. - * - * this should only be used with small numbers of bytes, to avoid - * hogging the system's entropy. - **/ -Status sys_generate_random_bytes(u8* buf, size_t count); - /** * get the proxy address for accessing the given HTTP URL. * Index: source/lib/sysdep/tests/test_sysdep.h =================================================================== --- source/lib/sysdep/tests/test_sysdep.h +++ source/lib/sysdep/tests/test_sysdep.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2014 Wildfire Games. +/* Copyright (C) 2022 Wildfire Games. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -37,14 +37,6 @@ class TestSysdep : public CxxTest::TestSuite { public: - void test_random() - { - u64 a = 0, b = 0; - TS_ASSERT_OK(sys_generate_random_bytes((u8*)&a, sizeof(a))); - TS_ASSERT_OK(sys_generate_random_bytes((u8*)&b, sizeof(b))); - TS_ASSERT_DIFFERS(a, b); - } - void test_sys_ExecutablePathname() { OsPath path = sys_ExecutablePathname(); Index: source/ps/GUID.cpp =================================================================== --- source/ps/GUID.cpp +++ source/ps/GUID.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2013 Wildfire Games. +/* Copyright (C) 2022 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -15,9 +15,13 @@ * along with 0 A.D. If not, see . */ #include "precompiled.h" -#include "lib/sysdep/sysdep.h" + #include "ps/CStr.h" +#include +#include +#include + CStr ps_generate_guid(void) { // TODO: Ideally this will be guaranteed unique (and verified @@ -27,15 +31,19 @@ // a host to masquerade as someone else. // For now, just try to pick a very random number. - CStr guid; - for (size_t i = 0; i < 2; ++i) + std::random_device rd; + std::uniform_int_distribution distrib; + if (rd.entropy() > 0) { - u32 r = 0; - sys_generate_random_bytes((u8*)&r, sizeof(r)); - char buf[32]; - sprintf_s(buf, ARRAY_SIZE(buf), "%08X", r); - guid += buf; + const u64 r = distrib(rd); + return fmt::format("{:016X}", r); } - return guid; + std::default_random_engine fallback + { + static_cast( + std::chrono::high_resolution_clock::now().time_since_epoch().count()) + }; + const u64 r = distrib(fallback); + return fmt::format("{:016X}", r); } Index: source/ps/UserReport.cpp =================================================================== --- source/ps/UserReport.cpp +++ source/ps/UserReport.cpp @@ -28,6 +28,7 @@ #include "lib/sysdep/sysdep.h" #include "ps/ConfigDB.h" #include "ps/Filesystem.h" +#include "ps/GUID.h" #include "ps/Profiler2.h" #include "ps/Pyrogenesis.h" #include "ps/Threading.h" @@ -523,26 +524,16 @@ // Read the user ID from user.cfg (if there is one) CFG_GET_VAL("userreport.id", userID); - // If we don't have a validly-formatted user ID, generate a new one - if (userID.length() != 16) - { - u8 bytes[8] = {0}; - sys_generate_random_bytes(bytes, ARRAY_SIZE(bytes)); - // ignore failures - there's not much we can do about it + if (userID.length() == 16) + return userID; - userID = ""; - for (size_t i = 0; i < ARRAY_SIZE(bytes); ++i) - { - char hex[3]; - sprintf_s(hex, ARRAY_SIZE(hex), "%02x", (unsigned int)bytes[i]); - userID += hex; - } + // We don't have a validly-formatted user ID, generate a new one + const CStr newUserID = ps_generate_guid(); - g_ConfigDB.SetValueString(CFG_USER, "userreport.id", userID); - g_ConfigDB.WriteValueToFile(CFG_USER, "userreport.id", userID); - } + g_ConfigDB.SetValueString(CFG_USER, "userreport.id", newUserID); + g_ConfigDB.WriteValueToFile(CFG_USER, "userreport.id", newUserID); - return userID; + return newUserID; } bool CUserReporter::IsReportingEnabled()