Core/Crypto: Switch away from most deprecated openssl functions and removed upper version limit

This commit is contained in:
Shauren
2022-05-03 17:03:57 +02:00
parent c68f52568f
commit bc87f7b337
11 changed files with 325 additions and 214 deletions

View File

@@ -80,7 +80,6 @@ Set ``OPENSSL_MSVC_STATIC_RT`` set ``TRUE`` to choose the MT version of the lib.
#]=======================================================================]
set(OPENSSL_EXPECTED_VERSION "1.0")
set(OPENSSL_MAX_VERSION "1.2")
macro(_OpenSSL_test_and_find_dependencies ssl_library crypto_library)
if((CMAKE_SYSTEM_NAME STREQUAL "Linux") AND
@@ -604,7 +603,7 @@ if(OPENSSL_FOUND)
message(STATUS "Found OpenSSL library: ${OPENSSL_LIBRARIES}")
message(STATUS "Found OpenSSL headers: ${OPENSSL_INCLUDE_DIR}")
include(EnsureVersion)
ENSURE_VERSION_RANGE("${OPENSSL_EXPECTED_VERSION}" "${OPENSSL_VERSION}" "${OPENSSL_MAX_VERSION}" OPENSSL_VERSION_OK)
ENSURE_VERSION("${OPENSSL_EXPECTED_VERSION}" "${OPENSSL_VERSION}" OPENSSL_VERSION_OK)
if(NOT OPENSSL_VERSION_OK)
message(FATAL_ERROR "TrinityCore needs OpenSSL version ${OPENSSL_EXPECTED_VERSION} but found too new version ${OPENSSL_VERSION}. TrinityCore needs OpenSSL 1.0.x or 1.1.x to work properly. If you still have problems please install OpenSSL 1.0.x if you still have problems search on forum for TCE00022")
endif()

View File

@@ -26,6 +26,7 @@ namespace Crypto
{
struct Constants
{
static constexpr size_t MD5_DIGEST_LENGTH_BYTES = 16;
static constexpr size_t SHA1_DIGEST_LENGTH_BYTES = 20;
static constexpr size_t SHA256_DIGEST_LENGTH_BYTES = 32;
};

View File

@@ -35,10 +35,10 @@ namespace Trinity::Impl
typedef EVP_MD const* (*HashCreator)();
#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x10100000L
static EVP_MD_CTX* MakeCTX() { return EVP_MD_CTX_create(); }
static EVP_MD_CTX* MakeCTX() noexcept { return EVP_MD_CTX_create(); }
static void DestroyCTX(EVP_MD_CTX* ctx) { EVP_MD_CTX_destroy(ctx); }
#else
static EVP_MD_CTX* MakeCTX() { return EVP_MD_CTX_new(); }
static EVP_MD_CTX* MakeCTX() noexcept { return EVP_MD_CTX_new(); }
static void DestroyCTX(EVP_MD_CTX* ctx) { EVP_MD_CTX_free(ctx); }
#endif
};
@@ -73,6 +73,16 @@ namespace Trinity::Impl
ASSERT(result == 1);
}
GenericHash(GenericHash const& right) : _ctx(GenericHashImpl::MakeCTX())
{
*this = right;
}
GenericHash(GenericHash&& right) noexcept
{
*this = std::move(right);
}
~GenericHash()
{
if (!_ctx)
@@ -81,6 +91,27 @@ namespace Trinity::Impl
_ctx = nullptr;
}
GenericHash& operator=(GenericHash const& right)
{
if (this == &right)
return *this;
int result = EVP_MD_CTX_copy(_ctx, right._ctx);
ASSERT(result == 1);
_digest = right._digest;
return *this;
}
GenericHash& operator=(GenericHash&& right) noexcept
{
if (this == &right)
return *this;
_ctx = std::exchange(right._ctx, GenericHashImpl::MakeCTX());
_digest = std::exchange(right._digest, Digest{});
return *this;
}
void UpdateData(uint8 const* data, size_t len)
{
int result = EVP_DigestUpdate(_ctx, data, len);
@@ -98,8 +129,6 @@ namespace Trinity::Impl
int result = EVP_DigestFinal_ex(_ctx, _digest.data(), &length);
ASSERT(result == 1);
ASSERT(length == DIGEST_LENGTH);
GenericHashImpl::DestroyCTX(_ctx);
_ctx = nullptr;
}
Digest const& GetDigest() const { return _digest; }
@@ -112,6 +141,7 @@ namespace Trinity::Impl
namespace Trinity::Crypto
{
using MD5 = Trinity::Impl::GenericHash<EVP_md5, Constants::MD5_DIGEST_LENGTH_BYTES>;
using SHA1 = Trinity::Impl::GenericHash<EVP_sha1, Constants::SHA1_DIGEST_LENGTH_BYTES>;
using SHA256 = Trinity::Impl::GenericHash<EVP_sha256, Constants::SHA256_DIGEST_LENGTH_BYTES>;
}

