From 54ae758b771963f895e6e6ebc0baaa7e4cbc1e0c Mon Sep 17 00:00:00 2001 From: KonstantinKondrashov Date: Tue, 27 Apr 2021 18:49:37 +0800 Subject: [PATCH] bootloader_support: Used esp_image_get_metadata() instead of esp_image_verify() - bootloader_common_get_sha256_of_partition will not do any unnecessery verifies. - Used esp_image_get_metadata() instead of esp_image_verify(). --- .../src/bootloader_common.c | 4 +- .../bootloader_support/src/esp_image_format.c | 133 +++++++----------- 2 files changed, 54 insertions(+), 83 deletions(-) diff --git a/components/bootloader_support/src/bootloader_common.c b/components/bootloader_support/src/bootloader_common.c index 2bf2074988..0a081679b9 100644 --- a/components/bootloader_support/src/bootloader_common.c +++ b/components/bootloader_support/src/bootloader_common.c @@ -163,9 +163,7 @@ esp_err_t bootloader_common_get_sha256_of_partition (uint32_t address, uint32_t .size = size, }; esp_image_metadata_t data; - // Function esp_image_verify() verifies and fills the structure data. - // here important to get: image_digest, image_len, hash_appended. - if (esp_image_verify(ESP_IMAGE_VERIFY_SILENT, &partition_pos, &data) != ESP_OK) { + if (esp_image_get_metadata(&partition_pos, &data) != ESP_OK) { return ESP_ERR_IMAGE_INVALID; } if (data.image.hash_appended) { diff --git a/components/bootloader_support/src/esp_image_format.c b/components/bootloader_support/src/esp_image_format.c index afe2eb4ad6..707b64fdbc 100644 --- a/components/bootloader_support/src/esp_image_format.c +++ b/components/bootloader_support/src/esp_image_format.c @@ -112,7 +112,7 @@ static esp_err_t verify_segment_header(int index, const esp_image_segment_header 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_checksum(bootloader_sha256_handle_t sha_handle, uint32_t checksum_word, esp_image_metadata_t *data, bool silent, bool skip_calc_checksum); +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); static esp_err_t __attribute__((unused)) verify_simple_hash(bootloader_sha256_handle_t sha_handle, esp_image_metadata_t *data); @@ -137,6 +137,15 @@ static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_ uint8_t image_digest[HASH_LEN] = { [ 0 ... 31] = 0xEE }; uint8_t verified_digest[HASH_LEN] = { [ 0 ... 31 ] = 0x01 }; #endif +#if CONFIG_SECURE_BOOT_V2_ENABLED + // For Secure Boot V2, we do verify signature on bootloader which includes the SHA calculation. + bool verify_sha = do_verify; +#else // Secure boot not enabled + // For secure boot V1 on ESP32, we don't calculate SHA or verify signature on bootloaders. + // (For non-secure boot, we don't verify any SHA-256 hash appended to the bootloader because + // esptool.py may have rewritten the header - rely on esptool.py having verified the bootloader at flashing time, instead.) + bool verify_sha = (data->start_addr != ESP_BOOTLOADER_OFFSET) && do_verify; +#endif if (data == NULL || part == NULL) { return ESP_ERR_INVALID_ARG; @@ -148,48 +157,34 @@ static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_ } bootloader_sha256_handle_t *p_sha_handle = &sha_handle; - CHECK_ERR(process_image_header(data, part->offset, p_sha_handle, do_verify, silent)); + CHECK_ERR(process_image_header(data, part->offset, (verify_sha) ? p_sha_handle : NULL, do_verify, silent)); CHECK_ERR(process_segments(data, silent, do_load, sha_handle, checksum)); - bool skip_calc_checksum = !do_verify || esp_cpu_in_ocd_debug_mode(); - CHECK_ERR(process_checksum(sha_handle, checksum_word, data, silent, skip_calc_checksum)); + bool skip_check_checksum = !do_verify || esp_cpu_in_ocd_debug_mode(); + CHECK_ERR(process_checksum(sha_handle, checksum_word, data, silent, skip_check_checksum)); CHECK_ERR(process_appended_hash(data, part->size, do_verify, silent)); - if (do_verify) { - /* For secure boot V1 on ESP32, we don't calculate SHA or verify signature on bootloaders. - For Secure Boot V2, we do verify signature on bootloader which includes the SHA calculation. - - (For non-secure boot, we don't verify any SHA-256 hash appended to the bootloader because - esptool.py may have rewritten the header - rely on esptool.py having verified the bootloader at flashing time, instead.) - */ -#if CONFIG_SECURE_BOOT_V2_ENABLED - bool verify_sha = true; -#else // Secure boot not enabled - bool verify_sha = (data->start_addr != ESP_BOOTLOADER_OFFSET); -#endif - - if (verify_sha) { + if (verify_sha) { #if (SECURE_BOOT_CHECK_SIGNATURE == 1) - // secure boot images have a signature appended + // secure boot images have a signature appended #if defined(BOOTLOADER_BUILD) && !defined(CONFIG_SECURE_BOOT) - // If secure boot is not enabled in hardware, then - // skip the signature check in bootloader when the debugger is attached. - // This is done to allow for breakpoints in Flash. - bool do_verify_sig = !esp_cpu_in_ocd_debug_mode(); + // If secure boot is not enabled in hardware, then + // skip the signature check in bootloader when the debugger is attached. + // This is done to allow for breakpoints in Flash. + bool do_verify_sig = !esp_cpu_in_ocd_debug_mode(); #else // CONFIG_SECURE_BOOT - bool do_verify_sig = true; + bool do_verify_sig = true; #endif // end checking for JTAG - if (do_verify_sig) { - err = verify_secure_boot_signature(sha_handle, data, image_digest, verified_digest); - sha_handle = NULL; // verify_secure_boot_signature finishes sha_handle - } + if (do_verify_sig) { + err = verify_secure_boot_signature(sha_handle, data, image_digest, verified_digest); + sha_handle = NULL; // verify_secure_boot_signature finishes sha_handle + } #else // SECURE_BOOT_CHECK_SIGNATURE - // No secure boot, but SHA-256 can be appended for basic corruption detection - if (sha_handle != NULL && !esp_cpu_in_ocd_debug_mode()) { - err = verify_simple_hash(sha_handle, data); - sha_handle = NULL; // calling verify_simple_hash finishes sha_handle - } + // No secure boot, but SHA-256 can be appended for basic corruption detection + if (sha_handle != NULL && !esp_cpu_in_ocd_debug_mode()) { + err = verify_simple_hash(sha_handle, data); + sha_handle = NULL; // calling verify_simple_hash finishes sha_handle + } #endif // SECURE_BOOT_CHECK_SIGNATURE - } // verify_sha - } // do_verify + } // verify_sha // bootloader may still have a sha256 digest handle open if (sha_handle != NULL) { @@ -290,41 +285,22 @@ esp_err_t esp_image_verify(esp_image_load_mode_t mode, const esp_partition_pos_t esp_err_t esp_image_get_metadata(const esp_partition_pos_t *part, esp_image_metadata_t *metadata) { + esp_err_t err; if (metadata == NULL || part == NULL || part->size > SIXTEEN_MB) { return ESP_ERR_INVALID_ARG; } - memset(metadata, 0, sizeof(esp_image_metadata_t)); - metadata->start_addr = part->offset; - - esp_err_t err = bootloader_flash_read(metadata->start_addr, &metadata->image, sizeof(esp_image_header_t), true); - if (err != ESP_OK) { - return err; - } - uint32_t next_addr = metadata->start_addr + sizeof(esp_image_header_t); - for (int i = 0; i < metadata->image.segment_count; i++) { - esp_image_segment_header_t *header = &metadata->segments[i]; - err = process_segment(i, next_addr, header, true, false, NULL, NULL); - if (err != ESP_OK) { - return err; - } - next_addr += sizeof(esp_image_segment_header_t); - metadata->segment_data[i] = next_addr; - next_addr += header->data_len; - } - metadata->image_len = next_addr - metadata->start_addr; - - // checksum - uint32_t unpadded_length = metadata->image_len; - uint32_t length = unpadded_length + 1; // Add a byte for the checksum - length = (length + 15) & ~15; // Pad to next full 16 byte block - if (metadata->image.hash_appended) { - // Account for the hash in the total image length - length += HASH_LEN; - } - metadata->image_len = length; - + bool silent = true; + bool do_verify = false; + bool do_load = false; + CHECK_ERR(process_image_header(metadata, part->offset, NULL, do_verify, silent)); + 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)); return ESP_OK; +err: + return err; } static esp_err_t verify_image_header(uint32_t src_addr, const esp_image_header_t *image, bool silent) @@ -803,7 +779,7 @@ err: return err; } -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_calc_checksum) +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) { esp_err_t err = ESP_OK; uint32_t unpadded_length = data->image_len; @@ -811,21 +787,18 @@ static esp_err_t process_checksum(bootloader_sha256_handle_t sha_handle, uint32_ length = (length + 15) & ~15; // Pad to next full 16 byte block length = length - unpadded_length; - if (!skip_calc_checksum) { - // Verify checksum - WORD_ALIGNED_ATTR uint8_t buf[16]; + // Verify checksum + WORD_ALIGNED_ATTR uint8_t buf[16]; + if (!skip_check_checksum || sha_handle != NULL) { CHECK_ERR(bootloader_flash_read(data->start_addr + unpadded_length, buf, length, true)); - uint8_t calc = buf[length - 1]; - uint8_t checksum = (checksum_word >> 24) - ^ (checksum_word >> 16) - ^ (checksum_word >> 8) - ^ (checksum_word >> 0); - if (checksum != calc) { - FAIL_LOAD("Checksum failed. Calculated 0x%x read 0x%x", checksum, calc); - } - if (sha_handle != NULL) { - bootloader_sha256_data(sha_handle, buf, length); - } + } + uint8_t read_checksum = buf[length - 1]; + uint8_t calc_checksum = (checksum_word >> 24) ^ (checksum_word >> 16) ^ (checksum_word >> 8) ^ (checksum_word >> 0); + if (!skip_check_checksum && calc_checksum != read_checksum) { + FAIL_LOAD("Checksum failed. Calculated 0x%x read 0x%x", calc_checksum, read_checksum); + } + if (sha_handle != NULL) { + bootloader_sha256_data(sha_handle, buf, length); } data->image_len += length;