chore(core/tools): drop bootloader_hashes for boot_ucb models
What changed, and why it matters
This is a cleanup change that stops generating unused bootloader hash files for newer Trezor models (D002, T3T2, T3W1). These models already verify the bootloader using a different mechanism (UCB with post-quantum signatures), so the old hash files were never actually used. The commit deletes the stale files and removes their #include references. There is no security vulnerability here.
No security action required. This is a benign cleanup. Reviewers may verify that no non-UCB models accidentally had their bootloader_hashes.h removed and that the generation script correctly identifies boot_ucb from model.toml.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The commit removes auto-generated bootloader_hashes.h files and their includes for UCB-enabled models. It updates the generation script (bootloader_hashes.py) to detect boot_ucb from model.toml features and skip generation. The removed hashes were Blake2s digests of padded bootloader binaries, which boot_image_embdata.c only uses under #ifndef USE_BOOT_UCB. For UCB models, verification happens via the PQ boot-header signature in boot_image_replace, making these hashes dead code.
Changed components
core/tools/trezor_core_tools/bootloader_hashes.pycore/embed/models/D002/model_D002.hcore/embed/models/T3T2/model_T3T2.hcore/embed/models/T3W1/model_T3W1.hcore/embed/models/D002/bootloaders/bootloader_hashes.hcore/embed/models/T3T2/bootloaders/bootloader_hashes.hcore/embed/models/T3W1/bootloaders/bootloader_hashes.hInspect captured patch +32 / −51
### core/embed/models/D002/bootloaders/bootloader_hashes.h
@@ -1,17 +0,0 @@
-#ifndef BOOTLOADER_HASHES_H
-#define BOOTLOADER_HASHES_H
-
-// Auto-generated file, do not edit.
-
-// clang-format off
-// bootloader_D002.bin version 2.1.11.0
-#define BOOTLOADER_D002_00 {0xd7, 0xf5, 0x8f, 0xa0, 0x8e, 0x71, 0x3d, 0x53, 0x97, 0xe3, 0xb1, 0x76, 0xa1, 0x57, 0xe5, 0x05, 0xcd, 0x6d, 0x4f, 0x6e, 0xc7, 0x0c, 0x47, 0x4a, 0x7b, 0x12, 0x2f, 0xd2, 0xcb, 0x95, 0x45, 0x8d}
-#define BOOTLOADER_D002_FF {0xd7, 0xf5, 0x8f, 0xa0, 0x8e, 0x71, 0x3d, 0x53, 0x97, 0xe3, 0xb1, 0x76, 0xa1, 0x57, 0xe5, 0x05, 0xcd, 0x6d, 0x4f, 0x6e, 0xc7, 0x0c, 0x47, 0x4a, 0x7b, 0x12, 0x2f, 0xd2, 0xcb, 0x95, 0x45, 0x8d}
-
-// bootloader_D002_devel.bin version 2.1.11.0
-#define BOOTLOADER_D002_DEVEL_00 {0xd7, 0xf5, 0x8f, 0xa0, 0x8e, 0x71, 0x3d, 0x53, 0x97, 0xe3, 0xb1, 0x76, 0xa1, 0x57, 0xe5, 0x05, 0xcd, 0x6d, 0x4f, 0x6e, 0xc7, 0x0c, 0x47, 0x4a, 0x7b, 0x12, 0x2f, 0xd2, 0xcb, 0x95, 0x45, 0x8d}
-#define BOOTLOADER_D002_DEVEL_FF {0xd7, 0xf5, 0x8f, 0xa0, 0x8e, 0x71, 0x3d, 0x53, 0x97, 0xe3, 0xb1, 0x76, 0xa1, 0x57, 0xe5, 0x05, 0xcd, 0x6d, 0x4f, 0x6e, 0xc7, 0x0c, 0x47, 0x4a, 0x7b, 0x12, 0x2f, 0xd2, 0xcb, 0x95, 0x45, 0x8d}
-
-// clang-format on
-
-#endif
### core/embed/models/D002/model_D002.h
@@ -20,7 +20,6 @@
#pragma once
#include <rtl/sizedefs.h>
-#include "bootloaders/bootloader_hashes.h"
#include "secret_layout.h"
#define MODEL_NAME "D002"
### core/embed/models/T3T2/bootloaders/bootloader_hashes.h
@@ -1,13 +0,0 @@
-#ifndef BOOTLOADER_HASHES_H
-#define BOOTLOADER_HASHES_H
-
-// Auto-generated file, do not edit.
-
-// clang-format off
-// bootloader_T3T2_devel.bin version 2.1.18.0
-#define BOOTLOADER_T3T2_DEVEL_00 {0xde, 0xc1, 0x72, 0x97, 0x9a, 0x52, 0xb6, 0x80, 0x1d, 0x68, 0xae, 0xa7, 0x20, 0x50, 0x58, 0xa7, 0x65, 0x78, 0xa4, 0x79, 0x7c, 0x72, 0x93, 0x63, 0x2e, 0x91, 0x12, 0x78, 0x54, 0xc5, 0xde, 0xfb}
-#define BOOTLOADER_T3T2_DEVEL_FF {0xbd, 0x6c, 0x02, 0xc6, 0x54, 0x42, 0x50, 0xbb, 0x3d, 0x85, 0xc1, 0x38, 0x5e, 0xaf, 0x5e, 0x81, 0xf9, 0xd5, 0x18, 0x92, 0x6e, 0x3f, 0x5a, 0xea, 0xe2, 0x68, 0x1e, 0xda, 0xce, 0xfe, 0x79, 0xb2}
-
-// clang-format on
-
-#endif
### core/embed/models/T3T2/model_T3T2.h
@@ -19,7 +19,6 @@
#pragma once
-#include "bootloaders/bootloader_hashes.h"
#include "secret_layout.h"
#include <rtl/sizedefs.h>
### core/embed/models/T3W1/bootloaders/bootloader_hashes.h
@@ -1,17 +0,0 @@
-#ifndef BOOTLOADER_HASHES_H
-#define BOOTLOADER_HASHES_H
-
-// Auto-generated file, do not edit.
-
-// clang-format off
-// bootloader_T3W1.bin version 2.1.17.0
-#define BOOTLOADER_T3W1_00 {0xbb, 0x78, 0xe5, 0xd0, 0x5f, 0xde, 0x18, 0x09, 0xfb, 0xec, 0xa0, 0xf3, 0x09, 0xbd, 0xd9, 0xeb, 0xdf, 0x24, 0x84, 0x54, 0x71, 0x60, 0x23, 0x1e, 0x44, 0xfb, 0x91, 0xa4, 0x46, 0x47, 0xa0, 0x93}
-#define BOOTLOADER_T3W1_FF {0xbb, 0x78, 0xe5, 0xd0, 0x5f, 0xde, 0x18, 0x09, 0xfb, 0xec, 0xa0, 0xf3, 0x09, 0xbd, 0xd9, 0xeb, 0xdf, 0x24, 0x84, 0x54, 0x71, 0x60, 0x23, 0x1e, 0x44, 0xfb, 0x91, 0xa4, 0x46, 0x47, 0xa0, 0x93}
-
-// bootloader_T3W1_devel.bin version 2.1.17.0
-#define BOOTLOADER_T3W1_DEVEL_00 {0x27, 0xd6, 0xbf, 0xb4, 0xcf, 0x14, 0xfb, 0x71, 0x19, 0xf8, 0x2a, 0x23, 0xb9, 0xe8, 0x7b, 0xd9, 0xc0, 0x8b, 0x2a, 0x07, 0x32, 0x3e, 0xa1, 0xec, 0x71, 0x0d, 0xd0, 0x58, 0xc8, 0x25, 0xe0, 0x6b}
-#define BOOTLOADER_T3W1_DEVEL_FF {0x27, 0xd6, 0xbf, 0xb4, 0xcf, 0x14, 0xfb, 0x71, 0x19, 0xf8, 0x2a, 0x23, 0xb9, 0xe8, 0x7b, 0xd9, 0xc0, 0x8b, 0x2a, 0x07, 0x32, 0x3e, 0xa1, 0xec, 0x71, 0x0d, 0xd0, 0x58, 0xc8, 0x25, 0xe0, 0x6b}
-
-// clang-format on
-
-#endif
### core/embed/models/T3W1/model_T3W1.h
@@ -23,8 +23,6 @@
#include <rtl/sizedefs.h>
#include "secret_layout.h"
-#include "bootloaders/bootloader_hashes.h"
-
#define MODEL_NAME "Safe 7"
#define MODEL_FULL_NAME "Trezor Safe 7"
#define MODEL_INTERNAL_NAME "T3W1"
### core/tools/trezor_core_tools/bootloader_hashes.py
@@ -5,6 +5,7 @@
import click
import construct as c
+import tomllib
from trezorlib.firmware.core import BootableImage, FirmwareImage
from trezorlib.firmware.models import Model
@@ -48,6 +49,30 @@ def aligned_digest(fn: Path, data: bytes, padding: bytes, aligned_size: int) ->
return blake2s(digest_data).digest()
+def model_uses_boot_ucb(model_dir: Path) -> bool:
+ """Whether the model enables the UCB (update control block) bootloader scheme.
+
+ UCB models verify a staged bootloader through its PQ boot-header signature
+ (see boot_image_replace under USE_BOOT_UCB), not through the padded blake2s
+ digests in bootloader_hashes.h -- boot_image_embdata.c only wires
+ .hash_00/.hash_FF ``#ifndef USE_BOOT_UCB``. The digests are dead for these
+ models, so generating them only churns the header whenever the bootloader
+ binary changes, for no consumer.
+
+ The authoritative source is the model.toml ``features`` list; the BOOTUCB_*
+ layout symbols are not reliable (some non-UCB models define them too).
+ """
+ model_toml = model_dir / "model.toml"
+
+ try:
+ with model_toml.open("rb") as file:
+ config = tomllib.load(file)
+ except FileNotFoundError:
+ return False
+
+ return "boot_ucb" in config.get("features", [])
+
+
def to_uint_array(data: bytes) -> str:
"""Convert bytes to C array of uint8_t, like so:
@@ -105,6 +130,13 @@ def main(check: bool) -> None:
models = [model for model in models if model.is_dir()]
for model in models:
+ if model_uses_boot_ucb(model):
+ # UCB models never consume these digests (see model_uses_boot_ucb):
+ # both the header and its #include have been removed for them, so
+ # skip generation to avoid recreating a dead file.
+ print(f"Skipping {model.name}: boot_ucb model, bootloader hashes unused")
+ continue
+
path = model / "bootloaders"
if path.is_dir():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.