diff --git a/contrib/pg_tde/src/access/pg_tde_tdemap.c b/contrib/pg_tde/src/access/pg_tde_tdemap.c index 42dd4e05758..7ced3361465 100644 --- a/contrib/pg_tde/src/access/pg_tde_tdemap.c +++ b/contrib/pg_tde/src/access/pg_tde_tdemap.c @@ -59,7 +59,7 @@ #define PG_TDE_FILEMAGIC 0x02454454 /* version ID value = TDE 02 */ -#define MAP_ENTRY_DAT_SIZE (offsetof(TDEMapEntry, enc_key) + offsetof(InternalKey, ctx)) +#define MAP_ENTRY_SIZE sizeof(TDEMapEntry) #define TDE_FILE_HEADER_SIZE sizeof(TDEFileHeader) #define MaxXLogRecPtr (~(XLogRecPtr)0) @@ -216,7 +216,6 @@ pg_tde_generate_internal_key(InternalKey *int_key, uint32 entry_type) { int_key->rel_type = entry_type; int_key->start_lsn = InvalidXLogRecPtr; - int_key->ctx = NULL; if (!RAND_bytes(int_key->key, INTERNAL_KEY_LEN)) ereport(ERROR, @@ -436,10 +435,10 @@ pg_tde_write_one_map_entry(int fd, const RelFileLocator *rlocator, InternalKey * map_entry.enc_key = *enc_rel_key_data; /* TODO: pgstat_report_wait_start / pgstat_report_wait_end */ - bytes_written = pg_pwrite(fd, &map_entry, MAP_ENTRY_DAT_SIZE, *offset); + bytes_written = pg_pwrite(fd, &map_entry, MAP_ENTRY_SIZE, *offset); /* Add the entry to the file */ - if (bytes_written != MAP_ENTRY_DAT_SIZE) + if (bytes_written != MAP_ENTRY_SIZE) { ereport(ERROR, (errcode_for_file_access(), @@ -778,8 +777,8 @@ pg_tde_wal_last_key_set_lsn(XLogRecPtr lsn, const char *keyfile_path) keyfile_path))); } - last_key_idx = ((lseek(fd, 0, SEEK_END) - TDE_FILE_HEADER_SIZE) / MAP_ENTRY_DAT_SIZE) - 1; - write_pos = TDE_FILE_HEADER_SIZE + (last_key_idx * MAP_ENTRY_DAT_SIZE) + offsetof(TDEMapEntry, enc_key) + offsetof(InternalKey, start_lsn); + last_key_idx = ((lseek(fd, 0, SEEK_END) - TDE_FILE_HEADER_SIZE) / MAP_ENTRY_SIZE) - 1; + write_pos = TDE_FILE_HEADER_SIZE + (last_key_idx * MAP_ENTRY_SIZE) + offsetof(TDEMapEntry, enc_key) + offsetof(InternalKey, start_lsn); /* TODO: pgstat_report_wait_start / pgstat_report_wait_end */ if (pg_pwrite(fd, &lsn, sizeof(XLogRecPtr), write_pos) != sizeof(XLogRecPtr)) @@ -797,10 +796,10 @@ pg_tde_wal_last_key_set_lsn(XLogRecPtr lsn, const char *keyfile_path) */ if (last_key_idx > 0) { - off_t prev_key_pos = TDE_FILE_HEADER_SIZE + ((last_key_idx - 1) * MAP_ENTRY_DAT_SIZE); + off_t prev_key_pos = TDE_FILE_HEADER_SIZE + ((last_key_idx - 1) * MAP_ENTRY_SIZE); TDEMapEntry prev_map_entry; - if (pg_pread(fd, &prev_map_entry, MAP_ENTRY_DAT_SIZE, prev_key_pos) != MAP_ENTRY_DAT_SIZE) + if (pg_pread(fd, &prev_map_entry, MAP_ENTRY_SIZE, prev_key_pos) != MAP_ENTRY_SIZE) { ereport(ERROR, (errcode_for_file_access(), @@ -811,7 +810,7 @@ pg_tde_wal_last_key_set_lsn(XLogRecPtr lsn, const char *keyfile_path) { WALKeySetInvalid(&prev_map_entry.enc_key); - if (pg_pwrite(fd, &prev_map_entry, MAP_ENTRY_DAT_SIZE, prev_key_pos) != MAP_ENTRY_DAT_SIZE) + if (pg_pwrite(fd, &prev_map_entry, MAP_ENTRY_SIZE, prev_key_pos) != MAP_ENTRY_SIZE) { ereport(ERROR, (errcode_for_file_access(), @@ -1066,10 +1065,10 @@ pg_tde_read_one_map_entry(File map_file, const RelFileLocator *rlocator, int fla /* Read the entry at the given offset */ /* TODO: pgstat_report_wait_start / pgstat_report_wait_end */ - bytes_read = pg_pread(map_file, map_entry, MAP_ENTRY_DAT_SIZE, *offset); + bytes_read = pg_pread(map_file, map_entry, MAP_ENTRY_SIZE, *offset); /* We've reached the end of the file. */ - if (bytes_read != MAP_ENTRY_DAT_SIZE) + if (bytes_read != MAP_ENTRY_SIZE) return false; *offset += bytes_read; @@ -1094,10 +1093,10 @@ pg_tde_read_one_map_entry2(int fd, int32 key_index, TDEPrincipalKey *principal_k off_t read_pos = 0; /* Calculate the reading position in the file. */ - read_pos += (key_index * MAP_ENTRY_DAT_SIZE) + TDE_FILE_HEADER_SIZE; + read_pos += (key_index * MAP_ENTRY_SIZE) + TDE_FILE_HEADER_SIZE; /* Check if the file has a valid key */ - if ((read_pos + MAP_ENTRY_DAT_SIZE) > lseek(fd, 0, SEEK_END)) + if ((read_pos + MAP_ENTRY_SIZE) > lseek(fd, 0, SEEK_END)) { char db_map_path[MAXPGPATH] = {0}; @@ -1113,7 +1112,7 @@ pg_tde_read_one_map_entry2(int fd, int32 key_index, TDEPrincipalKey *principal_k /* Read the encrypted key */ /* TODO: pgstat_report_wait_start / pgstat_report_wait_end */ - if (pg_pread(fd, map_entry, MAP_ENTRY_DAT_SIZE, read_pos) != MAP_ENTRY_DAT_SIZE) + if (pg_pread(fd, map_entry, MAP_ENTRY_SIZE, read_pos) != MAP_ENTRY_SIZE) { char db_map_path[MAXPGPATH] = {0}; @@ -1288,7 +1287,7 @@ pg_tde_read_last_wal_key(void) return NULL; } - file_idx = ((fsize - TDE_FILE_HEADER_SIZE) / MAP_ENTRY_DAT_SIZE) - 1; + file_idx = ((fsize - TDE_FILE_HEADER_SIZE) / MAP_ENTRY_SIZE) - 1; map_entry = pg_tde_read_one_map_entry2(fd, file_idx, principal_key); if (!map_entry) { @@ -1330,7 +1329,7 @@ pg_tde_fetch_wal_keys(XLogRecPtr start_lsn) fd = pg_tde_open_file(db_map_path, &principal_key->keyInfo, O_RDONLY, &read_pos); - keys_count = (lseek(fd, 0, SEEK_END) - TDE_FILE_HEADER_SIZE) / MAP_ENTRY_DAT_SIZE; + keys_count = (lseek(fd, 0, SEEK_END) - TDE_FILE_HEADER_SIZE) / MAP_ENTRY_SIZE; /* * If there is no keys, return a fake one (with the range 0-infinity) so @@ -1399,6 +1398,7 @@ pg_tde_add_wal_key_to_cache(InternalKey *cached_key, XLogRecPtr start_lsn) wal_rec->start_lsn = start_lsn; wal_rec->end_lsn = MaxXLogRecPtr; wal_rec->key = cached_key; + wal_rec->crypt_ctx = NULL; if (!tde_wal_key_last_rec) { tde_wal_key_last_rec = wal_rec; diff --git a/contrib/pg_tde/src/access/pg_tde_xlog_encrypt.c b/contrib/pg_tde/src/access/pg_tde_xlog_encrypt.c index 2f89a4b4fbb..2c897480fe5 100644 --- a/contrib/pg_tde/src/access/pg_tde_xlog_encrypt.c +++ b/contrib/pg_tde/src/access/pg_tde_xlog_encrypt.c @@ -75,8 +75,8 @@ static InternalKey EncryptionKey = { .rel_type = MAP_ENTRY_EMPTY, .start_lsn = InvalidXLogRecPtr, - .ctx = NULL, }; +static void *EncryptionCryptCtx = NULL; static int XLOGChooseNumBuffers(void); @@ -176,7 +176,7 @@ TDEXLogWriteEncryptedPages(int fd, const void *buf, size_t count, off_t offset, SetXLogPageIVPrefix(tli, segno, iv_prefix); PG_TDE_ENCRYPT_DATA(iv_prefix, offset, (char *) buf, count, - enc_buff, key); + enc_buff, key, &EncryptionCryptCtx); return pg_pwrite(fd, enc_buff, count, offset); } @@ -195,8 +195,7 @@ TDEXLogSmgrInit(void) ((key->rel_type & TDE_KEY_TYPE_WAL_ENCRYPTED && !EncryptXLog) || (key->rel_type & TDE_KEY_TYPE_WAL_UNENCRYPTED && EncryptXLog)))) { - pg_tde_create_wal_key( - &EncryptionKey, &GLOBAL_SPACE_RLOCATOR(XLOG_TDE_OID), + pg_tde_create_wal_key(&EncryptionKey, &GLOBAL_SPACE_RLOCATOR(XLOG_TDE_OID), (EncryptXLog ? TDE_KEY_TYPE_WAL_ENCRYPTED : TDE_KEY_TYPE_WAL_UNENCRYPTED)); } else if (key) @@ -342,7 +341,7 @@ tdeheap_xlog_seg_read(int fd, void *buf, size_t count, off_t offset, PG_TDE_DECRYPT_DATA(iv_prefix, dec_off, (char *) buf + (offset - dec_off), dec_sz, (char *) buf + (offset - dec_off), - curr_key->key); + curr_key->key, &curr_key->crypt_ctx); if (dec_off + dec_sz == offset) { diff --git a/contrib/pg_tde/src/encryption/enc_tde.c b/contrib/pg_tde/src/encryption/enc_tde.c index 9fd52713323..312ee42668f 100644 --- a/contrib/pg_tde/src/encryption/enc_tde.c +++ b/contrib/pg_tde/src/encryption/enc_tde.c @@ -37,7 +37,7 @@ iv_prefix_debug(const char *iv_prefix, char *out_hex) * This function assumes that everything is in a single block, and has an assertion ensuring this */ static void -pg_tde_crypt_simple(const char *iv_prefix, uint32 start_offset, const char *data, uint32 data_len, char *out, InternalKey *key, const char *context) +pg_tde_crypt_simple(const char *iv_prefix, uint32 start_offset, const char *data, uint32 data_len, char *out, InternalKey *key, void **ctxPtr, const char *context) { const uint64 aes_start_block = start_offset / AES_BLOCK_SIZE; const uint64 aes_end_block = (start_offset + data_len + (AES_BLOCK_SIZE - 1)) / AES_BLOCK_SIZE; @@ -46,7 +46,7 @@ pg_tde_crypt_simple(const char *iv_prefix, uint32 start_offset, const char *data Assert(aes_end_block - aes_start_block <= NUM_AES_BLOCKS_IN_BATCH + 1); - Aes128EncryptedZeroBlocks(&key->ctx, key->key, iv_prefix, aes_start_block, aes_end_block, enc_key); + Aes128EncryptedZeroBlocks(ctxPtr, key->key, iv_prefix, aes_start_block, aes_end_block, enc_key); #ifdef ENCRYPTION_DEBUG { @@ -73,7 +73,7 @@ pg_tde_crypt_simple(const char *iv_prefix, uint32 start_offset, const char *data * This is a generic function intended for large data, that do not fit into a single block */ static void -pg_tde_crypt_complex(const char *iv_prefix, uint32 start_offset, const char *data, uint32 data_len, char *out, InternalKey *key, const char *context) +pg_tde_crypt_complex(const char *iv_prefix, uint32 start_offset, const char *data, uint32 data_len, char *out, InternalKey *key, void **ctxPtr, const char *context) { const uint64 aes_start_block = start_offset / AES_BLOCK_SIZE; const uint64 aes_end_block = (start_offset + data_len + (AES_BLOCK_SIZE - 1)) / AES_BLOCK_SIZE; @@ -88,7 +88,7 @@ pg_tde_crypt_complex(const char *iv_prefix, uint32 start_offset, const char *dat uint32 current_batch_bytes; uint64 batch_end_block = Min(batch_start_block + NUM_AES_BLOCKS_IN_BATCH, aes_end_block); - Aes128EncryptedZeroBlocks(&key->ctx, key->key, iv_prefix, batch_start_block, batch_end_block, enc_key); + Aes128EncryptedZeroBlocks(ctxPtr, key->key, iv_prefix, batch_start_block, batch_end_block, enc_key); #ifdef ENCRYPTION_DEBUG { char ivp_debug[33]; @@ -141,15 +141,15 @@ pg_tde_crypt_complex(const char *iv_prefix, uint32 start_offset, const char *dat * This function simply selects between the two above variations based on the data length */ void -pg_tde_crypt(const char *iv_prefix, uint32 start_offset, const char *data, uint32 data_len, char *out, InternalKey *key, const char *context) +pg_tde_crypt(const char *iv_prefix, uint32 start_offset, const char *data, uint32 data_len, char *out, InternalKey *key, void **ctxPtr, const char *context) { if (data_len >= DATA_BYTES_PER_AES_BATCH) { - pg_tde_crypt_complex(iv_prefix, start_offset, data, data_len, out, key, context); + pg_tde_crypt_complex(iv_prefix, start_offset, data, data_len, out, key, ctxPtr, context); } else { - pg_tde_crypt_simple(iv_prefix, start_offset, data, data_len, out, key, context); + pg_tde_crypt_simple(iv_prefix, start_offset, data, data_len, out, key, ctxPtr, context); } } @@ -200,7 +200,6 @@ AesDecryptKey(const TDEPrincipalKey *principal_key, Oid dbOid, InternalKey **p_r /* Fill in the structure */ **p_rel_key_data = *enc_rel_key_data; - (*p_rel_key_data)->ctx = NULL; AesDecrypt(principal_key->keyData, iv, (unsigned char *) enc_rel_key_data, INTERNAL_KEY_LEN, (unsigned char *) *p_rel_key_data, (int *) key_bytes); } diff --git a/contrib/pg_tde/src/include/access/pg_tde_tdemap.h b/contrib/pg_tde/src/include/access/pg_tde_tdemap.h index f78a87c31f1..c1783647c06 100644 --- a/contrib/pg_tde/src/include/access/pg_tde_tdemap.h +++ b/contrib/pg_tde/src/include/access/pg_tde_tdemap.h @@ -31,8 +31,6 @@ typedef struct InternalKey uint32 rel_type; XLogRecPtr start_lsn; - - void *ctx; } InternalKey; #define WALKeySetInvalid(key) \ @@ -63,6 +61,7 @@ typedef struct WALKeyCacheRec XLogRecPtr end_lsn; InternalKey *key; + void *crypt_ctx; struct WALKeyCacheRec *next; } WALKeyCacheRec; diff --git a/contrib/pg_tde/src/include/encryption/enc_tde.h b/contrib/pg_tde/src/include/encryption/enc_tde.h index 9f67ddaff19..4ec87168917 100644 --- a/contrib/pg_tde/src/include/encryption/enc_tde.h +++ b/contrib/pg_tde/src/include/encryption/enc_tde.h @@ -12,15 +12,15 @@ #include "access/pg_tde_tdemap.h" -extern void pg_tde_crypt(const char *iv_prefix, uint32 start_offset, const char *data, uint32 data_len, char *out, InternalKey *key, const char *context); +extern void pg_tde_crypt(const char *iv_prefix, uint32 start_offset, const char *data, uint32 data_len, char *out, InternalKey *key, void **ctxPtr, const char *context); /* Function Macros over crypt */ -#define PG_TDE_ENCRYPT_DATA(_iv_prefix, _start_offset, _data, _data_len, _out, _key) \ - pg_tde_crypt(_iv_prefix, _start_offset, _data, _data_len, _out, _key, "ENCRYPT") +#define PG_TDE_ENCRYPT_DATA(_iv_prefix, _start_offset, _data, _data_len, _out, _key, _ctxptr) \ + pg_tde_crypt(_iv_prefix, _start_offset, _data, _data_len, _out, _key, _ctxptr, "ENCRYPT") -#define PG_TDE_DECRYPT_DATA(_iv_prefix, _start_offset, _data, _data_len, _out, _key) \ - pg_tde_crypt(_iv_prefix, _start_offset, _data, _data_len, _out, _key, "DECRYPT") +#define PG_TDE_DECRYPT_DATA(_iv_prefix, _start_offset, _data, _data_len, _out, _key, _ctxptr) \ + pg_tde_crypt(_iv_prefix, _start_offset, _data, _data_len, _out, _key, _ctxptr, "DECRYPT") extern void AesEncryptKey(const TDEPrincipalKey *principal_key, Oid dbOid, InternalKey *rel_key_data, InternalKey **p_enc_rel_key_data, size_t *enc_key_bytes); extern void AesDecryptKey(const TDEPrincipalKey *principal_key, Oid dbOid, InternalKey **p_rel_key_data, InternalKey *enc_rel_key_data, size_t *key_bytes);