aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/Cryptography/CryptoHash.h2
-rw-r--r--src/common/Cryptography/HMAC.h5
-rw-r--r--src/common/Cryptography/RSA.cpp50
-rw-r--r--src/common/Cryptography/RSA.h7
-rw-r--r--src/server/game/Server/Packets/AuthenticationPackets.cpp12
-rw-r--r--src/server/game/Server/Packets/AuthenticationPackets.h12
-rw-r--r--src/server/worldserver/Main.cpp3
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();