chore(core): add secmon keys to trezorlib
What changed, and why it matters
This commit updates Trezor's Python library so it can recognize and verify digital signatures for a new 'secure monitor' (secmont) firmware component. It fixes a mismatch where the secmon image verifier was accidentally returning bootloader keys instead of secmon keys, and adds the correct public keys and signature-count rules for two development hardware models. There is no direct evidence this is a security vulnerability fix; it reads as a routine key-registry update for a new feature.
No urgent action required. Treat as a normal library update. If you maintain downstream firmware verification tooling, ensure you accept this key set so secmon images validate correctly. Review whether the corrected key lookup should be backported to any pinned release branches that already ship secmon images.
Security signals we found
Public key list added for new secure-monitor firmware component
Existing key lookup bug corrected (secmon image was using boardloader keys)
Signature threshold (2-of-3) configured for secmon on two dev models
Evidence from the diff
The diff modifies trezorlib’s firmware header parsing. In firmware_headers.py, SecmonImage.public_keys() now returns get_model_keys(…).secmon_keys instead of .boardloader_keys, correcting a copy-paste error. In firmware/models.py, the ModelKeys dataclass gains secmon_keys and secmon_sigs_needed fields, populated with empty/placeholder values for legacy and most Core models, and with real Ed25519 public keys and a 2-of-3 threshold for TREZOR_CORE_DEV and T3W1. The change enables trezorlib to validate secmon image COSI signatures against the right key set.
Changed components
python/src/trezorlib/_internal/firmware_headers.pypython/src/trezorlib/firmware/models.pyInspect captured patch +37 / −1
diff --git a/python/src/trezorlib/_internal/firmware_headers.py b/python/src/trezorlib/_internal/firmware_headers.py
index 17417b04..3802ee7a 100644
--- a/python/src/trezorlib/_internal/firmware_headers.py
+++ b/python/src/trezorlib/_internal/firmware_headers.py
@@ -431,7 +431,7 @@ class SecmonImage(firmware.SecmonImage, CosiSignedMixin):
raise firmware.InvalidSignatureError("Invalid bootloader signature")
def public_keys(self, dev_keys: bool = False) -> t.Sequence[bytes]:
- return self.get_model_keys(dev_keys).boardloader_keys
+ return self.get_model_keys(dev_keys).secmon_keys
class BootloaderV2Image(firmware.BootableImage):
diff --git a/python/src/trezorlib/firmware/models.py b/python/src/trezorlib/firmware/models.py
index 5e539986..a8af71e0 100644
--- a/python/src/trezorlib/firmware/models.py
+++ b/python/src/trezorlib/firmware/models.py
@@ -80,6 +80,8 @@ class ModelKeys:
bootloader_sigs_needed: int
firmware_keys: t.Sequence[bytes]
firmware_sigs_needed: int
+ secmon_keys: t.Sequence[bytes]
+ secmon_sigs_needed: int
LEGACY_V1V2 = ModelKeys(
@@ -99,6 +101,8 @@ LEGACY_V1V2 = ModelKeys(
)
],
firmware_sigs_needed=3,
+ secmon_keys=(),
+ secmon_sigs_needed=-1,
)
LEGACY_V1V2_DEV = ModelKeys(
@@ -118,6 +122,8 @@ LEGACY_V1V2_DEV = ModelKeys(
)
],
firmware_sigs_needed=3,
+ secmon_keys=(),
+ secmon_sigs_needed=-1,
)
LEGACY_V3 = ModelKeys(
@@ -135,6 +141,8 @@ LEGACY_V3 = ModelKeys(
)
],
firmware_sigs_needed=2,
+ secmon_keys=(),
+ secmon_sigs_needed=-1,
)
LEGACY_V3_DEV = ModelKeys(
@@ -152,6 +160,8 @@ LEGACY_V3_DEV = ModelKeys(
)
],
firmware_sigs_needed=2,
+ secmon_keys=(),
+ secmon_sigs_needed=-1,
)
T2T1 = ModelKeys(
@@ -176,6 +186,8 @@ T2T1 = ModelKeys(
bootloader_sigs_needed=2,
firmware_keys=(),
firmware_sigs_needed=-1,
+ secmon_keys=(),
+ secmon_sigs_needed=-1,
)
TREZOR_CORE_DEV = ModelKeys(
@@ -200,6 +212,15 @@ TREZOR_CORE_DEV = ModelKeys(
bootloader_sigs_needed=2,
firmware_keys=(),
firmware_sigs_needed=-1,
+ secmon_keys=[
+ bytes.fromhex(key)
+ for key in (
+ "db995fe25169d141cab9bbba92baa01f9f2e1ece7df4cb2ac05190f37fcc1f9d",
+ "2152f8d19b791d24453242e15f2eab6cb7cffa7b6a5ed30097960e069881db12",
+ "22fc297792f0b6ffc0bfcfdb7edb0c0aa14e025a365ec0e342e86e3829cb74b6",
+ )
+ ],
+ secmon_sigs_needed=2,
)
T2B1 = ModelKeys(
@@ -224,6 +245,8 @@ T2B1 = ModelKeys(
bootloader_sigs_needed=2,
firmware_keys=(),
firmware_sigs_needed=-1,
+ secmon_keys=(),
+ secmon_sigs_needed=-1,
)
T3T1 = ModelKeys(
@@ -248,6 +271,8 @@ T3T1 = ModelKeys(
bootloader_sigs_needed=2,
firmware_keys=(),
firmware_sigs_needed=-1,
+ secmon_keys=(),
+ secmon_sigs_needed=-1,
)
T3B1 = ModelKeys(
@@ -272,6 +297,8 @@ T3B1 = ModelKeys(
bootloader_sigs_needed=2,
firmware_keys=(),
firmware_sigs_needed=-1,
+ secmon_keys=(),
+ secmon_sigs_needed=-1,
)
T3W1 = ModelKeys(
@@ -296,6 +323,15 @@ T3W1 = ModelKeys(
bootloader_sigs_needed=2,
firmware_keys=(),
firmware_sigs_needed=-1,
+ secmon_keys=[
+ bytes.fromhex(key)
+ for key in (
+ "7da3dd4769fef0f9489d5ff7fba8be122aef0f60778302557ba2cc67ff2a6d9e",
+ "4ae3bf88b0e5226322d867432940265b4bef46e5c45b64730e26ca32ee653e0b",
+ "6c1640f38d037c57e86960863505ef70ff60f98157440cf25f1c133b4a15960e",
+ )
+ ],
+ secmon_sigs_needed=2,
)
ROOT_ED25519_KEYS = [
Why this scored 18/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.