View File

@@ -19,41 +19,18 @@
#define TRINITY_HMAC_H
#include "CryptoConstants.h"
#include "CryptoHash.h"
#include "Define.h"
#include "Errors.h"
#include <array>
#include <string>
#include <string_view>
#include <openssl/hmac.h>
class BigNumber;
namespace Trinity::Impl
{
struct HMACImpl
{
typedef EVP_MD const* (*HashCreator)();
#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x10100000L
static HMAC_CTX* MakeCTX()
{
HMAC_CTX* ctx = new HMAC_CTX();
HMAC_CTX_init(ctx);
return ctx;
}
static void DestroyCTX(HMAC_CTX* ctx)
{
HMAC_CTX_cleanup(ctx);
delete ctx;
}
#else
static HMAC_CTX* MakeCTX() { return HMAC_CTX_new(); }
static void DestroyCTX(HMAC_CTX* ctx) { HMAC_CTX_free(ctx); }
#endif
};
template <HMACImpl::HashCreator HashCreator, size_t DigestLength>
template <GenericHashImpl::HashCreator HashCreator, size_t DigestLength>
class GenericHMAC
{
public:
@@ -78,25 +55,58 @@ namespace Trinity::Impl
return hash.GetDigest();
}
GenericHMAC(uint8 const* seed, size_t len) : _ctx(HMACImpl::MakeCTX())
GenericHMAC(uint8 const* seed, size_t len) : _ctx(GenericHashImpl::MakeCTX()), _key(EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, nullptr, seed, len))
{
int result = HMAC_Init_ex(_ctx, seed, len, HashCreator(), nullptr);
int result = EVP_DigestSignInit(_ctx, nullptr, HashCreator(), nullptr, _key);
ASSERT(result == 1);
}
template <typename Container>
GenericHMAC(Container const& container) : GenericHMAC(std::data(container), std::size(container)) {}
GenericHMAC(GenericHMAC const& right) : _ctx(GenericHashImpl::MakeCTX())
{
*this = right;
}
GenericHMAC(GenericHMAC&& right) noexcept
{
*this = std::move(right);
}
~GenericHMAC()
{
if (!_ctx)
return;
HMACImpl::DestroyCTX(_ctx);
GenericHashImpl::DestroyCTX(_ctx);
_ctx = nullptr;
EVP_PKEY_free(_key);
_key = nullptr;
}
GenericHMAC& operator=(GenericHMAC const& right)
{
if (this == &right)
return *this;
int result = EVP_MD_CTX_copy(_ctx, right._ctx);
ASSERT(result == 1);
_key = right._key; // EVP_PKEY uses reference counting internally, just copy the pointer
_digest = right._digest;
return *this;
}
GenericHMAC& operator=(GenericHMAC&& right) noexcept
{
if (this == &right)
return *this;
_ctx = std::exchange(right._ctx, GenericHashImpl::MakeCTX());
_key = std::exchange(right._key, EVP_PKEY_new());
_digest = std::exchange(right._digest, Digest{});
return *this;
}
void UpdateData(uint8 const* data, size_t len)
{
int result = HMAC_Update(_ctx, data, len);
int result = EVP_DigestSignUpdate(_ctx, data, len);
ASSERT(result == 1);
}
void UpdateData(std::string_view str) { UpdateData(reinterpret_cast<uint8 const*>(str.data()), str.size()); }
@@ -107,17 +117,16 @@ namespace Trinity::Impl
void Finalize()
{
uint32 length = 0;
int result = HMAC_Final(_ctx, _digest.data(), &length);
size_t length = 0;
int result = EVP_DigestSignFinal(_ctx, _digest.data(), &length);
ASSERT(result == 1);
ASSERT(length == DIGEST_LENGTH);
HMACImpl::DestroyCTX(_ctx);
_ctx = nullptr;
}
Digest const& GetDigest() const { return _digest; }
private:
HMAC_CTX* _ctx;
EVP_MD_CTX* _ctx;
EVP_PKEY* _key;
Digest _digest = { };
};
}

