From 035783039bec3bcd542d002bf3ee370a3047b6ed Mon Sep 17 00:00:00 2001 From: KonstantinKondrashov Date: Tue, 7 Jul 2020 21:56:58 +0800 Subject: [PATCH 1/2] bootloader_support: Fix bootloader_common_get_sha256_of_partition, can handle a long image Closes: IDFGH-3594 --- .../src/bootloader_common.c | 18 ++------------ components/spi_flash/test/test_partitions.c | 24 +++++++++++++++++++ 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/components/bootloader_support/src/bootloader_common.c b/components/bootloader_support/src/bootloader_common.c index 61d89f67e..3ab2af792 100644 --- a/components/bootloader_support/src/bootloader_common.c +++ b/components/bootloader_support/src/bootloader_common.c @@ -26,6 +26,7 @@ #include "esp_flash_partitions.h" #include "bootloader_flash.h" #include "bootloader_common.h" +#include "bootloader_utility.h" #include "soc/gpio_periph.h" #include "soc/efuse_reg.h" #include "soc/rtc.h" @@ -186,22 +187,7 @@ esp_err_t bootloader_common_get_sha256_of_partition (uint32_t address, uint32_t size = data.image_len; } // 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) diff --git a/components/spi_flash/test/test_partitions.c b/components/spi_flash/test/test_partitions.c index d859d3dd2..aa065d794 100644 --- a/components/spi_flash/test/test_partitions.c +++ b/components/spi_flash/test/test_partitions.c @@ -66,3 +66,27 @@ TEST_CASE("Test erase partition", "[spi_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); +} From 9ce137139be58e87eb0ab86c808ed2a6604bb3bf Mon Sep 17 00:00:00 2001 From: KonstantinKondrashov Date: Thu, 6 Aug 2020 15:22:26 +0800 Subject: [PATCH 2/2] bootloader: Adds bootloader_sha256_flash_contents() --- .../include_bootloader/bootloader_flash.h | 3 +- .../include_bootloader/bootloader_sha.h | 2 +- .../include_bootloader/bootloader_utility.h | 14 ++++++++ .../src/bootloader_common.c | 1 + .../bootloader_support/src/bootloader_sha.c | 5 +-- .../src/bootloader_utility.c | 36 +++++++++++++++++++ components/spi_flash/test/test_partitions.c | 1 + 7 files changed, 58 insertions(+), 4 deletions(-) diff --git a/components/bootloader_support/include_bootloader/bootloader_flash.h b/components/bootloader_support/include_bootloader/bootloader_flash.h index 6ac724646..705fa44e9 100644 --- a/components/bootloader_support/include_bootloader/bootloader_flash.h +++ b/components/bootloader_support/include_bootloader/bootloader_flash.h @@ -22,6 +22,7 @@ #define FLASH_SECTOR_SIZE 0x1000 #define FLASH_BLOCK_SIZE 0x10000 +#define MMAP_ALIGNED_MASK 0x0000FFFF /* Provide a Flash API for bootloader_support code, that can be used from bootloader or app code. @@ -35,7 +36,7 @@ * * @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 diff --git a/components/bootloader_support/include_bootloader/bootloader_sha.h b/components/bootloader_support/include_bootloader/bootloader_sha.h index 079a45791..48f65feed 100644 --- a/components/bootloader_support/include_bootloader/bootloader_sha.h +++ b/components/bootloader_support/include_bootloader/bootloader_sha.h @@ -26,7 +26,7 @@ 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); diff --git a/components/bootloader_support/include_bootloader/bootloader_utility.h b/components/bootloader_support/include_bootloader/bootloader_utility.h index 31213a016..227a328a8 100644 --- a/components/bootloader_support/include_bootloader/bootloader_utility.h +++ b/components/bootloader_support/include_bootloader/bootloader_utility.h @@ -62,3 +62,17 @@ __attribute__((noreturn)) void bootloader_utility_load_boot_image(const bootload * It is not recommended to call this function from an app (if called, the app will abort). */ __attribute__((noreturn)) void bootloader_reset(void); + +/** @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); \ No newline at end of file diff --git a/components/bootloader_support/src/bootloader_common.c b/components/bootloader_support/src/bootloader_common.c index 3ab2af792..3b5a0497e 100644 --- a/components/bootloader_support/src/bootloader_common.c +++ b/components/bootloader_support/src/bootloader_common.c @@ -26,6 +26,7 @@ #include "esp_flash_partitions.h" #include "bootloader_flash.h" #include "bootloader_common.h" +#include "bootloader_config.h" #include "bootloader_utility.h" #include "soc/gpio_periph.h" #include "soc/efuse_reg.h" diff --git a/components/bootloader_support/src/bootloader_sha.c b/components/bootloader_support/src/bootloader_sha.c index 1f7c1b493..aed31396b 100644 --- a/components/bootloader_support/src/bootloader_sha.c +++ b/components/bootloader_support/src/bootloader_sha.c @@ -21,7 +21,7 @@ // App version is a wrapper around mbedTLS SHA API #include -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)); if (!ctx) { @@ -53,6 +53,7 @@ void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest } mbedtls_sha256_free(ctx); free(handle); + handle = NULL; } #else // Bootloader version @@ -70,7 +71,7 @@ static const size_t BLOCK_WORDS = (64/sizeof(uint32_t)); // Words in final SHA256 digest 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 ets_sha_enable(); diff --git a/components/bootloader_support/src/bootloader_utility.c b/components/bootloader_support/src/bootloader_utility.c index 99bae9455..e5c6dad5b 100644 --- a/components/bootloader_support/src/bootloader_utility.c +++ b/components/bootloader_support/src/bootloader_utility.c @@ -703,3 +703,39 @@ void bootloader_reset(void) abort(); /* This function should really not be called from application code */ #endif } + + +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; +} \ No newline at end of file diff --git a/components/spi_flash/test/test_partitions.c b/components/spi_flash/test/test_partitions.c index aa065d794..d280f2625 100644 --- a/components/spi_flash/test/test_partitions.c +++ b/components/spi_flash/test/test_partitions.c @@ -24,6 +24,7 @@ #include #include #include +#include "esp_log.h" TEST_CASE("Test erase partition", "[spi_flash]") {