1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-02-06 20:52:40 +00:00

fix(core): calculate image hash including padding between header and code

[no changelog]
This commit is contained in:
tychovrahe 2025-01-20 22:26:56 +01:00 committed by TychoVrahe
parent b75c0a844d
commit d9c547c590
9 changed files with 24 additions and 65 deletions

View File

@ -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,

View File

@ -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;
@ -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

View File

@ -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

View File

@ -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);

View File

@ -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);
@ -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);

View File

@ -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);
@ -67,6 +67,10 @@ SECTIONS {
.header : ALIGN(4) {
KEEP(*(.header));
} >FLASH AT>FLASH
.padding : ALIGN(4) {
. = ALIGN(4);
. = ALIGN(CODE_ALIGNMENT);
} >FLASH AT>FLASH

View File

@ -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),

View File

@ -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()

View File

@ -66,9 +66,6 @@ class Model(Enum):
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:
@ -368,18 +365,6 @@ MODEL_HASH_PARAMS_MAP = {
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