Move XChunk processors to ZoneCommon

This commit is contained in:
Jan
2021-03-16 20:42:48 +01:00
parent ca1329323b
commit f22012d282
33 changed files with 383 additions and 317 deletions

View File

@ -8,11 +8,14 @@
#include <condition_variable>
#include <cassert>
#include <cstring>
#include <memory>
class DBLoadStream
{
int m_index;
std::unique_ptr<uint8_t[]> 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<uint8_t[]>(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;

View File

@ -2,7 +2,7 @@
#include <memory>
#include "Loading/StreamProcessor.h"
#include "XChunks/IXChunkProcessor.h"
#include "Zone/XChunk/IXChunkProcessor.h"
class ProcessorXChunks : public StreamProcessor
{

View File

@ -1,39 +0,0 @@
#include "ChunkProcessorInflate.h"
#include <stdexcept>
#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;
}

View File

@ -1,8 +0,0 @@
#pragma once
#include "IXChunkProcessor.h"
class ChunkProcessorInflate : public IXChunkProcessor
{
public:
size_t Process(int streamNumber, const uint8_t* input, size_t inputLength, uint8_t* output, size_t outputBufferSize) override;
};

View File

@ -1,156 +0,0 @@
#include "ChunkProcessorSalsa20.h"
#include "Crypto.h"
#include <cassert>
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<uint32_t*>(&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);
}

View File

@ -1,17 +0,0 @@
#pragma once
#include "IXChunkProcessor.h"
#include "Utils/ICapturedDataProvider.h"
#include <string>
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;
};

View File

@ -1,11 +0,0 @@
#pragma once
#include <cstdint>
#include <cstddef>
class IXChunkProcessor
{
public:
virtual ~IXChunkProcessor() = default;
virtual size_t Process(int streamNumber, const uint8_t* input, size_t inputLength, uint8_t* output, size_t outputBufferSize) = 0;
};

View File

@ -2,17 +2,11 @@
#include "Loading/Exception/InvalidSignatureException.h"
#include <cassert>
StepVerifySignature::StepVerifySignature(IPublicKeyAlgorithm* signatureAlgorithm, ISignatureProvider* signatureProvider, ICapturedDataProvider* signatureDataProvider)
StepVerifySignature::StepVerifySignature(std::unique_ptr<IPublicKeyAlgorithm> 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();
}
}
}

View File

@ -7,16 +7,16 @@
class StepVerifySignature final : public ILoadingStep
{
IPublicKeyAlgorithm* m_algorithm;
std::unique_ptr<IPublicKeyAlgorithm> 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<IPublicKeyAlgorithm> 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;