1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-18 20:38:10 +00:00

feat(core): add hw_model field to vendor headers

This commit is contained in:
matejcik 2023-05-31 14:43:20 +02:00
parent da14c22712
commit b6c2f2e5ba
12 changed files with 45 additions and 29 deletions

View File

@ -0,0 +1 @@
Added hw model field to all vendor headers.

View File

@ -1,6 +1,7 @@
{ {
"header_len": 4608, "header_len": 4608,
"text": "UNSAFE, FACTORY TEST ONLY", "text": "UNSAFE, FACTORY TEST ONLY",
"hw_model": null,
"expiry": 0, "expiry": 0,
"version": [0, 0], "version": [0, 0],
"sig_m": 2, "sig_m": 2,

View File

@ -1,6 +1,7 @@
{ {
"header_len": 4608, "header_len": 4608,
"text": "QA ONLY, DO NOT USE!", "text": "QA ONLY, DO NOT USE!",
"hw_model": null,
"expiry": 0, "expiry": 0,
"version": [0, 0], "version": [0, 0],
"sig_m": 2, "sig_m": 2,

View File

@ -1,6 +1,7 @@
{ {
"header_len": 4608, "header_len": 4608,
"text": "SatoshiLabs", "text": "SatoshiLabs",
"hw_model": null,
"expiry": 0, "expiry": 0,
"version": [0, 1], "version": [0, 1],
"sig_m": 2, "sig_m": 2,

View File

@ -1,6 +1,7 @@
{ {
"header_len": 4608, "header_len": 4608,
"text": "UNSAFE, DO NOT USE!", "text": "UNSAFE, DO NOT USE!",
"hw_model": null,
"expiry": 0, "expiry": 0,
"version": [0, 1], "version": [0, 1],
"sig_m": 2, "sig_m": 2,

View File

@ -27,6 +27,10 @@ def build_vendorheader(specfile, image, outfile):
spec["image"] = toif.ToifStruct.parse(image.read()) spec["image"] = toif.ToifStruct.parse(image.read())
spec["sigmask"] = 0 spec["sigmask"] = 0
spec["signature"] = b"\x00" * 64 spec["signature"] = b"\x00" * 64
if spec["hw_model"] is None:
spec["hw_model"] = b"\x00\x00\x00\x00"
else:
spec["hw_model"] = spec["hw_model"].encode("ascii")
min_length = minimum_header_len(spec) min_length = minimum_header_len(spec)
if "header_len" not in spec: if "header_len" not in spec:

View File

@ -0,0 +1 @@
Recognize hw model field in vendor headers.

View File

@ -264,6 +264,7 @@ class LegacySignedImage(SignableImageProto, Protocol):
class CosiSignatureHeaderProto(Protocol): class CosiSignatureHeaderProto(Protocol):
hw_model: t.Union[fw_models.Model, bytes]
signature: bytes signature: bytes
sigmask: int sigmask: int
@ -280,6 +281,11 @@ class CosiSignedMixin:
def get_header(self) -> CosiSignatureHeaderProto: def get_header(self) -> CosiSignatureHeaderProto:
raise NotImplementedError raise NotImplementedError
def get_model_keys(self, dev_keys: bool) -> fw_models.ModelKeys:
hw_model = self.get_header().hw_model
model = fw_models.Model.from_hw_model(hw_model)
return model.model_keys(dev_keys)
class VendorHeader(firmware.VendorHeader, CosiSignedMixin): class VendorHeader(firmware.VendorHeader, CosiSignedMixin):
NAME: t.ClassVar[str] = "vendorheader" NAME: t.ClassVar[str] = "vendorheader"
@ -318,10 +324,7 @@ class VendorHeader(firmware.VendorHeader, CosiSignedMixin):
return self._format(terse=False) return self._format(terse=False)
def public_keys(self, dev_keys: bool = False) -> t.Sequence[bytes]: def public_keys(self, dev_keys: bool = False) -> t.Sequence[bytes]:
if not dev_keys: return self.get_model_keys(dev_keys).bootloader_keys
return fw_models.TREZOR_T.bootloader_keys
else:
return fw_models.TREZOR_T_DEV.bootloader_keys
class VendorFirmware(firmware.VendorFirmware, CosiSignedMixin): class VendorFirmware(firmware.VendorFirmware, CosiSignedMixin):
@ -362,18 +365,6 @@ class BootloaderImage(firmware.FirmwareImage, CosiSignedMixin):
NAME: t.ClassVar[str] = "bootloader" NAME: t.ClassVar[str] = "bootloader"
DEV_KEYS = _make_dev_keys(b"\x41", b"\x42") DEV_KEYS = _make_dev_keys(b"\x41", b"\x42")
def get_model(self) -> fw_models.Model:
if isinstance(self.header.hw_model, fw_models.Model):
return self.header.hw_model
return fw_models.Model.T
def get_model_keys(self, dev_keys: bool) -> fw_models.ModelKeys:
model = self.get_model()
if dev_keys:
return fw_models.MODEL_MAP_DEV[model]
else:
return fw_models.MODEL_MAP[model]
def get_header(self) -> CosiSignatureHeaderProto: def get_header(self) -> CosiSignatureHeaderProto:
return self.header return self.header

View File

@ -48,7 +48,7 @@ class FirmwareHeader(Struct):
code_length: int code_length: int
version: t.Tuple[int, int, int, int] version: t.Tuple[int, int, int, int]
fix_version: t.Tuple[int, int, int, int] fix_version: t.Tuple[int, int, int, int]
hw_model: Model hw_model: t.Union[Model, bytes]
hw_revision: int hw_revision: int
monotonic: int monotonic: int
hashes: t.List[bytes] hashes: t.List[bytes]

View File

@ -18,12 +18,30 @@ import typing as t
from dataclasses import dataclass from dataclasses import dataclass
from enum import Enum from enum import Enum
if t.TYPE_CHECKING:
from typing_extensions import Self
class Model(Enum): class Model(Enum):
ONE = b"T1B1" ONE = b"T1B1"
T = b"T2T1" T = b"T2T1"
R = b"T2B1" R = b"T2B1"
@classmethod
def from_hw_model(cls, hw_model: t.Union["Self", bytes]) -> "Self":
if isinstance(hw_model, cls):
return hw_model
if hw_model == b"\x00\x00\x00\x00":
return cls.T
raise ValueError(f"Unknown hardware model: {hw_model}")
def model_keys(self, dev_keys: bool = False) -> "ModelKeys":
if dev_keys:
model_map = MODEL_MAP_DEV
else:
model_map = MODEL_MAP
return model_map[self]
@dataclass @dataclass
class ModelKeys: class ModelKeys:

View File

@ -23,9 +23,9 @@ from construct_classes import Struct, subcon
from .. import cosi from .. import cosi
from ..toif import ToifStruct from ..toif import ToifStruct
from ..tools import TupleAdapter from ..tools import EnumAdapter, TupleAdapter
from . import util from . import util
from .models import TREZOR_T, TREZOR_T_DEV from .models import Model
__all__ = [ __all__ = [
"VendorTrust", "VendorTrust",
@ -75,6 +75,7 @@ class VendorHeader(Struct):
version: t.Tuple[int, int] version: t.Tuple[int, int]
sig_m: int sig_m: int
# sig_n: int # sig_n: int
hw_model: t.Union[Model, bytes]
pubkeys: t.List[bytes] pubkeys: t.List[bytes]
text: str text: str
image: t.Dict[str, t.Any] image: t.Dict[str, t.Any]
@ -93,7 +94,8 @@ class VendorHeader(Struct):
"sig_m" / c.Int8ul, "sig_m" / c.Int8ul,
"sig_n" / c.Rebuild(c.Int8ul, c.len_(c.this.pubkeys)), "sig_n" / c.Rebuild(c.Int8ul, c.len_(c.this.pubkeys)),
"trust" / VendorTrust.SUBCON, "trust" / VendorTrust.SUBCON,
"_reserved" / c.Padding(14), "hw_model" / EnumAdapter(c.Bytes(4), Model),
"_reserved" / c.Padding(10),
"pubkeys" / c.Bytes(32)[c.this.sig_n], "pubkeys" / c.Bytes(32)[c.this.sig_n],
"text" / c.Aligned(4, c.PascalString(c.Int8ul, "utf-8")), "text" / c.Aligned(4, c.PascalString(c.Int8ul, "utf-8")),
"image" / ToifStruct, "image" / ToifStruct,
@ -128,19 +130,13 @@ class VendorHeader(Struct):
def verify(self, dev_keys: bool = False) -> None: def verify(self, dev_keys: bool = False) -> None:
digest = self.digest() digest = self.digest()
if not dev_keys: model_keys = Model.from_hw_model(self.hw_model).model_keys(dev_keys)
public_keys = TREZOR_T.bootloader_keys
sigs_needed = TREZOR_T.bootloader_sigs_needed
else:
public_keys = TREZOR_T_DEV.bootloader_keys
sigs_needed = TREZOR_T_DEV.bootloader_sigs_needed
# TODO: add model awareness
try: try:
cosi.verify( cosi.verify(
self.signature, self.signature,
digest, digest,
sigs_needed, model_keys.bootloader_sigs_needed,
public_keys, model_keys.bootloader_keys,
self.sigmask, self.sigmask,
) )
except Exception: except Exception:

View File

@ -29,6 +29,7 @@ VENDOR_HEADER = (
/ "core" / "core"
/ "embed" / "embed"
/ "vendorheader" / "vendorheader"
/ "T2T1"
/ "vendorheader_satoshilabs_signed_prod.bin" / "vendorheader_satoshilabs_signed_prod.bin"
) )