encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
#pragma once
|
|
|
|
|
2021-10-27 23:10:39 +00:00
|
|
|
#include <Common/config.h>
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
|
|
|
|
#if USE_SSL
|
|
|
|
#include <DataTypes/DataTypeString.h>
|
|
|
|
#include <Columns/ColumnString.h>
|
|
|
|
#include <Functions/IFunction.h>
|
|
|
|
#include <Functions/FunctionFactory.h>
|
|
|
|
#include <Functions/FunctionHelpers.h>
|
|
|
|
|
|
|
|
#include <fmt/format.h>
|
|
|
|
|
|
|
|
#include <openssl/evp.h>
|
2020-08-17 14:49:21 +00:00
|
|
|
#include <openssl/engine.h>
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
|
|
|
|
#include <string_view>
|
|
|
|
#include <functional>
|
|
|
|
#include <initializer_list>
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
|
2020-09-16 21:52:01 +00:00
|
|
|
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
namespace ErrorCodes
|
|
|
|
{
|
|
|
|
extern const int BAD_ARGUMENTS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace OpenSSLDetails
|
|
|
|
{
|
|
|
|
[[noreturn]] void onError(std::string error_message);
|
2022-07-15 11:15:46 +00:00
|
|
|
StringRef foldEncryptionKeyInMySQLCompatitableMode(size_t cipher_key_size, StringRef key, std::array<char, EVP_MAX_KEY_LENGTH> & folded_key);
|
2020-08-17 14:49:21 +00:00
|
|
|
|
2022-07-15 11:15:46 +00:00
|
|
|
const EVP_CIPHER * getCipherByName(StringRef name);
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
|
|
|
|
enum class CompatibilityMode
|
|
|
|
{
|
|
|
|
MySQL,
|
|
|
|
OpenSSL
|
|
|
|
};
|
|
|
|
|
|
|
|
enum class CipherMode
|
|
|
|
{
|
|
|
|
MySQLCompatibility, // with key folding
|
|
|
|
OpenSSLCompatibility, // just as regular openssl's enc application does (AEAD modes, like GCM and CCM are not supported)
|
|
|
|
RFC5116_AEAD_AES_GCM // AEAD GCM with custom IV length and tag (HMAC) appended to the ciphertext, see https://tools.ietf.org/html/rfc5116#section-5.1
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
template <CipherMode mode>
|
|
|
|
struct KeyHolder
|
|
|
|
{
|
2022-07-15 11:15:46 +00:00
|
|
|
inline StringRef setKey(size_t cipher_key_size, StringRef key) const
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
{
|
|
|
|
if (key.size != cipher_key_size)
|
|
|
|
throw DB::Exception(fmt::format("Invalid key size: {} expected {}", key.size, cipher_key_size),
|
|
|
|
DB::ErrorCodes::BAD_ARGUMENTS);
|
|
|
|
|
|
|
|
return key;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <>
|
|
|
|
struct KeyHolder<CipherMode::MySQLCompatibility>
|
|
|
|
{
|
2022-07-15 11:15:46 +00:00
|
|
|
inline StringRef setKey(size_t cipher_key_size, StringRef key)
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
{
|
|
|
|
if (key.size < cipher_key_size)
|
|
|
|
throw DB::Exception(fmt::format("Invalid key size: {} expected {}", key.size, cipher_key_size),
|
|
|
|
DB::ErrorCodes::BAD_ARGUMENTS);
|
|
|
|
|
|
|
|
// MySQL does something fancy with the keys that are too long,
|
|
|
|
// ruining compatibility with OpenSSL and not improving security.
|
|
|
|
// But we have to do the same to be compatitable with MySQL.
|
|
|
|
// see https://github.com/mysql/mysql-server/blob/8.0/router/src/harness/src/my_aes_openssl.cc#L71
|
|
|
|
// (my_aes_create_key function)
|
|
|
|
return foldEncryptionKeyInMySQLCompatitableMode(cipher_key_size, key, folded_key);
|
|
|
|
}
|
|
|
|
|
2020-11-30 07:01:55 +00:00
|
|
|
/// There is a function to clear key securely.
|
|
|
|
/// It makes absolutely zero sense to call it here because
|
|
|
|
/// key comes from column and already copied multiple times through various memory buffers.
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
std::array<char, EVP_MAX_KEY_LENGTH> folded_key;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <CompatibilityMode compatibility_mode>
|
|
|
|
inline void validateCipherMode(const EVP_CIPHER * evp_cipher)
|
|
|
|
{
|
|
|
|
if constexpr (compatibility_mode == CompatibilityMode::MySQL)
|
|
|
|
{
|
|
|
|
switch (EVP_CIPHER_mode(evp_cipher))
|
|
|
|
{
|
|
|
|
case EVP_CIPH_ECB_MODE: [[fallthrough]];
|
|
|
|
case EVP_CIPH_CBC_MODE: [[fallthrough]];
|
|
|
|
case EVP_CIPH_CFB_MODE: [[fallthrough]];
|
|
|
|
case EVP_CIPH_OFB_MODE:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if constexpr (compatibility_mode == CompatibilityMode::OpenSSL)
|
|
|
|
{
|
|
|
|
switch (EVP_CIPHER_mode(evp_cipher))
|
|
|
|
{
|
|
|
|
case EVP_CIPH_ECB_MODE: [[fallthrough]];
|
|
|
|
case EVP_CIPH_CBC_MODE: [[fallthrough]];
|
|
|
|
case EVP_CIPH_CFB_MODE: [[fallthrough]];
|
|
|
|
case EVP_CIPH_OFB_MODE: [[fallthrough]];
|
|
|
|
case EVP_CIPH_CTR_MODE: [[fallthrough]];
|
|
|
|
case EVP_CIPH_GCM_MODE:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-30 07:01:55 +00:00
|
|
|
throw DB::Exception("Unsupported cipher mode", DB::ErrorCodes::BAD_ARGUMENTS);
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <CipherMode mode>
|
2022-07-15 11:15:46 +00:00
|
|
|
inline void validateIV(StringRef iv_value, const size_t cipher_iv_size)
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
{
|
|
|
|
// In MySQL mode we don't care if IV is longer than expected, only if shorter.
|
|
|
|
if ((mode == CipherMode::MySQLCompatibility && iv_value.size != 0 && iv_value.size < cipher_iv_size)
|
|
|
|
|| (mode == CipherMode::OpenSSLCompatibility && iv_value.size != 0 && iv_value.size != cipher_iv_size))
|
|
|
|
throw DB::Exception(fmt::format("Invalid IV size: {} expected {}", iv_value.size, cipher_iv_size),
|
|
|
|
DB::ErrorCodes::BAD_ARGUMENTS);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
template <typename Impl>
|
|
|
|
class FunctionEncrypt : public IFunction
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
static constexpr OpenSSLDetails::CompatibilityMode compatibility_mode = Impl::compatibility_mode;
|
|
|
|
static constexpr auto name = Impl::name;
|
2021-06-01 12:20:52 +00:00
|
|
|
static FunctionPtr create(ContextPtr) { return std::make_shared<FunctionEncrypt>(); }
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
using CipherMode = OpenSSLDetails::CipherMode;
|
|
|
|
|
|
|
|
String getName() const override { return name; }
|
|
|
|
bool isVariadic() const override { return true; }
|
2021-06-22 16:21:23 +00:00
|
|
|
bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return true; }
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
size_t getNumberOfArguments() const override { return 0; }
|
2020-08-17 14:49:21 +00:00
|
|
|
ColumnNumbers getArgumentsThatAreAlwaysConstant() const override { return {0}; }
|
|
|
|
bool useDefaultImplementationForConstants() const override { return true; }
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
|
|
|
|
DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override
|
|
|
|
{
|
|
|
|
auto optional_args = FunctionArgumentDescriptors{
|
2021-09-30 11:35:24 +00:00
|
|
|
{"IV", &isStringOrFixedString<IDataType>, nullptr, "Initialization vector binary string"},
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
if constexpr (compatibility_mode == OpenSSLDetails::CompatibilityMode::OpenSSL)
|
|
|
|
{
|
|
|
|
optional_args.emplace_back(FunctionArgumentDescriptor{
|
2021-09-30 11:35:24 +00:00
|
|
|
"AAD", &isStringOrFixedString<IDataType>, nullptr, "Additional authenticated data binary string for GCM mode"
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
validateFunctionArgumentTypes(*this, arguments,
|
|
|
|
FunctionArgumentDescriptors{
|
2021-09-30 11:35:24 +00:00
|
|
|
{"mode", &isStringOrFixedString<IDataType>, isColumnConst, "encryption mode string"},
|
2022-08-14 02:28:30 +00:00
|
|
|
{"input", &isStringOrFixedString<IDataType>, {}, "plaintext"},
|
|
|
|
{"key", &isStringOrFixedString<IDataType>, {}, "encryption key binary string"},
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
},
|
|
|
|
optional_args
|
|
|
|
);
|
|
|
|
|
|
|
|
return std::make_shared<DataTypeString>();
|
|
|
|
}
|
|
|
|
|
2020-11-17 13:24:45 +00:00
|
|
|
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t input_rows_count) const override
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
{
|
|
|
|
using namespace OpenSSLDetails;
|
|
|
|
|
2020-10-21 06:22:20 +00:00
|
|
|
const auto mode = arguments[0].column->getDataAt(0);
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
|
2022-07-17 15:22:12 +00:00
|
|
|
if (mode.size == 0 || !mode.toView().starts_with("aes-"))
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
throw Exception("Invalid mode: " + mode.toString(), ErrorCodes::BAD_ARGUMENTS);
|
|
|
|
|
2020-10-21 06:22:20 +00:00
|
|
|
const auto * evp_cipher = getCipherByName(mode);
|
2020-09-08 13:28:52 +00:00
|
|
|
if (evp_cipher == nullptr)
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
throw Exception("Invalid mode: " + mode.toString(), ErrorCodes::BAD_ARGUMENTS);
|
|
|
|
|
|
|
|
const auto cipher_mode = EVP_CIPHER_mode(evp_cipher);
|
|
|
|
|
2020-10-21 06:22:20 +00:00
|
|
|
const auto input_column = arguments[1].column;
|
|
|
|
const auto key_column = arguments[2].column;
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
|
|
|
|
OpenSSLDetails::validateCipherMode<compatibility_mode>(evp_cipher);
|
|
|
|
|
|
|
|
ColumnPtr result_column;
|
|
|
|
if (arguments.size() <= 3)
|
|
|
|
result_column = doEncrypt(evp_cipher, input_rows_count, input_column, key_column, nullptr, nullptr);
|
|
|
|
else
|
|
|
|
{
|
2020-10-21 06:22:20 +00:00
|
|
|
const auto iv_column = arguments[3].column;
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
if (compatibility_mode != OpenSSLDetails::CompatibilityMode::MySQL && EVP_CIPHER_iv_length(evp_cipher) == 0)
|
|
|
|
throw Exception(mode.toString() + " does not support IV", ErrorCodes::BAD_ARGUMENTS);
|
|
|
|
|
|
|
|
if (arguments.size() <= 4)
|
|
|
|
{
|
|
|
|
result_column = doEncrypt(evp_cipher, input_rows_count, input_column, key_column, iv_column, nullptr);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (cipher_mode != EVP_CIPH_GCM_MODE)
|
|
|
|
throw Exception("AAD can be only set for GCM-mode", ErrorCodes::BAD_ARGUMENTS);
|
|
|
|
|
2020-10-21 06:22:20 +00:00
|
|
|
const auto aad_column = arguments[4].column;
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
result_column = doEncrypt(evp_cipher, input_rows_count, input_column, key_column, iv_column, aad_column);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-21 06:22:20 +00:00
|
|
|
return result_column;
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
}
|
|
|
|
|
2021-01-22 21:48:03 +00:00
|
|
|
static ColumnPtr doEncrypt(
|
|
|
|
const EVP_CIPHER * evp_cipher,
|
|
|
|
size_t input_rows_count,
|
|
|
|
const ColumnPtr & input_column,
|
|
|
|
const ColumnPtr & key_column,
|
|
|
|
const ColumnPtr & iv_column,
|
|
|
|
const ColumnPtr & aad_column)
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
{
|
|
|
|
if constexpr (compatibility_mode == OpenSSLDetails::CompatibilityMode::MySQL)
|
|
|
|
{
|
|
|
|
return doEncryptImpl<CipherMode::MySQLCompatibility>(evp_cipher, input_rows_count, input_column, key_column, iv_column, aad_column);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (EVP_CIPHER_mode(evp_cipher) == EVP_CIPH_GCM_MODE)
|
|
|
|
{
|
|
|
|
return doEncryptImpl<CipherMode::RFC5116_AEAD_AES_GCM>(evp_cipher, input_rows_count, input_column, key_column, iv_column, aad_column);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return doEncryptImpl<CipherMode::OpenSSLCompatibility>(evp_cipher, input_rows_count, input_column, key_column, iv_column, aad_column);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2021-01-22 21:48:03 +00:00
|
|
|
template <CipherMode mode>
|
|
|
|
static ColumnPtr doEncryptImpl(
|
|
|
|
const EVP_CIPHER * evp_cipher,
|
|
|
|
size_t input_rows_count,
|
|
|
|
const ColumnPtr & input_column,
|
|
|
|
const ColumnPtr & key_column,
|
|
|
|
[[maybe_unused]] const ColumnPtr & iv_column,
|
|
|
|
[[maybe_unused]] const ColumnPtr & aad_column)
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
{
|
|
|
|
using namespace OpenSSLDetails;
|
|
|
|
|
|
|
|
auto evp_ctx_ptr = std::unique_ptr<EVP_CIPHER_CTX, decltype(&::EVP_CIPHER_CTX_free)>(EVP_CIPHER_CTX_new(), &EVP_CIPHER_CTX_free);
|
2020-10-21 06:22:20 +00:00
|
|
|
auto * evp_ctx = evp_ctx_ptr.get();
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
|
|
|
|
const auto block_size = static_cast<size_t>(EVP_CIPHER_block_size(evp_cipher));
|
|
|
|
const auto key_size = static_cast<size_t>(EVP_CIPHER_key_length(evp_cipher));
|
|
|
|
[[maybe_unused]] const auto iv_size = static_cast<size_t>(EVP_CIPHER_iv_length(evp_cipher));
|
|
|
|
const auto tag_size = 16; // https://tools.ietf.org/html/rfc5116#section-5.1
|
|
|
|
|
|
|
|
auto encrypted_result_column = ColumnString::create();
|
|
|
|
auto & encrypted_result_column_data = encrypted_result_column->getChars();
|
|
|
|
auto & encrypted_result_column_offsets = encrypted_result_column->getOffsets();
|
|
|
|
|
|
|
|
{
|
|
|
|
size_t resulting_size = 0;
|
|
|
|
// for modes with block_size > 1, plaintext is padded up to a block_size,
|
|
|
|
// which may result in allocating to much for block_size = 1.
|
|
|
|
// That may lead later to reading unallocated data from underlying PaddedPODArray
|
|
|
|
// due to assumption that it is safe to read up to 15 bytes past end.
|
|
|
|
const auto pad_to_next_block = block_size == 1 ? 0 : 1;
|
2021-11-24 13:46:20 +00:00
|
|
|
for (size_t row_idx = 0; row_idx < input_rows_count; ++row_idx)
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
{
|
2021-11-24 13:46:20 +00:00
|
|
|
resulting_size += (input_column->getDataAt(row_idx).size / block_size + pad_to_next_block) * block_size + 1;
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
if constexpr (mode == CipherMode::RFC5116_AEAD_AES_GCM)
|
|
|
|
resulting_size += tag_size;
|
|
|
|
}
|
|
|
|
encrypted_result_column_data.resize(resulting_size);
|
|
|
|
}
|
|
|
|
|
2020-10-21 06:22:20 +00:00
|
|
|
auto * encrypted = encrypted_result_column_data.data();
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
|
|
|
|
KeyHolder<mode> key_holder;
|
|
|
|
|
2021-11-24 13:46:20 +00:00
|
|
|
for (size_t row_idx = 0; row_idx < input_rows_count; ++row_idx)
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
{
|
2021-11-24 13:46:20 +00:00
|
|
|
const auto key_value = key_holder.setKey(key_size, key_column->getDataAt(row_idx));
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
auto iv_value = StringRef{};
|
2021-01-22 21:48:03 +00:00
|
|
|
if (iv_column)
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
{
|
2021-11-24 13:46:20 +00:00
|
|
|
iv_value = iv_column->getDataAt(row_idx);
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
|
2021-01-22 01:08:10 +00:00
|
|
|
/// If the length is zero (empty string is passed) it should be treat as no IV.
|
|
|
|
if (iv_value.size == 0)
|
|
|
|
iv_value.data = nullptr;
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
}
|
|
|
|
|
2021-11-24 13:46:20 +00:00
|
|
|
const StringRef input_value = input_column->getDataAt(row_idx);
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
|
2020-10-13 14:49:03 +00:00
|
|
|
if constexpr (mode != CipherMode::MySQLCompatibility)
|
|
|
|
{
|
2020-10-17 16:48:22 +00:00
|
|
|
// in GCM mode IV can be of arbitrary size (>0), IV is optional for other modes.
|
|
|
|
if (mode == CipherMode::RFC5116_AEAD_AES_GCM && iv_value.size == 0)
|
2020-10-13 14:49:03 +00:00
|
|
|
{
|
|
|
|
throw Exception("Invalid IV size " + std::to_string(iv_value.size) + " != expected size " + std::to_string(iv_size),
|
|
|
|
DB::ErrorCodes::BAD_ARGUMENTS);
|
|
|
|
}
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
|
2020-10-17 16:48:22 +00:00
|
|
|
if (mode != CipherMode::RFC5116_AEAD_AES_GCM && key_value.size != key_size)
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
{
|
2020-10-13 14:49:03 +00:00
|
|
|
throw Exception("Invalid key size " + std::to_string(key_value.size) + " != expected size " + std::to_string(key_size),
|
|
|
|
DB::ErrorCodes::BAD_ARGUMENTS);
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
}
|
|
|
|
}
|
2020-10-13 14:49:03 +00:00
|
|
|
|
|
|
|
// Avoid extra work on empty ciphertext/plaintext for some ciphers
|
|
|
|
if (!(input_value.size == 0 && block_size == 1 && mode != CipherMode::RFC5116_AEAD_AES_GCM))
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
{
|
2020-10-13 14:49:03 +00:00
|
|
|
// 1: Init CTX
|
|
|
|
if constexpr (mode == CipherMode::RFC5116_AEAD_AES_GCM)
|
|
|
|
{
|
|
|
|
// 1.a.1: Init CTX with custom IV length and optionally with AAD
|
|
|
|
if (EVP_EncryptInit_ex(evp_ctx, evp_cipher, nullptr, nullptr, nullptr) != 1)
|
|
|
|
onError("Failed to initialize encryption context with cipher");
|
|
|
|
|
|
|
|
if (EVP_CIPHER_CTX_ctrl(evp_ctx, EVP_CTRL_AEAD_SET_IVLEN, iv_value.size, nullptr) != 1)
|
|
|
|
onError("Failed to set custom IV length to " + std::to_string(iv_value.size));
|
|
|
|
|
|
|
|
if (EVP_EncryptInit_ex(evp_ctx, nullptr, nullptr,
|
|
|
|
reinterpret_cast<const unsigned char*>(key_value.data),
|
|
|
|
reinterpret_cast<const unsigned char*>(iv_value.data)) != 1)
|
|
|
|
onError("Failed to set key and IV");
|
|
|
|
|
|
|
|
// 1.a.2 Set AAD
|
2021-01-22 21:48:03 +00:00
|
|
|
if (aad_column)
|
2020-10-13 14:49:03 +00:00
|
|
|
{
|
2021-11-24 13:46:20 +00:00
|
|
|
const auto aad_data = aad_column->getDataAt(row_idx);
|
2020-10-13 14:49:03 +00:00
|
|
|
int tmp_len = 0;
|
|
|
|
if (aad_data.size != 0 && EVP_EncryptUpdate(evp_ctx, nullptr, &tmp_len,
|
|
|
|
reinterpret_cast<const unsigned char *>(aad_data.data), aad_data.size) != 1)
|
|
|
|
onError("Failed to set AAD data");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// 1.b: Init CTX
|
|
|
|
validateIV<mode>(iv_value, iv_size);
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
|
2020-10-13 14:49:03 +00:00
|
|
|
if (EVP_EncryptInit_ex(evp_ctx, evp_cipher, nullptr,
|
|
|
|
reinterpret_cast<const unsigned char*>(key_value.data),
|
|
|
|
reinterpret_cast<const unsigned char*>(iv_value.data)) != 1)
|
|
|
|
onError("Failed to initialize cipher context");
|
|
|
|
}
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
|
2020-10-13 14:49:03 +00:00
|
|
|
int output_len = 0;
|
|
|
|
// 2: Feed the data to the cipher
|
|
|
|
if (EVP_EncryptUpdate(evp_ctx,
|
|
|
|
reinterpret_cast<unsigned char*>(encrypted), &output_len,
|
|
|
|
reinterpret_cast<const unsigned char*>(input_value.data), static_cast<int>(input_value.size)) != 1)
|
|
|
|
onError("Failed to encrypt");
|
|
|
|
encrypted += output_len;
|
|
|
|
|
|
|
|
// 3: retrieve encrypted data (ciphertext)
|
|
|
|
if (EVP_EncryptFinal_ex(evp_ctx,
|
|
|
|
reinterpret_cast<unsigned char*>(encrypted), &output_len) != 1)
|
|
|
|
onError("Failed to fetch ciphertext");
|
|
|
|
encrypted += output_len;
|
|
|
|
|
|
|
|
// 4: optionally retrieve a tag and append it to the ciphertext (RFC5116):
|
|
|
|
// https://tools.ietf.org/html/rfc5116#section-5.1
|
|
|
|
if constexpr (mode == CipherMode::RFC5116_AEAD_AES_GCM)
|
|
|
|
{
|
|
|
|
if (EVP_CIPHER_CTX_ctrl(evp_ctx, EVP_CTRL_AEAD_GET_TAG, tag_size, encrypted) != 1)
|
|
|
|
onError("Failed to retrieve GCM tag");
|
|
|
|
encrypted += tag_size;
|
|
|
|
}
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
}
|
2020-10-13 14:49:03 +00:00
|
|
|
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
*encrypted = '\0';
|
|
|
|
++encrypted;
|
|
|
|
|
|
|
|
encrypted_result_column_offsets.push_back(encrypted - encrypted_result_column_data.data());
|
|
|
|
}
|
|
|
|
|
|
|
|
// in case of block size of 1, we overestimate buffer required for encrypted data, fix it up.
|
|
|
|
if (!encrypted_result_column_offsets.empty() && encrypted_result_column_data.size() > encrypted_result_column_offsets.back())
|
|
|
|
{
|
|
|
|
encrypted_result_column_data.resize(encrypted_result_column_offsets.back());
|
|
|
|
}
|
|
|
|
|
|
|
|
encrypted_result_column->validate();
|
|
|
|
return encrypted_result_column;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2021-11-24 20:09:50 +00:00
|
|
|
/// decrypt(string, key, block_mode[, init_vector])
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
template <typename Impl>
|
|
|
|
class FunctionDecrypt : public IFunction
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
static constexpr OpenSSLDetails::CompatibilityMode compatibility_mode = Impl::compatibility_mode;
|
|
|
|
static constexpr auto name = Impl::name;
|
2021-06-01 12:20:52 +00:00
|
|
|
static FunctionPtr create(ContextPtr) { return std::make_shared<FunctionDecrypt>(); }
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
using CipherMode = OpenSSLDetails::CipherMode;
|
|
|
|
|
|
|
|
String getName() const override { return name; }
|
|
|
|
bool isVariadic() const override { return true; }
|
2021-06-22 16:21:23 +00:00
|
|
|
bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return true; }
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
size_t getNumberOfArguments() const override { return 0; }
|
2020-08-17 14:49:21 +00:00
|
|
|
ColumnNumbers getArgumentsThatAreAlwaysConstant() const override { return {0}; }
|
|
|
|
bool useDefaultImplementationForConstants() const override { return true; }
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
|
|
|
|
DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override
|
|
|
|
{
|
|
|
|
auto optional_args = FunctionArgumentDescriptors{
|
2021-09-30 11:35:24 +00:00
|
|
|
{"IV", &isStringOrFixedString<IDataType>, nullptr, "Initialization vector binary string"},
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
if constexpr (compatibility_mode == OpenSSLDetails::CompatibilityMode::OpenSSL)
|
|
|
|
{
|
|
|
|
optional_args.emplace_back(FunctionArgumentDescriptor{
|
2021-09-30 11:35:24 +00:00
|
|
|
"AAD", &isStringOrFixedString<IDataType>, nullptr, "Additional authenticated data binary string for GCM mode"
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
validateFunctionArgumentTypes(*this, arguments,
|
|
|
|
FunctionArgumentDescriptors{
|
2021-09-30 11:35:24 +00:00
|
|
|
{"mode", &isStringOrFixedString<IDataType>, isColumnConst, "decryption mode string"},
|
2022-08-14 02:28:30 +00:00
|
|
|
{"input", &isStringOrFixedString<IDataType>, {}, "ciphertext"},
|
|
|
|
{"key", &isStringOrFixedString<IDataType>, {}, "decryption key binary string"},
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
},
|
|
|
|
optional_args
|
|
|
|
);
|
|
|
|
|
|
|
|
return std::make_shared<DataTypeString>();
|
|
|
|
}
|
|
|
|
|
2020-11-17 13:24:45 +00:00
|
|
|
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t input_rows_count) const override
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
{
|
|
|
|
using namespace OpenSSLDetails;
|
|
|
|
|
2020-10-21 06:22:20 +00:00
|
|
|
const auto mode = arguments[0].column->getDataAt(0);
|
2022-07-17 15:22:12 +00:00
|
|
|
if (mode.size == 0 || !mode.toView().starts_with("aes-"))
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
throw Exception("Invalid mode: " + mode.toString(), ErrorCodes::BAD_ARGUMENTS);
|
|
|
|
|
2020-10-21 06:22:20 +00:00
|
|
|
const auto * evp_cipher = getCipherByName(mode);
|
2020-09-08 13:28:52 +00:00
|
|
|
if (evp_cipher == nullptr)
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
throw Exception("Invalid mode: " + mode.toString(), ErrorCodes::BAD_ARGUMENTS);
|
|
|
|
|
|
|
|
OpenSSLDetails::validateCipherMode<compatibility_mode>(evp_cipher);
|
|
|
|
|
2020-10-21 06:22:20 +00:00
|
|
|
const auto input_column = arguments[1].column;
|
|
|
|
const auto key_column = arguments[2].column;
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
|
|
|
|
ColumnPtr result_column;
|
|
|
|
if (arguments.size() <= 3)
|
2021-11-24 20:09:50 +00:00
|
|
|
{
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
result_column = doDecrypt(evp_cipher, input_rows_count, input_column, key_column, nullptr, nullptr);
|
2021-11-24 20:09:50 +00:00
|
|
|
}
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
else
|
|
|
|
{
|
2020-10-21 06:22:20 +00:00
|
|
|
const auto iv_column = arguments[3].column;
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
if (compatibility_mode != OpenSSLDetails::CompatibilityMode::MySQL && EVP_CIPHER_iv_length(evp_cipher) == 0)
|
|
|
|
throw Exception(mode.toString() + " does not support IV", ErrorCodes::BAD_ARGUMENTS);
|
|
|
|
|
|
|
|
if (arguments.size() <= 4)
|
|
|
|
{
|
|
|
|
result_column = doDecrypt(evp_cipher, input_rows_count, input_column, key_column, iv_column, nullptr);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (EVP_CIPHER_mode(evp_cipher) != EVP_CIPH_GCM_MODE)
|
|
|
|
throw Exception("AAD can be only set for GCM-mode", ErrorCodes::BAD_ARGUMENTS);
|
|
|
|
|
2020-10-21 06:22:20 +00:00
|
|
|
const auto aad_column = arguments[4].column;
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
result_column = doDecrypt(evp_cipher, input_rows_count, input_column, key_column, iv_column, aad_column);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-21 06:22:20 +00:00
|
|
|
return result_column;
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
}
|
|
|
|
|
2021-01-22 21:48:03 +00:00
|
|
|
static ColumnPtr doDecrypt(
|
|
|
|
const EVP_CIPHER * evp_cipher,
|
|
|
|
size_t input_rows_count,
|
|
|
|
const ColumnPtr & input_column,
|
|
|
|
const ColumnPtr & key_column,
|
|
|
|
const ColumnPtr & iv_column,
|
|
|
|
const ColumnPtr & aad_column)
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
{
|
|
|
|
if constexpr (compatibility_mode == OpenSSLDetails::CompatibilityMode::MySQL)
|
|
|
|
{
|
|
|
|
return doDecryptImpl<CipherMode::MySQLCompatibility>(evp_cipher, input_rows_count, input_column, key_column, iv_column, aad_column);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
const auto cipher_mode = EVP_CIPHER_mode(evp_cipher);
|
|
|
|
if (cipher_mode == EVP_CIPH_GCM_MODE)
|
|
|
|
{
|
|
|
|
return doDecryptImpl<CipherMode::RFC5116_AEAD_AES_GCM>(evp_cipher, input_rows_count, input_column, key_column, iv_column, aad_column);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return doDecryptImpl<CipherMode::OpenSSLCompatibility>(evp_cipher, input_rows_count, input_column, key_column, iv_column, aad_column);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2021-01-22 21:48:03 +00:00
|
|
|
template <CipherMode mode>
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
static ColumnPtr doDecryptImpl(const EVP_CIPHER * evp_cipher,
|
2021-01-22 21:48:03 +00:00
|
|
|
size_t input_rows_count,
|
|
|
|
const ColumnPtr & input_column,
|
|
|
|
const ColumnPtr & key_column,
|
|
|
|
[[maybe_unused]] const ColumnPtr & iv_column,
|
|
|
|
[[maybe_unused]] const ColumnPtr & aad_column)
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
{
|
|
|
|
using namespace OpenSSLDetails;
|
|
|
|
|
|
|
|
auto evp_ctx_ptr = std::unique_ptr<EVP_CIPHER_CTX, decltype(&::EVP_CIPHER_CTX_free)>(EVP_CIPHER_CTX_new(), &EVP_CIPHER_CTX_free);
|
2020-10-21 06:22:20 +00:00
|
|
|
auto * evp_ctx = evp_ctx_ptr.get();
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
|
|
|
|
[[maybe_unused]] const auto block_size = static_cast<size_t>(EVP_CIPHER_block_size(evp_cipher));
|
|
|
|
[[maybe_unused]] const auto iv_size = static_cast<size_t>(EVP_CIPHER_iv_length(evp_cipher));
|
2021-03-24 00:34:30 +00:00
|
|
|
|
|
|
|
const size_t key_size = static_cast<size_t>(EVP_CIPHER_key_length(evp_cipher));
|
|
|
|
static constexpr size_t tag_size = 16; // https://tools.ietf.org/html/rfc5116#section-5.1
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
|
|
|
|
auto decrypted_result_column = ColumnString::create();
|
|
|
|
auto & decrypted_result_column_data = decrypted_result_column->getChars();
|
|
|
|
auto & decrypted_result_column_offsets = decrypted_result_column->getOffsets();
|
|
|
|
|
|
|
|
{
|
|
|
|
size_t resulting_size = 0;
|
2021-11-24 13:46:20 +00:00
|
|
|
for (size_t row_idx = 0; row_idx < input_rows_count; ++row_idx)
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
{
|
2021-11-24 13:46:20 +00:00
|
|
|
size_t string_size = input_column->getDataAt(row_idx).size;
|
2021-03-24 00:34:30 +00:00
|
|
|
resulting_size += string_size + 1; /// With terminating zero.
|
|
|
|
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
if constexpr (mode == CipherMode::RFC5116_AEAD_AES_GCM)
|
2021-03-24 00:34:30 +00:00
|
|
|
{
|
2021-11-28 04:18:00 +00:00
|
|
|
if (string_size > 0)
|
|
|
|
{
|
|
|
|
if (string_size < tag_size)
|
|
|
|
throw Exception("Encrypted data is smaller than the size of additional data for AEAD mode, cannot decrypt.",
|
|
|
|
ErrorCodes::BAD_ARGUMENTS);
|
2021-03-24 00:34:30 +00:00
|
|
|
|
2021-11-28 04:18:00 +00:00
|
|
|
resulting_size -= tag_size;
|
|
|
|
}
|
2021-03-24 00:34:30 +00:00
|
|
|
}
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
decrypted_result_column_data.resize(resulting_size);
|
|
|
|
}
|
2021-03-24 00:34:30 +00:00
|
|
|
|
2020-10-21 06:22:20 +00:00
|
|
|
auto * decrypted = decrypted_result_column_data.data();
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
|
|
|
|
KeyHolder<mode> key_holder;
|
2021-11-24 13:46:20 +00:00
|
|
|
for (size_t row_idx = 0; row_idx < input_rows_count; ++row_idx)
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
{
|
|
|
|
// 0: prepare key if required
|
2021-11-24 13:46:20 +00:00
|
|
|
auto key_value = key_holder.setKey(key_size, key_column->getDataAt(row_idx));
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
auto iv_value = StringRef{};
|
2021-01-22 21:48:03 +00:00
|
|
|
if (iv_column)
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
{
|
2021-11-24 13:46:20 +00:00
|
|
|
iv_value = iv_column->getDataAt(row_idx);
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
|
2021-01-22 01:08:10 +00:00
|
|
|
/// If the length is zero (empty string is passed) it should be treat as no IV.
|
|
|
|
if (iv_value.size == 0)
|
|
|
|
iv_value.data = nullptr;
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
}
|
|
|
|
|
2021-11-24 13:46:20 +00:00
|
|
|
auto input_value = input_column->getDataAt(row_idx);
|
2021-11-24 20:09:50 +00:00
|
|
|
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
if constexpr (mode == CipherMode::RFC5116_AEAD_AES_GCM)
|
|
|
|
{
|
2021-11-24 20:09:50 +00:00
|
|
|
if (input_value.size > 0)
|
|
|
|
{
|
|
|
|
// empty plaintext results in empty ciphertext + tag, means there should be at least tag_size bytes.
|
|
|
|
if (input_value.size < tag_size)
|
|
|
|
throw Exception(fmt::format("Encrypted data is too short: only {} bytes, "
|
|
|
|
"should contain at least {} bytes of a tag.",
|
|
|
|
input_value.size, block_size, tag_size), ErrorCodes::BAD_ARGUMENTS);
|
2021-11-28 04:18:00 +00:00
|
|
|
|
2021-11-24 20:09:50 +00:00
|
|
|
input_value.size -= tag_size;
|
|
|
|
}
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
}
|
|
|
|
|
2020-10-17 16:48:22 +00:00
|
|
|
if constexpr (mode != CipherMode::MySQLCompatibility)
|
|
|
|
{
|
|
|
|
// in GCM mode IV can be of arbitrary size (>0), for other modes IV is optional.
|
|
|
|
if (mode == CipherMode::RFC5116_AEAD_AES_GCM && iv_value.size == 0)
|
|
|
|
{
|
|
|
|
throw Exception("Invalid IV size " + std::to_string(iv_value.size) + " != expected size " + std::to_string(iv_size),
|
|
|
|
DB::ErrorCodes::BAD_ARGUMENTS);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (key_value.size != key_size)
|
|
|
|
{
|
|
|
|
throw Exception("Invalid key size " + std::to_string(key_value.size) + " != expected size " + std::to_string(key_size),
|
|
|
|
DB::ErrorCodes::BAD_ARGUMENTS);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-24 13:46:20 +00:00
|
|
|
/// Avoid extra work on empty ciphertext/plaintext. Always decrypt empty to empty.
|
|
|
|
/// This makes sense for default implementation for NULLs.
|
|
|
|
if (input_value.size > 0)
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
{
|
2020-10-13 14:49:03 +00:00
|
|
|
// 1: Init CTX
|
|
|
|
if constexpr (mode == CipherMode::RFC5116_AEAD_AES_GCM)
|
|
|
|
{
|
|
|
|
if (EVP_DecryptInit_ex(evp_ctx, evp_cipher, nullptr, nullptr, nullptr) != 1)
|
|
|
|
onError("Failed to initialize cipher context 1");
|
|
|
|
|
|
|
|
// 1.a.1 : Set custom IV length
|
|
|
|
if (EVP_CIPHER_CTX_ctrl(evp_ctx, EVP_CTRL_AEAD_SET_IVLEN, iv_value.size, nullptr) != 1)
|
|
|
|
onError("Failed to set custom IV length to " + std::to_string(iv_value.size));
|
|
|
|
|
|
|
|
// 1.a.1 : Init CTX with key and IV
|
|
|
|
if (EVP_DecryptInit_ex(evp_ctx, nullptr, nullptr,
|
|
|
|
reinterpret_cast<const unsigned char*>(key_value.data),
|
|
|
|
reinterpret_cast<const unsigned char*>(iv_value.data)) != 1)
|
|
|
|
onError("Failed to set key and IV");
|
|
|
|
|
|
|
|
// 1.a.2: Set AAD if present
|
2021-01-22 21:48:03 +00:00
|
|
|
if (aad_column)
|
2020-10-13 14:49:03 +00:00
|
|
|
{
|
2021-11-24 13:46:20 +00:00
|
|
|
StringRef aad_data = aad_column->getDataAt(row_idx);
|
2020-10-13 14:49:03 +00:00
|
|
|
int tmp_len = 0;
|
|
|
|
if (aad_data.size != 0 && EVP_DecryptUpdate(evp_ctx, nullptr, &tmp_len,
|
|
|
|
reinterpret_cast<const unsigned char *>(aad_data.data), aad_data.size) != 1)
|
|
|
|
onError("Failed to sed AAD data");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// 1.b: Init CTX
|
|
|
|
validateIV<mode>(iv_value, iv_size);
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
|
2020-10-13 14:49:03 +00:00
|
|
|
if (EVP_DecryptInit_ex(evp_ctx, evp_cipher, nullptr,
|
|
|
|
reinterpret_cast<const unsigned char*>(key_value.data),
|
|
|
|
reinterpret_cast<const unsigned char*>(iv_value.data)) != 1)
|
|
|
|
onError("Failed to initialize cipher context");
|
|
|
|
}
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
|
2020-10-13 14:49:03 +00:00
|
|
|
// 2: Feed the data to the cipher
|
|
|
|
int output_len = 0;
|
|
|
|
if (EVP_DecryptUpdate(evp_ctx,
|
|
|
|
reinterpret_cast<unsigned char*>(decrypted), &output_len,
|
|
|
|
reinterpret_cast<const unsigned char*>(input_value.data), static_cast<int>(input_value.size)) != 1)
|
|
|
|
onError("Failed to decrypt");
|
|
|
|
decrypted += output_len;
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
|
2020-10-13 14:49:03 +00:00
|
|
|
// 3: optionally get tag from the ciphertext (RFC5116) and feed it to the context
|
|
|
|
if constexpr (mode == CipherMode::RFC5116_AEAD_AES_GCM)
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
{
|
2020-10-13 14:49:03 +00:00
|
|
|
void * tag = const_cast<void *>(reinterpret_cast<const void *>(input_value.data + input_value.size));
|
|
|
|
if (EVP_CIPHER_CTX_ctrl(evp_ctx, EVP_CTRL_AEAD_SET_TAG, tag_size, tag) != 1)
|
|
|
|
onError("Failed to set tag");
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
}
|
|
|
|
|
2020-10-13 14:49:03 +00:00
|
|
|
// 4: retrieve encrypted data (ciphertext)
|
|
|
|
if (EVP_DecryptFinal_ex(evp_ctx,
|
|
|
|
reinterpret_cast<unsigned char*>(decrypted), &output_len) != 1)
|
|
|
|
onError("Failed to decrypt");
|
|
|
|
decrypted += output_len;
|
encrypt, aes_encrypt_mysql, decrypt, aes_decrypt_mysql functions
Functions to encrypt/decrypt any input data with OpenSSL's ciphers
with custom key, iv, and add (-gcm mode only).
_mysql versions are 100% compatitable with corresponding MySQL functions
Supported modes depend on OpenSSL version, but generally are:
aes-{128,192,56}-{ecb,cbc,cfb1,cfb8,cfb128,ofb,gcm}
Please note that in a -gcm mode a 16-byte tag is appended to the ciphertext
on encryption and is expected to be found at the end of ciphertext on decryption.
Added tests that verify compatibility with MySQL functions,
and test vectors for GCM mode from OpenSSL.
Added masking rules for aes_X funtions
Rules are installed by default to config.d/query_masking_rules.xml
2020-06-16 09:22:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
*decrypted = '\0';
|
|
|
|
++decrypted;
|
|
|
|
|
|
|
|
decrypted_result_column_offsets.push_back(decrypted - decrypted_result_column_data.data());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// in case we overestimate buffer required for decrypted data, fix it up.
|
|
|
|
if (!decrypted_result_column_offsets.empty() && decrypted_result_column_data.size() > decrypted_result_column_offsets.back())
|
|
|
|
{
|
|
|
|
decrypted_result_column_data.resize(decrypted_result_column_offsets.back());
|
|
|
|
}
|
|
|
|
|
|
|
|
decrypted_result_column->validate();
|
|
|
|
return decrypted_result_column;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|