Skip to content

release(7.15.0-rc18): final audit candidate#320

Merged
BitHighlander merged 22 commits into
developfrom
audit/7.15.0-rc18-final
Jul 26, 2026
Merged

release(7.15.0-rc18): final audit candidate#320
BitHighlander merged 22 commits into
developfrom
audit/7.15.0-rc18-final

Conversation

@BitHighlander

@BitHighlander BitHighlander commented Jul 24, 2026

Copy link
Copy Markdown
Owner

Summary

Stages firmware 7.15.0 RC18 as a full dress-rehearsal PR against the exact upstream develop baseline. RC18 includes the regular multi-chain firmware with Zcash Orchard privacy and the bitcoin-only firmware. There is no separate Zcash artifact.

This remains a draft for final human and security review. Do not merge, tag, sign, or publish it yet.

Human review map

The release is deliberately split into four review targets:

Area Review target Exact candidate
Crypto, Orchard/Pallas, security backports keepkey/trezor-firmware#4 (merged) 62230ee620fa9ea2bdd2c8067be7fde3f9362248
Python integration keepkey/python-keepkey#197 addc0242847cd7be9c402980498b321b344bef34
Device protocol keepkey/device-protocol#112 6d0ae670e287a75338244fe82c4bef33a920a2ee
Firmware integration, release shape, UI, and gates this PR fd1012c5adbacf88e2ca521a95b335a2849d528f

Moving the crypto source back to the pinned KeepKey Trezor fork and removing an out-of-scope future-work document reduced this firmware PR to 168 files, 21,569 additions, and 1,888 deletions. The crypto PR is 54 files, 5,806 additions, and 372 deletions, organized as reviewable commits for the primitives, security backports, constant-time implementation, latency boundary, signing correctness/progress, and fork-owned CI/provenance.

PR #319's multiline signed-message fix and unit coverage are included here; #319 is closed as superseded.

Why this PR is 21,569 lines

The final diff does not contain generated protocol or vendored crypto source. The
dependency changes are three one-line submodule repins. The additions break down
as follows:

Area Additions
Production implementation under lib/ 11,269
Unit and regression tests 7,273
Public headers and transport bounds 1,462
Security/release documentation 354
SRAM, constant-time, and API-boundary tools 680
GitHub CI and release workflows 356
Remaining build, script, and submodule wiring 175
Total 21,569

Classifying the same additions by directly named feature path gives 5,789 lines
of Zcash/Orchard, 3,422 Hive, 2,980 clearsign/authenticator, 1,969
Tendermint-family, 1,530 Ethereum, 1,028 TRON, 1,022 Solana, and 3,829 shared
UI, storage, emulator, build, security, and release work. Removing tests,
provenance, or safety gates would reduce the displayed line count while making
the release harder to review and less safe.

The review-shape problem is commit history: accd11d9 staged 20,961 additions
as one snapshot after the fork's develop branch was reset to upstream. The
same work had already been separated into reviewable PRs before that reset:

Review slice Prior PR
EVM clearsign and Ethereum hardening upstream #444
Hive, initial Orchard, Ripple, THORChain upstream #445
BIP-85, recovery, fault hardening upstream #446
TRON, Solana, TON, Maya/THOR clearsign upstream #447
Build variants, seed lock, version upstream #448
Consolidated feature line fork #311
Router and round-12 remediation fork #313
Zcash progress UX fork #314
Hive phase 3 and wire correction fork #315, #316
Full signing/display/security hardening fork #317
RC-tag/release pipeline fork #318
Multiline exact-byte display fork #319

For upstream review, #320 should remain the exact aggregate integration and
release-evidence candidate. The smaller feature PRs can be refreshed and merged
bottom-up; as they land, the remaining #320 diff collapses to the final RC18
integration, constant-time Zcash repair, and dependency repins. Reopening only
the old five-PR upstream stack would still leave 11,642 additions because it
predates the later Hive and full-surface security work. Replaying the complete
previously merged fork sequence through #318 leaves only 1,675 additions and
562 deletions for the final RC18 integration layer.

