From 93e0ccb2ec86fb3fdcd888a7270d643b1ff2b532 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 96a55e5287..5e47ccc499 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-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2018-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -50,6 +50,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 bff2149fae..5f745df37d 100644 --- a/components/esp_system/port/soc/esp32c2/system_internal.c +++ b/components/esp_system/port/soc/esp32c2/system_internal.c @@ -41,8 +41,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 9372edd56f..6b0d5c8f6f 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-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2018-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -49,8 +49,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 75e43bf2d1..9fde3a176e 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 */ @@ -56,6 +56,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 bc4aecd271..093682e554 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 */ @@ -52,6 +52,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 db71cf1feb..581c135354 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-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2018-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -49,6 +49,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 3d0053edd2..1c206c17bf 100644 --- a/components/esp_system/port/soc/esp32s3/system_internal.c +++ b/components/esp_system/port/soc/esp32s3/system_internal.c @@ -51,8 +51,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);