Skip to content

release: integrate 7.14.1 firmware updates#425

Merged
BitHighlander merged 13 commits into
developfrom
release-7141
May 9, 2026
Merged

release: integrate 7.14.1 firmware updates#425
BitHighlander merged 13 commits into
developfrom
release-7141

Conversation

@BitHighlander

Copy link
Copy Markdown
Collaborator

Summary

Integrates the 7.14.1 firmware work onto upstream develop from upstream branch release-7141.

Includes:

Notes:

  • This PR is intentionally Zcash-free.
  • The python-keepkey/device-protocol pins can be moved back to their canonical branches after those upstream PRs merge.

Validation

  • git diff --check keepkey/develop..HEAD

CI's python-dylib-tests job runs `pytest test_dylib_screenshot.py` from
deps/python-keepkey/tests, but the previous submodule pin (7141dc8) did
not contain that file, so pytest exited 4 ("file or directory not
found") and the job failed.

Bump python-keepkey to 571c829, which adds the regression test for the
ringbuf capacity + DebugLinkGetState canvas-refresh fixes that landed
on this release branch.
…t tests

The screenshot regression added in 40eda37 hung CI for 25min because
tests/config.py had no KK_TRANSPORT=dylib branch, so it fell through
to UDPTransport against an emulator that the python-dylib-tests job
doesn't start. Bumps python-keepkey to f1a77c3 which adds:

  - keepkeylib/transport_dylib.py: ctypes singleton over libkkemu,
    pumps kkemu_poll on every read/write
  - tests/config.py: KK_TRANSPORT=dylib KK_DYLIB=... branch + a
    _KNOWN_TRANSPORTS guard so a typo'd value errors at import
    instead of silently falling back to UDP
  - tests/test_dylib_confirm_flow.py: confirm-flow regression
    (skipped pending the firmware confirm-helper fix)

Verified locally: 5 passed, 1 skipped in 0.22s.
Both release branches are now merged to master.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Integrates the upstream 7.14.1 firmware work into develop, adding new emulator capabilities (including an in-process shared library) and extending message-signing support for TRON/TON/Solana, along with CI coverage for the dylib emulator path.

Changes:

  • Add libkkemu shared-library emulator mode (ring-buffer I/O, framebuffer capture) alongside the existing UDP-based kkemu binary.
  • Add TRON TIP-191 signing + verify and TIP-712 typed-hash signing; add TON raw Ed25519 message signing (AdvancedMode-gated); add Solana off-chain domain-separated message signing.
  • Extend CI to build and run python-keepkey dylib screenshot tests (macOS), and update build system options/policies for cross-directory linking + PIC.

Reviewed changes

Copilot reviewed 28 out of 28 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
CMakeLists.txt Adds CMP0079 policy handling and KK_BUILD_DYLIB option; enables global PIC when building dylib.
tools/emulator/CMakeLists.txt Refactors firmware lib list and wires it into both kkemu (UDP) and kkemulator_dylib (shared lib) link steps.
lib/emulator/CMakeLists.txt Adds kkemulator_dylib shared library target and includes new dylib-specific sources.
lib/emulator/udp.c Adds dylib trampolines (ring-buffer mode) and supports configurable UDP port via env var in standalone mode.
lib/emulator/setup.c Adds setup_urandom_only() for dylib mode initialization.
lib/emulator/ringbuf.h Introduces ring buffer interface/constants for HID-report transport.
lib/emulator/ringbuf.c Implements ring buffer push/pop used by the dylib transport.
lib/emulator/libkkemu.c Implements libkkemu public API, ring-buffer transport, flash buffer handling, and display capture ring.
include/keepkey/emulator/setup.h Exposes setup_urandom_only() for dylib build.
include/keepkey/emulator/libkkemu.h Adds public C API for in-process emulator usage (init/poll/read/write/display/frame capture).
lib/firmware/tron.c Adds TIP-191 message hashing/signing, signature verification, and TIP-712 typed-hash digest signing.
lib/firmware/ton.c Adds raw Ed25519 message signing primitive for TON.
lib/firmware/solana.c Adds Solana off-chain, domain-separated message signing envelope + signature generation.
lib/firmware/messagemap.def Registers new TRON/TON/Solana message types and responses in the dispatch map.
include/keepkey/firmware/fsm.h Declares new FSM handlers for TRON/TON/Solana message types.
lib/firmware/fsm_msg_tron.h Adds TRON SignMessage / VerifyMessage / SignTypedHash handlers with on-device review flows.
lib/firmware/fsm_msg_ton.h Adds TON SignMessage handler with AdvancedMode policy gate and user confirmation.
lib/firmware/fsm_msg_solana.h Adds Solana SignOffchainMessage handler with format/version validation and confirmation UI.
lib/firmware/fsm_msg_debug.h Adjusts DebugLinkGetState to refresh display without forcing animations.
include/keepkey/transport/messages-tron.options Adds nanopb sizing constraints for new TRON message types.
include/keepkey/transport/messages-ton.options Adds nanopb sizing constraints for TON SignMessage/response.
include/keepkey/transport/messages-solana.options Adds nanopb sizing constraints for Solana off-chain message signing types.
include/keepkey/firmware/tron.h Exposes TRON message sign/verify and TIP-712 typed-hash signing APIs.
include/keepkey/firmware/ton.h Exposes TON message signing API and documents required policy gate.
include/keepkey/firmware/solana.h Exposes Solana off-chain message signing API.
.github/workflows/ci.yml Adds macOS dylib build + python-keepkey screenshot tests; threads dylib job into publish prerequisites and report label.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread lib/firmware/tron.c
Comment thread include/keepkey/emulator/libkkemu.h Outdated
Comment thread lib/emulator/libkkemu.c
Comment on lines +43 to +52
/*
* Captures every display_refresh() into a ring of 1-bit packed snapshots.
* The host drains via kkemu_pop_frame(). Adjacent identical frames are
* skipped so an idle firmware doesn't spam the ring.
*
* Sized for ~4 seconds at 16ms refresh; if the host falls behind the
* oldest frames are dropped (write advances past read).
*/
#define FRAME_PACKED_SIZE 2048
#define FRAME_RING_SIZE 64
Comment thread lib/emulator/ringbuf.c Outdated
pastaghost and others added 2 commits May 9, 2026 15:23
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
…ture

Copilot autofix in 2746ed3 copy-pasted the has_* pattern from the
TronMessageSignature path (where fields are 'optional' so nanopb emits
has_* flags) into tron_typed_hash_sign(), where the response type is
TronTypedDataSignature with 'required' fields — no has_* exists, so
the build broke on every target.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 28 out of 28 changed files in this pull request and generated 4 comments.

Comment thread lib/firmware/tron.c
Comment thread lib/emulator/libkkemu.c
Comment on lines +241 to +253
int kkemu_write(const uint8_t* data, size_t len, int iface) {
if (!libkkemu_initialized) return -1;
if (len != KKEMU_PACKET_SIZE) return -1;

RingBuf* rb = (iface == KKEMU_IFACE_MAIN) ? &rb_main_in : &rb_debug_in;
return ringbuf_push(rb, data, len) ? 0 : -1;
}

int kkemu_read(uint8_t* buf, size_t len, int iface) {
if (!libkkemu_initialized) return 0;
if (len < KKEMU_PACKET_SIZE) return 0;

RingBuf* rb = (iface == KKEMU_IFACE_MAIN) ? &rb_main_out : &rb_debug_out;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot Create an issue for this

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Copilot sandbox token doesn't have permission to create issues in this repo. Here is the ready-to-file issue — please paste it into a new issue:


Title: libkkemu: kkemu_write/kkemu_read silently route invalid iface values to debug queue

Body:

Bug

kkemu_write() and kkemu_read() use a ternary to select the ring buffer:

// lib/emulator/libkkemu.c:245
RingBuf* rb = (iface == KKEMU_IFACE_MAIN) ? &rb_main_in : &rb_debug_in;

// lib/emulator/libkkemu.c:253
RingBuf* rb = (iface == KKEMU_IFACE_MAIN) ? &rb_main_out : &rb_debug_out;

Any iface value that is not KKEMU_IFACE_MAIN (0) — including values like 2, -1, or 99 — is silently treated as KKEMU_IFACE_DEBUG (1). This makes API misuse invisible to callers and can cause cross-channel message contamination.

Expected behaviour

Both functions should explicitly validate iface and return an error for any value that is neither KKEMU_IFACE_MAIN nor KKEMU_IFACE_DEBUG.

Suggested fix

int kkemu_write(const uint8_t* data, size_t len, int iface) {
  if (!libkkemu_initialized) return -1;
  if (len != KKEMU_PACKET_SIZE) return -1;
  if (iface != KKEMU_IFACE_MAIN && iface != KKEMU_IFACE_DEBUG) return -1;

  RingBuf* rb = (iface == KKEMU_IFACE_MAIN) ? &rb_main_in : &rb_debug_in;
  return ringbuf_push(rb, data, len) ? 0 : -1;
}

int kkemu_read(uint8_t* buf, size_t len, int iface) {
  if (!libkkemu_initialized) return 0;
  if (len < KKEMU_PACKET_SIZE) return 0;
  if (iface != KKEMU_IFACE_MAIN && iface != KKEMU_IFACE_DEBUG) return 0;

  RingBuf* rb = (iface == KKEMU_IFACE_MAIN) ? &rb_main_out : &rb_debug_out;
  return ringbuf_pop(rb, buf, KKEMU_PACKET_SIZE) ? KKEMU_PACKET_SIZE : 0;
}

Affected files

  • lib/emulator/libkkemu.c (lines 241–255)
  • include/keepkey/emulator/libkkemu.h (API docs for kkemu_write / kkemu_read)

Context

Identified during review of the release-7141 PR (7.14.1 firmware integration).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try to create the issue again.

Comment thread lib/emulator/libkkemu.c
Comment on lines +250 to +253
if (!libkkemu_initialized) return 0;
if (len < KKEMU_PACKET_SIZE) return 0;

RingBuf* rb = (iface == KKEMU_IFACE_MAIN) ? &rb_main_out : &rb_debug_out;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot Create an issue for this

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Copilot sandbox token doesn't have permission to create issues in this repo. Here is the ready-to-file issue — please paste it into a new issue:


Title: libkkemu: kkemu_read silently routes invalid iface values to debug queue

Body:

Bug

kkemu_read() selects the output ring buffer with a ternary:

// lib/emulator/libkkemu.c:253
RingBuf* rb = (iface == KKEMU_IFACE_MAIN) ? &rb_main_out : &rb_debug_out;

Any iface value that is not KKEMU_IFACE_MAIN (0) — including garbage values like 2, -1, or 99 — is silently treated as KKEMU_IFACE_DEBUG (1). This makes API misuse invisible to callers and can cause callers to receive data from the wrong channel.

Expected behaviour

kkemu_read() should explicitly validate iface and return 0 (no data) for any value that is neither KKEMU_IFACE_MAIN nor KKEMU_IFACE_DEBUG.

Suggested fix

int kkemu_read(uint8_t* buf, size_t len, int iface) {
  if (!libkkemu_initialized) return 0;
  if (len < KKEMU_PACKET_SIZE) return 0;
  if (iface != KKEMU_IFACE_MAIN && iface != KKEMU_IFACE_DEBUG) return 0;

  RingBuf* rb = (iface == KKEMU_IFACE_MAIN) ? &rb_main_out : &rb_debug_out;
  return ringbuf_pop(rb, buf, KKEMU_PACKET_SIZE) ? KKEMU_PACKET_SIZE : 0;
}

Affected files

  • lib/emulator/libkkemu.c (lines 249–255)
  • include/keepkey/emulator/libkkemu.h (API doc for kkemu_read)

Context

Identified during review of the release-7141 PR (7.14.1 firmware integration). See also the companion issue for kkemu_write() which has the same problem.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try to create the issue again.

Comment thread include/keepkey/emulator/libkkemu.h Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

Copilot AI commented May 9, 2026

Copy link
Copy Markdown

Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • https://api.github.com/graphql
    • Triggering command: `/usr/bin/gh gh issue create --repo keepkey/keepkey-firmware --title libkkemu: kkemu_write/kkemu_read silently route invalid iface values to debug queue --body ## Bug

kkemu_write() and kkemu_read() use a ternary to select the ring buffer:

// kkemu_write (lib/emulator/libkkemu.c:245)
RingBuf* rb = (iface == KKEMU_IFACE_MAIN) ? &amp;rb_main_in : &amp;rb_debug_in;

// kkemu_read (lib/emulator/libkkemu.c:253)
Rin` (http block)
>
> If you need me to access, download, or install something from one of these locations, you can either:
>
> - Configure [Actions setup steps](https://gh.io/copilot/actions-setup-steps) to set up my environment, which run before the firewall is enabled
> - Add the appropriate URLs or hosts to the custom allowlist in this repository's [Copilot coding agent settings](https://github.com/keepkey/keepkey-firmware/settings/copilot/coding_agent) (admins only)
>
> </details>

Copilot AI commented May 9, 2026

Copy link
Copy Markdown

Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • https://api.github.com/graphql
    • Triggering command: `/usr/bin/gh gh issue create --repo keepkey/keepkey-firmware --title libkkemu: kkemu_read silently routes invalid iface values to debug queue --body ## Bug

kkemu_read() selects the output ring buffer with a ternary:

// lib/emulator/libkkemu.c:253
RingBuf* rb = (iface == KKEMU_IFACE_MAIN) ? &amp;rb_main_out : &amp;rb_debug_out;

Any iface value that is not KKEMU_IFACE_MAIN (0) ��� including ga` (http block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI requested a review from pastaghost May 9, 2026 21:49
…uced by 0f73158)

The Copilot Autofix suggestion that broke the build at 2746ed3 was
re-applied via the GitHub UI in 0f73158 with the same payload.
TronTypedDataSignature.{address,signature} are 'required' in the proto
so nanopb does not emit has_* flags — the lines do not compile.

Please dismiss the underlying code-scanning finding rather than
re-applying the suggested fix, or this will recur.
@BitHighlander BitHighlander merged commit 5482e73 into develop May 9, 2026
11 checks passed
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.

4 participants