Release shape

  • full / regular: the normal multi-chain firmware, including Zcash shielded/Orchard support;
  • bitcoin-only: Bitcoin-only firmware with non-Bitcoin chains and Zcash privacy compiled out;
  • no separate zcash-privacy build, artifact, emulator leg, or SRAM gate;
  • the regular and bitcoin-only products both remain release-gated.

Security-review disposition

  1. Orchard secret-scalar side channel — fixed and independently reviewed. The Pallas/RedPallas secret path now uses a fixed 255-round schedule, branchless point selection, complete-by-selection Jacobian addition, fixed-exponent inversion, and radix-2^16 Montgomery arithmetic. The Cortex-M3 disassembly gate rejects secret-conditioned branches, variable loop bounds, and operand-dependent long multiply/divide instructions. Independent numerical review reconstructed the multiplier, point formulas, and scalar ladder against reference arithmetic.
  2. Predictable emulator RNG — fixed. Emulator random32() now uses the OS CSPRNG path with complete-read, interruption, and failure handling; there is no libc random() fallback.
  3. Mutable release inputs — fixed. The release builder is digest-pinned, GitHub Actions are full-SHA-pinned, and release artifacts include provenance.
  4. Persistent clearsign trust anchors — fixed for RC18. Persistent identities are retired. Persistence requests are rejected before session mutation, signers are session-only, and legacy records are scrubbed.

Physical power/EM leakage assessment on STM32 remains a separate assurance gate. Software tests and structural disassembly checks do not replace it.

Zcash correctness and device UX

The RC18 flow validates, clear-signs, and hashes every Orchard action, but signs only real spends. Dummy-spend signatures created by PCZT finalization remain intact. This fixes the physical shield failure where firmware attempted to sign dummy actions and eventually returned RedPallas signing failed.

The device now reports progress for all three long-running phases that physical testing exposed:

  • Orchard account-key derivation;
  • action/CMX verification through the public Sinsemilla loop;
  • fixed-round constant-time RedPallas signing.

The public verification path is kept separate from the secret constant-time path, preserving the security property without forcing every public operation through the slow ladder.

Evidence

Crypto fork PR head 323e50d19..., canonically merged as 62230ee62...:

  • hosted Crypto audit CI is green on the exact PR head;
  • the PR head and canonical merge commit have the identical tree object 63d0766a248a8b5c849cfbd4757e6dad0d6c3c78;
  • 158/158 optimized trezor-crypto checks passed locally;
  • 158/158 ASan/UBSan checks passed locally;
  • Pallas constant-time and sanitized harnesses passed;
  • Valgrind secret-flow coverage and ARM disassembly gates are part of the pinned fork CI;
  • the forked crypto/ source is byte-identical to the crypto source exercised by the preceding firmware candidate.

Firmware evidence:

  • the physical-device candidate at 9d28cb3fde9dd2f1ec532368221bd3337bc1dcf1 completed shield, deshield, and Orchard-to-Orchard private send with the repaired progress UI;
  • run 30218813159 is fully green on pre-merge-pin head 5003ee6279d3cdbaad267d6a452d863d06a19133;
  • run 30220308264 built both canonical-repin ARM variants at a643f627a67b5d633007b54d541a0faf061fce21 and proved their executable payloads byte-identical to the tested candidate;
  • run 30220773721 is fully green on the exact reduced head fd1012c5adbacf88e2ca521a95b335a2849d528f;
  • 593 Python exact-image tests were collected: 581 passed, 12 skipped, 0 failed;
  • screenshot selection: 187/187 passed, with 897 OLED PNGs captured;
  • generated release report: 303/306 passed, 3 skipped, 0 failed, 0 pending; Zcash Orchard is accurately reported as 21/21 in the regular product;
  • full and bitcoin-only ARM builds, SRAM gates, emulator builds, native units, dylib tests, cppcheck, gitleaks, optimized crypto, ASan/UBSan, Valgrind, and report-catalog validation passed.

