PG-1460 Always generate a new WAL key on server start

Since you can take a copy of a PostgreSQL data directory and start both
the old and the new version you could get two versions where the same
encrypted counter is used for CTR which would mean we could comapre
them and potentially decrypt the data. For this reason we need to
generate a new WAL key every time we start the server.
pull/209/head
Andreas Karlsson 5 months ago committed by Andreas Karlsson
parent 253c8a4a72
commit 06b671fc04
  1. 20
      contrib/pg_tde/src/access/pg_tde_xlog_encrypt.c
  2. 11
      contrib/pg_tde/t/009_wal_encrypt.pl
  3. 8
      contrib/pg_tde/t/expected/009_wal_encrypt.out

@ -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);

@ -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);

@ -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;

Loading…
Cancel
Save