Browse Source

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().
KonstantinKondrashov 4 years ago
parent
commit
54ae758b77

+ 1 - 3
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) {

+ 53 - 80
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;