Exact-head artifact comparison (fd1012c5...):

  • full packaged firmware SHA-256: 6616b49602f453faee960043917b1e2cdb48d09585013557ea72c4076cd76eb9;
  • bitcoin-only packaged firmware SHA-256: 41303c45da55b3c58bfb70af56d088b9c1b007ea1753d80479739937b9d28abe;
  • executable payload SHA-256: 200e6507fde1bab941eed885a124de1ecb2d3c35f5e4d0eb43eeafb89f1587f9;
  • KeepKey variant binary SHA-256: b03f72ec9be230ca779e2f9d9cab24b49358d72234f99acc054293f52bb69b4c;
  • generated audit-report PDF SHA-256: 0e759c57a487556472d2bc604fcccdba143fd9c37f2c786460fceac69de45947;
  • the final full and bitcoin-only payloads and KeepKey variant binaries are byte-identical to both the hardware-tested 9d28cb3f... candidate and the green fork-projection a049a8b4... candidate;
  • package sizes are unchanged. Relative to canonical-repin head a643f627..., the only 38 differing bytes are inside the contiguous embedded Git commit SHA.

Fork policy

The firmware pins the exact reviewed commit from the KeepKey Trezor fork; it does not depend on a mutable branch. The fork is still 7,996 monorepo commits behind the audited upstream point. PR #4 records the upstream security triage through trezor/trezor-firmware@90e07df785d6b812e030cf841f75d8a641ab466b and owns the standalone crypto gates.

Updating the whole fork is intentionally a post-RC18 modernization task: the current upstream crypto tree differs from the tested RC18 tree across 156 files, so combining that migration with this release would invalidate the existing crypto and hardware evidence.

Remaining release gates

Do not tag, merge, sign, or publish RC18 until every remaining gate is complete.

@BitHighlander

Copy link
Copy Markdown
Owner Author

Dress rehearsal evidence for candidate
7683f10e624c40da21d2a57ed047425cd4c1bb02:

  • Hosted CI: https://github.com/BitHighlander/keepkey-firmware/actions/runs/30129710556
  • Regular ARM + SRAM: pass; 19,064 B reserve, 7,664 B largest
    frame, 11,400 B post-frame margin; zcash.c.obj present.
  • Bitcoin-only ARM + SRAM: pass; 32,908 B reserve, 7,664 B largest
    frame, 25,244 B post-frame margin; no zcash.c.obj.
  • Regular emulator units: 363/363 firmware, 2/2 board, 4/4 crypto.
  • Bitcoin-only emulator units: 28/28 firmware, 2/2 board, 4/4 crypto.
  • Workflow YAML, SRAM budget JSON, diff check, and stale
    zcash-privacy release-gate scan: pass.
  • Two clean regular ARM builds with the complete recursively initialized,
    pinned submodule graph were byte-identical:
    08b51c3f0b7c45dc9917befed00152482f58b90735f7f224f6010292b024a1be.
  • Bitcoin-only artifact SHA-256:
    ca3d4157ba849231d26842a7e38b82f7a33ea019e573ebb7c017fba9c4500497.

The RC-tag release workflow itself previously completed successfully for RC17
after the tag/prerelease hardening:
https://github.com/BitHighlander/keepkey-firmware/actions/runs/30038760639.
RC18 remains intentionally untagged while this draft is under final audit.

Remove the trezor-firmware submodule dependency and vendor the audited crypto subtree with applicable upstream security backports, regression coverage, provenance documentation, and firmware cache clearing.
Retain the complete default Gitleaks ruleset while excluding only published AES vectors and Ed25519 C declarations from the generic-api-key heuristic.
The first hosted run completed cppcheck in 9m40s under a 10-minute job timeout. Raise the bound to 15 minutes to avoid timing-dependent RC18 gate failures.

