fix: name the whole share set on the label the user copies down - #155
Merged
Merged
Conversation
Each generated SSKR share is headed by a label the user writes onto the sheet along with the words. It read "SSKR Share aido#2", which says which sheet this is but never how many the set has. That count is not decoration on a threshold scheme. Whoever opens the box later -- the owner years on, or an heir -- cannot tell a complete backup from a partial one, nor know how many more sheets to look for, nor whether enough of them survive to rebuild the secret at all. The application knows the number at the moment it prints the label and was dropping it. The label now reads "SSKR share 2 of 3" on the touch devices and "SSKR 2/3" on the Nano ones. Two forms rather than one because BAGL's bnnn_paging appends its own "(page/total)" counter to this title, and the long form plus that suffix overruns the Nano title line -- seen truncated as "SSKR Share... of 3 (4/5)" under Speculos while trying exactly that. "SSKR" stays in the label. A sheet carrying dozens of four-letter words and no name for its own format cannot be recovered by anyone who no longer has this application: there is nothing to search for, so neither this app nor Gordian SeedTool nor seedtool-cli can be found from the paper alone. That this application can itself rebuild a BIP39 phrase from SSKR shares does not cover that case -- the case is precisely not having it. A hand-written termination in the touch caller goes with it: it wrote a NUL at a fixed offset near the end of a 50-byte buffer, on the theory that the index might need one digit or two, when SPRINTF is snprintf bounded by sizeof and had already terminated the string. The new unit check is the one this change turned out to need. A bnnn_paging title does not wrap, it clips, silently -- which is how the overlong form above reached a screenshot rather than a test. The check builds the widest title the device can actually produce, from SSS_MAX_SHARE_COUNT and the page count a 46-ByteWord share can reach, and measures it in the bold font the title is drawn in: 108px against the 114px a Nano line holds. It is deliberately not an entry in the existing bounded table, which measures a macro alone: what reaches the screen here is the macro plus a counter the widget appends and the string knows nothing about, and expanding both fields to "99" as that table does would fail a layout that works, since 99 shares cannot be generated. Verified: six unit-test-matrix configurations 80/80 each; six targets built with text/data/bss byte-identical to before, the only binary difference being the two label strings themselves; functional tests under Speculos unchanged on both stacks, stax 12 passed/6 skipped and nanox 9 passed/9 skipped; clang-format clean. The new check was run in both states -- it passes on this label and rejects the overlong one with the right diagnostic.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Each generated SSKR share is headed by a label the user copies onto the sheet along with the words. It read:
That says which sheet this is. It never says how many the set has.
On a threshold scheme that count is not decoration. Whoever opens the box later — the owner years on, or an heir — cannot tell a complete backup from a partial one, cannot know how many more sheets to look for, and cannot tell whether enough of them survive to rebuild the secret at all. A 2-of-3 set missing one sheet is still recoverable; a 2-of-3 set missing two is not, and the sheets themselves never said which situation you are in. The application knows the number at the moment it prints the label, and was dropping it.
What changed
SSKR Share #2SSKR share 2 of 3SSKR Share #2SSKR 2/3Two forms rather than one shared macro, because they are not free to be the same length: BAGL's
bnnn_pagingappends its own(page/total)counter to this title, and the long form plus that suffix overruns the Nano title line. That is not a guess — it was seen truncated asSSKR Share... of 3 (4/5)under Speculos while trying exactly that.SSKRstays in the label. A sheet carrying dozens of four-letter words and no name for its own format cannot be recovered by anyone who no longer has this application: there is nothing to search for, so neither this app nor Gordian SeedTool norseedtool-clican be found from the paper alone. That this application can itself rebuild a BIP39 phrase from SSKR shares does not cover that case — the case is precisely not having it.Nothing else about the screen changes: same layout, same paging, same words, same navigation.
A hand-written termination goes with it
The touch caller followed its
SPRINTFwith:It wrote a NUL at a fixed offset near the end of a 50-byte buffer, on the theory that the index might need one digit or two.
SPRINTFissnprintfbounded bysizeof(os_print.h) and had already terminated the string, so this never truncated anything — and its condition tested the digit count of a total that was not in the string. Keeping it alongside the new format would have kept a line making a false claim.The new unit check, and why it is not in the existing table
A
bnnn_pagingtitle does not wrap. It clips, silently. That is how the overlong label above reached a screenshot instead of a failing test.tests/unit/tests/ui_strings.calready measures strings against the pixel budget of the fixed Nano layouts, but it excludesbnnn_paging— correctly for the body, which wraps and so cannot clip, and by oversight for the title, which can. This adds a check for the share label:SSS_MAX_SHARE_COUNTand the page count a 46-ByteWord share can reach on the one-line 128×32 screen;It is deliberately not an entry in the bounded table above it. That table measures a macro on its own, and what reaches the screen here is the macro plus a counter the widget appends and the string knows nothing about — measuring the macro alone reports 68px and calls it comfortable while the drawn title is 108px. Expanding both fields to
99as that table's helper does gives 116px and would fail a layout that works, since 99 shares cannot be generated.The check was run in both states: it passes on this label, and rejects the overlong one with the right diagnostic (
157px, over the 114px a Nano line holds).Verification
-O2,-Os,-fsigned-char,-funsigned-char): 80/80 each.nanosincluded by hand:text/data/bssbyte-identical to before on all six. The only difference in any binary is the two label strings themselves, confirmed by diffing sortedstringsoutput.stax12 passed / 6 skipped,nanox9 passed / 9 skipped — unchanged from before this change.test_sskr_generate_two_buttonreads the labels back off an emulated device, so the new Nano format is exercised end to end, not only asserted.clang-format --dry-run -Werrorclean on the touchedsrc/files.What is not covered
--modeloffers nanox, nanosp, stax, flex, apex_p), so the 128×32 device is covered only by compiling and by the pixel check above — which is written to bound that device in particular, since it is the one whose single text line per page pushes the page counter highest.