mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-26 01:22:04 +00:00
Add encryption support with openssl
This commit is contained in:
parent
496cacf25e
commit
1d4cf4fe69
@ -82,9 +82,7 @@
|
||||
#include <Common/ThreadFuzzer.h>
|
||||
#include <Common/getHashOfLoadedBinary.h>
|
||||
#include <Common/filesystemHelpers.h>
|
||||
#if USE_BORINGSSL
|
||||
#include <Compression/CompressionCodecEncrypted.h>
|
||||
#endif
|
||||
#include <Server/HTTP/HTTPServerConnectionFactory.h>
|
||||
#include <Server/MySQLHandlerFactory.h>
|
||||
#include <Server/PostgreSQLHandlerFactory.h>
|
||||
@ -1348,9 +1346,7 @@ try
|
||||
|
||||
global_context->updateStorageConfiguration(*config);
|
||||
global_context->updateInterserverCredentials(*config);
|
||||
#if USE_BORINGSSL
|
||||
CompressionCodecEncrypted::Configuration::instance().tryLoad(*config, "encryption_codecs");
|
||||
#endif
|
||||
#if USE_SSL
|
||||
CertificateReloader::instance().tryLoad(*config);
|
||||
#endif
|
||||
@ -1564,10 +1560,8 @@ try
|
||||
global_context->getMergeTreeSettings().sanityCheck(background_pool_tasks);
|
||||
global_context->getReplicatedMergeTreeSettings().sanityCheck(background_pool_tasks);
|
||||
}
|
||||
#if USE_BORINGSSL
|
||||
/// try set up encryption. There are some errors in config, error will be printed and server wouldn't start.
|
||||
CompressionCodecEncrypted::Configuration::instance().load(config(), "encryption_codecs");
|
||||
#endif
|
||||
|
||||
SCOPE_EXIT({
|
||||
async_metrics.stop();
|
||||
|
@ -226,13 +226,7 @@ add_object_library(clickhouse_access Access)
|
||||
add_object_library(clickhouse_backups Backups)
|
||||
add_object_library(clickhouse_core Core)
|
||||
add_object_library(clickhouse_core_mysql Core/MySQL)
|
||||
if (ENABLE_OPENSSL OR ENABLE_OPENSSL_DYNAMIC)
|
||||
add_headers_and_sources(dbms Compression)
|
||||
list(REMOVE_ITEM dbms_headers Compression/CompressionCodecEncrypted.h)
|
||||
list(REMOVE_ITEM dbms_sources Compression/CompressionCodecEncrypted.cpp)
|
||||
else ()
|
||||
add_object_library(clickhouse_compression Compression)
|
||||
endif ()
|
||||
add_object_library(clickhouse_compression Compression)
|
||||
add_object_library(clickhouse_querypipeline QueryPipeline)
|
||||
add_object_library(clickhouse_datatypes DataTypes)
|
||||
add_object_library(clickhouse_datatypes_serializations DataTypes/Serializations)
|
||||
|
@ -11,10 +11,14 @@
|
||||
|
||||
// This depends on BoringSSL-specific API, notably <openssl/aead.h>.
|
||||
#if USE_SSL
|
||||
#include <openssl/digest.h>
|
||||
#include <openssl/err.h>
|
||||
#include <boost/algorithm/hex.hpp>
|
||||
#if USE_BORINGSSL
|
||||
#include <openssl/digest.h>
|
||||
#include <openssl/aead.h>
|
||||
#else
|
||||
#include <openssl/evp.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Common part for both parts (with SSL and without)
|
||||
@ -87,23 +91,6 @@ constexpr size_t nonce_max_size = 13; /// Nonce size and one byte to show i
|
||||
constexpr size_t actual_nonce_size = 12; /// Nonce actual size
|
||||
const String empty_nonce = {"\0\0\0\0\0\0\0\0\0\0\0\0", actual_nonce_size};
|
||||
|
||||
/// Get encryption/decryption algorithms.
|
||||
auto getMethod(EncryptionMethod Method)
|
||||
{
|
||||
if (Method == AES_128_GCM_SIV)
|
||||
{
|
||||
return EVP_aead_aes_128_gcm_siv;
|
||||
}
|
||||
else if (Method == AES_256_GCM_SIV)
|
||||
{
|
||||
return EVP_aead_aes_256_gcm_siv;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Wrong encryption Method. Got {}", getMethodName(Method));
|
||||
}
|
||||
}
|
||||
|
||||
/// Find out key size for each algorithm
|
||||
UInt64 methodKeySize(EncryptionMethod Method)
|
||||
{
|
||||
@ -128,6 +115,24 @@ std::string lastErrorString()
|
||||
return std::string(buffer.data());
|
||||
}
|
||||
|
||||
#if USE_BORINGSSL
|
||||
/// Get encryption/decryption algorithms.
|
||||
auto getMethod(EncryptionMethod Method)
|
||||
{
|
||||
if (Method == AES_128_GCM_SIV)
|
||||
{
|
||||
return EVP_aead_aes_128_gcm_siv;
|
||||
}
|
||||
else if (Method == AES_256_GCM_SIV)
|
||||
{
|
||||
return EVP_ae'grant_type=urn%3Aibm%3Aparams%3Aoauth%3Agrant-type%3Aapikey&apikey=$API_KEY'ad_aes_256_gcm_siv;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Wrong encryption Method. Got {}", getMethodName(Method));
|
||||
}
|
||||
}
|
||||
|
||||
/// Encrypt plaintext with particular algorithm and put result into ciphertext_and_tag.
|
||||
/// This function get key and nonce and encrypt text with their help.
|
||||
/// If something went wrong (can't init context or can't encrypt data) it throws exception.
|
||||
@ -186,6 +191,138 @@ size_t decrypt(std::string_view ciphertext, char * plaintext, EncryptionMethod m
|
||||
|
||||
return out_len;
|
||||
}
|
||||
#else
|
||||
/// Get encryption/decryption algorithms.
|
||||
auto getMethod(EncryptionMethod Method)
|
||||
{
|
||||
if (Method == AES_128_GCM_SIV)
|
||||
{
|
||||
return EVP_aes_128_gcm;
|
||||
}
|
||||
else if (Method == AES_256_GCM_SIV)
|
||||
{
|
||||
return EVP_aes_256_gcm;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw Exception("Wrong encryption Method. Got " + getMethodName(Method), ErrorCodes::BAD_ARGUMENTS);
|
||||
}
|
||||
}
|
||||
|
||||
/// Encrypt plaintext with particular algorithm and put result into ciphertext_and_tag.
|
||||
/// This function get key and nonce and encrypt text with their help.
|
||||
/// If something went wrong (can't init context or can't encrypt data) it throws exception.
|
||||
/// It returns length of encrypted text.
|
||||
size_t encrypt(std::string_view plaintext, char * ciphertext_and_tag, EncryptionMethod method, const String & key, const String & nonce)
|
||||
{
|
||||
EVP_CIPHER_CTX *encrypt_ctx;
|
||||
|
||||
if (!(encrypt_ctx = EVP_CIPHER_CTX_new()))
|
||||
throw Exception(lastErrorString(), ErrorCodes::OPENSSL_ERROR);
|
||||
|
||||
const int ok_cryptinit = EVP_EncryptInit_ex(encrypt_ctx,
|
||||
getMethod(method)(),
|
||||
nullptr, nullptr, nullptr);
|
||||
if (!ok_cryptinit)
|
||||
throw Exception(lastErrorString(), ErrorCodes::OPENSSL_ERROR);
|
||||
|
||||
const int ok_cipherctrl = EVP_CIPHER_CTX_ctrl(encrypt_ctx,
|
||||
EVP_CTRL_GCM_SET_IVLEN,
|
||||
static_cast<int32_t>(nonce.size()),
|
||||
nullptr);
|
||||
if (!ok_cipherctrl)
|
||||
throw Exception(lastErrorString(), ErrorCodes::OPENSSL_ERROR);
|
||||
|
||||
const int ok_nonceinit = EVP_EncryptInit_ex(encrypt_ctx, nullptr, nullptr,
|
||||
reinterpret_cast<const uint8_t*>(key.data()),
|
||||
reinterpret_cast<const uint8_t *>(nonce.data()));
|
||||
if (!ok_nonceinit)
|
||||
throw Exception(lastErrorString(), ErrorCodes::OPENSSL_ERROR);
|
||||
|
||||
size_t out_len;
|
||||
const int ok_encryptudpate = EVP_EncryptUpdate(encrypt_ctx,
|
||||
reinterpret_cast<uint8_t *>(ciphertext_and_tag),
|
||||
reinterpret_cast<int32_t *>(&out_len),
|
||||
reinterpret_cast<const uint8_t *>(plaintext.data()),
|
||||
static_cast<int32_t>(plaintext.size()));
|
||||
if (!ok_encryptudpate)
|
||||
throw Exception(lastErrorString(), ErrorCodes::OPENSSL_ERROR);
|
||||
|
||||
const int ok_encryptfinal = EVP_EncryptFinal_ex(encrypt_ctx,
|
||||
reinterpret_cast<uint8_t *>(ciphertext_and_tag) + out_len,
|
||||
reinterpret_cast<int32_t *>(&out_len));
|
||||
if (!ok_encryptfinal)
|
||||
throw Exception(lastErrorString(), ErrorCodes::OPENSSL_ERROR);
|
||||
|
||||
/* Get the tag */
|
||||
const int ok_tag = EVP_CIPHER_CTX_ctrl(encrypt_ctx,
|
||||
EVP_CTRL_GCM_GET_TAG,
|
||||
tag_size,
|
||||
reinterpret_cast<uint8_t *>(ciphertext_and_tag) + plaintext.size());
|
||||
if (!ok_tag)
|
||||
throw Exception(lastErrorString(), ErrorCodes::OPENSSL_ERROR);
|
||||
|
||||
EVP_CIPHER_CTX_free(encrypt_ctx);
|
||||
|
||||
return plaintext.size() + tag_size;
|
||||
}
|
||||
|
||||
/// Encrypt plaintext with particular algorithm and put result into ciphertext_and_tag.
|
||||
/// This function get key and nonce and encrypt text with their help.
|
||||
/// If something went wrong (can't init context or can't encrypt data) it throws exception.
|
||||
/// It returns length of encrypted text.
|
||||
size_t decrypt(std::string_view ciphertext, char * plaintext, EncryptionMethod method, const String & key, const String & nonce)
|
||||
{
|
||||
EVP_CIPHER_CTX *decrypt_ctx;
|
||||
|
||||
if (!(decrypt_ctx = EVP_CIPHER_CTX_new()))
|
||||
throw Exception(lastErrorString(), ErrorCodes::OPENSSL_ERROR);
|
||||
|
||||
const int ok_cryptinit = EVP_DecryptInit_ex(decrypt_ctx,
|
||||
getMethod(method)(),
|
||||
nullptr, nullptr, nullptr);
|
||||
if (!ok_cryptinit)
|
||||
throw Exception(lastErrorString(), ErrorCodes::OPENSSL_ERROR);
|
||||
|
||||
const int ok_cipherctrl = EVP_CIPHER_CTX_ctrl(decrypt_ctx,
|
||||
EVP_CTRL_GCM_SET_IVLEN,
|
||||
static_cast<int32_t>(nonce.size()), nullptr);
|
||||
if (!ok_cipherctrl)
|
||||
throw Exception(lastErrorString(), ErrorCodes::OPENSSL_ERROR);
|
||||
|
||||
const int ok_nonceinit = EVP_DecryptInit_ex(decrypt_ctx, nullptr, nullptr,
|
||||
reinterpret_cast<const uint8_t*>(key.data()),
|
||||
reinterpret_cast<const uint8_t *>(nonce.data()));
|
||||
if (!ok_nonceinit)
|
||||
throw Exception(lastErrorString(), ErrorCodes::OPENSSL_ERROR);
|
||||
|
||||
size_t out_len;
|
||||
const int ok_decryptudpate = EVP_DecryptUpdate(decrypt_ctx,
|
||||
reinterpret_cast<uint8_t *>(plaintext),
|
||||
reinterpret_cast<int32_t *>(&out_len),
|
||||
reinterpret_cast<const uint8_t *>(ciphertext.data()),
|
||||
static_cast<int32_t>(ciphertext.size()) - tag_size);
|
||||
if (!ok_decryptudpate)
|
||||
throw Exception(lastErrorString(), ErrorCodes::OPENSSL_ERROR);
|
||||
|
||||
const int ok_tag = EVP_CIPHER_CTX_ctrl(decrypt_ctx,
|
||||
EVP_CTRL_GCM_SET_TAG,
|
||||
tag_size,
|
||||
reinterpret_cast<uint8_t *>(const_cast<char *>(ciphertext.data())) + ciphertext.size() - tag_size);
|
||||
if (!ok_tag)
|
||||
throw Exception(lastErrorString(), ErrorCodes::OPENSSL_ERROR);
|
||||
|
||||
const int ok_decryptfinal = EVP_DecryptFinal_ex(decrypt_ctx,
|
||||
reinterpret_cast<uint8_t *>(plaintext) + out_len,
|
||||
reinterpret_cast<int32_t *>(&out_len));
|
||||
if (!ok_decryptfinal)
|
||||
throw Exception(lastErrorString(), ErrorCodes::OPENSSL_ERROR);
|
||||
|
||||
EVP_CIPHER_CTX_free(decrypt_ctx);
|
||||
|
||||
return ciphertext.size() - tag_size;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Register codec in factory
|
||||
void registerEncryptionCodec(CompressionCodecFactory & factory, EncryptionMethod Method)
|
||||
|
@ -178,9 +178,7 @@ void registerCodecDelta(CompressionCodecFactory & factory);
|
||||
void registerCodecT64(CompressionCodecFactory & factory);
|
||||
void registerCodecDoubleDelta(CompressionCodecFactory & factory);
|
||||
void registerCodecGorilla(CompressionCodecFactory & factory);
|
||||
#if USE_BORINGSSL
|
||||
void registerCodecEncrypted(CompressionCodecFactory & factory);
|
||||
#endif
|
||||
void registerCodecFPC(CompressionCodecFactory & factory);
|
||||
|
||||
#endif
|
||||
@ -197,9 +195,7 @@ CompressionCodecFactory::CompressionCodecFactory()
|
||||
registerCodecT64(*this);
|
||||
registerCodecDoubleDelta(*this);
|
||||
registerCodecGorilla(*this);
|
||||
#if USE_BORINGSSL
|
||||
registerCodecEncrypted(*this);
|
||||
#endif
|
||||
registerCodecFPC(*this);
|
||||
#ifdef ENABLE_QPL_COMPRESSION
|
||||
registerCodecDeflateQpl(*this);
|
||||
|
Loading…
Reference in New Issue
Block a user