Copy link
Copy Markdown
Owner Author

Pushed the constant-time Pallas/RedPallas remediation as bfc0f3e9f7bd64a779e039fc3aa02f4ab4a855d9.

Validation on the exact source:

  • fixed 255-round scalar schedule with double/add/select in every round
  • branchless complete-by-selection Jacobian addition and fixed-exponent inversion
  • radix-2^16 Montgomery arithmetic; Cortex-M3 output contains no operand-dependent long multiply/divide instructions
  • ARM disassembly gate passes with no secret-conditioned branch or IT
  • 366 firmware tests pass, including all 59 Zcash tests; board 2/2, crypto 4/4, Pallas CT 6/6
  • ASan/UBSan, Valgrind secret-taint, cppcheck, SRAM, and bitcoin-only exclusion gates pass

This fixes the known variable-time implementation. The PR intentionally remains draft. Independent cryptographic review, physical power/EM leakage assessment, hosted CI on this exact head, the exact-pinned full-image rehearsal, and canonical dependency repins remain release gates. Do not tag, sign, merge, or publish yet.

Copy link
Copy Markdown
Owner Author

Exact-head CI is green: run 30179957180 completed successfully on bfc0f3e9f7bd64a779e039fc3aa02f4ab4a855d9.

Both ARM artifacts built successfully. The primary physical-test image is the regular/full artifact firmware-v7.15.0-bfc0f3e-full, which includes Zcash Orchard. GitHub artifact ZIP digest: sha256:201977be0d9b4f3e522059b00df6fe751f2b8a1d853a4d6091a903e2fd5f92f3. Complete firmware image SHA-256: 399e39524db2c76a9914796e163de531bf51bc703c7f9678306d8deae4d48372; payload-only SHA-256: 73aef508fb590e393a962bba2900f7cbcaee0b734000cc6f0552760b3115af53.

Independent cryptographic review is recorded as complete. The PR remains draft; next gate is flashing this exact unsigned image to a test device and exercising boot, Zcash Orchard signing/performance, Bitcoin/EVM smoke tests, reconnect behavior, and repeated power cycles.

@BitHighlander

Copy link
Copy Markdown
Owner Author

Physical RC18 dress rehearsal on bfc0f3e confirmed the Zcash PCZT flow was correct but exposed a severe latency regression: each Orchard action took more than five minutes before confirmation.

Root cause: the constant-time Pallas integration replaced the public affine compatibility path globally. Orchard cmx verification performs roughly 218 public Sinsemilla point additions per action, so routing all of them through the fixed-schedule projective path dominated runtime.

Head 030c43e repairs the boundary:

  • RedPallas authorization scalars, nonces, key reduction, transmission-key derivation, Sinsemilla blinding, and the final secret-dependent add remain constant-time.
  • Repeated Sinsemilla additions over host-provided transaction commitment data use the fast public path.
  • CI now enforces this API boundary structurally.
  • The independent-review Montgomery multiplication precondition is documented and the challenge product is wiped.

Local evidence on the exact pinned builder:

  • 1086-bit commitment benchmark: 0.913-0.937s on bfc0f3e versus 0.093-0.096s on 030c43e, same output.
  • 366 firmware, 2 board, 4 crypto, 6 Pallas constant-time, and 59 Zcash tests pass.
  • Full Cortex-M3 build and constant-time disassembly gate pass.
  • SRAM reserve 19,064 B; largest frame 7,664 B; remaining margin 11,400 B.
  • Local full firmware SHA-256: 1ae160c14791bd6615d0ceca33aefe2b5521ce09d904f36cb164453f9084ee9e.

The PR remains draft. bfc0f3e is superseded; 030c43e still requires green CI and a fresh physical timing/signing retest before RC approval.

@BitHighlander

Copy link
Copy Markdown
Owner Author

