From 040eacf7d24284552a73075c99927de21e74825e Mon Sep 17 00:00:00 2001 From: Almir Okato Date: Thu, 24 Aug 2023 15:40:26 -0300 Subject: [PATCH] espressif: update secure boot and flash encryption Adjust secure boot and flash encryption after IDF v5.x updates. It also allows to enable secure boot on ESP32-C2. Signed-off-by: Almir Okato --- boot/espressif/hal/CMakeLists.txt | 14 +- .../hal/include/esp32c6/esp32c6.cmake | 2 +- .../hal/include/esp32h2/esp32h2.cmake | 1 + boot/espressif/hal/src/flash_encrypt.c | 179 ++++++++++++------ boot/espressif/hal/src/secure_boot.c | 35 +++- boot/espressif/main.c | 74 +++++++- boot/espressif/port/esp32c2/bootloader.conf | 10 + boot/espressif/port/esp32c3/ld/bootloader.ld | 4 +- docs/readme-espressif.md | 24 ++- 9 files changed, 256 insertions(+), 87 deletions(-) diff --git a/boot/espressif/hal/CMakeLists.txt b/boot/espressif/hal/CMakeLists.txt index 7f3d1bbb4..d248c2670 100644 --- a/boot/espressif/hal/CMakeLists.txt +++ b/boot/espressif/hal/CMakeLists.txt @@ -71,11 +71,8 @@ set(hal_srcs ${esp_hal_dir}/components/bootloader_support/src/bootloader_random_${MCUBOOT_TARGET}.c ${esp_hal_dir}/components/bootloader_support/src/bootloader_utility.c ${esp_hal_dir}/components/bootloader_support/src/esp_image_format.c - ${esp_hal_dir}/components/bootloader_support/src/secure_boot_v2/secure_boot_signatures_bootloader.c ${esp_hal_dir}/components/bootloader_support/src/${MCUBOOT_TARGET}/bootloader_soc.c ${esp_hal_dir}/components/bootloader_support/src/${MCUBOOT_TARGET}/bootloader_sha.c - ${esp_hal_dir}/components/bootloader_support/src/${MCUBOOT_TARGET}/secure_boot_secure_features.c - ${esp_hal_dir}/components/bootloader_support/src/${MCUBOOT_TARGET}/flash_encryption_secure_features.c ${esp_hal_dir}/components/hal/mpu_hal.c ${esp_hal_dir}/components/hal/efuse_hal.c ${esp_hal_dir}/components/hal/mmu_hal.c @@ -103,12 +100,23 @@ set(hal_srcs if(DEFINED CONFIG_SECURE_BOOT_V2_ENABLED) list(APPEND hal_srcs ${src_dir}/secure_boot.c + ${esp_hal_dir}/components/bootloader_support/src/secure_boot_v2/secure_boot_signatures_bootloader.c + ${esp_hal_dir}/components/bootloader_support/src/${MCUBOOT_TARGET}/secure_boot_secure_features.c + ) + list(APPEND include_dirs + ${esp_hal_dir}/components/bootloader_support/src/secure_boot_v2 ) endif() if(DEFINED CONFIG_SECURE_FLASH_ENC_ENABLED) list(APPEND hal_srcs ${src_dir}/flash_encrypt.c + ${esp_hal_dir}/components/bootloader_support/src/${MCUBOOT_TARGET}/flash_encryption_secure_features.c + ) + set_source_files_properties( + ${src_dir}/flash_encrypt.c + PROPERTIES COMPILE_FLAGS + "-Wno-unused-variable" ) endif() diff --git a/boot/espressif/hal/include/esp32c6/esp32c6.cmake b/boot/espressif/hal/include/esp32c6/esp32c6.cmake index 23b6b0091..d26c5f0dc 100644 --- a/boot/espressif/hal/include/esp32c6/esp32c6.cmake +++ b/boot/espressif/hal/include/esp32c6/esp32c6.cmake @@ -8,7 +8,7 @@ list(APPEND include_dirs list(APPEND hal_srcs ${esp_hal_dir}/components/hal/cache_hal.c - ${esp_hal_dir}/components/hal/${MCUBOOT_TARGET}/lp_timer_hal.c + ${esp_hal_dir}/components/hal/lp_timer_hal.c ${esp_hal_dir}/components/efuse/src/efuse_controller/keys/with_key_purposes/esp_efuse_api_key.c ${esp_hal_dir}/components/esp_rom/patches/esp_rom_regi2c_${MCUBOOT_TARGET}.c ) diff --git a/boot/espressif/hal/include/esp32h2/esp32h2.cmake b/boot/espressif/hal/include/esp32h2/esp32h2.cmake index 9160eaba5..d26c5f0dc 100644 --- a/boot/espressif/hal/include/esp32h2/esp32h2.cmake +++ b/boot/espressif/hal/include/esp32h2/esp32h2.cmake @@ -8,6 +8,7 @@ list(APPEND include_dirs list(APPEND hal_srcs ${esp_hal_dir}/components/hal/cache_hal.c + ${esp_hal_dir}/components/hal/lp_timer_hal.c ${esp_hal_dir}/components/efuse/src/efuse_controller/keys/with_key_purposes/esp_efuse_api_key.c ${esp_hal_dir}/components/esp_rom/patches/esp_rom_regi2c_${MCUBOOT_TARGET}.c ) diff --git a/boot/espressif/hal/src/flash_encrypt.c b/boot/espressif/hal/src/flash_encrypt.c index 222e32e2a..d064d8b7b 100644 --- a/boot/espressif/hal/src/flash_encrypt.c +++ b/boot/espressif/hal/src/flash_encrypt.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -15,7 +15,11 @@ #include "esp_efuse_table.h" #include "esp_log.h" #include "hal/wdt_hal.h" +#include "hal/efuse_hal.h" #include "soc/soc_caps.h" +#ifdef CONFIG_SOC_EFUSE_CONSISTS_OF_ONE_KEY_BLOCK +#include "soc/sensitive_reg.h" +#endif #include "esp_mcuboot_image.h" @@ -27,6 +31,8 @@ #define WR_DIS_CRYPT_CNT ESP_EFUSE_WR_DIS_SPI_BOOT_CRYPT_CNT #endif +#define FLASH_ENC_CNT_MAX (CRYPT_CNT[0]->bit_count) + /* This file implements FLASH ENCRYPTION related APIs to perform * various operations such as programming necessary flash encryption * eFuses, detect whether flash encryption is enabled (by reading eFuse) @@ -36,10 +42,9 @@ static const char *TAG = "flash_encrypt"; /* Static functions for stages of flash encryption */ -static esp_err_t initialise_flash_encryption(void); -static esp_err_t encrypt_flash_contents(uint32_t flash_crypt_cnt, bool flash_crypt_wr_dis) __attribute__((unused)); static esp_err_t encrypt_bootloader(void); static esp_err_t encrypt_primary_slot(void); +static size_t get_flash_encrypt_cnt_value(void); /** * This former inlined function must not be defined in the header file anymore. @@ -50,15 +55,14 @@ static esp_err_t encrypt_primary_slot(void); */ bool IRAM_ATTR esp_flash_encryption_enabled(void) { - uint32_t flash_crypt_cnt = 0; #ifndef CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH - flash_crypt_cnt = efuse_ll_get_flash_crypt_cnt(); + return efuse_hal_flash_encryption_enabled(); #else + uint32_t flash_crypt_cnt = 0; #if CONFIG_IDF_TARGET_ESP32 esp_efuse_read_field_blob(ESP_EFUSE_FLASH_CRYPT_CNT, &flash_crypt_cnt, ESP_EFUSE_FLASH_CRYPT_CNT[0]->bit_count); #else esp_efuse_read_field_blob(ESP_EFUSE_SPI_BOOT_CRYPT_CNT, &flash_crypt_cnt, ESP_EFUSE_SPI_BOOT_CRYPT_CNT[0]->bit_count); -#endif #endif /* __builtin_parity is in flash, so we calculate parity inline */ bool enabled = false; @@ -69,34 +73,84 @@ bool IRAM_ATTR esp_flash_encryption_enabled(void) flash_crypt_cnt >>= 1; } return enabled; +#endif // CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH } -esp_err_t esp_flash_encrypt_check_and_update(void) +static size_t get_flash_encrypt_cnt_value(void) { size_t flash_crypt_cnt = 0; esp_efuse_read_field_cnt(CRYPT_CNT, &flash_crypt_cnt); - bool flash_crypt_wr_dis = esp_efuse_read_field_bit(WR_DIS_CRYPT_CNT); + return flash_crypt_cnt; +} + +bool esp_flash_encrypt_initialized_once(void) +{ + return get_flash_encrypt_cnt_value() != 0; +} + +bool esp_flash_encrypt_is_write_protected(bool print_error) +{ + if (esp_efuse_read_field_bit(WR_DIS_CRYPT_CNT)) { + if (print_error) { + ESP_LOGE(TAG, "Flash Encryption cannot be enabled (CRYPT_CNT (%d) is write protected)", get_flash_encrypt_cnt_value()); + } + return true; + } + return false; +} + +bool esp_flash_encrypt_state(void) +{ + size_t flash_crypt_cnt = get_flash_encrypt_cnt_value(); + bool flash_crypt_wr_dis = esp_flash_encrypt_is_write_protected(false); ESP_LOGV(TAG, "CRYPT_CNT %d, write protection %d", flash_crypt_cnt, flash_crypt_wr_dis); if (flash_crypt_cnt % 2 == 1) { /* Flash is already encrypted */ - int left = (CRYPT_CNT[0]->bit_count - flash_crypt_cnt) / 2; + int left = (FLASH_ENC_CNT_MAX - flash_crypt_cnt) / 2; if (flash_crypt_wr_dis) { left = 0; /* can't update FLASH_CRYPT_CNT, no more flashes */ } ESP_LOGI(TAG, "flash encryption is enabled (%d plaintext flashes left)", left); - return ESP_OK; - } else { + return true; + } + return false; +} + +esp_err_t esp_flash_encrypt_check_and_update(void) +{ + bool flash_encryption_enabled = esp_flash_encrypt_state(); + if (!flash_encryption_enabled) { #ifndef CONFIG_SECURE_FLASH_REQUIRE_ALREADY_ENABLED - /* Flash is not encrypted, so encrypt it! */ - return encrypt_flash_contents(flash_crypt_cnt, flash_crypt_wr_dis); + if (esp_flash_encrypt_is_write_protected(true)) { + return ESP_FAIL; + } + + esp_err_t err = esp_flash_encrypt_init(); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Initialization of Flash encryption key failed (%d)", err); + return err; + } + + err = esp_flash_encrypt_contents(); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Encryption flash contents failed (%d)", err); + return err; + } + + err = esp_flash_encrypt_enable(); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Enabling of Flash encryption failed (%d)", err); + return err; + } #else ESP_LOGE(TAG, "flash encryption is not enabled, and SECURE_FLASH_REQUIRE_ALREADY_ENABLED " "is set, refusing to boot."); return ESP_ERR_INVALID_STATE; #endif // CONFIG_SECURE_FLASH_REQUIRE_ALREADY_ENABLED } + return ESP_OK; } static esp_err_t check_and_generate_encryption_keys(void) @@ -126,11 +180,19 @@ static esp_err_t check_and_generate_encryption_keys(void) ESP_LOGE(TAG, "XTS_AES_128_KEY is already in use, XTS_AES_256_KEY_1/2 can not be used"); return ESP_ERR_INVALID_STATE; } +#else +#ifdef CONFIG_SECURE_FLASH_ENCRYPTION_AES128_DERIVED + enum { BLOCKS_NEEDED = 1 }; + esp_efuse_purpose_t purposes[BLOCKS_NEEDED] = { + ESP_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY_DERIVED_FROM_128_EFUSE_BITS, + }; + key_size = 16; #else enum { BLOCKS_NEEDED = 1 }; esp_efuse_purpose_t purposes[BLOCKS_NEEDED] = { ESP_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY, }; +#endif // CONFIG_SECURE_FLASH_ENCRYPTION_AES128_DERIVED #endif // CONFIG_SECURE_FLASH_ENCRYPTION_AES256 #endif // CONFIG_IDF_TARGET_ESP32 @@ -181,8 +243,14 @@ static esp_err_t check_and_generate_encryption_keys(void) return ESP_OK; } -static esp_err_t initialise_flash_encryption(void) +esp_err_t esp_flash_encrypt_init(void) { + if (esp_flash_encryption_enabled() || esp_flash_encrypt_initialized_once()) { + return ESP_OK; + } + + /* Very first flash encryption pass: generate keys, etc. */ + esp_efuse_batch_write_begin(); /* Batch all efuse writes at the end of this function */ /* Before first flash encryption pass, need to initialise key & crypto config */ @@ -198,26 +266,6 @@ static esp_err_t initialise_flash_encryption(void) return err; } -#if defined(SOC_SUPPORTS_SECURE_DL_MODE) && defined(CONFIG_SECURE_ENABLE_SECURE_ROM_DL_MODE) - ESP_LOGI(TAG, "Enabling Secure Download mode..."); - err = esp_efuse_enable_rom_secure_download_mode(); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Could not enable Secure Download mode..."); - esp_efuse_batch_write_cancel(); - return err; - } -#elif CONFIG_SECURE_DISABLE_ROM_DL_MODE - ESP_LOGI(TAG, "Disable ROM Download mode..."); - err = esp_efuse_disable_rom_download_mode(); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Could not disable ROM Download mode..."); - esp_efuse_batch_write_cancel(); - return err; - } -#else - ESP_LOGW(TAG, "UART ROM Download mode kept enabled - SECURITY COMPROMISED"); -#endif - err = esp_efuse_batch_write_commit(); if (err != ESP_OK) { ESP_LOGE(TAG, "Error programming security eFuses (err=0x%x).", err); @@ -228,24 +276,13 @@ static esp_err_t initialise_flash_encryption(void) } /* Encrypt all flash data that should be encrypted */ -static esp_err_t encrypt_flash_contents(uint32_t flash_crypt_cnt, bool flash_crypt_wr_dis) +esp_err_t esp_flash_encrypt_contents(void) { esp_err_t err; - /* If all flash_crypt_cnt bits are burned or write-disabled, the - device can't re-encrypt itself. */ - if (flash_crypt_wr_dis || flash_crypt_cnt == CRYPT_CNT[0]->bit_count) { - ESP_LOGE(TAG, "Cannot re-encrypt data CRYPT_CNT %d write disabled %d", flash_crypt_cnt, flash_crypt_wr_dis); - return ESP_FAIL; - } - - if (flash_crypt_cnt == 0) { - /* Very first flash of encrypted data: generate keys, etc. */ - err = initialise_flash_encryption(); - if (err != ESP_OK) { - return err; - } - } +#ifdef CONFIG_SOC_EFUSE_CONSISTS_OF_ONE_KEY_BLOCK + REG_WRITE(SENSITIVE_XTS_AES_KEY_UPDATE_REG, 1); +#endif err = encrypt_bootloader(); if (err != ESP_OK) { @@ -292,20 +329,48 @@ static esp_err_t encrypt_flash_contents(uint32_t flash_crypt_cnt, bool flash_cry } #endif + ESP_LOGI(TAG, "Flash encryption completed"); + + return ESP_OK; +} + +esp_err_t esp_flash_encrypt_enable(void) +{ + esp_err_t err = ESP_OK; + if (!esp_flash_encryption_enabled()) { + + if (esp_flash_encrypt_is_write_protected(true)) { + return ESP_FAIL; + } + + size_t flash_crypt_cnt = get_flash_encrypt_cnt_value(); + #ifdef CONFIG_SECURE_FLASH_ENCRYPTION_MODE_RELEASE - // Go straight to max, permanently enabled - ESP_LOGI(TAG, "Setting CRYPT_CNT for permanent encryption"); - size_t new_flash_crypt_cnt = CRYPT_CNT[0]->bit_count - flash_crypt_cnt; + // Go straight to max, permanently enabled + ESP_LOGI(TAG, "Setting CRYPT_CNT for permanent encryption"); + size_t new_flash_crypt_cnt = FLASH_ENC_CNT_MAX - flash_crypt_cnt; #else - /* Set least significant 0-bit in flash_crypt_cnt */ - size_t new_flash_crypt_cnt = 1; + /* Set least significant 0-bit in flash_crypt_cnt */ + size_t new_flash_crypt_cnt = 1; +#endif + ESP_LOGD(TAG, "CRYPT_CNT %d -> %d", flash_crypt_cnt, new_flash_crypt_cnt); + err = esp_efuse_write_field_cnt(CRYPT_CNT, new_flash_crypt_cnt); + +#if defined(CONFIG_SECURE_FLASH_ENCRYPTION_MODE_RELEASE) && defined(CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES_128_DERIVED) + // For AES128_DERIVED, FE key is 16 bytes and XTS_KEY_LENGTH_256 is 0. + // It is important to protect XTS_KEY_LENGTH_256 from further changing it to 1. Set write protection for this bit. + // Burning WR_DIS_CRYPT_CNT, blocks further changing of eFuses: DOWNLOAD_DIS_MANUAL_ENCRYPT, SPI_BOOT_CRYPT_CNT, [XTS_KEY_LENGTH_256], SECURE_BOOT_EN. + esp_efuse_write_field_bit(WR_DIS_CRYPT_CNT); #endif - ESP_LOGD(TAG, "CRYPT_CNT %d -> %d", flash_crypt_cnt, new_flash_crypt_cnt); - err = esp_efuse_write_field_cnt(CRYPT_CNT, new_flash_crypt_cnt); + } ESP_LOGI(TAG, "Flash encryption completed"); - return ESP_OK; +#ifdef CONFIG_EFUSE_VIRTUAL + ESP_LOGW(TAG, "Flash encryption not really completed. Must disable virtual efuses"); +#endif + + return err; } static esp_err_t encrypt_bootloader(void) diff --git a/boot/espressif/hal/src/secure_boot.c b/boot/espressif/hal/src/secure_boot.c index f724f0e88..8ad29ae7c 100644 --- a/boot/espressif/hal/src/secure_boot.c +++ b/boot/espressif/hal/src/secure_boot.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -14,7 +14,8 @@ #include "esp_image_format.h" #include "esp_efuse.h" #include "esp_efuse_table.h" -#include "rom/secure_boot.h" +#include "secure_boot_signature_priv.h" + /* The following API implementations are used only when called * from the bootloader code. @@ -99,12 +100,20 @@ static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uin /* Generating the SHA of the public key components in the signature block */ bootloader_sha256_handle_t sig_block_sha; sig_block_sha = bootloader_sha256_start(); +#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME bootloader_sha256_data(sig_block_sha, &block->key, sizeof(block->key)); +#elif CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME + bootloader_sha256_data(sig_block_sha, &block->ecdsa.key, sizeof(block->ecdsa.key)); +#endif bootloader_sha256_finish(sig_block_sha, key_digest); // Check we can verify the image using this signature and this key uint8_t temp_verified_digest[ESP_SECURE_BOOT_DIGEST_LEN]; +#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME bool verified = ets_rsa_pss_verify(&block->key, block->signature, image_digest, temp_verified_digest); +#elif CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME + bool verified = ets_ecdsa_verify(&block->ecdsa.key.point[0], block->ecdsa.signature, block->ecdsa.key.curve_id, image_digest, temp_verified_digest); +#endif if (!verified) { /* We don't expect this: the signature blocks before we enable secure boot should all be verifiable or invalid, @@ -133,21 +142,22 @@ esp_err_t check_and_generate_secure_boot_keys(void) { esp_err_t ret; #ifdef CONFIG_IDF_TARGET_ESP32 - esp_efuse_purpose_t secure_boot_key_purpose[SECURE_BOOT_NUM_BLOCKS] = { - ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_V2, - }; esp_efuse_coding_scheme_t coding_scheme = esp_efuse_get_coding_scheme(EFUSE_BLK_SECURE_BOOT); if (coding_scheme != EFUSE_CODING_SCHEME_NONE) { ESP_LOGE(TAG, "No coding schemes are supported in secure boot v2.(Detected scheme: 0x%x)", coding_scheme); return ESP_ERR_NOT_SUPPORTED; } -#else +#endif // CONFIG_IDF_TARGET_ESP32 + esp_efuse_purpose_t secure_boot_key_purpose[SECURE_BOOT_NUM_BLOCKS] = { +#if SECURE_BOOT_NUM_BLOCKS == 1 + ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_V2, +#else ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST0, ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST1, ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST2, +#endif }; -#endif // CONFIG_IDF_TARGET_ESP32 /* Verify the bootloader */ esp_image_metadata_t bootloader_data = { 0 }; @@ -209,17 +219,24 @@ esp_err_t check_and_generate_secure_boot_keys(void) continue; } #endif +#ifndef CONFIG_SOC_EFUSE_CONSISTS_OF_ONE_KEY_BLOCK if (esp_efuse_get_key_dis_read(blocks[i])) { ESP_LOGE(TAG, "Key digest (BLK%d) read protected, aborting...", blocks[i]); return ESP_FAIL; } +#endif if (esp_efuse_block_is_empty(blocks[i])) { ESP_LOGE(TAG, "%d eFuse block is empty, aborting...", blocks[i]); return ESP_FAIL; } esp_efuse_set_key_dis_write(blocks[i]); - ret = esp_efuse_read_block(blocks[i], boot_key_digests.key_digests[boot_key_digests.num_digests], 0, - sizeof(boot_key_digests.key_digests[0]) * 8); +#ifdef CONFIG_SOC_EFUSE_CONSISTS_OF_ONE_KEY_BLOCK + size_t offset = 128; +#else + size_t offset = 0; +#endif + ret = esp_efuse_read_block(blocks[i], boot_key_digests.key_digests[boot_key_digests.num_digests], offset, + ESP_SECURE_BOOT_KEY_DIGEST_LEN * 8); if (ret) { ESP_LOGE(TAG, "Error during reading %d eFuse block (err=0x%x)", blocks[i], ret); return ret; diff --git a/boot/espressif/main.c b/boot/espressif/main.c index 9e1aa0704..3f4d5a064 100644 --- a/boot/espressif/main.c +++ b/boot/espressif/main.c @@ -12,6 +12,7 @@ #include "bootloader_init.h" #include "bootloader_utility.h" #include "bootloader_random.h" +#include "bootloader_soc.h" #include "esp_assert.h" @@ -118,6 +119,21 @@ int main() esp_efuse_init_virtual_mode_in_flash(CONFIG_EFUSE_VIRTUAL_OFFSET, CONFIG_EFUSE_VIRTUAL_SIZE); #endif +#if defined(CONFIG_SECURE_BOOT) || defined(CONFIG_SECURE_FLASH_ENC_ENABLED) + esp_err_t err; +#endif + +#ifdef CONFIG_SECURE_BOOT_FLASH_ENC_KEYS_BURN_TOGETHER + if (esp_secure_boot_enabled() ^ esp_flash_encrypt_initialized_once()) { + BOOT_LOG_ERR("Secure Boot and Flash Encryption cannot be enabled separately, only together (their keys go into one eFuse key block)"); + FIH_PANIC; + } + + if (!esp_secure_boot_enabled() || !esp_flash_encryption_enabled()) { + esp_efuse_batch_write_begin(); + } +#endif // CONFIG_SECURE_BOOT_FLASH_ENC_KEYS_BURN_TOGETHER + #ifdef CONFIG_SECURE_BOOT /* Steps 1 (see above for full description): * 1) Compute digest of the public key. @@ -132,7 +148,6 @@ int main() } else { esp_efuse_batch_write_begin(); /* Batch all efuse writes at the end of this function */ - esp_err_t err; err = check_and_generate_secure_boot_keys(); if (err != ESP_OK) { esp_efuse_batch_write_cancel(); @@ -178,7 +193,6 @@ int main() if (!sb_hw_enabled) { BOOT_LOG_INF("blowing secure boot efuse..."); - esp_err_t err; err = esp_secure_boot_enable_secure_features(); if (err != ESP_OK) { esp_efuse_batch_write_cancel(); @@ -195,8 +209,10 @@ int main() assert(esp_efuse_read_field_bit(ESP_EFUSE_SECURE_BOOT_AGGRESSIVE_REVOKE)); #endif +#ifndef CONFIG_SECURE_BOOT_FLASH_ENC_KEYS_BURN_TOGETHER assert(esp_secure_boot_enabled()); BOOT_LOG_INF("Secure boot permanently enabled"); +#endif } #endif @@ -206,16 +222,50 @@ int main() * 5) Encrypt flash in-place including bootloader, image primary/secondary slot and scratch. * 6) Burn EFUSE to enable flash encryption */ - - int rc; - BOOT_LOG_INF("Checking flash encryption..."); - bool flash_encryption_enabled = esp_flash_encryption_enabled(); - rc = esp_flash_encrypt_check_and_update(); - if (rc != ESP_OK) { - BOOT_LOG_ERR("Flash encryption check failed (%d).", rc); + bool flash_encryption_enabled = esp_flash_encrypt_state(); + if (!flash_encryption_enabled) { +#ifdef CONFIG_SECURE_FLASH_REQUIRE_ALREADY_ENABLED + BOOT_LOG_ERR("flash encryption is not enabled, and SECURE_FLASH_REQUIRE_ALREADY_ENABLED is set, refusing to boot."); FIH_PANIC; +#endif // CONFIG_SECURE_FLASH_REQUIRE_ALREADY_ENABLED + + if (esp_flash_encrypt_is_write_protected(true)) { + FIH_PANIC; + } + + err = esp_flash_encrypt_init(); + if (err != ESP_OK) { + BOOT_LOG_ERR("Initialization of Flash Encryption key failed (%d)", err); + FIH_PANIC; + } + } + + if (!flash_encryption_enabled) { + err = esp_flash_encrypt_contents(); + if (err != ESP_OK) { + BOOT_LOG_ERR("Encryption flash contents failed (%d)", err); + FIH_PANIC; + } + + err = esp_flash_encrypt_enable(); + if (err != ESP_OK) { + BOOT_LOG_ERR("Enabling of Flash encryption failed (%d)", err); + FIH_PANIC; + } + } + +#ifdef CONFIG_SECURE_BOOT_FLASH_ENC_KEYS_BURN_TOGETHER + if (!esp_secure_boot_enabled() || !flash_encryption_enabled) { + err = esp_efuse_batch_write_commit(); + if (err != ESP_OK) { + BOOT_LOG_ERR("Error programming eFuses (err=0x%x).", err); + FIH_PANIC; + } + assert(esp_secure_boot_enabled()); + BOOT_LOG_INF("Secure boot permanently enabled"); } +#endif // CONFIG_SECURE_BOOT_FLASH_ENC_KEYS_BURN_TOGETHER /* Step 7 (see above for full description): * 7) Reset system to ensure flash encryption cache resets properly. @@ -229,6 +279,12 @@ int main() BOOT_LOG_INF("Disabling RNG early entropy source..."); bootloader_random_disable(); + /* Disable glitch reset after all the security checks are completed. + * Glitch detection can be falsely triggered by EMI interference (high RF TX power, etc) + * and to avoid such false alarms, disable it. + */ + bootloader_ana_clock_glitch_reset_config(false); + #ifdef CONFIG_ESP_MULTI_PROCESSOR_BOOT /* Multi image independent boot * Boot on the second processor happens before the image0 boot diff --git a/boot/espressif/port/esp32c2/bootloader.conf b/boot/espressif/port/esp32c2/bootloader.conf index 286b1a197..54f797e71 100644 --- a/boot/espressif/port/esp32c2/bootloader.conf +++ b/boot/espressif/port/esp32c2/bootloader.conf @@ -63,6 +63,12 @@ CONFIG_ESP_CONSOLE_UART_NUM=0 # using imgtool instead of use the existent sample # CONFIG_ESP_SIGN_KEY_FILE=root-ec-p256.pem +# Hardware Secure Boot related options +# CONFIG_SECURE_SIGNED_ON_BOOT=1 +# CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME=1 +# CONFIG_SECURE_BOOT=1 +# CONFIG_SECURE_BOOT_V2_ENABLED=1 + # Hardware Flash Encryption related options # CONFIG_SECURE_FLASH_ENC_ENABLED=1 # CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC=1 @@ -72,6 +78,10 @@ CONFIG_ESP_CONSOLE_UART_NUM=0 # CONFIG_SECURE_BOOT_ALLOW_JTAG=1 # CONFIG_SECURE_BOOT_ALLOW_ROM_BASIC=1 +# This option must be also enabled when enabling both Secure Boot +# and Flash Encryption at same time +# CONFIG_SECURE_BOOT_FLASH_ENC_KEYS_BURN_TOGETHER=1 + # Options for enabling eFuse emulation in Flash # CONFIG_EFUSE_VIRTUAL=1 # CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH=1 diff --git a/boot/espressif/port/esp32c3/ld/bootloader.ld b/boot/espressif/port/esp32c3/ld/bootloader.ld index 65f15cc4d..747b54914 100644 --- a/boot/espressif/port/esp32c3/ld/bootloader.ld +++ b/boot/espressif/port/esp32c3/ld/bootloader.ld @@ -13,8 +13,8 @@ MEMORY { iram_seg (RWX) : org = 0x403C7000, len = 0x9000 - iram_loader_seg (RWX) : org = 0x403D0000, len = 0x5000 - dram_seg (RW) : org = 0x3FCD5000, len = 0xA000 + iram_loader_seg (RWX) : org = 0x403D0000, len = 0x5400 + dram_seg (RW) : org = 0x3FCD5400, len = 0xA000 } /* Default entry point: */ diff --git a/docs/readme-espressif.md b/docs/readme-espressif.md index ff51d1f67..dc236fbdd 100644 --- a/docs/readme-espressif.md +++ b/docs/readme-espressif.md @@ -293,15 +293,13 @@ MCUboot header. The Secure Boot implementation is based on [IDF's Secure Boot V2](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/security/secure-boot-v2.html), -is hardware-assisted and RSA based, and has the role for ensuring that only authorized code will be -executed on the device. This is done through bootloader signature checking by the ROM bootloader. +is hardware-assisted and RSA based - except ESP32-C2 that uses ECDSA signing scheme - and has the +role for ensuring that only authorized code will be executed on the device. This is done through +bootloader signature checking by the ROM bootloader. ***Note***: ROM bootloader is the First Stage Bootloader, while the Espressif MCUboot port is the Second Stage Bootloader. -***Note***: Currently on MCUboot Espressif Port, the Secure Boot V2 for ESP32-C2 is not supported -yet. - ### [Building bootloader with Secure Boot](#building-bootloader-with-secure-boot) In order to build the bootloader with the feature on, the following configurations must be enabled: @@ -310,10 +308,24 @@ In order to build the bootloader with the feature on, the following configuratio CONFIG_SECURE_BOOT=1 CONFIG_SECURE_BOOT_V2_ENABLED=1 CONFIG_SECURE_SIGNED_ON_BOOT=1 +``` + +For the currently supported chips, with exception of ESP32-C2, enable RSA signing scheme: + +``` CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME=1 CONFIG_SECURE_BOOT_SUPPORTS_RSA=1 ``` +For ESP32-C2, enable ECDSA signing scheme and, if working with Flash Encryption too, enable the +configuration to burn keys to efuse together: + +``` +CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME=1 + +CONFIG_SECURE_BOOT_FLASH_ENC_KEYS_BURN_TOGETHER=1 +``` + --- :warning: ***ATTENTION*** @@ -1152,7 +1164,7 @@ application. * | | | *** OS CAN RECLAIM IT AFTER BOOT LATER AS HEAP *** * | | | * | v | - * +------------------------------+ 0x403D5000 / 0x3FCD5000 + * +------------------------------+ 0x403D5400 / 0x3FCD5400 * | ^ | * | | | * | | dram_seg | *** SHOULD NOT BE OVERLAPPED ***