Add secure m2p loader with runtime key enforcement
Some checks failed
build / Windows Build (push) Has been cancelled
Some checks failed
build / Windows Build (push) Has been cancelled
This commit is contained in:
92
src/PackLib/M2Pack.h
Normal file
92
src/PackLib/M2Pack.h
Normal 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"
|
||||
Reference in New Issue
Block a user