Add secure m2p loader with runtime key enforcement
Some checks failed
build / Windows Build (push) Has been cancelled

This commit is contained in:
server
2026-04-14 12:12:23 +02:00
parent 0c2d6c7c9c
commit 229c809b96
8 changed files with 719 additions and 6 deletions

92
src/PackLib/M2Pack.h Normal file
View File

@@ -0,0 +1,92 @@
#pragma once
#include <array>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
#include <mio/mmap.hpp>
#include <sodium.h>
class CBufferPool;
constexpr std::size_t M2PACK_MAGIC_SIZE = 8;
constexpr std::size_t M2PACK_HASH_SIZE = 32;
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_NONCE_SIZE = crypto_aead_xchacha20poly1305_ietf_NPUBBYTES;
constexpr std::size_t M2PACK_PUBLIC_KEY_SIZE = crypto_sign_PUBLICKEYBYTES;
#pragma pack(push, 1)
struct TM2PackHeader
{
char magic[M2PACK_MAGIC_SIZE];
uint32_t version;
uint32_t flags;
uint64_t manifest_offset;
uint64_t manifest_size;
uint8_t manifest_hash[M2PACK_HASH_SIZE];
uint8_t manifest_signature[M2PACK_SIGNATURE_SIZE];
uint8_t reserved[64];
};
struct TM2PackManifestHeader
{
uint32_t entry_count;
uint32_t flags;
};
struct TM2PackManifestEntryFixed
{
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 plaintext_hash[M2PACK_HASH_SIZE];
};
#pragma pack(pop)
struct TM2PackEntry
{
std::string path;
uint8_t compression = 0;
uint64_t data_offset = 0;
uint64_t original_size = 0;
uint64_t stored_size = 0;
std::array<uint8_t, M2PACK_NONCE_SIZE> nonce {};
std::array<uint8_t, M2PACK_HASH_SIZE> plaintext_hash {};
};
class CM2Pack : public std::enable_shared_from_this<CM2Pack>
{
public:
CM2Pack() = default;
~CM2Pack() = default;
bool Load(const std::string& path);
const std::vector<TM2PackEntry>& GetIndex() const { return m_index; }
bool GetFile(const TM2PackEntry& entry, std::vector<uint8_t>& result);
bool GetFileWithPool(const TM2PackEntry& entry, std::vector<uint8_t>& result, CBufferPool* pPool);
private:
bool ValidateManifest();
bool DecryptEntryPayload(const TM2PackEntry& entry, std::vector<uint8_t>& decrypted, CBufferPool* pPool);
private:
TM2PackHeader m_header {};
std::vector<uint8_t> m_manifest_bytes;
std::vector<TM2PackEntry> m_index;
mio::mmap_source m_file;
};
using TM2PackFileMapEntry = std::pair<std::shared_ptr<CM2Pack>, TM2PackEntry>;
using TM2PackFileMap = std::unordered_map<std::string, TM2PackFileMapEntry>;
#include "M2PackKeys.h"