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 16f6e9c531f..eaae1c87f24 100644 --- a/contrib/pg_tde/src/access/pg_tde_xlog_encrypt.c +++ b/contrib/pg_tde/src/access/pg_tde_xlog_encrypt.c @@ -192,19 +192,27 @@ TDEXLogSmgrInit(void) /* TODO: move to the separate func, it's not an SMGR init */ InternalKey *key = pg_tde_read_last_wal_key(); - /* TDOO: clean-up this mess */ - if ((!key && EncryptXLog) || (key && - ((key->rel_type & TDE_KEY_TYPE_WAL_ENCRYPTED && !EncryptXLog) || - (key->rel_type & TDE_KEY_TYPE_WAL_UNENCRYPTED && EncryptXLog)))) + /* + * Always generate a new key on starting PostgreSQL to protect against + * attacks on CTR ciphers based on comparing the WAL generated by two + * divergent copies of the same cluster. + */ + if (EncryptXLog) { pg_tde_create_wal_key(&EncryptionKey, &GLOBAL_SPACE_RLOCATOR(XLOG_TDE_OID), - (EncryptXLog ? TDE_KEY_TYPE_WAL_ENCRYPTED : TDE_KEY_TYPE_WAL_UNENCRYPTED)); + TDE_KEY_TYPE_WAL_ENCRYPTED); + } + else if (key && key->rel_type & TDE_KEY_TYPE_WAL_ENCRYPTED) + { + pg_tde_create_wal_key(&EncryptionKey, &GLOBAL_SPACE_RLOCATOR(XLOG_TDE_OID), + TDE_KEY_TYPE_WAL_UNENCRYPTED); + pfree(key); } else if (key) { EncryptionKey = *key; - pfree(key); pg_atomic_write_u64(&EncryptionState->enc_key_lsn, EncryptionKey.start_lsn); + pfree(key); } pg_tde_set_db_file_path(GLOBAL_SPACE_RLOCATOR(XLOG_TDE_OID).dbOid, EncryptionState->db_map_path); diff --git a/contrib/pg_tde/t/009_wal_encrypt.pl b/contrib/pg_tde/t/009_wal_encrypt.pl index 481f83d8541..88fece2e24d 100644 --- a/contrib/pg_tde/t/009_wal_encrypt.pl +++ b/contrib/pg_tde/t/009_wal_encrypt.pl @@ -86,6 +86,17 @@ PGTDE::append_to_file($stdout); $stdout = $node->safe_psql('postgres', 'INSERT INTO test_wal (k) VALUES (5), (6);', extra_params => ['-a']); PGTDE::append_to_file($stdout); +PGTDE::append_to_file("-- server restart with still wal encryption"); +$node->stop(); +$rt_value = $node->start(); +ok($rt_value == 1, "Restart Server"); + +$stdout = $node->safe_psql('postgres', "SHOW pg_tde.wal_encrypt;", extra_params => ['-a']); +PGTDE::append_to_file($stdout); + +$stdout = $node->safe_psql('postgres', 'INSERT INTO test_wal (k) VALUES (7), (8);', extra_params => ['-a']); +PGTDE::append_to_file($stdout); + $stdout = $node->safe_psql('postgres', "SELECT data FROM pg_logical_slot_get_changes('tde_slot', NULL, NULL);", extra_params => ['-a']); PGTDE::append_to_file($stdout); diff --git a/contrib/pg_tde/t/expected/009_wal_encrypt.out b/contrib/pg_tde/t/expected/009_wal_encrypt.out index 64fb19fa21b..7d7c5726891 100644 --- a/contrib/pg_tde/t/expected/009_wal_encrypt.out +++ b/contrib/pg_tde/t/expected/009_wal_encrypt.out @@ -21,6 +21,10 @@ ALTER SYSTEM SET pg_tde.wal_encrypt = on; SHOW pg_tde.wal_encrypt; on INSERT INTO test_wal (k) VALUES (5), (6); +-- server restart with still wal encryption +SHOW pg_tde.wal_encrypt; +on +INSERT INTO test_wal (k) VALUES (7), (8); SELECT data FROM pg_logical_slot_get_changes('tde_slot', NULL, NULL); BEGIN 739 COMMIT 739 @@ -36,6 +40,10 @@ BEGIN 742 table public.test_wal: INSERT: id[integer]:5 k[integer]:5 table public.test_wal: INSERT: id[integer]:6 k[integer]:6 COMMIT 742 +BEGIN 743 +table public.test_wal: INSERT: id[integer]:7 k[integer]:7 +table public.test_wal: INSERT: id[integer]:8 k[integer]:8 +COMMIT 743 SELECT pg_drop_replication_slot('tde_slot'); DROP EXTENSION pg_tde;