1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-22 14:28: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; 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( while (offset < end_offset) {
area, firstskip, MIN(remaining, IMAGE_CHUNK_SIZE - firstskip)); size_t bytes_to_check = MIN(IMAGE_CHUNK_SIZE - (offset % IMAGE_CHUNK_SIZE),
end_offset - offset);
const void *data = flash_area_get_address(area, offset, bytes_to_check);
if (!data) { if (!data) {
return secfalse; return secfalse;
} }
size_t hash_offset = (offset / IMAGE_CHUNK_SIZE) * 32;
if (sectrue != if (sectrue !=
check_single_hash(hdr->hashes, data, check_single_hash(hdr->hashes + hash_offset, data, bytes_to_check)) {
MIN(remaining, IMAGE_CHUNK_SIZE - firstskip))) {
return secfalse; return secfalse;
} }
remaining -= IMAGE_CHUNK_SIZE - firstskip; offset += bytes_to_check;
}
int chunk = 1; // Check the padding to the end of the area
end_offset = flash_area_get_size(area);
while (remaining > 0) { if (offset < end_offset) {
data = flash_area_get_address(area, chunk * IMAGE_CHUNK_SIZE, // Use the first byte in the checked area as the expected padding byte
MIN(remaining, IMAGE_CHUNK_SIZE)); // 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) { if (!data) {
return secfalse; return secfalse;
} }
if (sectrue != check_single_hash(hdr->hashes + chunk * 32, data,
MIN(remaining, IMAGE_CHUNK_SIZE))) { for (size_t i = 0; i < bytes_to_check; i++) {
if (data[i] != expected_byte) {
return secfalse; return secfalse;
} }
chunk++; }
remaining -= IMAGE_CHUNK_SIZE;
offset += bytes_to_check;
}
} }
return sectrue; return sectrue;