esp-idf: Flash Encryption is cannot be enabled - SecureBoot Enabled before (IDFGH-9578)

Answers checklist.

  • I have read the documentation ESP-IDF Programming Guide and the issue is not addressed there.
  • I have updated my IDF branch (master or release) to the latest version and checked that the issue is present there.
  • I have searched the issue tracker for a similar issue and not found a similar issue.

IDF version.

ESP-IDF v5.1-dev-3462-g045163a2ec-dirty

Operating System used.

macOS

How did you build your project?

Command line with CMake

If you are using Windows, please specify command line type.

None

Development Kit.

ESP32

Power Supply used.

USB

What is the expected behavior?

I expected that after enabling SecureBoot and then enable FlashEncryption in the IDF-Menuconfig. That the ESP with the newly flashed Bootloader will start the encrpytion process as described in the Manuals.

What is the actual behavior?

The Flash-Encryption is not working. If I try to flash the Image with the --encrypted Option I will get this Log:

Uploading stub...
Running stub...
Stub running...
Changing baud rate to 460800
Changed.
Configuring flash size...
Flash encryption key is not programmed

A fatal error occurred: Can't perform encrypted flash write, consult Flash Encryption documentation for more information
CMake Error at run_serial_tool.cmake:63 (message):
  
 /Users/USERNAME/.espressif/python_env/idf5.1_py3.10_env/bin/python;;/Users/USERNAME/esp/esp-idf/components/esptool_py/esptool/esptool.py;--chip;esp32
  failed.

FAILED: CMakeFiles/encrypted-flash /Users/USERNAME/esp/esp-idf/examples/system/ota/simple_ota_example/build/CMakeFiles/encrypted-flash 
cd /Users/USERNAME/esp/esp-idf/components/esptool_py && /Users/USERNAME/.espressif/tools/cmake/3.24.0/CMake.app/Contents/bin/cmake -D IDF_PATH=/Users/USERNAME/esp/esp-idf -D "SERIAL_TOOL=/Users/USERNAME/.espressif/python_env/idf5.1_py3.10_env/bin/python;;/Users/USERNAME/esp/esp-idf/components/esptool_py/esptool/esptool.py;--chip;esp32" -D "SERIAL_TOOL_ARGS=--before=default_reset;--after=no_reset;write_flash;@encrypted_flash_args" -D WORKING_DIRECTORY=/Users/USERNAME/esp/esp-idf/examples/system/ota/simple_ota_example/build -P /Users/USERNAME/esp/esp-idf/components/esptool_py/run_serial_tool.cmake
ninja: build stopped: subcommand failed

Now then I try to flash it without the --encryped flag it seems to work but in the end its not the case as you can see in the Monitor Log:

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
flash read err, 1000
ets_main.c 371 
ets Jun  8 2016 00:22:57
rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
flash read err, 1000
ets_main.c 371 
ets Jun  8 2016 00:22:57
rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
flash read err, 1000
ets_main.c 371 
ets Jun  8 2016 00:22:57
rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
flash read err, 1000
ets_main.c 371 
ets Jun  8 2016 00:22:57
rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
flash read err, 1000
ets_main.c 371 
ets Jun  8 2016 00:22:57
rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
flash read err, 1000
ets_main.c 371 
ets Jun  8 2016 00:22:57
rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
flash read err, 1000
ets_main.c 371 
ets Jun  8 2016 00:22:57
rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
flash read err, 1000
ets_main.c 371 
ets Jun  8 2016 00:22:57
rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
flash read err, 1000
ets_main.c 371 
ets Jun  8 2016 00:22:57

Steps to reproduce.

So I did this Steps:

  1. Enable SecureBoot
  2. Create Private-Key
  3. Create Bootloader
  4. flash bootloader => Now Secure Boot works only signed binarys are executed
  5. Enable Flash-Encryption
  6. Create new Bootloader
  7. Flash Bootloader
  8. Burn this Efuse: FLASH_CRYPT_CONFIG
  9. Flash-Encrytion should start after next flash.

Debug Logs.

Here you can find the EFuse Summary: 

Calibration fuses:
BLK3_PART_RESERVE (BLOCK0):                        BLOCK3 partially served for ADC calibration data   = False R/W (0b0)
ADC_VREF (BLOCK0):                                 Voltage reference calibration                      = 1107 R/W (0b00001)

Config fuses:
XPD_SDIO_FORCE (BLOCK0):                           Ignore MTDI pin (GPIO12) for VDD_SDIO on reset     = False R/W (0b0)
XPD_SDIO_REG (BLOCK0):                             If XPD_SDIO_FORCE, enable VDD_SDIO reg on reset    = False R/W (0b0)
XPD_SDIO_TIEH (BLOCK0):                            If XPD_SDIO_FORCE & XPD_SDIO_REG                   = 1.8V R/W (0b0)
CLK8M_FREQ (BLOCK0):                               8MHz clock freq override                           = 57 R/W (0x39)
SPI_PAD_CONFIG_CLK (BLOCK0):                       Override SD_CLK pad (GPIO6/SPICLK)                 = 0 R/W (0b00000)
SPI_PAD_CONFIG_Q (BLOCK0):                         Override SD_DATA_0 pad (GPIO7/SPIQ)                = 0 R/W (0b00000)
SPI_PAD_CONFIG_D (BLOCK0):                         Override SD_DATA_1 pad (GPIO8/SPID)                = 0 R/W (0b00000)
SPI_PAD_CONFIG_HD (BLOCK0):                        Override SD_DATA_2 pad (GPIO9/SPIHD)               = 0 R/W (0b00000)
SPI_PAD_CONFIG_CS0 (BLOCK0):                       Override SD_CMD pad (GPIO11/SPICS0)                = 0 R/W (0b00000)
DISABLE_SDIO_HOST (BLOCK0):                        Disable SDIO host                                  = False R/W (0b0)

