luksbox upgrade-header
Move an existing vault to header format v3, so a restored older keyslot table is detected.
luksbox upgrade-header [OPTIONS] <PATH>
luksbox deniable-upgrade-header [OPTIONS] <PATH>
Moves an existing vault to header format v3 (LUKSbox 0.6.0+).
Vaults created with 0.6.0 or later already use it; these commands are
for vaults made by LUKSbox 0.5.x or earlier, or with
create --header-v2. upgrade-header is for standard vaults,
deniable-upgrade-header for deniable vaults.
Both unlock the vault first.
What header format v3 protects against
The header holds the keyslot table. A copy saved earlier, for example
a header-backup taken before a
revoke, is still validly signed, because revoke does
not change the master key. Put back over the vault, it brings the
revoked credential back. On header format v2 nothing notices; only
rotate-mvk shuts a revoked credential out for good.
On header format v3, every keyslot change (enroll, revoke,
update, rotate-mvk, and the upgrade itself) gives the header a new
generation number, and the vault's rollback anchor (--anchor)
records it. An open with --anchor then refuses a header older than
the one the anchor saw:
error: header rollback detected: the anchor recorded header generation 5, but the vault's header is at generation 3. The keyslot table was replaced by an older copy (for example a backup taken before a revoke). Restore the current header, or re-establish the anchor deliberately if you restored it yourself.
Deniable v3 headers also commit to their slot table: an old slot envelope copied back in after the slot was cleared is refused (with the usual opaque unlock failure), even without an anchor.
The anchor does the checking
A standard v3 vault opened without --anchor accepts any older,
validly signed header, as a v2 vault does. The anchor is created
together with the vault (luksbox create --anchor <file>,
deniable-init --anchor <file>, or the anchor option of the wizard and
GUI create forms). Keep it on storage separate from the vault, such as
a USB stick you carry: someone who can roll back both together defeats
it.
Examples
# Standard vault: unlock as usual, and pass the vault's anchor
luksbox upgrade-header my.lbx --anchor /media/usb/my.anchor
# upgraded my.lbx to header format v3 (generation 1)
# LUKSbox versions before 0.6.0 can no longer open this vault.
# Deniable vault: same --cipher / --argon2-* / --credential /
# --kyber-path flags as deniable-info
luksbox deniable-upgrade-header secret.bin --anchor /media/usb/secret.anchor
# OK deniable vault upgraded to header format v3
# LUKSbox versions before 0.6.0 can no longer open this vault.
upgrade-header takes the usual unlock flags (--fido2, --tpm2,
--sep, --pq-hybrid, --header for a detached header, and so on).
Pass --anchor if the vault has one: the anchor is checked first, so a
rolled-back vault is refused before anything changes, and it starts
recording the header generation right away. Without --anchor the
upgrade still runs and prints a reminder; pass --anchor on your next
command.
Running it on a vault that is already on v3 changes nothing
(my.lbx already uses header format v3).
The wizard ("Upgrade header to format v3" in the vault menu) and the GUI (Manage keyslots, Upgrade header to v3) do the same.
One-way: needs LUKSbox 0.6.0+
There is no way back to v2. LUKSbox versions before 0.6.0 cannot open a
v3 vault (a deniable one fails with their usual opaque unlock error),
so upgrade only once every machine that opens the vault runs 0.6.0 or
later. To create a new vault that LUKSbox 0.2.1-0.5.x can still open,
use create --header-v2.
A vault still on the legacy --format v2 (header LUKSBOX1) is moved
to the current format in the same step. That step is refused while
LUKSBOX_FORMAT_V2 is set: unset it first.
Check the header format
luksbox info shows it, without unlocking:
$ luksbox info my.lbx
...
header format: v2 (no header generation; `luksbox upgrade-header` opts into v3)
After the upgrade:
header format: v3 (header generation 1; a restored older header is caught by the anchor)
luksbox deniable-info prints the same line for a deniable vault once
it has opened it, naming deniable-upgrade-header instead (0.6.1+).
Day to day on a v3 vault
- Pass
--anchorto every command that changes keyslots:enroll,revoke,update,rotate-mvk,header-restore. Since 0.6.0 every command that unlocks a vault checks the anchor before it runs and advances it after the header changes. A change made without--anchorstill works, but the anchor keeps the older generation, so a header restored from just before that change is not caught. - Restoring a header backup on purpose:
header-restoreof a verified backup saves it as a new header generation, so the anchor accepts it.header-restore --no-verifywrites the backup bytes as they are, and an older backup is then refused at the next anchored open. - Take a new
header-backupafter each keyslot change, as before.