View File

@@ -16,22 +16,12 @@
*/
#include "RSA.h"
#include "BigNumber.h"
#include <openssl/bn.h>
#include "HMAC.h"
#include <openssl/pem.h>
#include <algorithm>
#include <iterator>
#include <memory>
#include <vector>
#define CHECK_AND_DECLARE_FUNCTION_TYPE(name, publicKey, privateKey) \
static_assert(std::is_same<decltype(&publicKey), decltype(&privateKey)>::value, \
"Public key and private key functions must have the same signature"); \
using name ## _t = decltype(&publicKey); \
template <typename KeyTag> inline name ## _t get_ ## name () { return nullptr; } \
template <> inline name ## _t get_ ## name<Trinity::Crypto::RSA::PublicKey>() { return &publicKey; } \
template <> inline name ## _t get_ ## name<Trinity::Crypto::RSA::PrivateKey>() { return &privateKey; }
namespace
{
struct BIODeleter
@@ -42,41 +32,170 @@ struct BIODeleter
}
};
CHECK_AND_DECLARE_FUNCTION_TYPE(PEM_read, PEM_read_bio_RSAPublicKey, PEM_read_bio_RSAPrivateKey);
CHECK_AND_DECLARE_FUNCTION_TYPE(RSA_encrypt, RSA_public_encrypt, RSA_private_encrypt);
}
Trinity::Crypto::RSA::RSA()
struct HMAC_SHA256_MD
{
_rsa = RSA_new();
struct CTX_DATA
{
Trinity::Crypto::HMAC_SHA256* hmac;
};
#if TRINITY_COMPILER == TRINITY_COMPILER_GNU
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#else
#pragma warning(push)
#pragma warning(disable: 4996)
#endif
HMAC_SHA256_MD()
{
_md = EVP_MD_meth_new(NID_sha256, NID_sha256WithRSAEncryption);
EVP_MD_meth_set_result_size(_md, Trinity::Crypto::Constants::SHA256_DIGEST_LENGTH_BYTES);
EVP_MD_meth_set_flags(_md, EVP_MD_FLAG_DIGALGID_ABSENT);
EVP_MD_meth_set_init(_md, &Init);
EVP_MD_meth_set_update(_md, &UpdateData);
EVP_MD_meth_set_final(_md, &Finalize);
EVP_MD_meth_set_copy(_md, &Copy);
EVP_MD_meth_set_cleanup(_md, &Cleanup);
EVP_MD_meth_set_input_blocksize(_md, SHA256_CBLOCK);
EVP_MD_meth_set_app_datasize(_md, sizeof(EVP_MD*) + sizeof(CTX_DATA*));
}
HMAC_SHA256_MD(HMAC_SHA256_MD const&) = delete;
HMAC_SHA256_MD(HMAC_SHA256_MD&&) = delete;
HMAC_SHA256_MD& operator=(HMAC_SHA256_MD const&) = delete;
HMAC_SHA256_MD& operator=(HMAC_SHA256_MD&&) = delete;
~HMAC_SHA256_MD()
{
EVP_MD_meth_free(_md);
_md = nullptr;
}
#if TRINITY_COMPILER == TRINITY_COMPILER_GNU
#pragma GCC diagnostic pop
#else
#pragma warning(pop)
#endif
operator EVP_MD const* () const
{
return _md;
}
static int Init(EVP_MD_CTX* ctx)
{
Cleanup(ctx);
return 1;
}
static int UpdateData(EVP_MD_CTX* ctx, const void* data, size_t count)
{
CTX_DATA* ctxData = reinterpret_cast<CTX_DATA*>(EVP_MD_CTX_md_data(ctx));
if (!ctxData->hmac)
return 0;
ctxData->hmac->UpdateData(reinterpret_cast<uint8 const*>(data), count);
return 1;
}
static int Finalize(EVP_MD_CTX* ctx, unsigned char* md)
{
CTX_DATA* ctxData = reinterpret_cast<CTX_DATA*>(EVP_MD_CTX_md_data(ctx));
if (!ctxData->hmac)
return 0;
ctxData->hmac->Finalize();
memcpy(md, ctxData->hmac->GetDigest().data(), ctxData->hmac->GetDigest().size());
return 1;
}
// post-processing after openssl memcpys from source to dest (no need to cleanup dest)
static int Copy(EVP_MD_CTX* to, EVP_MD_CTX const* from)
{
CTX_DATA const* ctxDataFrom = reinterpret_cast<CTX_DATA const*>(EVP_MD_CTX_md_data(from));
CTX_DATA* ctxDataTo = reinterpret_cast<CTX_DATA*>(EVP_MD_CTX_md_data(to));
if (ctxDataFrom->hmac)
ctxDataTo->hmac = new Trinity::Crypto::HMAC_SHA256(*ctxDataFrom->hmac);
return 1;
}
static int Cleanup(EVP_MD_CTX* ctx)
{
CTX_DATA* data = reinterpret_cast<CTX_DATA*>(EVP_MD_CTX_md_data(ctx));
if (data->hmac)
{
delete data->hmac;
data->hmac = nullptr;
}
return 1;
}
private:
EVP_MD* _md;
} HmacSha256Md;
}
Trinity::Crypto::RSA::RSA(RSA&& rsa)
namespace Trinity::Crypto
{
_rsa = rsa._rsa;
rsa._rsa = RSA_new();
}
Trinity::Crypto::RSA::~RSA()
EVP_MD const* RsaSignature::SHA256::GetGenerator() const
{
RSA_free(_rsa);
return EVP_sha256();
}
template <typename KeyTag>
bool Trinity::Crypto::RSA::LoadFromFile(std::string const& fileName, KeyTag)
void RsaSignature::SHA256::PostInitCustomizeContext(EVP_MD_CTX*)
{
}
EVP_MD const* RsaSignature::HMAC_SHA256::GetGenerator() const
{
return HmacSha256Md;
}
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;
ctxData->hmac = new Crypto::HMAC_SHA256(_key, _keyLength);
}
RsaSignature::RsaSignature()
{
_ctx = Impl::GenericHashImpl::MakeCTX();
}
RsaSignature::RsaSignature(RsaSignature&& rsa) noexcept
{
_ctx = rsa._ctx;
rsa._ctx = Impl::GenericHashImpl::MakeCTX();
}
RsaSignature::~RsaSignature()
{
EVP_MD_CTX_free(_ctx);
}
bool RsaSignature::LoadKeyFromFile(std::string const& fileName)
{
std::unique_ptr<BIO, BIODeleter> keyBIO(BIO_new_file(fileName.c_str(), "r"));
if (!keyBIO)
return false;
if (!get_PEM_read<KeyTag>()(keyBIO.get(), &_rsa, nullptr, nullptr))
_key = EVP_PKEY_new();
if (!PEM_read_bio_PrivateKey(keyBIO.get(), &_key, nullptr, nullptr))
return false;
return true;
}
template <typename KeyTag>
bool Trinity::Crypto::RSA::LoadFromString(std::string const& keyPem, KeyTag)
bool RsaSignature::LoadKeyFromString(std::string const& keyPem)
{
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*/,
@@ -84,51 +203,26 @@ bool Trinity::Crypto::RSA::LoadFromString(std::string const& keyPem, KeyTag)
if (!keyBIO)
return false;
if (!get_PEM_read<KeyTag>()(keyBIO.get(), &_rsa, nullptr, nullptr))
_key = EVP_PKEY_new();
if (!PEM_read_bio_PrivateKey(keyBIO.get(), &_key, nullptr, nullptr))
return false;
return true;
}
BigNumber Trinity::Crypto::RSA::GetModulus() const
bool RsaSignature::Sign(uint8 const* message, std::size_t messageLength, DigestGenerator& generator, std::vector<uint8>& output)
{
BigNumber bn;
#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L
const BIGNUM* rsa_n;
RSA_get0_key(_rsa, &rsa_n, nullptr, nullptr);
BN_copy(bn.BN(), rsa_n);
#else
BN_copy(bn.BN(), _rsa->n);
#endif
return bn;
}
size_t signatureLength = 0;
EVP_DigestSignInit(_ctx, nullptr, generator.GetGenerator(), nullptr, _key);
generator.PostInitCustomizeContext(_ctx);
EVP_DigestSignUpdate(_ctx, message, messageLength);
int result = EVP_DigestSignFinal(_ctx, nullptr, &signatureLength);
if (result == 0)
return false;
template <typename KeyTag>
bool Trinity::Crypto::RSA::Encrypt(uint8 const* data, std::size_t dataLength, uint8* output, int32 paddingType)
{
std::vector<uint8> inputData(std::make_reverse_iterator(data + dataLength), std::make_reverse_iterator(data));
int result = get_RSA_encrypt<KeyTag>()(inputData.size(), inputData.data(), output, _rsa, paddingType);
std::reverse(output, output + GetOutputSize());
return result != -1;
}
bool Trinity::Crypto::RSA::Sign(int32 hashType, uint8 const* dataHash, std::size_t dataHashLength, uint8* output)
{
uint32 signatureLength = 0;
int result = RSA_sign(hashType, dataHash, dataHashLength, output, &signatureLength, _rsa);
std::reverse(output, output + GetOutputSize());
output.resize(signatureLength);
result = EVP_DigestSignFinal(_ctx, output.data(), &signatureLength);
std::reverse(output.begin(), output.end());
return result != 0;
}
namespace Trinity
{
namespace Crypto
{
template TC_COMMON_API bool RSA::LoadFromFile(std::string const& fileName, RSA::PublicKey);
template TC_COMMON_API bool RSA::LoadFromFile(std::string const& fileName, RSA::PrivateKey);
template TC_COMMON_API bool RSA::LoadFromString(std::string const& keyPem, RSA::PublicKey);
template TC_COMMON_API bool RSA::LoadFromString(std::string const& keyPem, RSA::PrivateKey);
template TC_COMMON_API bool RSA::Encrypt<RSA::PublicKey>(uint8 const* data, std::size_t dataLength, uint8* output, int32 paddingType);
template TC_COMMON_API bool RSA::Encrypt<RSA::PrivateKey>(uint8 const* data, std::size_t dataLength, uint8* output, int32 paddingType);
}
}

