bootloader_support: consider signature sector in image length validation

For secure boot enabled cases, bootloader and firmware images have signature
appended and size is variable based on scheme being used. This appended data
must be considered while verifying image length against allocated partition
size to avoid any possibilities of going beyond reserved size.

Closes IDF-5617
This commit is contained in:
Mahavir Jain
2022-07-27 17:33:43 +05:30
parent d3a7d21d0c
commit db7c4e4938

View File

@ -36,6 +36,8 @@
#include "esp32c2/rom/secure_boot.h"
#endif
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
/* Checking signatures as part of verifying images is necessary:
- Always if secure boot is enabled
- Differently in bootloader and/or app, depending on kconfig
@ -107,7 +109,7 @@ static esp_err_t verify_segment_header(int index, const esp_image_segment_header
while(0)
static esp_err_t process_image_header(esp_image_metadata_t *data, uint32_t part_offset, bootloader_sha256_handle_t *sha_handle, bool do_verify, bool silent);
static esp_err_t process_appended_hash(esp_image_metadata_t *data, uint32_t part_len, bool do_verify, bool silent);
static esp_err_t process_appended_hash_and_sig(esp_image_metadata_t *data, uint32_t part_offset, uint32_t part_len, bool do_verify, bool silent);
static esp_err_t process_checksum(bootloader_sha256_handle_t sha_handle, uint32_t checksum_word, esp_image_metadata_t *data, bool silent, bool skip_check_checksum);
static esp_err_t __attribute__((unused)) verify_secure_boot_signature(bootloader_sha256_handle_t sha_handle, esp_image_metadata_t *data, uint8_t *image_digest, uint8_t *verified_digest);
@ -159,7 +161,7 @@ static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_
CHECK_ERR(process_segments(data, silent, do_load, sha_handle, checksum));
bool skip_check_checksum = !do_verify || esp_cpu_dbgr_is_attached();
CHECK_ERR(process_checksum(sha_handle, checksum_word, data, silent, skip_check_checksum));
CHECK_ERR(process_appended_hash(data, part->size, do_verify, silent));
CHECK_ERR(process_appended_hash_and_sig(data, part->offset, part->size, do_verify, silent));
if (verify_sha) {
#if (SECURE_BOOT_CHECK_SIGNATURE == 1)
// secure boot images have a signature appended
@ -299,7 +301,7 @@ esp_err_t esp_image_get_metadata(const esp_partition_pos_t *part, esp_image_meta
CHECK_ERR(process_segments(metadata, silent, do_load, NULL, NULL));
bool skip_check_checksum = true;
CHECK_ERR(process_checksum(NULL, 0, metadata, silent, skip_check_checksum));
CHECK_ERR(process_appended_hash(metadata, part->size, true, silent));
CHECK_ERR(process_appended_hash_and_sig(metadata, part->offset, part->size, true, silent));
return ESP_OK;
err:
return err;
@ -762,7 +764,7 @@ esp_err_t esp_image_verify_bootloader_data(esp_image_metadata_t *data)
data);
}
static esp_err_t process_appended_hash(esp_image_metadata_t *data, uint32_t part_len, bool do_verify, bool silent)
static esp_err_t process_appended_hash_and_sig(esp_image_metadata_t *data, uint32_t part_offset, uint32_t part_len, bool do_verify, bool silent)
{
esp_err_t err = ESP_OK;
if (data->image.hash_appended) {
@ -773,8 +775,34 @@ static esp_err_t process_appended_hash(esp_image_metadata_t *data, uint32_t part
data->image_len += HASH_LEN;
}
if (data->image_len > part_len) {
FAIL_LOAD("Image length %d doesn't fit in partition length %d", data->image_len, part_len);
uint32_t sig_block_len = 0;
const uint32_t end = data->image_len;
#if CONFIG_SECURE_BOOT || CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT
// Case I: Bootloader part
if (part_offset == ESP_BOOTLOADER_OFFSET) {
// For bootloader with secure boot v1, signature stays in an independant flash
// sector (offset 0x0) and does not get appended to the image.
#if CONFIG_SECURE_BOOT_V2_ENABLED
// Sanity check - secure boot v2 signature block starts on 4K boundary
sig_block_len = ALIGN_UP(end, FLASH_SECTOR_SIZE) - end;
sig_block_len += sizeof(ets_secure_boot_signature_t);
#endif
} else {
// Case II: Application part
#if CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME
sig_block_len = sizeof(esp_secure_boot_sig_block_t);
#else
// Sanity check - secure boot v2 signature block starts on 4K boundary
sig_block_len = ALIGN_UP(end, FLASH_SECTOR_SIZE) - end;
sig_block_len += sizeof(ets_secure_boot_signature_t);
#endif
}
#endif // CONFIG_SECURE_BOOT || CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT
const uint32_t full_image_len = end + sig_block_len;
if (full_image_len > part_len) {
FAIL_LOAD("Image length %d doesn't fit in partition length %d", full_image_len, part_len);
}
return err;
err:
@ -835,7 +863,7 @@ static esp_err_t verify_secure_boot_signature(bootloader_sha256_handle_t sha_han
#if CONFIG_SECURE_BOOT_V2_ENABLED
// End of the image needs to be padded all the way to a 4KB boundary, after the simple hash
// (for apps they are usually already padded due to --secure-pad-v2, only a problem if this option was not used.)
uint32_t padded_end = (end + FLASH_SECTOR_SIZE - 1) & ~(FLASH_SECTOR_SIZE-1);
uint32_t padded_end = ALIGN_UP(end, FLASH_SECTOR_SIZE);
if (padded_end > end) {
const void *padding = bootloader_mmap(end, padded_end - end);
bootloader_sha256_data(sha_handle, padding, padded_end - end);