What changed, and why it matters
This commit is a build-script change that adds an optional way to compile firmware for a new Trezor Bluetooth chip (nRF) inside the existing Docker build tool. It does not change any wallet code, cryptography, or device behavior. There is no security issue visible in the diff.
No security action required. Review as normal build-system maintenance; ensure the hard-coded /nix/store path for GNUARMEMB_TOOLCHAIN_PATH is acceptable for reproducible builds and is updated when the toolchain derivation changes.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch extends build-docker.sh with an –nrf flag that, when enabled, generates and runs a secondary shell script inside the same Docker snapshot used for other Trezor builds. It initializes a Zephyr/west workspace, runs the existing Nordic build_sign_flash.sh script for the t3w1_revA_nrf52832 board, computes SHA-256 fingerprints of the resulting bootloader and firmware binaries, copies artifacts to build/nrf, and prints their fingerprints. The change is purely additive to CI/reproducible-build tooling and does not modify runtime firmware, signing logic, or secrets handling.
Changed components
build-docker.shInspect captured patch +130 / −0
diff --git a/build-docker.sh b/build-docker.sh
index 2da100701..ad34df062 100755
--- a/build-docker.sh
+++ b/build-docker.sh
@@ -54,6 +54,7 @@ function help_and_die() {
echo " --no-init - do not recreate docker environments"
echo " --models - comma-separated list of models. default: --models T1B1,T2B1,T2T1,T3T1"
echo " --targets - comma-separated list of targets for core build. default: --targets boardloader,bootloader,firmware"
+ echo " --nrf - build nRF bootloader and firmware (for bluetooth devices, i.e. T3W1)"
echo " --help"
echo
echo "Option --prodtest is deprecated. Use "--targets prodtest" to build prodtest."
@@ -64,6 +65,7 @@ function help_and_die() {
OPT_BUILD_NORMAL=1
OPT_BUILD_BITCOINONLY=1
+OPT_BUILD_NRF=0
INIT=1
MODELS=(T1B1 T2B1 T2T1 T3T1)
CORE_TARGETS=(boardloader bootloader firmware)
@@ -101,6 +103,10 @@ while true; do
IFS=',' read -r -a CORE_TARGETS <<< "$2"
shift 2
;;
+ --nrf)
+ OPT_BUILD_NRF=1
+ shift
+ ;;
*)
break
;;
@@ -303,6 +309,114 @@ EOF
done
done
+# build nRF bootloader and firmware
+if [ "$OPT_BUILD_NRF" -eq 1 ]; then
+ SCRIPT_NAME=".build_nrf.sh"
+ cat <<EOF > "build/$SCRIPT_NAME"
+ # DO NOT MODIFY!
+ # this file was generated by ${BASH_SOURCE[0]}
+ # variant: nrf build
+ set -e -o pipefail
+
+ echo "=== Toolchain Debug Info ==="
+ echo "ZEPHYR_TOOLCHAIN_VARIANT: \$ZEPHYR_TOOLCHAIN_VARIANT"
+ echo "GNUARMEMB_TOOLCHAIN_PATH: \$GNUARMEMB_TOOLCHAIN_PATH"
+ echo "ARM GCC location: \$(which arm-none-eabi-gcc)"
+ echo "ARM GCC version: \$(arm-none-eabi-gcc --version | head -1)"
+
+ # Initialize west workspace
+ echo "=== cleaning git repo ==="
+ cd /reproducible-build/trezor-firmware/nordic/trezor
+ $GIT_CLEAN_REPO
+ echo "=== west initializing workspace ==="
+ cd /reproducible-build/trezor-firmware/nordic
+ poetry run west init -l ./trezor || echo "West already initialized"
+ echo "=== west update ==="
+ poetry run west update
+
+ # Build using the script
+ echo "=== running build_sign_flash ==="
+ cd /reproducible-build/trezor-firmware/nordic/trezor
+ if [ "$PRODUCTION" = "1" ]; then
+ poetry run scripts/build_sign_flash.sh -b t3w1_revA_nrf52832 -p -c -s
+ else
+ poetry run scripts/build_sign_flash.sh -b t3w1_revA_nrf52832 -d -c -s
+ fi
+
+ # Generate fingerprints
+ echo "=== Generating fingerprints for nrf binary files ==="
+ cd /reproducible-build/trezor-firmware/nordic/trezor
+
+ # Generate fingerprint for bootloader
+ if [ -f "build/mcuboot/zephyr/zephyr.bin" ]; then
+ echo "Generating fingerprint for: build/mcuboot/zephyr/zephyr.bin"
+ sha256sum "build/mcuboot/zephyr/zephyr.bin" | cut -d' ' -f1 > "build/mcuboot/zephyr/zephyr.bin.fingerprint"
+ echo "Created: build/mcuboot/zephyr/zephyr.bin.fingerprint"
+ else
+ echo "File not found: build/mcuboot/zephyr/zephyr.bin"
+ fi
+
+ # Generate fingerprint for firmware
+ if [ -f "build/trezor-ble/zephyr/zephyr.signed_trz.bin" ]; then
+ echo "Generating fingerprint for: build/trezor-ble/zephyr/zephyr.signed_trz.bin"
+ sha256sum "build/trezor-ble/zephyr/zephyr.signed_trz.bin" | cut -d' ' -f1 > "build/trezor-ble/zephyr/zephyr.signed_trz.bin.fingerprint"
+ echo "Created: build/trezor-ble/zephyr/zephyr.signed_trz.bin.fingerprint"
+ else
+ echo "File not found: build/trezor-ble/zephyr/zephyr.signed_trz.bin"
+ fi
+
+ # Create output directory structure and copy artifacts
+ echo "=== Copy built files back to host ==="
+ mkdir -p /build/bootloader /build/firmware
+ cd /reproducible-build/trezor-firmware/nordic/trezor
+
+ # Copy nRF bootloader (MCUboot)
+ if [ -f build/mcuboot/zephyr/zephyr.hex ]; then
+ cp build/mcuboot/zephyr/zephyr.hex /build/bootloader/nrf-bootloader.hex
+ cp build/mcuboot/zephyr/zephyr.bin /build/bootloader/nrf-bootloader.bin
+ cp build/mcuboot/zephyr/zephyr.bin.fingerprint /build/bootloader/nrf-bootloader.bin.fingerprint 2>/dev/null || true
+ fi
+
+ # Copy signed nRF application firmware
+ if [ -f build/trezor-ble/zephyr/zephyr.signed_trz.hex ]; then
+ cp build/trezor-ble/zephyr/zephyr.signed_trz.hex /build/firmware/nrf-firmware.hex
+ cp build/trezor-ble/zephyr/zephyr.signed_trz.bin /build/firmware/nrf-firmware.bin
+ cp build/trezor-ble/zephyr/zephyr.signed_trz.bin.fingerprint /build/firmware/nrf-firmware.bin.fingerprint 2>/dev/null || true
+ fi
+
+ # Copy nRF ELF file (from unsigned build)
+ if [ -f build/trezor-ble/zephyr/zephyr.elf ]; then
+ cp build/trezor-ble/zephyr/zephyr.elf /build/firmware/nrf-firmware.elf
+ fi
+
+ # Copy merged signed nRF firmware
+ if [ -f build/zephyr.merged.signed_trz.hex ]; then
+ cp build/zephyr.merged.signed_trz.hex /build/firmware/nrf-firmware.merged.hex
+ fi
+
+ echo "=== NRF repro build DONE ==="
+
+ chown -R $USER:$GROUP /build
+EOF
+
+ echo
+ echo ">>> DOCKER RUN nrf PRODUCTION=$PRODUCTION"
+ echo
+
+ $DOCKER run \
+ --network=host \
+ --rm \
+ -v "$DIR:/local" \
+ -v "$DIR/build/nrf":/build:z \
+ --env PRODUCTION="$PRODUCTION" \
+ --env TREZOR_FIRMWARE_ACCEPT_JLINK_LICENSE="yes" \
+ --env ZEPHYR_TOOLCHAIN_VARIANT="gnuarmemb" \
+ --env GNUARMEMB_TOOLCHAIN_PATH="/nix/store/n6qhvpsx5ldqazhmx5lc9lyjdbmq8zj2-gcc-arm-embedded-13.3.rel1" \
+ --init \
+ "$SNAPSHOT_NAME" \
+ /nix/var/nix/profiles/default/bin/nix-shell --arg devTools true --run "bash /local/build/$SCRIPT_NAME"
+fi
+
# build legacy
if echo "${MODELS[@]}" | grep -q T1B1 ; then
@@ -362,6 +476,8 @@ echo
echo "Built from commit $COMMIT_HASH"
echo
echo "Fingerprints:"
+
+# Display core and legacy fingerprints (if built)
for VARIANT in core legacy; do
for MODEL in ${MODELS[@]}; do
for DIRSUFFIX in "" "-bitcoinonly"; do
@@ -376,3 +492,17 @@ for VARIANT in core legacy; do
done
done
done
+
+# Display nRF fingerprints (if built)
+if [ "$OPT_BUILD_NRF" -eq 1 ]; then
+ NRF_BUILD_DIR=build/nrf
+ if [ -d "$NRF_BUILD_DIR" ]; then
+ for file in $NRF_BUILD_DIR/firmware/*.fingerprint $NRF_BUILD_DIR/bootloader/*.fingerprint; do
+ if [ -f "$file" ]; then
+ origfile="${file%.fingerprint}"
+ fingerprint=$(tr -d '\n' < "$file")
+ echo "$fingerprint $origfile"
+ fi
+ done
+ fi
+fi
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.