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

feat(core/bootloader): check firmware padding

This commit is contained in:
cepetr 2023-10-25 09:34:50 +02:00 committed by matejcik
parent da7125f427
commit 02f34a2748

View File

@ -243,35 +243,60 @@ secbool check_image_contents(const image_header *const hdr, uint32_t firstskip,
return secfalse;
}
int remaining = hdr->codelen;
// Check the firmware integrity, calculate and compare hashes
size_t offset = firstskip;
size_t end_offset = offset + hdr->codelen;
const void *data = flash_area_get_address(
area, firstskip, MIN(remaining, IMAGE_CHUNK_SIZE - firstskip));
if (!data) {
return secfalse;
}
if (sectrue !=
check_single_hash(hdr->hashes, data,
MIN(remaining, IMAGE_CHUNK_SIZE - firstskip))) {
return secfalse;
}
while (offset < end_offset) {
size_t bytes_to_check = MIN(IMAGE_CHUNK_SIZE - (offset % IMAGE_CHUNK_SIZE),
end_offset - offset);
remaining -= IMAGE_CHUNK_SIZE - firstskip;
int chunk = 1;
while (remaining > 0) {
data = flash_area_get_address(area, chunk * IMAGE_CHUNK_SIZE,
MIN(remaining, IMAGE_CHUNK_SIZE));
const void *data = flash_area_get_address(area, offset, bytes_to_check);
if (!data) {
return secfalse;
}
if (sectrue != check_single_hash(hdr->hashes + chunk * 32, data,
MIN(remaining, IMAGE_CHUNK_SIZE))) {
size_t hash_offset = (offset / IMAGE_CHUNK_SIZE) * 32;
if (sectrue !=
check_single_hash(hdr->hashes + hash_offset, data, bytes_to_check)) {
return secfalse;
}
chunk++;
remaining -= IMAGE_CHUNK_SIZE;
offset += bytes_to_check;
}
// Check the padding to the end of the area
end_offset = flash_area_get_size(area);
if (offset < end_offset) {
// Use the first byte in the checked area as the expected padding byte
// Firmware is always padded with 0xFF, while the bootloader might be
// padded with 0x00 as well
uint8_t expected_byte = *(
(const uint8_t *)flash_area_get_address(area, offset, sizeof(uint8_t)));
if (expected_byte != 0x00 && expected_byte != 0xFF) {
return secfalse;
}
while (offset < end_offset) {
size_t bytes_to_check = MIN(
IMAGE_CHUNK_SIZE - (offset % IMAGE_CHUNK_SIZE), end_offset - offset);
const uint8_t *data =
(const uint8_t *)flash_area_get_address(area, offset, bytes_to_check);
if (!data) {
return secfalse;
}
for (size_t i = 0; i < bytes_to_check; i++) {
if (data[i] != expected_byte) {
return secfalse;
}
}
offset += bytes_to_check;
}
}
return sectrue;