diff --git a/implementations/encrypted/ciphers/AES256_GCM.cpp b/implementations/encrypted/ciphers/AES256_GCM.cpp new file mode 100644 index 00000000..fd7b5788 --- /dev/null +++ b/implementations/encrypted/ciphers/AES256_GCM.cpp @@ -0,0 +1,49 @@ +#include +#include "AES256_GCM.h" + +using CryptoPP::GCM; +using CryptoPP::AES; +using CryptoPP::AuthenticatedEncryptionFilter; +using CryptoPP::AuthenticatedDecryptionFilter; +using CryptoPP::ArraySource; +using CryptoPP::ArraySink; +using CryptoPP::GCM_64K_Tables; + +namespace blockstore { +namespace encrypted { + +constexpr unsigned int AES256_GCM::IV_SIZE; + +Data AES256_GCM::encrypt(const byte *plaintext, unsigned int plaintextSize, const EncryptionKey &encKey) { + FixedSizeData iv = FixedSizeData::CreateRandom(); + GCM::Encryption encryption; + encryption.SetKeyWithIV(encKey.data(), encKey.BINARY_LENGTH, iv.data(), IV_SIZE); + Data ciphertext(ciphertextSize(plaintextSize)); + + std::memcpy(ciphertext.data(), iv.data(), IV_SIZE); + ArraySource(plaintext, plaintextSize, true, + new AuthenticatedEncryptionFilter(encryption, + new ArraySink((byte*)ciphertext.data() + IV_SIZE, ciphertext.size() - IV_SIZE), + false, TAG_SIZE + ) + ); + return ciphertext; +} + +boost::optional AES256_GCM::decrypt(const byte *ciphertext, unsigned int ciphertextSize, const EncryptionKey &encKey) { + const byte *ciphertextIV = ciphertext; + const byte *ciphertextData = ciphertext + IV_SIZE; + GCM::Decryption decryption; + decryption.SetKeyWithIV((byte*)encKey.data(), encKey.BINARY_LENGTH, ciphertextIV, IV_SIZE); + Data plaintext(plaintextSize(ciphertextSize)); + + ArraySource((byte*)ciphertextData, ciphertextSize - IV_SIZE, true, + new AuthenticatedDecryptionFilter(decryption, + new ArraySink((byte*)plaintext.data(), plaintext.size()) + ) + ); + return std::move(plaintext); +} + +} +} diff --git a/implementations/encrypted/ciphers/AES256_GCM.h b/implementations/encrypted/ciphers/AES256_GCM.h new file mode 100644 index 00000000..f13c2a03 --- /dev/null +++ b/implementations/encrypted/ciphers/AES256_GCM.h @@ -0,0 +1,40 @@ +#pragma once +#ifndef MESSMER_BLOCKSTORE_IMPLEMENTATIONS_ENCRYPTED_CIPHERS_AES256_GCM_H_ +#define MESSMER_BLOCKSTORE_IMPLEMENTATIONS_ENCRYPTED_CIPHERS_AES256_GCM_H_ + +#include "../../../utils/FixedSizeData.h" +#include "../../../utils/Data.h" +#include +#include +#include "Cipher.h" + +namespace blockstore { +namespace encrypted { + +class AES256_GCM { +public: + BOOST_CONCEPT_ASSERT((CipherConcept)); + + using EncryptionKey = FixedSizeData<32>; + static_assert(32 == CryptoPP::AES::MAX_KEYLENGTH, "If AES offered larger keys, we should offer a variant with it"); + + static constexpr unsigned int ciphertextSize(unsigned int plaintextBlockSize) { + return plaintextBlockSize + IV_SIZE + TAG_SIZE; + } + + static constexpr unsigned int plaintextSize(unsigned int ciphertextBlockSize) { + return ciphertextBlockSize - IV_SIZE - TAG_SIZE; + } + + static Data encrypt(const byte *plaintext, unsigned int plaintextSize, const EncryptionKey &encKey); + static boost::optional decrypt(const byte *ciphertext, unsigned int ciphertextSize, const EncryptionKey &encKey); + +private: + static constexpr unsigned int IV_SIZE = CryptoPP::AES::BLOCKSIZE; + static constexpr unsigned int TAG_SIZE = 16; +}; + +} +} + +#endif diff --git a/test/implementations/encrypted/CipherTest.cpp b/test/implementations/encrypted/CipherTest.cpp index f7471d60..e650fcb4 100644 --- a/test/implementations/encrypted/CipherTest.cpp +++ b/test/implementations/encrypted/CipherTest.cpp @@ -1,5 +1,6 @@ #include #include "../../../implementations/encrypted/ciphers/AES256_CFB.h" +#include "../../../implementations/encrypted/ciphers/AES256_GCM.h" #include "../../../implementations/encrypted/ciphers/Cipher.h" #include "../../testutils/DataBlockFixture.h" @@ -117,3 +118,4 @@ REGISTER_TYPED_TEST_CASE_P(CipherTest, //TODO For authenticated ciphers, we need test cases checking that authentication fails on manipulations INSTANTIATE_TYPED_TEST_CASE_P(AES256_CFB, CipherTest, AES256_CFB); +INSTANTIATE_TYPED_TEST_CASE_P(AES256_GCM, CipherTest, AES256_GCM);