diff options
Diffstat (limited to 'src/common')
25 files changed, 763 insertions, 525 deletions
diff --git a/src/common/Cryptography/AES.cpp b/src/common/Cryptography/AES.cpp index 08762e224e9..7d4ccc7c46f 100644 --- a/src/common/Cryptography/AES.cpp +++ b/src/common/Cryptography/AES.cpp @@ -16,11 +16,14 @@ */ #include "AES.h" +#include "Errors.h" +#include <limits> Trinity::Crypto::AES::AES(bool encrypting) : _ctx(EVP_CIPHER_CTX_new()), _encrypting(encrypting) { EVP_CIPHER_CTX_init(_ctx); - EVP_CipherInit_ex(_ctx, EVP_aes_128_gcm(), nullptr, nullptr, nullptr, _encrypting ? 1 : 0); + int status = EVP_CipherInit_ex(_ctx, EVP_aes_128_gcm(), nullptr, nullptr, nullptr, _encrypting ? 1 : 0); + ASSERT(status); } Trinity::Crypto::AES::~AES() @@ -28,26 +31,33 @@ Trinity::Crypto::AES::~AES() EVP_CIPHER_CTX_free(_ctx); } -void Trinity::Crypto::AES::Init(uint8 const* key) +void Trinity::Crypto::AES::Init(Key const& key) { - EVP_CipherInit_ex(_ctx, nullptr, nullptr, key, nullptr, -1); + int status = EVP_CipherInit_ex(_ctx, nullptr, nullptr, key.data(), nullptr, -1); + ASSERT(status); } -bool Trinity::Crypto::AES::Process(uint8 const* iv, uint8* data, std::size_t length, uint8(&tag)[12]) +bool Trinity::Crypto::AES::Process(IV const& iv, uint8* data, size_t length, Tag& tag) { - if (!EVP_CipherInit_ex(_ctx, nullptr, nullptr, nullptr, iv, -1)) + ASSERT(length <= std::numeric_limits<int>::max()); + int len = static_cast<int>(length); + if (!EVP_CipherInit_ex(_ctx, nullptr, nullptr, nullptr, iv.data(), -1)) return false; int outLen; - if (!EVP_CipherUpdate(_ctx, data, &outLen, data, length)) + if (!EVP_CipherUpdate(_ctx, data, &outLen, data, len)) return false; + len -= outLen; + if (!_encrypting && !EVP_CIPHER_CTX_ctrl(_ctx, EVP_CTRL_GCM_SET_TAG, sizeof(tag), tag)) return false; if (!EVP_CipherFinal_ex(_ctx, data + outLen, &outLen)) return false; + ASSERT(len == outLen); + if (_encrypting && !EVP_CIPHER_CTX_ctrl(_ctx, EVP_CTRL_GCM_GET_TAG, sizeof(tag), tag)) return false; diff --git a/src/common/Cryptography/AES.h b/src/common/Cryptography/AES.h index 8f83b2e3e57..d3b9f48c552 100644 --- a/src/common/Cryptography/AES.h +++ b/src/common/Cryptography/AES.h @@ -19,26 +19,35 @@ #define Trinity_AES_h__ #include "Define.h" +#include <array> #include <openssl/evp.h> namespace Trinity { namespace Crypto { -class TC_COMMON_API AES -{ -public: - AES(bool encrypting); - ~AES(); + class TC_COMMON_API AES + { + public: + static constexpr size_t IV_SIZE_BYTES = 12; + static constexpr size_t KEY_SIZE_BYTES = 16; + static constexpr size_t TAG_SIZE_BYTES = 12; + + using IV = std::array<uint8, IV_SIZE_BYTES>; + using Key = std::array<uint8, KEY_SIZE_BYTES>; + using Tag = uint8[TAG_SIZE_BYTES]; + + AES(bool encrypting); + ~AES(); - void Init(uint8 const* key); + void Init(Key const& key); - bool Process(uint8 const* iv, uint8* data, std::size_t length, uint8(&tag)[12]); + bool Process(IV const& iv, uint8* data, size_t length, Tag& tag); -private: - EVP_CIPHER_CTX* _ctx; - bool _encrypting; -}; + private: + EVP_CIPHER_CTX* _ctx; + bool _encrypting; + }; } } diff --git a/src/common/Cryptography/ARC4.cpp b/src/common/Cryptography/ARC4.cpp index fe32fec8ef4..161303e2c15 100644 --- a/src/common/Cryptography/ARC4.cpp +++ b/src/common/Cryptography/ARC4.cpp @@ -16,35 +16,33 @@ */ #include "ARC4.h" +#include "Errors.h" -ARC4::ARC4(uint32 len) : m_ctx(EVP_CIPHER_CTX_new()) +Trinity::Crypto::ARC4::ARC4() : _ctx(EVP_CIPHER_CTX_new()) { - EVP_CIPHER_CTX_init(m_ctx); - EVP_EncryptInit_ex(m_ctx, EVP_rc4(), nullptr, nullptr, nullptr); - EVP_CIPHER_CTX_set_key_length(m_ctx, len); + EVP_CIPHER_CTX_init(_ctx); + int result = EVP_EncryptInit_ex(_ctx, EVP_rc4(), nullptr, nullptr, nullptr); + ASSERT(result == 1); } -ARC4::ARC4(uint8* seed, uint32 len) : m_ctx(EVP_CIPHER_CTX_new()) +Trinity::Crypto::ARC4::~ARC4() { - EVP_CIPHER_CTX_init(m_ctx); - EVP_EncryptInit_ex(m_ctx, EVP_rc4(), nullptr, nullptr, nullptr); - EVP_CIPHER_CTX_set_key_length(m_ctx, len); - EVP_EncryptInit_ex(m_ctx, nullptr, nullptr, seed, nullptr); + EVP_CIPHER_CTX_free(_ctx); } -ARC4::~ARC4() +void Trinity::Crypto::ARC4::Init(uint8 const* seed, size_t len) { - EVP_CIPHER_CTX_free(m_ctx); + int result1 = EVP_CIPHER_CTX_set_key_length(_ctx, len); + ASSERT(result1 == 1); + int result2 = EVP_EncryptInit_ex(_ctx, nullptr, nullptr, seed, nullptr); + ASSERT(result2 == 1); } -void ARC4::Init(uint8* seed) -{ - EVP_EncryptInit_ex(m_ctx, nullptr, nullptr, seed, nullptr); -} - -void ARC4::UpdateData(int len, uint8* data) +void Trinity::Crypto::ARC4::UpdateData(uint8* data, size_t len) { int outlen = 0; - EVP_EncryptUpdate(m_ctx, data, &outlen, data, len); - EVP_EncryptFinal_ex(m_ctx, data, &outlen); + int result1 = EVP_EncryptUpdate(_ctx, data, &outlen, data, len); + ASSERT(result1 == 1); + int result2 = EVP_EncryptFinal_ex(_ctx, data, &outlen); + ASSERT(result2 == 1); } diff --git a/src/common/Cryptography/ARC4.h b/src/common/Cryptography/ARC4.h index e0b0d2d39b6..2adfba919ec 100644 --- a/src/common/Cryptography/ARC4.h +++ b/src/common/Cryptography/ARC4.h @@ -19,18 +19,31 @@ #define _AUTH_SARC4_H #include "Define.h" +#include <array> #include <openssl/evp.h> +#include "advstd.h" // data/size -class TC_COMMON_API ARC4 +namespace Trinity { - public: - ARC4(uint32 len); - ARC4(uint8* seed, uint32 len); - ~ARC4(); - void Init(uint8* seed); - void UpdateData(int len, uint8* data); - private: - EVP_CIPHER_CTX* m_ctx; -}; +namespace Crypto +{ + class TC_COMMON_API ARC4 + { + public: + ARC4(); + ~ARC4(); + + void Init(uint8 const* seed, size_t len); + template <typename Container> + void Init(Container const& c) { Init(advstd::data(c), advstd::size(c)); } + + void UpdateData(uint8* data, size_t len); + template <typename Container> + void UpdateData(Container& c) { UpdateData(advstd::data(c), advstd::size(c)); } + private: + EVP_CIPHER_CTX* _ctx; + }; +} +} #endif diff --git a/src/common/Cryptography/Authentication/WorldPacketCrypt.cpp b/src/common/Cryptography/Authentication/WorldPacketCrypt.cpp index 6385c5cfd83..723657048d5 100644 --- a/src/common/Cryptography/Authentication/WorldPacketCrypt.cpp +++ b/src/common/Cryptography/Authentication/WorldPacketCrypt.cpp @@ -23,7 +23,7 @@ WorldPacketCrypt::WorldPacketCrypt() : _clientDecrypt(false), _serverEncrypt(tru { } -void WorldPacketCrypt::Init(uint8 const* key) +void WorldPacketCrypt::Init(Trinity::Crypto::AES::Key const& key) { _clientDecrypt.Init(key); _serverEncrypt.Init(key); @@ -41,12 +41,12 @@ struct WorldPacketCryptIV std::array<uint8, 12> Value; }; -bool WorldPacketCrypt::DecryptRecv(uint8* data, size_t length, uint8 (&tag)[12]) +bool WorldPacketCrypt::DecryptRecv(uint8* data, size_t length, Trinity::Crypto::AES::Tag& tag) { if (_initialized) { WorldPacketCryptIV iv{ _clientCounter, 0x544E4C43 }; - if (!_clientDecrypt.Process(iv.Value.data(), data, length, tag)) + if (!_clientDecrypt.Process(iv.Value, data, length, tag)) return false; } else @@ -56,12 +56,12 @@ bool WorldPacketCrypt::DecryptRecv(uint8* data, size_t length, uint8 (&tag)[12]) return true; } -bool WorldPacketCrypt::EncryptSend(uint8* data, size_t length, uint8 (&tag)[12]) +bool WorldPacketCrypt::EncryptSend(uint8* data, size_t length, Trinity::Crypto::AES::Tag& tag) { if (_initialized) { WorldPacketCryptIV iv{ _serverCounter, 0x52565253 }; - if (!_serverEncrypt.Process(iv.Value.data(), data, length, tag)) + if (!_serverEncrypt.Process(iv.Value, data, length, tag)) return false; } else diff --git a/src/common/Cryptography/Authentication/WorldPacketCrypt.h b/src/common/Cryptography/Authentication/WorldPacketCrypt.h index e2f061183f3..5cd6e1282b8 100644 --- a/src/common/Cryptography/Authentication/WorldPacketCrypt.h +++ b/src/common/Cryptography/Authentication/WorldPacketCrypt.h @@ -18,18 +18,17 @@ #ifndef _WORLDPACKETCRYPT_H #define _WORLDPACKETCRYPT_H -#include "Cryptography/AES.h" - -class BigNumber; +#include "AES.h" +#include <array> class TC_COMMON_API WorldPacketCrypt { public: WorldPacketCrypt(); - void Init(uint8 const* key); - bool DecryptRecv(uint8* data, size_t length, uint8 (&tag)[12]); - bool EncryptSend(uint8* data, size_t length, uint8 (&tag)[12]); + void Init(Trinity::Crypto::AES::Key const& key); + bool DecryptRecv(uint8* data, size_t length, Trinity::Crypto::AES::Tag& tag); + bool EncryptSend(uint8* data, size_t length, Trinity::Crypto::AES::Tag& tag); bool IsInitialized() const { return _initialized; } diff --git a/src/common/Cryptography/BigNumber.cpp b/src/common/Cryptography/BigNumber.cpp index 456893d3637..ef5a413d964 100644 --- a/src/common/Cryptography/BigNumber.cpp +++ b/src/common/Cryptography/BigNumber.cpp @@ -16,6 +16,7 @@ */ #include "Cryptography/BigNumber.h" +#include "Errors.h" #include <openssl/bn.h> #include <cstring> #include <algorithm> @@ -29,12 +30,6 @@ BigNumber::BigNumber(BigNumber const& bn) : _bn(BN_dup(bn._bn)) { } -BigNumber::BigNumber(uint32 val) - : _bn(BN_new()) -{ - BN_set_word(_bn, val); -} - BigNumber::~BigNumber() { BN_free(_bn); @@ -64,9 +59,10 @@ void BigNumber::SetBinary(uint8 const* bytes, int32 len) delete[] array; } -void BigNumber::SetHexStr(char const* str) +bool BigNumber::SetHexStr(char const* str) { - BN_hex2bn(&_bn, str); + int n = BN_hex2bn(&_bn, str); + return (n > 0); } void BigNumber::SetRand(int32 numbits) @@ -152,7 +148,7 @@ BigNumber BigNumber::ModExp(BigNumber const& bn1, BigNumber const& bn2) return ret; } -int32 BigNumber::GetNumBytes(void) +int32 BigNumber::GetNumBytes(void) const { return BN_num_bytes(_bn); } @@ -172,25 +168,33 @@ bool BigNumber::IsNegative() const return BN_is_negative(_bn); } -std::unique_ptr<uint8[]> BigNumber::AsByteArray(int32 minSize, bool littleEndian) +void BigNumber::GetBytes(uint8* buf, std::size_t bufsize, bool littleEndian) const { - int numBytes = GetNumBytes(); - int length = (minSize >= numBytes) ? minSize : numBytes; + int nBytes = GetNumBytes(); + ASSERT(nBytes >= 0, "Bignum has negative number of bytes (%d).", nBytes); + std::size_t numBytes = static_cast<std::size_t>(nBytes); - uint8* array = new uint8[length]; + // too large to store + ASSERT(numBytes <= bufsize, "Buffer of size %zu is too small to hold bignum with %zu bytes.\n", bufsize, numBytes); // If we need more bytes than length of BigNumber set the rest to 0 - if (length > numBytes) - memset((void*)array, 0, length); + if (numBytes < bufsize) + memset((void*)buf, 0, bufsize); - BN_bn2bin(_bn, (unsigned char *)array); + BN_bn2bin(_bn, buf + (bufsize - numBytes)); // openssl's BN stores data internally in big endian format, reverse if little endian desired if (littleEndian) - std::reverse(array, array + numBytes); + std::reverse(buf, buf + bufsize); +} - std::unique_ptr<uint8[]> ret(array); - return ret; +std::vector<uint8> BigNumber::ToByteVector(int32 minSize, bool littleEndian) const +{ + std::size_t length = std::max(GetNumBytes(), minSize); + std::vector<uint8> v; + v.resize(length); + GetBytes(v.data(), length, littleEndian); + return v; } std::string BigNumber::AsHexStr() const diff --git a/src/common/Cryptography/BigNumber.h b/src/common/Cryptography/BigNumber.h index 44052f5959b..1f5050bc4f5 100644 --- a/src/common/Cryptography/BigNumber.h +++ b/src/common/Cryptography/BigNumber.h @@ -21,6 +21,8 @@ #include "Define.h" #include <memory> #include <string> +#include <vector> +#include "advstd.h" // data/size struct bignum_st; @@ -29,13 +31,20 @@ class TC_COMMON_API BigNumber public: BigNumber(); BigNumber(BigNumber const& bn); - BigNumber(uint32); + BigNumber(uint32 v) : BigNumber() { SetDword(v); } + BigNumber(std::string const& v) : BigNumber() { SetHexStr(v); } + template <size_t Size> + BigNumber(std::array<uint8, Size> const& v) : BigNumber() { SetBinary(v.data(), Size); } + ~BigNumber(); void SetDword(uint32); void SetQword(uint64); void SetBinary(uint8 const* bytes, int32 len); - void SetHexStr(char const* str); + template <typename Container> + void SetBinary(Container const& c) { SetBinary(advstd::data(c), advstd::size(c)); } + bool SetHexStr(char const* str); + bool SetHexStr(std::string const& str) { return SetHexStr(str.c_str()); } void SetRand(int32 numbits); @@ -82,13 +91,22 @@ class TC_COMMON_API BigNumber BigNumber ModExp(BigNumber const& bn1, BigNumber const& bn2); BigNumber Exp(BigNumber const&); - int32 GetNumBytes(void); + int32 GetNumBytes(void) const; struct bignum_st *BN() { return _bn; } uint32 AsDword(); - std::unique_ptr<uint8[]> AsByteArray(int32 minSize = 0, bool littleEndian = true); + void GetBytes(uint8* buf, size_t bufsize, bool littleEndian = true) const; + std::vector<uint8> ToByteVector(int32 minSize = 0, bool littleEndian = true) const; + + template <std::size_t Size> + std::array<uint8, Size> ToByteArray(bool littleEndian = true) const + { + std::array<uint8, Size> buf; + GetBytes(buf.data(), Size, littleEndian); + return buf; + } std::string AsHexStr() const; std::string AsDecStr() const; diff --git a/src/common/Cryptography/CryptoConstants.h b/src/common/Cryptography/CryptoConstants.h new file mode 100644 index 00000000000..2def8f13622 --- /dev/null +++ b/src/common/Cryptography/CryptoConstants.h @@ -0,0 +1,35 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef TRINITY_CRYPTO_CONSTANTS_H +#define TRINITY_CRYPTO_CONSTANTS_H + +#include "Define.h" + +namespace Trinity +{ +namespace Crypto +{ + struct Constants + { + static constexpr size_t SHA1_DIGEST_LENGTH_BYTES = 20; + static constexpr size_t SHA256_DIGEST_LENGTH_BYTES = 32; + }; +} +} + +#endif diff --git a/src/common/Cryptography/CryptoGenerics.h b/src/common/Cryptography/CryptoGenerics.h new file mode 100644 index 00000000000..affa11bf79d --- /dev/null +++ b/src/common/Cryptography/CryptoGenerics.h @@ -0,0 +1,117 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef TRINITY_CRYPTO_GENERICS_HPP +#define TRINITY_CRYPTO_GENERICS_HPP + +#include "BigNumber.h" +#include "CryptoRandom.h" +#include "Define.h" +#include "Errors.h" +#include <iterator> +#include <vector> + +namespace Trinity +{ +namespace Impl +{ + struct CryptoGenericsImpl + { + template <typename Cipher> + static typename Cipher::IV GenerateRandomIV() + { + typename Cipher::IV iv; + Trinity::Crypto::GetRandomBytes(iv); + return iv; + } + + template <typename Container> + static void AppendToBack(std::vector<uint8>& data, Container const& tail) + { + data.insert(data.end(), std::begin(tail), std::end(tail)); + } + + template <typename Container> + static void SplitFromBack(std::vector<uint8>& data, Container& tail) + { + ASSERT(data.size() >= std::size(tail)); + for (size_t i = 1, N = std::size(tail); i <= N; ++i) + { + tail[N - i] = data.back(); + data.pop_back(); + } + } + }; +} +} + +namespace Trinity +{ +namespace Crypto +{ + template <typename Cipher> + void AEEncryptWithRandomIV(std::vector<uint8>& data, typename Cipher::Key const& key) + { + using IV = typename Cipher::IV; + using Tag = typename Cipher::Tag; + // select random IV + IV iv = Trinity::Impl::CryptoGenericsImpl::GenerateRandomIV<Cipher>(); + Tag tag; + + // encrypt data + Cipher cipher(true); + cipher.Init(key); + bool success = cipher.Process(iv, data.data(), data.size(), tag); + ASSERT(success); + + // append trailing IV and tag + Trinity::Impl::CryptoGenericsImpl::AppendToBack(data, iv); + Trinity::Impl::CryptoGenericsImpl::AppendToBack(data, tag); + } + + template <typename Cipher> + void AEEncryptWithRandomIV(std::vector<uint8>& data, BigNumber const& key) + { + AEEncryptWithRandomIV<Cipher>(data, key.ToByteArray<Cipher::KEY_SIZE_BYTES>()); + } + + template <typename Cipher> + bool AEDecrypt(std::vector<uint8>& data, typename Cipher::Key const& key) + { + using IV = typename Cipher::IV; + using Tag = typename Cipher::Tag; + // extract trailing IV and tag + IV iv; + Tag tag; + Trinity::Impl::CryptoGenericsImpl::SplitFromBack(data, tag); + Trinity::Impl::CryptoGenericsImpl::SplitFromBack(data, iv); + + // decrypt data + Cipher cipher(false); + cipher.Init(key); + return cipher.Process(iv, data.data(), data.size(), tag); + } + + template <typename Cipher> + bool AEDecrypt(std::vector<uint8>& data, BigNumber const& key) + { + return AEDecrypt<Cipher>(data, key.ToByteArray<Cipher::KEY_SIZE_BYTES>()); + } +} +} + +#endif diff --git a/src/common/Cryptography/CryptoHash.h b/src/common/Cryptography/CryptoHash.h new file mode 100644 index 00000000000..bb9fbc51c15 --- /dev/null +++ b/src/common/Cryptography/CryptoHash.h @@ -0,0 +1,142 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef TRINITY_CRYPTOHASH_H +#define TRINITY_CRYPTOHASH_H + +#include "CryptoConstants.h" +#include "Define.h" +#include "Errors.h" +#include <array> +#include <string> +//#include <string_view> +#include <openssl/evp.h> +#include <cstring> +#include "advstd.h" // data/size + +class BigNumber; + +namespace Trinity +{ +namespace Impl +{ + struct GenericHashImpl + { + 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 void DestroyCTX(EVP_MD_CTX* ctx) { EVP_MD_CTX_destroy(ctx); } +#else + static EVP_MD_CTX* MakeCTX() { return EVP_MD_CTX_new(); } + static void DestroyCTX(EVP_MD_CTX* ctx) { EVP_MD_CTX_free(ctx); } +#endif + }; + + template <GenericHashImpl::HashCreator HashCreator, size_t DigestLength> + class GenericHash + { + public: + static constexpr size_t DIGEST_LENGTH = DigestLength; + using Digest = std::array<uint8, DIGEST_LENGTH>; + + static Digest GetDigestOf(uint8 const* data, size_t len) + { + GenericHash hash; + hash.UpdateData(data, len); + hash.Finalize(); + return hash.GetDigest(); + } + + private: // c++17 + template <typename T> + static void UpdateData_OLDCPP(GenericHash& hash, T const& data) + { + hash.UpdateData(data); + } + + template <typename T, typename... TRest> + static void UpdateData_OLDCPP(GenericHash& hash, T const& data, TRest&&... rest) + { + hash.UpdateData(data); + UpdateData_OLDCPP(hash, std::forward<TRest>(rest)...); + } + + public: + template <typename... Ts> + static auto GetDigestOf(Ts&&... pack) -> /*std::enable_if_t<!(std::is_integral_v<std::decay_t<Ts>> || ...),*/ Digest/*>*/ + { + GenericHash hash; + UpdateData_OLDCPP(hash, std::forward<Ts>(pack)...); + hash.Finalize(); + return hash.GetDigest(); + } + + GenericHash() : _ctx(GenericHashImpl::MakeCTX()) + { + int result = EVP_DigestInit_ex(_ctx, HashCreator(), nullptr); + ASSERT(result == 1); + } + + ~GenericHash() + { + if (!_ctx) + return; + GenericHashImpl::DestroyCTX(_ctx); + _ctx = nullptr; + } + + void UpdateData(uint8 const* data, size_t len) + { + int result = EVP_DigestUpdate(_ctx, data, len); + ASSERT(result == 1); + } + // c++17 void UpdateData(std::string_view str) { UpdateData(reinterpret_cast<uint8 const*>(str.data()), str.size()); } + void UpdateData(std::string const& str) { UpdateData(str.c_str()); } /* explicit overload to avoid using the container template */ + void UpdateData(char const* str) { UpdateData(reinterpret_cast<uint8 const*>(str), strlen(str)); } /* explicit overload to avoid using the container template */ + template <typename Container> + void UpdateData(Container const& c) { UpdateData(advstd::data(c), advstd::size(c)); } + + void Finalize() + { + uint32 length; + 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; } + + private: + EVP_MD_CTX* _ctx; + Digest _digest = { }; + }; +} +} + +namespace Trinity +{ +namespace Crypto +{ + using SHA1 = Trinity::Impl::GenericHash<EVP_sha1, Constants::SHA1_DIGEST_LENGTH_BYTES>; + using SHA256 = Trinity::Impl::GenericHash<EVP_sha256, Constants::SHA256_DIGEST_LENGTH_BYTES>; +} +} + +#endif diff --git a/src/common/Cryptography/CryptoRandom.cpp b/src/common/Cryptography/CryptoRandom.cpp new file mode 100644 index 00000000000..971c2ce7f7c --- /dev/null +++ b/src/common/Cryptography/CryptoRandom.cpp @@ -0,0 +1,26 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "CryptoRandom.h" +#include "Errors.h" +#include <openssl/rand.h> + +void Trinity::Crypto::GetRandomBytes(uint8* buf, size_t len) +{ + int result = RAND_bytes(buf, len); + ASSERT(result == 1, "Not enough randomness in OpenSSL's entropy pool. What in the world are you running on?"); +} diff --git a/src/common/Cryptography/SHA256.h b/src/common/Cryptography/CryptoRandom.h index 2c97b49dbed..da8498a1fa4 100644 --- a/src/common/Cryptography/SHA256.h +++ b/src/common/Cryptography/CryptoRandom.h @@ -15,38 +15,33 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef SHA256_h__ -#define SHA256_h__ +#ifndef TRINITY_CRYPTORANDOM_H +#define TRINITY_CRYPTORANDOM_H #include "Define.h" -#include <string> -#include <type_traits> -#include <openssl/sha.h> +#include <array> +#include "advstd.h" -class BigNumber; - -class TC_COMMON_API SHA256Hash +namespace Trinity { - public: - typedef std::integral_constant<uint32, SHA256_DIGEST_LENGTH> DigestLength; - - SHA256Hash(); - ~SHA256Hash(); - - void UpdateBigNumbers(BigNumber* bn0, ...); - - void UpdateData(uint8 const* data, size_t len); - void UpdateData(std::string const& str); - - void Initialize(); - void Finalize(); - - uint8 *GetDigest() { return mDigest; } - uint32 GetLength() const { return SHA256_DIGEST_LENGTH; } - - private: - SHA256_CTX mC; - uint8 mDigest[SHA256_DIGEST_LENGTH]; -}; - -#endif // SHA256_h__ +namespace Crypto +{ + void TC_COMMON_API GetRandomBytes(uint8* buf, size_t len); + + template <typename Container> + void GetRandomBytes(Container& c) + { + GetRandomBytes(advstd::data(c), advstd::size(c)); + } + + template <size_t S> + std::array<uint8, S> GetRandomBytes() + { + std::array<uint8, S> arr; + GetRandomBytes(arr); + return arr; + } +} +} + +#endif diff --git a/src/common/Cryptography/HMAC.h b/src/common/Cryptography/HMAC.h new file mode 100644 index 00000000000..8562d3b5e2e --- /dev/null +++ b/src/common/Cryptography/HMAC.h @@ -0,0 +1,153 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef TRINITY_HMAC_H +#define TRINITY_HMAC_H + +#include "CryptoConstants.h" +#include "Define.h" +#include "Errors.h" +#include <array> +#include <string> +//#include <string_view> +#include <openssl/hmac.h> +#include "advstd.h" + +class BigNumber; + +namespace Trinity +{ +namespace 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> + class GenericHMAC + { + public: + static constexpr size_t DIGEST_LENGTH = DigestLength; + using Digest = std::array<uint8, DIGEST_LENGTH>; + + template <typename Container> + static Digest GetDigestOf(Container const& seed, uint8 const* data, size_t len) + { + GenericHMAC hash(seed); + hash.UpdateData(data, len); + hash.Finalize(); + return hash.GetDigest(); + } + + private: // c++17 + template <typename T> + static void UpdateData_OLDCPP(GenericHMAC& hash, T const& data) + { + hash.UpdateData(data); + } + + template <typename T, typename... TRest> + static void UpdateData_OLDCPP(GenericHMAC& hash, T const& data, TRest&&... rest) + { + hash.UpdateData(data); + UpdateData_OLDCPP(hash, std::forward<TRest>(rest)...); + } + + public: + template <typename Container, typename... Ts> + static auto GetDigestOf(Container const& seed, Ts&&... pack) -> /*std::enable_if_t<!(std::is_integral_v<std::decay_t<Ts>> || ...),*/ Digest/*>*/ + { + GenericHMAC hash(seed); + UpdateData_OLDCPP(hash, std::forward<Ts>(pack)...); + hash.Finalize(); + return hash.GetDigest(); + } + + GenericHMAC(uint8 const* seed, size_t len) : _ctx(HMACImpl::MakeCTX()) + { + int result = HMAC_Init_ex(_ctx, seed, len, HashCreator(), nullptr); + ASSERT(result == 1); + } + template <typename Container> + GenericHMAC(Container const& container) : GenericHMAC(container.data(), container.size()) {} + + ~GenericHMAC() + { + if (!_ctx) + return; + HMACImpl::DestroyCTX(_ctx); + _ctx = nullptr; + } + + void UpdateData(uint8 const* data, size_t len) + { + int result = HMAC_Update(_ctx, data, len); + ASSERT(result == 1); + } + // c++17 void UpdateData(std::string_view str) { UpdateData(reinterpret_cast<uint8 const*>(str.data()), str.size()); } + void UpdateData(std::string const& str) { UpdateData(str.c_str()); } /* explicit overload to avoid using the container template */ + void UpdateData(char const* str) { UpdateData(reinterpret_cast<uint8 const*>(str), strlen(str)); } /* explicit overload to avoid using the container template */ + template <typename Container> + void UpdateData(Container const& c) { UpdateData(advstd::data(c), advstd::size(c)); } + + void Finalize() + { + uint32 length = 0; + int result = HMAC_Final(_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; + Digest _digest = { }; + }; +} +} + +namespace Trinity +{ +namespace Crypto +{ + using HMAC_SHA1 = Trinity::Impl::GenericHMAC<EVP_sha1, Constants::SHA1_DIGEST_LENGTH_BYTES>; + using HMAC_SHA256 = Trinity::Impl::GenericHMAC<EVP_sha256, Constants::SHA256_DIGEST_LENGTH_BYTES>; +} +} + +#endif diff --git a/src/common/Cryptography/HmacHash.cpp b/src/common/Cryptography/HmacHash.cpp deleted file mode 100644 index e52113d2e0e..00000000000 --- a/src/common/Cryptography/HmacHash.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "HmacHash.h" -#include "BigNumber.h" -#include "Errors.h" -#include <cstring> - -#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x10100000L -HMAC_CTX* HMAC_CTX_new() -{ - HMAC_CTX *ctx = new HMAC_CTX(); - HMAC_CTX_init(ctx); - return ctx; -} - -void HMAC_CTX_free(HMAC_CTX* ctx) -{ - HMAC_CTX_cleanup(ctx); - delete ctx; -} -#endif - -template<HashCreateFn HashCreator, uint32 DigestLength> -HmacHash<HashCreator, DigestLength>::HmacHash(uint32 len, uint8 const* seed) : _ctx(HMAC_CTX_new()) -{ - HMAC_Init_ex(_ctx, seed, len, HashCreator(), nullptr); - memset(_digest, 0, DigestLength); -} - -template<HashCreateFn HashCreator, uint32 DigestLength> -HmacHash<HashCreator, DigestLength>::~HmacHash() -{ - HMAC_CTX_free(_ctx); -} - -template<HashCreateFn HashCreator, uint32 DigestLength> -void HmacHash<HashCreator, DigestLength>::UpdateData(std::string const& str) -{ - HMAC_Update(_ctx, reinterpret_cast<uint8 const*>(str.c_str()), str.length()); -} - -template<HashCreateFn HashCreator, uint32 DigestLength> -void HmacHash<HashCreator, DigestLength>::UpdateData(uint8 const* data, size_t len) -{ - HMAC_Update(_ctx, data, len); -} - -template<HashCreateFn HashCreator, uint32 DigestLength> -void HmacHash<HashCreator, DigestLength>::Finalize() -{ - uint32 length = 0; - HMAC_Final(_ctx, _digest, &length); - ASSERT(length == DigestLength); -} - -template<HashCreateFn HashCreator, uint32 DigestLength> -uint8* HmacHash<HashCreator, DigestLength>::ComputeHash(BigNumber* bn) -{ - HMAC_Update(_ctx, bn->AsByteArray().get(), bn->GetNumBytes()); - Finalize(); - return _digest; -} - -template class TC_COMMON_API HmacHash<EVP_sha1, SHA_DIGEST_LENGTH>; -template class TC_COMMON_API HmacHash<EVP_sha256, SHA256_DIGEST_LENGTH>; diff --git a/src/common/Cryptography/HmacHash.h b/src/common/Cryptography/HmacHash.h deleted file mode 100644 index 6985e4ac59a..00000000000 --- a/src/common/Cryptography/HmacHash.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef _AUTH_HMAC_H -#define _AUTH_HMAC_H - -#include "Define.h" -#include <string> -#include <openssl/hmac.h> -#include <openssl/sha.h> - -class BigNumber; - -#define SEED_KEY_SIZE 16 - -typedef EVP_MD const* (*HashCreateFn)(); - -template<HashCreateFn HashCreator, uint32 DigestLength> -class TC_COMMON_API HmacHash -{ - public: - HmacHash(uint32 len, uint8 const* seed); - ~HmacHash(); - void UpdateData(std::string const& str); - void UpdateData(uint8 const* data, size_t len); - void Finalize(); - uint8* ComputeHash(BigNumber* bn); - uint8* GetDigest() { return _digest; } - uint32 GetLength() const { return DigestLength; } - private: - HMAC_CTX* _ctx; - uint8 _digest[DigestLength]; -}; - -typedef HmacHash<EVP_sha1, SHA_DIGEST_LENGTH> HmacSha1; -typedef HmacHash<EVP_sha256, SHA256_DIGEST_LENGTH> HmacSha256; - -#endif diff --git a/src/common/Cryptography/RSA.h b/src/common/Cryptography/RSA.h index 6b51dcb8d10..a99bae8536a 100644 --- a/src/common/Cryptography/RSA.h +++ b/src/common/Cryptography/RSA.h @@ -18,6 +18,7 @@ #include "Define.h" #include <openssl/objects.h> #include <openssl/rsa.h> +#include <array> #include <string> #include <type_traits> @@ -57,12 +58,24 @@ public: return Encrypt<KeyTag>(data, dataLength, output, PaddingTag::value); } + 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); + } + private: template <typename KeyTag> bool Encrypt(uint8 const* data, std::size_t dataLength, uint8* output, int32 paddingType); diff --git a/src/common/Cryptography/SHA1.cpp b/src/common/Cryptography/SHA1.cpp deleted file mode 100644 index 15140d82a43..00000000000 --- a/src/common/Cryptography/SHA1.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* - * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "SHA1.h" -#include "BigNumber.h" -#include "Util.h" -#include <cstring> -#include <stdarg.h> - -SHA1Hash::SHA1Hash() -{ - SHA1_Init(&mC); - memset(mDigest, 0, SHA_DIGEST_LENGTH * sizeof(uint8)); -} - -SHA1Hash::~SHA1Hash() -{ - SHA1_Init(&mC); -} - -void SHA1Hash::UpdateData(const uint8 *dta, int len) -{ - SHA1_Update(&mC, dta, len); -} - -void SHA1Hash::UpdateData(const std::string &str) -{ - UpdateData((uint8 const*)str.c_str(), str.length()); -} - -void SHA1Hash::UpdateBigNumbers(BigNumber* bn0, ...) -{ - va_list v; - BigNumber* bn; - - va_start(v, bn0); - bn = bn0; - while (bn) - { - UpdateData(bn->AsByteArray().get(), bn->GetNumBytes()); - bn = va_arg(v, BigNumber*); - } - va_end(v); -} - -void SHA1Hash::Initialize() -{ - SHA1_Init(&mC); -} - -void SHA1Hash::Finalize(void) -{ - SHA1_Final(mDigest, &mC); -} - -std::string CalculateSHA1Hash(std::string const& content) -{ - unsigned char digest[SHA_DIGEST_LENGTH]; - SHA1((unsigned char*)content.c_str(), content.length(), (unsigned char*)&digest); - - return ByteArrayToHexStr(digest, SHA_DIGEST_LENGTH); -} diff --git a/src/common/Cryptography/SHA1.h b/src/common/Cryptography/SHA1.h deleted file mode 100644 index 5a537598bf8..00000000000 --- a/src/common/Cryptography/SHA1.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef _AUTH_SHA1_H -#define _AUTH_SHA1_H - -#include "Define.h" -#include <string> -#include <type_traits> -#include <openssl/sha.h> - -class BigNumber; - -class TC_COMMON_API SHA1Hash -{ - public: - typedef std::integral_constant<uint32, SHA_DIGEST_LENGTH> DigestLength; - - SHA1Hash(); - ~SHA1Hash(); - - void UpdateBigNumbers(BigNumber* bn0, ...); - - void UpdateData(const uint8 *dta, int len); - void UpdateData(const std::string &str); - - void Initialize(); - void Finalize(); - - uint8 *GetDigest(void) { return mDigest; } - int GetLength(void) const { return SHA_DIGEST_LENGTH; } - - private: - SHA_CTX mC; - uint8 mDigest[SHA_DIGEST_LENGTH]; -}; - -/// Returns the SHA1 hash of the given content as hex string. -TC_COMMON_API std::string CalculateSHA1Hash(std::string const& content); - -#endif diff --git a/src/common/Cryptography/SHA256.cpp b/src/common/Cryptography/SHA256.cpp deleted file mode 100644 index 5baa569ecc4..00000000000 --- a/src/common/Cryptography/SHA256.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* - * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "SHA256.h" -#include "BigNumber.h" -#include <cstring> -#include <stdarg.h> - -SHA256Hash::SHA256Hash() -{ - SHA256_Init(&mC); - memset(mDigest, 0, SHA256_DIGEST_LENGTH * sizeof(uint8)); -} - -SHA256Hash::~SHA256Hash() -{ - SHA256_Init(&mC); -} - -void SHA256Hash::UpdateData(uint8 const* data, size_t len) -{ - SHA256_Update(&mC, data, len); -} - -void SHA256Hash::UpdateData(const std::string &str) -{ - UpdateData((uint8 const*)str.c_str(), str.length()); -} - -void SHA256Hash::UpdateBigNumbers(BigNumber* bn0, ...) -{ - va_list v; - BigNumber* bn; - - va_start(v, bn0); - bn = bn0; - while (bn) - { - UpdateData(bn->AsByteArray().get(), bn->GetNumBytes()); - bn = va_arg(v, BigNumber*); - } - va_end(v); -} - -void SHA256Hash::Initialize() -{ - SHA256_Init(&mC); -} - -void SHA256Hash::Finalize(void) -{ - SHA256_Final(mDigest, &mC); -} diff --git a/src/common/Cryptography/SessionKeyGeneration.h b/src/common/Cryptography/SessionKeyGeneration.h deleted file mode 100644 index c16178a1dd4..00000000000 --- a/src/common/Cryptography/SessionKeyGeneration.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef SessionKeyGeneration_h__ -#define SessionKeyGeneration_h__ - -#include "Define.h" -#include <cstring> - -template<class Hash> -class SessionKeyGenerator -{ -public: - SessionKeyGenerator(uint8* buff, uint32 size) - { - uint32 halfSize = size / 2; - - sh.Initialize(); - sh.UpdateData(buff, halfSize); - sh.Finalize(); - - memcpy(o1, sh.GetDigest(), Hash::DigestLength::value); - - sh.Initialize(); - sh.UpdateData(buff + halfSize, size - halfSize); - sh.Finalize(); - - memcpy(o2, sh.GetDigest(), Hash::DigestLength::value); - - memset(o0, 0x00, Hash::DigestLength::value); - - FillUp(); - } - - void Generate(uint8* buf, uint32 sz) - { - for (uint32 i = 0; i < sz; ++i) - { - if (taken == Hash::DigestLength::value) - FillUp(); - - buf[i] = o0[taken]; - taken++; - } - } - -private: - void FillUp() - { - sh.Initialize(); - sh.UpdateData(o1, Hash::DigestLength::value); - sh.UpdateData(o0, Hash::DigestLength::value); - sh.UpdateData(o2, Hash::DigestLength::value); - sh.Finalize(); - - memcpy(o0, sh.GetDigest(), Hash::DigestLength::value); - - taken = 0; - } - - Hash sh; - uint32 taken; - uint8 o0[Hash::DigestLength::value]; - uint8 o1[Hash::DigestLength::value]; - uint8 o2[Hash::DigestLength::value]; -}; - -#endif // SessionKeyGeneration_h__ diff --git a/src/common/Cryptography/SessionKeyGenerator.h b/src/common/Cryptography/SessionKeyGenerator.h new file mode 100644 index 00000000000..5e9471b7746 --- /dev/null +++ b/src/common/Cryptography/SessionKeyGenerator.h @@ -0,0 +1,63 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef TRINITY_SESSIONKEYGENERATOR_HPP +#define TRINITY_SESSIONKEYGENERATOR_HPP + +#include "CryptoHash.h" +#include <cstring> +#include "advstd.h" // for data/size + +template <typename Hash> +class SessionKeyGenerator +{ + public: + template <typename C> + SessionKeyGenerator(C const& buf) : + o0it(o0.begin()) + { + uint8 const* data = advstd::data(buf); + size_t const len = advstd::size(buf); + size_t const halflen = (len / 2); + + o1 = Hash::GetDigestOf(data, halflen); + o2 = Hash::GetDigestOf(data + halflen, len - halflen); + o0 = Hash::GetDigestOf(o1, o0, o2); + } + + void Generate(uint8* buf, uint32 sz) + { + for (uint32 i = 0; i < sz; ++i) + { + if (o0it == o0.end()) + { + o0 = Hash::GetDigestOf(o1, o0, o2); + o0it = o0.begin(); + } + + buf[i] = *(o0it++); + } + } + + private: + typename Hash::Digest o0 = { }; + typename Hash::Digest o1 = { }; + typename Hash::Digest o2 = { }; + typename Hash::Digest::const_iterator o0it; + }; + +#endif diff --git a/src/common/Utilities/Util.cpp b/src/common/Utilities/Util.cpp index f5ca8a6ac4e..7625ae9d2ff 100644 --- a/src/common/Utilities/Util.cpp +++ b/src/common/Utilities/Util.cpp @@ -699,7 +699,7 @@ bool Utf8ToUpperOnlyLatin(std::string& utf8String) return WStrToUtf8(wstr, utf8String); } -std::string ByteArrayToHexStr(uint8 const* bytes, uint32 arrayLen, bool reverse /* = false */) +std::string ByteArrayToHexStr(uint8 const* bytes, size_t arrayLen, bool reverse /* = false */) { int32 init = 0; int32 end = arrayLen; diff --git a/src/common/Utilities/Util.h b/src/common/Utilities/Util.h index 5711397f904..b3270eb6c2c 100644 --- a/src/common/Utilities/Util.h +++ b/src/common/Utilities/Util.h @@ -22,6 +22,7 @@ #include "Errors.h" #include <string> #include <vector> +#include "advstd.h" enum LocaleConstant : uint8; @@ -301,7 +302,9 @@ TC_COMMON_API bool IsIPAddress(char const* ipaddress); TC_COMMON_API uint32 CreatePIDFile(std::string const& filename); TC_COMMON_API uint32 GetPID(); -TC_COMMON_API std::string ByteArrayToHexStr(uint8 const* bytes, uint32 length, bool reverse = false); +TC_COMMON_API std::string ByteArrayToHexStr(uint8 const* bytes, size_t length, bool reverse = false); +template <typename Container> +std::string ByteArrayToHexStr(Container const& c, bool reverse = false) { return ByteArrayToHexStr(advstd::data(c), advstd::size(c), reverse); } TC_COMMON_API void HexStrToByteArray(std::string const& str, uint8* out, bool reverse = false); TC_COMMON_API bool StringToBool(std::string const& str); diff --git a/src/common/Utilities/advstd.h b/src/common/Utilities/advstd.h new file mode 100644 index 00000000000..7514f156050 --- /dev/null +++ b/src/common/Utilities/advstd.h @@ -0,0 +1,52 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef TRINITY_ADVSTD_H +#define TRINITY_ADVSTD_H + +#include <cstddef> +#include <initializer_list> +#include <type_traits> + +// this namespace holds implementations of upcoming stdlib features that our c++ version doesn't have yet +namespace advstd +{ + // C++17 std::size + template <typename C> + constexpr auto size(const C& c) { return c.size(); } + + template <typename T, std::size_t N> + constexpr std::size_t size(const T(&)[N]) noexcept { return N; } + + // C++17 std::data + template <typename C> + constexpr auto data(C& c) { return c.data(); } + + template <typename C> + constexpr auto data(C const& c) { return c.data(); } + + template <typename T, std::size_t N> + constexpr T* data(T(&a)[N]) noexcept { return a; } + + template <typename T, std::size_t N> + constexpr T const* data(const T(&a)[N]) noexcept { return a; } + + template <typename T> + constexpr T const* data(std::initializer_list<T> l) noexcept { return l.begin(); } +} + +#endif |