diff --git a/contrib/pg_tde/src/access/pg_tde_xlog_keys.c b/contrib/pg_tde/src/access/pg_tde_xlog_keys.c index 4c14625e008..23a61df4f28 100644 --- a/contrib/pg_tde/src/access/pg_tde_xlog_keys.c +++ b/contrib/pg_tde/src/access/pg_tde_xlog_keys.c @@ -25,19 +25,33 @@ #define PG_TDE_WAL_KEY_FILE_MAGIC 0x014B4557 /* version ID value = WEK 01 */ #define PG_TDE_WAL_KEY_FILE_NAME "wal_keys" -#define MaxXLogRecPtr (~(XLogRecPtr)0) -#define MaxTimeLineID (~(TimeLineID)0) - typedef struct WalKeyFileHeader { int32 file_version; TDESignedPrincipalKeyInfo signed_key_info; } WalKeyFileHeader; +/* + * Feel free to use the unused fields for something, but beware that existing + * files may contain unexpected values here. Also be aware of alignment if + * changing any of the types as this struct is written/read directly from file. + * + * If changes are made, know that the first two fields are used as AAD when + * encrypting/decrypting existing keys from the key files, so any changes here + * might break existing clusters. + */ typedef struct WalKeyFileEntry { - uint32 type; - WalEncryptionKey enc_key; + uint32 _unused1; /* Part of AAD, is 1 or 2 in existing entries */ + uint32 _unused2; /* Part of AAD */ + + uint8 encrypted_key_data[INTERNAL_KEY_LEN]; + uint8 key_base_iv[INTERNAL_KEY_IV_LEN]; + + uint32 range_type; /* WalEncryptionRangeType */ + uint32 _unused3; + WalLocation range_start; + /* IV and tag used when encrypting the key itself */ unsigned char entry_iv[MAP_ENTRY_IV_SIZE]; unsigned char aead_tag[MAP_ENTRY_AEAD_TAG_SIZE]; @@ -46,11 +60,11 @@ typedef struct WalKeyFileEntry static WALKeyCacheRec *tde_wal_key_cache = NULL; static WALKeyCacheRec *tde_wal_prealloc_record = NULL; static WALKeyCacheRec *tde_wal_key_last_rec = NULL; -static WalEncryptionKey *tde_wal_prealloc_key = NULL; +static WalEncryptionRange *tde_wal_prealloc_range = NULL; -static WALKeyCacheRec *pg_tde_add_wal_key_to_cache(WalEncryptionKey *cached_key); -static WalEncryptionKey *pg_tde_decrypt_wal_key(const TDEPrincipalKey *principal_key, WalKeyFileEntry *entry); -static void pg_tde_initialize_wal_key_file_entry(WalKeyFileEntry *entry, const TDEPrincipalKey *principal_key, const WalEncryptionKey *rel_key_data); +static WALKeyCacheRec *pg_tde_add_wal_range_to_cache(WalEncryptionRange *cached_range); +static WalEncryptionRange *pg_tde_wal_range_from_entry(const TDEPrincipalKey *principal_key, WalKeyFileEntry *entry); +static void pg_tde_initialize_wal_key_file_entry(WalKeyFileEntry *entry, const TDEPrincipalKey *principal_key, const WalEncryptionRange *range); static int pg_tde_open_wal_key_file_basic(const char *filename, int flags, bool ignore_missing); static int pg_tde_open_wal_key_file_read(const char *filename, bool ignore_missing, off_t *curr_pos); static int pg_tde_open_wal_key_file_write(const char *filename, const TDESignedPrincipalKeyInfo *signed_key_info, bool truncate, off_t *curr_pos); @@ -59,7 +73,7 @@ static void pg_tde_read_one_wal_key_file_entry2(int fd, int32 key_index, WalKeyF static void pg_tde_wal_key_file_header_read(const char *filename, int fd, WalKeyFileHeader *fheader, off_t *bytes_read); static int pg_tde_wal_key_file_header_write(const char *filename, int fd, const TDESignedPrincipalKeyInfo *signed_key_info, off_t *bytes_written); static void pg_tde_write_one_wal_key_file_entry(int fd, const WalKeyFileEntry *entry, off_t *offset, const char *db_map_path); -static void pg_tde_write_wal_key_file_entry(const WalEncryptionKey *rel_key_data, const TDEPrincipalKey *principal_key); +static void pg_tde_write_wal_key_file_entry(const WalEncryptionRange *range, const TDEPrincipalKey *principal_key); static char * get_wal_key_file_path(void) @@ -90,7 +104,7 @@ pg_tde_free_wal_key_cache(void) } void -pg_tde_wal_last_key_set_location(WalLocation loc) +pg_tde_wal_last_range_set_location(WalLocation loc) { LWLock *lock_pk = tde_lwlock_enc_keys(); int fd; @@ -105,8 +119,7 @@ pg_tde_wal_last_key_set_location(WalLocation loc) last_key_idx = ((lseek(fd, 0, SEEK_END) - sizeof(WalKeyFileHeader)) / sizeof(WalKeyFileEntry)) - 1; write_pos = sizeof(WalKeyFileHeader) + (last_key_idx * sizeof(WalKeyFileEntry)) + - offsetof(WalKeyFileEntry, enc_key) + - offsetof(WalEncryptionKey, wal_start); + offsetof(WalKeyFileEntry, range_start); if (pg_pwrite(fd, &loc, sizeof(WalLocation), write_pos) != sizeof(WalLocation)) { @@ -132,9 +145,9 @@ pg_tde_wal_last_key_set_location(WalLocation loc) errmsg("could not read previous WAL key: %m")); } - if (wal_location_cmp(prev_entry.enc_key.wal_start, loc) >= 0) + if (wal_location_cmp(prev_entry.range_start, loc) >= 0) { - prev_entry.enc_key.type = WAL_KEY_TYPE_INVALID; + prev_entry.range_type = WAL_ENCRYPTION_RANGE_INVALID; if (pg_pwrite(fd, &prev_entry, sizeof(WalKeyFileEntry), prev_key_pos) != sizeof(WalKeyFileEntry)) { @@ -165,7 +178,7 @@ pg_tde_wal_last_key_set_location(WalLocation loc) * with the actual lsn by the first WAL write. */ void -pg_tde_create_wal_key(WalEncryptionKey *rel_key_data, WalEncryptionKeyType entry_type) +pg_tde_create_wal_range(WalEncryptionRange *range, WalEncryptionRangeType type) { TDEPrincipalKey *principal_key; @@ -179,23 +192,16 @@ pg_tde_create_wal_key(WalEncryptionKey *rel_key_data, WalEncryptionKeyType entry errhint("Use pg_tde_set_server_key_using_global_key_provider() to configure one.")); } - /* TODO: no need in generating key if WAL_KEY_TYPE_UNENCRYPTED */ - rel_key_data->type = entry_type; - rel_key_data->wal_start.lsn = InvalidXLogRecPtr; - rel_key_data->wal_start.tli = 0; + /* TODO: no need in generating key if WAL_ENCRYPTION_RANGE_UNENCRYPTED */ + range->type = type; + range->start.lsn = InvalidXLogRecPtr; + range->start.tli = 0; + range->end.lsn = MaxXLogRecPtr; + range->end.tli = MaxTimeLineID; - if (!RAND_bytes(rel_key_data->key, INTERNAL_KEY_LEN)) - ereport(ERROR, - errcode(ERRCODE_INTERNAL_ERROR), - errmsg("could not generate WAL encryption key: %s", - ERR_error_string(ERR_get_error(), NULL))); - if (!RAND_bytes(rel_key_data->base_iv, INTERNAL_KEY_IV_LEN)) - ereport(ERROR, - errcode(ERRCODE_INTERNAL_ERROR), - errmsg("could not generate IV for WAL encryption key: %s", - ERR_error_string(ERR_get_error(), NULL))); + pg_tde_generate_internal_key(&range->key); - pg_tde_write_wal_key_file_entry(rel_key_data, principal_key); + pg_tde_write_wal_key_file_entry(range, principal_key); #ifdef FRONTEND free(principal_key); @@ -218,8 +224,8 @@ pg_tde_get_wal_cache_keys(void) return tde_wal_key_cache; } -WalEncryptionKey * -pg_tde_read_last_wal_key(void) +WalEncryptionRange * +pg_tde_read_last_wal_range(void) { off_t read_pos = 0; LWLock *lock_pk = tde_lwlock_enc_keys(); @@ -227,7 +233,7 @@ pg_tde_read_last_wal_key(void) int fd; int file_idx; WalKeyFileEntry entry; - WalEncryptionKey *rel_key_data; + WalEncryptionRange *range; off_t fsize; LWLockAcquire(lock_pk, LW_EXCLUSIVE); @@ -255,14 +261,14 @@ pg_tde_read_last_wal_key(void) file_idx = ((fsize - sizeof(WalKeyFileHeader)) / sizeof(WalKeyFileEntry)) - 1; pg_tde_read_one_wal_key_file_entry2(fd, file_idx, &entry); - rel_key_data = pg_tde_decrypt_wal_key(principal_key, &entry); + range = pg_tde_wal_range_from_entry(principal_key, &entry); #ifdef FRONTEND pfree(principal_key); #endif LWLockRelease(lock_pk); CloseTransientFile(fd); - return rel_key_data; + return range; } /* Fetches WAL keys from disk and adds them to the WAL cache */ @@ -297,11 +303,12 @@ pg_tde_fetch_wal_keys(WalLocation start) if (keys_count == 0) { WALKeyCacheRec *wal_rec; - WalEncryptionKey stub_key = { - .wal_start = {.tli = 0,.lsn = InvalidXLogRecPtr}, + WalEncryptionRange stub_range = { + .start = {.tli = 0,.lsn = InvalidXLogRecPtr}, + .end = {.tli = MaxTimeLineID,.lsn = MaxXLogRecPtr}, }; - wal_rec = pg_tde_add_wal_key_to_cache(&stub_key); + wal_rec = pg_tde_add_wal_range_to_cache(&stub_range); #ifdef FRONTEND /* The backend frees it after copying to the cache. */ @@ -321,17 +328,16 @@ pg_tde_fetch_wal_keys(WalLocation start) /* * Skip new (just created but not updated by write) and invalid keys */ - if (wal_location_valid(entry.enc_key.wal_start) && - (entry.enc_key.type == WAL_KEY_TYPE_UNENCRYPTED || - entry.enc_key.type == WAL_KEY_TYPE_ENCRYPTED) && - wal_location_cmp(entry.enc_key.wal_start, start) >= 0) + if (entry.range_type != WAL_ENCRYPTION_RANGE_INVALID && + wal_location_valid(entry.range_start) && + wal_location_cmp(entry.range_start, start) >= 0) { - WalEncryptionKey *rel_key_data = pg_tde_decrypt_wal_key(principal_key, &entry); + WalEncryptionRange *range = pg_tde_wal_range_from_entry(principal_key, &entry); WALKeyCacheRec *wal_rec; - wal_rec = pg_tde_add_wal_key_to_cache(rel_key_data); + wal_rec = pg_tde_add_wal_range_to_cache(range); - pfree(rel_key_data); + pfree(range); if (!return_wal_rec) return_wal_rec = wal_rec; @@ -365,9 +371,9 @@ pg_tde_wal_cache_extra_palloc(void) { tde_wal_prealloc_record = palloc0_object(WALKeyCacheRec); } - if (tde_wal_prealloc_key == NULL) + if (tde_wal_prealloc_range == NULL) { - tde_wal_prealloc_key = palloc0_object(WalEncryptionKey); + tde_wal_prealloc_range = palloc0_object(WalEncryptionRange); } #ifndef FRONTEND MemoryContextSwitchTo(oldCtx); @@ -375,7 +381,7 @@ pg_tde_wal_cache_extra_palloc(void) } static WALKeyCacheRec * -pg_tde_add_wal_key_to_cache(WalEncryptionKey *key) +pg_tde_add_wal_range_to_cache(WalEncryptionRange *range) { WALKeyCacheRec *wal_rec; #ifndef FRONTEND @@ -389,10 +395,7 @@ pg_tde_add_wal_key_to_cache(WalEncryptionKey *key) MemoryContextSwitchTo(oldCtx); #endif - wal_rec->start = key->wal_start; - wal_rec->end.tli = MaxTimeLineID; - wal_rec->end.lsn = MaxXLogRecPtr; - wal_rec->key = *key; + wal_rec->range = *range; wal_rec->crypt_ctx = NULL; if (!tde_wal_key_last_rec) { @@ -402,7 +405,7 @@ pg_tde_add_wal_key_to_cache(WalEncryptionKey *key) else { tde_wal_key_last_rec->next = wal_rec; - tde_wal_key_last_rec->end = wal_rec->start; + tde_wal_key_last_rec->range.end = wal_rec->range.start; tde_wal_key_last_rec = wal_rec; } @@ -574,7 +577,7 @@ pg_tde_read_one_wal_key_file_entry2(int fd, } static void -pg_tde_write_wal_key_file_entry(const WalEncryptionKey *rel_key_data, +pg_tde_write_wal_key_file_entry(const WalEncryptionRange *range, const TDEPrincipalKey *principal_key) { int fd; @@ -591,7 +594,7 @@ pg_tde_write_wal_key_file_entry(const WalEncryptionKey *rel_key_data, curr_pos = lseek(fd, 0, SEEK_END); /* Initialize WAL key file entry and encrypt key */ - pg_tde_initialize_wal_key_file_entry(&write_entry, principal_key, rel_key_data); + pg_tde_initialize_wal_key_file_entry(&write_entry, principal_key, range); /* Write the given entry at curr_pos; i.e. the free entry. */ pg_tde_write_one_wal_key_file_entry(fd, &write_entry, &curr_pos, get_wal_key_file_path()); @@ -599,27 +602,31 @@ pg_tde_write_wal_key_file_entry(const WalEncryptionKey *rel_key_data, CloseTransientFile(fd); } -static WalEncryptionKey * -pg_tde_decrypt_wal_key(const TDEPrincipalKey *principal_key, WalKeyFileEntry *entry) +static WalEncryptionRange * +pg_tde_wal_range_from_entry(const TDEPrincipalKey *principal_key, WalKeyFileEntry *entry) { - WalEncryptionKey *key = tde_wal_prealloc_key == NULL ? palloc_object(WalEncryptionKey) : tde_wal_prealloc_key; + WalEncryptionRange *range = tde_wal_prealloc_range == NULL ? palloc0_object(WalEncryptionRange) : tde_wal_prealloc_range; - tde_wal_prealloc_key = NULL; + tde_wal_prealloc_range = NULL; Assert(principal_key); - *key = entry->enc_key; + range->type = entry->range_type; + range->start = entry->range_start; + range->end.tli = MaxTimeLineID; + range->end.lsn = MaxXLogRecPtr; + memcpy(range->key.base_iv, entry->key_base_iv, INTERNAL_KEY_IV_LEN); if (!AesGcmDecrypt(principal_key->keyData, entry->entry_iv, MAP_ENTRY_IV_SIZE, - (unsigned char *) entry, offsetof(WalKeyFileEntry, enc_key), - entry->enc_key.key, INTERNAL_KEY_LEN, - key->key, + (unsigned char *) entry, offsetof(WalKeyFileEntry, encrypted_key_data), + entry->encrypted_key_data, INTERNAL_KEY_LEN, + range->key.key, entry->aead_tag, MAP_ENTRY_AEAD_TAG_SIZE)) ereport(ERROR, errmsg("Failed to decrypt key, incorrect principal key or corrupted key file")); - return key; + return range; } static void @@ -651,10 +658,22 @@ pg_tde_write_one_wal_key_file_entry(int fd, static void pg_tde_initialize_wal_key_file_entry(WalKeyFileEntry *entry, const TDEPrincipalKey *principal_key, - const WalEncryptionKey *rel_key_data) + const WalEncryptionRange *range) { - entry->type = rel_key_data->type; - entry->enc_key = *rel_key_data; + Assert(range->type == WAL_ENCRYPTION_RANGE_ENCRYPTED || range->type == WAL_ENCRYPTION_RANGE_UNENCRYPTED); + + memset(entry, 0, sizeof(WalKeyFileEntry)); + + /* + * We set this field here so that existing file entries will be consistent + * and future use of this field easier. Some existing entries will have 2 + * here. + */ + entry->_unused1 = 1; + + entry->range_type = range->type; + entry->range_start = range->start; + memcpy(entry->key_base_iv, range->key.base_iv, INTERNAL_KEY_IV_LEN); if (!RAND_bytes(entry->entry_iv, MAP_ENTRY_IV_SIZE)) ereport(ERROR, @@ -663,9 +682,9 @@ pg_tde_initialize_wal_key_file_entry(WalKeyFileEntry *entry, AesGcmEncrypt(principal_key->keyData, entry->entry_iv, MAP_ENTRY_IV_SIZE, - (unsigned char *) entry, offsetof(WalKeyFileEntry, enc_key), - rel_key_data->key, INTERNAL_KEY_LEN, - entry->enc_key.key, + (unsigned char *) entry, offsetof(WalKeyFileEntry, encrypted_key_data), + range->key.key, INTERNAL_KEY_LEN, + entry->encrypted_key_data, entry->aead_tag, MAP_ENTRY_AEAD_TAG_SIZE); } @@ -698,7 +717,7 @@ pg_tde_perform_rotate_server_key(const TDEPrincipalKey *principal_key, /* Read all entries until EOF */ while (1) { - WalEncryptionKey *key; + WalEncryptionRange *range; WalKeyFileEntry read_map_entry; WalKeyFileEntry write_map_entry; @@ -706,12 +725,10 @@ pg_tde_perform_rotate_server_key(const TDEPrincipalKey *principal_key, break; /* Decrypt and re-encrypt key */ - key = pg_tde_decrypt_wal_key(principal_key, &read_map_entry); - pg_tde_initialize_wal_key_file_entry(&write_map_entry, new_principal_key, key); - + range = pg_tde_wal_range_from_entry(principal_key, &read_map_entry); + pg_tde_initialize_wal_key_file_entry(&write_map_entry, new_principal_key, range); pg_tde_write_one_wal_key_file_entry(new_fd, &write_map_entry, &new_curr_pos, tmp_path); - - pfree(key); + pfree(range); } CloseTransientFile(old_fd); @@ -840,7 +857,7 @@ pg_tde_get_server_key_info(void) } int -pg_tde_count_wal_keys_in_file(void) +pg_tde_count_wal_ranges_in_file(void) { File fd; off_t curr_pos = 0; @@ -869,7 +886,7 @@ pg_tde_delete_server_key(void) Oid dbOid = GLOBAL_DATA_TDE_OID; Assert(LWLockHeldByMeInMode(tde_lwlock_enc_keys(), LW_EXCLUSIVE)); - Assert(pg_tde_count_wal_keys_in_file() == 0); + Assert(pg_tde_count_wal_ranges_in_file() == 0); XLogBeginInsert(); XLogRegisterData((char *) &dbOid, sizeof(Oid)); diff --git a/contrib/pg_tde/src/access/pg_tde_xlog_smgr.c b/contrib/pg_tde/src/access/pg_tde_xlog_smgr.c index 79baa95d73a..3a0932675b5 100644 --- a/contrib/pg_tde/src/access/pg_tde_xlog_smgr.c +++ b/contrib/pg_tde/src/access/pg_tde_xlog_smgr.c @@ -41,10 +41,10 @@ static const XLogSmgr tde_xlog_smgr = { static void *EncryptionCryptCtx = NULL; /* TODO: can be swapped out to the disk */ -static WalEncryptionKey EncryptionKey = -{ - .type = WAL_KEY_TYPE_INVALID, - .wal_start = {.tli = 0,.lsn = InvalidXLogRecPtr}, +static WalEncryptionRange CurrentWalEncryptionRange = { + .type = WAL_ENCRYPTION_RANGE_INVALID, + .start = {.tli = 0,.lsn = InvalidXLogRecPtr}, + .end = {.tli = MaxTimeLineID,.lsn = MaxXLogRecPtr}, }; /* @@ -223,7 +223,7 @@ TDEXLogSmgrInit() void TDEXLogSmgrInitWrite(bool encrypt_xlog) { - WalEncryptionKey *key; + WalEncryptionRange *range; WALKeyCacheRec *keys; /* @@ -233,7 +233,7 @@ TDEXLogSmgrInitWrite(bool encrypt_xlog) */ pg_tde_free_wal_key_cache(); - key = pg_tde_read_last_wal_key(); + range = pg_tde_read_last_wal_range(); /* * Always generate a new key on starting PostgreSQL to protect against @@ -242,16 +242,16 @@ TDEXLogSmgrInitWrite(bool encrypt_xlog) */ if (encrypt_xlog) { - pg_tde_create_wal_key(&EncryptionKey, WAL_KEY_TYPE_ENCRYPTED); + pg_tde_create_wal_range(&CurrentWalEncryptionRange, WAL_ENCRYPTION_RANGE_ENCRYPTED); } - else if (key && key->type == WAL_KEY_TYPE_ENCRYPTED) + else if (range && range->type == WAL_ENCRYPTION_RANGE_ENCRYPTED) { - pg_tde_create_wal_key(&EncryptionKey, WAL_KEY_TYPE_UNENCRYPTED); + pg_tde_create_wal_range(&CurrentWalEncryptionRange, WAL_ENCRYPTION_RANGE_UNENCRYPTED); } - else if (key) + else if (range) { - EncryptionKey = *key; - TDEXLogSetEncKeyLocation(EncryptionKey.wal_start); + CurrentWalEncryptionRange = *range; + TDEXLogSetEncKeyLocation(CurrentWalEncryptionRange.start); } keys = pg_tde_get_wal_cache_keys(); @@ -265,8 +265,8 @@ TDEXLogSmgrInitWrite(bool encrypt_xlog) pg_tde_wal_cache_extra_palloc(); } - if (key) - pfree(key); + if (range) + pfree(range); } /* @@ -280,13 +280,14 @@ void TDEXLogSmgrInitWriteOldKeys() { WALKeyCacheRec *keys; - WalEncryptionKey dummy = { - .type = WAL_KEY_TYPE_UNENCRYPTED, - .wal_start = {.tli = -1,.lsn = -1} + WalEncryptionRange dummy = { + .type = WAL_ENCRYPTION_RANGE_UNENCRYPTED, + .start = {.tli = MaxTimeLineID,.lsn = MaxXLogRecPtr}, + .end = {.tli = MaxTimeLineID,.lsn = MaxXLogRecPtr}, }; - EncryptionKey = dummy; - TDEXLogSetEncKeyLocation(dummy.wal_start); + CurrentWalEncryptionRange = dummy; + TDEXLogSetEncKeyLocation(dummy.start); keys = pg_tde_get_wal_cache_keys(); @@ -333,7 +334,7 @@ TDEXLogWriteEncryptedPages(int fd, const void *buf, size_t count, off_t offset, TimeLineID tli, XLogSegNo segno) { char iv_prefix[16]; - WalEncryptionKey *key = &EncryptionKey; + WalEncryptionRange *range = &CurrentWalEncryptionRange; char *enc_buff = EncryptionBuf; #ifndef FRONTEND @@ -342,17 +343,17 @@ TDEXLogWriteEncryptedPages(int fd, const void *buf, size_t count, off_t offset, #ifdef TDE_XLOG_DEBUG elog(DEBUG1, "write encrypted WAL, size: %lu, offset: %ld [%lX], seg: %X/%X, key_start_lsn: %u_%X/%X", - count, offset, offset, LSN_FORMAT_ARGS(segno), key->wal_start.tli, LSN_FORMAT_ARGS(key->wal_start.lsn)); + count, offset, offset, LSN_FORMAT_ARGS(segno), range->start.tli, LSN_FORMAT_ARGS(range->start.lsn)); #endif - CalcXLogPageIVPrefix(tli, segno, key->base_iv, iv_prefix); + CalcXLogPageIVPrefix(tli, segno, range->key.base_iv, iv_prefix); pg_tde_stream_crypt(iv_prefix, offset, (char *) buf, count, enc_buff, - key->key, + range->key.key, &EncryptionCryptCtx); return pg_pwrite(fd, enc_buff, count, offset); @@ -384,15 +385,15 @@ tde_ensure_xlog_key_location(WalLocation loc) lastKeyUsable = (writeKeyLoc.lsn != 0); afterWriteKey = wal_location_cmp(writeKeyLoc, loc) <= 0; - if (EncryptionKey.type != WAL_KEY_TYPE_INVALID && !lastKeyUsable && afterWriteKey && !crashRecovery) + if (CurrentWalEncryptionRange.type != WAL_ENCRYPTION_RANGE_INVALID && !lastKeyUsable && afterWriteKey && !crashRecovery) { WALKeyCacheRec *last_key = pg_tde_get_last_wal_key(); - if (last_key == NULL || last_key->start.lsn < loc.lsn) + if (last_key == NULL || last_key->range.start.lsn < loc.lsn) { - pg_tde_wal_last_key_set_location(loc); - EncryptionKey.wal_start = loc; - TDEXLogSetEncKeyLocation(EncryptionKey.wal_start); + pg_tde_wal_last_range_set_location(loc); + CurrentWalEncryptionRange.start = loc; + TDEXLogSetEncKeyLocation(CurrentWalEncryptionRange.start); lastKeyUsable = true; } } @@ -410,11 +411,11 @@ tdeheap_xlog_seg_write(int fd, const void *buf, size_t count, off_t offset, XLogSegNoOffsetToRecPtr(segno, offset, segSize, loc.lsn); lastKeyUsable = tde_ensure_xlog_key_location(loc); - if (!lastKeyUsable && EncryptionKey.type != WAL_KEY_TYPE_INVALID) + if (!lastKeyUsable && CurrentWalEncryptionRange.type != WAL_ENCRYPTION_RANGE_INVALID) { return TDEXLogWriteEncryptedPagesOldKeys(fd, buf, count, offset, tli, segno, segSize); } - else if (EncryptionKey.type == WAL_KEY_TYPE_ENCRYPTED) + else if (CurrentWalEncryptionRange.type == WAL_ENCRYPTION_RANGE_ENCRYPTED) { return TDEXLogWriteEncryptedPages(fd, buf, count, offset, tli, segno); } @@ -481,7 +482,7 @@ TDEXLogCryptBuffer(const void *buf, void *out_buf, size_t count, off_t offset, WalLocation write_loc = {.tli = TDEXLogGetEncKeyTli(),.lsn = write_key_lsn}; /* write has generated a new key, need to fetch it */ - if (last_key != NULL && wal_location_cmp(last_key->start, write_loc) < 0) + if (last_key != NULL && wal_location_cmp(last_key->range.start, write_loc) < 0) { pg_tde_fetch_wal_keys(write_loc); @@ -501,19 +502,20 @@ TDEXLogCryptBuffer(const void *buf, void *out_buf, size_t count, off_t offset, { #ifdef TDE_XLOG_DEBUG elog(DEBUG1, "WAL key %u_%X/%X - %u_%X/%X, encrypted: %s", - curr_key->start.tli, LSN_FORMAT_ARGS(curr_key->start.lsn), - curr_key->end.tli, LSN_FORMAT_ARGS(curr_key->end.lsn), - curr_key->key.type == WAL_KEY_TYPE_ENCRYPTED ? "yes" : "no"); + curr_key->range.start.tli, LSN_FORMAT_ARGS(curr_key->range.start.lsn), + curr_key->range.end.tli, LSN_FORMAT_ARGS(curr_key->range.end.lsn), + curr_key->range.type == WAL_ENCRYPTION_RANGE_ENCRYPTED ? "yes" : "no"); #endif - if (wal_location_valid(curr_key->key.wal_start) && - curr_key->key.type == WAL_KEY_TYPE_ENCRYPTED) + if (wal_location_valid(curr_key->range.start) && + curr_key->range.type == WAL_ENCRYPTION_RANGE_ENCRYPTED) { /* * Check if the key's range overlaps with the buffer's and decypt * the part that does. */ - if (wal_location_cmp(data_start, curr_key->end) < 0 && wal_location_cmp(data_end, curr_key->start) > 0) + if (wal_location_cmp(data_start, curr_key->range.end) < 0 && + wal_location_cmp(data_end, curr_key->range.start) > 0) { char iv_prefix[16]; @@ -544,11 +546,11 @@ TDEXLogCryptBuffer(const void *buf, void *out_buf, size_t count, off_t offset, size_t end_lsn = - data_end.tli < curr_key->end.tli ? data_end.lsn : - Min(data_end.lsn, curr_key->end.lsn); + data_end.tli < curr_key->range.end.tli ? data_end.lsn : + Min(data_end.lsn, curr_key->range.end.lsn); size_t start_lsn = - data_start.tli > curr_key->start.tli ? data_start.lsn : - Max(data_start.lsn, curr_key->start.lsn); + data_start.tli > curr_key->range.start.tli ? data_start.lsn : + Max(data_start.lsn, curr_key->range.start.lsn); off_t dec_off = XLogSegmentOffset(start_lsn, segSize); off_t dec_end = @@ -559,7 +561,7 @@ TDEXLogCryptBuffer(const void *buf, void *out_buf, size_t count, off_t offset, Assert(dec_off >= offset); - CalcXLogPageIVPrefix(tli, segno, curr_key->key.base_iv, + CalcXLogPageIVPrefix(tli, segno, curr_key->range.key.base_iv, iv_prefix); /* @@ -575,7 +577,7 @@ TDEXLogCryptBuffer(const void *buf, void *out_buf, size_t count, off_t offset, #ifdef TDE_XLOG_DEBUG elog(DEBUG1, "decrypt WAL, dec_off: %lu [buff_off %lu], sz: %lu | key %u_%X/%X", - dec_off, dec_off - offset, dec_sz, curr_key->key.wal_start.tli, LSN_FORMAT_ARGS(curr_key->key.wal_start.lsn)); + dec_off, dec_off - offset, dec_sz, curr_key->range.start.tli, LSN_FORMAT_ARGS(curr_key->range.start.lsn)); #endif pg_tde_stream_crypt(iv_prefix, @@ -583,7 +585,7 @@ TDEXLogCryptBuffer(const void *buf, void *out_buf, size_t count, off_t offset, dec_buf, dec_sz, o_buf, - curr_key->key.key, + curr_key->range.key.key, &curr_key->crypt_ctx); } } diff --git a/contrib/pg_tde/src/catalog/tde_principal_key.c b/contrib/pg_tde/src/catalog/tde_principal_key.c index abb160f47e2..7c2ef542b80 100644 --- a/contrib/pg_tde/src/catalog/tde_principal_key.c +++ b/contrib/pg_tde/src/catalog/tde_principal_key.c @@ -812,7 +812,7 @@ pg_tde_delete_default_key(PG_FUNCTION_ARGS) principal_key = GetPrincipalKeyNoDefault(GLOBAL_DATA_TDE_OID, LW_EXCLUSIVE); if (pg_tde_is_same_principal_key(default_principal_key, principal_key)) { - if (pg_tde_count_wal_keys_in_file() != 0) + if (pg_tde_count_wal_ranges_in_file() != 0) ereport(ERROR, errcode(ERRCODE_OBJECT_IN_USE), errmsg("cannot delete default principal key"), diff --git a/contrib/pg_tde/src/include/access/pg_tde_xlog_keys.h b/contrib/pg_tde/src/include/access/pg_tde_xlog_keys.h index 63c2e202151..047d76414e9 100644 --- a/contrib/pg_tde/src/include/access/pg_tde_xlog_keys.h +++ b/contrib/pg_tde/src/include/access/pg_tde_xlog_keys.h @@ -5,13 +5,14 @@ #include "access/pg_tde_keys_common.h" #include "access/pg_tde_tdemap.h" +#include "encryption/enc_tde.h" typedef enum { - WAL_KEY_TYPE_INVALID = 0, - WAL_KEY_TYPE_UNENCRYPTED = 1, - WAL_KEY_TYPE_ENCRYPTED = 2, -} WalEncryptionKeyType; + WAL_ENCRYPTION_RANGE_INVALID = 0, + WAL_ENCRYPTION_RANGE_UNENCRYPTED = 1, + WAL_ENCRYPTION_RANGE_ENCRYPTED = 2, +} WalEncryptionRangeType; typedef struct WalLocation { @@ -47,14 +48,19 @@ wal_location_valid(WalLocation loc) return loc.tli != 0 && loc.lsn != InvalidXLogRecPtr; } -typedef struct WalEncryptionKey +#define MaxXLogRecPtr UINT64_MAX +#define MaxTimeLineID UINT32_MAX + +typedef struct WalEncryptionRange { - uint8 key[INTERNAL_KEY_LEN]; - uint8 base_iv[INTERNAL_KEY_IV_LEN]; - uint32 type; + WalEncryptionRangeType type; + + /* key is only used when type is WAL_ENCRYPTION_RANGE_ENCRYPTED */ + InternalKey key; - WalLocation wal_start; -} WalEncryptionKey; + WalLocation start; + WalLocation end; +} WalEncryptionRange; /* * TODO: For now it's a simple linked list which is no good. So consider having @@ -62,17 +68,14 @@ typedef struct WalEncryptionKey */ typedef struct WALKeyCacheRec { - WalLocation start; - WalLocation end; - - WalEncryptionKey key; + WalEncryptionRange range; void *crypt_ctx; struct WALKeyCacheRec *next; } WALKeyCacheRec; -extern int pg_tde_count_wal_keys_in_file(void); -extern void pg_tde_create_wal_key(WalEncryptionKey *rel_key_data, WalEncryptionKeyType entry_type); +extern int pg_tde_count_wal_ranges_in_file(void); +extern void pg_tde_create_wal_range(WalEncryptionRange *range, WalEncryptionRangeType type); extern void pg_tde_delete_server_key(void); extern WALKeyCacheRec *pg_tde_fetch_wal_keys(WalLocation start); extern void pg_tde_free_wal_key_cache(void); @@ -80,10 +83,10 @@ extern WALKeyCacheRec *pg_tde_get_last_wal_key(void); extern TDESignedPrincipalKeyInfo *pg_tde_get_server_key_info(void); extern WALKeyCacheRec *pg_tde_get_wal_cache_keys(void); extern void pg_tde_perform_rotate_server_key(const TDEPrincipalKey *principal_key, const TDEPrincipalKey *new_principal_key, bool write_xlog); -extern WalEncryptionKey *pg_tde_read_last_wal_key(void); +extern WalEncryptionRange *pg_tde_read_last_wal_range(void); extern void pg_tde_save_server_key(const TDEPrincipalKey *principal_key, bool write_xlog); extern void pg_tde_save_server_key_redo(const TDESignedPrincipalKeyInfo *signed_key_info); -extern void pg_tde_wal_last_key_set_location(WalLocation loc); +extern void pg_tde_wal_last_range_set_location(WalLocation loc); extern void pg_tde_wal_cache_extra_palloc(void); #endif /* PG_TDE_XLOG_KEYS_H */