diff --git a/premake5.lua b/premake5.lua index 5e7d36ae..549541f1 100644 --- a/premake5.lua +++ b/premake5.lua @@ -73,7 +73,7 @@ workspace "iw4x" toolset "msc-140" configuration "windows" - defines { "_WINDOWS" } + defines { "_WINDOWS", "WIN32" } configuration "Release*" defines { "NDEBUG" } @@ -205,7 +205,7 @@ workspace "iw4x" -- libtomcrypt project "libtomcrypt" language "C" - defines { "_LIB", "LTC_SOURCE", "LTC_NO_RSA_BLINDING", "LTM_DESC", "USE_LTM" } + defines { "_LIB", "LTC_SOURCE", "LTC_NO_RSA_BLINDING", "LTM_DESC", "USE_LTM", "WIN32" } links { "libtommath" } includedirs { "./deps/libtomcrypt/src/headers" } diff --git a/src/Components/Modules/Discovery.cpp b/src/Components/Modules/Discovery.cpp index f1c1b68a..c5b74556 100644 --- a/src/Components/Modules/Discovery.cpp +++ b/src/Components/Modules/Discovery.cpp @@ -28,7 +28,7 @@ namespace Components Logger::Print("Starting local server discovery...\n"); - Discovery::DiscoveryContainer.Challenge = Utils::VA("%d", Game::Com_Milliseconds()); + Discovery::DiscoveryContainer.Challenge = Utils::VA("%d", Utils::Cryptography::Rand::GenerateInt()); //Network::BroadcastAll("discovery\n"); unsigned int minPort = Dvar::Var("net_discoveryPortRangeMin").Get(); diff --git a/src/Components/Modules/Download.cpp b/src/Components/Modules/Download.cpp index 4de984b3..8396b5eb 100644 --- a/src/Components/Modules/Download.cpp +++ b/src/Components/Modules/Download.cpp @@ -224,7 +224,7 @@ namespace Components download.maxParts = download.buffer.size() / PACKET_SIZE; if (download.buffer.size() % PACKET_SIZE) download.maxParts++; - download.challenge = Utils::VA("%X", Game::Com_Milliseconds()); + download.challenge = Utils::VA("%X", Utils::Cryptography::Rand::GenerateInt()); Download::Container::AckRequest request; request.id = id; diff --git a/src/Components/Modules/Node.cpp b/src/Components/Modules/Node.cpp index 3617e29a..4a01f02e 100644 --- a/src/Components/Modules/Node.cpp +++ b/src/Components/Modules/Node.cpp @@ -317,7 +317,7 @@ namespace Components count++; dedi.lastTime = Game::Com_Milliseconds(); - dedi.challenge = Utils::VA("%d", dedi.lastTime); + dedi.challenge = Utils::VA("%d", Utils::Cryptography::Rand::GenerateInt()); dedi.state = Node::STATE_QUERYING; Logger::Print("Verifying dedi %s...\n", dedi.address.GetString()); diff --git a/src/Components/Modules/Party.cpp b/src/Components/Modules/Party.cpp index 4244f91b..7448e913 100644 --- a/src/Components/Modules/Party.cpp +++ b/src/Components/Modules/Party.cpp @@ -28,7 +28,7 @@ namespace Components Party::Container.AwaitingPlaylist = false; Party::Container.JoinTime = Game::Com_Milliseconds(); Party::Container.Target = target; - Party::Container.Challenge = Utils::VA("%X", Party::Container.JoinTime); + Party::Container.Challenge = Utils::VA("%X", Utils::Cryptography::Rand::GenerateInt()); Network::Send(Party::Container.Target, Utils::VA("getinfo %s\n", Party::Container.Challenge.data())); diff --git a/src/Components/Modules/ServerList.cpp b/src/Components/Modules/ServerList.cpp index 4117033e..f7fefef1 100644 --- a/src/Components/Modules/ServerList.cpp +++ b/src/Components/Modules/ServerList.cpp @@ -500,7 +500,7 @@ namespace Components SendServers--; server->SendTime = Game::Com_Milliseconds(); - server->Challenge = Utils::VA("%d", server->SendTime); + server->Challenge = Utils::VA("%d", Utils::Cryptography::Rand::GenerateInt()); ServerList::RefreshContainer.SentCount++; diff --git a/src/Utils/Cryptography.cpp b/src/Utils/Cryptography.cpp index 09188000..868d06ff 100644 --- a/src/Utils/Cryptography.cpp +++ b/src/Utils/Cryptography.cpp @@ -6,6 +6,65 @@ namespace Utils { namespace Cryptography { +#pragma region Rand + + uint32_t Rand::GenerateInt() + { + size_t length = 0; + uint8_t buffer[4] = { 0 }; + + while (length != 4) + { + length = sprng_read(buffer, sizeof(buffer), NULL); + } + + return *reinterpret_cast(buffer); + } + +#pragma endregion + +#pragma region ECDSA + + ECDSA::Key ECDSA::GenerateKey(int bits) + { + ECDSA::Key key; + + register_prng(&sprng_desc); + register_hash(&sha1_desc); + + ltc_mp = ltm_desc; + + ecc_make_key(NULL, find_prng("sprng"), bits / 8, key.GetKeyPtr()); + + return key; + } + + std::string ECDSA::SignMessage(Key key, std::string message) + { + uint8_t buffer[0x200]; // Default size is 512 + DWORD length = sizeof(buffer); + + register_prng(&sprng_desc); + + ltc_mp = ltm_desc; + + ecc_sign_hash(reinterpret_cast(message.data()), message.size(), buffer, &length, NULL, find_prng("sprng"), key.GetKeyPtr()); + + return std::string(reinterpret_cast(buffer), length); + } + + bool ECDSA::VerifyMessage(Key key, std::string message, std::string signature) + { + ltc_mp = ltm_desc; + + int result = 0; + return (ecc_verify_hash(reinterpret_cast(signature.data()), signature.size(), reinterpret_cast(message.data()), message.size(), &result, key.GetKeyPtr()) == CRYPT_OK && result != 0); + } + +#pragma endregion + +#pragma region RSA + RSA::Key RSA::GenerateKey(int bits) { RSA::Key key; @@ -45,4 +104,7 @@ namespace Utils return (rsa_verify_hash(reinterpret_cast(signature.data()), signature.size(), reinterpret_cast(message.data()), message.size(), find_hash("sha1"), 0, &result, key.GetKeyPtr()) == CRYPT_OK && result != 0); } } + +#pragma endregion + } diff --git a/src/Utils/Cryptography.hpp b/src/Utils/Cryptography.hpp index 2cb620d3..bd0ea53a 100644 --- a/src/Utils/Cryptography.hpp +++ b/src/Utils/Cryptography.hpp @@ -2,6 +2,52 @@ namespace Utils { namespace Cryptography { + class Rand + { + public: + static uint32_t GenerateInt(); + }; + + class ECDSA + { + public: + class Key + { + public: + Key() { ZeroMemory(&this->KeyStorage, sizeof(this->KeyStorage)); }; + Key(ecc_key* key) : Key(*key) {}; + Key(ecc_key key) : KeyStorage(key) {}; + Key(const Key& obj) : KeyStorage(obj.KeyStorage) {}; + + ~Key() {} + + ecc_key* GetKeyPtr() + { + return &this->KeyStorage; + } + + std::string GetPublicKey() + { + uint8_t buffer[0x1000] = { 0 }; + DWORD length = sizeof(buffer); + + if (ecc_ansi_x963_export(this->GetKeyPtr(), buffer, &length) == CRYPT_OK) + { + return std::string(reinterpret_cast(buffer), length); + } + + return ""; + } + + private: + ecc_key KeyStorage; + }; + + static Key GenerateKey(int bits); + static std::string SignMessage(Key key, std::string message); + static bool VerifyMessage(Key key, std::string message, std::string signature); + }; + class RSA { public: @@ -24,7 +70,7 @@ namespace Utils rsa_key KeyStorage; }; - static RSA::Key GenerateKey(int bits); + static Key GenerateKey(int bits); static std::string SignMessage(Key key, std::string message); static bool VerifyMessage(Key key, std::string message, std::string signature); };