diff --git a/src/observer/ob_server_reload_config.cpp b/src/observer/ob_server_reload_config.cpp index 5fc1d4a398..667b51e2a7 100644 --- a/src/observer/ob_server_reload_config.cpp +++ b/src/observer/ob_server_reload_config.cpp @@ -87,6 +87,7 @@ int ObServerReloadConfig::operator()() { int ret = OB_SUCCESS; int real_ret = ret; + if (!gctx_.is_inited()) { real_ret = ret = OB_INNER_STAT_ERROR; LOG_WARN("gctx not init", "gctx inited", gctx_.is_inited(), K(ret)); @@ -124,6 +125,10 @@ int ObServerReloadConfig::operator()() real_ret = ret; LOG_WARN("reload config for ratelimit manager fail", K(ret)); } + if (OB_FAIL(ObTdeEncryptEngineLoader::get_instance().reload_config())) { + real_ret = ret; + LOG_WARN("reload config for tde encrypt engine fail", K(ret)); + } } { GMEMCONF.reload_config(GCONF); diff --git a/src/share/config/ob_config_manager.cpp b/src/share/config/ob_config_manager.cpp index a1eec639c4..7f323c50f5 100644 --- a/src/share/config/ob_config_manager.cpp +++ b/src/share/config/ob_config_manager.cpp @@ -86,6 +86,8 @@ int ObConfigManager::reload_config() LOG_WARN("reload config for ratelimit manager fail", K(ret)); } else if (OB_FAIL(OBSERVER.get_net_frame().reload_mysql_login_thread_config())) { LOG_WARN("reload config for mysql login thread count failed", K(ret)); + } else if (OB_FAIL(ObTdeEncryptEngineLoader::get_instance().reload_config())) { + LOG_WARN("reload config for tde encrypt engine fail", K(ret)); } return ret; } diff --git a/src/share/ob_encryption_util.cpp b/src/share/ob_encryption_util.cpp index 5a53cd760b..c68035d205 100644 --- a/src/share/ob_encryption_util.cpp +++ b/src/share/ob_encryption_util.cpp @@ -18,8 +18,10 @@ #include "ob_encryption_struct.h" #include "lib/alloc/alloc_assist.h" #include "share/ob_errno.h" +#include "lib/atomic/atomic128.h" #include "lib/string/ob_string.h" #include "lib/random/ob_random.h" +#include "lib/utility/ob_macro_utils.h" #include "observer/ob_server_struct.h" #include "observer/omt/ob_tenant_config_mgr.h" @@ -149,6 +151,8 @@ int ObAesEncryption::aes_encrypt(const char *key, const int64_t &key_len, const int ret = OB_SUCCESS; int64_t expect_buf_len = (data_len / OB_AES_BLOCK_SIZE + 1) * OB_AES_BLOCK_SIZE; bool need_iv = false; + ENGINE *engine = NULL; + common::ObString err_reason; if (OB_ISNULL(buf) || buf_len < expect_buf_len || key_len < 0 || ObAesOpMode::ob_invalid_mode == mode || (iv_len != 0 && iv_len != OB_AES_IV_SIZE) || @@ -162,6 +166,12 @@ int ObAesEncryption::aes_encrypt(const char *key, const int64_t &key_len, const int u_len=0, f_len=0; unsigned char rkey[OB_MAX_AES_KEY_LENGTH / 8]; unsigned char *iv_encrypt = need_iv ? (unsigned char *)iv : NULL; + engine = ObTdeEncryptEngineLoader::get_instance().get_tde_engine(mode); + if (NULL != engine) { + if (EXECUTE_COUNT_PER_SEC(1)) { + LOG_INFO("tde use engine to encrypt data", K(mode)); + } + } EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); if (OB_ISNULL(ctx)) { ret = OB_INVALID_ARGUMENT; @@ -169,7 +179,7 @@ int ObAesEncryption::aes_encrypt(const char *key, const int64_t &key_len, const } else if (FALSE_IT(EVP_CIPHER_CTX_init(ctx))) { } else if (FALSE_IT(aes_create_key((const unsigned char *)key, (int)key_len, (char *)rkey, mode))) { - } else if (!EVP_EncryptInit(ctx, aes_evp_type(mode), rkey, iv_encrypt)) { + } else if (!EVP_EncryptInit_ex(ctx, aes_evp_type(mode), engine, rkey, iv_encrypt)) { ret = OB_ERR_AES_ENCRYPT; LOG_WARN("fail to init evp ctx in aes_encrypt", K(ret)); } else if (!EVP_CIPHER_CTX_set_padding(ctx, true)) { @@ -184,6 +194,10 @@ int ObAesEncryption::aes_encrypt(const char *key, const int64_t &key_len, const } else { out_len = u_len + f_len; } + if (OB_FAIL(ret)) { + err_reason = common::ObString::make_string(ERR_reason_error_string(ERR_get_error())); + LOG_WARN("tde encrypt failed", K(err_reason)); + } if (OB_NOT_NULL(ctx)) { EVP_CIPHER_CTX_free(ctx); } @@ -197,6 +211,8 @@ int ObAesEncryption::aes_decrypt(const char *key, const int64_t &key_len, const { int ret = OB_SUCCESS; bool need_iv = false; + ENGINE *engine = NULL; + common::ObString err_reason; if (OB_ISNULL(buf) || key_len < 0 || buf_len < data_len || ObAesOpMode::ob_invalid_mode == mode || (iv_len != 0 && iv_len != OB_AES_IV_SIZE) || @@ -210,6 +226,12 @@ int ObAesEncryption::aes_decrypt(const char *key, const int64_t &key_len, const int u_len=0, f_len=0; unsigned char rkey[OB_MAX_AES_KEY_LENGTH / 8]; unsigned char *iv_encrypt = need_iv ? (unsigned char *)iv : NULL; + engine = ObTdeEncryptEngineLoader::get_instance().get_tde_engine(mode); + if (NULL != engine) { + if (EXECUTE_COUNT_PER_SEC(1)) { + LOG_INFO("tde use engine to decrypt data", K(mode)); + } + } EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); if (OB_ISNULL(ctx)) { ret = OB_INVALID_ARGUMENT; @@ -217,7 +239,7 @@ int ObAesEncryption::aes_decrypt(const char *key, const int64_t &key_len, const } else if (FALSE_IT(EVP_CIPHER_CTX_init(ctx))) { } else if (FALSE_IT(aes_create_key((const unsigned char *)key, (int)key_len, (char *)rkey, mode))) { - } else if (!EVP_DecryptInit(ctx, aes_evp_type(mode), rkey, iv_encrypt)) { + } else if (!EVP_DecryptInit_ex(ctx, aes_evp_type(mode), engine, rkey, iv_encrypt)) { ret = OB_ERR_AES_DECRYPT; LOG_WARN("fail to init evp ctx in aes_decrypt", K(ret)); } else if (!EVP_CIPHER_CTX_set_padding(ctx, true)) { @@ -232,6 +254,10 @@ int ObAesEncryption::aes_decrypt(const char *key, const int64_t &key_len, const } else { out_len = u_len + f_len; } + if (OB_FAIL(ret)) { + err_reason = common::ObString::make_string(ERR_reason_error_string(ERR_get_error())); + LOG_WARN("tde decrypt failed", K(err_reason)); + } if (OB_NOT_NULL(ctx)) { EVP_CIPHER_CTX_free(ctx); } @@ -485,5 +511,118 @@ const EVP_MD* ObHashUtil::get_hash_evp_md(const ObHashAlgorithm algo) } } +void ObTdeEncryptEngineLoader::ssl_init() +{ + OpenSSL_add_all_digests(); + OpenSSL_add_all_ciphers(); + OPENSSL_load_builtin_modules(); + ENGINE_load_builtin_engines(); + ERR_load_ERR_strings(); +} + +int ObTdeEncryptEngineLoader::load(const common::ObString& engine) +{ + int ret = OB_SUCCESS; + common::ObString err_reason; + ObEncryptEngineType type = get_engine_type(engine); + if (OB_NONE_ENGINE == type) { + } else if (OB_INVALID_ENGINE == type) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("unsupport engine", K(engine)); + } else { + if (NULL == tde_engine_[type]) { + tde_engine_[type] = ENGINE_by_id(engine.ptr()); + if (NULL == tde_engine_[type]) { + ret = OB_INIT_FAIL; + err_reason = common::ObString::make_string(ERR_reason_error_string(ERR_get_error())); + LOG_WARN("load engine failed", K(engine), K(err_reason)); + } else if (!ENGINE_init(tde_engine_[type])) { + ret = OB_INIT_FAIL; + err_reason = common::ObString::make_string(ERR_reason_error_string(ERR_get_error())); + LOG_WARN("Failed initialisation engine!", K(engine), K(err_reason)); + ENGINE_free(tde_engine_[type]); + tde_engine_[type] = NULL; + } else { + LOG_INFO("tde install engine success", K(engine)); + } + } + } + return ret; +} + +void ObTdeEncryptEngineLoader::destroy() +{ + for (int i = 0; i < OB_MAX_ENGINE; i++) { + if (NULL != tde_engine_[i]) { + ENGINE_finish(tde_engine_[i]); + ENGINE_free(tde_engine_[i]); + } + } +} + +ENGINE* ObTdeEncryptEngineLoader::get_tde_engine(ObAesOpMode &mode) const +{ + ObEncryptEngineType type = OB_INVALID_ENGINE; + switch(mode) { + case ob_sm4_mode: + case ob_sm4_cbc_mode: + type = OB_SM4_ENGINE; + break; + case ob_aes_128_ecb: + case ob_aes_128_cbc: + case ob_aes_128_cfb1: + case ob_aes_128_cfb8: + case ob_aes_128_cfb128: + case ob_aes_128_ofb: + case ob_aes_192_ecb: + case ob_aes_192_cbc: + case ob_aes_192_cfb1: + case ob_aes_192_cfb8: + case ob_aes_192_cfb128: + case ob_aes_192_ofb: + case ob_aes_256_ecb: + case ob_aes_256_cbc: + case ob_aes_256_cfb1: + case ob_aes_256_cfb8: + case ob_aes_256_cfb128: + case ob_aes_256_ofb: + type = OB_AES_ENGINE; + break; + case ob_invalid_mode: + case ob_max_mode: + type = OB_INVALID_ENGINE; + break; + } + return tde_engine_[type]; +} + +ObTdeEncryptEngineLoader &ObTdeEncryptEngineLoader::get_instance() +{ + static ObTdeEncryptEngineLoader instance; + return instance; +} + +ObTdeEncryptEngineLoader::ObEncryptEngineType ObTdeEncryptEngineLoader::get_engine_type(const common::ObString& engine) +{ + ObEncryptEngineType type = OB_INVALID_ENGINE; + if (OB_NOT_NULL(strcasestr(engine.ptr(), "sm4"))) { + type = OB_SM4_ENGINE; + } else if (OB_NOT_NULL(strcasestr(engine.ptr(), "hy"))) { + type = OB_SM4_ENGINE; + } else if (OB_NOT_NULL(strcasestr(engine.ptr(), "aes"))) { + type = OB_AES_ENGINE; + } else if (0 == engine.case_compare("none")) { + type = OB_NONE_ENGINE; + } + return type; +} + +int ObTdeEncryptEngineLoader::reload_config() +{ + int ret = OB_SUCCESS; + common::ObString engine = GCONF._load_tde_encrypt_engine.get_value_string(); + return load(engine); +} + }//end share } //end oceanbase diff --git a/src/share/ob_encryption_util.h b/src/share/ob_encryption_util.h index b565a08981..e68fb835e7 100644 --- a/src/share/ob_encryption_util.h +++ b/src/share/ob_encryption_util.h @@ -171,6 +171,32 @@ private: static const EVP_MD* get_hash_evp_md(const ObHashAlgorithm algo); }; +class ObTdeEncryptEngineLoader { +public: + enum ObEncryptEngineType { + OB_NONE_ENGINE = 0, + OB_INVALID_ENGINE = 1, + OB_AES_ENGINE = 2, + OB_SM4_ENGINE = 3, + OB_MAX_ENGINE + }; + static ObTdeEncryptEngineLoader &get_instance(); + ObTdeEncryptEngineLoader() { + ssl_init(); + MEMSET(tde_engine_, 0, sizeof(ENGINE*)*OB_MAX_ENGINE); + } + ~ObTdeEncryptEngineLoader() { destroy(); } + void ssl_init(); + void destroy(); + int load(const common::ObString& engine); + ObEncryptEngineType get_engine_type(const common::ObString& engine); + ENGINE* get_tde_engine(ObAesOpMode &mode) const; + int reload_config(); +private: + bool is_inited_; + ENGINE* tde_engine_[OB_MAX_ENGINE]; +}; + }//end share } //end oceanbase #endif diff --git a/src/share/parameter/ob_parameter_seed.ipp b/src/share/parameter/ob_parameter_seed.ipp index d196f24c1c..087dbe1401 100644 --- a/src/share/parameter/ob_parameter_seed.ipp +++ b/src/share/parameter/ob_parameter_seed.ipp @@ -1361,3 +1361,6 @@ DEF_BOOL(_enable_protocol_diagnose, OB_CLUSTER_PARAMETER, "True", DEF_BOOL(_enable_transaction_internal_routing, OB_TENANT_PARAMETER, "True", "enable SQLs of transaction routed to any servers in the cluster on demand", ObParameterAttr(Section::TRANS, Source::DEFAULT, EditLevel::DYNAMIC_EFFECTIVE)); +DEF_STR(_load_tde_encrypt_engine, OB_CLUSTER_PARAMETER, "NONE", + "load the engine that meet the security classification requirement to encrypt data. default NONE", + ObParameterAttr(Section::OBSERVER, Source::DEFAULT, EditLevel::DYNAMIC_EFFECTIVE)); diff --git a/src/sql/resolver/cmd/ob_alter_system_resolver.cpp b/src/sql/resolver/cmd/ob_alter_system_resolver.cpp index fcd010ac7c..ba51a076e8 100644 --- a/src/sql/resolver/cmd/ob_alter_system_resolver.cpp +++ b/src/sql/resolver/cmd/ob_alter_system_resolver.cpp @@ -2086,6 +2086,10 @@ int ObSetConfigResolver::check_param_valid(int64_t tenant_id , LOG_WARN("ERRSIM, fail to set ssl invite node", K(ret)); } #endif + } else if (0 == name.case_compare("_load_tde_encrypt_engine")) { + if (OB_FAIL(share::ObTdeEncryptEngineLoader::get_instance().load(value))) { + LOG_WARN("load antsm-engine failed", K(ret)); + } } } return ret; diff --git a/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/all_virtual_sys_parameter_stat.result b/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/all_virtual_sys_parameter_stat.result index 7bd72c3911..78ceee219e 100644 --- a/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/all_virtual_sys_parameter_stat.result +++ b/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/all_virtual_sys_parameter_stat.result @@ -270,6 +270,7 @@ _ignore_system_memory_over_limit_error _io_callback_thread_count _large_query_io_percentage _lcl_op_interval +_load_tde_encrypt_engine _max_elr_dependent_trx_count _max_schema_slot_num _migrate_block_verify_level