// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. #include #include #include #include #include #include #include #include #include "common/status.h" #include "util/encryption_util.h" #include "util/string_util.h" #include "vec/aggregate_functions/aggregate_function.h" #include "vec/columns/column.h" #include "vec/columns/column_nullable.h" #include "vec/columns/column_string.h" #include "vec/columns/column_vector.h" #include "vec/columns/columns_number.h" #include "vec/common/assert_cast.h" #include "vec/common/pod_array.h" #include "vec/core/block.h" #include "vec/core/column_numbers.h" #include "vec/core/column_with_type_and_name.h" #include "vec/core/types.h" #include "vec/data_types/data_type.h" #include "vec/data_types/data_type_nullable.h" #include "vec/data_types/data_type_string.h" #include "vec/functions/function.h" #include "vec/functions/function_string.h" #include "vec/functions/simple_function_factory.h" #include "vec/utils/util.hpp" namespace doris { class FunctionContext; } // namespace doris namespace doris::vectorized { inline StringCaseUnorderedMap aes_mode_map { {"AES_128_ECB", EncryptionMode::AES_128_ECB}, {"AES_192_ECB", EncryptionMode::AES_192_ECB}, {"AES_256_ECB", EncryptionMode::AES_256_ECB}, {"AES_128_CBC", EncryptionMode::AES_128_CBC}, {"AES_192_CBC", EncryptionMode::AES_192_CBC}, {"AES_256_CBC", EncryptionMode::AES_256_CBC}, {"AES_128_CFB", EncryptionMode::AES_128_CFB}, {"AES_192_CFB", EncryptionMode::AES_192_CFB}, {"AES_256_CFB", EncryptionMode::AES_256_CFB}, {"AES_128_CFB1", EncryptionMode::AES_128_CFB1}, {"AES_192_CFB1", EncryptionMode::AES_192_CFB1}, {"AES_256_CFB1", EncryptionMode::AES_256_CFB1}, {"AES_128_CFB8", EncryptionMode::AES_128_CFB8}, {"AES_192_CFB8", EncryptionMode::AES_192_CFB8}, {"AES_256_CFB8", EncryptionMode::AES_256_CFB8}, {"AES_128_CFB128", EncryptionMode::AES_128_CFB128}, {"AES_192_CFB128", EncryptionMode::AES_192_CFB128}, {"AES_256_CFB128", EncryptionMode::AES_256_CFB128}, {"AES_128_CTR", EncryptionMode::AES_128_CTR}, {"AES_192_CTR", EncryptionMode::AES_192_CTR}, {"AES_256_CTR", EncryptionMode::AES_256_CTR}, {"AES_128_OFB", EncryptionMode::AES_128_OFB}, {"AES_192_OFB", EncryptionMode::AES_192_OFB}, {"AES_256_OFB", EncryptionMode::AES_256_OFB}}; inline StringCaseUnorderedMap sm4_mode_map { {"SM4_128_ECB", EncryptionMode::SM4_128_ECB}, {"SM4_128_CBC", EncryptionMode::SM4_128_CBC}, {"SM4_128_CFB128", EncryptionMode::SM4_128_CFB128}, {"SM4_128_OFB", EncryptionMode::SM4_128_OFB}, {"SM4_128_CTR", EncryptionMode::SM4_128_CTR}}; template class FunctionEncryptionAndDecrypt : public IFunction { public: static constexpr auto name = FunctionName::name; String get_name() const override { return name; } static FunctionPtr create() { return std::make_shared(); } DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { return make_nullable(std::make_shared()); } DataTypes get_variadic_argument_types_impl() const override { return Impl::get_variadic_argument_types_impl(); } size_t get_number_of_arguments() const override { return get_variadic_argument_types_impl().size(); } bool use_default_implementation_for_nulls() const override { return false; } Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments, size_t result, size_t input_rows_count) const override { size_t argument_size = arguments.size(); ColumnPtr argument_columns[argument_size]; std::vector offsets_list(argument_size); std::vector chars_list(argument_size); auto result_null_map = ColumnUInt8::create(input_rows_count, 0); auto result_data_column = ColumnString::create(); auto& result_data = result_data_column->get_chars(); auto& result_offset = result_data_column->get_offsets(); result_offset.resize(input_rows_count); for (int i = 0; i < argument_size; ++i) { argument_columns[i] = block.get_by_position(arguments[i]).column->convert_to_full_column_if_const(); if (auto* nullable = check_and_get_column(*argument_columns[i])) { VectorizedUtils::update_null_map(result_null_map->get_data(), nullable->get_null_map_data()); argument_columns[i] = nullable->get_nested_column_ptr(); } } for (size_t i = 0; i < argument_size; ++i) { auto col_str = assert_cast(argument_columns[i].get()); offsets_list[i] = &col_str->get_offsets(); chars_list[i] = &col_str->get_chars(); } Impl::vector_vector(offsets_list, chars_list, input_rows_count, result_data, result_offset, result_null_map->get_data()); block.get_by_position(result).column = ColumnNullable::create(std::move(result_data_column), std::move(result_null_map)); return Status::OK(); } }; template void exectue_result(std::vector& offsets_list, std::vector& chars_list, size_t i, EncryptionMode& encryption_mode, const char* iv_raw, int iv_length, ColumnString::Chars& result_data, ColumnString::Offsets& result_offset, NullMap& null_map) { int src_size = (*offsets_list[0])[i] - (*offsets_list[0])[i - 1]; const auto src_raw = reinterpret_cast(&(*chars_list[0])[(*offsets_list[0])[i - 1]]); int key_size = (*offsets_list[1])[i] - (*offsets_list[1])[i - 1]; const auto key_raw = reinterpret_cast(&(*chars_list[1])[(*offsets_list[1])[i - 1]]); if (src_size == 0) { StringOP::push_null_string(i, result_data, result_offset, null_map); return; } int cipher_len = src_size; if constexpr (is_encrypt) { cipher_len += 16; } std::unique_ptr p; p.reset(new char[cipher_len]); int ret_code = 0; ret_code = Impl::exectue_impl(encryption_mode, (unsigned char*)src_raw, src_size, (unsigned char*)key_raw, key_size, iv_raw, iv_length, true, (unsigned char*)p.get()); if (ret_code < 0) { StringOP::push_null_string(i, result_data, result_offset, null_map); } else { StringOP::push_value_string(std::string_view(p.get(), ret_code), i, result_data, result_offset); } } template struct EncryptionAndDecryptTwoImpl { static DataTypes get_variadic_argument_types_impl() { return {std::make_shared(), std::make_shared(), std::make_shared()}; } static Status vector_vector(std::vector& offsets_list, std::vector& chars_list, size_t input_rows_count, ColumnString::Chars& result_data, ColumnString::Offsets& result_offset, NullMap& null_map) { for (int i = 0; i < input_rows_count; ++i) { if (null_map[i]) { StringOP::push_null_string(i, result_data, result_offset, null_map); continue; } EncryptionMode encryption_mode = mode; int mode_size = (*offsets_list[2])[i] - (*offsets_list[2])[i - 1]; const auto mode_raw = reinterpret_cast(&(*chars_list[2])[(*offsets_list[2])[i - 1]]); if (mode_size != 0) { std::string mode_str(mode_raw, mode_size); if (aes_mode_map.count(mode_str) == 0) { StringOP::push_null_string(i, result_data, result_offset, null_map); continue; } encryption_mode = aes_mode_map.at(mode_str); } exectue_result(offsets_list, chars_list, i, encryption_mode, nullptr, 0, result_data, result_offset, null_map); } return Status::OK(); } }; template struct EncryptionAndDecryptFourImpl { static DataTypes get_variadic_argument_types_impl() { return {std::make_shared(), std::make_shared(), std::make_shared(), std::make_shared()}; } static Status vector_vector(std::vector& offsets_list, std::vector& chars_list, size_t input_rows_count, ColumnString::Chars& result_data, ColumnString::Offsets& result_offset, NullMap& null_map) { for (int i = 0; i < input_rows_count; ++i) { if (null_map[i]) { StringOP::push_null_string(i, result_data, result_offset, null_map); continue; } EncryptionMode encryption_mode = mode; int mode_size = (*offsets_list[3])[i] - (*offsets_list[3])[i - 1]; int iv_size = (*offsets_list[2])[i] - (*offsets_list[2])[i - 1]; const auto mode_raw = reinterpret_cast(&(*chars_list[3])[(*offsets_list[3])[i - 1]]); const auto iv_raw = reinterpret_cast(&(*chars_list[2])[(*offsets_list[2])[i - 1]]); if (mode_size != 0) { std::string mode_str(mode_raw, mode_size); if constexpr (is_sm_mode) { if (sm4_mode_map.count(mode_str) == 0) { StringOP::push_null_string(i, result_data, result_offset, null_map); continue; } encryption_mode = sm4_mode_map.at(mode_str); } else { if (aes_mode_map.count(mode_str) == 0) { StringOP::push_null_string(i, result_data, result_offset, null_map); continue; } encryption_mode = aes_mode_map.at(mode_str); } } exectue_result(offsets_list, chars_list, i, encryption_mode, iv_raw, iv_size, result_data, result_offset, null_map); } return Status::OK(); } }; struct EncryptImpl { static int exectue_impl(EncryptionMode mode, const unsigned char* source, uint32_t source_length, const unsigned char* key, uint32_t key_length, const char* iv, int iv_length, bool padding, unsigned char* encrypt) { return EncryptionUtil::encrypt(mode, source, source_length, key, key_length, iv, iv_length, true, encrypt); } }; struct DecryptImpl { static int exectue_impl(EncryptionMode mode, const unsigned char* source, uint32_t source_length, const unsigned char* key, uint32_t key_length, const char* iv, int iv_length, bool padding, unsigned char* encrypt) { return EncryptionUtil::decrypt(mode, source, source_length, key, key_length, iv, iv_length, true, encrypt); } }; struct SM4EncryptName { static constexpr auto name = "sm4_encrypt"; }; struct SM4DecryptName { static constexpr auto name = "sm4_decrypt"; }; struct AESEncryptName { static constexpr auto name = "aes_encrypt"; }; struct AESDecryptName { static constexpr auto name = "aes_decrypt"; }; void register_function_encryption(SimpleFunctionFactory& factory) { factory.register_function, SM4EncryptName>>(); factory.register_function, SM4DecryptName>>(); factory.register_function, AESEncryptName>>(); factory.register_function, AESDecryptName>>(); factory.register_function, SM4EncryptName>>(); factory.register_function, SM4DecryptName>>(); factory.register_function, AESEncryptName>>(); factory.register_function, AESDecryptName>>(); } } // namespace doris::vectorized