Skip to content

fix(storage): take V20, because 18 and 19 are burned - #505

Merged
BitHighlander merged 1 commit into
feat/passkeys-7.16from
fix/passkey-storage-v19
Aug 22, 2026
Merged

fix(storage): take V20, because 18 and 19 are burned#505
BitHighlander merged 1 commit into
feat/passkeys-7.16from
fix/passkey-storage-v19

Conversation

@BitHighlander

Copy link
Copy Markdown
Owner

Unblocks #504's U5 failure without merging past the gate.

The problem

#504 bumps the flash format to 18. That number already means something else.

18 was the clear-sign identity block; 19 was the PIN-KDF migration. Both were active, not merely drafted:

git log -S"STORAGE_VERSION_LAST(19)" -- lib/firmware/storage_versions.inc
  e109404ee  feat(storage): PIN KDF hardening, seed lock, BIP-85 and recovery fixes
  6bebde7b2  fix(storage): revert the flash format to V17 for the 7.15 release

Any device that ran an alpha build between those two commits carries a blob stamped 18 or 19 whose layout has nothing to do with passkeys. Dev devices in this building are in that population.

Reusing 18 makes this firmware read those blobs as CTAP2 state — not refuse them, not wipe them, parse them as something they are not. That is the failure docs/StorageVersionGate.md calls the highest-severity item in the file, and it is exactly why U5 asserts a literal rather than trusting the compile-time check: STORAGE_VERSION and STORAGE_VERSION_LAST_SHIPPED are two numbers in the same header, and raising one to make a build compile is the edit that must not pass silently.

The fix

The passkey format takes 20.

18 and 19 stay in the ladder — the enum is positional, so removing an entry renumbers everything after it — but there is deliberately no reader for either. A blob stamped 18 or 19 falls through to the default and the device wipes: the documented behaviour for an unrecognised format, and strictly better than misparsing one.

The passkey format itself is unchanged. Same layout, same 2525 bytes in V17's reserved plaintext area, same reader logic. Only the version number it registers under and the V18_*V20_* symbol names moved.

Still owed before U5 goes green

U5 needs updating with the release argument for the bump — reader chain, anti-rollback story, release-note wording. That is a deliberate release act per the gate doc and belongs to whoever cuts 7.16, not to this fix. I did not touch the test.

U5 (test_active_flash_format_is_v17) went red on this branch, and it was right
to. The branch bumped the flash format to 18 -- a number that already means
something else.

18 was the clear-sign identity block and 19 was the PIN-KDF migration. Both
were ACTIVE, not merely drafted: git log -S"STORAGE_VERSION_LAST(19)" shows
e109404 making 19 live and 6bebde7 reverting the format to V17 for 7.15.
Any device that ran an alpha build in that window carries a blob stamped 18 or
19 whose layout has nothing to do with passkeys.

Reusing 18 would make this firmware read those blobs as CTAP2 state. Not
refuse them, not wipe them -- parse them, as something they are not. That is
the failure docs/StorageVersionGate.md calls the highest-severity item in the
file, and it is the reason U5 asserts a literal instead of trusting the
compile-time check: STORAGE_VERSION and STORAGE_VERSION_LAST_SHIPPED are two
numbers in the same header, and raising one to make a build compile is exactly
the edit that must not pass silently.

So: the passkey format takes 20. 18 and 19 stay in the ladder -- the enum is
positional, so removing an entry renumbers everything after it -- but there is
deliberately NO reader for either. A blob stamped 18 or 19 falls through to the
default and the device wipes, which is the documented behaviour for an
unrecognised format and is strictly better than misparsing one.

The passkey format itself is unchanged: same layout, same 2525 bytes in V17's
reserved plaintext area, same reader logic. Only the version number it
registers under, and the V18_* -> V20_* symbol names, have moved.

U5 still needs updating with the release argument for the bump (reader chain,
anti-rollback story, release note) -- that is a deliberate release act and
belongs to whoever cuts 7.16, not to this fix.
@BitHighlander
BitHighlander merged commit 937d5e9 into feat/passkeys-7.16 Aug 22, 2026
5 checks passed
@BitHighlander
BitHighlander deleted the fix/passkey-storage-v19 branch August 22, 2026 00:49
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.

1 participant