Skip to content

security: derive a per-file salt for temporary-file encryption (H3)#17

Merged
jdatcmd merged 1 commit into
mainfrom
security/tempfile-iv-salt
Jul 15, 2026
Merged

security: derive a per-file salt for temporary-file encryption (H3)#17
jdatcmd merged 1 commit into
mainfrom
security/tempfile-iv-salt

Conversation

@jdatcmd

@jdatcmd jdatcmd commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

H3 (High): temporary-file IV/tweak reuse across BufFiles

Problem

Temporary-file encryption derived the AES-XTS tweak (and the CTR IV for a sub-block tail) from a cluster-global base IV and the buffer's block position. The block position resets to zero in every new BufFile, so two different temporary files encrypted identical plaintext blocks under the same (key, tweak):

  • XTS body: an equality oracle across files (identical plaintext block to identical ciphertext block).
  • CTR tail: a two-time pad on any sub-16-byte tail (XOR of two ciphertexts reveals XOR of plaintexts).

Fix

Core assigns each BufFile a 16-byte salt and passes it to the temporary-file encryption hooks, which mix it into the tweak/IV ahead of the block position:

  • Private temp file (BufFileCreateTemp): a random salt (pg_strong_random), unique and never shared.
  • Fileset based BufFile (BufFileCreateFileSet / BufFileOpenFileSet, e.g. parallel workers sharing a hash-join spill): the salt is derived deterministically from the fileset identity (creator_pid, number) and the BufFile name, so the writer and every reader arrive at the same salt without communicating it.

Temporary keys are per-boot and never persisted, so there is no on-disk compatibility concern.

Changes

  • Core patch 0002 (PG16/17/18): add crypt_salt to struct BufFile, fill it at create/open, and extend the TempFileCryptHook signature with the salt. Only buffile.c and tempfile_crypt.h hunks change; the other four hunks are byte-identical to what was committed.
  • src/open_pg_tde_tempfile.c: mix the salt into the XTS tweak / CTR IV.
  • t/temp_file_encryption.pl: two identical spilling sorts must now produce distinct ciphertext, with an encryption-off control and a parallel shared-fileset round trip.
  • Docs: note per-file uniqueness on the encryption architecture page.

Validation

  • PG18: full build + verify-gate.sh 3/3 (gate off = stock PostgreSQL, gate on = hooks load); full meson test suite green.
  • PG16 and PG18: temp_file_encryption.pl 9/9 subtests, including the H3 distinctness property and the parallel shared-fileset round trip.
  • Discrimination: neutralizing the salt makes the H3 subtest fail, confirming the test catches the bug (the pre-existing "temp files are ciphertext" check does not).
  • pgindent and perltidy clean.

Note: a full PG17 build currently trips over an unrelated 0001 base-drift (path_is_safe_for_extraction now exists both in the REL_17_STABLE tip and in 0001, a redefinition). This PR's 0002 never touches path.c, applies cleanly, and its buffile.c / tempfile_crypt.h edits are byte-identical to the compiled-clean PG16/PG18.

🤖 Generated with Claude Code

Temporary-file encryption derived the AES-XTS tweak (and the CTR IV for a
sub-block tail) from a cluster-global base IV and the buffer's block
position. The block position resets to zero in every new BufFile, so two
different temporary files encrypted identical plaintext blocks under the
same (key, tweak): an equality oracle across files for the XTS body and a
two-time pad for any CTR tail.

Core now assigns each BufFile a 16-byte salt and passes it to the
temporary-file encryption hooks, which mix it into the tweak/IV ahead of
the block position. A private temp file gets a random salt; a fileset
based BufFile (shared by parallel workers) derives its salt
deterministically from the fileset identity and name so the writer and
every reader agree without communicating it. Temporary keys are per-boot
and never persisted, so there is no on-disk compatibility concern.

Applies to the PostgreSQL 16/17/18 core patch (0002) and the extension.

- patches: add crypt_salt to struct BufFile, fill it at create/open, and
  extend the TempFileCryptHook signature with the salt.
- open_pg_tde_tempfile.c: mix the salt into the XTS tweak / CTR IV.
- test: two identical spilling sorts must now produce distinct ciphertext,
  with an encryption-off control and a parallel shared-fileset round trip.
- docs: note per-file uniqueness in the encryption architecture page.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jdatcmd
jdatcmd merged commit 886e54d into main Jul 15, 2026
24 of 36 checks passed
@jdatcmd
jdatcmd deleted the security/tempfile-iv-salt branch July 15, 2026 23:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants