Files
oceanbase/src/share/ob_encryption_util_os.cpp

703 lines
24 KiB
C++

/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
#ifndef OB_BUILD_TDE_SECURITY
#define USING_LOG_PREFIX SHARE
#include "share/ob_encryption_util.h"
#include <openssl/md4.h>
#include <openssl/md5.h>
#include <openssl/sha.h>
#include "share/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"
namespace oceanbase
{
using namespace common;
namespace share
{
int ObKeyGenerator::generate_encrypt_key(char *buf, int64_t len)
{
int ret = OB_SUCCESS;
if (len <= 0) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("the buf of len is invalid", K(ret));
} else if (!RAND_bytes((unsigned char*)buf, (int)len)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("failed to get a rand bytes");
}
return ret;
}
int ObKeyGenerator::generate_encrypt_key_char(char *buf, int64_t len)
{
int ret = OB_SUCCESS;
if (len <= 0) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("the buf of len is invalid", K(ret));
} else {
int i;
for (i = 0; i < len; ++i) {
switch (common::ObRandom::rand(0, 2)) {
case 1:
buf[i] = 'A' + common::ObRandom::rand(0, 25);
break;
case 2:
buf[i] = 'a' + common::ObRandom::rand(0, 25);
break;
default:
buf[i] = '0' + common::ObRandom::rand(0, 9);
break;
}
}
}
return ret;
}
static const EVP_CIPHER *get_evp_cipher(const ObCipherOpMode mode)
{
switch (mode)
{
case ob_aes_128_ecb: return EVP_aes_128_ecb();
case ob_aes_128_cbc: return EVP_aes_128_cbc();
case ob_aes_128_cfb1: return EVP_aes_128_cfb1();
case ob_aes_128_cfb8: return EVP_aes_128_cfb8();
case ob_aes_128_cfb128: return EVP_aes_128_cfb128();
case ob_aes_128_ofb: return EVP_aes_128_ofb();
case ob_aes_192_ecb: return EVP_aes_192_ecb();
case ob_aes_192_cbc: return EVP_aes_192_cbc();
case ob_aes_192_cfb1: return EVP_aes_192_cfb1();
case ob_aes_192_cfb8: return EVP_aes_192_cfb8();
case ob_aes_192_cfb128: return EVP_aes_192_cfb128();
case ob_aes_192_ofb: return EVP_aes_192_ofb();
case ob_aes_256_ecb: return EVP_aes_256_ecb();
case ob_aes_256_cbc: return EVP_aes_256_cbc();
case ob_aes_256_cfb1: return EVP_aes_256_cfb1();
case ob_aes_256_cfb8: return EVP_aes_256_cfb8();
case ob_aes_256_cfb128: return EVP_aes_256_cfb128();
case ob_aes_256_ofb: return EVP_aes_256_ofb();
case ob_aes_128_gcm: return EVP_aes_128_gcm();
case ob_aes_192_gcm: return EVP_aes_192_gcm();
case ob_aes_256_gcm: return EVP_aes_256_gcm();
#ifdef OB_USE_BABASSL
case ob_sm4_mode: return EVP_sm4_ctr();
case ob_sm4_cbc_mode: return EVP_sm4_cbc();
case ob_sm4_cbc: return EVP_sm4_cbc();
case ob_sm4_ecb: return EVP_sm4_ecb();
case ob_sm4_ofb: return EVP_sm4_ofb();
case ob_sm4_cfb128: return EVP_sm4_cfb128();
case ob_sm4_ctr: return EVP_sm4_ctr();
case ob_sm4_gcm: return EVP_sm4_gcm();
#endif
default: return NULL;
}
}
int ObBlockCipher::get_key_length(const ObCipherOpMode opmode)
{
int length = 0;
const EVP_CIPHER *cipher = get_evp_cipher(opmode);
if (NULL != cipher) {
length = EVP_CIPHER_key_length(cipher);
}
return length;
}
bool ObBlockCipher::is_need_iv(const ObCipherOpMode opmode)
{
bool need_iv = false;
const EVP_CIPHER *cipher = get_evp_cipher(opmode);
if (NULL != cipher) {
int default_iv_length = EVP_CIPHER_iv_length(cipher);
need_iv = default_iv_length == 0 ? false : true;
}
return need_iv;
}
bool ObBlockCipher::is_need_aead(const ObCipherOpMode opmode)
{
bool need_aead = false;
const EVP_CIPHER *cipher = get_evp_cipher(opmode);
if (NULL != cipher) {
need_aead = EVP_CIPHER_mode(cipher) == EVP_CIPH_GCM_MODE;
}
return need_aead;
}
bool ObBlockCipher::is_need_padding(const ObCipherOpMode opmode)
{
bool need_padding = false;
const EVP_CIPHER *cipher = get_evp_cipher(opmode);
if (NULL != cipher) {
need_padding = EVP_CIPH_ECB_MODE == EVP_CIPHER_mode(cipher) ||
EVP_CIPH_CBC_MODE == EVP_CIPHER_mode(cipher);
}
return need_padding;
}
int64_t ObBlockCipher::get_iv_length(const ObCipherOpMode opmode)
{
int64_t iv_length = 0;
const EVP_CIPHER *cipher = get_evp_cipher(opmode);
if (NULL != cipher) {
iv_length = EVP_CIPHER_iv_length(cipher);
}
return iv_length;
}
int64_t ObBlockCipher::get_aead_tag_length(const ObCipherOpMode opmode)
{
return is_need_aead(opmode) ? OB_DEFAULT_AEAD_TAG_LENGTH : 0;
}
int64_t ObBlockCipher::get_ciphertext_length(const ObCipherOpMode opmode, const int64_t data_len)
{
return is_need_padding(opmode) ?
(data_len / OB_CIPHER_BLOCK_LENGTH + 1) * OB_CIPHER_BLOCK_LENGTH : data_len;
}
int64_t ObBlockCipher::get_max_plaintext_length(const ObCipherOpMode opmode,
const int64_t encrypt_len)
{
return is_need_padding(opmode) ?
encrypt_len - 1 - (encrypt_len % OB_CIPHER_BLOCK_LENGTH) : encrypt_len;
}
void ObBlockCipher::create_key(const unsigned char *key, int key_length, char *rkey,
enum ObCipherOpMode opmode)
{
const int key_size= get_key_length(opmode);
char *rkey_end = NULL;
char *ptr = NULL; /* 真正的key的起始位置 */
char *sptr = NULL;
char *key_end= ((char *)key) + key_length;
rkey_end= rkey + key_size;
memset(rkey, 0, key_size); /* 初始化key */
for (ptr= rkey, sptr= (char *)key; sptr < key_end; ptr++, sptr++)
{
if (ptr == rkey_end)
ptr= rkey;
*ptr^= *sptr;
}
}
bool ObBlockCipher::is_valid_cipher_opmode(const ObCipherOpMode opmode)
{
return opmode > ObCipherOpMode::ob_invalid_mode && opmode < ObCipherOpMode::ob_max_mode &&
opmode != ObCipherOpMode::ob_sm4_mode;
}
int ObBlockCipher::encrypt(const char *key, const int64_t key_len,
const char *data, const int64_t data_len, const int64_t buf_len,
const char *iv, const int64_t iv_len,
const char *aad, const int64_t aad_len, const int64_t tag_len,
enum ObCipherOpMode mode, char *buf, int64_t &out_len, char *tag)
{
int ret = OB_SUCCESS;
bool need_iv = is_need_iv(mode);
bool need_aead = is_need_aead(mode);
bool need_padding = is_need_padding(mode);
if (!is_valid_cipher_opmode(mode) ||
(OB_ISNULL(key) && key_len != 0) || key_len < 0 || // allow NULL key
(OB_ISNULL(data) && data_len != 0) || data_len < 0 || // allow NULL data
OB_ISNULL(buf) || buf_len < get_ciphertext_length(mode, data_len)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(ret), K(data_len), K(key_len), K(buf_len), KP(buf), KP(data),
KP(key), K(mode));
} else if (need_iv && ((iv_len != 0 && OB_ISNULL(iv)) ||
(iv_len != 0 && iv_len != get_iv_length(mode)))) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid initial vector argument", K(ret), K(iv_len), KP(iv), K(mode));
} else if (need_aead && ((aad_len != 0 && OB_ISNULL(aad)) ||
(aad_len != 0 && aad_len != OB_DEFAULT_AEAD_AAD_LENGTH) ||
tag_len != OB_DEFAULT_AEAD_TAG_LENGTH || OB_ISNULL(tag))){
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid aead argument", K(ret), K(aad_len), K(tag_len), KP(aad), K(mode));
} else {
int u_len=0, f_len=0;
unsigned char rkey[OB_MAX_CIPHER_KEY_LENGTH / 8];
unsigned char *iv_encrypt = (!need_iv || iv_len == 0) ? NULL : (unsigned char *)iv;
unsigned char *add_encrypt = (!need_aead || aad_len == 0) ? NULL : (unsigned char *)aad;
ENGINE *engine = ObTdeEncryptEngineLoader::get_instance().get_tde_engine(mode);
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
const EVP_CIPHER *cipher = get_evp_cipher(mode);
if (NULL != engine) {
if (EXECUTE_COUNT_PER_SEC(10)) {
LOG_INFO("tde use engine to encrypt data", K(mode));
}
}
if (OB_ISNULL(ctx) ||OB_ISNULL(cipher)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("get EVP_ctx or EVP_cipher is NULL", K(ret), KP(ctx), KP(cipher));
} else if (FALSE_IT(create_key((const unsigned char *)key, (int)key_len, (char *)rkey, mode))) {
} else if (FALSE_IT(EVP_CIPHER_CTX_init(ctx))) {
} else if (!EVP_EncryptInit_ex(ctx, cipher, engine, rkey, (unsigned char*)iv_encrypt)) {
ret = OB_ERR_AES_ENCRYPT;
LOG_WARN("fail to init evp encrytion cipher and engine in encrypt", K(ret));
} else if (need_padding && !EVP_CIPHER_CTX_set_padding(ctx, true)) {
ret = OB_ERR_AES_ENCRYPT;
LOG_WARN("fail to set padding in encrypt", K(ret));
} else if (need_aead && NULL != add_encrypt && !EVP_EncryptUpdate(ctx, NULL, &u_len, (unsigned char *)add_encrypt, (int)aad_len)) {
ret = OB_ERR_AES_ENCRYPT;
LOG_WARN("fail to set AAD in encrypt", K(ret));
} else if (!EVP_EncryptUpdate(ctx, (unsigned char *)buf, &u_len, (unsigned char *)data, (int)data_len)) {
ret = OB_ERR_AES_ENCRYPT;
LOG_WARN("fail to encrypt data in encrypt", K(ret));
} else if (!EVP_EncryptFinal(ctx, (unsigned char*)buf + u_len, &f_len)) {
ret = OB_ERR_AES_ENCRYPT;
LOG_WARN("fail to encrypt final frame data in encrypt", K(ret));
} else if (need_aead && !EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, (int)tag_len, (unsigned char*)tag)) {
ret = OB_ERR_AES_ENCRYPT;
LOG_WARN("fail to encrypt final frame data in encrypt", K(ret));
} else {
out_len = u_len + f_len;
}
if (OB_UNLIKELY(OB_ERR_AES_ENCRYPT == ret)) {
common::ObString err_reason = common::ObString::make_string(ERR_reason_error_string(ERR_get_error()));
LOG_WARN("encrypt failed", K(err_reason));
}
if (OB_NOT_NULL(ctx)) {
EVP_CIPHER_CTX_free(ctx);
}
}
return ret;
}
int ObBlockCipher::decrypt(const char *key, const int64_t key_len,
const char *data, const int64_t data_len, const int64_t buf_len,
const char *iv, const int64_t iv_len, const char *aad,
const int64_t aad_len, const char *tag, const int64_t tag_len,
enum ObCipherOpMode mode, char *buf, int64_t &out_len)
{
int ret = OB_SUCCESS;
bool need_iv = is_need_iv(mode);
bool need_aead = is_need_aead(mode);
bool need_padding = is_need_padding(mode);
if (!is_valid_cipher_opmode(mode) ||
(OB_ISNULL(key) && key_len != 0) || key_len < 0 ||
(OB_ISNULL(data) && data_len != 0) || data_len < 0 ||
OB_ISNULL(buf) || buf_len < data_len) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(ret), K(data_len), K(key_len), K(buf_len), KP(buf), KP(data),
KP(key), K(mode));
} else if (need_iv && ((iv_len != 0 && OB_ISNULL(iv)) ||
(iv_len != 0 && iv_len != get_iv_length(mode)))) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid initial vector argument", K(ret), K(iv_len), KP(iv), K(mode));
} else if (need_aead && ((aad_len != 0 && OB_ISNULL(aad)) ||
(aad_len != 0 && aad_len != OB_DEFAULT_AEAD_AAD_LENGTH) ||
tag_len != OB_DEFAULT_AEAD_TAG_LENGTH || OB_ISNULL(tag))) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid aead argument", K(ret), K(aad_len), K(tag_len), KP(aad), KP(tag), K(mode));
} else {
int u_len=0, f_len=0;
unsigned char rkey[OB_MAX_CIPHER_KEY_LENGTH / 8];
unsigned char *iv_decrypt = (!need_iv || iv_len == 0) ? NULL : (unsigned char *)iv;
unsigned char *add_decrypt = (!need_aead || aad_len == 0) ? NULL : (unsigned char *)aad;
ENGINE *engine = ObTdeEncryptEngineLoader::get_instance().get_tde_engine(mode);
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
const EVP_CIPHER *cipher = get_evp_cipher(mode);
if (NULL != engine) {
if (EXECUTE_COUNT_PER_SEC(10)) {
LOG_INFO("use engine to decrypt data", K(mode));
}
}
if (OB_ISNULL(ctx) || OB_ISNULL(cipher)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("fail to to init cipher ctx in decrypt", K(ret), KP(ctx), KP(cipher));
} else if (FALSE_IT(create_key((const unsigned char *)key, (int)key_len, (char *)rkey, mode))) {
} else if (FALSE_IT(EVP_CIPHER_CTX_init(ctx))) {
} else if (!EVP_DecryptInit_ex(ctx, cipher, engine, rkey, (unsigned char*)iv_decrypt)) {
ret = OB_ERR_AES_DECRYPT;
LOG_WARN("fail to init evp ctx in decrypt", K(ret));
} else if (need_padding && !EVP_CIPHER_CTX_set_padding(ctx, true)) {
ret = OB_ERR_AES_DECRYPT;
LOG_WARN("fail to set padding in decrypt", K(ret));
} else if (need_aead && NULL != add_decrypt && !EVP_DecryptUpdate(ctx, NULL, &u_len, (const unsigned char *)add_decrypt, (int)aad_len)) {
ret = OB_ERR_AES_DECRYPT;
LOG_WARN("fail to set AAD in decrypt", K(ret));
} else if (!EVP_DecryptUpdate(ctx, (unsigned char *)buf, &u_len, (const unsigned char *)data, (int)data_len)) {
ret = OB_ERR_AES_DECRYPT;
LOG_WARN("fail to decrypt data in decrypt", K(ret));
} else if (need_aead && !EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, (int)tag_len, (unsigned char *)tag)) {
ret = OB_ERR_AES_DECRYPT;
} else if (!EVP_DecryptFinal(ctx, (unsigned char*)buf + u_len, &f_len)) {
ret = OB_ERR_AES_DECRYPT;
LOG_WARN("fail to decrypt final frame data in decrypt", K(ret), K(u_len), K(f_len));
} else {
out_len = u_len + f_len;
}
if (OB_UNLIKELY(OB_ERR_AES_DECRYPT == ret)) {
common::ObString err_reason = common::ObString::make_string(ERR_reason_error_string(ERR_get_error()));
LOG_WARN("decrypt failed", K(err_reason));
}
if (OB_NOT_NULL(ctx)) {
EVP_CIPHER_CTX_free(ctx);
}
}
return ret;
}
static void* ob_malloc_openssl(size_t nbyte, const char *, int)
{
ObMemAttr attr;
attr.ctx_id_ = ObCtxIds::GLIBC;
attr.label_ = ObModIds::OB_BUFFER;
return ob_malloc(nbyte, attr);
}
static void* ob_realloc_openssl(void *ptr, size_t nbyte, const char *, int)
{
ObMemAttr attr;
attr.ctx_id_ = ObCtxIds::GLIBC;
attr.label_ = ObModIds::OB_BUFFER;
return ob_realloc(ptr, nbyte, attr);
}
static void ob_free_openssl(void *ptr, const char *, int)
{
ob_free(ptr);
}
int ObEncryptionUtil::init_ssl_malloc()
{
int ret = OB_SUCCESS;
int tmp_ret = CRYPTO_set_mem_functions(ob_malloc_openssl, ob_realloc_openssl, ob_free_openssl);
if (OB_UNLIKELY(tmp_ret != 1)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("failed to set crypto mem functions", K(tmp_ret), K(ret));
}
return ret;
}
int ObEncryptionUtil::parse_encryption_algorithm(const char *str,
ObCipherOpMode &encryption_algorithm)
{
int ret = OB_SUCCESS;
encryption_algorithm = ObCipherOpMode::ob_invalid_mode;
return ret;
}
int ObEncryptionUtil::parse_encryption_id(const ObString &str, int64_t &encrypt_id)
{
int ret = OB_SUCCESS;
ObCipherOpMode encryption_algorithm = ObCipherOpMode::ob_invalid_mode;
return ret;
}
bool ObEncryptionUtil::is_aes_encryption(const ObCipherOpMode opmode) {
return (opmode >= ObCipherOpMode::ob_aes_128_ecb && opmode <= ObCipherOpMode::ob_aes_256_ofb) ||
(opmode >= ObCipherOpMode::ob_aes_128_gcm && opmode <= ObCipherOpMode::ob_aes_256_gcm);
}
bool ObEncryptionUtil::is_sm4_encryption(const ObCipherOpMode opmode) {
return (opmode >= ObCipherOpMode::ob_sm4_mode && opmode <= ObCipherOpMode::ob_sm4_cbc_mode) ||
(opmode >= ObCipherOpMode::ob_sm4_cbc && opmode <= ObCipherOpMode::ob_sm4_gcm);
}
bool ObBackupEncryptionMode::is_valid(const EncryptionMode &mode)
{
return mode >= NONE && mode < MAX_MODE;
}
//TODO(yaoying.yyy):暂时只支持tde,后续需要更新
bool ObBackupEncryptionMode::is_valid_for_log_archive(const EncryptionMode &mode)
{
return (NONE == mode || TRANSPARENT_ENCRYPTION == mode);
}
const char *backup_encryption_strs[] =
{
"NONE",
"PASSWORD",
"PASSWORD_ENCRYPTION",
"TRANSPARENT_ENCRYPTION",
"DUAL_MODE_ENCRYPTION",
};
const char *ObBackupEncryptionMode::to_str(const EncryptionMode &mode)
{
const char *str = "UNKNOWN";
if (is_valid(mode)) {
str = backup_encryption_strs[mode];
}
return str;
}
ObBackupEncryptionMode::EncryptionMode ObBackupEncryptionMode::parse_str(const char *str)
{
ObString obstr(str);
return parse_str(obstr);
}
ObBackupEncryptionMode::EncryptionMode ObBackupEncryptionMode::parse_str(const common::ObString &str)
{
EncryptionMode mode = MAX_MODE;
const int64_t count = ARRAYSIZEOF(backup_encryption_strs);
STATIC_ASSERT(static_cast<int64_t>(ObBackupEncryptionMode::MAX_MODE) == count,
"encryption mode count mismatch");
if (str.empty()) {
mode = NONE;
} else {
for (int64_t i = 0; i < count; ++i) {
if (0 == str.case_compare(backup_encryption_strs[i])) {
mode = static_cast<EncryptionMode>(i);
break;
}
}
}
return mode;
}
int ObHashUtil::hash(const enum ObHashAlgorithm algo, const ObString data,
ObIAllocator &allocator, ObString &output)
{
int ret = OB_SUCCESS;
char *buf = NULL;
const char *data_ptr = NULL != data.ptr() ? data.ptr() : "";
int64_t buf_len = 0;
int64_t out_len = 0;
if (OB_FAIL(get_hash_output_len(algo, buf_len))) {
LOG_WARN("fail to get hash output len", K(algo), K(ret));
} else if (OB_ISNULL(buf = static_cast<char *>(allocator.alloc(buf_len)))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("fail to allocate memory", K(ret));
} else if (OB_FAIL(hash(algo, data_ptr, data.length(), buf, buf_len, out_len))) {
LOG_WARN("fail to calc hash output", K(ret));
} else {
output.assign_ptr(buf, static_cast<int32_t>(out_len));
}
return ret;
}
int ObHashUtil::hash(const enum ObHashAlgorithm algo, const char *data, const int64_t data_len,
char *buf, const int64_t &buf_len, int64_t &out_len)
{
int ret = OB_SUCCESS;
int64_t expect_out_len = 0;
if (ObHashAlgorithm::OB_HASH_INVALID == algo || OB_ISNULL(data) || data_len < 0 ||
OB_ISNULL(buf)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(algo), K(data_len), K(buf_len), K(ret));
} else if (OB_FAIL(get_hash_output_len(algo, expect_out_len))) {
LOG_WARN("fail to get hash output len", K(algo), K(ret));
} else if (OB_UNLIKELY(buf_len < expect_out_len)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(algo), K(buf_len), K(expect_out_len), K(ret));
} else {
unsigned int res_len = 0;
const EVP_MD *md = get_hash_evp_md(algo);
EVP_MD_CTX *mdctx = EVP_MD_CTX_create();
if (OB_ISNULL(mdctx) || OB_ISNULL(md)) {
ret = OB_ERR_AES_ENCRYPT;
LOG_WARN("fail to init hash ctx", K(ret));
} else if (!EVP_DigestInit_ex(mdctx, md, NULL)) {
ret = OB_ERR_AES_ENCRYPT;
LOG_WARN("fail to init hash ctx", K(ret));
} else if (!EVP_DigestUpdate(mdctx, (const unsigned char *)data, data_len)) {
ret = OB_ERR_AES_ENCRYPT;
LOG_WARN("fail to update hash result", K(ret));
} else if (!EVP_DigestFinal_ex(mdctx, (unsigned char *)buf, &res_len)) {
ret = OB_ERR_AES_ENCRYPT;
LOG_WARN("fail to retrieve hash result", K(ret));
} else if (OB_UNLIKELY(expect_out_len != res_len)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid hash result length", K(expect_out_len), K(res_len), K(ret));
} else {
out_len = res_len;
}
if (OB_NOT_NULL(mdctx)) {
EVP_MD_CTX_destroy(mdctx);
}
}
return ret;
}
int ObHashUtil::get_hash_output_len(const ObHashAlgorithm algo, int64_t &output_len)
{
int ret = OB_SUCCESS;
switch(algo) {
case OB_HASH_MD4:
output_len = MD4_DIGEST_LENGTH;
break;
case OB_HASH_MD5:
output_len = MD5_DIGEST_LENGTH;
break;
case OB_HASH_SH1:
output_len = SHA_DIGEST_LENGTH;
break;
case OB_HASH_SH224:
output_len = SHA224_DIGEST_LENGTH;
break;
case OB_HASH_SH256:
output_len = SHA256_DIGEST_LENGTH;
break;
case OB_HASH_SH384:
output_len = SHA384_DIGEST_LENGTH;
break;
case OB_HASH_SH512:
output_len = SHA512_DIGEST_LENGTH;
break;
default:
ret = OB_NOT_SUPPORTED;
LOG_USER_ERROR(OB_NOT_SUPPORTED, "cipher type passed");
}
return ret;
}
int ObHashUtil::get_sha_hash_algorightm(const int64_t bit_length, ObHashAlgorithm &algo)
{
int ret = OB_SUCCESS;
const int64_t BIT_PER_BYTE = 8;
switch(bit_length) {
case SHA_DIGEST_LENGTH * BIT_PER_BYTE:
algo = OB_HASH_SH1;
break;
case SHA224_DIGEST_LENGTH * BIT_PER_BYTE:
algo = OB_HASH_SH224;
break;
case SHA256_DIGEST_LENGTH * BIT_PER_BYTE:
algo = OB_HASH_SH256;
break;
case SHA384_DIGEST_LENGTH * BIT_PER_BYTE:
algo = OB_HASH_SH384;
break;
case SHA512_DIGEST_LENGTH * BIT_PER_BYTE:
algo = OB_HASH_SH512;
break;
default:
ret = OB_NOT_SUPPORTED;
LOG_USER_ERROR(OB_NOT_SUPPORTED, "sha hash output length");
}
return ret;
}
const EVP_MD* ObHashUtil::get_hash_evp_md(const ObHashAlgorithm algo)
{
switch(algo) {
case OB_HASH_MD4: return EVP_md4();
case OB_HASH_MD5: return EVP_md5();
case OB_HASH_SH1: return EVP_sha1();
case OB_HASH_SH224: return EVP_sha224();
case OB_HASH_SH256: return EVP_sha256();
case OB_HASH_SH384: return EVP_sha384();
case OB_HASH_SH512: return EVP_sha512();
default: return NULL;
}
}
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]) {
ENGINE *e = ENGINE_by_id(engine.ptr());
if (NULL == e) {
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(e)) {
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(e);
} else {
tde_engine_[type] = e;
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(ObCipherOpMode &mode) const
{
ObEncryptEngineType type = OB_INVALID_ENGINE;
if (ObEncryptionUtil::is_aes_encryption(mode)) {
type = OB_AES_ENGINE;
} else if (ObEncryptionUtil::is_sm4_encryption(mode)) {
type = OB_SM4_ENGINE;
} else {
type = OB_INVALID_ENGINE;
}
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")) || OB_NOT_NULL(strcasestr(engine.ptr(), "hct"))) {
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
#endif