CI run 30181705474 is fully green on exact head 030c43e. All crypto, Valgrind, ASan/UBSan, static analysis, full and bitcoin-only ARM/emulator builds, SRAM/disassembly gates, unit suites, Python integration, dylib screenshot tests, and aggregate reporting passed.

The authoritative GitHub-built regular/full Zcash firmware is artifact firmware-v7.15.0-030c43e-full. Its complete firmware image SHA-256 is:

68e2c0d1807176191632903af65e96b78e74495cec283e4413f07774d4065533

This supersedes both the slow bfc0f3e image and the locally built pre-CI checksum recorded above. PR remains draft pending the physical two-action Orchard timing and final serialized-transaction verification.

@BitHighlander

Copy link
Copy Markdown
Owner Author

Hardware-test candidate update for exact head b6e6e5ff3c2503fec828c82fbbae31b02722db8c.

The apparent 0% hang was real: the existing progress trickle advanced only from usbPoll(), so it could not redraw while the device was inside the CPU-bound constant-time Pallas scalar loop.

This head:

  • reports OLED progress from each of the fixed 255 public loop rounds, mapped monotonically across the Orchard actions;
  • removes one of the two dominant constant-time basepoint multiplications per action by deriving and verifying public rk = ak + [alpha]G from cached ak;
  • keeps secret ask/rsk, nonce, and secret-IVK operations on the constant-time path;
  • uses the fast public path for transaction-public Sinsemilla note blinding;
  • extends schedule, API-boundary, mismatch-rejection, and ARM disassembly tests.

CI run 30185858191 is fully green: crypto/Valgrind/ASan/UBSan, static analysis, both ARM builds and SRAM gates, both emulator/unit variants, dylib tests, Python integration, and test-report generation.

Full device-test artifact: firmware-v7.15.0-b6e6e5f-full

Flash image SHA-256 (firmware.keepkey.v7.15.0-b6e6e5f-full-firmware.keepkey.bin):

098edb928cca37f66e18234e5cb17fd842ea36d304f6d5c5c6d1e781adf4bf7f

Remaining release gate: measure on real hardware. Confirm that the signing bar advances smoothly from 0–50% for action 0 and 50–100% for action 1, record each action's elapsed time, and complete/broadcast the shield transaction. The expected speedup is approximately 2x in the dominant RedPallas portion, but the hardware measurement is authoritative.

PR intentionally remains draft; no tag/release action taken.

@BitHighlander
BitHighlander marked this pull request as ready for review July 26, 2026 21:46
@BitHighlander
BitHighlander merged commit dd2f156 into develop Jul 26, 2026
15 checks passed
@BitHighlander

Copy link
Copy Markdown
Owner Author

RC19 follow-through: merged as dd2f156f589c001ddbbe73f5fdaf0033890dc13c, preserved as signed annotated tag v7.15.0-rc19, and validated by exact-commit CI 30221786081. The clean 12-commit upstream presentation is keepkey/keepkey-firmware#452; its final tree is identical (f06cd8e87c71d96ad0c50f990e8cb5c7669f0772).

@BitHighlander

Copy link
Copy Markdown
Owner Author

Audit-record correction from the authoritative RC19 manifests: 200e6507fde1bab941eed885a124de1ecb2d3c35f5e4d0eb43eeafb89f1587f9, previously labeled above as an executable payload hash, is the full bootloader hash. RC19 firmware hashes are: regular full 22681eb2de6ad4c404bc2cf47da253dc36feb511a3f3af7d5f51e5be0fa4fa6e, regular payload 651e6f53f11dcddf3e890250d4b81093eabfd73a948aea68125e6e6d2bc4ff6a; bitcoin-only full 8c64b7001a0751fc0ad93b02d369bbc7502fe8cc804e88e80f9113e6bfafeb5f, bitcoin-only payload 835d99f08fe128268cc50fdf68450e1c2576aa3437cba49fe003f96f6fa0d29f. Provenance records commit dd2f156f... and the pinned builder digest.

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