فهرست منبع

Merge branch 'bugfix/bootloader_common_get_sha256_of_partition_v4.0' into 'release/v4.0'

bootloader_support: Fix bootloader_common_get_sha256_of_partition(), can handle a long image (v4.0)

See merge request espressif/esp-idf!9954
Angus Gratton 5 سال پیش
والد
کامیت
36f3845331

+ 2 - 1
components/bootloader_support/include_bootloader/bootloader_flash.h

@@ -22,6 +22,7 @@
 
 
 #define FLASH_SECTOR_SIZE 0x1000
 #define FLASH_SECTOR_SIZE 0x1000
 #define FLASH_BLOCK_SIZE 0x10000
 #define FLASH_BLOCK_SIZE 0x10000
+#define MMAP_ALIGNED_MASK 0x0000FFFF
 
 
 /* Provide a Flash API for bootloader_support code,
 /* Provide a Flash API for bootloader_support code,
    that can be used from bootloader or app code.
    that can be used from bootloader or app code.
@@ -35,7 +36,7 @@
  *
  *
  * @return Number of free pages
  * @return Number of free pages
  */
  */
-uint32_t bootloader_mmap_get_free_pages();
+uint32_t bootloader_mmap_get_free_pages(void);
 
 
 /**
 /**
  * @brief Map a region of flash to data memory
  * @brief Map a region of flash to data memory

+ 1 - 1
components/bootloader_support/include_bootloader/bootloader_sha.h

@@ -26,7 +26,7 @@
 
 
 typedef void *bootloader_sha256_handle_t;
 typedef void *bootloader_sha256_handle_t;
 
 
-bootloader_sha256_handle_t bootloader_sha256_start();
+bootloader_sha256_handle_t bootloader_sha256_start(void);
 
 
 void bootloader_sha256_data(bootloader_sha256_handle_t handle, const void *data, size_t data_len);
 void bootloader_sha256_data(bootloader_sha256_handle_t handle, const void *data, size_t data_len);
 
 

+ 14 - 0
components/bootloader_support/include_bootloader/bootloader_utility.h

@@ -86,3 +86,17 @@ __attribute__((noreturn)) void bootloader_reset(void);
  *           ESP_ERR_INVALID_ARG: Error in the passed arguments
  *           ESP_ERR_INVALID_ARG: Error in the passed arguments
  */
  */
 esp_err_t bootloader_sha256_hex_to_str(char *out_str, const uint8_t *in_array_hex, size_t len);
 esp_err_t bootloader_sha256_hex_to_str(char *out_str, const uint8_t *in_array_hex, size_t len);
+
+/** @brief Generates the digest of the data between offset & offset+length.
+ *
+ * This function should be used when the size of the data is larger than 3.2MB.
+ * The MMU capacity is 3.2MB (50 pages - 64KB each). This function generates the SHA-256 
+ * of the data in chunks of 3.2MB, considering the MMU capacity. 
+ * 
+ * @param[in]  flash_offset  Offset of the data in flash.
+ * @param[in]  len           Length of data in bytes.
+ * @param[out] digest        Pointer to buffer where the digest is written, if ESP_OK is returned. 
+ * 
+ * @return ESP_OK if secure boot digest is generated successfully.
+ */
+esp_err_t bootloader_sha256_flash_contents(uint32_t flash_offset, uint32_t len, uint8_t *digest);

+ 2 - 16
components/bootloader_support/src/bootloader_common.c

@@ -23,6 +23,7 @@
 #include "esp_flash_partitions.h"
 #include "esp_flash_partitions.h"
 #include "bootloader_flash.h"
 #include "bootloader_flash.h"
 #include "bootloader_common.h"
 #include "bootloader_common.h"
+#include "bootloader_utility.h"
 #include "soc/gpio_periph.h"
 #include "soc/gpio_periph.h"
 #include "soc/rtc.h"
 #include "soc/rtc.h"
 #include "soc/efuse_reg.h"
 #include "soc/efuse_reg.h"
@@ -181,22 +182,7 @@ esp_err_t bootloader_common_get_sha256_of_partition (uint32_t address, uint32_t
         size = data.image_len;
         size = data.image_len;
     }
     }
     // If image is type by data then hash is calculated for entire image.
     // If image is type by data then hash is calculated for entire image.
-    const void *partition_bin = bootloader_mmap(address, size);
-    if (partition_bin == NULL) {
-        ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", address, size);
-        return ESP_FAIL;
-    }
-    bootloader_sha256_handle_t sha_handle = bootloader_sha256_start();
-    if (sha_handle == NULL) {
-        bootloader_munmap(partition_bin);
-        return ESP_ERR_NO_MEM;
-    }
-    bootloader_sha256_data(sha_handle, partition_bin, size);
-    bootloader_sha256_finish(sha_handle, out_sha_256);
-
-    bootloader_munmap(partition_bin);
-
-    return ESP_OK;
+    return bootloader_sha256_flash_contents(address, size, out_sha_256);
 }
 }
 
 
 int bootloader_common_select_otadata(const esp_ota_select_entry_t *two_otadata, bool *valid_two_otadata, bool max)
 int bootloader_common_select_otadata(const esp_ota_select_entry_t *two_otadata, bool *valid_two_otadata, bool max)

