mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-18 04:18:10 +00:00
feat(core): add hw_model field to vendor headers
This commit is contained in:
parent
da14c22712
commit
b6c2f2e5ba
1
core/.changelog.d/3048.added
Normal file
1
core/.changelog.d/3048.added
Normal file
@ -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:
|
||||
|
1
python/.changelog.d/3048.added
Normal file
1
python/.changelog.d/3048.added
Normal file
@ -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…
Reference in New Issue
Block a user