View File

@@ -15,77 +15,75 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TRINITYCORE_RSA_H
#define TRINITYCORE_RSA_H
#include "Define.h"
#include <openssl/objects.h>
#include <openssl/rsa.h>
#include <openssl/evp.h>
#include <array>
#include <string>
#include <type_traits>
class BigNumber;
#include <vector>
namespace Trinity
{
namespace Crypto
{
class TC_COMMON_API RSA
class TC_COMMON_API RsaSignature
{
public:
struct PublicKey {};
struct PrivateKey {};
struct NoPadding : std::integral_constant<int32, RSA_NO_PADDING> {};
struct PKCS1Padding : std::integral_constant<int32, RSA_PKCS1_PADDING> {};
struct SHA256 : std::integral_constant<int32, NID_sha256> {};
RSA();
RSA(RSA&& rsa);
~RSA();
template <typename KeyTag>
bool LoadFromFile(std::string const& fileName, KeyTag);
template <typename KeyTag>
bool LoadFromString(std::string const& keyPem, KeyTag);
uint32 GetOutputSize() const { return uint32(RSA_size(_rsa)); }
BigNumber GetModulus() const;
template <typename KeyTag, typename PaddingTag>
bool Encrypt(uint8 const* data, std::size_t dataLength, uint8* output, KeyTag, PaddingTag)
class TC_COMMON_API DigestGenerator
{
return Encrypt<KeyTag>(data, dataLength, output, PaddingTag::value);
public:
virtual ~DigestGenerator() = default;
virtual EVP_MD const* GetGenerator() const = 0;
virtual void PostInitCustomizeContext(EVP_MD_CTX* ctx) = 0;
};
class TC_COMMON_API SHA256 : public DigestGenerator
{
public:
EVP_MD const* GetGenerator() const override;
void PostInitCustomizeContext(EVP_MD_CTX* ctx) override;
};
class TC_COMMON_API HMAC_SHA256 : public DigestGenerator
{
public:
explicit HMAC_SHA256(uint8 const* key, size_t keyLength) : _key(key), _keyLength(keyLength) { }
EVP_MD const* GetGenerator() const override;
void PostInitCustomizeContext(EVP_MD_CTX* ctx) override;
private:
uint8 const* _key;
size_t _keyLength;
};
RsaSignature();
RsaSignature(RsaSignature&& rsa) noexcept;
~RsaSignature();
RsaSignature(RsaSignature const& rsa) = delete;
RsaSignature& operator=(RsaSignature const& rsa) = delete;
bool LoadKeyFromFile(std::string const& fileName);
bool LoadKeyFromString(std::string const& keyPem);
template <std::size_t N>
bool Sign(std::array<uint8, N> const& message, DigestGenerator& generator, std::vector<uint8>& output)
{
return this->Sign(message.data(), message.size(), generator, output);
}
template <std::size_t N, typename KeyTag, typename PaddingTag>
bool Encrypt(std::array<uint8, N> const& data, uint8* output, KeyTag, PaddingTag)
{
return Encrypt<KeyTag>(data.data(), data.size(), output, PaddingTag::value);
}
template <typename HashTag>
bool Sign(uint8 const* dataHash, std::size_t dataHashLength, uint8* output, HashTag)
{
return Sign(HashTag::value, dataHash, dataHashLength, output);
}
template <std::size_t N, typename HashTag>
bool Sign(std::array<uint8, N> const& dataHash, uint8* output, HashTag)
{
return Sign(HashTag::value, dataHash.data(), dataHash.size(), output);
}
bool Sign(uint8 const* message, std::size_t messageLength, DigestGenerator& generator, std::vector<uint8>& output);
private:
template <typename KeyTag>
bool Encrypt(uint8 const* data, std::size_t dataLength, uint8* output, int32 paddingType);
bool Sign(int32 hashType, uint8 const* dataHash, std::size_t dataHashLength, uint8* output);
RSA(RSA const& rsa) = delete;
RSA& operator=(RSA const& rsa) = delete;
::RSA* _rsa;
EVP_MD_CTX* _ctx = nullptr;
EVP_PKEY* _key = nullptr;
};
}
}
#endif // TRINITYCORE_RSA_H

