From 37e28522c218ed4747a404b2e14d7586d53ea4d7 Mon Sep 17 00:00:00 2001 From: Mahavir Jain Date: Mon, 12 May 2025 10:53:11 +0530 Subject: [PATCH 1/2] fix: secure OTA without secure boot issue for MMU page size configurable SoCs For secure app verification during OTA update case, the image was getting memory mapped twice and hence the failure in verification. Modified from memory mapped flash read to SPI flash read approach for the MMU page size from image header. Regression from 07318a49874d9b3be7fd1b81aa6657050497c511 Closes https://github.com/espressif/esp-idf/issues/15936 --- .../bootloader_support/src/esp_image_format.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/components/bootloader_support/src/esp_image_format.c b/components/bootloader_support/src/esp_image_format.c index 509e852d4e..d0644cdcb3 100644 --- a/components/bootloader_support/src/esp_image_format.c +++ b/components/bootloader_support/src/esp_image_format.c @@ -796,20 +796,27 @@ static esp_err_t verify_segment_header(int index, const esp_image_segment_header bool map_segment = should_map(load_addr); #if SOC_MMU_PAGE_SIZE_CONFIGURABLE + esp_err_t err = ESP_FAIL; + /* ESP APP descriptor is present in the DROM segment #0 */ if (index == 0 && !is_bootloader(metadata->start_addr)) { - const esp_app_desc_t *app_desc = (const esp_app_desc_t *)bootloader_mmap(segment_data_offs, sizeof(esp_app_desc_t)); - if (!app_desc || app_desc->magic_word != ESP_APP_DESC_MAGIC_WORD) { + uint32_t mmu_page_size = 0, magic_word = 0; + const uint32_t mmu_page_size_offset = segment_data_offs + offsetof(esp_app_desc_t, mmu_page_size); + CHECK_ERR(bootloader_flash_read(segment_data_offs, &magic_word, sizeof(uint32_t), true)); + CHECK_ERR(bootloader_flash_read(mmu_page_size_offset, &mmu_page_size, sizeof(uint32_t), true)); + // Extract only the lowest byte from mmu_page_size (as per image format) + mmu_page_size &= 0xFF; + + if (magic_word != ESP_APP_DESC_MAGIC_WORD) { ESP_LOGE(TAG, "Failed to fetch app description header!"); return ESP_FAIL; } // Convert from log base 2 number to actual size while handling legacy image case (value 0) - metadata->mmu_page_size = (app_desc->mmu_page_size > 0) ? (1UL << app_desc->mmu_page_size) : SPI_FLASH_MMU_PAGE_SIZE; + metadata->mmu_page_size = (mmu_page_size > 0) ? (1UL << mmu_page_size) : SPI_FLASH_MMU_PAGE_SIZE; if (metadata->mmu_page_size != SPI_FLASH_MMU_PAGE_SIZE) { ESP_LOGI(TAG, "MMU page size mismatch, configured: 0x%x, found: 0x%"PRIx32, SPI_FLASH_MMU_PAGE_SIZE, metadata->mmu_page_size); } - bootloader_munmap(app_desc); } else if (index == 0 && is_bootloader(metadata->start_addr)) { // Bootloader always uses the default MMU page size metadata->mmu_page_size = SPI_FLASH_MMU_PAGE_SIZE; @@ -836,6 +843,10 @@ static esp_err_t verify_segment_header(int index, const esp_image_segment_header } return ESP_OK; +#if SOC_MMU_PAGE_SIZE_CONFIGURABLE +err: + return err; +#endif } static bool should_map(uint32_t load_addr) From 45831351fa546a9a3560ff65f43975ab53e59f3e Mon Sep 17 00:00:00 2001 From: Mahavir Jain Date: Mon, 12 May 2025 11:02:46 +0530 Subject: [PATCH 2/2] test: add secure image verification case for C6/H2 --- .../system/mmu_page_size/main/CMakeLists.txt | 2 +- .../system/mmu_page_size/main/main.c | 23 ++++++++++- .../mmu_page_size/pytest_mmu_page_size.py | 2 + .../system/mmu_page_size/sdkconfig.defaults | 3 ++ .../mmu_page_size/secure_boot_signing_key.pem | 39 +++++++++++++++++++ 5 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 tools/test_apps/system/mmu_page_size/secure_boot_signing_key.pem diff --git a/tools/test_apps/system/mmu_page_size/main/CMakeLists.txt b/tools/test_apps/system/mmu_page_size/main/CMakeLists.txt index 06087b89d5..3aa21a2cd1 100644 --- a/tools/test_apps/system/mmu_page_size/main/CMakeLists.txt +++ b/tools/test_apps/system/mmu_page_size/main/CMakeLists.txt @@ -1,2 +1,2 @@ idf_component_register(SRCS "main.c" - PRIV_REQUIRES unity esp_partition) + PRIV_REQUIRES unity esp_partition bootloader_support) diff --git a/tools/test_apps/system/mmu_page_size/main/main.c b/tools/test_apps/system/mmu_page_size/main/main.c index a820c55c54..e3ca07859e 100644 --- a/tools/test_apps/system/mmu_page_size/main/main.c +++ b/tools/test_apps/system/mmu_page_size/main/main.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,6 +10,7 @@ #include "unity.h" #include "esp_partition.h" +#include "esp_image_format.h" #define SZ 4096 @@ -37,4 +38,24 @@ void app_main(void) esp_partition_munmap(handle1); printf("Partition test done\n"); + + // Get the factory partition + partition = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL); + if (partition == NULL) { + printf("Failed to find factory partition\n"); + return; + } + + esp_image_metadata_t data; + const esp_partition_pos_t part_pos = { + .offset = partition->address, + .size = partition->size, + }; + + if (esp_image_verify(ESP_IMAGE_VERIFY, &part_pos, &data) != ESP_OK) { + printf("Failed to verify image\n"); + } else { + printf("Image verified successfully\n"); + } + return; } diff --git a/tools/test_apps/system/mmu_page_size/pytest_mmu_page_size.py b/tools/test_apps/system/mmu_page_size/pytest_mmu_page_size.py index 3ccaf74aca..efe62c80d2 100644 --- a/tools/test_apps/system/mmu_page_size/pytest_mmu_page_size.py +++ b/tools/test_apps/system/mmu_page_size/pytest_mmu_page_size.py @@ -28,6 +28,7 @@ def test_app_mmu_page_size_32k_and_bootloader_mmu_page_size_64k(dut: Dut, app_do dut.expect('MMU page size mismatch') dut.expect('App is running') dut.expect('Partition test done') + dut.expect('Image verified successfully', timeout=30) @pytest.mark.generic @@ -49,3 +50,4 @@ def test_app_mmu_page_size_64k_and_bootloader_mmu_page_size_32k(dut: Dut, app_do dut.expect('MMU page size mismatch') dut.expect('App is running') dut.expect('Partition test done') + dut.expect('Image verified successfully', timeout=30) diff --git a/tools/test_apps/system/mmu_page_size/sdkconfig.defaults b/tools/test_apps/system/mmu_page_size/sdkconfig.defaults index 4b0421e1ab..3042a908d6 100644 --- a/tools/test_apps/system/mmu_page_size/sdkconfig.defaults +++ b/tools/test_apps/system/mmu_page_size/sdkconfig.defaults @@ -1 +1,4 @@ CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_OFFSET=0xa000 +CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT=y +CONFIG_ESP_MAIN_TASK_STACK_SIZE=4096 diff --git a/tools/test_apps/system/mmu_page_size/secure_boot_signing_key.pem b/tools/test_apps/system/mmu_page_size/secure_boot_signing_key.pem new file mode 100644 index 0000000000..da5fe069c0 --- /dev/null +++ b/tools/test_apps/system/mmu_page_size/secure_boot_signing_key.pem @@ -0,0 +1,39 @@ +-----BEGIN RSA PRIVATE KEY----- +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 +-----END RSA PRIVATE KEY-----