Skip to content

BTC checksum hashes pointer-size bytes, so ARM and emulator validate different data #615

Description

@BitHighlander

Summary

The Bitcoin transaction consistency checksum hashes sizeof(&script_type) bytes rather than sizeof(script_type). It happens to hash four bytes in the shipping 32-bit ARM build, but hashes eight bytes in the 64-bit emulator and incorporates adjacent struct representation.

Found while auditing PR #604 at exact head 1d446ccbc9cf32a6e499990e65bcf7b358f1325b.

Evidence

lib/firmware/signing.c:1845-1848:

hasher_Update(&hasher_check, (const uint8_t*)&tx->inputs[0].script_type,
              sizeof(&tx->inputs[0].script_type));

The second argument is a pointer expression. Its size is ABI-dependent (4 on ARM, 8 on the CI emulator), while the intended enum member is four bytes in this build. The emulator therefore tests a different checksum contract from the product and may bind padding/neighboring fields unintentionally.

Impact

Low — target-dependent transaction validation and weakened test equivalence. Shipping ARM behavior currently matches the apparent intent by accident; emulator evidence does not exercise the same bytes.

Acceptance criteria

  • Replace the pointer-size expression with sizeof(tx->inputs[0].script_type) (or an explicit canonical-width serialization).
  • Add a compile-time assertion for the encoded width or, preferably, hash a fixed-width value.
  • Add a regression test that records identical checksum input bytes on ARM and emulator builds.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions