From 142f69448f18c634bb37a841b2b8454c9fe13085 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Fri, 20 Mar 2020 13:55:15 +1100 Subject: [PATCH] secure boot v2: esp32: Prevent read disabling additional efuses Also reduce the number of eFuse write cycles during first boot when Secure Boot and/or Flash Encryption are enabled. --- components/bootloader/Kconfig.projbuild | 12 +++++ .../src/esp32/flash_encrypt.c | 31 ++++++++---- .../src/esp32/secure_boot.c | 48 +++++++++++++------ docs/en/security/secure-boot-v2.rst | 7 +++ 4 files changed, 73 insertions(+), 25 deletions(-) diff --git a/components/bootloader/Kconfig.projbuild b/components/bootloader/Kconfig.projbuild index 9b06eceaca..69db85cf31 100644 --- a/components/bootloader/Kconfig.projbuild +++ b/components/bootloader/Kconfig.projbuild @@ -640,6 +640,18 @@ menu "Security features" image to this length. It is generally not recommended to set this option, unless you have a legacy partitioning scheme which doesn't support 64KB aligned partition lengths. + config SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS + bool "Allow additional read protecting of efuses" + depends on SECURE_BOOT_INSECURE && SECURE_BOOT_V2_ENABLED + help + If not set (default, recommended), on first boot the bootloader will burn the WR_DIS_RD_DIS + efuse when Secure Boot is enabled. This prevents any more efuses from being read protected. + + If this option is set, it will remain possible to write the EFUSE_RD_DIS efuse field after Secure + Boot is enabled. This may allow an attacker to read-protect the BLK2 efuse holding the public + key digest, causing an immediate denial of service and possibly allowing an additional fault + injection attack to bypass the signature protection. + config SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC bool "Leave UART bootloader encryption enabled" depends on SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT diff --git a/components/bootloader_support/src/esp32/flash_encrypt.c b/components/bootloader_support/src/esp32/flash_encrypt.c index 322414adcf..701a569856 100644 --- a/components/bootloader_support/src/esp32/flash_encrypt.c +++ b/components/bootloader_support/src/esp32/flash_encrypt.c @@ -73,6 +73,10 @@ esp_err_t esp_flash_encrypt_check_and_update(void) static esp_err_t initialise_flash_encryption(void) { + uint32_t new_wdata0 = 0; + uint32_t new_wdata5 = 0; + uint32_t new_wdata6 = 0; + uint32_t coding_scheme = REG_GET_FIELD(EFUSE_BLK0_RDATA6_REG, EFUSE_CODING_SCHEME); if (coding_scheme != EFUSE_CODING_SCHEME_VAL_NONE && coding_scheme != EFUSE_CODING_SCHEME_VAL_34) { ESP_LOGE(TAG, "Unknown/unsupported CODING_SCHEME value 0x%x", coding_scheme); @@ -97,11 +101,10 @@ static esp_err_t initialise_flash_encryption(void) && REG_READ(EFUSE_BLK1_RDATA7_REG) == 0) { ESP_LOGI(TAG, "Generating new flash encryption key..."); esp_efuse_write_random_key(EFUSE_BLK1_WDATA0_REG); - esp_efuse_burn_new_values(); + // defer efuse programming step to the end ESP_LOGI(TAG, "Read & write protecting new key..."); - REG_WRITE(EFUSE_BLK0_WDATA0_REG, EFUSE_WR_DIS_BLK1 | EFUSE_RD_DIS_BLK1); - esp_efuse_burn_new_values(); + new_wdata0 |= EFUSE_WR_DIS_BLK1 | EFUSE_RD_DIS_BLK1; } else { if(!(efuse_key_read_protected && efuse_key_write_protected)) { @@ -122,34 +125,36 @@ static esp_err_t initialise_flash_encryption(void) operation does nothing. Please note this is not recommended! */ ESP_LOGI(TAG, "Setting CRYPT_CONFIG efuse to 0xF"); - REG_WRITE(EFUSE_BLK0_WDATA5_REG, EFUSE_FLASH_CRYPT_CONFIG_M); - esp_efuse_burn_new_values(); + new_wdata5 |= EFUSE_FLASH_CRYPT_CONFIG_M; - uint32_t new_wdata6 = 0; #ifndef CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC ESP_LOGI(TAG, "Disable UART bootloader encryption..."); new_wdata6 |= EFUSE_DISABLE_DL_ENCRYPT; #else ESP_LOGW(TAG, "Not disabling UART bootloader encryption"); #endif + #ifndef CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_DEC ESP_LOGI(TAG, "Disable UART bootloader decryption..."); new_wdata6 |= EFUSE_DISABLE_DL_DECRYPT; #else ESP_LOGW(TAG, "Not disabling UART bootloader decryption - SECURITY COMPROMISED"); #endif + #ifndef CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_CACHE ESP_LOGI(TAG, "Disable UART bootloader MMU cache..."); new_wdata6 |= EFUSE_DISABLE_DL_CACHE; #else ESP_LOGW(TAG, "Not disabling UART bootloader MMU cache - SECURITY COMPROMISED"); #endif + #ifndef CONFIG_SECURE_BOOT_ALLOW_JTAG ESP_LOGI(TAG, "Disable JTAG..."); new_wdata6 |= EFUSE_RD_DISABLE_JTAG; #else ESP_LOGW(TAG, "Not disabling JTAG - SECURITY COMPROMISED"); #endif + #ifndef CONFIG_SECURE_BOOT_ALLOW_ROM_BASIC ESP_LOGI(TAG, "Disable ROM BASIC interpreter fallback..."); new_wdata6 |= EFUSE_RD_CONSOLE_DEBUG_DISABLE; @@ -157,10 +162,16 @@ static esp_err_t initialise_flash_encryption(void) ESP_LOGW(TAG, "Not disabling ROM BASIC fallback - SECURITY COMPROMISED"); #endif - if (new_wdata6 != 0) { - REG_WRITE(EFUSE_BLK0_WDATA6_REG, new_wdata6); - esp_efuse_burn_new_values(); - } +#if defined(CONFIG_SECURE_BOOT_V2_ENABLED) && !defined(CONFIG_SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS) + // This bit is set when enabling Secure Boot V2, but we can't enable it until this later point in the first boot + // otherwise the Flash Encryption key cannot be read protected + new_wdata0 |= EFUSE_WR_DIS_RD_DIS; +#endif + + REG_WRITE(EFUSE_BLK0_WDATA0_REG, new_wdata0); + REG_WRITE(EFUSE_BLK0_WDATA5_REG, new_wdata5); + REG_WRITE(EFUSE_BLK0_WDATA6_REG, new_wdata6); + esp_efuse_burn_new_values(); return ESP_OK; } diff --git a/components/bootloader_support/src/esp32/secure_boot.c b/components/bootloader_support/src/esp32/secure_boot.c index 6e6462138f..853d54af14 100644 --- a/components/bootloader_support/src/esp32/secure_boot.c +++ b/components/bootloader_support/src/esp32/secure_boot.c @@ -39,11 +39,6 @@ /* The following API implementations are used only when called * from the bootloader code. */ -/* Burn values written to the efuse write registers */ -static inline void burn_efuses(void) -{ - esp_efuse_burn_new_values(); -} #ifdef CONFIG_SECURE_BOOT_V1_ENABLED static const char *TAG = "secure_boot_v1"; @@ -140,7 +135,7 @@ esp_err_t esp_secure_boot_generate_digest(void) && REG_READ(EFUSE_BLK2_RDATA7_REG) == 0) { ESP_LOGI(TAG, "Generating new secure boot key..."); esp_efuse_write_random_key(EFUSE_BLK2_WDATA0_REG); - burn_efuses(); + esp_efuse_burn_new_values(); } else { ESP_LOGW(TAG, "Using pre-loaded secure boot key in EFUSE block 2"); } @@ -163,6 +158,9 @@ esp_err_t esp_secure_boot_generate_digest(void) esp_err_t esp_secure_boot_permanently_enable(void) { + uint32_t new_wdata0 = 0; + uint32_t new_wdata6 = 0; + if (esp_secure_boot_enabled()) { ESP_LOGI(TAG, "bootloader secure boot is already enabled, continuing.."); return ESP_OK; @@ -174,8 +172,7 @@ esp_err_t esp_secure_boot_permanently_enable(void) if (efuse_key_read_protected == false && efuse_key_write_protected == false) { ESP_LOGI(TAG, "Read & write protecting new key..."); - REG_WRITE(EFUSE_BLK0_WDATA0_REG, EFUSE_WR_DIS_BLK2 | EFUSE_RD_DIS_BLK2); - burn_efuses(); + new_wdata0 = EFUSE_WR_DIS_BLK2 | EFUSE_RD_DIS_BLK2; efuse_key_read_protected = true; efuse_key_write_protected = true; } @@ -192,7 +189,7 @@ esp_err_t esp_secure_boot_permanently_enable(void) ESP_LOGI(TAG, "blowing secure boot efuse..."); ESP_LOGD(TAG, "before updating, EFUSE_BLK0_RDATA6 %x", REG_READ(EFUSE_BLK0_RDATA6_REG)); - uint32_t new_wdata6 = EFUSE_RD_ABS_DONE_0; + new_wdata6 |= EFUSE_RD_ABS_DONE_0; #ifndef CONFIG_SECURE_BOOT_ALLOW_JTAG ESP_LOGI(TAG, "Disable JTAG..."); @@ -208,8 +205,9 @@ esp_err_t esp_secure_boot_permanently_enable(void) ESP_LOGW(TAG, "Not disabling ROM BASIC fallback - SECURITY COMPROMISED"); #endif + REG_WRITE(EFUSE_BLK0_WDATA0_REG, new_wdata0); REG_WRITE(EFUSE_BLK0_WDATA6_REG, new_wdata6); - burn_efuses(); + esp_efuse_burn_new_values(); uint32_t after = REG_READ(EFUSE_BLK0_RDATA6_REG); ESP_LOGD(TAG, "after updating, EFUSE_BLK0_RDATA6 %x", after); if (after & EFUSE_RD_ABS_DONE_0) { @@ -293,6 +291,9 @@ done: esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *image_data) { + uint32_t new_wdata0 = 0; + uint32_t new_wdata6 = 0; + ESP_LOGI(TAG, "enabling secure boot v2..."); esp_err_t ret; if (esp_secure_boot_enabled()) { @@ -306,7 +307,7 @@ esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *imag return ESP_ERR_NOT_SUPPORTED; } - /* Verify the bootloader */ + /* Verify the bootloader */ esp_image_metadata_t bootloader_data = { 0 }; ret = esp_image_verify_bootloader_data(&bootloader_data); if (ret != ESP_OK) { @@ -343,7 +344,7 @@ esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *imag } ESP_LOGI(TAG, "Write protecting public key digest..."); - REG_WRITE(EFUSE_BLK0_WDATA0_REG, EFUSE_WR_DIS_BLK2); + new_wdata0 |= EFUSE_WR_DIS_BLK2; efuse_key_write_protected = true; efuse_key_read_protected = false; } else { @@ -375,7 +376,7 @@ esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *imag ESP_LOGI(TAG, "blowing secure boot efuse..."); ESP_LOGD(TAG, "before updating, EFUSE_BLK0_RDATA6 %x", REG_READ(EFUSE_BLK0_RDATA6_REG)); - uint32_t new_wdata6 = EFUSE_RD_ABS_DONE_1; + new_wdata6 |= EFUSE_RD_ABS_DONE_1; #ifndef CONFIG_SECURE_BOOT_ALLOW_JTAG ESP_LOGI(TAG, "Disable JTAG..."); @@ -391,10 +392,27 @@ esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *imag ESP_LOGW(TAG, "Not disabling ROM BASIC fallback - SECURITY COMPROMISED"); #endif +#ifndef CONFIG_SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS + bool rd_dis_now = true; +#ifdef CONFIG_SECURE_FLASH_ENC_ENABLED + /* If flash encryption is not enabled yet then don't read-disable efuses yet, do it later in the boot + when Flash Encryption is being enabled */ + rd_dis_now = esp_flash_encryption_enabled(); +#endif + if (rd_dis_now) { + ESP_LOGI(TAG, "Prevent read disabling of additional efuses..."); + new_wdata0 |= EFUSE_WR_DIS_RD_DIS; + } +#else + ESP_LOGW(TAG, "Allowing read disabling of additional efuses - SECURITY COMPROMISED"); +#endif + + REG_WRITE(EFUSE_BLK0_WDATA0_REG, new_wdata0); REG_WRITE(EFUSE_BLK0_WDATA6_REG, new_wdata6); - burn_efuses(); + esp_efuse_burn_new_values(); uint32_t after = REG_READ(EFUSE_BLK0_RDATA6_REG); - ESP_LOGD(TAG, "after updating, EFUSE_BLK0_RDATA6 %x", after); + ESP_LOGD(TAG, "after updating, EFUSE_BLK0_RDATA0 0x%08x EFUSE_BLK0_RDATA6 0x%08x", + REG_READ(EFUSE_BLK0_RDATA0_REG), after); if (after & EFUSE_RD_ABS_DONE_1) { ESP_LOGI(TAG, "secure boot v2 is now enabled."); return ESP_OK; diff --git a/docs/en/security/secure-boot-v2.rst b/docs/en/security/secure-boot-v2.rst index da5c0da191..b29dbe6e35 100644 --- a/docs/en/security/secure-boot-v2.rst +++ b/docs/en/security/secure-boot-v2.rst @@ -168,6 +168,13 @@ How To Enable Secure Boot V2 10. On subsequent boots, the secure boot hardware will verify the software bootloader has not changed and the software bootloader will verify the signed app image (using the validated public key portion of its appended signature block). +Restrictions after Secure Boot is enabled +----------------------------------------- + +- Any updated bootloader or app will need to be signed with a key matching the digest already stored in efuse. + +- After Secure Boot is enabled, no further efuses can be read protected. (If :doc:`/security/flash-encryption` is enabled then the bootloader will ensure that any flash encryption key generated on first boot will already be read protected.) If :ref:`CONFIG_SECURE_BOOT_INSECURE` is enabled then this behaviour can be disabled, but this is not recommended. + .. _secure-boot-v2-generate-key: Generating Secure Boot Signing Key