Skip to content

Solana parse/sign buffer offset mismatch #461

Description

@BitHighlander

Triaged during the 7.14.2 residual pass and deferred out of 7.14.2 as medium. Still present at release/7.14.2 head.

Evidence

lib/firmware/solana.c:586 (inspect advances past the 0x00 prefix) vs lib/firmware/solana.c:661 (sign uses msg->raw_tx.bytes/.size unshifted), called from lib/firmware/fsm_msg_solana.h:389 and :454

Assessment

Still present. Five commits touched Solana on this branch (the TransferChecked decimals fix, the token-symbol removal, the confirm-screen rework at fsm_msg_solana.h) and none of them addressed the offset. At HEAD solana_inspectTx still does if (raw[0] == 0 && raw_len > 1) { raw++; raw_len--; } at solana.c:586, and every downstream decision — instruction decode, the per-instruction confirm screens, the VERIFIED/OPAQUE/MALFORMED verdict, and solana_signerInTx at fsm_msg_solana.h:300 — runs on the shifted slice, while solana_signTx at solana.c:661 Ed25519-signs the unshifted buffer. Both parsers pin exact consumption (if (pos != raw_len) return MALFORMED), so the divergence is exactly the one leading byte.

So the device literally displays a parse of M and signs 0x00||M. I nevertheless hold this at medium rather than promoting it to the rubric's 'signs materially different bytes' high band, because I traced the artifact and it is inert. Solana verifies signatures over the message bytes, so sig(0x00||M) does not verify against M — the approved transaction is simply unbroadcastable while the device reports success. The reverse direction also dead-ends: for an attacker to obtain a signature over some M_evil this way, M_evil must itself begin with 0x00, which as a legacy message header means num_required_signatures = 0; the Solana runtime rejects that at sanitize (no fee payer, no signature slot), and for a v0 payload the 0x00 lead byte is not a valid version prefix either. I could construct no path where the emitted signature moves funds or forges anything an honest verifier would accept. The residual is a narrow oracle: a signature over 0x00||M, dangerous only to an off-chain verifier that accepts a bare signature without rejecting a 0x00 lead byte.

File it. Worth noting for the owner that the fix is cheap and already written on ORPHAN 4895b81 as solana_message_slice() used by both the inspect and sign paths, plus an ed25519_sign_open self-check; the even smaller option is to reject a leading 0x00 outright and fail closed. If the owner wants a correctness-only backport in this tag it is a low-risk candidate, but it does not meet the bar to block.


Deferred because 7.14.2 is a minimal security release; this did not clear the bar for a late change. Filed so it is not lost.

Metadata

Metadata

Assignees

No one assigned

    Labels

    securitySecurity-relevant defect or hardening

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions