Skip to content

[Reproducible Builds] Keycard Shell: Bootloader binary not published in releases #216

Description

@xrviv

Please publish shellos-bootloader.bin in GitHub releases for third-party reproducibility

We are WalletScrutiny, an independent project that verifies whether the firmware of hardware and software wallets can be independently reproduced from published source code. We recently completed a reproducibility verification of Keycard Shell firmware v1.3.0 — and are happy to report that shellos.bin is fully reproducible.

During that verification, however, we noticed that shellos-bootloader.bin is built as part of the standard CMake release build but is not included in the GitHub releases page alongside shellos-*.bin. This issue is a request to include it.


What we observed

The CMakeLists.txt at v1.3.0 defines a shellos-bootloader.elf target that compiles bootloader/bootloader.c, then invokes tools/bootloader-perso.py post-build to embed the public key and produce shellos-bootloader.bin:

add_executable(shellos-bootloader.elf ...)
add_custom_command(TARGET shellos-bootloader.elf POST_BUILD
    COMMAND ... uv run python tools/bootloader-perso.py
        -p deployment/bootloader-pubkey.txt
        -e shellos-bootloader.elf
        -o shellos-bootloader.bin ...)

When we run cmake --build --preset release, both shellos.bin and shellos-bootloader.bin are produced. The firmware binary (shellos.bin) is published in releases and is reproducible. The bootloader binary (shellos-bootloader.bin) is not published, so there is no reference artifact for third parties to verify against.


Why this matters

The bootloader is security-critical. Reading bootloader/bootloader.c, it:

  1. Embeds the firmware verification public key (FW_PUB, 64 bytes, placed in .fw_verification_key section via bootloader-perso.py)
  2. Runs verify_firmware() on every boot — hashing the firmware image (identical skip logic to firmware-hash.py, bytes 0–587 + 652–end) and verifying the ECDSA signature against FW_PUB
  3. Refuses to boot and triggers a firmware slot switch if verification fails

This means the bootloader defines which public key the device trusts to authorize firmware. Without a published reference binary, users and auditors cannot independently verify that the bootloader running on their device matches the source code — even if the firmware itself is reproducible.


Request

We would like to ask that you publish shellos-bootloader.bin as a release artifact alongside shellos-{date}-{version}.bin for each release going forward.

Ideally, the release would include:

File Description
shellos-{date}-{version}.bin Firmware binary (already published)
shellos-bootloader-{date}-{version}.bin Bootloader binary (requested)
sha256.txt SHA256 of both binaries

If the bootloader release cadence differs from firmware (i.e., the bootloader does not change with every firmware release), publishing it once per bootloader version with a clear changelog note would also be acceptable.


Notes on our verification

  • Our build environment: Ubuntu 22.04 Docker container, CMake 3.22.1, Ninja 1.10.1, ARM GNU Toolchain 15.2.rel1
  • Both shellos.bin and shellos-bootloader.bin built cleanly from the v1.3.0 tag (355/355 ninja targets)
  • Firmware hash (excluding sig bytes 588–651, per firmware-hash.py): 0cdbc6210af73a0448b3be708c9873500a93ee56fb4899f382a4d6b10b1ad13b — matches official release ✅
  • Bootloader: builds successfully, no reference binary to compare

Thank you for the clean build system and for providing firmware-hash.py — it made the firmware verification straightforward. We hope publishing the bootloader binary is a small addition that significantly improves the auditability of the full stack.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions