Revert stream M2Pack archive support
Some checks are pending
build / Windows Build (push) Waiting to run
Some checks are pending
build / Windows Build (push) Waiting to run
This commit is contained in:
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#include <zstd.h>
|
#include <zstd.h>
|
||||||
|
|
||||||
#include "EterBase/Debug.h"
|
#include "EterBase/Debug.h"
|
||||||
@@ -37,44 +38,6 @@ bool ReadPod(const uint8_t* bytes, std::size_t size, std::size_t& offset, T& out
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsSupportedM2PackVersion(uint32_t version)
|
|
||||||
{
|
|
||||||
return version == M2PACK_VERSION_AEAD || version == M2PACK_VERSION_STREAM;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool VerifyM2PackHash(
|
|
||||||
std::string_view stage,
|
|
||||||
const uint8_t* input,
|
|
||||||
std::size_t inputSize,
|
|
||||||
const std::array<uint8_t, M2PACK_HASH_SIZE>& expected,
|
|
||||||
const char* path)
|
|
||||||
{
|
|
||||||
std::array<uint8_t, M2PACK_HASH_SIZE> actual {};
|
|
||||||
const auto hashStart = std::chrono::steady_clock::now();
|
|
||||||
crypto_generichash(
|
|
||||||
actual.data(),
|
|
||||||
actual.size(),
|
|
||||||
input,
|
|
||||||
inputSize,
|
|
||||||
nullptr,
|
|
||||||
0);
|
|
||||||
RecordPackProfileStage(
|
|
||||||
"m2p",
|
|
||||||
stage,
|
|
||||||
inputSize,
|
|
||||||
actual.size(),
|
|
||||||
static_cast<std::uint64_t>(std::chrono::duration_cast<std::chrono::microseconds>(
|
|
||||||
std::chrono::steady_clock::now() - hashStart).count()));
|
|
||||||
|
|
||||||
if (memcmp(actual.data(), expected.data(), actual.size()) != 0)
|
|
||||||
{
|
|
||||||
TraceError("CM2Pack: %s mismatch for '%s'", std::string(stage).c_str(), path);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CM2Pack::Load(const std::string& path)
|
bool CM2Pack::Load(const std::string& path)
|
||||||
@@ -103,7 +66,7 @@ bool CM2Pack::Load(const std::string& path)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsSupportedM2PackVersion(m_header.version))
|
if (m_header.version != 1)
|
||||||
{
|
{
|
||||||
TraceError("CM2Pack::Load: unsupported version %u in '%s'", m_header.version, path.c_str());
|
TraceError("CM2Pack::Load: unsupported version %u in '%s'", m_header.version, path.c_str());
|
||||||
return false;
|
return false;
|
||||||
@@ -207,54 +170,26 @@ bool CM2Pack::ValidateManifest()
|
|||||||
|
|
||||||
for (uint32_t i = 0; i < manifest_header.entry_count; ++i)
|
for (uint32_t i = 0; i < manifest_header.entry_count; ++i)
|
||||||
{
|
{
|
||||||
|
TM2PackManifestEntryFixed fixed {};
|
||||||
|
if (!ReadPod(m_manifest_bytes.data(), m_manifest_bytes.size(), offset, fixed))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset + fixed.path_size > m_manifest_bytes.size())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
TM2PackEntry entry;
|
TM2PackEntry entry;
|
||||||
uint16_t pathSize = 0;
|
entry.path.assign(reinterpret_cast<const char*>(m_manifest_bytes.data() + offset), fixed.path_size);
|
||||||
|
offset += fixed.path_size;
|
||||||
if (m_header.version == M2PACK_VERSION_AEAD)
|
entry.compression = fixed.compression;
|
||||||
{
|
entry.data_offset = fixed.data_offset;
|
||||||
TM2PackManifestEntryFixed fixed {};
|
entry.original_size = fixed.original_size;
|
||||||
if (!ReadPod(m_manifest_bytes.data(), m_manifest_bytes.size(), offset, fixed))
|
entry.stored_size = fixed.stored_size;
|
||||||
{
|
memcpy(entry.nonce.data(), fixed.nonce, entry.nonce.size());
|
||||||
return false;
|
memcpy(entry.plaintext_hash.data(), fixed.plaintext_hash, entry.plaintext_hash.size());
|
||||||
}
|
|
||||||
|
|
||||||
pathSize = fixed.path_size;
|
|
||||||
entry.compression = fixed.compression;
|
|
||||||
entry.data_offset = fixed.data_offset;
|
|
||||||
entry.original_size = fixed.original_size;
|
|
||||||
entry.stored_size = fixed.stored_size;
|
|
||||||
memcpy(entry.nonce.data(), fixed.nonce, entry.nonce.size());
|
|
||||||
memcpy(entry.plaintext_hash.data(), fixed.plaintext_hash, entry.plaintext_hash.size());
|
|
||||||
}
|
|
||||||
else if (m_header.version == M2PACK_VERSION_STREAM)
|
|
||||||
{
|
|
||||||
TM2PackManifestEntryFixedV2 fixed {};
|
|
||||||
if (!ReadPod(m_manifest_bytes.data(), m_manifest_bytes.size(), offset, fixed))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
pathSize = fixed.path_size;
|
|
||||||
entry.compression = fixed.compression;
|
|
||||||
entry.data_offset = fixed.data_offset;
|
|
||||||
entry.original_size = fixed.original_size;
|
|
||||||
entry.stored_size = fixed.stored_size;
|
|
||||||
memcpy(entry.nonce.data(), fixed.nonce, entry.nonce.size());
|
|
||||||
memcpy(entry.payload_hash.data(), fixed.payload_hash, entry.payload_hash.size());
|
|
||||||
memcpy(entry.plaintext_hash.data(), fixed.plaintext_hash, entry.plaintext_hash.size());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (offset + pathSize > m_manifest_bytes.size())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
entry.path.assign(reinterpret_cast<const char*>(m_manifest_bytes.data() + offset), pathSize);
|
|
||||||
offset += pathSize;
|
|
||||||
|
|
||||||
const uint64_t payload_begin = sizeof(TM2PackHeader);
|
const uint64_t payload_begin = sizeof(TM2PackHeader);
|
||||||
const uint64_t payload_end = m_header.manifest_offset;
|
const uint64_t payload_end = m_header.manifest_offset;
|
||||||
@@ -296,66 +231,17 @@ bool CM2Pack::DecryptEntryPayload(const TM2PackEntry& entry, std::vector<uint8_t
|
|||||||
}
|
}
|
||||||
decrypted.resize(entry.stored_size);
|
decrypted.resize(entry.stored_size);
|
||||||
const auto decryptStart = std::chrono::steady_clock::now();
|
const auto decryptStart = std::chrono::steady_clock::now();
|
||||||
std::size_t written = entry.stored_size;
|
unsigned long long written = 0;
|
||||||
|
if (crypto_aead_xchacha20poly1305_ietf_decrypt(
|
||||||
if (m_header.version == M2PACK_VERSION_AEAD)
|
decrypted.data(),
|
||||||
{
|
&written,
|
||||||
unsigned long long aeadWritten = 0;
|
nullptr,
|
||||||
if (crypto_aead_xchacha20poly1305_ietf_decrypt(
|
ciphertext,
|
||||||
decrypted.data(),
|
entry.stored_size,
|
||||||
&aeadWritten,
|
reinterpret_cast<const unsigned char*>(entry.path.data()),
|
||||||
nullptr,
|
entry.path.size(),
|
||||||
ciphertext,
|
entry.nonce.data(),
|
||||||
entry.stored_size,
|
GetM2PackActiveMasterKey().data()) != 0)
|
||||||
reinterpret_cast<const unsigned char*>(entry.path.data()),
|
|
||||||
entry.path.size(),
|
|
||||||
entry.nonce.data(),
|
|
||||||
GetM2PackActiveMasterKey().data()) != 0)
|
|
||||||
{
|
|
||||||
if (pPool)
|
|
||||||
{
|
|
||||||
pPool->Release(std::move(decrypted));
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
written = static_cast<std::size_t>(aeadWritten);
|
|
||||||
RecordPackProfileStage(
|
|
||||||
"m2p",
|
|
||||||
"aead_decrypt",
|
|
||||||
entry.stored_size,
|
|
||||||
written,
|
|
||||||
static_cast<std::uint64_t>(std::chrono::duration_cast<std::chrono::microseconds>(
|
|
||||||
std::chrono::steady_clock::now() - decryptStart).count()));
|
|
||||||
}
|
|
||||||
else if (m_header.version == M2PACK_VERSION_STREAM)
|
|
||||||
{
|
|
||||||
if (!decrypted.empty())
|
|
||||||
{
|
|
||||||
crypto_stream_xchacha20_xor(
|
|
||||||
decrypted.data(),
|
|
||||||
ciphertext,
|
|
||||||
entry.stored_size,
|
|
||||||
entry.nonce.data(),
|
|
||||||
GetM2PackActiveMasterKey().data());
|
|
||||||
}
|
|
||||||
RecordPackProfileStage(
|
|
||||||
"m2p",
|
|
||||||
"stream_decrypt",
|
|
||||||
entry.stored_size,
|
|
||||||
written,
|
|
||||||
static_cast<std::uint64_t>(std::chrono::duration_cast<std::chrono::microseconds>(
|
|
||||||
std::chrono::steady_clock::now() - decryptStart).count()));
|
|
||||||
|
|
||||||
if (!VerifyM2PackHash("payload_hash", decrypted.data(), decrypted.size(), entry.payload_hash, entry.path.c_str()))
|
|
||||||
{
|
|
||||||
if (pPool)
|
|
||||||
{
|
|
||||||
pPool->Release(std::move(decrypted));
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
if (pPool)
|
if (pPool)
|
||||||
{
|
{
|
||||||
@@ -363,8 +249,15 @@ bool CM2Pack::DecryptEntryPayload(const TM2PackEntry& entry, std::vector<uint8_t
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
RecordPackProfileStage(
|
||||||
|
"m2p",
|
||||||
|
"aead_decrypt",
|
||||||
|
entry.stored_size,
|
||||||
|
written,
|
||||||
|
static_cast<std::uint64_t>(std::chrono::duration_cast<std::chrono::microseconds>(
|
||||||
|
std::chrono::steady_clock::now() - decryptStart).count()));
|
||||||
|
|
||||||
decrypted.resize(written);
|
decrypted.resize(static_cast<std::size_t>(written));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -422,12 +315,32 @@ bool CM2Pack::GetFileWithPool(const TM2PackEntry& entry, std::vector<uint8_t>& r
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ShouldVerifyM2PackPlaintextHash())
|
if (!ShouldVerifyM2PackPlaintextHash())
|
||||||
{
|
{
|
||||||
if (!VerifyM2PackHash("plaintext_hash", result.data(), result.size(), entry.plaintext_hash, entry.path.c_str()))
|
return true;
|
||||||
{
|
}
|
||||||
return false;
|
|
||||||
}
|
std::array<uint8_t, M2PACK_HASH_SIZE> plain_hash {};
|
||||||
|
const auto hashStart = std::chrono::steady_clock::now();
|
||||||
|
crypto_generichash(
|
||||||
|
plain_hash.data(),
|
||||||
|
plain_hash.size(),
|
||||||
|
result.data(),
|
||||||
|
result.size(),
|
||||||
|
nullptr,
|
||||||
|
0);
|
||||||
|
RecordPackProfileStage(
|
||||||
|
"m2p",
|
||||||
|
"plaintext_hash",
|
||||||
|
result.size(),
|
||||||
|
plain_hash.size(),
|
||||||
|
static_cast<std::uint64_t>(std::chrono::duration_cast<std::chrono::microseconds>(
|
||||||
|
std::chrono::steady_clock::now() - hashStart).count()));
|
||||||
|
|
||||||
|
if (memcmp(plain_hash.data(), entry.plaintext_hash.data(), plain_hash.size()) != 0)
|
||||||
|
{
|
||||||
|
TraceError("CM2Pack::GetFileWithPool: plaintext hash mismatch for '%s'", entry.path.c_str());
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -19,8 +19,6 @@ constexpr std::size_t M2PACK_SIGNATURE_SIZE = 64;
|
|||||||
constexpr std::size_t M2PACK_KEY_SIZE = crypto_aead_xchacha20poly1305_ietf_KEYBYTES;
|
constexpr std::size_t M2PACK_KEY_SIZE = crypto_aead_xchacha20poly1305_ietf_KEYBYTES;
|
||||||
constexpr std::size_t M2PACK_NONCE_SIZE = crypto_aead_xchacha20poly1305_ietf_NPUBBYTES;
|
constexpr std::size_t M2PACK_NONCE_SIZE = crypto_aead_xchacha20poly1305_ietf_NPUBBYTES;
|
||||||
constexpr std::size_t M2PACK_PUBLIC_KEY_SIZE = crypto_sign_PUBLICKEYBYTES;
|
constexpr std::size_t M2PACK_PUBLIC_KEY_SIZE = crypto_sign_PUBLICKEYBYTES;
|
||||||
constexpr uint32_t M2PACK_VERSION_AEAD = 1;
|
|
||||||
constexpr uint32_t M2PACK_VERSION_STREAM = 2;
|
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
struct TM2PackHeader
|
struct TM2PackHeader
|
||||||
@@ -53,19 +51,6 @@ struct TM2PackManifestEntryFixed
|
|||||||
uint8_t nonce[M2PACK_NONCE_SIZE];
|
uint8_t nonce[M2PACK_NONCE_SIZE];
|
||||||
uint8_t plaintext_hash[M2PACK_HASH_SIZE];
|
uint8_t plaintext_hash[M2PACK_HASH_SIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TM2PackManifestEntryFixedV2
|
|
||||||
{
|
|
||||||
uint16_t path_size;
|
|
||||||
uint8_t compression;
|
|
||||||
uint8_t flags;
|
|
||||||
uint64_t data_offset;
|
|
||||||
uint64_t original_size;
|
|
||||||
uint64_t stored_size;
|
|
||||||
uint8_t nonce[M2PACK_NONCE_SIZE];
|
|
||||||
uint8_t payload_hash[M2PACK_HASH_SIZE];
|
|
||||||
uint8_t plaintext_hash[M2PACK_HASH_SIZE];
|
|
||||||
};
|
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
struct TM2PackEntry
|
struct TM2PackEntry
|
||||||
@@ -76,7 +61,6 @@ struct TM2PackEntry
|
|||||||
uint64_t original_size = 0;
|
uint64_t original_size = 0;
|
||||||
uint64_t stored_size = 0;
|
uint64_t stored_size = 0;
|
||||||
std::array<uint8_t, M2PACK_NONCE_SIZE> nonce {};
|
std::array<uint8_t, M2PACK_NONCE_SIZE> nonce {};
|
||||||
std::array<uint8_t, M2PACK_HASH_SIZE> payload_hash {};
|
|
||||||
std::array<uint8_t, M2PACK_HASH_SIZE> plaintext_hash {};
|
std::array<uint8_t, M2PACK_HASH_SIZE> plaintext_hash {};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user