Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions contrib/openssl-cmake/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ target_compile_options(ssl INTERFACE

target_compile_options(ssl INTERFACE
-DOPENSSL_IS_BORINGSSL=1
-DFIPS_CLICKHOUSE=1
)

# This is taken from the later in the file when FIPS_CLICKHOUSE is not defined.
Expand Down
43 changes: 41 additions & 2 deletions src/Compression/CompressionCodecEncrypted.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,17 @@ namespace ErrorCodes

EncryptionMethod toEncryptionMethod(const std::string & name)
{
#if defined(FIPS_CLICKHOUSE) && FIPS_CLICKHOUSE
if (name == "AES_128_GCM")
return AES_128_GCM;
if (name == "AES_256_GCM")
return AES_256_GCM;
#else
if (name == "AES_128_GCM_SIV")
return AES_128_GCM_SIV;
if (name == "AES_256_GCM_SIV")
return AES_256_GCM_SIV;
#endif
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Unknown encryption method. Got {}", name);
}

Expand All @@ -42,20 +49,34 @@ namespace
/// Get string name for method. Return empty string for undefined Method
String getMethodName(EncryptionMethod Method)
{
#if defined(FIPS_CLICKHOUSE) && FIPS_CLICKHOUSE
if (Method == AES_128_GCM)
return "AES_128_GCM";
if (Method == AES_256_GCM)
return "AES_256_GCM";
#else
if (Method == AES_128_GCM_SIV)
return "AES_128_GCM_SIV";
if (Method == AES_256_GCM_SIV)
return "AES_256_GCM_SIV";
#endif
return "";
}

/// Get method code (used for codec, to understand which one we are using)
uint8_t getMethodCode(EncryptionMethod Method)
{
#if defined(FIPS_CLICKHOUSE) && FIPS_CLICKHOUSE
if (Method == AES_128_GCM)
return static_cast<uint8_t>(CompressionMethodByte::AES_128_GCM);
if (Method == AES_256_GCM)
return static_cast<uint8_t>(CompressionMethodByte::AES_256_GCM);
#else
if (Method == AES_128_GCM_SIV)
return static_cast<uint8_t>(CompressionMethodByte::AES_128_GCM_SIV);
if (Method == AES_256_GCM_SIV)
return static_cast<uint8_t>(CompressionMethodByte::AES_256_GCM_SIV);
#endif
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Unknown encryption method. Got {}", getMethodName(Method));
}

Expand Down Expand Up @@ -86,10 +107,17 @@ const String empty_nonce = {"\0\0\0\0\0\0\0\0\0\0\0\0", actual_nonce_size};
/// Find out key size for each algorithm
UInt64 methodKeySize(EncryptionMethod Method)
{
#if defined(FIPS_CLICKHOUSE) && FIPS_CLICKHOUSE
if (Method == AES_128_GCM)
return 16;
if (Method == AES_256_GCM)
return 32;
#else
if (Method == AES_128_GCM_SIV)
return 16;
if (Method == AES_256_GCM_SIV)
return 32;
#endif
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Unknown encryption method. Got {}", getMethodName(Method));
}

Expand All @@ -104,6 +132,12 @@ std::string lastErrorString()
/// Get encryption/decryption algorithms.
const char * getMethod(EncryptionMethod Method)
{
#if defined(FIPS_CLICKHOUSE) && FIPS_CLICKHOUSE
if (Method == AES_128_GCM)
return "AES-128-GCM";
else if (Method == AES_256_GCM)
return "AES-256-GCM";
#else
/// The encrypting codecs were originally implemented using boringssl's API. At a later point and for FIPS-related reasons, an
/// implementation based on OpenSSL was added specifically for s390/x. At that time, OpenSSL did not provide *-SIV ciphers (they were
/// only added with OpenSSL 3.2), whereas boringssl provided them for ages. As a result, s390/x used non-SIV ciphers instead (leading to
Expand All @@ -120,6 +154,7 @@ const char * getMethod(EncryptionMethod Method)
return "AES-256-GCM";
#else
return "AES-256-GCM-SIV";
#endif
#endif
else
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Unknown encryption method. Got {}", getMethodName(Method));
Expand Down Expand Up @@ -440,7 +475,11 @@ void CompressionCodecEncrypted::Configuration::load(const Poco::Util::AbstractCo
/// In case of an error, throw exception
std::unique_ptr<Params> new_params;
static constexpr std::pair<std::string_view, EncryptionMethod> config_encryption_methods[] =
#if defined(FIPS_CLICKHOUSE) && FIPS_CLICKHOUSE
{{".aes_128_gcm", AES_128_GCM}, {".aes_256_gcm", AES_256_GCM}};
#else
{{".aes_128_gcm_siv", AES_128_GCM_SIV}, {".aes_256_gcm_siv", AES_256_GCM_SIV}};
#endif
for (const auto& config_encryption_method : config_encryption_methods)
{
auto encryption_method_key = config_prefix + config_encryption_method.first.data();
Expand Down Expand Up @@ -644,7 +683,7 @@ namespace DB
/// Register codecs for all algorithms
void registerCodecEncrypted(CompressionCodecFactory & factory)
{
registerEncryptionCodec(factory, AES_128_GCM_SIV);
registerEncryptionCodec(factory, AES_256_GCM_SIV);
registerEncryptionCodec(factory, AES_128_GCM);
registerEncryptionCodec(factory, AES_256_GCM);
}
}
7 changes: 7 additions & 0 deletions src/Compression/CompressionCodecEncrypted.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,15 @@ namespace DB
/// Now we have two algorithms.
enum EncryptionMethod
{
#if defined(FIPS_CLICKHOUSE) && FIPS_CLICKHOUSE
// Since _SIV methods are not explicitly included into a "white list" of ciphers in security policy
// we have to use non-SIV ciphers here
AES_128_GCM,
AES_256_GCM,
#else
AES_128_GCM_SIV,
AES_256_GCM_SIV,
#endif
MAX_ENCRYPTION_METHOD
};

Expand Down
7 changes: 7 additions & 0 deletions src/Compression/CompressionInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,13 @@ enum class CompressionMethodByte : uint8_t
DeflateQpl = 0x99,
GCD = 0x9a,
ZSTD_QPL = 0x9b,

#if defined(FIPS_CLICKHOUSE) && FIPS_CLICKHOUSE
// Ciphers are NOT compatible, and we are eliminating even slightest chance of mixing those up while loading encrypted data
// since erroring out early is better than loading data incorrectly.
AES_128_GCM = 0xfa,
AES_256_GCM = 0xfb,
#endif
};

}
5 changes: 5 additions & 0 deletions src/Compression/fuzzers/encrypted_decompress_fuzzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -308,8 +308,13 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t * data, size_t size)
return 0;

