From 83edb6418e0bb5f5cfe1085675ace14eba66498f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=80=B6=E6=A2=A6=E5=8A=A0=E5=BE=97?= Date: Tue, 3 Sep 2024 18:49:29 +0800 Subject: [PATCH] =?UTF-8?q?probackup=E7=A1=AC=E4=BB=B6=E5=8A=A0=E5=AF=86?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0hmac=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/bin/pg_probackup/backup.cpp | 46 +++++++++++++++++---- src/bin/pg_probackup/catalog.cpp | 56 ++++++++++++++++++-------- src/bin/pg_probackup/common_cipher.cpp | 28 ++++++++++--- src/bin/pg_probackup/common_cipher.h | 8 +++- src/bin/pg_probackup/pg_probackup.cpp | 3 +- src/bin/pg_probackup/pg_probackupc.h | 1 + 6 files changed, 110 insertions(+), 32 deletions(-) diff --git a/src/bin/pg_probackup/backup.cpp b/src/bin/pg_probackup/backup.cpp index 8c9242597..851055fca 100644 --- a/src/bin/pg_probackup/backup.cpp +++ b/src/bin/pg_probackup/backup.cpp @@ -2915,6 +2915,7 @@ static void compress_encrypt_directory() int ret = 0; bool res = false; uint key_len = 0; + uint hmac_len = MAX_HMAC_LEN; uint enc_buffer_len = 0; uint out_buffer_len = 0; long int backup_tar_pos = 0; @@ -2923,6 +2924,7 @@ static void compress_encrypt_directory() char sys_cmd[MAXPGPATH] = {0}; char tar_file[MAXPGPATH] = {0}; char enc_file[MAXPGPATH] = {0}; + unsigned char hmac_buffer[MAX_HMAC_LEN + 1] = {0}; unsigned char enc_buffer[MAX_ENCRYPT_LEN + 1] = {0}; unsigned char out_buffer[MAX_ENCRYPT_LEN + 1] = {0}; char errmsg[MAX_ERRMSG_LEN] = {0}; @@ -2969,25 +2971,43 @@ static void compress_encrypt_directory() ret = crypto_create_symm_key_use(crypto_module_session, (ModuleSymmKeyAlgo)algo, (unsigned char*)key, (size_t*)&key_len); if (ret != 1) { crypto_get_errmsg_use(NULL, errmsg); - clearCrypto(crypto_module_session, crypto_module_keyctx); + clearCrypto(crypto_module_session, crypto_module_keyctx, crypto_hmac_keyctx); elog(ERROR, "crypto module gen key error, errmsg:%s\n", errmsg); } } else { key = SEC_decodeBase64(encrypt_key, &key_len); if (NULL == key) { - clearCrypto(crypto_module_session, crypto_module_keyctx); - elog(ERROR, "crypto module decode key error, please check --with-key."); + clearCrypto(crypto_module_session, crypto_module_keyctx, crypto_hmac_keyctx); + elog(ERROR, "crypto module decode key error, please check --with-key.\n"); } } + encrypt_key = SEC_encodeBase64(key, (GS_UINT32)key_len); + if (NULL == encrypt_key) { + clearCrypto(crypto_module_session, crypto_module_keyctx, crypto_hmac_keyctx); + elog(ERROR, "crypto module encode key error.\n"); + } + + elog(INFO, "crypto module encrypt with key: %s , salt: %s \n", encrypt_key, encrypt_salt); + ret = crypto_ctx_init_use(crypto_module_session, &crypto_module_keyctx, (ModuleSymmKeyAlgo)algo, 1, (unsigned char*)key, key_len); if (ret != 1) { crypto_get_errmsg_use(NULL, errmsg); - clearCrypto(crypto_module_session, crypto_module_keyctx); + clearCrypto(crypto_module_session, crypto_module_keyctx, crypto_hmac_keyctx); elog(ERROR, "crypto keyctx init error, errmsg:%s\n", errmsg); } + algo = getHmacType((ModuleSymmKeyAlgo)algo); + + ret = crypto_hmac_init_use(crypto_module_session, &crypto_hmac_keyctx, (ModuleSymmKeyAlgo)algo, (unsigned char*)key, key_len); + if (ret != 1) + { + crypto_get_errmsg_use(NULL, errmsg); + clearCrypto(crypto_module_session, crypto_module_keyctx, crypto_hmac_keyctx); + elog(ERROR, "crypto hmac keyctx init error, errmsg:%s\n", errmsg); + } + fseek(backup_tar_fd,0,SEEK_END); backup_tar_length = ftell(backup_tar_fd); fseek(backup_tar_fd,0,SEEK_SET); @@ -3011,25 +3031,35 @@ static void compress_encrypt_directory() ret = memset_s(out_buffer, MAX_ENCRYPT_LEN + 1, '\0', MAX_ENCRYPT_LEN + 1); securec_check(ret, "\0", "\0"); + ret = memset_s(hmac_buffer, MAX_HMAC_LEN + 1, '\0', MAX_HMAC_LEN + 1); + securec_check(ret, "\0", "\0"); + + ret = crypto_hmac_use(crypto_hmac_keyctx, (unsigned char*)enc_buffer, enc_buffer_len, hmac_buffer, (size_t*)&hmac_len); + if (ret != 1) { + clearCrypto(crypto_module_session, crypto_module_keyctx, crypto_hmac_keyctx); + elog(ERROR, ("failed to calculate hmac\n")); + } + ret = crypto_encrypt_decrypt_use(crypto_module_keyctx, 1, (unsigned char*)enc_buffer, enc_buffer_len, (unsigned char*)encrypt_salt, MAX_IV_LEN, out_buffer, (size_t*)&out_buffer_len, NULL); if (ret != 1) { - clearCrypto(crypto_module_session, crypto_module_keyctx); - elog(ERROR, ("failed to encrypt backup file")); + clearCrypto(crypto_module_session, crypto_module_keyctx, crypto_hmac_keyctx); + elog(ERROR, ("failed to encrypt backup file\n")); } fwrite(out_buffer, 1, out_buffer_len, enc_backup_fd); + fwrite(hmac_buffer, 1, hmac_len, enc_backup_fd); } fclose(backup_tar_fd); fclose(enc_backup_fd); - clearCrypto(crypto_module_session, crypto_module_keyctx); + clearCrypto(crypto_module_session, crypto_module_keyctx, crypto_hmac_keyctx); rc = sprintf_s(sys_cmd, MAXPGPATH, "rm %s %s.tar -rf", current.root_dir, current.root_dir); securec_check_ss_c(rc, "\0", "\0"); if (!is_valid_cmd(sys_cmd)) { - elog(ERROR, "cmd is rejected"); + elog(ERROR, "cmd is rejected\n"); } system(sys_cmd); enc_flag = true; diff --git a/src/bin/pg_probackup/catalog.cpp b/src/bin/pg_probackup/catalog.cpp index d79c7bc2b..b257429ee 100644 --- a/src/bin/pg_probackup/catalog.cpp +++ b/src/bin/pg_probackup/catalog.cpp @@ -2884,13 +2884,16 @@ static void uncompress_decrypt_directory(const char *instance_name_str) DIR *data_dir = NULL; struct dirent *data_ent = NULL; uint key_len = 0; + uint hmac_len = MAX_HMAC_LEN; uint key_idx_uint = 0; uint dec_buffer_len = 0; uint out_buffer_len = MAX_CRYPTO_MODULE_LEN; long int enc_file_pos = 0; long int enc_file_len = 0; char sys_cmd[MAXPGPATH] = {0}; - char* key = NULL; + char* key = NULL; + unsigned char hmac_read_buffer[MAX_HMAC_LEN +1] = {0}; + unsigned char hmac_cal_buffer[MAX_HMAC_LEN +1] = {0}; unsigned char dec_buffer[MAX_CRYPTO_MODULE_LEN + 1] = {0}; unsigned char out_buffer[MAX_CRYPTO_MODULE_LEN + 1] = {0}; char enc_backup_file[MAXPGPATH] = {0}; @@ -2912,22 +2915,29 @@ static void uncompress_decrypt_directory(const char *instance_name_str) rc = crypto_create_symm_key_use(crypto_module_session, (ModuleSymmKeyAlgo)algo, (unsigned char*)key, (size_t*)&key_len); if (rc != 1) { crypto_get_errmsg_use(NULL, errmsg); - clearCrypto(crypto_module_session, crypto_module_keyctx); + clearCrypto(crypto_module_session, crypto_module_keyctx, crypto_hmac_keyctx); elog(ERROR, "crypto module gen key error, errmsg:%s\n", errmsg); } } else { key = SEC_decodeBase64(encrypt_key, &key_len); if (NULL == key) { - clearCrypto(crypto_module_session, crypto_module_keyctx); + clearCrypto(crypto_module_session, crypto_module_keyctx, crypto_hmac_keyctx); elog(ERROR, "crypto module decode key error, please check --with-key."); } } rc = crypto_ctx_init_use(crypto_module_session, &crypto_module_keyctx, (ModuleSymmKeyAlgo)algo, 0, (unsigned char*)key, key_len); - if (rc != 1) - { + if (rc != 1) { crypto_get_errmsg_use(NULL, errmsg); - clearCrypto(crypto_module_session, crypto_module_keyctx); + clearCrypto(crypto_module_session, crypto_module_keyctx, crypto_hmac_keyctx); + elog(ERROR, "crypto keyctx init error, errmsg:%s\n", errmsg); + } + + algo = getHmacType((ModuleSymmKeyAlgo)algo); + rc = crypto_hmac_init_use(crypto_module_session, &crypto_hmac_keyctx, (ModuleSymmKeyAlgo)algo, (unsigned char*)key, key_len); + if (rc != 1) { + crypto_get_errmsg_use(NULL, errmsg); + clearCrypto(crypto_module_session, crypto_module_keyctx, crypto_hmac_keyctx); elog(ERROR, "crypto keyctx init error, errmsg:%s\n", errmsg); } @@ -2949,7 +2959,7 @@ static void uncompress_decrypt_directory(const char *instance_name_str) FILE* enc_backup_fd = fopen(enc_backup_file,"rb"); if(NULL == enc_backup_fd) { - clearCrypto(crypto_module_session, crypto_module_keyctx); + clearCrypto(crypto_module_session, crypto_module_keyctx, crypto_hmac_keyctx); elog(ERROR, ("failed to create or open encrypt backup file.")); return; } @@ -2968,17 +2978,18 @@ static void uncompress_decrypt_directory(const char *instance_name_str) while(enc_file_pos < enc_file_len) { - if(enc_file_pos + MAX_CRYPTO_MODULE_LEN < enc_file_len) { - memset_s(dec_buffer, MAX_CRYPTO_MODULE_LEN, 0, MAX_CRYPTO_MODULE_LEN); - memset_s(out_buffer, MAX_CRYPTO_MODULE_LEN, 0, MAX_CRYPTO_MODULE_LEN); + memset_s(dec_buffer, MAX_CRYPTO_MODULE_LEN, 0, MAX_CRYPTO_MODULE_LEN); + memset_s(out_buffer, MAX_CRYPTO_MODULE_LEN, 0, MAX_CRYPTO_MODULE_LEN); + + if(enc_file_pos + MAX_CRYPTO_MODULE_LEN + MAX_HMAC_LEN < enc_file_len) { fread(dec_buffer, 1, MAX_CRYPTO_MODULE_LEN, enc_backup_fd); + fread(hmac_read_buffer, 1, MAX_HMAC_LEN, enc_backup_fd); dec_buffer_len = MAX_CRYPTO_MODULE_LEN; - enc_file_pos += MAX_CRYPTO_MODULE_LEN; + enc_file_pos += (MAX_CRYPTO_MODULE_LEN + MAX_HMAC_LEN); } else { - memset_s(dec_buffer, MAX_CRYPTO_MODULE_LEN, 0, MAX_CRYPTO_MODULE_LEN); - memset_s(out_buffer, MAX_CRYPTO_MODULE_LEN, 0, MAX_CRYPTO_MODULE_LEN); - fread(dec_buffer, 1, enc_file_len - enc_file_pos, enc_backup_fd); - dec_buffer_len = enc_file_len - enc_file_pos; + fread(dec_buffer, 1, enc_file_len - (enc_file_pos + MAX_HMAC_LEN), enc_backup_fd); + fread(hmac_read_buffer, 1, MAX_HMAC_LEN, enc_backup_fd); + dec_buffer_len = enc_file_len - (enc_file_pos + MAX_HMAC_LEN); enc_file_pos = enc_file_len; } @@ -2986,16 +2997,27 @@ static void uncompress_decrypt_directory(const char *instance_name_str) (unsigned char*)encrypt_salt, MAX_IV_LEN, (unsigned char*)out_buffer, (size_t*)&out_buffer_len, NULL); if(rc != 1) { crypto_get_errmsg_use(NULL, errmsg); - clearCrypto(crypto_module_session, crypto_module_keyctx); + clearCrypto(crypto_module_session, crypto_module_keyctx, crypto_hmac_keyctx); elog(ERROR, ("failed to decrypt enc_backup_file, errmsg: %s"), errmsg); } + rc = crypto_hmac_use(crypto_hmac_keyctx, (unsigned char*)out_buffer, out_buffer_len, hmac_cal_buffer, (size_t*)&hmac_len); + if(rc != 1) { + crypto_get_errmsg_use(NULL, errmsg); + clearCrypto(crypto_module_session, crypto_module_keyctx, crypto_hmac_keyctx); + elog(ERROR, ("failed to calculate hmac, errmsg: %s"), errmsg); + } + + if (strncmp((char*)hmac_cal_buffer, (char*)hmac_read_buffer, (size_t)hmac_len) != 0) { + elog(ERROR, ("hmac verify failed\n")); + } + fwrite(out_buffer, 1, out_buffer_len, dec_file_fd); } fclose(dec_file_fd); fclose(enc_backup_fd); - clearCrypto(crypto_module_session, crypto_module_keyctx); + clearCrypto(crypto_module_session, crypto_module_keyctx, crypto_hmac_keyctx); rc = sprintf_s(sys_cmd, MAXPGPATH, "tar -xPf %s/%s.tar", backup_instance_path, data_ent->d_name); diff --git a/src/bin/pg_probackup/common_cipher.cpp b/src/bin/pg_probackup/common_cipher.cpp index 29ca68922..c7185a0ca 100644 --- a/src/bin/pg_probackup/common_cipher.cpp +++ b/src/bin/pg_probackup/common_cipher.cpp @@ -14,9 +14,7 @@ typedef void (*crypto_module_sess_exit_type)(void *sess); typedef int (*crypto_result_size_type)(void *ctx, int enc, size_t data_size); typedef void (*crypto_ctx_clean_type)(void *ctx); typedef int (*crypto_digest_type)(void *sess, ModuleDigestAlgo algo, unsigned char * data, size_t data_size,unsigned char *result, size_t *result_size); -typedef int (*crypto_hmac_init_type)(void *sess, void **ctx, ModuleSymmKeyAlgo algo, unsigned char *key_id, size_t key_id_size); typedef void (*crypto_hmac_clean_type)(void *ctx); -typedef int (*crypto_hmac_type)(void *ctx, unsigned char * data, size_t data_size, unsigned char *result, size_t *result_size); typedef int (*crypto_gen_random_type)(void *sess, char *buffer, size_t size); typedef int (*crypto_deterministic_enc_dec_type)(void *sess, int enc, unsigned char *data, unsigned char *key_id, size_t key_id_size, size_t data_size, unsigned char *result, size_t *result_size); @@ -32,9 +30,9 @@ static crypto_result_size_type crypto_result_size_use = NULL; static crypto_ctx_clean_type crypto_ctx_clean_use = NULL; crypto_encrypt_decrypt_type crypto_encrypt_decrypt_use = NULL; static crypto_digest_type crypto_digest_use = NULL; -static crypto_hmac_init_type crypto_hmac_init_use = NULL; +crypto_hmac_init_type crypto_hmac_init_use = NULL; static crypto_hmac_clean_type crypto_hmac_clean_use = NULL; -static crypto_hmac_type crypto_hmac_use = NULL; +crypto_hmac_type crypto_hmac_use = NULL; static crypto_gen_random_type crypto_gen_random_use = NULL; static crypto_deterministic_enc_dec_type crypto_deterministic_enc_dec_use = NULL; crypto_get_errmsg_type crypto_get_errmsg_use = NULL; @@ -127,6 +125,17 @@ int transform_type(const char* type) } +int getHmacType(ModuleSymmKeyAlgo algo) +{ + if (algo >= MODULE_AES_128_CBC && algo <= MODULE_AES_256_GCM) { + return MODULE_HMAC_SHA256; + } else if (algo == MODULE_SM4_CBC || algo == MODULE_SM4_CTR) { + return MODULE_HMAC_SM3; + } + + return MODULE_ALGO_MAX; +} + void initCryptoModule(char* crypto_module_params, const char* encrypt_mode) { int ret = 1; @@ -184,8 +193,17 @@ void releaseCryptoCtx(void* crypto_module_keyctx) } } -void clearCrypto(void* crypto_module_session, void* crypto_module_keyctx) +void releaseHmacCtx(void* crypto_hmac_keyctx) { + if (libhandle && crypto_hmac_keyctx) { + crypto_hmac_clean_use(crypto_hmac_keyctx); + crypto_hmac_keyctx = NULL; + } +} + +void clearCrypto(void* crypto_module_session, void* crypto_module_keyctx, void* crypto_hmac_keyctx) +{ + releaseHmacCtx(crypto_hmac_keyctx); releaseCryptoCtx(crypto_module_keyctx); releaseCryptoSession(crypto_module_session); unload_crypto_module(); diff --git a/src/bin/pg_probackup/common_cipher.h b/src/bin/pg_probackup/common_cipher.h index 66b020cc6..81e52bc51 100644 --- a/src/bin/pg_probackup/common_cipher.h +++ b/src/bin/pg_probackup/common_cipher.h @@ -19,6 +19,7 @@ extern "C" { #define MAX_PROVIDER_NAME_LEN 128 #define MAX_ERRMSG_LEN 256 #define MAX_IV_LEN 16 +#define MAX_HMAC_LEN 32 typedef enum { MODULE_AES_128_CBC = 0, @@ -60,20 +61,25 @@ typedef int (*crypto_encrypt_decrypt_type)(void *ctx, int enc, unsigned char *da typedef int (*crypto_create_symm_key_type)(void *sess, ModuleSymmKeyAlgo algo, unsigned char *key_id, size_t *key_id_size); typedef int (*crypto_get_errmsg_type)(void *sess, char *errmsg); typedef int (*crypto_ctx_init_type)(void *sess, void **ctx, ModuleSymmKeyAlgo algo, int enc, unsigned char *key_id, size_t key_id_size); +typedef int (*crypto_hmac_init_type)(void *sess, void **ctx, ModuleSymmKeyAlgo algo, unsigned char *key_id, size_t key_id_size); +typedef int (*crypto_hmac_type)(void *ctx, unsigned char * data, size_t data_size, unsigned char *result, size_t *result_size); extern crypto_create_symm_key_type crypto_create_symm_key_use; extern crypto_encrypt_decrypt_type crypto_encrypt_decrypt_use; extern crypto_get_errmsg_type crypto_get_errmsg_use; extern crypto_ctx_init_type crypto_ctx_init_use; +extern crypto_hmac_init_type crypto_hmac_init_use; +extern crypto_hmac_type crypto_hmac_use; extern int transform_type(const char* type); +extern int getHmacType(ModuleSymmKeyAlgo algo); extern bool load_crypto_module_lib(); extern void unload_crypto_module(); extern void initCryptoModule(char* crypto_module_params, const char* encrypt_mode); extern void initCryptoSession(void** crypto_module_session); extern void releaseCryptoSession(void* crypto_module_session); extern void releaseCryptoCtx(void* crypto_module_keyctx); -extern void clearCrypto(void* crypto_module_session, void* crypto_module_keyctx); +extern void clearCrypto(void* crypto_module_session, void* crypto_module_keyctx, void* crypto_hmac_keyctx); extern void CryptoModuleParamsCheck(bool gen_key, char* params, const char* module_encrypt_mode, const char* module_encrypt_key, const char* module_encrypt_salt); #ifdef __cplusplus diff --git a/src/bin/pg_probackup/pg_probackup.cpp b/src/bin/pg_probackup/pg_probackup.cpp index 120f1f510..c78fec59d 100644 --- a/src/bin/pg_probackup/pg_probackup.cpp +++ b/src/bin/pg_probackup/pg_probackup.cpp @@ -160,6 +160,7 @@ char* encrypt_salt = NULL; char* encrypt_dev_params = NULL; void* crypto_module_session = NULL; void* crypto_module_keyctx = NULL; +void* crypto_hmac_keyctx = NULL; /* Mark whether encryption and decryption are performed */ /* only when encryption and decryption are actually performed will it be marked as true */ @@ -640,7 +641,7 @@ static int do_actual_operate() delete_backup_directory(instance_name); on_cleanup(); release_logfile(); - clearCrypto(crypto_module_session, crypto_module_keyctx); + clearCrypto(crypto_module_session, crypto_module_keyctx, crypto_hmac_keyctx); return res; } diff --git a/src/bin/pg_probackup/pg_probackupc.h b/src/bin/pg_probackup/pg_probackupc.h index 2b13c9c1c..151fa1898 100644 --- a/src/bin/pg_probackup/pg_probackupc.h +++ b/src/bin/pg_probackup/pg_probackupc.h @@ -88,6 +88,7 @@ extern char* encrypt_salt; extern char* encrypt_dev_params; extern void* crypto_module_session; extern void* crypto_module_keyctx; +extern void* crypto_hmac_keyctx; extern bool do_enc; extern bool enc_flag;