diff options
author | Treeston <treeston.mmoc@gmail.com> | 2020-07-26 01:53:34 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2020-08-03 19:39:00 +0200 |
commit | e9392ad28767626e519c463e2110184d71ba8426 (patch) | |
tree | da391d7daf1ede4ef73883b5053520e160dc4ec4 | |
parent | caa1e1171a1ea4e2db754cfb52b3be795385d544 (diff) |
Core/Authserver: Authserver cleanup (PR#25093)
- Fix a handful of 1/256 bugs with most significant byte zero in BigNumber
- Get rid of (most of) the C-style arrays in authserver
- CryptoRandom as a unified source for cryptographic randomness
- Bring our other crypto APIs into 2020
- BigNumber usability improvements
- Authserver is now actually readable as a result of all of the above
(cherry picked from commit 210176fd915cf4ba16f428d3c1a249a71f4aa7a7)
49 files changed, 906 insertions, 697 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 diff --git a/src/server/bnetserver/Main.cpp b/src/server/bnetserver/Main.cpp index bbb48ac6128..c2590271b98 100644 --- a/src/server/bnetserver/Main.cpp +++ b/src/server/bnetserver/Main.cpp @@ -25,6 +25,7 @@ #include "AppenderDB.h" #include "Banner.h" +#include "BigNumber.h" #include "Config.h" #include "DatabaseEnv.h" #include "DatabaseLoader.h" diff --git a/src/server/bnetserver/REST/LoginRESTService.cpp b/src/server/bnetserver/REST/LoginRESTService.cpp index c8fb91b163b..16ce194b190 100644 --- a/src/server/bnetserver/REST/LoginRESTService.cpp +++ b/src/server/bnetserver/REST/LoginRESTService.cpp @@ -17,6 +17,8 @@ #include "LoginRESTService.h" #include "Configuration/Config.h" +#include "CryptoHash.h" +#include "CryptoRandom.h" #include "DatabaseEnv.h" #include "Errors.h" #include "IpNetwork.h" @@ -24,8 +26,6 @@ #include "Realm.h" #include "Resolver.h" #include "SessionManager.h" -#include "SHA1.h" -#include "SHA256.h" #include "SslContext.h" #include "Util.h" #include "httpget.h" @@ -362,10 +362,9 @@ int32 LoginRESTService::HandlePostLogin(std::shared_ptr<AsyncRequest> request) { if (loginTicket.empty() || loginTicketExpiry < time(nullptr)) { - BigNumber ticket; - ticket.SetRand(20 * 8); + std::array<uint8, 20> ticket = Trinity::Crypto::GetRandomBytes<20>(); - loginTicket = "TC-" + ByteArrayToHexStr(ticket.AsByteArray(20).get(), 20); + loginTicket = "TC-" + ByteArrayToHexStr(ticket); } LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_BNET_AUTHENTICATION); @@ -503,17 +502,17 @@ void LoginRESTService::HandleAsyncRequest(std::shared_ptr<AsyncRequest> request) std::string LoginRESTService::CalculateShaPassHash(std::string const& name, std::string const& password) { - SHA256Hash email; + Trinity::Crypto::SHA256 email; email.UpdateData(name); email.Finalize(); - SHA256Hash sha; - sha.UpdateData(ByteArrayToHexStr(email.GetDigest(), email.GetLength())); + Trinity::Crypto::SHA256 sha; + sha.UpdateData(ByteArrayToHexStr(email.GetDigest())); sha.UpdateData(":"); sha.UpdateData(password); sha.Finalize(); - return ByteArrayToHexStr(sha.GetDigest(), sha.GetLength(), true); + return ByteArrayToHexStr(sha.GetDigest(), true); } Namespace namespaces[] = diff --git a/src/server/bnetserver/Server/Session.cpp b/src/server/bnetserver/Server/Session.cpp index 9e3ec49a0ca..249a871aa04 100644 --- a/src/server/bnetserver/Server/Session.cpp +++ b/src/server/bnetserver/Server/Session.cpp @@ -18,6 +18,7 @@ #include "Session.h" #include "BattlenetRpcErrorCodes.h" #include "ByteConverter.h" +#include "CryptoRandom.h" #include "DatabaseEnv.h" #include "Errors.h" #include "IPLocation.h" @@ -386,9 +387,8 @@ uint32 Battlenet::Session::VerifyWebCredentials(std::string const& webCredential if (!_ipCountry.empty()) logonResult.set_geoip_country(_ipCountry); - BigNumber k; - k.SetRand(8 * 64); - logonResult.set_session_key(k.AsByteArray(64).get(), 64); + std::array<uint8, 64> k = Trinity::Crypto::GetRandomBytes<64>(); + logonResult.set_session_key(k.data(), 64); _authed = true; diff --git a/src/server/bnetserver/Server/Session.h b/src/server/bnetserver/Server/Session.h index 5738b43e381..520ee263545 100644 --- a/src/server/bnetserver/Server/Session.h +++ b/src/server/bnetserver/Server/Session.h @@ -23,7 +23,6 @@ #include "SslContext.h" #include "SslSocket.h" #include "Socket.h" -#include "BigNumber.h" #include "QueryResult.h" #include <boost/asio/ip/tcp.hpp> #include <boost/asio/ssl.hpp> diff --git a/src/server/database/Updater/UpdateFetcher.cpp b/src/server/database/Updater/UpdateFetcher.cpp index b34cb9ff39c..a5220ab7af1 100644 --- a/src/server/database/Updater/UpdateFetcher.cpp +++ b/src/server/database/Updater/UpdateFetcher.cpp @@ -19,10 +19,10 @@ #include "Common.h" #include "DBUpdater.h" #include "Field.h" +#include "CryptoHash.h" #include "Log.h" #include "QueryResult.h" #include "Util.h" -#include "SHA1.h" #include <boost/filesystem/operations.hpp> #include <fstream> #include <sstream> @@ -223,7 +223,7 @@ UpdateResult UpdateFetcher::Update(bool const redundancyChecks, } // Calculate a Sha1 hash based on query content. - std::string const hash = CalculateSHA1Hash(ReadSQLUpdate(availableQuery.first)); + std::string const hash = ByteArrayToHexStr(Trinity::Crypto::SHA1::GetDigestOf(ReadSQLUpdate(availableQuery.first))); UpdateMode mode = MODE_APPLY; diff --git a/src/server/game/Accounts/AccountMgr.cpp b/src/server/game/Accounts/AccountMgr.cpp index 30e831a598b..a0720e6f93c 100644 --- a/src/server/game/Accounts/AccountMgr.cpp +++ b/src/server/game/Accounts/AccountMgr.cpp @@ -18,12 +18,12 @@ #include "AccountMgr.h" #include "Config.h" #include "DatabaseEnv.h" +#include "CryptoHash.h" #include "Log.h" #include "ObjectAccessor.h" #include "Player.h" #include "Realm.h" #include "ScriptMgr.h" -#include "SHA1.h" #include "Util.h" #include "World.h" #include "WorldSession.h" @@ -389,14 +389,7 @@ uint32 AccountMgr::GetCharactersCount(uint32 accountId) std::string AccountMgr::CalculateShaPassHash(std::string const& name, std::string const& password) { - SHA1Hash sha; - sha.Initialize(); - sha.UpdateData(name); - sha.UpdateData(":"); - sha.UpdateData(password); - sha.Finalize(); - - return ByteArrayToHexStr(sha.GetDigest(), sha.GetLength()); + return ByteArrayToHexStr(Trinity::Crypto::SHA1::GetDigestOf(name, ":", password)); } bool AccountMgr::IsBannedAccount(std::string const& name) diff --git a/src/server/game/Accounts/BattlenetAccountMgr.cpp b/src/server/game/Accounts/BattlenetAccountMgr.cpp index fc78a264156..a726fdf5c7d 100644 --- a/src/server/game/Accounts/BattlenetAccountMgr.cpp +++ b/src/server/game/Accounts/BattlenetAccountMgr.cpp @@ -17,9 +17,9 @@ #include "BattlenetAccountMgr.h" #include "AccountMgr.h" +#include "CryptoHash.h" #include "DatabaseEnv.h" #include "Util.h" -#include "SHA256.h" using GameAccountMgr = AccountMgr; @@ -174,15 +174,15 @@ uint8 Battlenet::AccountMgr::GetMaxIndex(uint32 accountId) std::string Battlenet::AccountMgr::CalculateShaPassHash(std::string const& name, std::string const& password) { - SHA256Hash email; + Trinity::Crypto::SHA256 email; email.UpdateData(name); email.Finalize(); - SHA256Hash sha; - sha.UpdateData(ByteArrayToHexStr(email.GetDigest(), email.GetLength())); + Trinity::Crypto::SHA256 sha; + sha.UpdateData(ByteArrayToHexStr(email.GetDigest())); sha.UpdateData(":"); sha.UpdateData(password); sha.Finalize(); - return ByteArrayToHexStr(sha.GetDigest(), sha.GetLength(), true); + return ByteArrayToHexStr(sha.GetDigest(), true); } diff --git a/src/server/game/Scripting/ScriptReloadMgr.cpp b/src/server/game/Scripting/ScriptReloadMgr.cpp index b8cc437ecb7..1df8b5705db 100644 --- a/src/server/game/Scripting/ScriptReloadMgr.cpp +++ b/src/server/game/Scripting/ScriptReloadMgr.cpp @@ -40,13 +40,14 @@ ScriptReloadMgr* ScriptReloadMgr::instance() #include "BuiltInConfig.h" #include "Config.h" #include "GitRevision.h" +#include "CryptoHash.h" #include "Log.h" #include "MPSCQueue.h" #include "Regex.h" #include "ScriptMgr.h" -#include "SHA1.h" #include "StartProcess.h" #include "Timer.h" +#include "Util.h" #include "World.h" #include <boost/algorithm/string/replace.hpp> #include <boost/filesystem.hpp> @@ -758,7 +759,7 @@ private: auto path = fs::temp_directory_path(); path /= Trinity::StringFormat("tc_script_cache_%s_%s", GitRevision::GetBranch(), - CalculateSHA1Hash(sConfigMgr->GetFilename()).c_str()); + ByteArrayToHexStr(Trinity::Crypto::SHA1::GetDigestOf(sConfigMgr->GetFilename())).c_str()); return path; } diff --git a/src/server/game/Server/Packets/AuthenticationPackets.cpp b/src/server/game/Server/Packets/AuthenticationPackets.cpp index b69f7b1c3ab..5b2e9aa28f0 100644 --- a/src/server/game/Server/Packets/AuthenticationPackets.cpp +++ b/src/server/game/Server/Packets/AuthenticationPackets.cpp @@ -18,10 +18,10 @@ #include "AuthenticationPackets.h" #include "BigNumber.h" #include "CharacterTemplateDataStore.h" -#include "HmacHash.h" +#include "CryptoHash.h" +#include "HMAC.h" #include "ObjectMgr.h" #include "RSA.h" -#include "SHA256.h" #include "Util.h" ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Auth::VirtualRealmNameInfo const& virtualRealmInfo) @@ -272,13 +272,13 @@ WorldPacket const* WorldPackets::Auth::ConnectTo::Write() } uint32 type = Payload.Where.Type; - SHA256Hash hash; + 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(); - ConnectToRSA->Sign(hash.GetDigest(), hash.GetLength(), Payload.Signature.data(), Trinity::Crypto::RSA::SHA256{}); + ConnectToRSA->Sign(hash.GetDigest(), Payload.Signature.data(), Trinity::Crypto::RSA::SHA256{}); _worldPacket.append(Payload.Signature.data(), Payload.Signature.size()); _worldPacket.append(whereBuffer); @@ -308,14 +308,14 @@ uint8 constexpr EnableEncryptionSeed[16] = { 0x90, 0x9C, 0xD0, 0x50, 0x5A, 0x2C, WorldPacket const* WorldPackets::Auth::EnableEncryption::Write() { - HmacSha256 hash(16, EncryptionKey); + Trinity::Crypto::HMAC_SHA256 hash(EncryptionKey, 16); hash.UpdateData(reinterpret_cast<uint8 const*>(&Enabled), 1); hash.UpdateData(EnableEncryptionSeed, 16); hash.Finalize(); _worldPacket.resize(_worldPacket.size() + ConnectToRSA->GetOutputSize()); - ConnectToRSA->Sign(hash.GetDigest(), hash.GetLength(), _worldPacket.contents(), Trinity::Crypto::RSA::SHA256{}); + ConnectToRSA->Sign(hash.GetDigest(), _worldPacket.contents(), Trinity::Crypto::RSA::SHA256{}); _worldPacket.WriteBit(Enabled); _worldPacket.FlushBits(); diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 0e3817bb509..9ac9aba7b56 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -906,7 +906,7 @@ TransactionCallback& WorldSession::AddTransactionCallback(TransactionCallback&& return _transactionCallbacks.AddCallback(std::move(callback)); } -void WorldSession::InitWarden(BigNumber* k) +void WorldSession::InitWarden(std::array<uint8, 40> const& k) { if (_os == "Win") { diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index fdbac1a465e..29b6a104bb6 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -35,7 +35,6 @@ #include <unordered_set> class BattlePetMgr; -class BigNumber; class BlackMarketEntry; class CollectionMgr; class Creature; @@ -958,7 +957,7 @@ class TC_GAME_API WorldSession uint8 GetExpansion() const { return m_expansion; } std::string const& GetOS() const { return _os; } - void InitWarden(BigNumber* k); + void InitWarden(std::array<uint8, 40> const& k); /// Session in auth.queue currently void SetInQueue(bool state) { m_inQueue = state; } diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp index 0ea17e4143d..b05afa02883 100644 --- a/src/server/game/Server/WorldSocket.cpp +++ b/src/server/game/Server/WorldSocket.cpp @@ -19,16 +19,17 @@ #include "AuthenticationPackets.h" #include "BattlenetRpcErrorCodes.h" #include "CharacterPackets.h" +#include "CryptoHash.h" +#include "CryptoRandom.h" #include "DatabaseEnv.h" #include "Errors.h" -#include "HmacHash.h" +#include "HMAC.h" #include "IPLocation.h" #include "PacketLog.h" #include "RealmList.h" #include "RBAC.h" #include "ScriptMgr.h" -#include "SessionKeyGeneration.h" -#include "SHA256.h" +#include "SessionKeyGenerator.h" #include "Util.h" #include "World.h" #include "WorldPacket.h" @@ -72,8 +73,8 @@ WorldSocket::WorldSocket(tcp::socket&& socket) : Socket(std::move(socket)), _type(CONNECTION_TYPE_REALM), _key(0), _OverSpeedPings(0), _worldSession(nullptr), _authed(false), _sendBufferSize(4096), _compressionStream(nullptr) { - _serverChallenge.SetRand(8 * 16); - memset(_encryptKey, 0, sizeof(_encryptKey)); + Trinity::Crypto::GetRandomBytes(_serverChallenge); + _encryptKey.fill(0); _headerBuffer.Resize(sizeof(PacketHeader)); } @@ -237,12 +238,9 @@ bool WorldSocket::Update() void WorldSocket::HandleSendAuthSession() { - BigNumber dosChallenge; - dosChallenge.SetRand(32 * 8); - WorldPackets::Auth::AuthChallenge challenge; - memcpy(challenge.Challenge.data(), _serverChallenge.AsByteArray(16).get(), 16); - memcpy(challenge.DosChallenge.data(), dosChallenge.AsByteArray(32).get(), 32); + challenge.Challenge = _serverChallenge; + memcpy(challenge.DosChallenge.data(), Trinity::Crypto::GetRandomBytes<32>().data(), 32); challenge.DosZeroBits = 1; SendPacketAndLogOpcode(*challenge.Write()); @@ -683,7 +681,7 @@ void WorldSocket::HandleAuthSessionCallback(std::shared_ptr<WorldPackets::Auth:: // For hook purposes, we get Remoteaddress at this point. std::string address = GetRemoteIpAddress().to_string(); - SHA256Hash digestKeyHash; + Trinity::Crypto::SHA256 digestKeyHash; digestKeyHash.UpdateData(account.Game.KeyData.data(), account.Game.KeyData.size()); if (account.Game.OS == "Wn64") digestKeyHash.UpdateData(buildInfo->Win64AuthSeed.data(), buildInfo->Win64AuthSeed.size()); @@ -692,44 +690,41 @@ void WorldSocket::HandleAuthSessionCallback(std::shared_ptr<WorldPackets::Auth:: digestKeyHash.Finalize(); - HmacSha256 hmac(digestKeyHash.GetLength(), digestKeyHash.GetDigest()); - hmac.UpdateData(authSession->LocalChallenge.data(), authSession->LocalChallenge.size()); - hmac.UpdateData(_serverChallenge.AsByteArray(16).get(), 16); + Trinity::Crypto::HMAC_SHA256 hmac(digestKeyHash.GetDigest()); + hmac.UpdateData(authSession->LocalChallenge); + hmac.UpdateData(_serverChallenge); hmac.UpdateData(AuthCheckSeed, 16); hmac.Finalize(); // Check that Key and account name are the same on client and server - if (memcmp(hmac.GetDigest(), authSession->Digest.data(), authSession->Digest.size()) != 0) + if (memcmp(hmac.GetDigest().data(), authSession->Digest.data(), authSession->Digest.size()) != 0) { TC_LOG_ERROR("network", "WorldSocket::HandleAuthSession: Authentication failed for account: %u ('%s') address: %s", account.Game.Id, authSession->RealmJoinTicket.c_str(), address.c_str()); DelayedCloseSocket(); return; } - SHA256Hash keyData; + Trinity::Crypto::SHA256 keyData; keyData.UpdateData(account.Game.KeyData.data(), account.Game.KeyData.size()); keyData.Finalize(); - HmacSha256 sessionKeyHmac(keyData.GetLength(), keyData.GetDigest()); - sessionKeyHmac.UpdateData(_serverChallenge.AsByteArray(16).get(), 16); - sessionKeyHmac.UpdateData(authSession->LocalChallenge.data(), authSession->LocalChallenge.size()); + Trinity::Crypto::HMAC_SHA256 sessionKeyHmac(keyData.GetDigest()); + sessionKeyHmac.UpdateData(_serverChallenge); + sessionKeyHmac.UpdateData(authSession->LocalChallenge); sessionKeyHmac.UpdateData(SessionKeySeed, 16); sessionKeyHmac.Finalize(); - uint8 sessionKey[40]; - SessionKeyGenerator<SHA256Hash> sessionKeyGenerator(sessionKeyHmac.GetDigest(), sessionKeyHmac.GetLength()); - sessionKeyGenerator.Generate(sessionKey, 40); - - _sessionKey.SetBinary(sessionKey, 40); + SessionKeyGenerator<Trinity::Crypto::SHA256> sessionKeyGenerator(sessionKeyHmac.GetDigest()); + sessionKeyGenerator.Generate(_sessionKey.data(), 40); - HmacSha256 encryptKeyGen(40, sessionKey); - encryptKeyGen.UpdateData(authSession->LocalChallenge.data(), authSession->LocalChallenge.size()); - encryptKeyGen.UpdateData(_serverChallenge.AsByteArray(16).get(), 16); + Trinity::Crypto::HMAC_SHA256 encryptKeyGen(_sessionKey); + encryptKeyGen.UpdateData(authSession->LocalChallenge); + encryptKeyGen.UpdateData(_serverChallenge); encryptKeyGen.UpdateData(EncryptionKeySeed, 16); encryptKeyGen.Finalize(); // only first 16 bytes of the hmac are used - memcpy(_encryptKey, encryptKeyGen.GetDigest(), 16); + memcpy(_encryptKey.data(), encryptKeyGen.GetDigest().data(), 16); // As we don't know if attempted login process by ip works, we update last_attempt_ip right away LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_LAST_ATTEMPT_IP); @@ -739,7 +734,7 @@ void WorldSocket::HandleAuthSessionCallback(std::shared_ptr<WorldPackets::Auth:: // This also allows to check for possible "hack" attempts on account stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_ACCOUNT_INFO_CONTINUED_SESSION); - stmt->setString(0, _sessionKey.AsHexStr()); + stmt->setString(0, ByteArrayToHexStr(_sessionKey)); stmt->setUInt32(1, account.Game.Id); LoginDatabase.Execute(stmt); @@ -852,7 +847,7 @@ void WorldSocket::HandleAuthSessionCallback(std::shared_ptr<WorldPackets::Auth:: // Initialize Warden system only if it is enabled by config if (wardenActive) - _worldSession->InitWarden(&_sessionKey); + _worldSession->InitWarden(_sessionKey); _queryProcessor.AddCallback(_worldSession->LoadPermissionsAsync().WithPreparedCallback(std::bind(&WorldSocket::LoadSessionPermissionsCallback, this, std::placeholders::_1))); AsyncRead(); @@ -863,7 +858,7 @@ void WorldSocket::LoadSessionPermissionsCallback(PreparedQueryResult result) // RBAC must be loaded before adding session to check for skip queue permission _worldSession->GetRBACData()->LoadFromDBCallback(result); - SendPacketAndLogOpcode(*WorldPackets::Auth::EnableEncryption(_encryptKey, true).Write()); + SendPacketAndLogOpcode(*WorldPackets::Auth::EnableEncryption(_encryptKey.data(), true).Write()); } void WorldSocket::HandleAuthContinuedSession(std::shared_ptr<WorldPackets::Auth::AuthContinuedSession> authSession) @@ -901,32 +896,32 @@ void WorldSocket::HandleAuthContinuedSessionCallback(std::shared_ptr<WorldPacket uint32 accountId = uint32(key.Fields.AccountId); Field* fields = result->Fetch(); std::string login = fields[0].GetString(); - _sessionKey.SetHexStr(fields[1].GetCString()); + HexStrToByteArray(fields[1].GetString(), _sessionKey.data()); - HmacSha256 hmac(40, _sessionKey.AsByteArray(40).get()); + Trinity::Crypto::HMAC_SHA256 hmac(_sessionKey); hmac.UpdateData(reinterpret_cast<uint8 const*>(&authSession->Key), sizeof(authSession->Key)); - hmac.UpdateData(authSession->LocalChallenge.data(), authSession->LocalChallenge.size()); - hmac.UpdateData(_serverChallenge.AsByteArray(16).get(), 16); + hmac.UpdateData(authSession->LocalChallenge); + hmac.UpdateData(_serverChallenge); hmac.UpdateData(ContinuedSessionSeed, 16); hmac.Finalize(); - if (memcmp(hmac.GetDigest(), authSession->Digest.data(), authSession->Digest.size())) + if (memcmp(hmac.GetDigest().data(), authSession->Digest.data(), authSession->Digest.size())) { TC_LOG_ERROR("network", "WorldSocket::HandleAuthContinuedSession: Authentication failed for account: %u ('%s') address: %s", accountId, login.c_str(), GetRemoteIpAddress().to_string().c_str()); DelayedCloseSocket(); return; } - HmacSha256 encryptKeyGen(40, _sessionKey.AsByteArray(40).get()); - encryptKeyGen.UpdateData(authSession->LocalChallenge.data(), authSession->LocalChallenge.size()); - encryptKeyGen.UpdateData(_serverChallenge.AsByteArray(16).get(), 16); + Trinity::Crypto::HMAC_SHA256 encryptKeyGen(_sessionKey); + encryptKeyGen.UpdateData(authSession->LocalChallenge); + encryptKeyGen.UpdateData(_serverChallenge); encryptKeyGen.UpdateData(EncryptionKeySeed, 16); encryptKeyGen.Finalize(); // only first 16 bytes of the hmac are used - memcpy(_encryptKey, encryptKeyGen.GetDigest(), 16); + memcpy(_encryptKey.data(), encryptKeyGen.GetDigest().data(), 16); - SendPacketAndLogOpcode(*WorldPackets::Auth::EnableEncryption(_encryptKey, true).Write()); + SendPacketAndLogOpcode(*WorldPackets::Auth::EnableEncryption(_encryptKey.data(), true).Write()); AsyncRead(); } diff --git a/src/server/game/Server/WorldSocket.h b/src/server/game/Server/WorldSocket.h index 057c5bd1250..77028643855 100644 --- a/src/server/game/Server/WorldSocket.h +++ b/src/server/game/Server/WorldSocket.h @@ -20,12 +20,12 @@ #include "Common.h" #include "AsyncCallbackProcessor.h" -#include "BigNumber.h" #include "DatabaseEnvFwd.h" #include "MessageBuffer.h" #include "Socket.h" #include "WorldPacketCrypt.h" #include "MPSCQueue.h" +#include <array> #include <chrono> #include <functional> #include <mutex> @@ -130,10 +130,10 @@ private: ConnectionType _type; uint64 _key; - BigNumber _serverChallenge; + std::array<uint8, 16> _serverChallenge; WorldPacketCrypt _authCrypt; - BigNumber _sessionKey; - uint8 _encryptKey[16]; + std::array<uint8, 40> _sessionKey; + std::array<uint8, 16> _encryptKey; std::chrono::steady_clock::time_point _LastPingTime; uint32 _OverSpeedPings; diff --git a/src/server/game/Tools/PlayerDump.cpp b/src/server/game/Tools/PlayerDump.cpp index e96a1101ad4..87d2c76b874 100644 --- a/src/server/game/Tools/PlayerDump.cpp +++ b/src/server/game/Tools/PlayerDump.cpp @@ -636,7 +636,7 @@ inline void AppendTableDump(StringTransaction& trans, TableStruct const& tableSt else { std::vector<uint8> b(fields[i].GetBinary()); - ss << "0x" << ByteArrayToHexStr(b.data(), b.size()); + ss << "0x" << ByteArrayToHexStr(b); } } diff --git a/src/server/game/Warden/Warden.cpp b/src/server/game/Warden/Warden.cpp index e3ddf6a2e74..fdfc128106b 100644 --- a/src/server/game/Warden/Warden.cpp +++ b/src/server/game/Warden/Warden.cpp @@ -30,7 +30,7 @@ #include <openssl/sha.h> -Warden::Warden() : _session(NULL), _inputCrypto(16), _outputCrypto(16), _checkTimer(10000/*10 sec*/), _clientResponseTimer(0), +Warden::Warden() : _session(NULL), _checkTimer(10000/*10 sec*/), _clientResponseTimer(0), _dataSent(false), _previousTimestamp(0), _module(NULL), _initialized(false) { memset(_inputKey, 0, sizeof(_inputKey)); @@ -131,12 +131,12 @@ void Warden::Update() void Warden::DecryptData(uint8* buffer, uint32 length) { - _inputCrypto.UpdateData(length, buffer); + _inputCrypto.UpdateData(buffer, length); } void Warden::EncryptData(uint8* buffer, uint32 length) { - _outputCrypto.UpdateData(length, buffer); + _outputCrypto.UpdateData(buffer, length); } bool Warden::IsValidCheckSum(uint32 checksum, const uint8* data, const uint16 length) diff --git a/src/server/game/Warden/Warden.h b/src/server/game/Warden/Warden.h index 12dea8861fa..8ed0c222969 100644 --- a/src/server/game/Warden/Warden.h +++ b/src/server/game/Warden/Warden.h @@ -18,11 +18,10 @@ #ifndef _WARDEN_BASE_H #define _WARDEN_BASE_H -#include <map> -#include "Cryptography/ARC4.h" -#include "Cryptography/BigNumber.h" +#include "ARC4.h" #include "ByteBuffer.h" #include "WardenCheckMgr.h" +#include <array> enum WardenOpcodes { @@ -100,7 +99,7 @@ class TC_GAME_API Warden Warden(); virtual ~Warden(); - virtual void Init(WorldSession* session, BigNumber* k) = 0; + virtual void Init(WorldSession* session, std::array<uint8, 40> const& K) = 0; virtual ClientWardenModule* GetModuleForClient() = 0; virtual void InitializeModule() = 0; virtual void RequestHash() = 0; @@ -125,8 +124,8 @@ class TC_GAME_API Warden uint8 _inputKey[16]; uint8 _outputKey[16]; uint8 _seed[16]; - ARC4 _inputCrypto; - ARC4 _outputCrypto; + Trinity::Crypto::ARC4 _inputCrypto; + Trinity::Crypto::ARC4 _outputCrypto; uint32 _checkTimer; // Timer for sending check requests uint32 _clientResponseTimer; // Timer for client response delay bool _dataSent; diff --git a/src/server/game/Warden/WardenCheckMgr.cpp b/src/server/game/Warden/WardenCheckMgr.cpp index b79b760581b..872779b574d 100644 --- a/src/server/game/Warden/WardenCheckMgr.cpp +++ b/src/server/game/Warden/WardenCheckMgr.cpp @@ -89,19 +89,7 @@ void WardenCheckMgr::LoadWardenChecks() wardenCheck->Action = WardenActions(sWorld->getIntConfig(CONFIG_WARDEN_CLIENT_FAIL_ACTION)); if (checkType == PAGE_CHECK_A || checkType == PAGE_CHECK_B || checkType == DRIVER_CHECK) - { wardenCheck->Data.SetHexStr(data.c_str()); - int len = data.size() / 2; - - if (wardenCheck->Data.GetNumBytes() < len) - { - uint8 temp[24]; - memset(temp, 0, len); - memcpy(temp, wardenCheck->Data.AsByteArray().get(), wardenCheck->Data.GetNumBytes()); - std::reverse(temp, temp + len); - wardenCheck->Data.SetBinary((uint8*)temp, len); - } - } if (checkType == MEM_CHECK || checkType == MODULE_CHECK) MemChecksIdPool.push_back(id); @@ -124,16 +112,6 @@ void WardenCheckMgr::LoadWardenChecks() { WardenCheckResult* wr = new WardenCheckResult(); wr->Result.SetHexStr(checkResult.c_str()); - int len = checkResult.size() / 2; - if (wr->Result.GetNumBytes() < len) - { - uint8 *temp = new uint8[len]; - memset(temp, 0, len); - memcpy(temp, wr->Result.AsByteArray().get(), wr->Result.GetNumBytes()); - std::reverse(temp, temp + len); - wr->Result.SetBinary((uint8*)temp, len); - delete [] temp; - } CheckResultStore[id] = wr; } diff --git a/src/server/game/Warden/WardenMac.cpp b/src/server/game/Warden/WardenMac.cpp index cc344298eb6..0129c805a08 100644 --- a/src/server/game/Warden/WardenMac.cpp +++ b/src/server/game/Warden/WardenMac.cpp @@ -15,20 +15,18 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "Cryptography/SessionKeyGeneration.h" +#include "WardenMac.h" +#include "ByteBuffer.h" #include "Common.h" -#include "WorldPacket.h" -#include "WorldSession.h" +#include "GameTime.h" #include "Log.h" #include "Opcodes.h" -#include "ByteBuffer.h" -#include "GameTime.h" -#include "World.h" #include "Player.h" +#include "SessionKeyGenerator.h" #include "Util.h" -#include "WardenMac.h" #include "WardenModuleMac.h" -#include "SHA1.h" +#include "WorldPacket.h" +#include "WorldSession.h" #include <openssl/md5.h> @@ -36,11 +34,11 @@ WardenMac::WardenMac() : Warden() { } WardenMac::~WardenMac() { } -void WardenMac::Init(WorldSession* pClient, BigNumber* K) +void WardenMac::Init(WorldSession* pClient, std::array<uint8, 40> const& K) { _session = pClient; // Generate Warden Key - SessionKeyGenerator<SHA1Hash> WK(K->AsByteArray().get(), K->GetNumBytes()); + SessionKeyGenerator<Trinity::Crypto::SHA1> WK(K); WK.Generate(_inputKey, 16); WK.Generate(_outputKey, 16); /* @@ -156,14 +154,14 @@ void WardenMac::HandleHashResult(ByteBuffer &buff) buff.rpos(buff.wpos()); - SHA1Hash sha1; + Trinity::Crypto::SHA1 sha1; sha1.UpdateData((uint8*)keyIn, 16); sha1.Finalize(); //const uint8 validHash[20] = { 0x56, 0x8C, 0x05, 0x4C, 0x78, 0x1A, 0x97, 0x2A, 0x60, 0x37, 0xA2, 0x29, 0x0C, 0x22, 0xB5, 0x25, 0x71, 0xA0, 0x6F, 0x4E }; // Verify key - if (memcmp(buff.contents() + 1, sha1.GetDigest(), 20) != 0) + if (memcmp(buff.contents() + 1, sha1.GetDigest().data(), 20) != 0) { TC_LOG_WARN("warden", "%s failed hash reply. Action: %s", _session->GetPlayerInfo().c_str(), Penalty().c_str()); return; @@ -237,16 +235,16 @@ void WardenMac::HandleData(ByteBuffer &buff) std::string str = "Test string!"; - SHA1Hash sha1; + Trinity::Crypto::SHA1 sha1; sha1.UpdateData(str); uint32 magic = 0xFEEDFACE; // unsure sha1.UpdateData((uint8*)&magic, 4); sha1.Finalize(); - uint8 sha1Hash[20]; - buff.read(sha1Hash, 20); + std::array<uint8, Trinity::Crypto::SHA1::DIGEST_LENGTH> sha1Hash; + buff.read(sha1Hash.data(), sha1Hash.size()); - if (memcmp(sha1Hash, sha1.GetDigest(), 20) != 0) + if (sha1Hash != sha1.GetDigest()) { TC_LOG_DEBUG("warden", "Handle data failed: SHA1 hash is wrong!"); //found = true; diff --git a/src/server/game/Warden/WardenMac.h b/src/server/game/Warden/WardenMac.h index 81ab864cf02..c186e546f9e 100644 --- a/src/server/game/Warden/WardenMac.h +++ b/src/server/game/Warden/WardenMac.h @@ -18,9 +18,7 @@ #ifndef _WARDEN_MAC_H #define _WARDEN_MAC_H -#include "Cryptography/ARC4.h" -#include <map> -#include "Cryptography/BigNumber.h" +#include "ARC4.h" #include "ByteBuffer.h" #include "Warden.h" @@ -33,7 +31,7 @@ class TC_GAME_API WardenMac : public Warden WardenMac(); ~WardenMac(); - void Init(WorldSession* session, BigNumber* k) override; + void Init(WorldSession* session, std::array<uint8, 40> const& k) override; ClientWardenModule* GetModuleForClient() override; void InitializeModule() override; void RequestHash() override; diff --git a/src/server/game/Warden/WardenWin.cpp b/src/server/game/Warden/WardenWin.cpp index 8e427de0acc..3e374c98a11 100644 --- a/src/server/game/Warden/WardenWin.cpp +++ b/src/server/game/Warden/WardenWin.cpp @@ -15,24 +15,24 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "Cryptography/HmacHash.h" -#include "Cryptography/SessionKeyGeneration.h" +#include "WardenWin.h" #include "Common.h" -#include "WorldPacket.h" -#include "WorldSession.h" -#include "Log.h" -#include "Opcodes.h" #include "ByteBuffer.h" -#include "Database/DatabaseEnv.h" +#include "CryptoRandom.h" +#include "DatabaseEnv.h" #include "GameTime.h" -#include "World.h" +#include "HMAC.h" +#include "Log.h" +#include "Opcodes.h" #include "Player.h" +#include "Random.h" +#include "SessionKeyGenerator.h" #include "Util.h" -#include "WardenWin.h" #include "WardenModuleWin.h" #include "WardenCheckMgr.h" -#include "SHA1.h" -#include "Random.h" +#include "World.h" +#include "WorldPacket.h" +#include "WorldSession.h" #include <boost/thread/locks.hpp> #include <boost/thread/shared_mutex.hpp> #include <openssl/md5.h> @@ -41,11 +41,11 @@ WardenWin::WardenWin() : Warden(), _serverTicks(0) {} WardenWin::~WardenWin() { } -void WardenWin::Init(WorldSession* session, BigNumber* k) +void WardenWin::Init(WorldSession* session, std::array<uint8, 40> const& K) { _session = session; // Generate Warden Key - SessionKeyGenerator<SHA1Hash> WK(k->AsByteArray().get(), k->GetNumBytes()); + SessionKeyGenerator<Trinity::Crypto::SHA1> WK(K); WK.Generate(_inputKey, 16); WK.Generate(_outputKey, 16); @@ -265,7 +265,8 @@ void WardenWin::RequestData() case PAGE_CHECK_A: case PAGE_CHECK_B: { - buff.append(wd->Data.AsByteArray(0, false).get(), wd->Data.GetNumBytes()); + std::vector<uint8> data = wd->Data.ToByteVector(0, false); + buff.append(data.data(), data.size()); buff << uint32(wd->Address); buff << uint8(wd->Length); break; @@ -278,18 +279,16 @@ void WardenWin::RequestData() } case DRIVER_CHECK: { - buff.append(wd->Data.AsByteArray(0, false).get(), wd->Data.GetNumBytes()); + std::vector<uint8> data = wd->Data.ToByteVector(0, false); + buff.append(data.data(), data.size()); buff << uint8(index++); break; } case MODULE_CHECK: { - uint32 seed = rand32(); - buff << uint32(seed); - HmacSha1 hmac(4, (uint8*)&seed); - hmac.UpdateData(wd->Str); - hmac.Finalize(); - buff.append(hmac.GetDigest(), hmac.GetLength()); + std::array<uint8, 4> seed = Trinity::Crypto::GetRandomBytes<4>(); + buff.append(seed); + buff.append(Trinity::Crypto::HMAC_SHA1::GetDigestOf(seed, wd->Str)); break; } /*case PROC_CHECK: @@ -394,7 +393,8 @@ void WardenWin::HandleData(ByteBuffer &buff) continue; } - if (memcmp(buff.contents() + buff.rpos(), rs->Result.AsByteArray(0, false).get(), rd->Length) != 0) + std::vector<uint8> result = rs->Result.ToByteVector(); + if (memcmp(buff.contents() + buff.rpos(), result.data(), rd->Length) != 0) { TC_LOG_DEBUG("warden", "RESULT MEM_CHECK fail CheckId %u account Id %u", *itr, _session->GetAccountId()); checkFailed = *itr; @@ -473,7 +473,7 @@ void WardenWin::HandleData(ByteBuffer &buff) continue; } - if (memcmp(buff.contents() + buff.rpos(), rs->Result.AsByteArray(0, false).get(), 20) != 0) // SHA1 + if (memcmp(buff.contents() + buff.rpos(), rs->Result.ToByteArray<20>(false).data(), 20) != 0) // SHA1 { TC_LOG_DEBUG("warden", "RESULT MPQ_CHECK fail, CheckId %u account Id %u", *itr, _session->GetAccountId()); checkFailed = *itr; diff --git a/src/server/game/Warden/WardenWin.h b/src/server/game/Warden/WardenWin.h index c45d73572be..77f66f621a3 100644 --- a/src/server/game/Warden/WardenWin.h +++ b/src/server/game/Warden/WardenWin.h @@ -18,11 +18,11 @@ #ifndef _WARDEN_WIN_H #define _WARDEN_WIN_H -#include <map> #include "Cryptography/ARC4.h" #include "Cryptography/BigNumber.h" #include "ByteBuffer.h" #include "Warden.h" +#include <list> #pragma pack(push, 1) @@ -67,7 +67,7 @@ class TC_GAME_API WardenWin : public Warden WardenWin(); ~WardenWin(); - void Init(WorldSession* session, BigNumber* K) override; + void Init(WorldSession* session, std::array<uint8, 40> const& K) override; ClientWardenModule* GetModuleForClient() override; void InitializeModule() override; void RequestHash() override; diff --git a/src/server/scripts/Commands/cs_battlenet_account.cpp b/src/server/scripts/Commands/cs_battlenet_account.cpp index a1166a6c3c9..fc7e8948382 100644 --- a/src/server/scripts/Commands/cs_battlenet_account.cpp +++ b/src/server/scripts/Commands/cs_battlenet_account.cpp @@ -17,8 +17,8 @@ #include "AccountMgr.h" #include "BattlenetAccountMgr.h" -#include "BigNumber.h" #include "Chat.h" +#include "CryptoRandom.h" #include "DatabaseEnv.h" #include "IpAddress.h" #include "IPLocation.h" @@ -425,10 +425,9 @@ public: std::string accountName = std::to_string(accountId) + '#' + std::to_string(uint32(index)); // Generate random hex string for password, these accounts must not be logged on with GRUNT - BigNumber randPassword; - randPassword.SetRand(8 * 16); + std::array<uint8, 16> randPassword = Trinity::Crypto::GetRandomBytes<16>(); - switch (sAccountMgr->CreateAccount(accountName, ByteArrayToHexStr(randPassword.AsByteArray().get(), randPassword.GetNumBytes()), bnetAccountName, accountId, index)) + switch (sAccountMgr->CreateAccount(accountName, ByteArrayToHexStr(randPassword), bnetAccountName, accountId, index)) { case AccountOpResult::AOR_OK: handler->PSendSysMessage(LANG_ACCOUNT_CREATED, accountName.c_str()); diff --git a/src/server/shared/Packets/ByteBuffer.h b/src/server/shared/Packets/ByteBuffer.h index 296da13dafe..13d77b41c14 100644 --- a/src/server/shared/Packets/ByteBuffer.h +++ b/src/server/shared/Packets/ByteBuffer.h @@ -20,6 +20,7 @@ #include "Define.h" #include "ByteConverter.h" +#include <array> #include <string> #include <vector> #include <cstring> @@ -472,6 +473,12 @@ class TC_SHARED_API ByteBuffer _rpos += len; } + template <size_t Size> + void read(std::array<uint8, Size>& arr) + { + read(arr.data(), Size); + } + void ReadPackedUInt64(uint64& guid) { guid = 0; @@ -564,6 +571,12 @@ class TC_SHARED_API ByteBuffer append(buffer.contents(), buffer.size()); } + template <size_t Size> + void append(std::array<uint8, Size> const& arr) + { + append(arr.data(), Size); + } + // can be used in SMSG_MONSTER_MOVE opcode void appendPackXYZ(float x, float y, float z) { diff --git a/src/server/shared/Realm/RealmList.cpp b/src/server/shared/Realm/RealmList.cpp index ca591e423f5..5673636eb28 100644 --- a/src/server/shared/Realm/RealmList.cpp +++ b/src/server/shared/Realm/RealmList.cpp @@ -17,7 +17,7 @@ #include "RealmList.h" #include "BattlenetRpcErrorCodes.h" -#include "BigNumber.h" +#include "CryptoRandom.h" #include "DatabaseEnv.h" #include "DeadlineTimer.h" #include "Errors.h" @@ -404,15 +404,14 @@ uint32 RealmList::JoinRealm(uint32 realmAddress, uint32 build, boost::asio::ip:: if (compress(compressed.data() + 4, &compressedLength, reinterpret_cast<uint8 const*>(json.c_str()), uLong(json.length() + 1)) != Z_OK) return ERROR_UTIL_SERVER_FAILED_TO_SERIALIZE_RESPONSE; - BigNumber serverSecret; - serverSecret.SetRand(8 * 32); + std::array<uint8, 32> serverSecret = Trinity::Crypto::GetRandomBytes<32>(); std::array<uint8, 64> keyData; memcpy(&keyData[0], clientSecret.data(), 32); - memcpy(&keyData[32], serverSecret.AsByteArray(32).get(), 32); + memcpy(&keyData[32], serverSecret.data(), 32); LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_BNET_GAME_ACCOUNT_LOGIN_INFO); - stmt->setString(0, ByteArrayToHexStr(keyData.data(), keyData.size())); + stmt->setString(0, ByteArrayToHexStr(keyData)); stmt->setString(1, clientAddress.to_string()); stmt->setUInt8(2, locale); stmt->setString(3, os); @@ -429,7 +428,7 @@ uint32 RealmList::JoinRealm(uint32 realmAddress, uint32 build, boost::asio::ip:: attribute = response->add_attribute(); attribute->set_name("Param_JoinSecret"); - attribute->mutable_value()->set_blob_value(serverSecret.AsByteArray(32).get(), 32); + attribute->mutable_value()->set_blob_value(serverSecret.data(), 32); return ERROR_OK; } |