From 70b1496d9fa593bfe9cd3031b17ecc4babb4b7ef Mon Sep 17 00:00:00 2001 From: Mahavir Jain Date: Mon, 14 Apr 2025 15:13:40 +0530 Subject: [PATCH] fix(esp_system): reset crypto peripherals before device restart MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change addresses a rare but critical issue observed on certain ESP32-C3 and ESP32-S3 devices, where secure boot verification intermittently fails due to improper cleanup of crypto peripherals during a restart. Background – Restart Behavior in IDF ------------------------------------ In ESP-IDF, when the device restarts (via `esp_restart()` or due to a panic/exception), a partial peripheral reset is performed followed by a CPU reset. However, until now, crypto-related peripherals were not included in this selective reset sequence. Problem Scenario ---------------- If a restart occurs while the application is in the middle of a bignum operation (i.e., using the MPI/Bignum peripheral), the ROM code may encounter an inconsistent peripheral state during the subsequent boot. This leads to transient RSA-PSS secure boot verification failures. Following such a failure, the ROM typically triggers a full-chip reset via the watchdog timer (WDT). This full reset clears the crypto peripheral state, allowing secure boot verification to succeed on the next boot. Risk with Aggressive Revocation ------------------------------- If secure boot aggressive revocation is enabled (disabled by default in IDF), this transient verification failure could mistakenly lead to revocation of the secure boot digest. If your product configuration has aggressive revocation enabled, applying this fix is strongly recommended. Frequency of Occurrence ----------------------- The issue is rare and only occurs in corner cases involving simultaneous use of the MPI peripheral and an immediate CPU reset. Fix --- This fix ensures that all crypto peripherals are explicitly reset prior to any software-triggered restart (including panic scenarios), guaranteeing a clean peripheral state for the next boot and preventing incorrect secure boot behavior. --- .../port/soc/esp32/system_internal.c | 8 +++++++- .../port/soc/esp32c2/system_internal.c | 6 ++++-- .../port/soc/esp32c3/system_internal.c | 9 ++++++--- .../port/soc/esp32c6/system_internal.c | 17 ++++++++++++++++- .../port/soc/esp32h2/system_internal.c | 19 ++++++++++++++++++- .../port/soc/esp32s2/system_internal.c | 9 ++++++++- .../port/soc/esp32s3/system_internal.c | 6 ++++-- 7 files changed, 63 insertions(+), 11 deletions(-) diff --git a/components/esp_system/port/soc/esp32/system_internal.c b/components/esp_system/port/soc/esp32/system_internal.c index 47a0b1ace2..8b26f684d0 100644 --- a/components/esp_system/port/soc/esp32/system_internal.c +++ b/components/esp_system/port/soc/esp32/system_internal.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2018-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2018-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -51,6 +51,12 @@ void IRAM_ATTR esp_system_reset_modules_on_exit(void) DPORT_SPI_DMA_RST | DPORT_UART_RST | DPORT_UART1_RST | DPORT_UART2_RST | DPORT_UART_MEM_RST | DPORT_PWM0_RST | DPORT_PWM1_RST); DPORT_REG_WRITE(DPORT_PERIP_RST_EN_REG, 0); + + // Reset crypto peripherals. This ensures a clean state for the crypto peripherals after a CPU restart and hence + // avoiding any possibility with crypto failure in ROM security workflows. + DPORT_SET_PERI_REG_MASK(DPORT_PERI_RST_EN_REG, DPORT_PERI_EN_AES | DPORT_PERI_EN_RSA | + DPORT_PERI_EN_SHA | DPORT_PERI_EN_DIGITAL_SIGNATURE); + DPORT_REG_WRITE(DPORT_PERI_RST_EN_REG, 0); } /* "inner" restart function for after RTOS, interrupts & anything else on this diff --git a/components/esp_system/port/soc/esp32c2/system_internal.c b/components/esp_system/port/soc/esp32c2/system_internal.c index da9094272a..32ada063e5 100644 --- a/components/esp_system/port/soc/esp32c2/system_internal.c +++ b/components/esp_system/port/soc/esp32c2/system_internal.c @@ -44,8 +44,10 @@ void IRAM_ATTR esp_system_reset_modules_on_exit(void) SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN0_REG, SYSTEM_SPI01_RST | SYSTEM_UART_RST | SYSTEM_SYSTIMER_RST); REG_WRITE(SYSTEM_PERIP_RST_EN0_REG, 0); - // Reset dma - SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_DMA_RST); + + // Reset dma and crypto peripherals. This ensures a clean state for the crypto peripherals after a CPU restart + // and hence avoiding any possibility with crypto failure in ROM security workflows. + SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_DMA_RST | SYSTEM_CRYPTO_ECC_RST | SYSTEM_CRYPTO_SHA_RST); REG_WRITE(SYSTEM_PERIP_RST_EN1_REG, 0); } diff --git a/components/esp_system/port/soc/esp32c3/system_internal.c b/components/esp_system/port/soc/esp32c3/system_internal.c index 5113bc2b72..0ca01a11a9 100644 --- a/components/esp_system/port/soc/esp32c3/system_internal.c +++ b/components/esp_system/port/soc/esp32c3/system_internal.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2018-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2018-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -52,8 +52,11 @@ void IRAM_ATTR esp_system_reset_modules_on_exit(void) SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN0_REG, SYSTEM_TIMERS_RST | SYSTEM_SPI01_RST | SYSTEM_UART_RST | SYSTEM_SYSTIMER_RST); REG_WRITE(SYSTEM_PERIP_RST_EN0_REG, 0); - // Reset dma - SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_DMA_RST); + + // Reset dma and crypto peripherals. This ensures a clean state for the crypto peripherals after a CPU restart + // and hence avoiding any possibility with crypto failure in ROM security workflows. + SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_DMA_RST | SYSTEM_CRYPTO_AES_RST | SYSTEM_CRYPTO_DS_RST | + SYSTEM_CRYPTO_HMAC_RST | SYSTEM_CRYPTO_RSA_RST | SYSTEM_CRYPTO_SHA_RST); REG_WRITE(SYSTEM_PERIP_RST_EN1_REG, 0); } diff --git a/components/esp_system/port/soc/esp32c6/system_internal.c b/components/esp_system/port/soc/esp32c6/system_internal.c index 2829b4de67..32c9b9f966 100644 --- a/components/esp_system/port/soc/esp32c6/system_internal.c +++ b/components/esp_system/port/soc/esp32c6/system_internal.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -59,6 +59,21 @@ void IRAM_ATTR esp_system_reset_modules_on_exit(void) CLEAR_PERI_REG_MASK(PCR_SDIO_SLAVE_CONF_REG, PCR_SDIO_SLAVE_RST_EN); CLEAR_PERI_REG_MASK(PCR_MODEM_APB_CONF_REG, PCR_MODEM_RST_EN); CLEAR_PERI_REG_MASK(PCR_PWM_CONF_REG, PCR_PWM_RST_EN); + + // Reset crypto peripherals. This ensures a clean state for the crypto peripherals after a CPU restart + // and hence avoiding any possibility with crypto failure in ROM security workflows. + SET_PERI_REG_MASK(PCR_AES_CONF_REG, PCR_AES_RST_EN); + SET_PERI_REG_MASK(PCR_DS_CONF_REG, PCR_DS_RST_EN); + SET_PERI_REG_MASK(PCR_ECC_CONF_REG, PCR_ECC_RST_EN); + SET_PERI_REG_MASK(PCR_HMAC_CONF_REG, PCR_HMAC_RST_EN); + SET_PERI_REG_MASK(PCR_RSA_CONF_REG, PCR_RSA_RST_EN); + SET_PERI_REG_MASK(PCR_SHA_CONF_REG, PCR_SHA_RST_EN); + CLEAR_PERI_REG_MASK(PCR_AES_CONF_REG, PCR_AES_RST_EN); + CLEAR_PERI_REG_MASK(PCR_DS_CONF_REG, PCR_DS_RST_EN); + CLEAR_PERI_REG_MASK(PCR_ECC_CONF_REG, PCR_ECC_RST_EN); + CLEAR_PERI_REG_MASK(PCR_HMAC_CONF_REG, PCR_HMAC_RST_EN); + CLEAR_PERI_REG_MASK(PCR_RSA_CONF_REG, PCR_RSA_RST_EN); + CLEAR_PERI_REG_MASK(PCR_SHA_CONF_REG, PCR_SHA_RST_EN); } /* "inner" restart function for after RTOS, interrupts & anything else on this diff --git a/components/esp_system/port/soc/esp32h2/system_internal.c b/components/esp_system/port/soc/esp32h2/system_internal.c index 93cbb12d55..0c37db6264 100644 --- a/components/esp_system/port/soc/esp32h2/system_internal.c +++ b/components/esp_system/port/soc/esp32h2/system_internal.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -55,6 +55,23 @@ void IRAM_ATTR esp_system_reset_modules_on_exit(void) CLEAR_PERI_REG_MASK(PCR_GDMA_CONF_REG, PCR_GDMA_RST_EN); CLEAR_PERI_REG_MASK(PCR_MODEM_CONF_REG, PCR_MODEM_RST_EN); CLEAR_PERI_REG_MASK(PCR_PWM_CONF_REG, PCR_PWM_RST_EN); + + // Reset crypto peripherals. This ensures a clean state for the crypto peripherals after a CPU restart + // and hence avoiding any possibility with crypto failure in ROM security workflows. + SET_PERI_REG_MASK(PCR_AES_CONF_REG, PCR_AES_RST_EN); + SET_PERI_REG_MASK(PCR_DS_CONF_REG, PCR_DS_RST_EN); + SET_PERI_REG_MASK(PCR_ECC_CONF_REG, PCR_ECC_RST_EN); + SET_PERI_REG_MASK(PCR_ECDSA_CONF_REG, PCR_ECDSA_RST_EN); + SET_PERI_REG_MASK(PCR_HMAC_CONF_REG, PCR_HMAC_RST_EN); + SET_PERI_REG_MASK(PCR_RSA_CONF_REG, PCR_RSA_RST_EN); + SET_PERI_REG_MASK(PCR_SHA_CONF_REG, PCR_SHA_RST_EN); + CLEAR_PERI_REG_MASK(PCR_AES_CONF_REG, PCR_AES_RST_EN); + CLEAR_PERI_REG_MASK(PCR_DS_CONF_REG, PCR_DS_RST_EN); + CLEAR_PERI_REG_MASK(PCR_ECC_CONF_REG, PCR_ECC_RST_EN); + CLEAR_PERI_REG_MASK(PCR_ECDSA_CONF_REG, PCR_ECDSA_RST_EN); + CLEAR_PERI_REG_MASK(PCR_HMAC_CONF_REG, PCR_HMAC_RST_EN); + CLEAR_PERI_REG_MASK(PCR_RSA_CONF_REG, PCR_RSA_RST_EN); + CLEAR_PERI_REG_MASK(PCR_SHA_CONF_REG, PCR_SHA_RST_EN); } /* "inner" restart function for after RTOS, interrupts & anything else on this diff --git a/components/esp_system/port/soc/esp32s2/system_internal.c b/components/esp_system/port/soc/esp32s2/system_internal.c index b790f36b65..22cf0751ea 100644 --- a/components/esp_system/port/soc/esp32s2/system_internal.c +++ b/components/esp_system/port/soc/esp32s2/system_internal.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2018-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2018-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -51,6 +51,13 @@ void IRAM_ATTR esp_system_reset_modules_on_exit(void) DPORT_TIMERS_RST | DPORT_SPI01_RST | DPORT_SPI2_RST | DPORT_SPI3_RST | DPORT_SPI2_DMA_RST | DPORT_SPI3_DMA_RST | DPORT_UART_RST); DPORT_REG_WRITE(DPORT_PERIP_RST_EN_REG, 0); + + // Reset crypto peripherals. This ensures a clean state for the crypto peripherals after a CPU restart + // and hence avoiding any possibility with crypto failure in ROM security workflows. + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN1_REG, + DPORT_CRYPTO_DMA_RST | DPORT_CRYPTO_AES_RST | DPORT_CRYPTO_DS_RST | + DPORT_CRYPTO_HMAC_RST | DPORT_CRYPTO_RSA_RST | DPORT_CRYPTO_SHA_RST); + DPORT_REG_WRITE(DPORT_PERIP_RST_EN1_REG, 0); } /* "inner" restart function for after RTOS, interrupts & anything else on this diff --git a/components/esp_system/port/soc/esp32s3/system_internal.c b/components/esp_system/port/soc/esp32s3/system_internal.c index 635d80cb4c..196b8ae98a 100644 --- a/components/esp_system/port/soc/esp32s3/system_internal.c +++ b/components/esp_system/port/soc/esp32s3/system_internal.c @@ -52,8 +52,10 @@ void IRAM_ATTR esp_system_reset_modules_on_exit(void) SYSTEM_PWM0_RST | SYSTEM_PWM1_RST); REG_WRITE(SYSTEM_PERIP_RST_EN0_REG, 0); - // Reset dma - SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_DMA_RST); + // Reset dma and crypto peripherals. This ensures a clean state for the crypto peripherals after a CPU restart + // and hence avoiding any possibility with crypto failure in ROM security workflows. + SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_DMA_RST | SYSTEM_CRYPTO_AES_RST | SYSTEM_CRYPTO_DS_RST | + SYSTEM_CRYPTO_HMAC_RST | SYSTEM_CRYPTO_RSA_RST | SYSTEM_CRYPTO_SHA_RST); REG_WRITE(SYSTEM_PERIP_RST_EN1_REG, 0); SET_PERI_REG_MASK(SYSTEM_EDMA_CTRL_REG, SYSTEM_EDMA_RESET);