From 00d098952b9fc2e5ba402a3b92b58ecb0b8f199e Mon Sep 17 00:00:00 2001 From: Sebastian Messmer Date: Sat, 16 Sep 2017 00:09:15 +0100 Subject: [PATCH] Storing block ID is job of VersionCountingBlockStore, not EncryptedBlockStore. --- .../encrypted/EncryptedBlockStore2.h | 89 +++++++++++-------- .../VersionCountingBlockStore2.cpp | 55 ++++++++++-- .../VersionCountingBlockStore2.h | 24 +++-- .../EncryptedBlockStoreTest_Specific.cpp | 14 --- ...VersionCountingBlockStoreTest_Specific.cpp | 10 +++ .../testutils/FakeAuthenticatedCipher.h | 24 ++--- 6 files changed, 140 insertions(+), 76 deletions(-) diff --git a/src/blockstore/implementations/encrypted/EncryptedBlockStore2.h b/src/blockstore/implementations/encrypted/EncryptedBlockStore2.h index 4960b5c3..8e7e0cbe 100644 --- a/src/blockstore/implementations/encrypted/EncryptedBlockStore2.h +++ b/src/blockstore/implementations/encrypted/EncryptedBlockStore2.h @@ -34,17 +34,21 @@ public: private: // This header is prepended to blocks to allow future versions to have compatibility. - static constexpr uint16_t FORMAT_VERSION_HEADER = 0; - static constexpr unsigned int HEADER_LENGTH = Key::BINARY_LENGTH; +#ifndef CRYFS_NO_COMPATIBILITY + static constexpr uint16_t FORMAT_VERSION_HEADER_OLD = 0; +#endif + static constexpr uint16_t FORMAT_VERSION_HEADER = 1; - cpputils::Data _encrypt(const Key &key, const cpputils::Data &data) const; + cpputils::Data _encrypt(const cpputils::Data &data) const; boost::optional _tryDecrypt(const Key &key, const cpputils::Data &data) const; - static cpputils::Data _prependKeyHeaderToData(const Key &key, const cpputils::Data &data); - static bool _keyHeaderIsCorrect(const Key &key, const cpputils::Data &data); static cpputils::Data _prependFormatHeaderToData(const cpputils::Data &data); - static cpputils::Data _removeKeyHeader(const cpputils::Data &data); - static cpputils::Data _checkAndRemoveFormatHeader(const cpputils::Data &data); +#ifndef CRYFS_NO_COMPATIBILITY + static bool _keyHeaderIsCorrect(const Key &key, const cpputils::Data &data); + static cpputils::Data _migrateBlock(const cpputils::Data &data); +#endif + static void _checkFormatHeader(const cpputils::Data &data); + static uint16_t _readFormatHeader(const cpputils::Data &data); cpputils::unique_ref _baseBlockStore; typename Cipher::EncryptionKey _encKey; @@ -52,11 +56,13 @@ private: DISALLOW_COPY_AND_ASSIGN(EncryptedBlockStore2); }; +#ifndef CRYFS_NO_COMPATIBILITY template -constexpr uint16_t EncryptedBlockStore2::FORMAT_VERSION_HEADER; +constexpr uint16_t EncryptedBlockStore2::FORMAT_VERSION_HEADER_OLD; +#endif template -constexpr unsigned int EncryptedBlockStore2::HEADER_LENGTH; +constexpr uint16_t EncryptedBlockStore2::FORMAT_VERSION_HEADER; template inline EncryptedBlockStore2::EncryptedBlockStore2(cpputils::unique_ref baseBlockStore, const typename Cipher::EncryptionKey &encKey) @@ -65,7 +71,7 @@ inline EncryptedBlockStore2::EncryptedBlockStore2(cpputils::unique_ref inline bool EncryptedBlockStore2::tryCreate(const Key &key, const cpputils::Data &data) { - cpputils::Data encrypted = _encrypt(key, data); + cpputils::Data encrypted = _encrypt(data); return _baseBlockStore->tryCreate(key, encrypted); } @@ -86,7 +92,7 @@ inline boost::optional EncryptedBlockStore2::load(const template inline void EncryptedBlockStore2::store(const Key &key, const cpputils::Data &data) { - cpputils::Data encrypted = _encrypt(key, data); + cpputils::Data encrypted = _encrypt(data); return _baseBlockStore->store(key, encrypted); } @@ -103,10 +109,10 @@ inline uint64_t EncryptedBlockStore2::estimateNumFreeBytes() const { template inline uint64_t EncryptedBlockStore2::blockSizeFromPhysicalBlockSize(uint64_t blockSize) const { uint64_t baseBlockSize = _baseBlockStore->blockSizeFromPhysicalBlockSize(blockSize); - if (baseBlockSize <= Cipher::ciphertextSize(HEADER_LENGTH) + sizeof(FORMAT_VERSION_HEADER)) { + if (baseBlockSize <= Cipher::ciphertextSize(0) + sizeof(FORMAT_VERSION_HEADER)) { return 0; } - return Cipher::plaintextSize(baseBlockSize - sizeof(FORMAT_VERSION_HEADER)) - HEADER_LENGTH; + return Cipher::plaintextSize(baseBlockSize - sizeof(FORMAT_VERSION_HEADER)); } template @@ -115,39 +121,45 @@ inline void EncryptedBlockStore2::forEachBlock(std::function -inline cpputils::Data EncryptedBlockStore2::_encrypt(const Key &key, const cpputils::Data &data) const { - cpputils::Data plaintextWithHeader = _prependKeyHeaderToData(key, data); - cpputils::Data encrypted = Cipher::encrypt((CryptoPP::byte*)plaintextWithHeader.data(), plaintextWithHeader.size(), _encKey); +inline cpputils::Data EncryptedBlockStore2::_encrypt(const cpputils::Data &data) const { + cpputils::Data encrypted = Cipher::encrypt((CryptoPP::byte*)data.data(), data.size(), _encKey); return _prependFormatHeaderToData(encrypted); } template inline boost::optional EncryptedBlockStore2::_tryDecrypt(const Key &key, const cpputils::Data &data) const { - auto ciphertext = _checkAndRemoveFormatHeader(data); - boost::optional decrypted = Cipher::decrypt((CryptoPP::byte*)ciphertext.data(), ciphertext.size(), _encKey); - if (boost::none == decrypted) { - // TODO Warning + _checkFormatHeader(data); + boost::optional decrypted = Cipher::decrypt((CryptoPP::byte*)data.dataOffset(sizeof(FORMAT_VERSION_HEADER)), data.size() - sizeof(FORMAT_VERSION_HEADER), _encKey); + if (decrypted == boost::none) { + // TODO Log warning return boost::none; } - if (!_keyHeaderIsCorrect(key, *decrypted)) { - // TODO Warning - return boost::none; + +#ifndef CRYFS_NO_COMPATIBILITY + if (FORMAT_VERSION_HEADER_OLD == _readFormatHeader(data)) { + if (!_keyHeaderIsCorrect(key, *decrypted)) { + return boost::none; + } + *decrypted = _migrateBlock(*decrypted); + // no need to write migrated back to block store because + // this migration happens in line with a migration in VersionCountingBlockStore2 + // which then writes it back } - return _removeKeyHeader(*decrypted); +#endif + return decrypted; } +#ifndef CRYFS_NO_COMPATIBILITY template -inline cpputils::Data EncryptedBlockStore2::_prependKeyHeaderToData(const Key &key, const cpputils::Data &data) { - cpputils::Data result(data.size() + Key::BINARY_LENGTH); - std::memcpy(result.data(), key.data(), Key::BINARY_LENGTH); - std::memcpy((uint8_t*)result.data() + Key::BINARY_LENGTH, data.data(), data.size()); - return result; +inline cpputils::Data EncryptedBlockStore2::_migrateBlock(const cpputils::Data &data) { + return data.copyAndRemovePrefix(Key::BINARY_LENGTH); } template inline bool EncryptedBlockStore2::_keyHeaderIsCorrect(const Key &key, const cpputils::Data &data) { return 0 == std::memcmp(key.data(), data.data(), Key::BINARY_LENGTH); } +#endif template inline cpputils::Data EncryptedBlockStore2::_prependFormatHeaderToData(const cpputils::Data &data) { @@ -158,16 +170,21 @@ inline cpputils::Data EncryptedBlockStore2::_prependFormatHeaderToData(c } template -inline cpputils::Data EncryptedBlockStore2::_removeKeyHeader(const cpputils::Data &data) { - return data.copyAndRemovePrefix(Key::BINARY_LENGTH); +inline void EncryptedBlockStore2::_checkFormatHeader(const cpputils::Data &data) { + const uint16_t formatVersionHeader = _readFormatHeader(data); +#ifndef CRYFS_NO_COMPATIBILITY + const bool formatVersionHeaderValid = formatVersionHeader == FORMAT_VERSION_HEADER || formatVersionHeader == FORMAT_VERSION_HEADER_OLD; +#else + const bool formatVersionHeaderValid = formatVersionHeader == FORMAT_VERSION_HEADER; +#endif + if (!formatVersionHeaderValid) { + throw std::runtime_error("The encrypted block has the wrong format. Was it created with a newer version of CryFS?"); + } } template -inline cpputils::Data EncryptedBlockStore2::_checkAndRemoveFormatHeader(const cpputils::Data &data) { - if (*reinterpret_cast(data.data()) != FORMAT_VERSION_HEADER) { - throw std::runtime_error("The encrypted block has the wrong format. Was it created with a newer version of CryFS?"); - } - return data.copyAndRemovePrefix(sizeof(FORMAT_VERSION_HEADER)); +uint16_t EncryptedBlockStore2::_readFormatHeader(const cpputils::Data &data) { + return *reinterpret_cast(data.data()); } template diff --git a/src/blockstore/implementations/versioncounting/VersionCountingBlockStore2.cpp b/src/blockstore/implementations/versioncounting/VersionCountingBlockStore2.cpp index 182f9b23..5aeb57df 100644 --- a/src/blockstore/implementations/versioncounting/VersionCountingBlockStore2.cpp +++ b/src/blockstore/implementations/versioncounting/VersionCountingBlockStore2.cpp @@ -12,16 +12,21 @@ using namespace cpputils::logging; namespace blockstore { namespace versioncounting { +#ifndef CRYFS_NO_COMPATIBILITY +constexpr uint16_t VersionCountingBlockStore2::FORMAT_VERSION_HEADER_OLD; +#endif constexpr uint16_t VersionCountingBlockStore2::FORMAT_VERSION_HEADER; constexpr uint64_t VersionCountingBlockStore2::VERSION_ZERO; +constexpr unsigned int VersionCountingBlockStore2::ID_HEADER_OFFSET; constexpr unsigned int VersionCountingBlockStore2::CLIENTID_HEADER_OFFSET; constexpr unsigned int VersionCountingBlockStore2::VERSION_HEADER_OFFSET; constexpr unsigned int VersionCountingBlockStore2::HEADER_LENGTH; -Data VersionCountingBlockStore2::_prependHeaderToData(uint32_t myClientId, uint64_t version, const Data &data) { - static_assert(HEADER_LENGTH == sizeof(FORMAT_VERSION_HEADER) + sizeof(myClientId) + sizeof(version), "Wrong header length"); +Data VersionCountingBlockStore2::_prependHeaderToData(const Key& key, uint32_t myClientId, uint64_t version, const Data &data) { + static_assert(HEADER_LENGTH == sizeof(FORMAT_VERSION_HEADER) + Key::BINARY_LENGTH + sizeof(myClientId) + sizeof(version), "Wrong header length"); Data result(data.size() + HEADER_LENGTH); std::memcpy(result.dataOffset(0), &FORMAT_VERSION_HEADER, sizeof(FORMAT_VERSION_HEADER)); + std::memcpy(result.dataOffset(ID_HEADER_OFFSET), key.data(), Key::BINARY_LENGTH); std::memcpy(result.dataOffset(CLIENTID_HEADER_OFFSET), &myClientId, sizeof(myClientId)); std::memcpy(result.dataOffset(VERSION_HEADER_OFFSET), &version, sizeof(version)); std::memcpy((uint8_t*)result.dataOffset(HEADER_LENGTH), data.data(), data.size()); @@ -30,11 +35,12 @@ Data VersionCountingBlockStore2::_prependHeaderToData(uint32_t myClientId, uint6 void VersionCountingBlockStore2::_checkHeader(const Key &key, const Data &data) const { _checkFormatHeader(data); + _checkIdHeader(key, data); _checkVersionHeader(key, data); } void VersionCountingBlockStore2::_checkFormatHeader(const Data &data) const { - if (*reinterpret_cast(data.data()) != FORMAT_VERSION_HEADER) { + if (FORMAT_VERSION_HEADER != _readFormatHeader(data)) { throw std::runtime_error("The versioned block has the wrong format. Was it created with a newer version of CryFS?"); } } @@ -48,19 +54,34 @@ void VersionCountingBlockStore2::_checkVersionHeader(const Key &key, const Data } } +void VersionCountingBlockStore2::_checkIdHeader(const Key &expectedKey, const Data &data) const { + Key actualKey = _readBlockId(data); + if (expectedKey != actualKey) { + integrityViolationDetected("The block key is wrong. Did an attacker try to rename some blocks?"); + } +} + +uint16_t VersionCountingBlockStore2::_readFormatHeader(const Data &data) { + return *reinterpret_cast(data.data()); +} + uint32_t VersionCountingBlockStore2::_readClientId(const Data &data) { uint32_t clientId; std::memcpy(&clientId, data.dataOffset(CLIENTID_HEADER_OFFSET), sizeof(clientId)); return clientId; } +Key VersionCountingBlockStore2::_readBlockId(const Data &data) { + return Key::FromBinary(data.dataOffset(ID_HEADER_OFFSET)); +} + uint64_t VersionCountingBlockStore2::_readVersion(const Data &data) { uint64_t version; std::memcpy(&version, data.dataOffset(VERSION_HEADER_OFFSET), sizeof(version)); return version; } -Data VersionCountingBlockStore2::_removeHeader(const Data &data) const { +Data VersionCountingBlockStore2::_removeHeader(const Data &data) { return data.copyAndRemovePrefix(HEADER_LENGTH); } @@ -86,7 +107,7 @@ VersionCountingBlockStore2::VersionCountingBlockStore2(unique_ref b bool VersionCountingBlockStore2::tryCreate(const Key &key, const Data &data) { _checkNoPastIntegrityViolations(); uint64_t version = _knownBlockVersions.incrementVersion(key); - Data dataWithHeader = _prependHeaderToData(_knownBlockVersions.myClientId(), version, data); + Data dataWithHeader = _prependHeaderToData(key, _knownBlockVersions.myClientId(), version, data); return _baseBlockStore->tryCreate(key, dataWithHeader); } @@ -105,14 +126,34 @@ optional VersionCountingBlockStore2::load(const Key &key) const { } return optional(none); } +#ifndef CRYFS_NO_COMPATIBILITY + if (FORMAT_VERSION_HEADER_OLD == _readFormatHeader(*loaded)) { + Data migrated = _migrateBlock(key, *loaded); + _checkHeader(key, migrated); + Data content = _removeHeader(migrated); + const_cast(this)->store(key, content); + return optional(_removeHeader(migrated)); + } +#endif _checkHeader(key, *loaded); return optional(_removeHeader(*loaded)); } +#ifndef CRYFS_NO_COMPATIBILITY +Data VersionCountingBlockStore2::_migrateBlock(const Key &key, const Data &data) { + Data migrated(data.size() + Key::BINARY_LENGTH); + std::memcpy(migrated.dataOffset(0), &FORMAT_VERSION_HEADER, sizeof(FORMAT_VERSION_HEADER)); + std::memcpy(migrated.dataOffset(ID_HEADER_OFFSET), key.data(), Key::BINARY_LENGTH); + std::memcpy(migrated.dataOffset(ID_HEADER_OFFSET + Key::BINARY_LENGTH), data.dataOffset(sizeof(FORMAT_VERSION_HEADER)), data.size() - sizeof(FORMAT_VERSION_HEADER)); + ASSERT(migrated.size() == sizeof(FORMAT_VERSION_HEADER) + Key::BINARY_LENGTH + (data.size() - sizeof(FORMAT_VERSION_HEADER)), "Wrong offset computation"); + return migrated; +} +#endif + void VersionCountingBlockStore2::store(const Key &key, const Data &data) { _checkNoPastIntegrityViolations(); uint64_t version = _knownBlockVersions.incrementVersion(key); - Data dataWithHeader = _prependHeaderToData(_knownBlockVersions.myClientId(), version, data); + Data dataWithHeader = _prependHeaderToData(key, _knownBlockVersions.myClientId(), version, data); return _baseBlockStore->store(key, dataWithHeader); } @@ -170,7 +211,7 @@ void VersionCountingBlockStore2::migrateBlockFromBlockstoreWithoutVersionNumbers return; } cpputils::Data data = std::move(*data_); - cpputils::Data dataWithHeader = _prependHeaderToData(knownBlockVersions->myClientId(), version, std::move(data)); + cpputils::Data dataWithHeader = _prependHeaderToData(key, knownBlockVersions->myClientId(), version, std::move(data)); baseBlockStore->store(key, std::move(dataWithHeader)); } #endif diff --git a/src/blockstore/implementations/versioncounting/VersionCountingBlockStore2.h b/src/blockstore/implementations/versioncounting/VersionCountingBlockStore2.h index 408f3a06..b94547e8 100644 --- a/src/blockstore/implementations/versioncounting/VersionCountingBlockStore2.h +++ b/src/blockstore/implementations/versioncounting/VersionCountingBlockStore2.h @@ -26,14 +26,18 @@ public: void forEachBlock(std::function callback) const override; private: - // This header is prepended to blocks to allow future versions to have compatibility. - static constexpr uint16_t FORMAT_VERSION_HEADER = 0; + // 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 CLIENTID_HEADER_OFFSET = sizeof(FORMAT_VERSION_HEADER); - static constexpr unsigned int VERSION_HEADER_OFFSET = sizeof(FORMAT_VERSION_HEADER) + sizeof(uint32_t); - static constexpr unsigned int HEADER_LENGTH = sizeof(FORMAT_VERSION_HEADER) + sizeof(uint32_t) + sizeof(VERSION_ZERO); + static constexpr unsigned int ID_HEADER_OFFSET = sizeof(FORMAT_VERSION_HEADER); + static constexpr unsigned int CLIENTID_HEADER_OFFSET = ID_HEADER_OFFSET + Key::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); @@ -42,13 +46,19 @@ public: private: - static cpputils::Data _prependHeaderToData(uint32_t myClientId, uint64_t version, const cpputils::Data &data); + static cpputils::Data _prependHeaderToData(const Key& key, uint32_t myClientId, uint64_t version, const cpputils::Data &data); void _checkHeader(const Key &key, const cpputils::Data &data) const; void _checkFormatHeader(const cpputils::Data &data) const; + void _checkIdHeader(const Key &expectedKey, const cpputils::Data &data) const; void _checkVersionHeader(const Key &key, const cpputils::Data &data) const; + static uint16_t _readFormatHeader(const cpputils::Data &data); static uint32_t _readClientId(const cpputils::Data &data); + static Key _readBlockId(const cpputils::Data &data); static uint64_t _readVersion(const cpputils::Data &data); - cpputils::Data _removeHeader(const cpputils::Data &data) const; +#ifndef CRYFS_NO_COMPATIBILITY + static cpputils::Data _migrateBlock(const Key &key, const cpputils::Data &data); +#endif + static cpputils::Data _removeHeader(const cpputils::Data &data); void _checkNoPastIntegrityViolations() const; void integrityViolationDetected(const std::string &reason) const; diff --git a/test/blockstore/implementations/encrypted/EncryptedBlockStoreTest_Specific.cpp b/test/blockstore/implementations/encrypted/EncryptedBlockStoreTest_Specific.cpp index a912aa9b..25beeb99 100644 --- a/test/blockstore/implementations/encrypted/EncryptedBlockStoreTest_Specific.cpp +++ b/test/blockstore/implementations/encrypted/EncryptedBlockStoreTest_Specific.cpp @@ -105,20 +105,6 @@ TEST_F(EncryptedBlockStoreTest, LoadingModifiedBlockFails_WriteSeparately) { EXPECT_EQ(boost::none, loaded); } -TEST_F(EncryptedBlockStoreTest, LoadingWithDifferentBlockIdFails_WriteOnCreate) { - auto key = CreateBlockDirectlyWithFixtureAndReturnKey(); - auto key2 = CopyBaseBlock(key); - auto loaded = blockStore->load(key2); - EXPECT_EQ(boost::none, loaded); -} - -TEST_F(EncryptedBlockStoreTest, LoadingWithDifferentBlockIdFails_WriteSeparately) { - auto key = CreateBlockWriteFixtureToItAndReturnKey(); - auto key2 = CopyBaseBlock(key); - auto loaded = blockStore->load(key2); - EXPECT_EQ(boost::none, loaded); -} - TEST_F(EncryptedBlockStoreTest, PhysicalBlockSize_zerophysical) { EXPECT_EQ(0u, blockStore->blockSizeFromPhysicalBlockSize(0)); } diff --git a/test/blockstore/implementations/versioncounting/VersionCountingBlockStoreTest_Specific.cpp b/test/blockstore/implementations/versioncounting/VersionCountingBlockStoreTest_Specific.cpp index d66ac28a..e05d2048 100644 --- a/test/blockstore/implementations/versioncounting/VersionCountingBlockStoreTest_Specific.cpp +++ b/test/blockstore/implementations/versioncounting/VersionCountingBlockStoreTest_Specific.cpp @@ -235,6 +235,16 @@ TEST_F(VersionCountingBlockStoreTest, DeletionPrevention_InForEachBlock_DoesntAl ); } +TEST_F(VersionCountingBlockStoreTest, LoadingWithDifferentBlockIdFails) { + auto key = CreateBlockReturnKey(); + blockstore::Key key2 = blockstore::Key::FromString("1491BB4932A389EE14BC7090AC772972"); + baseBlockStore->store(key2, baseBlockStore->load(key).value()); + EXPECT_THROW( + blockStore->load(key2), + IntegrityViolationError + ); +} + // TODO Test more integrity cases: // - RollbackPrevention_DoesntAllowReintroducingDeletedBlocks with different client id (i.e. trying to re-introduce the newest block of a different client) // - RollbackPrevention_AllowsReintroducingDeletedBlocksWithNewVersionNumber with different client id diff --git a/test/cpp-utils/crypto/symmetric/testutils/FakeAuthenticatedCipher.h b/test/cpp-utils/crypto/symmetric/testutils/FakeAuthenticatedCipher.h index 7b10c008..f8c2a41b 100644 --- a/test/cpp-utils/crypto/symmetric/testutils/FakeAuthenticatedCipher.h +++ b/test/cpp-utils/crypto/symmetric/testutils/FakeAuthenticatedCipher.h @@ -25,7 +25,7 @@ namespace cpputils { uint8_t value; }; - // This is a fake cipher that uses an indeterministic caesar chiffre and a 4-byte parity for a simple authentication mechanism + // This is a fake cipher that uses an indeterministic caesar chiffre and a 4-byte checksum for a simple authentication mechanism class FakeAuthenticatedCipher { public: BOOST_CONCEPT_ASSERT((CipherConcept)); @@ -58,22 +58,22 @@ namespace cpputils { //Use caesar chiffre on plaintext _caesar((CryptoPP::byte *) result.data() + 1, plaintext, plaintextSize, encKey.value + iv); - //Add parity information - int32_t parity = _parity((CryptoPP::byte *) result.data(), plaintextSize + 1); - std::memcpy((CryptoPP::byte *) result.data() + plaintextSize + 1, &parity, 4); + //Add checksum information + int32_t checksum = _checksum((CryptoPP::byte *) result.data(), encKey, plaintextSize + 1); + std::memcpy((CryptoPP::byte *) result.data() + plaintextSize + 1, &checksum, 4); return result; } static boost::optional decrypt(const CryptoPP::byte *ciphertext, unsigned int ciphertextSize, const EncryptionKey &encKey) { - //We need at least 5 bytes (iv + parity) + //We need at least 5 bytes (iv + checksum) if (ciphertextSize < 5) { return boost::none; } - //Check parity - int32_t expectedParity = _parity(ciphertext, plaintextSize(ciphertextSize) + 1); + //Check checksum + int32_t expectedParity = _checksum(ciphertext, encKey, plaintextSize(ciphertextSize) + 1); int32_t actualParity = *(int32_t * )(ciphertext + plaintextSize(ciphertextSize) + 1); if (expectedParity != actualParity) { return boost::none; @@ -89,18 +89,18 @@ namespace cpputils { static constexpr const char *NAME = "FakeAuthenticatedCipher"; private: - static int32_t _parity(const CryptoPP::byte *data, unsigned int size) { - int32_t parity = 34343435; // some init value + static int32_t _checksum(const CryptoPP::byte *data, FakeKey encKey, unsigned int size) { + int32_t checksum = 34343435 * encKey.value; // some init value const int32_t *intData = reinterpret_cast(data); unsigned int intSize = size / sizeof(int32_t); for (unsigned int i = 0; i < intSize; ++i) { - parity = ((int64_t)parity) + intData[i]; + checksum = ((int64_t)checksum) + intData[i]; } unsigned int remainingBytes = size - 4 * intSize; for (unsigned int i = 0; i < remainingBytes; ++i) { - parity = ((int64_t)parity) + (data[4 * intSize + i] << (24 - 8 * i)); + checksum = ((int64_t)checksum) + (data[4 * intSize + i] << (24 - 8 * i)); } - return parity; + return checksum; } static void _caesar(CryptoPP::byte *dst, const CryptoPP::byte *src, unsigned int size, uint8_t key) {