remove debug information, fix seek issue and encryption issue

This commit is contained in:
Alexandra 2021-05-17 16:15:21 +00:00
parent 10a5b734ee
commit af420569f8
4 changed files with 51 additions and 50 deletions

View File

@ -62,15 +62,13 @@ std::unique_ptr<ReadBufferFromFileBase> DiskEncrypted::readFile(
size_t mmap_threshold, size_t mmap_threshold,
MMappedFileCache * mmap_cache) const MMappedFileCache * mmap_cache) const
{ {
using namespace FileEncryption;
auto wrapped_path = wrappedPath(path); auto wrapped_path = wrappedPath(path);
auto buffer = delegate->readFile(wrapped_path, buf_size, estimated_size, aio_threshold, mmap_threshold, mmap_cache); auto buffer = delegate->readFile(wrapped_path, buf_size, estimated_size, aio_threshold, mmap_threshold, mmap_cache);
auto iv = GetRandomString(kIVSize); auto iv = GetRandomString(kIVSize);
size_t offset = 0; size_t offset = 0;
if (delegate->getFileSize(wrapped_path)) if (exists(path) && getFileSize(path))
{ {
iv = ReadIV(kIVSize, *buffer); iv = ReadIV(kIVSize, *buffer);
offset = kIVSize; offset = kIVSize;
@ -84,16 +82,14 @@ std::unique_ptr<WriteBufferFromFileBase> DiskEncrypted::writeFile(
size_t buf_size, size_t buf_size,
WriteMode mode) WriteMode mode)
{ {
using namespace FileEncryption;
auto wrapped_path = wrappedPath(path); auto wrapped_path = wrappedPath(path);
auto iv = GetRandomString(kIVSize); auto iv = GetRandomString(kIVSize);
try { if (exists(path) && getFileSize(path))
{
auto read_buffer = delegate->readFile(wrapped_path, kIVSize); auto read_buffer = delegate->readFile(wrapped_path, kIVSize);
iv = ReadIV(kIVSize, *read_buffer); iv = ReadIV(kIVSize, *read_buffer);
} }
catch ( ... ) { }
auto buffer = delegate->writeFile(wrapped_path, buf_size, mode); auto buffer = delegate->writeFile(wrapped_path, buf_size, mode);
return std::make_unique<WriteEncryptedBuffer>(buf_size, std::move(buffer), iv, key, return std::make_unique<WriteEncryptedBuffer>(buf_size, std::move(buffer), iv, key,
@ -161,6 +157,9 @@ void registerDiskEncrypted(DiskFactory & factory)
String key = config.getString(config_prefix + ".key", ""); String key = config.getString(config_prefix + ".key", "");
if (key.empty()) if (key.empty())
throw Exception("Encrypted disk key can not be empty. Disk " + name, ErrorCodes::UNKNOWN_ELEMENT_IN_CONFIG); throw Exception("Encrypted disk key can not be empty. Disk " + name, ErrorCodes::UNKNOWN_ELEMENT_IN_CONFIG);
if (key.size() != CipherKeyLength(DefaultCipher()))
throw Exception("Expected key with size " + std::to_string(CipherKeyLength(DefaultCipher())) + ", got key with size " + std::to_string(key.size()),
ErrorCodes::UNKNOWN_ELEMENT_IN_CONFIG);
auto wrapped_disk = map.find(wrapped_disk_name); auto wrapped_disk = map.find(wrapped_disk_name);
if (wrapped_disk == map.end()) if (wrapped_disk == map.end())

View File

@ -1,7 +1,5 @@
#pragma once #pragma once
#include <fstream>
#include <openssl/evp.h> #include <openssl/evp.h>
#include <openssl/engine.h> #include <openssl/engine.h>
@ -9,8 +7,6 @@
#include <IO/WriteBuffer.h> #include <IO/WriteBuffer.h>
#include <IO/WriteHelpers.h> #include <IO/WriteHelpers.h>
#include <common/logger_useful.h>
#include <sys/random.h> #include <sys/random.h>
#include <limits> #include <limits>
@ -19,10 +15,11 @@
#include <Functions/FunctionsAES.h> #include <Functions/FunctionsAES.h>
namespace FileEncryption namespace FileEncryption
{ {
constexpr size_t kIVSize = 128 / CHAR_BIT / 2; constexpr size_t kIVSize = sizeof(DB::UInt64);
class InitVector class InitVector
{ {
@ -59,7 +56,6 @@ private:
mutable String modify; mutable String modify;
}; };
class EncryptionKey class EncryptionKey
{ {
public: public:
@ -87,6 +83,12 @@ String GetRandomString(size_t size)
return iv; return iv;
} }
void WriteIV(const String & iv, DB::WriteBuffer & out)
{
for (auto i : iv)
DB::writeChar(i, out);
}
size_t CipherKeyLength(const EVP_CIPHER * evp_cipher) size_t CipherKeyLength(const EVP_CIPHER * evp_cipher)
{ {
return static_cast<size_t>(EVP_CIPHER_key_length(evp_cipher)); return static_cast<size_t>(EVP_CIPHER_key_length(evp_cipher));
@ -97,12 +99,16 @@ size_t CipherIVLength(const EVP_CIPHER * evp_cipher)
return static_cast<size_t>(EVP_CIPHER_iv_length(evp_cipher)); return static_cast<size_t>(EVP_CIPHER_iv_length(evp_cipher));
} }
const EVP_CIPHER * DefaultCipher()
{
return EVP_aes_128_ctr();
}
class Encryption class Encryption
{ {
public: public:
Encryption(const String & iv_, const EncryptionKey & key_, size_t offset_ = 0) Encryption(const String & iv_, const EncryptionKey & key_, size_t offset_ = 0)
: evp_cipher(EVP_aes_128_ctr()) : evp_cipher(DefaultCipher())
, init_vector(iv_) , init_vector(iv_)
, key(key_) , key(key_)
, block_size(CipherIVLength(evp_cipher)) , block_size(CipherIVLength(evp_cipher))
@ -127,13 +133,12 @@ protected:
const EVP_CIPHER * get() const { return evp_cipher; } const EVP_CIPHER * get() const { return evp_cipher; }
const EVP_CIPHER * evp_cipher; const EVP_CIPHER * evp_cipher;
const InitVector init_vector; const String init_vector;
EncryptionKey key; const EncryptionKey key;
size_t block_size; size_t block_size;
size_t offset = 0; // global offset size_t offset = 0;
}; };
class Encryptor : public Encryption class Encryptor : public Encryption
{ {
public: public:
@ -145,22 +150,24 @@ public:
if (!size) if (!size)
return; return;
auto iv = init_vector; auto iv = InitVector(init_vector);
iv.SetCounter(Blocks(offset)); iv.SetCounter(Blocks(offset));
size_t first_block_size = FirstBlockSize(size, offset);
size_t first_block_size = FirstBlockSize(size, offset);
if (offset) if (offset)
{ {
buf.write(EncryptPartialBlock(plaintext, first_block_size, iv, offset).data(), first_block_size); buf.write(EncryptPartialBlock(plaintext, first_block_size, iv, offset).data(), first_block_size);
offset = BlockOffset(offset + first_block_size);
size -= first_block_size; size -= first_block_size;
offset += first_block_size;
iv.Inc(); iv.Inc();
} }
if (size) if (size)
{ {
size_t blocks = Blocks(size);
buf.write(EncryptNBytes(plaintext + first_block_size, size, iv).data(), size); buf.write(EncryptNBytes(plaintext + first_block_size, size, iv).data(), size);
offset += size; iv.Inc(blocks);
offset = size - blocks * block_size;
} }
} }
@ -169,7 +176,7 @@ private:
{ {
using namespace OpenSSLDetails; using namespace OpenSSLDetails;
if (size > block_size) if (size > block_size)
onError("Expecter partial block, got block with size > block_size: size = " + std::to_string(size)); onError("Expecter partial block, got block with size > block_size: size = " + std::to_string(size) + " and offset = " + std::to_string(off));
String plaintext(block_size, '\0'); String plaintext(block_size, '\0');
for (size_t i = 0; i < size; ++i) for (size_t i = 0; i < size; ++i)
@ -204,9 +211,6 @@ private:
ciphertext_ref += output_len; ciphertext_ref += output_len;
//* always do nothing for default cipher
int final_output_len = 0; int final_output_len = 0;
if (EVP_EncryptFinal_ex(evp_ctx, if (EVP_EncryptFinal_ex(evp_ctx,
reinterpret_cast<unsigned char*>(ciphertext_ref), &final_output_len) != 1) reinterpret_cast<unsigned char*>(ciphertext_ref), &final_output_len) != 1)
@ -230,7 +234,7 @@ public:
if (!size) if (!size)
return; return;
auto iv = init_vector; auto iv = InitVector(init_vector);
iv.SetCounter(Blocks(off)); iv.SetCounter(Blocks(off));
off = BlockOffset(off); off = BlockOffset(off);
@ -239,12 +243,15 @@ public:
{ {
DecryptPartialBlock(buf, ciphertext, first_block_size, iv, off); DecryptPartialBlock(buf, ciphertext, first_block_size, iv, off);
size -= first_block_size; size -= first_block_size;
if (first_block_size + off == block_size)
iv.Inc(); iv.Inc();
} }
if (size) if (size)
{ {
size_t blocks = Blocks(size);
DecryptNBytes(buf, ciphertext + first_block_size, size, iv); DecryptNBytes(buf, ciphertext + first_block_size, size, iv);
iv.Inc(blocks);
} }
} }
@ -275,7 +282,7 @@ private:
auto * evp_ctx = evp_ctx_ptr.get(); auto * evp_ctx = evp_ctx_ptr.get();
if (EVP_DecryptInit_ex(evp_ctx, evp_cipher, nullptr, nullptr, nullptr) != 1) if (EVP_DecryptInit_ex(evp_ctx, evp_cipher, nullptr, nullptr, nullptr) != 1)
onError("Failed to initialize decryption context with cipher"); onError("Failed to initialize encryption context with cipher");
if (EVP_DecryptInit_ex(evp_ctx, nullptr, nullptr, if (EVP_DecryptInit_ex(evp_ctx, nullptr, nullptr,
reinterpret_cast<const unsigned char*>(key.GetRef()), reinterpret_cast<const unsigned char*>(key.GetRef()),
@ -290,9 +297,6 @@ private:
to += output_len; to += output_len;
//* always do nothing for default cipher
int final_output_len = 0; int final_output_len = 0;
if (EVP_DecryptFinal_ex(evp_ctx, if (EVP_DecryptFinal_ex(evp_ctx,
reinterpret_cast<unsigned char*>(to), &final_output_len) != 1) reinterpret_cast<unsigned char*>(to), &final_output_len) != 1)

View File

@ -4,7 +4,6 @@
#include <IO/WriteBufferFromFileBase.h> #include <IO/WriteBufferFromFileBase.h>
#include <Functions/FileEncryption.h> #include <Functions/FileEncryption.h>
#include <common/logger_useful.h>
namespace DB namespace DB
{ {
@ -24,7 +23,6 @@ public:
, in(std::move(in_)) , in(std::move(in_))
, buf_size(buf_size_) , buf_size(buf_size_)
, decryptor(Decryptor(init_vector_, key_)) , decryptor(Decryptor(init_vector_, key_))
, start_pos(iv_offset_)
, iv_offset(iv_offset_) , iv_offset(iv_offset_)
{ } { }
@ -35,36 +33,35 @@ public:
if (off < 0 && -off > getPosition()) if (off < 0 && -off > getPosition())
throw Exception("SEEK_CUR shift out of bounds", ErrorCodes::ARGUMENT_OUT_OF_BOUND); throw Exception("SEEK_CUR shift out of bounds", ErrorCodes::ARGUMENT_OUT_OF_BOUND);
if (!working_buffer.empty() && size_t(offset() + off) < working_buffer.size()) if (!working_buffer.empty() && static_cast<size_t>(offset() + off) < working_buffer.size())
{ {
pos += off; pos += off;
return getPosition(); return getPosition();
} }
else else
start_pos = off + getPosition() + iv_offset; start_pos = off + getPosition();
} }
else if (whence == SEEK_SET) else if (whence == SEEK_SET)
{ {
if (off < 0) if (off < 0)
throw Exception("SEEK_SET underflow", ErrorCodes::ARGUMENT_OUT_OF_BOUND); throw Exception("SEEK_SET underflow: off = " + std::to_string(off), ErrorCodes::ARGUMENT_OUT_OF_BOUND);
if (!working_buffer.empty() && size_t(off) >= start_pos - working_buffer.size() if (!working_buffer.empty() && static_cast<size_t>(off) >= start_pos && static_cast<size_t>(off) < (start_pos + working_buffer.size()))
&& size_t(off) < start_pos)
{ {
pos = working_buffer.end() - (start_pos - off); pos = working_buffer.begin() + (off - start_pos);
return getPosition(); return getPosition();
} }
else else
start_pos = off + iv_offset; start_pos = off;
} }
else else
throw Exception("ReadEncryptedBuffer::seek expects SEEK_SET or SEEK_CUR as whence", ErrorCodes::ARGUMENT_OUT_OF_BOUND); throw Exception("ReadEncryptedBuffer::seek expects SEEK_SET or SEEK_CUR as whence", ErrorCodes::ARGUMENT_OUT_OF_BOUND);
initialize(); initialize();
return start_pos - iv_offset; return start_pos;
} }
off_t getPosition() override { return start_pos + offset() - iv_offset; } off_t getPosition() override { return start_pos + offset(); }
std::string getFileName() const override { return in->getFileName(); } std::string getFileName() const override { return in->getFileName(); }
@ -83,7 +80,7 @@ private:
void initialize() void initialize()
{ {
size_t in_pos = start_pos; size_t in_pos = start_pos + iv_offset;
String data; String data;
data.resize(buf_size); data.resize(buf_size);
@ -101,7 +98,7 @@ private:
data.resize(data_size); data.resize(data_size);
working_buffer.resize(data_size); working_buffer.resize(data_size);
decryptor.Decrypt(data.data(), working_buffer.begin(), data_size, start_pos - iv_offset); decryptor.Decrypt(data.data(), working_buffer.begin(), data_size, start_pos);
pos = working_buffer.begin(); pos = working_buffer.begin();
initialized = true; initialized = true;
@ -112,6 +109,8 @@ private:
Decryptor decryptor; Decryptor decryptor;
bool initialized = false; bool initialized = false;
// current working_buffer.begin() offset from decrypted file
size_t start_pos = 0; size_t start_pos = 0;
size_t iv_offset = 0; size_t iv_offset = 0;
}; };

View File

@ -3,7 +3,6 @@
#include <IO/WriteBufferFromFileBase.h> #include <IO/WriteBufferFromFileBase.h>
#include <Functions/FileEncryption.h> #include <Functions/FileEncryption.h>
#include <common/logger_useful.h>
namespace DB namespace DB
{ {
@ -63,7 +62,7 @@ private:
return; return;
if (flush_iv) if (flush_iv)
{ {
writeText(iv.data(), *out); WriteIV(iv, *out);
flush_iv = false; flush_iv = false;
} }