7.15 audit 1/6: release foundation - #359
Conversation
Sets the 7.15.0 project version and the build-time plumbing the rest of the release sits on: - KK_BITCOIN_ONLY option plus the derived KK_ZCASH_PRIVACY selection, so the product is two images (regular, bitcoin-only) rather than three. - Device builds route snprintf/vsnprintf to newlib's integer-only engine and emit per-function stack-usage data for the SRAM budget gate. - tools/check_sram_budget.py + tools/sram-budgets.json enforce the stack frame margin that the RC7 boot fault exposed. - CI: variant matrix across ARM/emulator builds and unit tests, a crypto job running the pinned fork's suites under Valgrind and ASan/UBSan, release invariant checks, action SHA pinning and digest-pinned builder images. - Release workflow supports RC tags and selective submodule checkout. - Dependency pins move to the reviewed heads: trezor-firmware fork, and the device-protocol / python-keepkey commits carrying the 7.15 messages. - Include paths follow the crypto fork's layout (trezor-firmware/crypto). Feature code and its per-feature CI gates land in the branches stacked on top of this one; nothing here compiles new firmware sources.
Display: - Long bech32/bech32m addresses were cut at the first 42 characters on the verify screen, so the QR code and the text disagreed about where funds were going. Addresses now wrap across the full screen, and Zcash unified addresses get a dedicated text-first confirmation layout. - Font, draw and layout helpers gained the measurement and wrapping support those screens need. ROM: - Device snprintf/vsnprintf are redirected to newlib's integer-only engine (see cmake/caches/device.cmake), which removes the float formatting path, soft-double libgcc and its malloc dependency from the image. Percent and amount rendering that used %f is reworked to integer formatting, so THORChain withdraw percentages and send amounts still display exactly as before — Gate-3 frames under docs/security/evidence/rom-printf-integer-percent. - keepkey.ld asserts the 16 KiB stack reserve the SRAM budget gate measures.
msg_write() encoded outbound frames into a MAX_FRAME_SIZE TrezorFrameBuffer declared as an automatic — a ~12.4 KB stack frame. With the Orchard engine linked in, static SRAM left an ~11 KB gap and the device hard-faulted on boot during RC7 bring-up. Inbound reassembly, outbound encode and the recovery-cipher wordlist scratch are mutually exclusive on a strictly cooperative single-threaded transport (there is no USB ISR; usbd_poll runs only from explicit usbPoll call sites), so they now share one static union. Acquiring the arena for TX or scratch drops any partially reassembled inbound frame; only a host that pipelines a second request before reading the first response can observe it, and it gets a Failure on its next continuation frame rather than silent corruption. The reassembly state moves to file scope so arena acquisition can invalidate it.
|
CI queue note: this head was explicitly dispatched at https://github.com/BitHighlander/keepkey-firmware/actions/runs/31128230696 after the superseded 17-PR stack saturated the Actions queue. GitHub currently shows the jobs queued before runner assignment. The complete aggregate independently passed the CI-equivalent container suite locally: 405 firmware, 2 board, 18 crypto, and 7 Pallas constant-time tests, plus actionlint, gitleaks, the Pallas API-boundary gate, and git diff --check. |
Two problems with how this workflow gated the 7.15 audit stack. The pull_request trigger listed only master/develop/alpha, so every PR in the train except the first -- each based on the previous release branch -- matched nothing and reported "no checks" in the GitHub UI. The push trigger already covers 'release/**', so those branches were being built and were red; the PRs just never showed it. A reviewer saw a clean PR sitting on a failing build. Add 'release/**' to the pull_request branches so the checks attach to the PR. Second, the RC18 invariant forbidding libc random() in lib/rand/rng.c was introduced here, in the foundation slice, but the emulatorRandom() change that satisfies it arrives three slices later with the rest of the RNG work. The result was that this branch and the clear-signing branch failed check-submodules and skipped every build and test job behind it -- nothing was compiled or run on either. Move the invariant to the commit that makes it true; a gate that fails for code its own PR does not contain teaches reviewers to ignore the gate. No invariant is lost: it comes back, unchanged, in the RNG slice.
|
Superseded by #364, which now carries the whole 7.15 stack against develop. Once the CI gate stopped short-circuiting the build (the libc-random() invariant was asserted three slices before the fix that satisfies it, so check-submodules failed and every build/test job was SKIPPED), these branches compiled for the first time — and none of them compile. The topic-based split cuts across at least three signature/caller pairs:
The dependency graph is a tangle, not a chain, so re-slicing it by build order means re-authoring the release. Only the complete set compiles, and #364 is green. No content is dropped. |
What changed
The
python-keepkeyrelease pin is deliberately deferred to bundle 6/6. That keeps this foundation PR from running client tests for firmware features that are not present yet.Why
This is the buildable review foundation for the 7.15 audit stack. Dependency changes are explicitly identified as dependency baselines rather than being hidden under an “infra only” label.
Validation
actionlint .github/workflows/ci.ymlgitleaks detect --source . --log-opts=HEADgit diff --checkStack: 1 of 6. Base:
develop.