From e2479b46f75c29e03f6b8226a29faaa1c1a4766c Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Mon, 24 Apr 2017 16:21:27 +1000 Subject: [PATCH] secure boot: Fix bootloader image verification failure * Failure prevented secure boot from enabling. * Also adds unit test cases for esp_image_basic_verify() Ref https://esp32.com/viewtopic.php?f=2&t=1602 TW11878 --- .../bootloader/src/main/bootloader_config.h | 9 +---- .../bootloader/src/main/bootloader_start.c | 8 ++-- .../bootloader_support/src/esp_image_format.c | 25 ++++++++----- .../bootloader_support/test/component.mk | 4 ++ .../test/test_verify_image.c | 37 +++++++++++++++++++ components/soc/esp32/include/soc/soc.h | 10 +++++ 6 files changed, 71 insertions(+), 22 deletions(-) create mode 100644 components/bootloader_support/test/component.mk create mode 100644 components/bootloader_support/test/test_verify_image.c diff --git a/components/bootloader/src/main/bootloader_config.h b/components/bootloader/src/main/bootloader_config.h index 6b37899ac..f7379b2e4 100644 --- a/components/bootloader/src/main/bootloader_config.h +++ b/components/bootloader/src/main/bootloader_config.h @@ -22,16 +22,9 @@ extern "C" #endif #include "esp_flash_data_types.h" +#include "soc/soc.h" #define SPI_SEC_SIZE 0x1000 -#define IROM_LOW 0x400D0000 -#define IROM_HIGH 0x40400000 -#define DROM_LOW 0x3F400000 -#define DROM_HIGH 0x3F800000 -#define RTC_IRAM_LOW 0x400C0000 -#define RTC_IRAM_HIGH 0x400C2000 -#define RTC_DATA_LOW 0x50000000 -#define RTC_DATA_HIGH 0x50002000 #define SPI_ERROR_LOG "spi flash error" diff --git a/components/bootloader/src/main/bootloader_start.c b/components/bootloader/src/main/bootloader_start.c index aa30ad4c7..1fe65d2ca 100644 --- a/components/bootloader/src/main/bootloader_start.c +++ b/components/bootloader/src/main/bootloader_start.c @@ -475,7 +475,7 @@ static void unpack_load_app(const esp_partition_pos_t* partition) // TODO: actually check md5 } - if (address >= DROM_LOW && address < DROM_HIGH) { + if (address >= SOC_DROM_LOW && address < SOC_DROM_HIGH) { ESP_LOGD(TAG, "found drom segment, map from %08x to %08x", data_offs, segment_header.load_addr); drom_addr = data_offs; @@ -485,7 +485,7 @@ static void unpack_load_app(const esp_partition_pos_t* partition) map = true; } - if (address >= IROM_LOW && address < IROM_HIGH) { + if (address >= SOC_IROM_LOW && address < SOC_IROM_HIGH) { ESP_LOGD(TAG, "found irom segment, map from %08x to %08x", data_offs, segment_header.load_addr); irom_addr = data_offs; @@ -495,12 +495,12 @@ static void unpack_load_app(const esp_partition_pos_t* partition) map = true; } - if (!load_rtc_memory && address >= RTC_IRAM_LOW && address < RTC_IRAM_HIGH) { + if (!load_rtc_memory && address >= SOC_RTC_IRAM_LOW && address < SOC_RTC_IRAM_HIGH) { ESP_LOGD(TAG, "Skipping RTC code segment at %08x\n", data_offs); load = false; } - if (!load_rtc_memory && address >= RTC_DATA_LOW && address < RTC_DATA_HIGH) { + if (!load_rtc_memory && address >= SOC_RTC_DATA_LOW && address < SOC_RTC_DATA_HIGH) { ESP_LOGD(TAG, "Skipping RTC data segment at %08x\n", data_offs); load = false; } diff --git a/components/bootloader_support/src/esp_image_format.c b/components/bootloader_support/src/esp_image_format.c index 942ffd4bf..e6c5f899c 100644 --- a/components/bootloader_support/src/esp_image_format.c +++ b/components/bootloader_support/src/esp_image_format.c @@ -108,16 +108,6 @@ esp_err_t esp_image_basic_verify(uint32_t src_addr, bool log_errors, uint32_t *p *p_length = 0; } - if (src_addr % SPI_FLASH_MMU_PAGE_SIZE != 0) { - /* Image must start on a 64KB boundary - - (This is not a technical limitation, only the flash mapped regions need to be 64KB aligned. But the most - consistent way to do this is to have all the offsets internal to the image correctly 64KB aligned, and then - start the image on a 64KB boundary also.) - */ - return ESP_ERR_INVALID_ARG; - } - err = esp_image_load_header(src_addr, log_errors, &image_header); if (err != ESP_OK) { return err; @@ -133,6 +123,21 @@ esp_err_t esp_image_basic_verify(uint32_t src_addr, bool log_errors, uint32_t *p return err; } + uint32_t load_addr = segment_header.load_addr; + bool map_segment = (load_addr >= SOC_DROM_LOW && load_addr < SOC_DROM_HIGH) + || (load_addr >= SOC_IROM_LOW && load_addr < SOC_IROM_HIGH); + + + /* Check that flash cache mapped segment aligns correctly from flash it's mapped address, + relative to the 64KB page mapping size. + */ + ESP_LOGV(TAG, "segment %d map_segment %d segment_data_offs 0x%x load_addr 0x%x", + i, map_segment, segment_data_offs, load_addr); + if (map_segment && ((segment_data_offs % SPI_FLASH_MMU_PAGE_SIZE) != (load_addr % SPI_FLASH_MMU_PAGE_SIZE))) { + ESP_LOGE(TAG, "Segment %d has load address 0x%08x, conflict with segment data at 0x%08x", + i, load_addr, segment_data_offs); + } + for (int i = 0; i < segment_header.data_len; i += sizeof(buf)) { err = bootloader_flash_read(segment_data_offs + i, buf, sizeof(buf), true); if (err != ESP_OK) { diff --git a/components/bootloader_support/test/component.mk b/components/bootloader_support/test/component.mk new file mode 100644 index 000000000..8c6eb513e --- /dev/null +++ b/components/bootloader_support/test/component.mk @@ -0,0 +1,4 @@ +# +#Component Makefile +# +COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive diff --git a/components/bootloader_support/test/test_verify_image.c b/components/bootloader_support/test/test_verify_image.c new file mode 100644 index 000000000..0c6d1ac5b --- /dev/null +++ b/components/bootloader_support/test/test_verify_image.c @@ -0,0 +1,37 @@ +/* + * Tests for bootloader_support esp_image_basic_verify() + */ + +#include +#include +#include "rom/ets_sys.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "freertos/queue.h" +#include "freertos/xtensa_api.h" +#include "unity.h" + +#include "esp_partition.h" +#include "esp_ota_ops.h" +#include "esp_image_format.h" + +TEST_CASE("Verify bootloader image in flash", "[bootloader_support]") +{ + uint32_t image_len = 0; + TEST_ASSERT_EQUAL_HEX(ESP_OK, esp_image_basic_verify(0x1000, true, &image_len)); + TEST_ASSERT_NOT_EQUAL(0, image_len); +} + +TEST_CASE("Verify unit test app image", "[bootloader_support]") +{ + uint32_t image_len = 0; + const esp_partition_t *running = esp_ota_get_running_partition(); + TEST_ASSERT_NOT_EQUAL(NULL, running); + + TEST_ASSERT_EQUAL_HEX(ESP_OK, esp_image_basic_verify(running->address, true, &image_len)); + TEST_ASSERT_NOT_EQUAL(0, image_len); + TEST_ASSERT_TRUE(image_len <= running->size); +} + diff --git a/components/soc/esp32/include/soc/soc.h b/components/soc/esp32/include/soc/soc.h index fe6acee2a..b42a77690 100644 --- a/components/soc/esp32/include/soc/soc.h +++ b/components/soc/esp32/include/soc/soc.h @@ -149,6 +149,16 @@ #define TICKS_PER_US_ROM 26 // CPU is 80MHz //}} +/* Overall memory map */ +#define SOC_IROM_LOW 0x400D0000 +#define SOC_IROM_HIGH 0x40400000 +#define SOC_DROM_LOW 0x3F400000 +#define SOC_DROM_HIGH 0x3F800000 +#define SOC_RTC_IRAM_LOW 0x400C0000 +#define SOC_RTC_IRAM_HIGH 0x400C2000 +#define SOC_RTC_DATA_LOW 0x50000000 +#define SOC_RTC_DATA_HIGH 0x50002000 + #define DR_REG_DPORT_BASE 0x3ff00000 #define DR_REG_RSA_BASE 0x3ff02000 #define DR_REG_SHA_BASE 0x3ff03000