1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-22 14:28:07 +00:00

refactor(core): prepare fw for differently sized fw chunks

[no changelog]
This commit is contained in:
tychovrahe 2023-10-16 21:49:25 +02:00 committed by matejcik
parent 07b6ae9f77
commit 8a4f376f20
10 changed files with 59 additions and 35 deletions

View File

@ -224,12 +224,13 @@ secbool check_image_contents(const image_header *const hdr, uint32_t firstskip,
return secfalse; return secfalse;
} }
const void *data = int remaining = hdr->codelen;
flash_area_get_address(area, firstskip, IMAGE_CHUNK_SIZE - firstskip);
const void *data = flash_area_get_address(
area, firstskip, MIN(remaining, IMAGE_CHUNK_SIZE - firstskip));
if (!data) { if (!data) {
return secfalse; return secfalse;
} }
int remaining = hdr->codelen;
if (sectrue != if (sectrue !=
check_single_hash(hdr->hashes, data, check_single_hash(hdr->hashes, data,
MIN(remaining, IMAGE_CHUNK_SIZE - firstskip))) { MIN(remaining, IMAGE_CHUNK_SIZE - firstskip))) {
@ -242,7 +243,7 @@ secbool check_image_contents(const image_header *const hdr, uint32_t firstskip,
while (remaining > 0) { while (remaining > 0) {
data = flash_area_get_address(area, chunk * IMAGE_CHUNK_SIZE, data = flash_area_get_address(area, chunk * IMAGE_CHUNK_SIZE,
IMAGE_CHUNK_SIZE); MIN(remaining, IMAGE_CHUNK_SIZE));
if (!data) { if (!data) {
return secfalse; return secfalse;
} }

View File

@ -22,11 +22,11 @@
#include <stdint.h> #include <stdint.h>
#include "flash.h" #include "flash.h"
#include "model.h"
#include "secbool.h" #include "secbool.h"
#define IMAGE_HEADER_SIZE 0x400 // size of the bootloader or firmware header #define IMAGE_HEADER_SIZE 0x400 // size of the bootloader or firmware header
#define IMAGE_SIG_SIZE 65 #define IMAGE_SIG_SIZE 65
#define IMAGE_CHUNK_SIZE (128 * 1024)
#define IMAGE_INIT_CHUNK_SIZE (16 * 1024) #define IMAGE_INIT_CHUNK_SIZE (16 * 1024)
#define BOOTLOADER_IMAGE_MAGIC 0x425A5254 // TRZB #define BOOTLOADER_IMAGE_MAGIC 0x425A5254 // TRZB

View File

@ -22,6 +22,7 @@
#define BOOTLOADER_START 0x08020000 #define BOOTLOADER_START 0x08020000
#define FIRMWARE_START 0x08040000 #define FIRMWARE_START 0x08040000
#define IMAGE_CHUNK_SIZE (128 * 1024)
#define BOOTLOADER_IMAGE_MAXSIZE (128 * 1024 * 1) // 128 KB #define BOOTLOADER_IMAGE_MAXSIZE (128 * 1024 * 1) // 128 KB
#define FIRMWARE_IMAGE_MAXSIZE (128 * 1024 * 13) // 1664 KB #define FIRMWARE_IMAGE_MAXSIZE (128 * 1024 * 13) // 1664 KB
#define NORCOW_SECTOR_SIZE (64 * 1024) #define NORCOW_SECTOR_SIZE (64 * 1024)

View File

@ -10,6 +10,7 @@
#define BOOTLOADER_START 0x08000000 #define BOOTLOADER_START 0x08000000
#define FIRMWARE_START 0x08010000 #define FIRMWARE_START 0x08010000
#define IMAGE_CHUNK_SIZE (64 * 1024)
#define BOOTLOADER_IMAGE_MAXSIZE (32 * 1024 * 1) // 32 KB #define BOOTLOADER_IMAGE_MAXSIZE (32 * 1024 * 1) // 32 KB
#define FIRMWARE_IMAGE_MAXSIZE (64 * 1024 * 15) // 960 KB #define FIRMWARE_IMAGE_MAXSIZE (64 * 1024 * 15) // 960 KB
#define NORCOW_SECTOR_SIZE (16 * 1024) #define NORCOW_SECTOR_SIZE (16 * 1024)

View File

@ -22,6 +22,7 @@
#define BOOTLOADER_START 0x08020000 #define BOOTLOADER_START 0x08020000
#define FIRMWARE_START 0x08040000 #define FIRMWARE_START 0x08040000
#define IMAGE_CHUNK_SIZE (128 * 1024)
#define BOOTLOADER_IMAGE_MAXSIZE (128 * 1024 * 1) // 128 KB #define BOOTLOADER_IMAGE_MAXSIZE (128 * 1024 * 1) // 128 KB
#define FIRMWARE_IMAGE_MAXSIZE (128 * 1024 * 13) // 1664 KB #define FIRMWARE_IMAGE_MAXSIZE (128 * 1024 * 13) // 1664 KB
#define NORCOW_SECTOR_SIZE (64 * 1024) #define NORCOW_SECTOR_SIZE (64 * 1024)

View File

@ -22,6 +22,7 @@
#define BOOTLOADER_START 0x08020000 #define BOOTLOADER_START 0x08020000
#define FIRMWARE_START 0x08040000 #define FIRMWARE_START 0x08040000
#define IMAGE_CHUNK_SIZE (128 * 1024)
#define BOOTLOADER_IMAGE_MAXSIZE (128 * 1024 * 1) // 128 KB #define BOOTLOADER_IMAGE_MAXSIZE (128 * 1024 * 1) // 128 KB
#define FIRMWARE_IMAGE_MAXSIZE (128 * 1024 * 13) // 1664 KB #define FIRMWARE_IMAGE_MAXSIZE (128 * 1024 * 13) // 1664 KB
#define NORCOW_SECTOR_SIZE (64 * 1024) #define NORCOW_SECTOR_SIZE (64 * 1024)

View File

@ -18,10 +18,6 @@ from . import models
V1_SIGNATURE_SLOTS = 3 V1_SIGNATURE_SLOTS = 3
ONEV2_CHUNK_SIZE = 1024 * 64
V2_CHUNK_SIZE = 1024 * 128
# === KEYS KEPT FOR COMPATIBILITY === # === KEYS KEPT FOR COMPATIBILITY ===
# use `trezorlib.firmware.models` directly # use `trezorlib.firmware.models` directly

View File

@ -14,7 +14,6 @@
# You should have received a copy of the License along with this library. # You should have received a copy of the License along with this library.
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
import hashlib
import typing as t import typing as t
from copy import copy from copy import copy
from enum import Enum from enum import Enum
@ -117,11 +116,8 @@ class FirmwareImage(Struct):
c.Terminated, c.Terminated,
) )
HASH_PARAMS = util.FirmwareHashParameters( def get_hash_params(self) -> "util.FirmwareHashParameters":
hash_function=hashlib.blake2s, return Model.from_hw_model(self.header.hw_model).hash_params()
chunk_size=consts.V2_CHUNK_SIZE,
padding_byte=None,
)
def code_hashes(self) -> t.List[bytes]: def code_hashes(self) -> t.List[bytes]:
"""Calculate hashes of chunks of `code`. """Calculate hashes of chunks of `code`.
@ -129,26 +125,23 @@ class FirmwareImage(Struct):
Assume that the first `code_offset` bytes of `code` are taken up by the header. Assume that the first `code_offset` bytes of `code` are taken up by the header.
""" """
hashes = [] hashes = []
hash_params = self.get_hash_params()
# End offset for each chunk. Normally this would be (i+1)*chunk_size for i-th chunk, # End offset for each chunk. Normally this would be (i+1)*chunk_size for i-th chunk,
# but the first chunk is shorter by code_offset, so all end offsets are shifted. # but the first chunk is shorter by code_offset, so all end offsets are shifted.
ends = [ ends = [(i + 1) * hash_params.chunk_size - self._code_offset for i in range(16)]
(i + 1) * self.HASH_PARAMS.chunk_size - self._code_offset for i in range(16)
]
start = 0 start = 0
for end in ends: for end in ends:
chunk = self.code[start:end] chunk = self.code[start:end]
# padding for last non-empty chunk # padding for last non-empty chunk
if ( if hash_params.padding_byte is not None and start < len(self.code) < end:
self.HASH_PARAMS.padding_byte is not None chunk += hash_params.padding_byte[0:1] * (end - start - len(chunk))
and start < len(self.code)
and end > len(self.code)
):
chunk += self.HASH_PARAMS.padding_byte[0:1] * (end - start - len(chunk))
if not chunk: if not chunk:
hashes.append(b"\0" * 32) hashes.append(b"\0" * 32)
else: else:
hashes.append(self.HASH_PARAMS.hash_function(chunk).digest()) hashes.append(hash_params.hash_function(chunk).digest())
start = end start = end
@ -159,13 +152,16 @@ class FirmwareImage(Struct):
raise util.FirmwareIntegrityError("Invalid firmware data.") raise util.FirmwareIntegrityError("Invalid firmware data.")
def digest(self) -> bytes: def digest(self) -> bytes:
hash_params = self.get_hash_params()
header = copy(self.header) header = copy(self.header)
header.hashes = self.code_hashes() header.hashes = self.code_hashes()
header.signature = b"\x00" * 64 header.signature = b"\x00" * 64
header.sigmask = 0 header.sigmask = 0
header.v1_key_indexes = [0] * consts.V1_SIGNATURE_SLOTS header.v1_key_indexes = [0] * consts.V1_SIGNATURE_SLOTS
header.v1_signatures = [b"\x00" * 64] * consts.V1_SIGNATURE_SLOTS header.v1_signatures = [b"\x00" * 64] * consts.V1_SIGNATURE_SLOTS
return self.HASH_PARAMS.hash_function(header.build()).digest() return hash_params.hash_function(header.build()).digest()
class VendorFirmware(Struct): class VendorFirmware(Struct):

View File

@ -24,6 +24,7 @@ from construct_classes import Struct, subcon
from . import consts, models, util from . import consts, models, util
from .core import FirmwareImage from .core import FirmwareImage
from .models import Model
__all__ = [ __all__ = [
"LegacyFirmware", "LegacyFirmware",
@ -98,14 +99,11 @@ def check_sig_signmessage(
class LegacyV2Firmware(FirmwareImage): class LegacyV2Firmware(FirmwareImage):
"""Firmware image in the format used by Trezor One 1.8.0 and newer.""" """Firmware image in the format used by Trezor One 1.8.0 and newer."""
HASH_PARAMS = util.FirmwareHashParameters(
hash_function=hashlib.sha256,
chunk_size=consts.ONEV2_CHUNK_SIZE,
padding_byte=b"\xff",
)
V3_FIRST_VERSION = (1, 12, 0) V3_FIRST_VERSION = (1, 12, 0)
def get_hash_params(self) -> "util.FirmwareHashParameters":
return Model.ONE.hash_params()
def verify_v2(self, dev_keys: bool) -> None: def verify_v2(self, dev_keys: bool) -> None:
if not dev_keys: if not dev_keys:
public_keys = models.LEGACY_V1V2.firmware_keys public_keys = models.LEGACY_V1V2.firmware_keys

View File

@ -14,10 +14,13 @@
# You should have received a copy of the License along with this library. # You should have received a copy of the License along with this library.
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
import hashlib
import typing as t import typing as t
from dataclasses import dataclass from dataclasses import dataclass
from enum import Enum from enum import Enum
from .util import FirmwareHashParameters
if t.TYPE_CHECKING: if t.TYPE_CHECKING:
from typing_extensions import Self from typing_extensions import Self
@ -26,12 +29,13 @@ class Model(Enum):
T1B1 = b"T1B1" T1B1 = b"T1B1"
T2T1 = b"T2T1" T2T1 = b"T2T1"
T2B1 = b"T2B1" T2B1 = b"T2B1"
DISC1 = b"D001" D001 = b"D001"
# legacy aliases # legacy aliases
ONE = T1B1 ONE = T1B1
T = T2T1 T = T2T1
R = T2B1 R = T2B1
DISC1 = D001
@classmethod @classmethod
def from_hw_model(cls, hw_model: t.Union["Self", bytes]) -> "Self": def from_hw_model(cls, hw_model: t.Union["Self", bytes]) -> "Self":
@ -48,6 +52,9 @@ class Model(Enum):
model_map = MODEL_MAP model_map = MODEL_MAP
return model_map[self] return model_map[self]
def hash_params(self) -> "FirmwareHashParameters":
return MODEL_HASH_PARAMS_MAP[self]
@dataclass @dataclass
class ModelKeys: class ModelKeys:
@ -206,18 +213,38 @@ T2B1 = ModelKeys(
firmware_sigs_needed=-1, firmware_sigs_needed=-1,
) )
LEGACY_HASH_PARAMS = FirmwareHashParameters(
hash_function=hashlib.sha256,
chunk_size=1024 * 64,
padding_byte=b"\xff",
)
T2T1_HASH_PARAMS = FirmwareHashParameters(
hash_function=hashlib.blake2s,
chunk_size=1024 * 128,
padding_byte=None,
)
MODEL_MAP = { MODEL_MAP = {
Model.T1B1: LEGACY_V3, Model.T1B1: LEGACY_V3,
Model.T2T1: T2T1, Model.T2T1: T2T1,
Model.T2B1: T2B1, Model.T2B1: T2B1,
Model.DISC1: TREZOR_CORE_DEV, Model.D001: TREZOR_CORE_DEV,
} }
MODEL_MAP_DEV = { MODEL_MAP_DEV = {
Model.T1B1: LEGACY_V3_DEV, Model.T1B1: LEGACY_V3_DEV,
Model.T2T1: TREZOR_CORE_DEV, Model.T2T1: TREZOR_CORE_DEV,
Model.T2B1: TREZOR_CORE_DEV, Model.T2B1: TREZOR_CORE_DEV,
Model.DISC1: TREZOR_CORE_DEV, Model.D001: TREZOR_CORE_DEV,
}
MODEL_HASH_PARAMS_MAP = {
Model.T1B1: LEGACY_HASH_PARAMS,
Model.T2T1: T2T1_HASH_PARAMS,
Model.T2B1: T2T1_HASH_PARAMS,
Model.D001: T2T1_HASH_PARAMS,
} }
# aliases # aliases
@ -234,3 +261,5 @@ TREZOR_R_DEV = TREZOR_CORE_DEV
DISC1 = TREZOR_CORE_DEV DISC1 = TREZOR_CORE_DEV
DISC1_DEV = TREZOR_CORE_DEV DISC1_DEV = TREZOR_CORE_DEV
D001 = TREZOR_CORE_DEV
D001_DEV = TREZOR_CORE_DEV