Efuse fuses:
WR_DIS (BLOCK0):                                   Efuse write disable mask                           = 256 R/W (0x0100)
RD_DIS (BLOCK0):                                   Efuse read disable mask                            = 2 R/W (0x2)
CODING_SCHEME (BLOCK0):                            Efuse variable block length scheme                
   = NONE (BLK1-3 len=256 bits) R/W (0b00)
KEY_STATUS (BLOCK0):                               Usage of efuse block 3 (reserved)                  = False R/W (0b0)

Identity fuses:
MAC (BLOCK0):                                      Factory MAC Address                               
   = 58:bf:25:36:1e:dc (CRC 0x95 OK) R/W 
MAC_CRC (BLOCK0):                                  CRC8 for factory MAC address                       = 149 R/W (0x95)
CHIP_VER_REV1 (BLOCK0):                            Silicon Revision 1                                 = True R/W (0b1)
CHIP_VER_REV2 (BLOCK0):                            Silicon Revision 2                                 = False R/W (0b0)
WAFER_VERSION_MINOR (BLOCK0):                      WAFER VERSION MINOR                                = 0 R/W (0b00)
CHIP_PACKAGE (BLOCK0):                             Chip package identifier                            = 0 R/W (0b000)
CHIP_PACKAGE_4BIT (BLOCK0):                        Chip package identifier #4bit                      = 0 R/W (0b0)
MAC_VERSION (BLOCK3):                              Version of the MAC field                           = 0 R/W (0x00)
WAFER_VERSION_MAJOR (BLOCK0):                      calc WAFER VERSION MAJOR from CHIP_VER_REV1 and CH = 1 R/W (0b001)
                                                   IP_VER_REV2 and apb_ctl_date (read only)          
PKG_VERSION (BLOCK0):                              calc Chip package = CHIP_PACKAGE_4BIT << 3 + CHIP_ = 0 R/W (0x0)
                                                   PACKAGE (read only)                               

Security fuses:
FLASH_CRYPT_CNT (BLOCK0):                          Flash encryption mode counter                      = 1 R/W (0b0000001)
UART_DOWNLOAD_DIS (BLOCK0):                        Disable UART download mode (ESP32 rev3 only)       = False R/W (0b0)
FLASH_CRYPT_CONFIG (BLOCK0):                       Flash encryption config (key tweak bits)           = 15 R/W (0xf)
CONSOLE_DEBUG_DISABLE (BLOCK0):                    Disable ROM BASIC interpreter fallback             = True R/W (0b1)
ABS_DONE_0 (BLOCK0):                               Secure boot V1 is enabled for bootloader image     = True R/W (0b1)
ABS_DONE_1 (BLOCK0):                               Secure boot V2 is enabled for bootloader image     = False R/W (0b0)
JTAG_DISABLE (BLOCK0):                             Disable JTAG                                       = 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        = False R/W (0b0)
DISABLE_DL_CACHE (BLOCK0):                         Disable flash cache in UART bootloader             = False R/W (0b0)
BLOCK1 (BLOCK1):                                   Flash encryption key                              
   = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W 
BLOCK2 (BLOCK2):                                   Secure boot key                                   
   = ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? -/- 
BLOCK3 (BLOCK3):                                   Variable Block 3                                  
   = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W

More Information.

No response

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Comments: 45 (11 by maintainers)

Most upvoted comments

Google…? Disable all insecure options and change from development to production and do all steps again.

@DerPicknicker Is there anything else that we can help you with? or we can close the issue for now?

@DerPicknicker

  1. Please enable required security features through idf.py menuconfig -> Security features
  2. You may keep flash encryption in DEVELOPMENT mode for testing purpose
  3. You may also keep some potentially insecure options enabled, like SECURE_INSECURE_ALLOW_DL_MODE enabled. This is to keep UART DL mode enabled and hence all esptool commands to be supported. Same thing for other options like JTAG etc.
  4. Modify partition table offset, with security features bootloader size increases and hence partition table offset must be increased. Typically 0xd000 offset should work well here.
  5. Build the project
  6. Build system would notify regarding missing signing key and command to generate one. Execute the command to generate the signing key. This is private key which will be used to sign the artifacts but only public key (its digest) would be programmed in the EFuse by bootloader on very 1st boot.
  7. If secure boot is enabled, then bootloader must be flashed separately. Please flash all other artifacts like partition table, application and then bootloader at the very last. Flashing commands would be displayed during the build process.
  8. On the 1st boot, bootloader would verify, configure EFuses and encrypt all partitions. This process may take some time. Once this is over, device should restart and have all security features enabled in the EFuse.

Additionally, we also have a qemu (emulator) fork for ESP32 chip, you may use that to verify the security features workflow. Instructions are available here. Process would then be similar for other chips like ESP32-S3.

Hope this helps!

If I get you correctly I should increase the field to disable the flash-encryption. Then the Encryption process will start automatically, right?

Yes

In option 2) you mentioned flashing the key externally is this a real security issue then I go to release later? I want the highest possible security to protect my Code and prevent flashing unofficial firmware.

If you generate per device unique key and carefully destroy it once its programmed in the device then it should not result in any security issue. Of-course, enabling flash encryption release mode through bootloader is more convenient option but here we are trying to recover this device first.