diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/common/Cryptography/CryptoHash.h | 2 | ||||
-rw-r--r-- | src/common/Cryptography/HMAC.h | 5 | ||||
-rw-r--r-- | src/common/Cryptography/RSA.cpp | 50 | ||||
-rw-r--r-- | src/common/Cryptography/RSA.h | 7 | ||||
-rw-r--r-- | src/server/game/Server/Packets/AuthenticationPackets.cpp | 12 | ||||
-rw-r--r-- | src/server/game/Server/Packets/AuthenticationPackets.h | 12 | ||||
-rw-r--r-- | src/server/worldserver/Main.cpp | 3 |
7 files changed, 71 insertions, 20 deletions
diff --git a/src/common/Cryptography/CryptoHash.h b/src/common/Cryptography/CryptoHash.h index d36d345b88c..a2cd393745e 100644 --- a/src/common/Cryptography/CryptoHash.h +++ b/src/common/Cryptography/CryptoHash.h @@ -96,7 +96,7 @@ namespace Trinity::Impl if (this == &right) return *this; - int result = EVP_MD_CTX_copy(_ctx, right._ctx); + int result = EVP_MD_CTX_copy_ex(_ctx, right._ctx); ASSERT(result == 1); _digest = right._digest; return *this; diff --git a/src/common/Cryptography/HMAC.h b/src/common/Cryptography/HMAC.h index 6ed86de4bab..d07ba19216d 100644 --- a/src/common/Cryptography/HMAC.h +++ b/src/common/Cryptography/HMAC.h @@ -86,9 +86,10 @@ namespace Trinity::Impl if (this == &right) return *this; - int result = EVP_MD_CTX_copy(_ctx, right._ctx); + int result = EVP_MD_CTX_copy_ex(_ctx, right._ctx); ASSERT(result == 1); - _key = right._key; // EVP_PKEY uses reference counting internally, just copy the pointer + _key = right._key; // EVP_PKEY uses reference counting internally, just copy the pointer + EVP_PKEY_up_ref(_key); // Bump reference count for PKEY, as every instance of this class holds two references to PKEY and destructor decrements it twice _digest = right._digest; return *this; } diff --git a/src/common/Cryptography/RSA.cpp b/src/common/Cryptography/RSA.cpp index e8f8b4966ac..69f2916b343 100644 --- a/src/common/Cryptography/RSA.cpp +++ b/src/common/Cryptography/RSA.cpp @@ -160,30 +160,60 @@ EVP_MD const* RsaSignature::HMAC_SHA256::GetGenerator() const void RsaSignature::HMAC_SHA256::PostInitCustomizeContext(EVP_MD_CTX* ctx) { HMAC_SHA256_MD::CTX_DATA* ctxData = reinterpret_cast<HMAC_SHA256_MD::CTX_DATA*>(EVP_MD_CTX_md_data(ctx)); - if (ctxData->hmac) - delete ctxData->hmac; + delete ctxData->hmac; ctxData->hmac = new Crypto::HMAC_SHA256(_key, _keyLength); } -RsaSignature::RsaSignature() +RsaSignature::RsaSignature() : _ctx(Impl::GenericHashImpl::MakeCTX()) { - _ctx = Impl::GenericHashImpl::MakeCTX(); } -RsaSignature::RsaSignature(RsaSignature&& rsa) noexcept +RsaSignature::RsaSignature(RsaSignature const& other) : _ctx(Impl::GenericHashImpl::MakeCTX()) { - _ctx = rsa._ctx; - rsa._ctx = Impl::GenericHashImpl::MakeCTX(); + *this = other; +} + +RsaSignature::RsaSignature(RsaSignature&& other) noexcept +{ + *this = std::move(other); } RsaSignature::~RsaSignature() { EVP_MD_CTX_free(_ctx); + EVP_PKEY_free(_key); +} + +RsaSignature& RsaSignature::operator=(RsaSignature const& right) +{ + if (this == &right) + return *this; + + EVP_MD_CTX_copy_ex(_ctx, right._ctx); // Allowed to fail if not yet initialized + _key = right._key; // EVP_PKEY uses reference counting internally, just copy the pointer + EVP_PKEY_up_ref(_key); // Bump reference count for PKEY, as every instance of this class holds two references to PKEY and destructor decrements it twice + return *this; +} + +RsaSignature& RsaSignature::operator=(RsaSignature&& right) noexcept +{ + if (this == &right) + return *this; + + _ctx = std::exchange(right._ctx, Impl::GenericHashImpl::MakeCTX()); + _key = std::exchange(right._key, EVP_PKEY_new()); + return *this; } bool RsaSignature::LoadKeyFromFile(std::string const& fileName) { + if (_key) + { + EVP_PKEY_free(_key); + _key = nullptr; + } + std::unique_ptr<BIO, BIODeleter> keyBIO(BIO_new_file(fileName.c_str(), "r")); if (!keyBIO) return false; @@ -197,6 +227,12 @@ bool RsaSignature::LoadKeyFromFile(std::string const& fileName) bool RsaSignature::LoadKeyFromString(std::string const& keyPem) { + if (_key) + { + EVP_PKEY_free(_key); + _key = nullptr; + } + std::unique_ptr<BIO, BIODeleter> keyBIO(BIO_new_mem_buf( const_cast<char*>(keyPem.c_str()) /*api hack - this function assumes memory is readonly but lacks const modifier*/, keyPem.length() + 1)); diff --git a/src/common/Cryptography/RSA.h b/src/common/Cryptography/RSA.h index 9c8399d2fda..18771f14926 100644 --- a/src/common/Cryptography/RSA.h +++ b/src/common/Cryptography/RSA.h @@ -60,11 +60,12 @@ public: }; RsaSignature(); - RsaSignature(RsaSignature&& rsa) noexcept; + RsaSignature(RsaSignature const& other); + RsaSignature(RsaSignature&& other) noexcept; ~RsaSignature(); - RsaSignature(RsaSignature const& rsa) = delete; - RsaSignature& operator=(RsaSignature const& rsa) = delete; + RsaSignature& operator=(RsaSignature const& right); + RsaSignature& operator=(RsaSignature&& right) noexcept; bool LoadKeyFromFile(std::string const& fileName); diff --git a/src/server/game/Server/Packets/AuthenticationPackets.cpp b/src/server/game/Server/Packets/AuthenticationPackets.cpp index e9004a8f5da..7ba0c8b886d 100644 --- a/src/server/game/Server/Packets/AuthenticationPackets.cpp +++ b/src/server/game/Server/Packets/AuthenticationPackets.cpp @@ -247,6 +247,11 @@ bool WorldPackets::Auth::ConnectTo::InitializeEncryption() return true; } +void WorldPackets::Auth::ConnectTo::ShutdownEncryption() +{ + ConnectToRSA.reset(); +} + WorldPackets::Auth::ConnectTo::ConnectTo() : ServerPacket(SMSG_CONNECT_TO, 256 + 1 + 16 + 2 + 4 + 1 + 8) { } @@ -274,9 +279,11 @@ WorldPacket const* WorldPackets::Auth::ConnectTo::Write() signBuffer.append(whereBuffer); signBuffer << uint32(Payload.Where.Type); signBuffer << uint16(Payload.Port); + + Trinity::Crypto::RsaSignature rsa(*ConnectToRSA); Trinity::Crypto::RsaSignature::SHA256 digestGenerator; std::vector<uint8> signature; - ConnectToRSA->Sign(signBuffer.contents(), signBuffer.size(), digestGenerator, signature); + rsa.Sign(signBuffer.contents(), signBuffer.size(), digestGenerator, signature); _worldPacket.append(signature.data(), signature.size()); _worldPacket.append(whereBuffer); @@ -310,10 +317,11 @@ WorldPacket const* WorldPackets::Auth::EnterEncryptedMode::Write() msg[0] = Enabled ? 1 : 0; std::copy_n(std::begin(EnableEncryptionSeed), std::size(EnableEncryptionSeed), &msg[1]); + Trinity::Crypto::RsaSignature rsa(*ConnectToRSA); Trinity::Crypto::RsaSignature::HMAC_SHA256 digestGenerator(EncryptionKey, 16); std::vector<uint8> signature; - ConnectToRSA->Sign(msg, digestGenerator, signature); + rsa.Sign(msg, digestGenerator, signature); _worldPacket.append(signature.data(), signature.size()); _worldPacket.WriteBit(Enabled); diff --git a/src/server/game/Server/Packets/AuthenticationPackets.h b/src/server/game/Server/Packets/AuthenticationPackets.h index 017afed87fb..aa4216ec30e 100644 --- a/src/server/game/Server/Packets/AuthenticationPackets.h +++ b/src/server/game/Server/Packets/AuthenticationPackets.h @@ -203,13 +203,15 @@ namespace WorldPackets WorldAttempt5 = 89 }; - class ConnectTo final : public ServerPacket + class TC_GAME_API ConnectTo final : public ServerPacket { public: static bool InitializeEncryption(); + static void ShutdownEncryption(); enum AddressType : uint8 { + None = 0, IPv4 = 1, IPv6 = 2, NamedSocket = 3 // not supported by windows client @@ -217,20 +219,20 @@ namespace WorldPackets struct SocketAddress { - AddressType Type; + AddressType Type = None; union { std::array<uint8, 4> V4; std::array<uint8, 16> V6; std::array<char, 128> Name; - } Address; + } Address = { }; }; struct ConnectPayload { SocketAddress Where; - uint16 Port; - std::array<uint8, 256> Signature; + uint16 Port = 0; + std::array<uint8, 256> Signature = { }; }; ConnectTo(); diff --git a/src/server/worldserver/Main.cpp b/src/server/worldserver/Main.cpp index 079d4d4102b..e08e9610965 100644 --- a/src/server/worldserver/Main.cpp +++ b/src/server/worldserver/Main.cpp @@ -22,6 +22,7 @@ #include "Common.h" #include "AppenderDB.h" #include "AsyncAcceptor.h" +#include "AuthenticationPackets.h" #include "Banner.h" #include "BattlegroundMgr.h" #include "BigNumber.h" @@ -401,6 +402,8 @@ extern int main(int argc, char** argv) WorldUpdateLoop(); // Shutdown starts here + WorldPackets::Auth::ConnectTo::ShutdownEncryption(); + threadPool.reset(); sLog->SetSynchronous(); |