Failed to disable ROM download mode

dizcza
Posts: 61
Joined: Tue Sep 07, 2021 6:59 pm

Failed to disable ROM download mode

Postby dizcza » Sat Feb 22, 2025 4:19 pm

  • I enabled Secure Boot v2 and Flash Encryption in development mode.
  • I ran

    Code: Select all

    idf.py bootloader-flash
    and then

    Code: Select all

    idf.py flash
    only once. Confirmed it works with monitor.
  • I reconfigured the app to Flash Encryption Release mode, uploaded it to the server and did OTA upgrade to upgrade the app Flash Encryption from Dev to Release.
  • I got the error "Failed to disable ROM download mode" and the corresponding eFuse became write-protected (it wasn't before I did OTA upgrade, I checked).
Logs:

Code: Select all

I (681) cpu_start: Multicore app
I (681) quad_psram: This chip is ESP32-D0WD
I (682) esp_psram: Found 8MB PSRAM device
I (683) esp_psram: Speed: 40MHz
I (687) esp_psram: PSRAM initialized, cache is in low/high (2-core) mode.
W (694) esp_psram: Virtual address not enough for PSRAM, map as much as we can. 4MB is mapped
I (703) cpu_start: Pro cpu up.
I (707) cpu_start: Starting app cpu, entry point is 0x40081510
--- 0x40081510: call_start_cpu1 at /home/dizcza/tools/esp-idf/components/esp_system/port/cpu_start.c:160

I (688) cpu_start: App cpu up.
I (1592) esp_psram: SPI SRAM memory test OK
I (1602) cpu_start: Pro cpu start user code
I (1602) cpu_start: cpu freq: 160000000 Hz
I (1602) cpu_start: Application information:
I (1606) cpu_start: Project name:     frogboard_arduino
I (1611) cpu_start: App version:      4110e53-dirty
I (1617) cpu_start: Compile time:     Feb 22 2025 17:21:42
I (1623) cpu_start: ELF file SHA256:  4d860f2b20ee008a...
--- Warning: Checksum mismatch between flashed and built applications. Checksum of built application is 4b2ab48fdfec0a8096b64227857f0bd02237b3197b6771f7b151662949f074f7
I (1629) cpu_start: ESP-IDF:          v5.1.5-143-gdb1c67632a
I (1636) cpu_start: Min chip rev:     v3.0
I (1640) cpu_start: Max chip rev:     v3.99 
I (1645) cpu_start: Chip rev:         v3.0
I (1650) heap_init: Initializing. RAM available for dynamic allocation:
I (1658) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (1664) heap_init: At 3FFBB540 len 00024AC0 (146 KiB): DRAM
I (1670) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM
I (1676) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (1683) heap_init: At 400979C8 len 00008638 (33 KiB): IRAM
I (1690) esp_psram: Adding pool of 4062K of PSRAM memory to heap allocator
I (1698) spi_flash: detected chip: generic
I (1701) spi_flash: flash io: dio

E (1706) flash_encrypt: Flash encryption & Secure Boot together requires FLASH_CRYPT_CNT efuse to be write protected. Fixing now...
I (1718) efuse: BURN BLOCK0
I (1733) efuse: BURN BLOCK0 - OK (all write block bits are set)
E (1733) flash_encrypt: Flash encryption settings error: app is configured for RELEASE but efuses are set for DEVELOPMENT
E (1742) flash_encrypt: Mismatch found in security options in bootloader menuconfig and efuse settings. Device is not secure.

assert failed: do_core_init startup.c:392 (err == ESP_OK && "Failed to disable ROM download mode")


Backtrace: 0x40081cf6:0x3ffe29d0 0x4008c279:0x3ffe29f0 0x40091e55:0x3ffe2a10 0x400d428a:0x3ffe2b30 0x40081901:0x3ffe2b70 0x40079c29:0x3ffe2ba0 |<-CORRUPTED
--- 0x40081cf6: panic_abort at /home/dizcza/tools/esp-idf/components/esp_system/panic.c:466
0x4008c279: esp_system_abort at /home/dizcza/tools/esp-idf/components/esp_system/port/esp_system_chip.c:84
0x40091e55: __assert_func at /home/dizcza/tools/esp-idf/components/newlib/assert.c:81
0x400d428a: do_core_init at /home/dizcza/tools/esp-idf/components/esp_system/startup.c:311
 (inlined by) start_cpu0_default at /home/dizcza/tools/esp-idf/components/esp_system/startup.c:483
0x40081901: call_start_cpu0 at /home/dizcza/tools/esp-idf/components/esp_system/port/cpu_start.c:724
Now I cannot disable ROM download mode because it's write-protected. I can manually disable DISABLE_DL_ENCRYPT, if I want.

Code: Select all

Security fuses:
UART_DOWNLOAD_DIS (BLOCK0)                         Disable UART download mode. Valid for ESP32 V3 and = False R/- (0b0)
                                                    newer; only                                      
ABS_DONE_0 (BLOCK0)                                Secure boot V1 is enabled for bootloader image     = False R/W (0b0)
ABS_DONE_1 (BLOCK0)                                Secure boot V2 is enabled for bootloader image     = True R/W (0b1)
DISABLE_DL_ENCRYPT (BLOCK0)                        Disable flash encryption in UART bootloader        = False R/W (0b0)
DISABLE_DL_DECRYPT (BLOCK0)                        Disable flash decryption in UART bootloader        = True R/W (0b1)
KEY_STATUS (BLOCK0)                                Usage of efuse block 3 (reserved)                  = False R/W (0b0)
SECURE_VERSION (BLOCK3)                            Secure version for anti-rollback                   = 0 R/W (0x00000000)
BLOCK1 (BLOCK1)                                    Flash encryption key                              
I found the corresponding code in the "startup.c" that causes this error:

Code: Select all

395 #if CONFIG_SECURE_ENABLE_SECURE_ROM_DL_MODE
396     err = esp_efuse_enable_rom_secure_download_mode();
397     assert(err == ESP_OK && "Failed to enable Secure Download mode");
398 #endif
Questions:
  • Why does ESP fail to burn the DISABLE_DL_ENCRYPT eFuse? I think I'm following the guidelines correctly. And I don't find troubleshooting in the docs for this reason.
  • Why does it become write-protected? I am not doing it manually.
  • Could it be that during the fixing "E (1706) flash_encrypt: Flash encryption & Secure Boot together requires FLASH_CRYPT_CNT efuse to be write protected. Fixing now..." the DISABLE_DL_ENCRYPT eFuse gets write-protected as well?
  • In case ROM download mode is disabled, I cannot use

    Code: Select all

    espefuse.py summary
    , can I?
This is the second device that got bricked for this reason and 5th in total trying to get the Release mode working. The Flash Encryption Dev mode isn't a problem.

dizcza
Posts: 61
Joined: Tue Sep 07, 2021 6:59 pm

Re: Failed to disable ROM download mode

Postby dizcza » Sat Feb 22, 2025 6:29 pm

All right, I managed to manually burn the relevant eFuses. Here is what I did. Firstly, I enable Secure Boot V2 and Flash Encryption Development mode. Then

Code: Select all

idf.py erase-flash -p $PORT
idf.py bootloader
esptool.py --chip esp32 --port=$PORT --before=default_reset --after=no_reset write_flash --flash_mode dio --flash_freq 80m --flash_size keep 0x1000 build/bootloader/bootloader.bin
idf.py flash monitor
espefuse.py --port $PORT burn_efuse FLASH_CRYPT_CNT 127
espefuse.py --port $PORT burn_efuse DISABLE_DL_ENCRYPT
espefuse.py --port $PORT write_protect_efuse MAC
espefuse.py --port $PORT burn_efuse UART_DOWNLOAD_DIS
After that, I see the log "flash_encrypt: Flash encryption mode is RELEASE". Done. It looks easy when you know the correct order of commands.

I still don't know why esp_efuse_enable_rom_secure_download_mode failed and the following assert made UART_DOWNLOAD_DIS write-protected. Looks like a bug on the ESP side (because I manually burn them without a problem).

Now I have two devices with Secure Boot v2 + Flash Encryption Release + NVS keys encryption but UART ROM download not disabled. What security risks does non-disabled UART_DOWNLOAD_DIS eFuse pose in my configuration? Assuming an adversary has physical access, would they be able to download the encrypted firmware and that's it?

Mahavir
Espressif staff
Espressif staff
Posts: 194
Joined: Wed Jan 24, 2018 6:51 am

Re: Failed to disable ROM download mode

Postby Mahavir » Thu Feb 27, 2025 8:47 am

Hello,

To switch from the flash encryption development to release mode, we recommend using API `esp_flash_encryption_set_release_mode`. This API can be called in the application startup sequence and it shall take care of burning all necessary efuses required for the release mode. (https://github.com/espressif/esp-idf/bl ... C6-L219C43)

Why does ESP fail to burn the DISABLE_DL_ENCRYPT eFuse? I think I'm following the guidelines correctly. And I don't find troubleshooting in the docs for this reason.
Probably you mean the field UART_DOWNLOAD_DIS here (and not DISABLE_DL_ENCRYPT).

For ESP32 V3 silicon write protecting the `FLASH_CRYPT_CNT` field also prevents disabling the UART download mode. Please see the documentation here: https://github.com/espressif/esp-idf/bl ... #L147-L149

Why does it become write-protected? I am not doing it manually.
This happens because the flash encryption related checks in the IDF startup code happens before the UART DL mode disable operation. We will have to avoid write protecting the FLASH_CRYPT_CNT field for ESP32 V3 case in our startup code (instead can exhaust all bits from this field).
Could it be that during the fixing "E (1706) flash_encrypt: Flash encryption & Secure Boot together requires FLASH_CRYPT_CNT efuse to be write protected. Fixing now..." the DISABLE_DL_ENCRYPT eFuse gets write-protected as well?
Yes, right.
In case ROM download mode is disabled, I cannot use `espefuse.py summary`?
No. Even the reflash over UART port using esptool won't work.
Now I have two devices with Secure Boot v2 + Flash Encryption Release + NVS keys encryption but UART ROM download not disabled. What security risks does non-disabled UART_DOWNLOAD_DIS eFuse pose in my configuration? Assuming an adversary has physical access, would they be able to download the encrypted firmware and that's it?
Keeping UART DL mode enabled can allow someone with the physical access to device to download and execute arbitrary stub code (from internal RAM). Secure boot verification does not happen for the code downloaded over UART DL mode.

Hope this helps!

dizcza
Posts: 61
Joined: Tue Sep 07, 2021 6:59 pm

Re: Failed to disable ROM download mode

Postby dizcza » Thu Feb 27, 2025 9:08 am

Thanks for the clarification, ESP_Mahavir.

I hope your next esp-idf release will mind the ESP32 V3 revision and call the esp_efuse_disable_rom_download_mode before write-protecting FLASH_CRYPT_CNT.

Either way, I find keeping the source code in the development mode (both flash encryption and keeping UART ROM download enabled) the safest way. Because I can manually burn eFuses with the esptool command rather than relying on the esp side to handle it for me on the next start-up with Release mode enabled.

Who is online

Users browsing this forum: Baidu [Spider], Bing [Bot], PetalBot, Qwantbot and 10 guests