Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
422 commits
Select commit Hold shift + click to select a range
7f34a66
docs(security): correct the accounting after review reopened two find…
BitHighlander Aug 12, 2026
fc092c8
fix(release): bind the manifest to one named image, and stop overstat…
BitHighlander Aug 12, 2026
bee5b29
fix(storage): _Alignas broke both ARM builds; repin the catalog
BitHighlander Aug 12, 2026
53866b9
docs(clearsign): two more protocol blockers — bootstrap and work acco…
BitHighlander Aug 12, 2026
3246b5f
fix(rng): make it link, feed the continuous test, and keep memcmp_s raw
BitHighlander Aug 12, 2026
b988dcc
docs(security): #366 and #368 did not build; record why that was miss…
BitHighlander Aug 12, 2026
5487e26
docs(security): put the cross-compile step in the build recipe too
BitHighlander Aug 12, 2026
e514301
fix(rng): keep the gate out of the boot path, and out of the bootloader
BitHighlander Aug 12, 2026
3f617b6
docs(security): hard gate — do not ship a bootloader from this tree yet
BitHighlander Aug 12, 2026
72ea186
descope(rng): seed-time gate only, opt-in, no deps and no bootloader
BitHighlander Aug 12, 2026
af933a5
fix(release): publish firmware only — never a bootloader
BitHighlander Aug 12, 2026
440e8f8
docs(security): record the post-7.15 RNG project and why the crypto b…
BitHighlander Aug 12, 2026
f4a0900
Merge PR #368 into develop [rc28]
BitHighlander Aug 12, 2026
cb52485
Merge PR #367 into develop [rc28]
BitHighlander Aug 12, 2026
f31a743
Merge PR #366 into develop [rc28]
BitHighlander Aug 12, 2026
d4265d9
feat(storage): make a wiping upgrade a build failure
BitHighlander Aug 13, 2026
0a2a604
docs(dice): what the roll digest proves, and what it cannot
BitHighlander Aug 13, 2026
88fe777
fix(storage): assert every version entry, not just the last
BitHighlander Aug 13, 2026
a3bd19f
docs(anti-rollback): withdraw a guarantee the hardware cannot provide
BitHighlander Aug 13, 2026
8392b2d
docs(clearsign): lock all ten blockers, and record what each decision…
BitHighlander Aug 13, 2026
eb12165
feat(release): verify firmware signatures host-side, before publishing
BitHighlander Aug 13, 2026
5ddfcf8
fix(policy): AdvancedMode is session state, not a flash bit
BitHighlander Aug 13, 2026
aa25a0b
docs(gate3): OLED proof for the AdvancedMode confirm, and say both tr…
BitHighlander Aug 14, 2026
1d3d5ec
Merge pull request #374 from BitHighlander/feat/verify-signatures
BitHighlander Aug 14, 2026
8c271ab
Merge pull request #375 from BitHighlander/docs/anti-rollback-recover…
BitHighlander Aug 14, 2026
986faf1
Merge pull request #372 from BitHighlander/fix/storage-version-gate
BitHighlander Aug 14, 2026
dd38324
Merge pull request #373 from BitHighlander/feat/session-scoped-advanc…
BitHighlander Aug 14, 2026
5bb8b19
ci: ship the emulator libs with every release, both platforms or neither
BitHighlander Aug 14, 2026
afe5876
docs(security): measure the ERC-20 token table and phase its retirement
BitHighlander Aug 15, 2026
67ef34f
chore(deps): bump python-keepkey to the canonical branch head
BitHighlander Aug 15, 2026
69c45a4
chore(deps): point the release submodules at upstream, not the fork
BitHighlander Aug 15, 2026
deff341
docs(clearsign): name Phase 0 as a shippable provider tier
BitHighlander Aug 15, 2026
3b5382e
Merge pull request #369 from BitHighlander/docs/clearsign-delegation-…
BitHighlander Aug 15, 2026
a19d1c0
Merge pull request #376 from BitHighlander/docs/clearsign-decisions-l…
BitHighlander Aug 15, 2026
cf7b3a7
Merge pull request #381 from BitHighlander/docs/phase0-provider-tier
BitHighlander Aug 15, 2026
ca53161
Merge pull request #370 from BitHighlander/docs/rc28-handoff
BitHighlander Aug 15, 2026
bca93fc
Merge pull request #379 from BitHighlander/docs/token-table-retirement
BitHighlander Aug 15, 2026
8eed825
docs(clearsign): state the scope as rules, not a phase number
BitHighlander Aug 15, 2026
4895b81
Merge pull request #382 from BitHighlander/docs/clearsign-scope-invar…
BitHighlander Aug 15, 2026
fc9c59e
merge develop into alpha, taking develop's tree wholesale
BitHighlander Aug 15, 2026
a70d128
Merge pull request #380 from BitHighlander/chore/bump-pyk-to-canonica…
BitHighlander Aug 16, 2026
b46e718
Merge pull request #378 from BitHighlander/ci/emulator-libs-release
BitHighlander Aug 16, 2026
dc6bd37
Merge pull request #371 from BitHighlander/fix/pin-kdf-30pct-faster
BitHighlander Aug 16, 2026
681df4a
Revert "Merge pull request #371 from BitHighlander/fix/pin-kdf-30pct-…
BitHighlander Aug 16, 2026
05e7a14
WIP: alpha <- develop merge, 40 symbol regressions outstanding
BitHighlander Aug 20, 2026
0573495
docs: branch SOP and the alpha merge handoff
BitHighlander Aug 20, 2026
dc657b8
merge(board): restore alpha's board/confirm symbols onto develop's im…
BitHighlander Aug 20, 2026
41949ea
merge(evm,rng): restore the clearsign handlers and the emulator rando…
BitHighlander Aug 20, 2026
37c3c10
docs(handoff): record batch 1 and 2 progress, 40 -> 32
BitHighlander Aug 20, 2026
768ebae
merge(storage): take alpha's storage.c and replay develop's ceremony …
BitHighlander Aug 21, 2026
1caded7
merge(thorchain,maya): alpha's labelled parser, carrying develop's me…
BitHighlander Aug 21, 2026
e49cf15
merge(transaction): alpha's file, carrying develop's cancel-is-not-a-…
BitHighlander Aug 21, 2026
b897174
merge(osmosis): keep alpha's canonical-input validators and develop's…
BitHighlander Aug 21, 2026
7843eb4
merge(evm): alpha's THOR/Maya and Uniswap handlers, with develop's st…
BitHighlander Aug 21, 2026
384ff3a
merge(direction): restore alpha's work in 12 files taken wholesale fr…
BitHighlander Aug 21, 2026
96046dd
merge(reset,solana,evm): the last two symbol regressions, and the dic…
BitHighlander Aug 21, 2026
f054e41
build: make the merge compile, and fix what the compiler exposed
BitHighlander Aug 21, 2026
affa4d1
fix(thorchain): disclose a fee whose affiliate slot is empty; correct…
BitHighlander Aug 21, 2026
c5ab505
tools: keep both merge gates, and record what the symbol gate cannot see
BitHighlander Aug 21, 2026
0b49508
tools: record which direction-gate flags were adjudicated, and why
BitHighlander Aug 21, 2026
ef440cb
fix: three merge defects the tests caught, and a harness race that hi…
BitHighlander Aug 21, 2026
b2853d3
docs(handoff): the merge is green; what it does and does not prove
BitHighlander Aug 21, 2026
d838471
fix(evm): a Uniswap recipient screen the user approved is an approval
BitHighlander Aug 21, 2026
ba4324c
merge: carry alpha's handoff commit into the merged tree
BitHighlander Aug 21, 2026
56d5ff8
chore(deps): repin python-keepkey to 9f3b176 — the Uniswap tests now run
BitHighlander Aug 21, 2026
f2ab054
ci(secret-scan): one allowlist form, so the config loads and CI runs …
BitHighlander Aug 21, 2026
dabfdf9
fix(build): three merge defects that only the ARM and bitcoin-only bu…
BitHighlander Aug 21, 2026
8999917
style: clang-format-20 the two comments added by the build fixes
BitHighlander Aug 21, 2026
22cb37f
fix(btc): an OP_RETURN output must re-arm the duplicate-transaction hash
BitHighlander Aug 21, 2026
62b999f
fix(variant): the bitcoin-only emulator must report EmulatorBTC, not …
BitHighlander Aug 21, 2026
10a9615
fix(storage): stamp the magic before serialising, not after
BitHighlander Aug 21, 2026
3b29ea7
fix(sram): restore alpha's arena-shared permutation; the ARM link was…
BitHighlander Aug 21, 2026
b83b054
Merge pull request #495 from BitHighlander/fix/715-opreturn-dupe-and-…
BitHighlander Aug 21, 2026
3fe000a
Merge pull request #496 from BitHighlander/fix/715-storage-magic-orde…
BitHighlander Aug 21, 2026
b42af37
Merge pull request #497 from BitHighlander/fix/715-sram-recovery-cipher
BitHighlander Aug 21, 2026
dda5310
chore(deps): repin python-keepkey to 1ed34a70
BitHighlander Aug 21, 2026
add6085
feat(features): report supports_taproot, which the firmware already i…
BitHighlander Aug 21, 2026
6569434
Merge pull request #498 from BitHighlander/fix/715-report-taproot-cap…
BitHighlander Aug 21, 2026
3aaacac
chore(deps): repin python-keepkey to d5560b589 (report module-prefix …
BitHighlander Aug 21, 2026
78c819b
docs: SRS for 7.15/7.16/7.17, the defect register, and how to read th…
BitHighlander Aug 21, 2026
302aeee
Merge pull request #499 from BitHighlander/docs/715-srs-and-atlas
BitHighlander Aug 21, 2026
b905186
chore(deps): repin python-keepkey to cedad1c72 (power-cycle portability)
BitHighlander Aug 21, 2026
1d6e6e6
docs(srs): say where the CI-test-signed schemas actually live
BitHighlander Aug 21, 2026
e48beaf
feat(solana): KKSOLSW1 -- show provider-attested lookup-table accounts
BitHighlander Aug 21, 2026
217fadf
chore(deps): repin python-keepkey to ba05282f8 (power-cycle runs on p…
BitHighlander Aug 21, 2026
7062713
Merge remote-tracking branch 'origin/alpha' into feat/715-kksolsw1
BitHighlander Aug 21, 2026
6136437
chore(deps): repin python-keepkey to af148d89e (revert my pb2 regener…
BitHighlander Aug 21, 2026
4d299a5
chore(deps): repin python-keepkey to ef34f3564
BitHighlander Aug 21, 2026
629a4da
Merge remote-tracking branch 'origin/alpha' into feat/715-kksolsw1
BitHighlander Aug 21, 2026
492d5d1
docs: the 7.16 reductive design, and what the token budget cannot fix
BitHighlander Aug 21, 2026
60c35e9
ci: actually run the screen audit, and repin the report fixes
BitHighlander Aug 21, 2026
69d3b6d
docs(7.15): record KKSOLSW1 as built, and how the release lands
BitHighlander Aug 21, 2026
6595102
Merge pull request #500 from BitHighlander/feat/715-kksolsw1
BitHighlander Aug 21, 2026
d3bb005
chore: repin python-keepkey — KKSOLSW1 is catalogued now that it is m…
BitHighlander Aug 21, 2026
2a16831
fix(policy): disabling AdvancedMode revokes loaded clear-sign signers
BitHighlander Aug 21, 2026
f830808
docs: R-2.2 now includes the AdvancedMode disable, and 7.16 carries o…
BitHighlander Aug 21, 2026
5acbe3a
docs(atlas): the counts reconcile now, and empty means something
BitHighlander Aug 21, 2026
0dfe1fe
docs(7.15): measured budget numbers, including what KKSOLSW1 costs
BitHighlander Aug 21, 2026
c8dc70e
fix(rng): implement the entropy audit budget C27 has been asserting
BitHighlander Aug 21, 2026
5898d6b
Merge pull request #502 from BitHighlander/fix/entropy-audit-budget
BitHighlander Aug 21, 2026
f522fa4
feat(eip712): the encoder core for device-driven structured signing
BitHighlander Aug 21, 2026
d17a28d
feat(eip712): encodeType with the alphabetical closure sort
BitHighlander Aug 21, 2026
f93b7f2
fix(eip712): bound the new messages in the .options the BUILD reads
BitHighlander Aug 21, 2026
0e494d1
Merge pull request #501 from BitHighlander/fix/advanced-mode-revokes-…
BitHighlander Aug 21, 2026
4fb334b
test(eip712): the sort canary passed under a plain reversal
BitHighlander Aug 21, 2026
cc5addc
test(eip712): assert PUBLISHED digests, not ones this test derives
BitHighlander Aug 21, 2026
f37853d
feat(eip712): the walk, wired into the FSM and fitting in SRAM
BitHighlander Aug 21, 2026
c52a435
feat(eip712): arrays, paid for by a kilobyte of decode buffer
BitHighlander Aug 21, 2026
19720fe
chore: repin python-keepkey for the EIP-712 streaming client and its …
BitHighlander Aug 21, 2026
dde1473
fix(eip712): clear the cppcheck and clang-format gates
BitHighlander Aug 21, 2026
d5b9600
merge alpha: entropy audit budget and AdvancedMode revocation
BitHighlander Aug 21, 2026
aa8b1d7
chore: repin python-keepkey for atlas section TD
BitHighlander Aug 21, 2026
95ad076
feat(firmware): add CTAP2 passkey support for 7.16
BitHighlander Aug 21, 2026
8c68952
fix(storage): take V20, because 18 and 19 are burned
BitHighlander Aug 22, 2026
937d5e9
Merge pull request #505 from BitHighlander/fix/passkey-storage-v19
BitHighlander Aug 22, 2026
9abf7f9
chore: repin python-keepkey for the V20 storage argument
BitHighlander Aug 22, 2026
9e00548
feat(7.16): reductive clear-signing, behind a KeepKey delegation
BitHighlander Aug 22, 2026
fc8fed2
fix(storage): bump STORAGE_VERSION to 20 as well as the ladder
BitHighlander Aug 22, 2026
4564ba8
chore: repin python-keepkey for the corrected LAST_SHIPPED assertion
BitHighlander Aug 22, 2026
d7ef7fa
fix(test): follow the V18 -> V20 rename into the unit tests
BitHighlander Aug 22, 2026
736fd43
fix(7.16): verify the certificate preimage the ceremony actually signs
BitHighlander Aug 22, 2026
d517523
fix(storage): name the burned versions in the switch, not in a comment
BitHighlander Aug 22, 2026
6e372a4
fix(7.16): a hardware build ships no clear-signing root
BitHighlander Aug 22, 2026
e0bea6a
style(eip712): fold_frame only reads its frame
BitHighlander Aug 22, 2026
53faa40
style: clang-format the domain separator macro
BitHighlander Aug 22, 2026
a96f0ff
test(eip712): a canary that fits, plus the closure's real ceiling
BitHighlander Aug 22, 2026
9c12720
Merge branch 'feat/715-eip712-structured' into feat/716-reductive
BitHighlander Aug 22, 2026
6aef3c1
Merge pull request #503 from BitHighlander/feat/715-eip712-structured
BitHighlander Aug 22, 2026
e44e499
fix(7.16): two ways a certified describer could conceal what it signed
BitHighlander Aug 22, 2026
fbc5e6d
chore: repin python-keepkey for the capability gates
BitHighlander Aug 22, 2026
c83bf8c
Merge remote-tracking branch 'origin/alpha' into feat/passkeys-7.16
BitHighlander Aug 22, 2026
3d1f1a5
test(7.16): re-mint the root against a key that still exists, + the c…
BitHighlander Aug 22, 2026
8c9c506
fix(sram): reclaim the kilobyte passkeys needed to link
BitHighlander Aug 22, 2026
f1973a1
fix(7.16): the revocation floor predated its own release cut
BitHighlander Aug 22, 2026
d69d8ea
style: clang-format the resampled ethereum icon table
BitHighlander Aug 22, 2026
b2d9345
chore: repin python-keepkey for the CI hang fix and the derived stora…
BitHighlander Aug 22, 2026
8e18407
chore: repin python-keepkey for the atlas catalog fix
BitHighlander Aug 22, 2026
a1d977b
Merge pull request #506 from BitHighlander/feat/716-reductive
BitHighlander Aug 22, 2026
a710bb5
Merge pull request #504 from BitHighlander/feat/passkeys-7.16
BitHighlander Aug 22, 2026
40da090
backport(security): the 7.15 audit fixes into alpha
BitHighlander Aug 23, 2026
9ed7d59
fix(display): seed and BIP-85 pages fit the width they are drawn at
BitHighlander Aug 23, 2026
9568f11
build(deps): pin alpha to the reconciled pyk line and the dp branch tip
BitHighlander Aug 23, 2026
71e6c1d
port(security): the a3da828 follow-up that PR #533 omitted
BitHighlander Aug 23, 2026
8b0457a
fix(display): page seed and BIP-85 locally, without new ButtonRequests
BitHighlander Aug 23, 2026
cbbe7a3
fix(display): close the review blockers in the local pager
BitHighlander Aug 23, 2026
ac42e0b
test(display): prove subpage content where DebugLink cannot observe it
BitHighlander Aug 23, 2026
49a9eb6
fix(display): preserve indentation, fail closed, restore SIGALRM
BitHighlander Aug 23, 2026
bd92e22
fix(tests): include order broke the emulator build
BitHighlander Aug 23, 2026
b67e535
fix(tests): fixture would not have linked, and the regression was inert
BitHighlander Aug 23, 2026
8007849
fix(bitcoin-only): identify physical firmware to Vault
BitHighlander Aug 23, 2026
f6ad7d8
test(bitcoin-only): assert firmware handler surface
BitHighlander Aug 23, 2026
5e76034
ci(release): verify bitcoin-only artifact boundary
BitHighlander Aug 23, 2026
c1fe648
fix(tests): geometry fixture creates no alarm and leaks no signal state
BitHighlander Aug 23, 2026
1cfa90a
ci(bitcoin-only): run Python integration matrix
BitHighlander Aug 23, 2026
d690567
test(bitcoin-only): pin exact product surface
BitHighlander Aug 23, 2026
2bc333a
fix(bitcoin-only): omit unused full variant cache
BitHighlander Aug 23, 2026
3dee2f0
fix(tests): one board bootstrap per binary, not one per file
BitHighlander Aug 23, 2026
08d3546
Merge pull request #535 from BitHighlander/fix/alpha-bitcoin-only-ide…
BitHighlander Aug 23, 2026
8290661
fix(ci): gate MAYA memo suite on full firmware
BitHighlander Aug 24, 2026
9c9046a
fix(tests): preserve C linkage for board bootstrap
BitHighlander Aug 24, 2026
0e0bff2
fix(ci): validate required suites per product
BitHighlander Aug 24, 2026
008dcd7
Merge pull request #534 from BitHighlander/fix/alpha-seed-bip85-display
BitHighlander Aug 24, 2026
78cbd65
Merge pull request #533 from BitHighlander/backport/7.15-security-to-…
BitHighlander Aug 24, 2026
18613c4
fix(tokens): drop seven ERC-20s that no longer exist on Ethereum
BitHighlander Aug 22, 2026
9bc5d23
test(tokens): keep retired contracts out of the coin table
BitHighlander Aug 24, 2026
e92c486
Merge pull request #536 from BitHighlander/cleanup/alpha-retired-erc20
BitHighlander Aug 24, 2026
482ae3c
fix(security): check bn_format() return value in 3 clear-sign paths, …
BitHighlander Aug 25, 2026
3514384
fix(cosmos-family): insert missing comma between multi-message JSON i…
BitHighlander Aug 25, 2026
45cbc13
remove(binance): delete the Binance Chain (Beacon Chain) signing path
BitHighlander Aug 25, 2026
be89112
fix(security): 3 clear-sign blank-amount bugs, multi-message comma bu…
BitHighlander Aug 25, 2026
bde9cad
fix(bitcoin): internal-transfer output path corrupts duplicate-transa…
BitHighlander Aug 25, 2026
a5fd251
fix(bitcoin): signing_abort() never scrubs the static privkey buffer
BitHighlander Aug 25, 2026
7614e81
fix(solana): disclose withdrawal destination and authority type; show…
BitHighlander Aug 25, 2026
da73417
fix(solana): >32 accounts fails closed instead of silently skipping s…
BitHighlander Aug 25, 2026
2216275
fix(hive): hive_prepare_account_sign() leaves the master root private…
BitHighlander Aug 25, 2026
7177eff
fix(ripple): report internal signing failures as failures; bound paym…
BitHighlander Aug 25, 2026
be47a9f
fix(storage): scrub plaintext PIN/wipe-code on every exit path in pin…
BitHighlander Aug 25, 2026
8283b0a
fix(storage): storage_readPolicyV1/storage_writePolicyV1 off-by-one l…
BitHighlander Aug 25, 2026
41bd48b
style(pin_sm.c): clang-format the change_wipe_code() goto-done refactor
BitHighlander Aug 25, 2026
858dfff
fix(security): round-2 signing/hygiene audit -- clear-sign disclosure…
BitHighlander Aug 25, 2026
9bb3703
fix(bitcoin): CRITICAL -- signing_abort() only zeroed the master-key …
BitHighlander Aug 25, 2026
f311af8
fix(ethereum): CRITICAL -- confirm_body_message[121] overflow reintro…
BitHighlander Aug 25, 2026
0f4dafc
fix(eos): CRITICAL -- isStandardAuthorization() ignored accounts_coun…
BitHighlander Aug 25, 2026
23481b2
fix(thorchain): missing multi-message comma fix (round-2 gap) + atoi(…
BitHighlander Aug 25, 2026
b0010be
fix(u2f): interleaved CTAP2 request could silently auto-approve a sta…
BitHighlander Aug 25, 2026
0bbabdc
fix(eip712): domain field whitelist gap + stale confirmation globals …
BitHighlander Aug 25, 2026
617ab79
fix(eip712_stream): eip712_validate_leaf() didn't bound-check BYTES f…
BitHighlander Aug 25, 2026
92430ab
fix(cosmos-family): escape validator_address/validator_src/dst_addres…
BitHighlander Aug 25, 2026
6d5e191
fix(security): round-3 critical audit -- master key never scrubbed, E…
BitHighlander Aug 25, 2026
aa88b99
fix(storage): preserve setup state and make commits crash-recoverable
BitHighlander Aug 25, 2026
307b593
fix(rng): fail closed when PIN and recovery permutations lose entropy
BitHighlander Aug 25, 2026
57f5675
fix(nanopb): reject bytes beyond exact schema capacity
BitHighlander Aug 25, 2026
8a906d6
fix(confirm): display exact binary payload without UTF-8 truncation
BitHighlander Aug 25, 2026
ab7c658
test(ethereum): exercise successful Uniswap liquidity confirmations
BitHighlander Aug 25, 2026
5ed6396
build(python): require signing-path report evidence
BitHighlander Aug 25, 2026
1fb4635
test(signing): enforce Solana and Ripple parser boundaries
BitHighlander Aug 25, 2026
f30a9a3
fix(solana): bind clear-sign prompts to signed identities
BitHighlander Aug 25, 2026
bcbe0db
fix(ci): scope secret scan to the triggering revision range
BitHighlander Aug 25, 2026
de74918
fix(ci): scope secret-scan to HEAD's own ancestry, not every branch o…
BitHighlander Aug 25, 2026
84b5296
fix(solana): bind remaining verified instructions to accounts
BitHighlander Aug 25, 2026
3f6834c
build(python): align retired signing integration vectors
BitHighlander Aug 25, 2026
7a2eae4
fix(ci): assert the verified scanner version
BitHighlander Aug 25, 2026
616b8d3
test(solana): prove reviewed and signed message slices match
BitHighlander Aug 25, 2026
c644d0e
build(python): preserve the RC18 compatibility gate
BitHighlander Aug 25, 2026
4003e4a
fix(bitcoin): validate multisig quorum before fee accounting
BitHighlander Aug 25, 2026
4ca24b8
fix(secrets): scrub wallet caches on authorization loss
BitHighlander Aug 25, 2026
c6fe3a0
test(bitcoin): isolate multisig quorum regression
BitHighlander Aug 25, 2026
2150c32
chore(deps): pin python-keepkey to the stale-test fixes surfaced by t…
BitHighlander Aug 25, 2026
42fff90
Merge pull request #585 from BitHighlander/fix/secret-scan-log-opts-s…
BitHighlander Aug 25, 2026
339f5d1
fix(storage): scrub AES iv/key-schedule and authdata key material on …
BitHighlander Aug 25, 2026
0a32516
fix(u2f): refuse a CTAP2 rp_id too long to fully display (#578)
BitHighlander Aug 25, 2026
a35e49f
fix(fsm): scrub CipherKeyValue derived key material (#579)
BitHighlander Aug 25, 2026
2b62d08
fix(transaction): size node_str to txin_check's ADDR_STR_LEN contract…
BitHighlander Aug 25, 2026
758cfe4
fix(recovery): preserve real cipher bytes across a backspace (#581, #…
BitHighlander Aug 25, 2026
97f0512
test(solana,ripple): add #550/#553 boundary regressions requested bef…
BitHighlander Aug 25, 2026
a91a176
Merge pull request #582 from BitHighlander/fix/round4-storage-secrets
BitHighlander Aug 25, 2026
fd9fca3
fix(ci): stop overwriting checksum-verified gitleaks with an unverifi…
BitHighlander Aug 25, 2026
2622906
Merge pull request #589 from BitHighlander/fix/round5-gitleaks-unveri…
BitHighlander Aug 25, 2026
40cc068
fix(ci): add explicit least-privilege permissions default
BitHighlander Aug 25, 2026
7fa7605
Merge pull request #590 from BitHighlander/fix/round5-ci-least-privil…
BitHighlander Aug 25, 2026
642632d
fix(ci): raise static-analysis timeout from 15 to 25 minutes
BitHighlander Aug 25, 2026
7a29564
Merge pull request #593 from BitHighlander/fix/round5-static-analysis…
BitHighlander Aug 26, 2026
2043162
test(binance): retain retirement regression
BitHighlander Aug 26, 2026
283a83f
Merge alpha after independent Round 4 review
BitHighlander Aug 26, 2026
93291e6
fix(nanopb): preserve descriptor layout for oneof fields
BitHighlander Aug 26, 2026
b0afc98
test(nanopb): prove descriptor pointer placement
BitHighlander Aug 26, 2026
7dfff0b
fix(omni): disclose unsupported transaction bytes
BitHighlander Aug 26, 2026
04b529f
fix(ethereum): disclose complete transform route
BitHighlander Aug 26, 2026
087615a
fix(tests): share confirmation driver across variants
BitHighlander Aug 26, 2026
d27a684
fix(ethereum): commit complete streamed calldata
BitHighlander Aug 26, 2026
92ae970
fix(build): reject empty token definitions
BitHighlander Aug 26, 2026
ec9ced7
build(python): add alpha audit follow-ups
BitHighlander Aug 26, 2026
facefc7
build(python): pin companion CI target
BitHighlander Aug 26, 2026
78731bc
build(python): include fork CI repair
BitHighlander Aug 26, 2026
54b169a
test(report): require native evidence before python report
BitHighlander Aug 26, 2026
7d3cf27
build(python): pin complete report remediation
BitHighlander Aug 26, 2026
896743d
build(python): pin RC18-compatible report coverage
BitHighlander Aug 26, 2026
e4ec531
build(python): pin merged alpha audit harness
BitHighlander Aug 26, 2026
893c93d
Merge pull request #587 from BitHighlander/fix/alpha-auditor-review
BitHighlander Aug 26, 2026
cb710ae
feat(solana): certify Relay routes on alpha
BitHighlander Aug 25, 2026
397e126
fix(solana): display certified native amount as SOL
BitHighlander Aug 25, 2026
1b029dd
test(solana): gate Relay certification in full FSM
BitHighlander Aug 25, 2026
4d7edee
ci(dylib): verify checked-out source revision
BitHighlander Aug 26, 2026
aee78b1
Merge pull request #607 from BitHighlander/feat/716-certified-solana-lut
BitHighlander Aug 26, 2026
79c2bc8
rehearsal: stage 7.16 after upstream 7.15
BitHighlander Aug 26, 2026
a12e806
Merge updated 7.15 release fixes into 7.16 rehearsal
BitHighlander Aug 26, 2026
e7937a0
fix(ctap2): invalidate credentials and harden ClientPIN
BitHighlander Aug 26, 2026
efe6da7
docs(release): define the complete 7.16 gate
BitHighlander Aug 26, 2026
91130eb
merge(develop): restack 7.16 after audited 7.15
BitHighlander Aug 27, 2026
5053626
ci(report): download the artifacts actually uploaded
BitHighlander Aug 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 77 additions & 34 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,11 @@ env:
BASE_IMAGE: kktech/firmware@sha256:7438e53933d47d53157ed6d96d864cb208597e62dce26235ace09d1063427fa2
EMU_IMAGE: kkemu-ci

# Least-privilege default. Jobs in this workflow only need repository reads;
# publishing uses DockerHub credentials and does not need a write-capable
# GITHUB_TOKEN.
# Least-privilege default: every job gets a read-only GITHUB_TOKEN unless it
# declares its own `permissions:` override (publish-emulator-libs does, for
# the `gh release` calls it needs `contents: write` for). Without this,
# every job -- including ones that just checkout/build/test -- inherited
# whatever the repo's default token scope was, with no explicit floor. #424.
permissions:
contents: read

Expand Down Expand Up @@ -103,37 +105,32 @@ jobs:
fetch-depth: 0

- name: Install gitleaks
# Pin and verify the only scanner binary that is installed/executed.
# Bumps require an independently recorded digest and ruleset review.
# PINNED + checksum-verified. Tracking releases/latest means a new
# upstream ruleset can turn this gate red with no change to this
# repository -- which is exactly what happened: a newer
# generic-api-key rule began flagging published BIP32 test vectors
# in 2014/2018 history, and because every build job declares
# `needs: [.., secret-scan]`, the whole build and test graph was
# SKIPPED rather than failed. Bump deliberately, with the scan
# re-verified and a fresh sha256 recorded below. See #424.
#
# This used to install this checksummed build and then immediately
# overwrite it with a second, unverified `curl | tar` of a different
# (older) version -- so the binary actually executed was never the
# one the checksum covered, defeating the point of pinning at all.
# See #586.
run: |
# PINNED to 8.30.0, deliberately, and VERIFIED.
#
# Two things this block has to get right at once, and a clean merge of
# two parents previously got exactly one of them:
#
# - the VERSION is pinned because tracking releases/latest lets a new
# upstream ruleset turn this gate red with no change to this
# repository. That happened: a newer generic-api-key rule began
# flagging published BIP32 test vectors in 2014/2018 history, and
# because every build job declares `needs: [.., secret-scan]`, the
# whole build and test graph was SKIPPED rather than failed (#424).
# - the BINARY is checksummed, because a scan is only worth what the
# executable running it is.
#
# The merged version downloaded 8.30.1 with a verified checksum and then
# overwrote it with an unverified 8.30.0 through `curl | tar`, so the
# checksum proved nothing about the binary that actually ran. One
# version, one archive, one verified digest. Bump deliberately, with the
# scan re-verified.
GITLEAKS_VERSION=8.30.0
GITLEAKS_SHA256=79a3ab579b53f71efd634f3aaf7e04a0fa0cf206b7ed434638d1547a2470a66e
GITLEAKS_VERSION=8.30.1
GITLEAKS_SHA256=551f6fc83ea457d62a0d98237cbad105af8d557003051f41f3e7ca7b3f2470eb
GITLEAKS_ARCHIVE="${RUNNER_TEMP}/gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz"
curl -sSfL --retry 3 --retry-all-errors \
"https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz" \
-o "${GITLEAKS_ARCHIVE}"
echo "${GITLEAKS_SHA256} ${GITLEAKS_ARCHIVE}" | sha256sum --check --strict
tar -xzf "${GITLEAKS_ARCHIVE}" -C /usr/local/bin gitleaks
gitleaks version
INSTALLED_VERSION=$(gitleaks version)
echo "gitleaks ${INSTALLED_VERSION}"
test "${INSTALLED_VERSION}" = "${GITLEAKS_VERSION}"

- name: Run gitleaks
env:
Expand All @@ -144,18 +141,22 @@ jobs:
run: |
set -euo pipefail

# fetch-depth: 0 makes every fork ref available. An unscoped scan
# therefore walks disconnected keepkey-stack histories that are not
# ancestors of this firmware change (#544). Scan only the revisions
# introduced by the triggering event.
# actions/checkout fetch-depth: 0 makes every fork branch available.
# An unscoped gitleaks run therefore scans unrelated branch histories;
# one keepkey-stack branch in this fork made every firmware build and
# test skip even though its commits are not ancestors of this change.
# Scan exactly the commits introduced by the event instead.
if [ "$EVENT_NAME" = "pull_request" ]; then
LOG_OPTS="${PR_BASE_SHA}..${PR_HEAD_SHA}"
elif [ "$EVENT_NAME" = "push" ] &&
[[ ! "$PUSH_BEFORE_SHA" =~ ^0+$ ]]; then
LOG_OPTS="${PUSH_BEFORE_SHA}..${GITHUB_SHA}"
elif [ "$EVENT_NAME" = "push" ]; then
# New branch: scan only the history reachable from its head, not
# every fetched ref in the repository.
LOG_OPTS="${GITHUB_SHA}"
else
# A manual run has no before/base pair. Scan the checked-out tree.
gitleaks detect --source . --no-git --verbose --redact
exit 0
fi
Expand All @@ -165,7 +166,11 @@ jobs:

static-analysis:
runs-on: ubuntu-latest
timeout-minutes: 15
# Was 15. cppcheck alone has been observed running right up to (and past)
# that ceiling under normal runner load with an unchanged, clean diff --
# two consecutive PR #591 runs hit 15m10s and 14m59s, one of them killed
# mid-scan, forcing a manual rerun of an otherwise-passing check. #592.
timeout-minutes: 25
steps:
- name: Checkout
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
Expand Down Expand Up @@ -462,7 +467,7 @@ jobs:
- variant: full
label: ""
suffix: ""
cmake_flags: ""
cmake_flags: "-DKK_CLEARSIGN_ALPHA_ROOT=ON"
- variant: bitcoin-only
label: " (bitcoin-only)"
suffix: "-bitcoin-only"
Expand Down Expand Up @@ -522,6 +527,10 @@ jobs:
python3 /root/keepkey-firmware/tools/check_pallas_ct_disassembly.py \
--elf bin/firmware.keepkey.elf \
--variant '${{ matrix.variant }}' && \
python3 /root/keepkey-firmware/tools/check_bitcoin_only_identity.py \
--artifact bin/firmware.keepkey.bin \
--elf bin/firmware.keepkey.elf \
--variant '${{ matrix.variant }}' && \
mkdir -p /root/keepkey-firmware/bin && \
cp bin/*.bin /root/keepkey-firmware/bin/ && \
cp bin/*.elf /root/keepkey-firmware/bin/ && \
Expand All @@ -530,6 +539,28 @@ jobs:
find . -name '*.su' -print0 | tar czf /root/keepkey-firmware/bin/stack-usage.tgz --null -T - && \
chmod -R a+rw /root/keepkey-firmware/bin"

- name: Assert alpha ClearSign root product boundary
run: |
# Full alpha must carry the hardware-held root that issued Vault's
# alpha certificates. Bitcoin-only excludes all non-Bitcoin signing
# code and must not carry it. Assert both sides using the CURRENT key;
# the prior gate still searched for the superseded 02be... root and
# could not detect the 02de... key this source actually compiled.
python3 - <<'EOF'
import sys
ALPHA_ROOT = bytes.fromhex(
"02de9231b2094433235532fb1932e324a2c7304195e12e610c675cccbbd606dae7")
blob = open("bin/firmware.keepkey.bin", "rb").read()
expected = "${{ matrix.variant }}" == "full"
present = ALPHA_ROOT in blob
if present != expected:
sys.exit("::error::alpha ClearSign root presence mismatch: "
"variant=${{ matrix.variant }}, expected=%s, present=%s"
% (expected, present))
print("Alpha root boundary verified: variant=${{ matrix.variant }}, "
"present=%s" % present)
EOF

# SRAM budget gate — RC7's privacy-enabled build hard-faulted on boot
# because static SRAM left an 11.2 KB gap while msg_write() carried a
# 12.4 KB stack frame. keepkey.ld now ASSERTs a 16 KiB reserve at link
Expand Down Expand Up @@ -638,6 +669,7 @@ jobs:
retention-days: 30

python-integration-tests:
name: python-integration-tests${{ matrix.label }}
needs: [lint-format, static-analysis, check-submodules, secret-scan, crypto-tests]
runs-on: ubuntu-latest
timeout-minutes: 30
Expand All @@ -646,10 +678,14 @@ jobs:
matrix:
include:
- variant: full
label: ""
cmake_flags: ""
project: kkci-full
python_artifact: python-test-results
oled_artifact: oled-screenshots
- variant: bitcoin-only
label: " (bitcoin-only)"
cmake_flags: "-DKK_BITCOIN_ONLY=ON"
project: kkci-bitcoin-only
python_artifact: python-test-results-bitcoin-only
oled_artifact: oled-screenshots-bitcoin-only
Expand All @@ -670,6 +706,9 @@ jobs:

- name: Build and run tests (docker compose)
working-directory: scripts/emulator
env:
COINSUPPORT: ${{ matrix.cmake_flags }}
KK_TEST_BUILD_VARIANT: ${{ matrix.variant }}
run: |
# Run each test container — capture exit codes, always extract reports
#
Expand Down Expand Up @@ -995,6 +1034,10 @@ jobs:
env:
KK_TRANSPORT: dylib
KK_DYLIB: ${{ env.DYLIB_PATH }}
# PR jobs expose a synthetic merge SHA as GITHUB_SHA, while Checkout
# above intentionally builds the head SHA. Bind the assertion to the
# exact source revision that produced this dylib.
KK_EXPECTED_FIRMWARE_REVISION: ${{ github.event.pull_request.head.sha || github.sha }}
run: |
# `keepkeylib/` on PYTHONPATH so the package's relative-style
# imports inside generated *_pb2.py files resolve.
Expand Down Expand Up @@ -1142,7 +1185,7 @@ jobs:
NOT_SUCCESS=$(echo "$NEEDS_JSON" \
| jq -r 'to_entries[] | select(.value.result != "success") | .key')
if [ -n "$NOT_SUCCESS" ]; then
echo "::error::Required jobs did not succeed: $(echo $NOT_SUCCESS | tr '\n' ' ')"
echo "::error::Required jobs did not succeed: $(printf '%s\n' "$NOT_SUCCESS" | tr '\n' ' ')"
echo "A skipped or cancelled required job is NOT a pass. If a gate-stage"
echo "job failed, everything downstream was skipped and produced no signal."
exit 1
Expand Down
39 changes: 31 additions & 8 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,22 +82,21 @@ jobs:
build-firmware:
needs: validate
runs-on: ubuntu-latest
timeout-minutes: 20
strategy:
fail-fast: false
matrix:
include:
# 'suffix' names the published files; 'variant' is the internal build
# selector. The default build takes an EMPTY suffix so its assets keep
# the names every previous release used (v7.14.x shipped
# firmware.keepkey.bin). Only bitcoin-only is qualified, because it is
# the unusual one.
# 'suffix' names the published files; 'variant' stays the internal build
# selector. The default build takes an EMPTY suffix so its assets keep the
# names every previous release used (v7.14.x shipped firmware.keepkey.bin).
# Only the bitcoin-only build is qualified, because it is the unusual one.
- variant: full
suffix: ""
cmake_flags: ""
- variant: bitcoin-only
suffix: "-bitcoin-only"
cmake_flags: "-DKK_BITCOIN_ONLY=ON"
timeout-minutes: 20
steps:
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6

Expand Down Expand Up @@ -138,6 +137,10 @@ jobs:
-DCMAKE_COLOR_MAKEFILE=ON \
${{ matrix.cmake_flags }} && \
make && \
python3 /root/keepkey-firmware/tools/check_bitcoin_only_identity.py \
--artifact bin/firmware.keepkey.bin \
--elf bin/firmware.keepkey.elf \
--variant '${{ matrix.variant }}' && \
mkdir -p /root/keepkey-firmware/release && \
cp bin/firmware.keepkey.bin /root/keepkey-firmware/release/ && \
cp bin/firmware.keepkey.elf /root/keepkey-firmware/release/ && \
Expand All @@ -154,6 +157,28 @@ jobs:
--su-tar release/stack-usage.tgz \
--budgets tools/sram-budgets.json \
--variant "${{ matrix.variant }}"
echo "# KeepKey Firmware v${{ needs.validate.outputs.fw_version }} — Hash Manifest" > HASHES.txt
echo "" >> HASHES.txt
# Provenance: name the exact toolchain these bytes came out of. BASE_IMAGE
# is a sha256 manifest digest, not a tag, so this identifies one immutable
# image rather than whatever the tag pointed at on the day. Without it a
# green CI build and a locally reproduced binary cannot be shown to be the
# same toolchain product. See GH #425.
echo "builder image ${BASE_IMAGE}" >> HASHES.txt
echo "source commit ${GITHUB_SHA}" >> HASHES.txt
echo "" >> HASHES.txt
for f in *.bin; do
[ -f "$f" ] || continue
FULL_HASH=$(sha256sum "$f" | awk '{print $1}')
echo "sha256 (full) $f $FULL_HASH" >> HASHES.txt
FILE_SIZE=$(stat -c%s "$f")
if [ "$FILE_SIZE" -gt 256 ]; then
PAYLOAD_HASH=$(tail -c +257 "$f" | sha256sum | awk '{print $1}')
echo "sha256 (payload) $f $PAYLOAD_HASH" >> HASHES.txt
fi
echo "" >> HASHES.txt
done
cat HASHES.txt

# A RELEASE PUBLISHES FIRMWARE ONLY -- never a bootloader.
#
Expand Down Expand Up @@ -209,8 +234,6 @@ jobs:
- name: Upload release artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
# Per-variant, because upload-artifact v4+ makes names immutable: two
# matrix legs writing one name is a hard failure, not a merge.
name: release-firmware-${{ matrix.variant }}
path: release/*
retention-days: 90
Expand Down
7 changes: 4 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ path = deps/device-protocol
branch = up/release-protocol
[submodule "deps/trezor-firmware"]
path = deps/crypto/trezor-firmware
url = https://github.com/BitHighlander/trezor-firmware.git
url = https://github.com/keepkey/trezor-firmware.git
branch = keepkey
[submodule "googletest"]
path = deps/googletest
url = https://github.com/google/googletest.git
Expand All @@ -13,8 +14,8 @@ path = code-signing-keys
url = https://github.com/keepkey/code-signing-keys.git
[submodule "deps/python-keepkey"]
path = deps/python-keepkey
url = https://github.com/keepkey/python-keepkey.git
branch = reconcile/upstream-sync
url = https://github.com/BitHighlander/python-keepkey.git
branch = develop
[submodule "deps/qrenc/QR-Code-generator"]
path = deps/qrenc/QR-Code-generator
url = https://github.com/keepkey/QR-Code-generator.git
Expand Down
18 changes: 7 additions & 11 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ endif()

project(
KeepKeyFirmware
VERSION 7.15.0
VERSION 7.16.0
LANGUAGES C CXX ASM)

set(BOOTLOADER_MAJOR_VERSION 2)
Expand All @@ -20,8 +20,7 @@ option(KK_EMULATOR "Build the emulator" OFF)
option(KK_BUILD_DYLIB "Build libkkemu shared library (.dylib/.so)" OFF)
option(KK_DEBUG_LINK "Build with debug-link enabled" OFF)
option(KK_BUILD_FUZZERS "Build the fuzzers?" OFF)
option(KK_BITCOIN_ONLY "Build Bitcoin-only firmware (strip all non-BTC coins)"
OFF)
option(KK_BITCOIN_ONLY "Build Bitcoin-only firmware (strip all non-BTC coins)" OFF)
# Zcash shielded/Orchard support is part of the regular firmware. It is an
# internal compile selection, not a third release variant: bitcoin-only strips
# the Zcash coin and privacy engine; every regular device/emulator build ships
Expand Down Expand Up @@ -117,9 +116,9 @@ add_definitions(-DED25519_FORCE_32BIT=1)
add_definitions(-DUSE_PRECOMPUTED_CP=0)

if(${KK_BITCOIN_ONLY})
# Strip the coin-specific trezor-crypto primitives whose only callers
# (ethereum.c / nano.c) are themselves compiled out of this image. KECCAK
# stays on: it is a generic hash, and the saving is not worth the risk.
# Bitcoin-only: strip the coin-specific trezor-crypto primitives whose only
# callers (ethereum.c / nano.c) are compiled out below. KECCAK stays on --
# marginal size win, and it is a generic hash we don't want to risk.
add_definitions(-DUSE_ETHEREUM=0)
add_definitions(-DUSE_NANO=0)
else()
Expand Down Expand Up @@ -171,11 +170,8 @@ else()
add_definitions(-DDEBUG_LINK=0)
endif()

# Value macros: always defined, 0 or 1, and always tested with `#if FLAG`.
# Device builds compile with -Wundef -Werror, so an undefined identifier inside
# `#if` is a hard error rather than a silent zero -- which is what we want,
# because a silently-zero guard would ship the coin engines into the stripped
# image.
# Value macros (always defined 0/1) -- device builds use -Wundef -Werror, so an
# undefined identifier in `#if` is a hard error. Guard code with `#if FLAG`.
if(${KK_BITCOIN_ONLY})
add_definitions(-DBITCOIN_ONLY=1)
else()
Expand Down
2 changes: 1 addition & 1 deletion deps/python-keepkey
Submodule python-keepkey updated 41 files
+26 −8 .circleci/config.yml
+237 −6 .github/workflows/ci.yml
+1 −1 device-protocol
+48 −5 keepkeylib/clearsign_abi.py
+7 −1 keepkeylib/clearsign_catalog.py
+45 −20 keepkeylib/client.py
+13 −2 keepkeylib/eth/ethereum_tokens.py
+16 −3 keepkeylib/eth/token_policy.py
+8 −0 keepkeylib/eth/uniswap_tokens.json
+4 −1 keepkeylib/eth/uniswap_tokens.py
+19 −12 keepkeylib/messages_solana_pb2.py
+53 −23 keepkeylib/signed_metadata.py
+20 −2 keepkeylib/transport_udp.py
+65 −55 scripts/generate-test-report.py
+5 −1 tests/common.py
+52 −0 tests/test_clearsign_abi.py
+16 −0 tests/test_dylib_confirm_flow.py
+24 −0 tests/test_message_signing_protocol_bindings.py
+29 −0 tests/test_msg_binance_sign_tx.py
+0 −1 tests/test_msg_bip85.py
+6 −0 tests/test_msg_eip712_streaming.py
+11 −1 tests/test_msg_eos_signtx.py
+25 −8 tests/test_msg_ethereum_clear_signing.py
+8 −0 tests/test_msg_ethereum_clearsign_additive.py
+3 −19 tests/test_msg_ethereum_erc20_uniswap_liquidity.py
+191 −30 tests/test_msg_ethereum_signing_guards.py
+9 −4 tests/test_msg_ethereum_signtx.py
+3 −1 tests/test_msg_mayachain_signtx.py
+108 −1 tests/test_msg_osmosis_signtx.py
+7 −0 tests/test_msg_recoverydevice_cipher.py
+25 −11 tests/test_msg_resetdevice.py
+47 −4 tests/test_msg_session_trust_lifetime.py
+4 −1 tests/test_msg_solana_lut_attestation.py
+87 −12 tests/test_msg_solana_signtx.py
+21 −0 tests/test_msg_zcash_sign_pczt_device.py
+3 −0 tests/test_multisig.py
+0 −45 tests/test_report_variant_validation.py
+10 −4 tests/test_sign_typed_data.py
+105 −20 tests/test_storage_version_gate.py
+186 −0 tests/test_token_table_generators.py
+3 −3 tests/test_verify_typed_data.py
Loading
Loading