trackslash
VAULT-45 P2

Encryption 6: persist the encrypted vault store

0
Sub-issue of VAULT-22 P2 Add an optional password to the app lock

Description

Sub-issue 6 of the on-device encryption design (VAULT-26, docs/on-device-encryption.md, "Reading and writing while unlocked", "Crash safety").

The change: add EncryptedVaultStore, which is the RecordVaultStore plus:

  • an atomic, verified replacement of the whole file on every change
  • flock and a generation check, for writes coming from both the app and its extensions
  • failure handling that can never lose data

A failed killphrase write returns the same "no match" as today (MANIFESTO.md C2).

Tests: inject a failure at every step, and cover concurrent writers.

Linked issues

0

GitHub

0

No branches or pull requests linked.

Comments

1
Bradley

Done in https://github.com/badbundle/vault-app/pull/639 (merged as 9fa5c363).

What it adds: EncryptedVaultStore, which is RecordVaultStore persisted to the slot file. Each change is worked out first, then saved under flock:

  1. Read the file and check the slot's generation.
  2. Seal the slot at the next generation.
  3. Write a temp file and F_FULLFSYNC it.
  4. Read it back and verify it, byte for byte and by decrypting its own slot.
  5. Rename it over the file, then F_FULLFSYNC the directory.
  6. Publish the change.

Failures: anything before the rename leaves the disk and memory as they were. A failed killphrase deletion returns false, exactly like "no match" (C2).

Conflicts: if another writer (AutoFill) saved first, the change is made again on top of that writer's state, up to 3 times. So killphrase deletions and background writes aren't lost.

Temp files: every save first removes stray temp files, under the lock, so a crashed save can't leave an older copy of the vault behind (C6).

Limits: slots stop growing at 4 MiB (a 64 MiB file), and the uncompressed payload is capped at 64 MiB.

Wiping: the decrypted payload JSON is wiped after decoding.

Tests:

  • The contract suite also runs against the encrypted store, checking the file matches memory.
  • The differential test.
  • A failure and a crash at every step, including a failed cleanup.
  • Two stores on one file.
  • A performance guard at 1,000 items.

Review: a security review of the first version found three should-fixes: the conflict retry, temp cleanup on every save, and wiping. All three were fixed before merging, and a re-review confirmed them. The #633 follow-ups for the header-AAD test, buffer wiping, the growth-length residual and memory bounds are in this PR too.