From f22012d282fee1cf3618765b58478e91767830d6 Mon Sep 17 00:00:00 2001 From: Jan Date: Tue, 16 Mar 2021 20:42:48 +0100 Subject: [PATCH] Move XChunk processors to ZoneCommon --- src/Crypto/Crypto.cpp | 16 +- src/Crypto/Crypto.h | 10 +- src/ZoneCommon.lua | 2 + .../Zone/XChunk/AbstractSalsa20Processor.cpp | 53 ++++++ .../Zone/XChunk/AbstractSalsa20Processor.h | 45 +++++ .../Zone/XChunk}/IXChunkProcessor.h | 0 .../Zone/XChunk/XChunkException.cpp | 16 ++ src/ZoneCommon/Zone/XChunk/XChunkException.h | 16 ++ .../Zone/XChunk/XChunkProcessorDeflate.cpp | 33 ++++ .../Zone/XChunk/XChunkProcessorDeflate.h} | 2 +- .../Zone/XChunk/XChunkProcessorInflate.cpp | 33 ++++ .../Zone/XChunk/XChunkProcessorInflate.h} | 4 +- .../XChunkProcessorSalsa20Decryption.cpp | 44 +++++ .../XChunk/XChunkProcessorSalsa20Decryption.h | 13 ++ .../XChunkProcessorSalsa20Encryption.cpp | 41 +++++ .../XChunk/XChunkProcessorSalsa20Encryption.h | 14 ++ .../Game/IW4/ZoneLoaderFactoryIW4.cpp | 10 +- .../Game/T6/ZoneLoaderFactoryT6.cpp | 18 +- .../Loading/Processor/ProcessorXChunks.cpp | 19 +-- .../Loading/Processor/ProcessorXChunks.h | 2 +- .../XChunks/ChunkProcessorInflate.cpp | 39 ----- .../XChunks/ChunkProcessorSalsa20.cpp | 156 ------------------ .../Processor/XChunks/ChunkProcessorSalsa20.h | 17 -- .../Loading/Steps/StepVerifySignature.cpp | 18 +- .../Loading/Steps/StepVerifySignature.h | 10 +- .../Game/T6/ZoneWriterFactoryT6.cpp | 8 +- .../Processor/OutputProcessorXChunks.cpp | 2 +- .../Processor/OutputProcessorXChunks.h | 4 +- .../XChunks/IXChunkOutputProcessor.h | 17 -- .../XChunks/XChunkOutputProcessorDeflate.cpp | 0 .../XChunks/XChunkOutputProcessorSalsa20.cpp | 0 .../XChunks/XChunkOutputProcessorSalsa20.h | 20 --- src/ZoneWriting/ZoneWriting.cpp | 18 +- 33 files changed, 383 insertions(+), 317 deletions(-) create mode 100644 src/ZoneCommon/Zone/XChunk/AbstractSalsa20Processor.cpp create mode 100644 src/ZoneCommon/Zone/XChunk/AbstractSalsa20Processor.h rename src/{ZoneLoading/Loading/Processor/XChunks => ZoneCommon/Zone/XChunk}/IXChunkProcessor.h (100%) create mode 100644 src/ZoneCommon/Zone/XChunk/XChunkException.cpp create mode 100644 src/ZoneCommon/Zone/XChunk/XChunkException.h create mode 100644 src/ZoneCommon/Zone/XChunk/XChunkProcessorDeflate.cpp rename src/{ZoneLoading/Loading/Processor/XChunks/ChunkProcessorInflate.h => ZoneCommon/Zone/XChunk/XChunkProcessorDeflate.h} (75%) create mode 100644 src/ZoneCommon/Zone/XChunk/XChunkProcessorInflate.cpp rename src/{ZoneWriting/Writing/Processor/XChunks/XChunkOutputProcessorDeflate.h => ZoneCommon/Zone/XChunk/XChunkProcessorInflate.h} (59%) create mode 100644 src/ZoneCommon/Zone/XChunk/XChunkProcessorSalsa20Decryption.cpp create mode 100644 src/ZoneCommon/Zone/XChunk/XChunkProcessorSalsa20Decryption.h create mode 100644 src/ZoneCommon/Zone/XChunk/XChunkProcessorSalsa20Encryption.cpp create mode 100644 src/ZoneCommon/Zone/XChunk/XChunkProcessorSalsa20Encryption.h delete mode 100644 src/ZoneLoading/Loading/Processor/XChunks/ChunkProcessorInflate.cpp delete mode 100644 src/ZoneLoading/Loading/Processor/XChunks/ChunkProcessorSalsa20.cpp delete mode 100644 src/ZoneLoading/Loading/Processor/XChunks/ChunkProcessorSalsa20.h delete mode 100644 src/ZoneWriting/Writing/Processor/XChunks/IXChunkOutputProcessor.h delete mode 100644 src/ZoneWriting/Writing/Processor/XChunks/XChunkOutputProcessorDeflate.cpp delete mode 100644 src/ZoneWriting/Writing/Processor/XChunks/XChunkOutputProcessorSalsa20.cpp delete mode 100644 src/ZoneWriting/Writing/Processor/XChunks/XChunkOutputProcessorSalsa20.h diff --git a/src/Crypto/Crypto.cpp b/src/Crypto/Crypto.cpp index 9eb876fe..94a3cfb4 100644 --- a/src/Crypto/Crypto.cpp +++ b/src/Crypto/Crypto.cpp @@ -4,22 +4,22 @@ #include "Impl/AlgorithmSalsa20.h" #include "Impl/AlgorithmSHA256.h" -IHashFunction* Crypto::CreateSHA1() +std::unique_ptr Crypto::CreateSHA1() { - return new AlgorithmSHA1(); + return std::make_unique(); } -IHashFunction* Crypto::CreateSHA256() +std::unique_ptr Crypto::CreateSHA256() { - return new AlgorithmSHA256(); + return std::make_unique(); } -IStreamCipher* Crypto::CreateSalsa20(const uint8_t* keyBytes, const size_t keySize) +std::unique_ptr Crypto::CreateSalsa20(const uint8_t* keyBytes, const size_t keySize) { - return new AlgorithmSalsa20(keyBytes, keySize); + return std::make_unique(keyBytes, keySize); } -IPublicKeyAlgorithm* Crypto::CreateRSA(const IPublicKeyAlgorithm::HashingAlgorithm hashingAlgorithm, const RSAPaddingMode paddingMode) +std::unique_ptr Crypto::CreateRSA(const IPublicKeyAlgorithm::HashingAlgorithm hashingAlgorithm, const RSAPaddingMode paddingMode) { - return new AlgorithmRSA(hashingAlgorithm, paddingMode); + return std::make_unique(hashingAlgorithm, paddingMode); } \ No newline at end of file diff --git a/src/Crypto/Crypto.h b/src/Crypto/Crypto.h index 70a16af5..910f4946 100644 --- a/src/Crypto/Crypto.h +++ b/src/Crypto/Crypto.h @@ -1,6 +1,8 @@ #pragma once #include +#include + #include "IHashFunction.h" #include "IStreamCipher.h" @@ -15,10 +17,10 @@ public: RSA_PADDING_PSS, }; - static IHashFunction* CreateSHA1(); - static IHashFunction* CreateSHA256(); + static std::unique_ptr CreateSHA1(); + static std::unique_ptr CreateSHA256(); - static IStreamCipher* CreateSalsa20(const uint8_t* keyBytes, size_t keySize); + static std::unique_ptr CreateSalsa20(const uint8_t* keyBytes, size_t keySize); - static IPublicKeyAlgorithm* CreateRSA(IPublicKeyAlgorithm::HashingAlgorithm hashingAlgorithm, RSAPaddingMode paddingMode); + static std::unique_ptr CreateRSA(IPublicKeyAlgorithm::HashingAlgorithm hashingAlgorithm, RSAPaddingMode paddingMode); }; diff --git a/src/ZoneCommon.lua b/src/ZoneCommon.lua index 6ad06fd7..fa9fd969 100644 --- a/src/ZoneCommon.lua +++ b/src/ZoneCommon.lua @@ -9,12 +9,14 @@ function ZoneCommon:include(includes) Common:include(includes) ObjCommon:include(includes) Parser:include(includes) + Crypto:include(includes) end end function ZoneCommon:link(links) links:add(self:name()) links:linkto(Common) + links:linkto(Crypto) links:linkto(ObjCommon) links:linkto(Parser) links:linkto(Utils) diff --git a/src/ZoneCommon/Zone/XChunk/AbstractSalsa20Processor.cpp b/src/ZoneCommon/Zone/XChunk/AbstractSalsa20Processor.cpp new file mode 100644 index 00000000..280fe922 --- /dev/null +++ b/src/ZoneCommon/Zone/XChunk/AbstractSalsa20Processor.cpp @@ -0,0 +1,53 @@ +#include "AbstractSalsa20Processor.h" + +#include + +AbstractSalsa20Processor::AbstractSalsa20Processor(const int streamCount, std::string& zoneName, const uint8_t* salsa20Key, size_t keySize) + : m_stream_count(streamCount), + m_stream_contexts(std::make_unique(streamCount)), + m_block_hashes(std::make_unique(BLOCK_HASHES_COUNT * streamCount * SHA1_HASH_SIZE)), + m_stream_block_indices(std::make_unique(streamCount)) +{ + InitStreams(zoneName, salsa20Key, keySize); +} + +uint8_t* AbstractSalsa20Processor::GetHashBlock(const int streamNumber) const +{ + const auto blockIndexOffset = m_stream_block_indices[streamNumber] * m_stream_count * SHA1_HASH_SIZE; + const auto streamOffset = static_cast(streamNumber) * SHA1_HASH_SIZE; + + return &m_block_hashes[blockIndexOffset + streamOffset]; +} + +void AbstractSalsa20Processor::InitStreams(std::string& zoneName, const uint8_t* salsa20Key, size_t keySize) const +{ + const int zoneNameLength = zoneName.length(); + const size_t blockHashBufferSize = BLOCK_HASHES_COUNT * m_stream_count * SHA1_HASH_SIZE; + + assert(blockHashBufferSize % 4 == 0); + + size_t zoneNameOffset = 0; + for (size_t i = 0; i < blockHashBufferSize; i += 4) + { + *reinterpret_cast(&m_block_hashes[i]) = 0x1010101 * zoneName[zoneNameOffset++]; + + zoneNameOffset %= zoneNameLength; + } + + for (auto stream = 0; stream < m_stream_count; stream++) + { + m_stream_block_indices[stream] = 0; + + m_stream_contexts[stream].m_salsa20 = Crypto::CreateSalsa20(salsa20Key, keySize); + m_stream_contexts[stream].m_sha1 = Crypto::CreateSHA1(); + } +} + +void AbstractSalsa20Processor::GetCapturedData(const uint8_t** pCapturedData, size_t* pSize) +{ + assert(pCapturedData != nullptr); + assert(pSize != nullptr); + + *pCapturedData = m_block_hashes.get(); + *pSize = BLOCK_HASHES_COUNT * m_stream_count * SHA1_HASH_SIZE; +} diff --git a/src/ZoneCommon/Zone/XChunk/AbstractSalsa20Processor.h b/src/ZoneCommon/Zone/XChunk/AbstractSalsa20Processor.h new file mode 100644 index 00000000..884ae18e --- /dev/null +++ b/src/ZoneCommon/Zone/XChunk/AbstractSalsa20Processor.h @@ -0,0 +1,45 @@ +#pragma once +#include +#include +#include + +#include "Utils/ClassUtils.h" +#include "Crypto.h" +#include "Utils/ICapturedDataProvider.h" + +class AbstractSalsa20Processor : public ICapturedDataProvider +{ +protected: + static constexpr int BLOCK_HASHES_COUNT = 200; + static constexpr int SHA1_HASH_SIZE = 20; + static constexpr int SALSA20_IV_SIZE = 8; + + class StreamContext + { + public: + std::unique_ptr m_salsa20; + std::unique_ptr m_sha1; + }; + + int m_stream_count; + std::unique_ptr m_stream_contexts; + + // m_block_hashes[BLOCK_HASHES_COUNT][numStreams][HASH_SIZE] + std::unique_ptr m_block_hashes; + std::unique_ptr m_stream_block_indices; + + AbstractSalsa20Processor(int streamCount, std::string& zoneName, const uint8_t* salsa20Key, size_t keySize); + + _NODISCARD uint8_t* GetHashBlock(int streamNumber) const; + + void InitStreams(std::string& zoneName, const uint8_t* salsa20Key, size_t keySize) const; + +public: + virtual ~AbstractSalsa20Processor() = default; + AbstractSalsa20Processor(const AbstractSalsa20Processor& other) = delete; + AbstractSalsa20Processor(AbstractSalsa20Processor&& other) noexcept = default; + AbstractSalsa20Processor& operator=(const AbstractSalsa20Processor& other) = delete; + AbstractSalsa20Processor& operator=(AbstractSalsa20Processor&& other) noexcept = default; + + void GetCapturedData(const uint8_t** pCapturedData, size_t* pSize) override; +}; diff --git a/src/ZoneLoading/Loading/Processor/XChunks/IXChunkProcessor.h b/src/ZoneCommon/Zone/XChunk/IXChunkProcessor.h similarity index 100% rename from src/ZoneLoading/Loading/Processor/XChunks/IXChunkProcessor.h rename to src/ZoneCommon/Zone/XChunk/IXChunkProcessor.h diff --git a/src/ZoneCommon/Zone/XChunk/XChunkException.cpp b/src/ZoneCommon/Zone/XChunk/XChunkException.cpp new file mode 100644 index 00000000..58aa13d5 --- /dev/null +++ b/src/ZoneCommon/Zone/XChunk/XChunkException.cpp @@ -0,0 +1,16 @@ +#include "XChunkException.h" + +XChunkException::XChunkException(std::string message) + : m_message(std::move(message)) +{ +} + +char const* XChunkException::what() const +{ + return m_message.c_str(); +} + +const std::string& XChunkException::Message() const +{ + return m_message; +} diff --git a/src/ZoneCommon/Zone/XChunk/XChunkException.h b/src/ZoneCommon/Zone/XChunk/XChunkException.h new file mode 100644 index 00000000..d1fb094b --- /dev/null +++ b/src/ZoneCommon/Zone/XChunk/XChunkException.h @@ -0,0 +1,16 @@ +#pragma once +#include +#include + +#include "Utils/ClassUtils.h" + +class XChunkException final : public std::exception +{ + std::string m_message; + +public: + explicit XChunkException(std::string message); + + _NODISCARD char const* what() const override; + _NODISCARD const std::string& Message() const; +}; diff --git a/src/ZoneCommon/Zone/XChunk/XChunkProcessorDeflate.cpp b/src/ZoneCommon/Zone/XChunk/XChunkProcessorDeflate.cpp new file mode 100644 index 00000000..5f1cf5ca --- /dev/null +++ b/src/ZoneCommon/Zone/XChunk/XChunkProcessorDeflate.cpp @@ -0,0 +1,33 @@ +#include "XChunkProcessorDeflate.h" + +#include +#include + +#include "XChunkException.h" + +size_t XChunkProcessorDeflate::Process(int streamNumber, const uint8_t* input, const size_t inputLength, uint8_t* output, const size_t outputBufferSize) +{ + z_stream stream{}; + stream.zalloc = Z_NULL; + stream.zfree = Z_NULL; + stream.opaque = Z_NULL; + + auto ret = deflateInit2(&stream, Z_BEST_COMPRESSION, Z_DEFLATED, -DEF_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); + if (ret != Z_OK) + throw XChunkException("Initializing deflate failed."); + + stream.avail_in = inputLength; + stream.next_in = input; + stream.avail_out = outputBufferSize; + stream.next_out = output; + + ret = deflate(&stream, Z_FINISH); + if (ret != Z_STREAM_END) + throw XChunkException("Zone has invalid or unsupported compression. Deflate failed"); + + const size_t outputSize = stream.total_out; + + deflateEnd(&stream); + + return outputSize; +} diff --git a/src/ZoneLoading/Loading/Processor/XChunks/ChunkProcessorInflate.h b/src/ZoneCommon/Zone/XChunk/XChunkProcessorDeflate.h similarity index 75% rename from src/ZoneLoading/Loading/Processor/XChunks/ChunkProcessorInflate.h rename to src/ZoneCommon/Zone/XChunk/XChunkProcessorDeflate.h index b02afa17..7c158c86 100644 --- a/src/ZoneLoading/Loading/Processor/XChunks/ChunkProcessorInflate.h +++ b/src/ZoneCommon/Zone/XChunk/XChunkProcessorDeflate.h @@ -1,7 +1,7 @@ #pragma once #include "IXChunkProcessor.h" -class ChunkProcessorInflate : public IXChunkProcessor +class XChunkProcessorDeflate final : public IXChunkProcessor { public: size_t Process(int streamNumber, const uint8_t* input, size_t inputLength, uint8_t* output, size_t outputBufferSize) override; diff --git a/src/ZoneCommon/Zone/XChunk/XChunkProcessorInflate.cpp b/src/ZoneCommon/Zone/XChunk/XChunkProcessorInflate.cpp new file mode 100644 index 00000000..82203921 --- /dev/null +++ b/src/ZoneCommon/Zone/XChunk/XChunkProcessorInflate.cpp @@ -0,0 +1,33 @@ +#include "XChunkProcessorInflate.h" + +#include +#include + +#include "XChunkException.h" + +size_t XChunkProcessorInflate::Process(int streamNumber, const uint8_t* input, const size_t inputLength, uint8_t* output, const size_t outputBufferSize) +{ + z_stream stream{}; + stream.zalloc = Z_NULL; + stream.zfree = Z_NULL; + stream.opaque = Z_NULL; + + auto ret = inflateInit2(&stream, -DEF_WBITS); + if (ret != Z_OK) + throw XChunkException("Initializing inflate failed."); + + stream.avail_in = inputLength; + stream.next_in = input; + stream.avail_out = outputBufferSize; + stream.next_out = output; + + ret = inflate(&stream, Z_FULL_FLUSH); + if (ret != Z_STREAM_END) + throw XChunkException("Zone has invalid or unsupported compression. Inflate failed"); + + const size_t outputSize = stream.total_out; + + inflateEnd(&stream); + + return outputSize; +} diff --git a/src/ZoneWriting/Writing/Processor/XChunks/XChunkOutputProcessorDeflate.h b/src/ZoneCommon/Zone/XChunk/XChunkProcessorInflate.h similarity index 59% rename from src/ZoneWriting/Writing/Processor/XChunks/XChunkOutputProcessorDeflate.h rename to src/ZoneCommon/Zone/XChunk/XChunkProcessorInflate.h index 870731b0..c328219f 100644 --- a/src/ZoneWriting/Writing/Processor/XChunks/XChunkOutputProcessorDeflate.h +++ b/src/ZoneCommon/Zone/XChunk/XChunkProcessorInflate.h @@ -1,7 +1,7 @@ #pragma once -#include "IXChunkOutputProcessor.h" +#include "IXChunkProcessor.h" -class XChunkOutputProcessorDeflate final : public IXChunkOutputProcessor +class XChunkProcessorInflate final : public IXChunkProcessor { public: size_t Process(int streamNumber, const uint8_t* input, size_t inputLength, uint8_t* output, size_t outputBufferSize) override; diff --git a/src/ZoneCommon/Zone/XChunk/XChunkProcessorSalsa20Decryption.cpp b/src/ZoneCommon/Zone/XChunk/XChunkProcessorSalsa20Decryption.cpp new file mode 100644 index 00000000..b4b6887f --- /dev/null +++ b/src/ZoneCommon/Zone/XChunk/XChunkProcessorSalsa20Decryption.cpp @@ -0,0 +1,44 @@ +#include "XChunkProcessorSalsa20Decryption.h" + +#include + +#include "Crypto.h" +#include "AbstractSalsa20Processor.h" + +XChunkProcessorSalsa20Decryption::XChunkProcessorSalsa20Decryption(const int streamCount, std::string& zoneName, const uint8_t* salsa20Key, size_t keySize) + : AbstractSalsa20Processor(streamCount, zoneName, salsa20Key, keySize) +{ +} + +size_t XChunkProcessorSalsa20Decryption::Process(const int streamNumber, const uint8_t* input, const size_t inputLength, uint8_t* output, const size_t outputBufferSize) +{ + assert(streamNumber >= 0 && streamNumber < m_stream_count); + assert(input != nullptr); + assert(output != nullptr); + assert(inputLength <= outputBufferSize); + + auto& streamContext = m_stream_contexts[streamNumber]; + + // Initialize Salsa20 with an IV of the first 8 bytes of the current hash block + streamContext.m_salsa20->SetIV(GetHashBlock(streamNumber), SALSA20_IV_SIZE); + streamContext.m_salsa20->Process(input, output, inputLength); + + // Hash decrypted XChunk + uint8_t blockSha1Hash[SHA1_HASH_SIZE]; + streamContext.m_sha1->Init(); + streamContext.m_sha1->Process(output, inputLength); + streamContext.m_sha1->Finish(&blockSha1Hash); + + // Advance index to next hash block + m_stream_block_indices[streamNumber] = (m_stream_block_indices[streamNumber] + 1) % BLOCK_HASHES_COUNT; + + auto* nextHashBlock = GetHashBlock(streamNumber); + + // XOR the upcoming hash block with the hash of the XChunk utilizing the previous hash block + for (unsigned int hashOffset = 0; hashOffset < sizeof(blockSha1Hash); hashOffset++) + { + nextHashBlock[hashOffset] ^= blockSha1Hash[hashOffset]; + } + + return inputLength; +} diff --git a/src/ZoneCommon/Zone/XChunk/XChunkProcessorSalsa20Decryption.h b/src/ZoneCommon/Zone/XChunk/XChunkProcessorSalsa20Decryption.h new file mode 100644 index 00000000..38076848 --- /dev/null +++ b/src/ZoneCommon/Zone/XChunk/XChunkProcessorSalsa20Decryption.h @@ -0,0 +1,13 @@ +#pragma once +#include + +#include "IXChunkProcessor.h" +#include "AbstractSalsa20Processor.h" + +class XChunkProcessorSalsa20Decryption final : public IXChunkProcessor, public AbstractSalsa20Processor +{ +public: + XChunkProcessorSalsa20Decryption(int streamCount, std::string& zoneName, const uint8_t* salsa20Key, size_t keySize); + + size_t Process(int streamNumber, const uint8_t* input, size_t inputLength, uint8_t* output, size_t outputBufferSize) override; +}; diff --git a/src/ZoneCommon/Zone/XChunk/XChunkProcessorSalsa20Encryption.cpp b/src/ZoneCommon/Zone/XChunk/XChunkProcessorSalsa20Encryption.cpp new file mode 100644 index 00000000..b9579567 --- /dev/null +++ b/src/ZoneCommon/Zone/XChunk/XChunkProcessorSalsa20Encryption.cpp @@ -0,0 +1,41 @@ +#include "XChunkProcessorSalsa20Encryption.h" + +#include + +XChunkProcessorSalsa20Encryption::XChunkProcessorSalsa20Encryption(const int streamCount, std::string& zoneName, const uint8_t* salsa20Key, const size_t keySize) + : AbstractSalsa20Processor(streamCount, zoneName, salsa20Key, keySize) +{ +} + +size_t XChunkProcessorSalsa20Encryption::Process(const int streamNumber, const uint8_t* input, const size_t inputLength, uint8_t* output, const size_t outputBufferSize) +{ + assert(streamNumber >= 0 && streamNumber < m_stream_count); + assert(input != nullptr); + assert(output != nullptr); + assert(inputLength <= outputBufferSize); + + auto& streamContext = m_stream_contexts[streamNumber]; + + // Hash not yet encrypted XChunk + uint8_t blockSha1Hash[SHA1_HASH_SIZE]; + streamContext.m_sha1->Init(); + streamContext.m_sha1->Process(input, inputLength); + streamContext.m_sha1->Finish(&blockSha1Hash); + + // Initialize Salsa20 with an IV of the first 8 bytes of the current hash block + streamContext.m_salsa20->SetIV(GetHashBlock(streamNumber), SALSA20_IV_SIZE); + streamContext.m_salsa20->Process(input, output, inputLength); + + // Advance index to next hash block + m_stream_block_indices[streamNumber] = (m_stream_block_indices[streamNumber] + 1) % BLOCK_HASHES_COUNT; + + auto* nextHashBlock = GetHashBlock(streamNumber); + + // XOR the upcoming hash block with the hash of the XChunk utilizing the previous hash block + for (unsigned int hashOffset = 0; hashOffset < sizeof(blockSha1Hash); hashOffset++) + { + nextHashBlock[hashOffset] ^= blockSha1Hash[hashOffset]; + } + + return inputLength; +} diff --git a/src/ZoneCommon/Zone/XChunk/XChunkProcessorSalsa20Encryption.h b/src/ZoneCommon/Zone/XChunk/XChunkProcessorSalsa20Encryption.h new file mode 100644 index 00000000..cc5637ed --- /dev/null +++ b/src/ZoneCommon/Zone/XChunk/XChunkProcessorSalsa20Encryption.h @@ -0,0 +1,14 @@ +#pragma once + +#include + +#include "AbstractSalsa20Processor.h" +#include "IXChunkProcessor.h" + +class XChunkProcessorSalsa20Encryption final : public IXChunkProcessor, public AbstractSalsa20Processor +{ +public: + XChunkProcessorSalsa20Encryption(int streamCount, std::string& zoneName, const uint8_t* salsa20Key, size_t keySize); + + size_t Process(int streamNumber, const uint8_t* input, size_t inputLength, uint8_t* output, size_t outputBufferSize) override; +}; diff --git a/src/ZoneLoading/Game/IW4/ZoneLoaderFactoryIW4.cpp b/src/ZoneLoading/Game/IW4/ZoneLoaderFactoryIW4.cpp index 74356cb6..9042d6c5 100644 --- a/src/ZoneLoading/Game/IW4/ZoneLoaderFactoryIW4.cpp +++ b/src/ZoneLoading/Game/IW4/ZoneLoaderFactoryIW4.cpp @@ -79,18 +79,16 @@ class ZoneLoaderFactory::Impl #undef XBLOCK_DEF } - static IPublicKeyAlgorithm* SetupRSA(const bool isOfficial) + static std::unique_ptr SetupRSA(const bool isOfficial) { if (isOfficial) { - auto* rsa = Crypto::CreateRSA(IPublicKeyAlgorithm::HashingAlgorithm::RSA_HASH_SHA256, + auto rsa = Crypto::CreateRSA(IPublicKeyAlgorithm::HashingAlgorithm::RSA_HASH_SHA256, Crypto::RSAPaddingMode::RSA_PADDING_PSS); if (!rsa->SetKey(ZoneConstants::RSA_PUBLIC_KEY_INFINITY_WARD, sizeof(ZoneConstants::RSA_PUBLIC_KEY_INFINITY_WARD))) { printf("Invalid public key for signature checking\n"); - - delete rsa; return nullptr; } @@ -113,7 +111,7 @@ class ZoneLoaderFactory::Impl return; // If file is signed setup a RSA instance. - IPublicKeyAlgorithm* rsa = SetupRSA(isOfficial); + auto rsa = SetupRSA(isOfficial); zoneLoader->AddLoadingStep(std::make_unique(ZoneConstants::MAGIC_AUTH_HEADER)); zoneLoader->AddLoadingStep(std::make_unique(4)); // Skip reserved @@ -126,7 +124,7 @@ class ZoneLoaderFactory::Impl auto* subHeaderHashSignaturePtr = subHeaderHashSignature.get(); zoneLoader->AddLoadingStep(std::move(subHeaderHashSignature)); - zoneLoader->AddLoadingStep(std::make_unique(rsa, subHeaderHashSignaturePtr, subHeaderHashPtr)); + zoneLoader->AddLoadingStep(std::make_unique(std::move(rsa), subHeaderHashSignaturePtr, subHeaderHashPtr)); auto subHeaderCapture = std::make_unique(sizeof(DB_AuthSubHeader)); auto* subHeaderCapturePtr = subHeaderCapture.get(); diff --git a/src/ZoneLoading/Game/T6/ZoneLoaderFactoryT6.cpp b/src/ZoneLoading/Game/T6/ZoneLoaderFactoryT6.cpp index b8100dde..de0ed935 100644 --- a/src/ZoneLoading/Game/T6/ZoneLoaderFactoryT6.cpp +++ b/src/ZoneLoading/Game/T6/ZoneLoaderFactoryT6.cpp @@ -12,8 +12,8 @@ #include "Game/GameLanguage.h" #include "Game/T6/GameT6.h" #include "Loading/Processor/ProcessorXChunks.h" -#include "Loading/Processor/XChunks/ChunkProcessorSalsa20.h" -#include "Loading/Processor/XChunks/ChunkProcessorInflate.h" +#include "Zone/XChunk/XChunkProcessorSalsa20Decryption.h" +#include "Zone/XChunk/XChunkProcessorInflate.h" #include "Loading/Steps/StepVerifyMagic.h" #include "Loading/Steps/StepSkipBytes.h" #include "Loading/Steps/StepVerifyFileName.h" @@ -104,17 +104,15 @@ class ZoneLoaderFactory::Impl #undef XBLOCK_DEF } - static IPublicKeyAlgorithm* SetupRSA(const bool isOfficial) + static std::unique_ptr SetupRSA(const bool isOfficial) { if (isOfficial) { - auto* rsa = Crypto::CreateRSA(IPublicKeyAlgorithm::HashingAlgorithm::RSA_HASH_SHA256, Crypto::RSAPaddingMode::RSA_PADDING_PSS); + auto rsa = Crypto::CreateRSA(IPublicKeyAlgorithm::HashingAlgorithm::RSA_HASH_SHA256, Crypto::RSAPaddingMode::RSA_PADDING_PSS); if (!rsa->SetKey(ZoneConstants::RSA_PUBLIC_KEY_TREYARCH, sizeof(ZoneConstants::RSA_PUBLIC_KEY_TREYARCH))) { printf("Invalid public key for signature checking\n"); - - delete rsa; return nullptr; } @@ -154,14 +152,14 @@ class ZoneLoaderFactory::Impl if (isEncrypted) { // If zone is encrypted, the decryption is applied before the decompression. T6 Zones always use Salsa20. - auto chunkProcessorSalsa20 = std::make_unique(ZoneConstants::STREAM_COUNT, fileName, ZoneConstants::SALSA20_KEY_TREYARCH, + auto chunkProcessorSalsa20 = std::make_unique(ZoneConstants::STREAM_COUNT, fileName, ZoneConstants::SALSA20_KEY_TREYARCH, sizeof(ZoneConstants::SALSA20_KEY_TREYARCH)); result = chunkProcessorSalsa20.get(); xChunkProcessor->AddChunkProcessor(std::move(chunkProcessorSalsa20)); } // Decompress the chunks using zlib - xChunkProcessor->AddChunkProcessor(std::make_unique()); + xChunkProcessor->AddChunkProcessor(std::make_unique()); zoneLoader->AddLoadingStep(std::make_unique(std::move(xChunkProcessor))); // If there is encryption, the signed data of the zone is the final hash blocks provided by the Salsa20 IV adaption algorithm @@ -190,7 +188,7 @@ public: SetupBlock(zoneLoader); // If file is signed setup a RSA instance. - IPublicKeyAlgorithm* rsa = isSecure ? SetupRSA(isOfficial) : nullptr; + auto rsa = isSecure ? SetupRSA(isOfficial) : nullptr; // Add steps for loading the auth header which also contain the signature of the zone if it is signed. ISignatureProvider* signatureProvider = AddAuthHeaderSteps(isSecure, zoneLoader, fileName); @@ -207,7 +205,7 @@ public: if (isSecure) { - zoneLoader->AddLoadingStep(std::make_unique(rsa, signatureProvider, signatureDataProvider)); + zoneLoader->AddLoadingStep(std::make_unique(std::move(rsa), signatureProvider, signatureDataProvider)); } // Return the fully setup zoneloader diff --git a/src/ZoneLoading/Loading/Processor/ProcessorXChunks.cpp b/src/ZoneLoading/Loading/Processor/ProcessorXChunks.cpp index 509d212a..80e65599 100644 --- a/src/ZoneLoading/Loading/Processor/ProcessorXChunks.cpp +++ b/src/ZoneLoading/Loading/Processor/ProcessorXChunks.cpp @@ -8,11 +8,14 @@ #include #include #include +#include class DBLoadStream { int m_index; + std::unique_ptr m_buffers[2]; + uint8_t* m_input_buffer; size_t m_input_size; @@ -62,8 +65,11 @@ public: m_index = streamIndex; m_chunk_size = chunkSize; - m_input_buffer = new uint8_t[chunkSize]; - m_output_buffer = new uint8_t[chunkSize]; + for(auto& buffer : m_buffers) + buffer = std::make_unique(chunkSize); + + m_input_buffer = m_buffers[0].get(); + m_output_buffer = m_buffers[1].get(); m_input_size = 0; m_output_size = 0; @@ -71,15 +77,6 @@ public: m_is_loading = false; } - ~DBLoadStream() - { - delete[] m_input_buffer; - m_input_buffer = nullptr; - - delete[] m_output_buffer; - m_output_buffer = nullptr; - } - uint8_t* GetInputBuffer() const { return m_input_buffer; diff --git a/src/ZoneLoading/Loading/Processor/ProcessorXChunks.h b/src/ZoneLoading/Loading/Processor/ProcessorXChunks.h index 1f2df3e3..f3f82e44 100644 --- a/src/ZoneLoading/Loading/Processor/ProcessorXChunks.h +++ b/src/ZoneLoading/Loading/Processor/ProcessorXChunks.h @@ -2,7 +2,7 @@ #include #include "Loading/StreamProcessor.h" -#include "XChunks/IXChunkProcessor.h" +#include "Zone/XChunk/IXChunkProcessor.h" class ProcessorXChunks : public StreamProcessor { diff --git a/src/ZoneLoading/Loading/Processor/XChunks/ChunkProcessorInflate.cpp b/src/ZoneLoading/Loading/Processor/XChunks/ChunkProcessorInflate.cpp deleted file mode 100644 index 2f33d262..00000000 --- a/src/ZoneLoading/Loading/Processor/XChunks/ChunkProcessorInflate.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include "ChunkProcessorInflate.h" - -#include - -#include "zlib.h" -#include "zutil.h" - -#include "Loading/Exception/InvalidCompressionException.h" - -size_t ChunkProcessorInflate::Process(int streamNumber, const uint8_t* input, const size_t inputLength, uint8_t* output, const size_t outputBufferSize) -{ - z_stream stream{}; - stream.zalloc = Z_NULL; - stream.zfree = Z_NULL; - stream.opaque = Z_NULL; - - int ret = inflateInit2(&stream, -DEF_WBITS); - if(ret != Z_OK) - { - throw std::runtime_error("Initializing inflate failed."); - } - - stream.avail_in = inputLength; - stream.next_in = input; - stream.avail_out = outputBufferSize; - stream.next_out = output; - - ret = inflate(&stream, Z_FULL_FLUSH); - if(ret != Z_STREAM_END) - { - throw InvalidCompressionException(); - } - - const size_t outputSize = stream.total_out; - - inflateEnd(&stream); - - return outputSize; -} diff --git a/src/ZoneLoading/Loading/Processor/XChunks/ChunkProcessorSalsa20.cpp b/src/ZoneLoading/Loading/Processor/XChunks/ChunkProcessorSalsa20.cpp deleted file mode 100644 index 648f060b..00000000 --- a/src/ZoneLoading/Loading/Processor/XChunks/ChunkProcessorSalsa20.cpp +++ /dev/null @@ -1,156 +0,0 @@ -#include "ChunkProcessorSalsa20.h" -#include "Crypto.h" -#include - -class StreamContextSalsa20 -{ -public: - IStreamCipher* m_salsa20; - IHashFunction* m_sha1; - - StreamContextSalsa20() - { - m_salsa20 = nullptr; - m_sha1 = nullptr; - } - - ~StreamContextSalsa20() - { - delete m_salsa20; - m_salsa20 = nullptr; - - delete m_sha1; - m_sha1 = nullptr; - } -}; - -class ChunkProcessorSalsa20::ChunkProcessorSalsa20Impl -{ - static const int BLOCK_HASHES_COUNT = 200; - static const int SHA1_HASH_SIZE = 20; - static const int SALSA20_IV_SIZE = 8; - - int m_stream_count; - StreamContextSalsa20* m_stream_contexts; - - // m_block_hashes[BLOCK_HASHES_COUNT][numStreams][HASH_SIZE] - uint8_t* m_block_hashes; - unsigned int* m_stream_block_indices; - - uint8_t* GetHashBlock(const int streamNumber) const - { - const size_t blockIndexOffset = m_stream_block_indices[streamNumber] * m_stream_count * SHA1_HASH_SIZE; - const size_t streamOffset = streamNumber * SHA1_HASH_SIZE; - - return &m_block_hashes[blockIndexOffset + streamOffset]; - } - -public: - ChunkProcessorSalsa20Impl(const int streamCount, std::string& zoneName, const uint8_t* salsa20Key, size_t keySize) - { - m_stream_count = streamCount; - m_stream_contexts = new StreamContextSalsa20[streamCount]; - m_block_hashes = new uint8_t[BLOCK_HASHES_COUNT * streamCount * SHA1_HASH_SIZE]; - m_stream_block_indices = new unsigned int[streamCount]; - - InitStreams(zoneName, salsa20Key, keySize); - } - - ~ChunkProcessorSalsa20Impl() - { - delete[] m_stream_contexts; - - delete[] m_block_hashes; - m_block_hashes = nullptr; - - delete[] m_stream_block_indices; - m_stream_block_indices = nullptr; - } - - void InitStreams(std::string& zoneName, const uint8_t* salsa20Key, size_t keySize) const - { - const int zoneNameLength = zoneName.length(); - const size_t blockHashBufferSize = BLOCK_HASHES_COUNT * m_stream_count * SHA1_HASH_SIZE; - - assert(blockHashBufferSize % 4 == 0); - - size_t zoneNameOffset = 0; - for(size_t i = 0; i < blockHashBufferSize; i += 4) - { - *reinterpret_cast(&m_block_hashes[i]) = 0x1010101 * zoneName[zoneNameOffset++]; - - zoneNameOffset %= zoneNameLength; - } - - for(int stream = 0; stream < m_stream_count; stream++) - { - m_stream_block_indices[stream] = 0; - - m_stream_contexts[stream].m_salsa20 = Crypto::CreateSalsa20(salsa20Key, keySize); - m_stream_contexts[stream].m_sha1 = Crypto::CreateSHA1(); - } - } - - size_t Process(const int streamNumber, const uint8_t* input, const size_t inputLength, uint8_t* output, const size_t outputBufferSize) const - { - assert(streamNumber >= 0 && streamNumber < m_stream_count); - assert(input != nullptr); - assert(output != nullptr); - assert(inputLength <= outputBufferSize); - - StreamContextSalsa20& streamContext = m_stream_contexts[streamNumber]; - - // Initialize Salsa20 with an IV of the first 8 bytes of the current hash block - streamContext.m_salsa20->SetIV(GetHashBlock(streamNumber), SALSA20_IV_SIZE); - streamContext.m_salsa20->Process(input, output, inputLength); - - // Hash decrypted XChunk - uint8_t blockSha1Hash[SHA1_HASH_SIZE]; - streamContext.m_sha1->Init(); - streamContext.m_sha1->Process(output, inputLength); - streamContext.m_sha1->Finish(&blockSha1Hash); - - // Advance index to next hash block - m_stream_block_indices[streamNumber] = (m_stream_block_indices[streamNumber] + 1) % BLOCK_HASHES_COUNT; - - uint8_t* nextHashBlock = GetHashBlock(streamNumber); - - // XOR the upcoming hash block with the hash of the XChunk utilizing the previous hash block - for(unsigned int hashOffset = 0; hashOffset < sizeof(blockSha1Hash); hashOffset++) - { - nextHashBlock[hashOffset] ^= blockSha1Hash[hashOffset]; - } - - return inputLength; - } - - void GetSignatureData(const uint8_t** pSignatureData, size_t* pSize) const - { - assert(pSignatureData != nullptr); - assert(pSize != nullptr); - - *pSignatureData = m_block_hashes; - *pSize = BLOCK_HASHES_COUNT * m_stream_count * SHA1_HASH_SIZE; - } -}; - -ChunkProcessorSalsa20::ChunkProcessorSalsa20(const int streamCount, std::string& zoneName, const uint8_t* salsa20Key, size_t keySize) -{ - m_impl = new ChunkProcessorSalsa20Impl(streamCount, zoneName, salsa20Key, keySize); -} - -ChunkProcessorSalsa20::~ChunkProcessorSalsa20() -{ - delete m_impl; - m_impl = nullptr; -} - -size_t ChunkProcessorSalsa20::Process(const int streamNumber, const uint8_t* input, const size_t inputLength, uint8_t* output, const size_t outputBufferSize) -{ - return m_impl->Process(streamNumber, input, inputLength, output, outputBufferSize); -} - -void ChunkProcessorSalsa20::GetCapturedData(const uint8_t** pCapturedData, size_t* pSize) -{ - m_impl->GetSignatureData(pCapturedData, pSize); -} \ No newline at end of file diff --git a/src/ZoneLoading/Loading/Processor/XChunks/ChunkProcessorSalsa20.h b/src/ZoneLoading/Loading/Processor/XChunks/ChunkProcessorSalsa20.h deleted file mode 100644 index 4868268e..00000000 --- a/src/ZoneLoading/Loading/Processor/XChunks/ChunkProcessorSalsa20.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include "IXChunkProcessor.h" -#include "Utils/ICapturedDataProvider.h" -#include - -class ChunkProcessorSalsa20 : public IXChunkProcessor, public ICapturedDataProvider -{ - class ChunkProcessorSalsa20Impl; - ChunkProcessorSalsa20Impl* m_impl; - -public: - ChunkProcessorSalsa20(int streamCount, std::string& zoneName, const uint8_t* salsa20Key, size_t keySize); - ~ChunkProcessorSalsa20() override; - - size_t Process(int streamNumber, const uint8_t* input, size_t inputLength, uint8_t* output, size_t outputBufferSize) override; - void GetCapturedData(const uint8_t** pCapturedData, size_t* pSize) override; -}; diff --git a/src/ZoneLoading/Loading/Steps/StepVerifySignature.cpp b/src/ZoneLoading/Loading/Steps/StepVerifySignature.cpp index 1ce1b9cf..72824082 100644 --- a/src/ZoneLoading/Loading/Steps/StepVerifySignature.cpp +++ b/src/ZoneLoading/Loading/Steps/StepVerifySignature.cpp @@ -2,17 +2,11 @@ #include "Loading/Exception/InvalidSignatureException.h" #include -StepVerifySignature::StepVerifySignature(IPublicKeyAlgorithm* signatureAlgorithm, ISignatureProvider* signatureProvider, ICapturedDataProvider* signatureDataProvider) +StepVerifySignature::StepVerifySignature(std::unique_ptr signatureAlgorithm, ISignatureProvider* signatureProvider, ICapturedDataProvider* signatureDataProvider) + : m_algorithm(std::move(signatureAlgorithm)), + m_signature_provider(signatureProvider), + m_signature_data_provider(signatureDataProvider) { - m_algorithm = signatureAlgorithm; - m_signature_provider = signatureProvider; - m_signature_data_provider = signatureDataProvider; -} - -StepVerifySignature::~StepVerifySignature() -{ - delete m_algorithm; - m_algorithm = nullptr; } void StepVerifySignature::PerformStep(ZoneLoader* zoneLoader, ILoadingStream* stream) @@ -29,8 +23,8 @@ void StepVerifySignature::PerformStep(ZoneLoader* zoneLoader, ILoadingStream* st size_t signatureDataSize; m_signature_data_provider->GetCapturedData(&signatureData, &signatureDataSize); - if(!m_algorithm->Verify(signatureData, signatureDataSize, signature, signatureSize)) + if (!m_algorithm->Verify(signatureData, signatureDataSize, signature, signatureSize)) { throw InvalidSignatureException(); } -} \ No newline at end of file +} diff --git a/src/ZoneLoading/Loading/Steps/StepVerifySignature.h b/src/ZoneLoading/Loading/Steps/StepVerifySignature.h index fe8c60f0..2beb0d39 100644 --- a/src/ZoneLoading/Loading/Steps/StepVerifySignature.h +++ b/src/ZoneLoading/Loading/Steps/StepVerifySignature.h @@ -7,16 +7,16 @@ class StepVerifySignature final : public ILoadingStep { - IPublicKeyAlgorithm* m_algorithm; + std::unique_ptr m_algorithm; ISignatureProvider* m_signature_provider; ICapturedDataProvider* m_signature_data_provider; public: - StepVerifySignature(IPublicKeyAlgorithm* signatureAlgorithm, ISignatureProvider* signatureProvider, ICapturedDataProvider* signatureDataProvider); - ~StepVerifySignature(); - StepVerifySignature(const StepVerifySignature& other) = default; + StepVerifySignature(std::unique_ptr signatureAlgorithm, ISignatureProvider* signatureProvider, ICapturedDataProvider* signatureDataProvider); + ~StepVerifySignature() override = default; + StepVerifySignature(const StepVerifySignature& other) = delete; StepVerifySignature(StepVerifySignature&& other) noexcept = default; - StepVerifySignature& operator=(const StepVerifySignature& other) = default; + StepVerifySignature& operator=(const StepVerifySignature& other) = delete; StepVerifySignature& operator=(StepVerifySignature&& other) noexcept = default; void PerformStep(ZoneLoader* zoneLoader, ILoadingStream* stream) override; diff --git a/src/ZoneWriting/Game/T6/ZoneWriterFactoryT6.cpp b/src/ZoneWriting/Game/T6/ZoneWriterFactoryT6.cpp index ce25f863..95308590 100644 --- a/src/ZoneWriting/Game/T6/ZoneWriterFactoryT6.cpp +++ b/src/ZoneWriting/Game/T6/ZoneWriterFactoryT6.cpp @@ -8,8 +8,8 @@ #include "Game/T6/GameT6.h" #include "Game/T6/ZoneConstantsT6.h" #include "Writing/Processor/OutputProcessorXChunks.h" -#include "Writing/Processor/XChunks/XChunkOutputProcessorDeflate.h" -#include "Writing/Processor/XChunks/XChunkOutputProcessorSalsa20.h" +#include "Zone/XChunk/XChunkProcessorDeflate.h" +#include "Zone/XChunk/XChunkProcessorSalsa20Encryption.h" #include "Writing/Steps/StepAddOutputProcessor.h" #include "Writing/Steps/StepWriteXBlockSizes.h" #include "Writing/Steps/StepWriteZoneContentToFile.h" @@ -77,14 +77,14 @@ public: if (isEncrypted) { // If zone is encrypted, the decryption is applied before the decompression. T6 Zones always use Salsa20. - auto chunkProcessorSalsa20 = std::make_unique(ZoneConstants::STREAM_COUNT, m_zone->m_name, ZoneConstants::SALSA20_KEY_TREYARCH, + auto chunkProcessorSalsa20 = std::make_unique(ZoneConstants::STREAM_COUNT, m_zone->m_name, ZoneConstants::SALSA20_KEY_TREYARCH, sizeof(ZoneConstants::SALSA20_KEY_TREYARCH)); result = chunkProcessorSalsa20.get(); xChunkProcessor->AddChunkProcessor(std::move(chunkProcessorSalsa20)); } // Decompress the chunks using zlib - xChunkProcessor->AddChunkProcessor(std::make_unique()); + xChunkProcessor->AddChunkProcessor(std::make_unique()); m_writer->AddWritingStep(std::make_unique(std::move(xChunkProcessor))); // If there is encryption, the signed data of the zone is the final hash blocks provided by the Salsa20 IV adaption algorithm diff --git a/src/ZoneWriting/Writing/Processor/OutputProcessorXChunks.cpp b/src/ZoneWriting/Writing/Processor/OutputProcessorXChunks.cpp index 4c2285c4..a3a45a2d 100644 --- a/src/ZoneWriting/Writing/Processor/OutputProcessorXChunks.cpp +++ b/src/ZoneWriting/Writing/Processor/OutputProcessorXChunks.cpp @@ -32,7 +32,7 @@ OutputProcessorXChunks& OutputProcessorXChunks::operator=(OutputProcessorXChunks return *this; } -void OutputProcessorXChunks::AddChunkProcessor(std::unique_ptr chunkProcessor) const +void OutputProcessorXChunks::AddChunkProcessor(std::unique_ptr chunkProcessor) const { } diff --git a/src/ZoneWriting/Writing/Processor/OutputProcessorXChunks.h b/src/ZoneWriting/Writing/Processor/OutputProcessorXChunks.h index 458bec90..c9f16d25 100644 --- a/src/ZoneWriting/Writing/Processor/OutputProcessorXChunks.h +++ b/src/ZoneWriting/Writing/Processor/OutputProcessorXChunks.h @@ -2,7 +2,7 @@ #include #include "Writing/OutputStreamProcessor.h" -#include "XChunks/IXChunkOutputProcessor.h" +#include "Zone/XChunk/IXChunkProcessor.h" class OutputProcessorXChunks final : public OutputStreamProcessor { @@ -19,7 +19,7 @@ public: OutputProcessorXChunks& operator=(const OutputProcessorXChunks& other) = delete; OutputProcessorXChunks& operator=(OutputProcessorXChunks&& other) noexcept; - void AddChunkProcessor(std::unique_ptr chunkProcessor) const; + void AddChunkProcessor(std::unique_ptr chunkProcessor) const; void Write(const void* buffer, size_t length) override; int64_t Pos() override; diff --git a/src/ZoneWriting/Writing/Processor/XChunks/IXChunkOutputProcessor.h b/src/ZoneWriting/Writing/Processor/XChunks/IXChunkOutputProcessor.h deleted file mode 100644 index 60b5270c..00000000 --- a/src/ZoneWriting/Writing/Processor/XChunks/IXChunkOutputProcessor.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include -#include - -class IXChunkOutputProcessor -{ -public: - IXChunkOutputProcessor() = default; - virtual ~IXChunkOutputProcessor() = default; - IXChunkOutputProcessor(const IXChunkOutputProcessor& other) = default; - IXChunkOutputProcessor(IXChunkOutputProcessor&& other) noexcept = default; - IXChunkOutputProcessor& operator=(const IXChunkOutputProcessor& other) = default; - IXChunkOutputProcessor& operator=(IXChunkOutputProcessor&& other) noexcept = default; - - virtual size_t Process(int streamNumber, const uint8_t* input, size_t inputLength, uint8_t* output, size_t outputBufferSize) = 0; -}; diff --git a/src/ZoneWriting/Writing/Processor/XChunks/XChunkOutputProcessorDeflate.cpp b/src/ZoneWriting/Writing/Processor/XChunks/XChunkOutputProcessorDeflate.cpp deleted file mode 100644 index e69de29b..00000000 diff --git a/src/ZoneWriting/Writing/Processor/XChunks/XChunkOutputProcessorSalsa20.cpp b/src/ZoneWriting/Writing/Processor/XChunks/XChunkOutputProcessorSalsa20.cpp deleted file mode 100644 index e69de29b..00000000 diff --git a/src/ZoneWriting/Writing/Processor/XChunks/XChunkOutputProcessorSalsa20.h b/src/ZoneWriting/Writing/Processor/XChunks/XChunkOutputProcessorSalsa20.h deleted file mode 100644 index 120fb761..00000000 --- a/src/ZoneWriting/Writing/Processor/XChunks/XChunkOutputProcessorSalsa20.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once -#include "IXChunkOutputProcessor.h" -#include "Utils/ICapturedDataProvider.h" - -class XChunkOutputProcessorSalsa20 final : public IXChunkOutputProcessor, public ICapturedDataProvider -{ - class Impl; - Impl* m_impl; - -public: - XChunkOutputProcessorSalsa20(int streamCount, std::string& zoneName, const uint8_t* salsa20Key, size_t keySize); - ~XChunkOutputProcessorSalsa20() override; - XChunkOutputProcessorSalsa20(const XChunkOutputProcessorSalsa20& other) = delete; - XChunkOutputProcessorSalsa20(XChunkOutputProcessorSalsa20&& other) noexcept = default; - XChunkOutputProcessorSalsa20& operator=(const XChunkOutputProcessorSalsa20& other) = delete; - XChunkOutputProcessorSalsa20& operator=(XChunkOutputProcessorSalsa20&& other) noexcept = default; - - size_t Process(int streamNumber, const uint8_t* input, size_t inputLength, uint8_t* output, size_t outputBufferSize) override; - void GetCapturedData(const uint8_t** pCapturedData, size_t* pSize) override; -}; diff --git a/src/ZoneWriting/ZoneWriting.cpp b/src/ZoneWriting/ZoneWriting.cpp index e5044081..42f103df 100644 --- a/src/ZoneWriting/ZoneWriting.cpp +++ b/src/ZoneWriting/ZoneWriting.cpp @@ -12,5 +12,21 @@ IZoneWriterFactory* ZoneWriterFactories[] bool ZoneWriting::WriteZone(std::ostream& stream, Zone* zone) { - return true; + std::unique_ptr zoneWriter; + for (auto* factory : ZoneWriterFactories) + { + if(factory->SupportsZone(zone)) + { + zoneWriter = factory->CreateWriter(zone); + break; + } + } + + if (zoneWriter == nullptr) + { + printf("Could not create ZoneWriter for zone '%s'.\n", zone->m_name.c_str()); + return false; + } + + return zoneWriter->WriteZone(stream); }