feat(core): add hw_model field to vendor headers

pull/3048/head
matejcik 1 year ago
parent da14c22712
commit b6c2f2e5ba

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

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

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

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

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

@ -27,6 +27,10 @@ def build_vendorheader(specfile, image, outfile):
spec["image"] = toif.ToifStruct.parse(image.read())
spec["sigmask"] = 0
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)
if "header_len" not in spec:

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

@ -264,6 +264,7 @@ class LegacySignedImage(SignableImageProto, Protocol):
class CosiSignatureHeaderProto(Protocol):
hw_model: t.Union[fw_models.Model, bytes]
signature: bytes
sigmask: int
@ -280,6 +281,11 @@ class CosiSignedMixin:
def get_header(self) -> CosiSignatureHeaderProto:
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):
NAME: t.ClassVar[str] = "vendorheader"
@ -318,10 +324,7 @@ class VendorHeader(firmware.VendorHeader, CosiSignedMixin):
return self._format(terse=False)
def public_keys(self, dev_keys: bool = False) -> t.Sequence[bytes]:
if not dev_keys:
return fw_models.TREZOR_T.bootloader_keys
else:
return fw_models.TREZOR_T_DEV.bootloader_keys
return self.get_model_keys(dev_keys).bootloader_keys
class VendorFirmware(firmware.VendorFirmware, CosiSignedMixin):
@ -362,18 +365,6 @@ class BootloaderImage(firmware.FirmwareImage, CosiSignedMixin):
NAME: t.ClassVar[str] = "bootloader"
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:
return self.header

@ -48,7 +48,7 @@ class FirmwareHeader(Struct):
code_length: int
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
monotonic: int
hashes: t.List[bytes]

@ -18,12 +18,30 @@ import typing as t
from dataclasses import dataclass
from enum import Enum
if t.TYPE_CHECKING:
from typing_extensions import Self
class Model(Enum):
ONE = b"T1B1"
T = b"T2T1"
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
class ModelKeys:

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

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

Loading…
Cancel
Save