auto config = generator.getResult();
#if defined(FIPS_CLICKHOUSE) && FIPS_CLICKHOUSE
auto codec_128 = getCompressionCodecEncrypted(DB::AES_128_GCM_SIV);
auto codec_256 = getCompressionCodecEncrypted(DB::AES_256_GCM_SIV);
#else
auto codec_128 = getCompressionCodecEncrypted(DB::AES_128_GCM_SIV);
auto codec_256 = getCompressionCodecEncrypted(DB::AES_256_GCM_SIV);
#endif
DB::CompressionCodecEncrypted::Configuration::instance().tryLoad(*config, "");

size_t data_size = size - generator.keySize();
Expand Down
8 changes: 4 additions & 4 deletions tests/config/config.d/encryption.xml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<clickhouse>
<encryption_codecs>
<aes_128_gcm_siv>
<aes_128_gcm>
<key_hex>a32902703dab1cedd7ff7287067787ca</key_hex>
</aes_128_gcm_siv>
<aes_256_gcm_siv>
</aes_128_gcm>
<aes_256_gcm>
<key_hex>a32902703dab1cedd7ff7287067787caa32902703dab1cedd7ff7287067787ca</key_hex>
</aes_256_gcm_siv>
</aes_256_gcm>
</encryption_codecs>
</clickhouse>
12 changes: 6 additions & 6 deletions tests/integration/test_codec_encrypted/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,16 @@ def make_storage_with_key(id):
"""cat > /etc/clickhouse-server/config.d/storage_keys_config.xml << EOF
<clickhouse>
<encryption_codecs>
<aes_128_gcm_siv>
<aes_128_gcm>
<key_hex id="0">83e84e9a4eb11535c0670dc62d808ee0</key_hex>
<key id="1">abcdefghijklmnop</key>
<current_key_id>{cur_id}</current_key_id>
</aes_128_gcm_siv>
<aes_256_gcm_siv>
</aes_128_gcm>
<aes_256_gcm>
<key_hex id="0">83e84e9a4eb11535c0670dc62d808ee083e84e9a4eb11535c0670dc62d808ee0</key_hex>
<key id="1">abcdefghijklmnopabcdefghijklmnop</key>
<current_key_id>{cur_id}</current_key_id>
</aes_256_gcm_siv>
</aes_256_gcm>
</encryption_codecs>
</clickhouse>
EOF""".format(
Expand All @@ -53,7 +53,7 @@ def test_different_keys(start_cluster):
"""
CREATE TABLE encrypted_test_128 (
id Int64,
data String Codec(AES_128_GCM_SIV)
data String Codec(AES_128_GCM)
) ENGINE=MergeTree()
ORDER BY id
"""
Expand All @@ -63,7 +63,7 @@ def test_different_keys(start_cluster):
"""
CREATE TABLE encrypted_test_256 (
id Int64,
data String Codec(AES_256_GCM_SIV)
data String Codec(AES_256_GCM)
) ENGINE=MergeTree()
ORDER BY id
"""
Expand Down
14 changes: 8 additions & 6 deletions tests/integration/test_config_decryption/configs/config.xml
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
<clickhouse>

<encryption_codecs>
<aes_128_gcm_siv>
<aes_128_gcm>
<key_hex>00112233445566778899aabbccddeeff</key_hex>
</aes_128_gcm_siv>
<aes_256_gcm_siv>
</aes_128_gcm>
<aes_256_gcm>
<key_hex>00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff</key_hex>
</aes_256_gcm_siv>
</aes_256_gcm>
</encryption_codecs>

<max_table_size_to_drop encrypted_by="AES_128_GCM_SIV">96260000000B0000000000E8FE3C087CED2205A5071078B29FD5C3B97F824911DED3217E980C</max_table_size_to_drop>
<max_partition_size_to_drop encrypted_by="AES_256_GCM_SIV">97260000000B0000000000BFFF70C4DA718754C1DA0E2F25FF9246D4783F7FFEC4089EC1CC14</max_partition_size_to_drop>
<!-- plaintext: 60000000000 -->
<max_table_size_to_drop encrypted_by="AES_128_GCM">FA260000000B00000000002BC9170775238FE4AF735B4AE0DE79EE1EB544ACC3D2D8D4CAA99E</max_table_size_to_drop>
<!-- plaintext: 40000000000 -->
<max_partition_size_to_drop encrypted_by="AES_256_GCM">FB260000000B0000000000FFC2029EE82DD331A166B9B8C349D11367C831C45F27E5D4BB8601</max_partition_size_to_drop>

</clickhouse>
14 changes: 8 additions & 6 deletions tests/integration/test_config_decryption/configs/config.yaml
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
encryption_codecs:
aes_128_gcm_siv:
aes_128_gcm:
key_hex: 00112233445566778899aabbccddeeff
aes_256_gcm_siv:
aes_256_gcm:
key_hex: 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff

max_table_size_to_drop:
'@encrypted_by': AES_128_GCM_SIV
'#text': 96260000000B0000000000E8FE3C087CED2205A5071078B29FD5C3B97F824911DED3217E980C
'@encrypted_by': AES_128_GCM
# plaintext: 60000000000
'#text': FA260000000B00000000002BC9170775238FE4AF735B4AE0DE79EE1EB544ACC3D2D8D4CAA99E

max_partition_size_to_drop:
'@encrypted_by': AES_256_GCM_SIV
'#text': 97260000000B0000000000BFFF70C4DA718754C1DA0E2F25FF9246D4783F7FFEC4089EC1CC14
'@encrypted_by': AES_256_GCM
# plaintext: 40000000000
'#text': FB260000000B0000000000FFC2029EE82DD331A166B9B8C349D11367C831C45F27E5D4BB8601
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
<clickhouse>

<encryption_codecs>
<aes_128_gcm_siv>
<aes_128_gcm>
<key_hex>00112233445566778899aabbccddeeff</key_hex>
</aes_128_gcm_siv>
<aes_256_gcm_siv>
</aes_128_gcm>
<aes_256_gcm>
<key_hex>00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff</key_hex>
</aes_256_gcm_siv>
</aes_256_gcm>
</encryption_codecs>

<!-- Dash prefix leads to invalid hex-encoding -->
<max_table_size_to_drop encrypted_by="AES_128_GCM_SIV">--96260000000B0000000000E8FE3C087CED2205A5071078B29FD5C3B97F824911DED3217E980C</max_table_size_to_drop>
<max_partition_size_to_drop encrypted_by="AES_256_GCM_SIV">97260000000B0000000000BFFF70C4DA718754C1DA0E2F25FF9246D4783F7FFEC4089EC1CC14</max_partition_size_to_drop>
<!-- plaintext: 60000000000 -->
<max_table_size_to_drop encrypted_by="AES_128_GCM">--FA260000000B00000000002BC9170775238FE4AF735B4AE0DE79EE1EB544ACC3D2D8D4CAA99E</max_table_size_to_drop>
<!-- plaintext: 40000000000 -->
<max_partition_size_to_drop encrypted_by="AES_256_GCM">FB260000000B0000000000FFC2029EE82DD331A166B9B8C349D11367C831C45F27E5D4BB8601</max_partition_size_to_drop>

</clickhouse>
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

<!-- section "encryption_codec" is not specified -->

<max_table_size_to_drop encrypted_by="AES_128_GCM_SIV">96260000000B0000000000E8FE3C087CED2205A5071078B29FD5C3B97F824911DED3217E980C</max_table_size_to_drop>
<!-- plaintext: 60000000000 -->
<max_table_size_to_drop encrypted_by="AES_128_GCM">FA260000000B00000000002BC9170775238FE4AF735B4AE0DE79EE1EB544ACC3D2D8D4CAA99E</max_table_size_to_drop>

</clickhouse>
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<clickhouse>
<!-- no encryption key found in ZK -->
<encryption_codecs>
<aes_128_gcm_siv>
<aes_128_gcm>
<key_hex from_zk="/invalid_key"/>
</aes_128_gcm_siv>
</aes_128_gcm>
</encryption_codecs>
</clickhouse>
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
<clickhouse>

<encryption_codecs>
<aes_128_gcm_siv>
<aes_128_gcm>
<key_hex>00112233445566778899aabbccddeeff</key_hex>
</aes_128_gcm_siv>
</aes_128_gcm>
</encryption_codecs>

<!-- tags with "encrypted_by" must not have nested tags -->
<interserver_http_credentials encrypted_by="AES_128_GCM_SIV">
<password>96260000000B0000000000E8FE3C087CED2205A5071078B29FD5C3B97F824911DED3217E980C</password>
<interserver_http_credentials encrypted_by="AES_128_GCM">
<!-- plaintext: 60000000000 -->
<password>FA260000000B00000000002BC9170775238FE4AF735B4AE0DE79EE1EB544ACC3D2D8D4CAA99E</password>
</interserver_http_credentials>

</clickhouse>
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
<clickhouse>

<encryption_codecs>
<aes_128_gcm_siv>
<aes_128_gcm>
<key_hex>00112233445566778899aabbccddeeff</key_hex>
</aes_128_gcm_siv>
<aes_256_gcm_siv>
</aes_128_gcm>
<aes_256_gcm>
<key_hex>00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff</key_hex>
</aes_256_gcm_siv>
</aes_256_gcm>
</encryption_codecs>

<max_table_size_to_drop encrypted_by="AES_128_GCM_SIV">96260000000B0000000000E8FE3C087CED2205A5071078B29FD5C3B97F824911DED3217E980C</max_table_size_to_drop>
<max_partition_size_to_drop encrypted_by="WRONG">97260000000B0000000000BFFF70C4DA718754C1DA0E2F25FF9246D4783F7FFEC4089EC1CC14</max_partition_size_to_drop>
<!-- plaintext: 60000000000 -->
<max_table_size_to_drop encrypted_by="AES_128_GCM">FA260000000B00000000002BC9170775238FE4AF735B4AE0DE79EE1EB544ACC3D2D8D4CAA99E</max_table_size_to_drop>
<!-- plaintext: 40000000000 -->
<max_partition_size_to_drop encrypted_by="WRONG">FB260000000B0000000000FFC2029EE82DD331A166B9B8C349D11367C831C45F27E5D4BB8601</max_partition_size_to_drop>

</clickhouse>
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<clickhouse>
<!-- key for decryption is stored in ZK -->
<encryption_codecs>
<aes_128_gcm_siv>
<aes_128_gcm>
<key_hex from_zk="/clickhouse/key128"/>
</aes_128_gcm_siv>
</aes_128_gcm>
</encryption_codecs>
</clickhouse>
3 changes: 2 additions & 1 deletion tests/integration/test_config_decryption/configs/users.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
<clickhouse>
<users>
<test_user>
<password encrypted_by="AES_128_GCM_SIV">96280000000D000000000030D4632962295D46C6FA4ABF007CCEC9C1D0E19DA5AF719C1D9A46C446</password>
<!-- plaintext: test_password -->
<password encrypted_by="AES_128_GCM">FA280000000D0000000000699C54431A63DEA7EC3404A55BF07CF2FF4F77E4FCCEB878E6BE6BACC8</password>
<profile>default</profile>
</test_user>
</users>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<clickhouse>
<encryption_codecs>
<aes_128_gcm_siv>
<aes_128_gcm>
<key>0000000000000000</key>
</aes_128_gcm_siv>
</aes_128_gcm>
</encryption_codecs>
</clickhouse>
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def create_table():
"""
CREATE TABLE tbl ON CLUSTER 'cluster' (
id Int64,
str String Codec(AES_128_GCM_SIV)
str String Codec(AES_128_GCM)
) ENGINE=ReplicatedMergeTree('/clickhouse/tables/tbl/', '{replica}')
ORDER BY id
"""
Expand Down
Loading
Loading