libcryfs/src/blockstore/implementations/integrity/IntegrityBlockStore2.h

80 lines
3.7 KiB
C++

#pragma once
#ifndef MESSMER_BLOCKSTORE_IMPLEMENTATIONS_INTEGRITY_INTEGRITYBLOCKSTORE2_H_
#define MESSMER_BLOCKSTORE_IMPLEMENTATIONS_INTEGRITY_INTEGRITYBLOCKSTORE2_H_
#include "../../interface/BlockStore2.h"
#include <cpp-utils/macros.h>
#include "KnownBlockVersions.h"
#include "IntegrityViolationError.h"
namespace blockstore {
namespace integrity {
//TODO Format version headers
// This blockstore implements integrity measures.
// It depends on being used on top of an encrypted block store that protects integrity of the block contents (i.e. uses an authenticated cipher).
class IntegrityBlockStore2 final: public BlockStore2 {
public:
IntegrityBlockStore2(cpputils::unique_ref<BlockStore2> baseBlockStore, const boost::filesystem::path &integrityFilePath, uint32_t myClientId, bool allowIntegrityViolations, bool missingBlockIsIntegrityViolation);
bool tryCreate(const BlockId &blockId, const cpputils::Data &data) override;
bool remove(const BlockId &blockId) override;
boost::optional<cpputils::Data> load(const BlockId &blockId) const override;
void store(const BlockId &blockId, const cpputils::Data &data) override;
uint64_t numBlocks() const override;
uint64_t estimateNumFreeBytes() const override;
uint64_t blockSizeFromPhysicalBlockSize(uint64_t blockSize) const override;
void forEachBlock(std::function<void (const BlockId &)> callback) const override;
private:
// This format version is prepended to blocks to allow future versions to have compatibility.
#ifndef CRYFS_NO_COMPATIBILITY
static constexpr uint16_t FORMAT_VERSION_HEADER_OLD = 0;
#endif
static constexpr uint16_t FORMAT_VERSION_HEADER = 1;
public:
static constexpr uint64_t VERSION_ZERO = 0;
static constexpr unsigned int ID_HEADER_OFFSET = sizeof(FORMAT_VERSION_HEADER);
static constexpr unsigned int CLIENTID_HEADER_OFFSET = ID_HEADER_OFFSET + BlockId::BINARY_LENGTH;
static constexpr unsigned int VERSION_HEADER_OFFSET = CLIENTID_HEADER_OFFSET + sizeof(uint32_t);
static constexpr unsigned int HEADER_LENGTH = VERSION_HEADER_OFFSET + sizeof(VERSION_ZERO);
#ifndef CRYFS_NO_COMPATIBILITY
static void migrateFromBlockstoreWithoutVersionNumbers(BlockStore2 *baseBlockStore, const boost::filesystem::path &integrityFilePath, uint32_t myClientId);
static void migrateBlockFromBlockstoreWithoutVersionNumbers(BlockStore2* baseBlockStore, const blockstore::BlockId &blockId, KnownBlockVersions *knownBlockVersions);
#endif
private:
static cpputils::Data _prependHeaderToData(const BlockId &blockId, uint32_t myClientId, uint64_t version, const cpputils::Data &data);
void _checkHeader(const BlockId &blockId, const cpputils::Data &data) const;
void _checkFormatHeader(const cpputils::Data &data) const;
void _checkIdHeader(const BlockId &expectedBlockId, const cpputils::Data &data) const;
void _checkVersionHeader(const BlockId &blockId, const cpputils::Data &data) const;
static uint16_t _readFormatHeader(const cpputils::Data &data);
static uint32_t _readClientId(const cpputils::Data &data);
static BlockId _readBlockId(const cpputils::Data &data);
static uint64_t _readVersion(const cpputils::Data &data);
#ifndef CRYFS_NO_COMPATIBILITY
static cpputils::Data _migrateBlock(const BlockId &blockId, const cpputils::Data &data);
#endif
static cpputils::Data _removeHeader(const cpputils::Data &data);
void _checkNoPastIntegrityViolations() const;
void integrityViolationDetected(const std::string &reason) const;
cpputils::unique_ref<BlockStore2> _baseBlockStore;
mutable KnownBlockVersions _knownBlockVersions;
const bool _allowIntegrityViolations;
const bool _missingBlockIsIntegrityViolation;
mutable bool _integrityViolationDetected;
DISALLOW_COPY_AND_ASSIGN(IntegrityBlockStore2);
};
}
}
#endif