Files
oceanbase/src/share/ob_encryption_util.h
2023-09-25 12:10:08 +00:00

304 lines
13 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.
*/
#include "lib/ob_define.h"
#include <openssl/evp.h>
#include "lib/container/ob_se_array.h"
#ifndef OCEANBASE_SHARE_OB_ENCRYPTION_UTIIL_H
#define OCEANBASE_SHARE_OB_ENCRYPTION_UTIIL_H
namespace oceanbase
{
namespace common
{
class ObString;
}
namespace share
{
struct ObEncryptMeta;
struct ObZoneEncryptMeta;
class ObKeyGenerator
{
public:
static int generate_encrypt_key(char *buf, int64_t len);
static int generate_encrypt_key_char(char *buf, int64_t len);
};
enum ObCipherOpMode {
ob_invalid_mode = 0,
ob_aes_128_ecb = 1,
ob_aes_192_ecb = 2,
ob_aes_256_ecb = 3,
ob_aes_128_cbc = 4,
ob_aes_192_cbc = 5,
ob_aes_256_cbc = 6,
ob_aes_128_cfb1 = 7,
ob_aes_192_cfb1 = 8,
ob_aes_256_cfb1 = 9,
ob_aes_128_cfb8 = 10,
ob_aes_192_cfb8 = 11,
ob_aes_256_cfb8 = 12,
ob_aes_128_cfb128 = 13,
ob_aes_192_cfb128 = 14,
ob_aes_256_cfb128 = 15,
ob_aes_128_ofb = 16,
ob_aes_192_ofb = 17,
ob_aes_256_ofb = 18,
ob_sm4_mode = 19, // old sm4_ctr using NULL as IV which is wrong, should not be used
ob_sm4_cbc_mode = 20, // sm4_cbc, use NULL as IV
ob_aes_128_gcm = 21,
ob_aes_192_gcm = 22,
ob_aes_256_gcm = 23,
ob_sm4_cbc = 24, // sm4_cbc, use random iv
ob_sm4_ecb = 25,
ob_sm4_ofb = 26,
ob_sm4_cfb128 = 27,
ob_sm4_ctr = 28, // sm4_ctr using unique iv
ob_sm4_gcm = 29,
/* attention:
1.remember to modify compare_aes_mod_safety when add new mode
2.considering compatibility of parse_encryption_id, only add modes sequentially
*/
ob_max_mode
};
class ObBlockCipher
{
public:
static int 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, const ObCipherOpMode mode, char *buf, int64_t &out_len,
char *tag);
static int 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, const ObCipherOpMode mode, char *buf,
int64_t &out_len);
static bool is_valid_cipher_opmode(const ObCipherOpMode opmode);
static bool is_need_iv(const ObCipherOpMode opmode);
static bool is_need_aead(const ObCipherOpMode opmode);
static int get_key_length(const ObCipherOpMode opmode);
static int64_t get_iv_length(const ObCipherOpMode opmode);
static int64_t get_aead_tag_length(const ObCipherOpMode opmode);
static int64_t get_ciphertext_length(const ObCipherOpMode opmode, const int64_t plaintext_len);
static int64_t get_max_plaintext_length(const ObCipherOpMode opmode,
const int64_t ciphertext_len);
//return true if right is more safe then left
static bool compare_aes_mod_safety(ObCipherOpMode left, ObCipherOpMode right);
private:
static bool is_need_padding(const ObCipherOpMode opmode);
static void create_key(const unsigned char *key, int key_length, char *rkey,
enum ObCipherOpMode opmode);
public:
static const int OB_MAX_CIPHER_KEY_LENGTH = 256; // max aes key bit length
static const int OB_DEFAULT_IV_LENGTH = 16;
static const int OB_CIPHER_BLOCK_LENGTH = 16;
static const int OB_DEFAULT_AEAD_AAD_LENGTH = 16;
static const int OB_DEFAULT_AEAD_TAG_LENGTH = 16;
};
const int64_t OB_ROOT_KEY_LEN = 16;
const int64_t OB_ORIGINAL_TABLE_KEY_LEN = 15;
const int64_t OB_ENCRYPTED_TABLE_KEY_LEN = 16;
const int64_t OB_INTERNAL_MASTER_KEY_LENGTH = 16;
const int64_t OB_MAX_MASTER_KEY_LENGTH = 32;
const int64_t OB_MAX_TABLESPACE_ENCRYPT_KEY_LENGTH = 16;
const int64_t OB_ENCRYPT_KEY_SALT_LEN = 8;
const int64_t OB_SALTED_MASTER_KEY_LEN = OB_INTERNAL_MASTER_KEY_LENGTH + OB_ENCRYPT_KEY_SALT_LEN;
const int64_t OB_MAX_ENCRYPTED_KEY_LENGTH = 256;
const int64_t OB_INTERNAL_ENCRYPTED_KEY_LENGTH = 32;
const int64_t OB_CLOG_ENCRYPT_MASTER_KEY_LEN = 32;
const int64_t OB_CLOG_ENCRYPT_TABLE_KEY_LEN = 32;
class ObEncryptionUtil
{
public:
static int init_ssl_malloc();
#ifdef OB_BUILD_TDE_SECURITY
static bool need_encrypt(const ObCipherOpMode opmode);
static int get_tde_method(int64_t tenant_id, common::ObString &tde_method);
static int get_tde_kms_info(int64_t tenant_id, common::ObString &kms_info);
#endif
static int parse_encryption_algorithm(const common::ObString &str,
ObCipherOpMode &encryption_algorithm);
static int parse_encryption_algorithm(const char *str,
ObCipherOpMode &encryption_algorithm);
static int parse_encryption_id(const char *str, int64_t &encrypt_id);
static int parse_encryption_id(const common::ObString &str, int64_t &encrypt_id);
static bool is_aes_encryption(const ObCipherOpMode opmode);
static bool is_sm4_encryption(const ObCipherOpMode opmode);
#ifdef OB_BUILD_TDE_SECURITY
static const ObCipherOpMode DEFAULT_TABLE_KEY_AES_ENCRYPT_ALGORITHM =
share::ObCipherOpMode::ob_aes_128_ecb;
static const ObCipherOpMode DEFAULT_TABLE_KEY_SM4_ENCRYPT_ALGORITHM =
share::ObCipherOpMode::ob_sm4_cbc_mode;
static const ObCipherOpMode DEFAULT_TABLE_KEY_AES256_ENCRYPT_ALGORITHM =
share::ObCipherOpMode::ob_aes_256_ecb;
static const ObCipherOpMode SYS_DATA_ENCRYPT_ALGORITHM = share::ObCipherOpMode::ob_aes_128_cbc;
static int64_t sys_encrypted_length(int64_t data_len);
// encrypt data with create a random iv and store iv in buf if needed.
static int encrypt_data(const char *key, const int64_t key_len, enum ObCipherOpMode mode,
const char *data, const int64_t data_len,
char *buf, const int64_t buf_len, int64_t &out_len);
// using to decrypt data which encrypted by encrypt_data
static int decrypt_data(const char *key, const int64_t key_len, enum ObCipherOpMode mode,
const char *data, const int64_t data_len,
char *buf, const int64_t buf_len, int64_t &out_len);
static int encrypt_data(const char *key, const int64_t key_len, enum ObCipherOpMode mode,
const char *data, const int64_t data_len, const char *iv,
const int64_t iv_len, char *buf, const int64_t buf_len, int64_t &out_len);
static int encrypt_data(const share::ObEncryptMeta &meta,
const char *data, const int64_t data_len,
char *buf, int64_t const buf_len, int64_t &out_len);
static int decrypt_data(const share::ObEncryptMeta &meta,
const char *data, const int64_t data_len,
char *buf, int64_t const buf_len, int64_t &out_len);
static int create_encrypted_table_key(const uint64_t tenant_id, uint64_t &master_key_id,
char *out_buf, const int64_t out_buf_len, int64_t &out_len,
int retry_times = 3);
static int decrypt_table_key(const uint64_t tenant_id,
const char *master_key, const int64_t master_key_len,
const char *encrypt_key, const int64_t encrypt_key_len,
char *out_buf, const int64_t out_buf_len, int64_t &out_len);
static int decrypt_table_key(share::ObEncryptMeta &meta);
static int encrypt_master_key(const uint64_t tenant_id, const char *data, const int64_t data_len,
char *buf, const int64_t buf_len, int64_t &out_len);
static int decrypt_master_key(const uint64_t tenant_id, const char *data, const int64_t data_len,
char *buf, const int64_t buf_len, int64_t &out_len);
static int encrypt_sys_data(const uint64_t tenant_id, const char *data, const int64_t data_len,
char *buf, const int64_t buf_len, int64_t &out_len);
static int decrypt_sys_data(const uint64_t tenant_id, const char *data, const int64_t data_len,
char *buf, const int64_t buf_len, int64_t &out_len);
static int encrypt_zone_data(share::ObZoneEncryptMeta &meta,
const char *data, const int64_t data_len,
char *buf, const int64_t buf_len, int64_t &out_len);
static int decrypt_zone_data(const share::ObZoneEncryptMeta &meta,
const char *data, const int64_t data_len,
char *buf, const int64_t buf_len, int64_t &out_len);
#endif
#ifdef OB_BUILD_TDE_SECURITY
// return the max buf length after encryption
static int64_t encrypted_length(const ObCipherOpMode mode, const int64_t data_len);
// return an unencrypted data length whose length after encryption is always less than data_len
static int64_t decrypted_length(const ObCipherOpMode mode, const int64_t data_len);
// return the max length after decryption
static int64_t safe_buffer_length(const int64_t data_len);
private:
static int encrypt_sys_data_default(const char *data, const int64_t data_len,
char *buf, const int64_t buf_len, int64_t &out_len);
static int decrypt_sys_data_default(const char *data, const int64_t data_len,
char *buf, const int64_t buf_len, int64_t &out_len);
private:
static const char* system_encrypt_key_;
static const char* system_encrypt_iv_;
#endif
};
struct ObBackupEncryptionMode final
{
enum EncryptionMode
{
NONE = 0, // 不加密
PASSWORD = 1, // 密码校验
PASSWORD_ENCRYPTION = 2,//密码校验+加密
TRANSPARENT_ENCRYPTION = 3,//透明加密
DUAL_MODE_ENCRYPTION = 4,//透明加密+密码校验
MAX_MODE
};
static bool is_valid(const EncryptionMode &mode);
static bool is_valid_for_log_archive(const EncryptionMode &mode);
static const char *to_str(const EncryptionMode &mode);
static EncryptionMode parse_str(const char *str);
static EncryptionMode parse_str(const common::ObString &str);
};
#ifdef OB_BUILD_TDE_SECURITY
class ObTdeMethodUtil
{
public:
static bool is_valid(const common::ObString &tde_method);
static bool is_internal(const common::ObString &tde_method);
static bool is_kms(const common::ObString &tde_method);
static bool is_sm_algorithm(const common::ObString &tde_method);
static bool is_aes256_algorithm(const common::ObString &tde_method);
static bool use_external_key_id(const common::ObString &tde_method);
static ObString extract_kms_name(const common::ObString &tde_method);
static ObString extract_mode_name(const common::ObString &tde_method);
private:
static bool inner_is_internal(const common::ObString &kms_name);
static bool inner_is_kms(const common::ObString &kms_name);
static bool is_valid_kms(const common::ObString &kms_name);
static bool is_valid_mode(const common::ObString &mode_name);
};
#endif
enum ObHashAlgorithm {
OB_HASH_INVALID = 0,
OB_HASH_MD4,
OB_HASH_MD5,
OB_HASH_SH1,
OB_HASH_SH224,
OB_HASH_SH256,
OB_HASH_SH384,
OB_HASH_SH512,
OB_HASH_MAX
};
class ObHashUtil
{
public:
static int hash(const enum ObHashAlgorithm algo, const common::ObString data,
common::ObIAllocator &allocator, common::ObString &output);
static int hash(const enum ObHashAlgorithm algo, const char *data, const int64_t data_len,
char *buf, const int64_t &buf_len, int64_t &out_len);
static int get_hash_output_len(const ObHashAlgorithm algo, int64_t &output_len);
static int get_sha_hash_algorightm(const int64_t bit_length, ObHashAlgorithm &algo);
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(ObCipherOpMode &mode) const;
int reload_config();
private:
bool is_inited_;
ENGINE* tde_engine_[OB_MAX_ENGINE];
};
}//end share
} //end oceanbase
#endif