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().
This commit is contained in:
KonstantinKondrashov
2021-04-27 18:49:37 +08:00
committed by bot
parent 99af5e9a71
commit 54ae758b77
2 changed files with 54 additions and 83 deletions

View File

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

View File

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