+ 35 - 0
components/bootloader_support/src/bootloader_utility.c

@@ -719,3 +719,38 @@ esp_err_t bootloader_sha256_hex_to_str(char *out_str, const uint8_t *in_array_he
     }
     }
     return ESP_OK;
     return ESP_OK;
 }
 }
+
+esp_err_t bootloader_sha256_flash_contents(uint32_t flash_offset, uint32_t len, uint8_t *digest)
+{
+
+    if (digest == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    /* Handling firmware images larger than MMU capacity */
+    uint32_t mmu_free_pages_count = bootloader_mmap_get_free_pages();
+    bootloader_sha256_handle_t sha_handle = NULL;
+
+    sha_handle = bootloader_sha256_start();
+    if (sha_handle == NULL) {
+        return ESP_ERR_NO_MEM;
+    }
+
+    while (len > 0) {
+        uint32_t mmu_page_offset = ((flash_offset & MMAP_ALIGNED_MASK) != 0) ? 1 : 0; /* Skip 1st MMU Page if it is already populated */
+        uint32_t partial_image_len = MIN(len, ((mmu_free_pages_count - mmu_page_offset) * SPI_FLASH_MMU_PAGE_SIZE)); /* Read the image that fits in the free MMU pages */
+
+        const void * image = bootloader_mmap(flash_offset, partial_image_len);
+        if (image == NULL) {
+            bootloader_sha256_finish(sha_handle, NULL);
+            return ESP_FAIL;
+        }
+        bootloader_sha256_data(sha_handle, image, partial_image_len);
+        bootloader_munmap(image);
+
+        flash_offset += partial_image_len;
+        len -= partial_image_len;
+    }
+    bootloader_sha256_finish(sha_handle, digest);
+    return ESP_OK;
+}

+ 1 - 1
components/bootloader_support/src/esp32/bootloader_sha.c

@@ -27,7 +27,7 @@ static const size_t BLOCK_WORDS = (64 / sizeof(uint32_t));
 // Words in final SHA256 digest
 // Words in final SHA256 digest
 static const size_t DIGEST_WORDS = (32 / sizeof(uint32_t));
 static const size_t DIGEST_WORDS = (32 / sizeof(uint32_t));
 
 
-bootloader_sha256_handle_t bootloader_sha256_start()
+bootloader_sha256_handle_t bootloader_sha256_start(void)
 {
 {
     // Enable SHA hardware
     // Enable SHA hardware
     ets_sha_enable();
     ets_sha_enable();

+ 2 - 1
components/bootloader_support/src/idf/bootloader_sha.c

@@ -18,7 +18,7 @@
 #include <sys/param.h>
 #include <sys/param.h>
 #include <mbedtls/sha256.h>
 #include <mbedtls/sha256.h>
 
 
-bootloader_sha256_handle_t bootloader_sha256_start()
+bootloader_sha256_handle_t bootloader_sha256_start(void)
 {
 {
     mbedtls_sha256_context *ctx = (mbedtls_sha256_context *)malloc(sizeof(mbedtls_sha256_context));
     mbedtls_sha256_context *ctx = (mbedtls_sha256_context *)malloc(sizeof(mbedtls_sha256_context));
     if (!ctx) {
     if (!ctx) {
@@ -50,4 +50,5 @@ void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest
     }
     }
     mbedtls_sha256_free(ctx);
     mbedtls_sha256_free(ctx);
     free(handle);
     free(handle);
+    handle = NULL;
 }
 }

+ 25 - 0
components/spi_flash/test/test_partitions.c

@@ -24,6 +24,7 @@
 #include <test_utils.h>
 #include <test_utils.h>
 #include <esp_partition.h>
 #include <esp_partition.h>
 #include <esp_attr.h>
 #include <esp_attr.h>
+#include "esp_log.h"
 
 
 TEST_CASE("Test erase partition", "[spi_flash][esp_flash]")
 TEST_CASE("Test erase partition", "[spi_flash][esp_flash]")
 {
 {
@@ -66,3 +67,27 @@ TEST_CASE("Test erase partition", "[spi_flash][esp_flash]")
         }
         }
     }
     }
 }
 }
+
+TEST_CASE("Test esp_partition_get_sha256() that it can handle a big partition", "[spi_flash]")
+{
+    esp_partition_t partition;
+    const void *ptr;
+    spi_flash_mmap_handle_t handle;
+
+    uint8_t sha256[32] = { 0 };
+    size_t size_flash_chip = spi_flash_get_chip_size();
+
+    printf("size_flash_chip = %d bytes\n", size_flash_chip);
+
+    ESP_ERROR_CHECK(spi_flash_mmap(0x00000000, size_flash_chip * 7 / 10, SPI_FLASH_MMAP_DATA, &ptr, &handle));
+    TEST_ASSERT_NOT_NULL(ptr);
+
+    partition.address   = 0x00000000;
+    partition.size      = size_flash_chip;
+    partition.type      = ESP_PARTITION_TYPE_DATA;
+
+    ESP_ERROR_CHECK(esp_partition_get_sha256(&partition, sha256));
+    ESP_LOG_BUFFER_HEX("sha", sha256, sizeof(sha256));
+
+    spi_flash_munmap(handle);
+}