Skip to content

Commit

Permalink
fix(core): calculate image hash including padding between header and …
Browse files Browse the repository at this point in the history
…code

[no changelog]
  • Loading branch information
TychoVrahe committed Jan 29, 2025
1 parent b75c0a8 commit d9c547c
Show file tree
Hide file tree
Showing 9 changed files with 24 additions and 65 deletions.
9 changes: 1 addition & 8 deletions core/embed/projects/boardloader/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -181,14 +181,7 @@ static uint32_t check_sdcard(void) {
_Static_assert(IMAGE_CHUNK_SIZE >= BOOTLOADER_MAXSIZE,
"BOOTLOADER IMAGE MAXSIZE too large for IMAGE_CHUNK_SIZE");

const uint32_t headers_end_offset = hdr->hdrlen;
const uint32_t code_start_offset = IMAGE_CODE_ALIGN(headers_end_offset);

for (uint32_t i = headers_end_offset; i < code_start_offset; i++) {
if (((uint8_t *)sdcard_buf)[i] != 0) {
return 0;
}
}
const uint32_t code_start_offset = hdr->hdrlen;

if (sectrue !=
(check_single_hash(hdr->hashes,
Expand Down
17 changes: 1 addition & 16 deletions core/embed/projects/bootloader/messages.c
Original file line number Diff line number Diff line change
Expand Up @@ -595,21 +595,6 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size,

memcpy(&hdr, received_hdr, sizeof(hdr));

size_t headers_end = IMAGE_HEADER_SIZE + vhdr.hdrlen;
size_t tmp_headers_offset =
IMAGE_CODE_ALIGN(IMAGE_HEADER_SIZE + vhdr.hdrlen);

// check padding between headers and the code
for (size_t i = headers_end; i < tmp_headers_offset; i++) {
if (CHUNK_BUFFER_PTR[i] != 0) {
MSG_SEND_INIT(Failure);
MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError);
MSG_SEND_ASSIGN_STRING(message, "Invalid chunk padding");
MSG_SEND(Failure);
return UPLOAD_ERR_INVALID_CHUNK_PADDING;
}
}

vendor_header current_vhdr;

secbool is_new = secfalse;
Expand Down Expand Up @@ -727,7 +712,7 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size,
ensure(erase_storage(NULL), NULL);
}

headers_offset = IMAGE_CODE_ALIGN(IMAGE_HEADER_SIZE + vhdr.hdrlen);
headers_offset = IMAGE_HEADER_SIZE + vhdr.hdrlen;
read_offset = IMAGE_INIT_CHUNK_SIZE;

// request the rest of the first chunk
Expand Down
2 changes: 1 addition & 1 deletion core/embed/projects/bootloader_ci/messages.c
Original file line number Diff line number Diff line change
Expand Up @@ -556,7 +556,7 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size,

// no user confirmations, go directly to upload

headers_offset = IMAGE_CODE_ALIGN(IMAGE_HEADER_SIZE + vhdr.hdrlen);
headers_offset = IMAGE_HEADER_SIZE + vhdr.hdrlen;
read_offset = IMAGE_INIT_CHUNK_SIZE;

// request the rest of the first chunk
Expand Down
7 changes: 6 additions & 1 deletion core/embed/sys/linker/stm32u5g/bootloader.ld
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,18 @@ _shutdown_clear_ram_2_end = MCU_SRAM6 + MCU_SRAM6_SIZE;
_shutdown_clear_ram_3_start = MCU_SRAM4;
_shutdown_clear_ram_3_end = MCU_SRAM4 + MCU_SRAM4_SIZE;

_codelen = SIZEOF(.flash) + SIZEOF(.data) + SIZEOF(.confidential);
_codelen = SIZEOF(.padding) + SIZEOF(.flash) + SIZEOF(.data) + SIZEOF(.confidential);

SECTIONS {
.header : ALIGN(4) {
KEEP(*(.header));
} >FLASH AT>FLASH

.padding : ALIGN(4) {
. = ALIGN(4);
. = ALIGN(CODE_ALIGNMENT);
} >FLASH AT>FLASH

.flash : ALIGN(CODE_ALIGNMENT) {
KEEP(*(.vector_table));
. = ALIGN(4);
Expand Down
7 changes: 6 additions & 1 deletion core/embed/sys/linker/stm32u5g/firmware.ld
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ confidential_lma = LOADADDR(.confidential);
confidential_vma = ADDR(.confidential);
confidential_size = SIZEOF(.confidential);

_codelen = SIZEOF(.flash) + SIZEOF(.data) + SIZEOF(.confidential);
_codelen = SIZEOF(.padding) + SIZEOF(.flash) + SIZEOF(.data) + SIZEOF(.confidential);
_flash_start = ORIGIN(FLASH);
_flash_end = ORIGIN(FLASH) + LENGTH(FLASH);
_heap_start = ADDR(.heap);
Expand All @@ -39,6 +39,11 @@ SECTIONS {
KEEP(*(.header));
} >FLASH AT>FLASH

.padding : ALIGN(4) {
. = ALIGN(4);
. = ALIGN(CODE_ALIGNMENT);
} >FLASH AT>FLASH

.flash : ALIGN(CODE_ALIGNMENT) {
KEEP(*(.kernel));
. = ALIGN(COREAPP_ALIGNMENT);
Expand Down
6 changes: 5 additions & 1 deletion core/embed/sys/linker/stm32u5g/prodtest.ld
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ _shutdown_clear_ram_3_start = MCU_SRAM4;
_shutdown_clear_ram_3_end = MCU_SRAM4 + MCU_SRAM4_SIZE;


_codelen = SIZEOF(.flash) + SIZEOF(.data) + SIZEOF(.confidential);
_codelen = SIZEOF(.padding) + SIZEOF(.flash) + SIZEOF(.data) + SIZEOF(.confidential);
_flash_start = ORIGIN(FLASH);
_flash_end = ORIGIN(FLASH) + LENGTH(FLASH);

Expand All @@ -67,6 +67,10 @@ SECTIONS {

.header : ALIGN(4) {
KEEP(*(.header));
} >FLASH AT>FLASH

.padding : ALIGN(4) {
. = ALIGN(4);
. = ALIGN(CODE_ALIGNMENT);
} >FLASH AT>FLASH

Expand Down
15 changes: 4 additions & 11 deletions core/embed/util/image/image.c
Original file line number Diff line number Diff line change
Expand Up @@ -263,18 +263,11 @@ secbool check_image_contents(const image_header *const hdr, uint32_t firstskip,
}

// Check the firmware integrity, calculate and compare hashes
size_t offset = IMAGE_CODE_ALIGN(firstskip);
size_t end_offset = offset + hdr->codelen;

// Check area between headers and code
uint32_t padding_size = offset - firstskip;
const uint8_t *addr =
(uint8_t *)flash_area_get_address(area, firstskip, padding_size);
for (size_t i = 0; i < padding_size; i++) {
if (*addr++ != 0) {
return secfalse;
}
}
// check hashes of image chunks
// we hash the image including the padding to the end of the area
size_t offset = firstskip;
size_t end_offset = offset + hdr->codelen;

while (offset < end_offset) {
size_t bytes_to_check = MIN(IMAGE_CHUNK_SIZE - (offset % IMAGE_CHUNK_SIZE),
Expand Down
11 changes: 0 additions & 11 deletions python/src/trezorlib/firmware/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,22 +113,11 @@ class FirmwareImage(Struct):
SUBCON = c.Struct(
"header" / FirmwareHeader.SUBCON,
"_header_end" / c.Tell,
"padding"
/ c.Padding(
lambda this: FirmwareImage.calc_padding(
this.header.hw_model, this._header_end
)
),
"_code_offset" / c.Tell,
"code" / c.Bytes(c.this.header.code_length),
c.Terminated,
)

@staticmethod
def calc_padding(hw_model: bytes, len: int) -> int:
alignment = Model.from_hw_model(hw_model).code_alignment()
return ((len + alignment - 1) & ~(alignment - 1)) - len

def get_hash_params(self) -> "util.FirmwareHashParameters":
return Model.from_hw_model(self.header.hw_model).hash_params()

Expand Down
15 changes: 0 additions & 15 deletions python/src/trezorlib/firmware/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,6 @@ def model_keys(self, dev_keys: bool = False) -> "ModelKeys":
def hash_params(self) -> "FirmwareHashParameters":
return MODEL_HASH_PARAMS_MAP[self]

def code_alignment(self) -> int:
return MODEL_CODE_ALIGNMENT_MAP[self]


@dataclass
class ModelKeys:
Expand Down Expand Up @@ -368,18 +365,6 @@ class ModelKeys:
Model.D002: D002_HASH_PARAMS,
}


MODEL_CODE_ALIGNMENT_MAP = {
Model.T1B1: 0x200,
Model.T2T1: 0x200,
Model.T2B1: 0x200,
Model.T3T1: 0x200,
Model.T3B1: 0x200,
Model.T3W1: 0x200,
Model.D001: 0x200,
Model.D002: 0x400,
}

# deprecated aliases -- don't add more

TREZOR_ONE_V1V2 = LEGACY_V1V2
Expand Down

0 comments on commit d9c547c

Please sign in to comment.