View File

@@ -126,7 +126,7 @@ int main(int argc, char** argv)
[]()
{
TC_LOG_INFO("server.bnetserver", "Using configuration file %s.", sConfigMgr->GetFilename().c_str());
TC_LOG_INFO("server.bnetserver", "Using SSL version: %s (library: %s)", OPENSSL_VERSION_TEXT, SSLeay_version(SSLEAY_VERSION));
TC_LOG_INFO("server.bnetserver", "Using SSL version: %s (library: %s)", OPENSSL_VERSION_TEXT, OpenSSL_version(OPENSSL_VERSION));
TC_LOG_INFO("server.bnetserver", "Using Boost version: %i.%i.%i", BOOST_VERSION / 100000, BOOST_VERSION / 100 % 1000, BOOST_VERSION % 100);
}
);

View File

@@ -234,13 +234,13 @@ OHYtKG3GK3GEcFDwZU2LPHq21EroUAdtRfbrJ4KW2yc8igtXKxTBYw==
-----END RSA PRIVATE KEY-----
)";
std::unique_ptr<Trinity::Crypto::RSA> ConnectToRSA;
std::unique_ptr<Trinity::Crypto::RsaSignature> ConnectToRSA;
}
bool WorldPackets::Auth::ConnectTo::InitializeEncryption()
{
std::unique_ptr<Trinity::Crypto::RSA> rsa = std::make_unique<Trinity::Crypto::RSA>();
if (!rsa->LoadFromString(RSAPrivateKey, Trinity::Crypto::RSA::PrivateKey{}))
std::unique_ptr<Trinity::Crypto::RsaSignature> rsa = std::make_unique<Trinity::Crypto::RsaSignature>();
if (!rsa->LoadKeyFromString(RSAPrivateKey))
return false;
ConnectToRSA = std::move(rsa);
@@ -270,16 +270,15 @@ WorldPacket const* WorldPackets::Auth::ConnectTo::Write()
break;
}
uint32 type = Payload.Where.Type;
Trinity::Crypto::SHA256 hash;
hash.UpdateData(whereBuffer.contents(), whereBuffer.size());
hash.UpdateData(reinterpret_cast<uint8 const*>(&type), 4);
hash.UpdateData(reinterpret_cast<uint8 const*>(&Payload.Port), 2);
hash.Finalize();
ByteBuffer signBuffer;
signBuffer.append(whereBuffer);
signBuffer << uint32(Payload.Where.Type);
signBuffer << uint16(Payload.Port);
Trinity::Crypto::RsaSignature::SHA256 digestGenerator;
std::vector<uint8> signature;
ConnectToRSA->Sign(signBuffer.contents(), signBuffer.size(), digestGenerator, signature);
ConnectToRSA->Sign(hash.GetDigest(), Payload.Signature.data(), Trinity::Crypto::RSA::SHA256{});
_worldPacket.append(Payload.Signature.data(), Payload.Signature.size());
_worldPacket.append(signature.data(), signature.size());
_worldPacket.append(whereBuffer);
_worldPacket << uint16(Payload.Port);
_worldPacket << uint32(Serial);
@@ -307,15 +306,16 @@ uint8 constexpr EnableEncryptionSeed[16] = { 0x90, 0x9C, 0xD0, 0x50, 0x5A, 0x2C,
WorldPacket const* WorldPackets::Auth::EnterEncryptedMode::Write()
{
Trinity::Crypto::HMAC_SHA256 hash(EncryptionKey, 16);
hash.UpdateData(reinterpret_cast<uint8 const*>(&Enabled), 1);
hash.UpdateData(EnableEncryptionSeed, 16);
hash.Finalize();
std::array<uint8, 17> msg{};
msg[0] = Enabled ? 1 : 0;
std::copy_n(std::begin(EnableEncryptionSeed), std::size(EnableEncryptionSeed), &msg[1]);
_worldPacket.resize(_worldPacket.size() + ConnectToRSA->GetOutputSize());
Trinity::Crypto::RsaSignature::HMAC_SHA256 digestGenerator(EncryptionKey, 16);
std::vector<uint8> signature;
ConnectToRSA->Sign(hash.GetDigest(), _worldPacket.contents(), Trinity::Crypto::RSA::SHA256{});
ConnectToRSA->Sign(msg, digestGenerator, signature);
_worldPacket.append(signature.data(), signature.size());
_worldPacket.WriteBit(Enabled);
_worldPacket.FlushBits();

View File

@@ -19,6 +19,7 @@
#include "AccountMgr.h"
#include "ByteBuffer.h"
#include "Common.h"
#include "CryptoHash.h"
#include "GameTime.h"
#include "Log.h"
#include "SmartEnum.h"
@@ -27,10 +28,6 @@
#include "World.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include <openssl/md5.h>
#include <openssl/sha.h>
#include <charconv>
Warden::Warden() : _session(nullptr), _checkTimer(10 * IN_MILLISECONDS), _clientResponseTimer(0),
@@ -48,10 +45,7 @@ void Warden::MakeModuleForClient()
TC_LOG_DEBUG("warden", "Make module for client");
InitializeModuleForClient(_module.emplace());
MD5_CTX ctx;
MD5_Init(&ctx);
MD5_Update(&ctx, _module->CompressedData, _module->CompressedSize);
MD5_Final(_module->Id.data(), &ctx);
_module->Id = Trinity::Crypto::MD5::GetDigestOf(_module->CompressedData, _module->CompressedSize);
}
void Warden::SendModuleToClient()
@@ -161,28 +155,19 @@ bool Warden::IsValidCheckSum(uint32 checksum, uint8 const* data, const uint16 le
}
}
struct keyData {
union
{
struct
{
uint8 bytes[20];
} bytes;
struct
{
uint32 ints[5];
} ints;
};
union keyData
{
std::array<uint8, 20> bytes;
std::array<uint32, 5> ints;
};
uint32 Warden::BuildChecksum(uint8 const* data, uint32 length)
{
keyData hash;
SHA1(data, length, hash.bytes.bytes);
hash.bytes = Trinity::Crypto::SHA1::GetDigestOf(data, size_t(length));
uint32 checkSum = 0;
for (uint8 i = 0; i < 5; ++i)
checkSum = checkSum ^ hash.ints.ints[i];
checkSum = checkSum ^ hash.ints[i];
return checkSum;
}

View File

@@ -18,6 +18,7 @@
#include "WardenMac.h"
#include "ByteBuffer.h"
#include "Common.h"
#include "CryptoHash.h"
#include "GameTime.h"
#include "Log.h"
#include "Opcodes.h"
@@ -27,7 +28,6 @@
#include "WorldPacket.h"
#include "WorldSession.h"
#include <openssl/md5.h>
#include <array>
WardenMac::WardenMac() : Warden() { }
@@ -230,12 +230,7 @@ void WardenMac::HandleCheckResult(ByteBuffer &buff)
//found = true;
}
MD5_CTX ctx;
MD5_Init(&ctx);
MD5_Update(&ctx, str.c_str(), str.size());
std::array<uint8, 16> ourMD5Hash;
MD5_Final(ourMD5Hash.data(), &ctx);
std::array<uint8, 16> ourMD5Hash = Trinity::Crypto::MD5::GetDigestOf(str);
std::array<uint8, 16> theirsMD5Hash;
buff.read(theirsMD5Hash);

View File

@@ -208,7 +208,7 @@ extern int main(int argc, char** argv)
[]()
{
TC_LOG_INFO("server.worldserver", "Using configuration file %s.", sConfigMgr->GetFilename().c_str());
TC_LOG_INFO("server.worldserver", "Using SSL version: %s (library: %s)", OPENSSL_VERSION_TEXT, SSLeay_version(SSLEAY_VERSION));
TC_LOG_INFO("server.worldserver", "Using SSL version: %s (library: %s)", OPENSSL_VERSION_TEXT, OpenSSL_version(OPENSSL_VERSION));
TC_LOG_INFO("server.worldserver", "Using Boost version: %i.%i.%i", BOOST_VERSION / 100000, BOOST_VERSION / 100 % 1000, BOOST_VERSION % 100);
}
);