mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
Core/Crypto: Fixed EVP_PKEY reference counting for copied objects
Closes #27943
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user