FE I rephrase my question

Nespressif
Posts: 89
Joined: Tue Sep 12, 2017 11:25 am

FE I rephrase my question

Postby Nespressif » Mon Feb 24, 2025 9:35 am

Hello everyone, I briefly rephrase my question to see if any security experts can answer me. Thank you.

If I enable in menuconfig the flash encryption (checking option enable app encryption only), in development mode and without disabling the uart rom download mode, Could someone decrypt the app code to copy it?

ESP-IDF v5.4 stable ---target ESP32 Rev v1.1 to v3.1
ESP32 generated key burned in flash_encryption (block1)
Enable flash encryption on boot
Development mode
UART ROM download mode enabled

Nespressif
Posts: 89
Joined: Tue Sep 12, 2017 11:25 am

Re: FE I rephrase my question

Postby Nespressif » Wed Feb 26, 2025 7:14 am

I understand that without a copy of the encryption key the app cannot be decrypted.

https://docs.espressif.com/projects/esp ... ting-files
Manually encrypting or decrypting files requires the flash encryption key to be pre-burned in eFuse (see Using Host Generated Key) and a copy to be kept on the host.

Sprite
Espressif staff
Espressif staff
Posts: 10593
Joined: Thu Nov 26, 2015 4:08 am

Re: FE I rephrase my question

Postby Sprite » Thu Feb 27, 2025 12:38 am

I don't think it should be trivially possible: download mode only allows you access to the plain flash, not the unencrypted contents. Note that if an attacker somehow manages to get code execution on your ESP32, they can still read out the unencrypted contents: to lower that chance, we recommend enabling secureboot and disabling download mode.

Note that 'development mode' may still allow flashing plaintext code to the ESP32s flash, where the bootloader will transparently encrypt it. An attacker could use this to upload a tiny program that reads out the rest of the flash, thereby giving them a large part (but not all) of the unencrypted firmware. Read the esp-idf documentation for details, I'm not 100% familiar with what features get enabled when.

Nespressif
Posts: 89
Joined: Tue Sep 12, 2017 11:25 am

Re: FE I rephrase my question

Postby Nespressif » Thu Feb 27, 2025 10:50 am

I don't think it should be trivially possible: download mode only allows you access to the plain flash, not the unencrypted contents. Note that if an attacker somehow manages to get code execution on your ESP32, they can still read out the unencrypted contents: to lower that chance, we recommend enabling secureboot and disabling download mode.

Note that 'development mode' may still allow flashing plaintext code to the ESP32s flash, where the bootloader will transparently encrypt it. An attacker could use this to upload a tiny program that reads out the rest of the flash, thereby giving them a large part (but not all) of the unencrypted firmware. Read the esp-idf documentation for details, I'm not 100% familiar with what features get enabled when.
Hello ESP_Sprite, first of all thank you for your reply. I have already read and reread the security guide in the documentation several times. And I am quite clear, with this configuration a hacker could install software on the Esp32, the hacker could also read the contents of the flash both encrypted and unencrypted, but this does not matter to me, because what the hacker could not decrypt the app that is encrypted without having the key and that is what is important to me in this project.

If anyone has anything else to tell me, I would be very grateful.

Cheers

Sprite
Espressif staff
Espressif staff
Posts: 10593
Joined: Thu Nov 26, 2015 4:08 am

Re: FE I rephrase my question

Postby Sprite » Fri Feb 28, 2025 12:42 am

the hacker could also read the contents of the flash both encrypted and unencrypted,
[...]
because what the hacker could not decrypt the app that is encrypted without having the key and that is what is important to me in this project.
I don't get your reasoning. Given the fact that the app is per definition written to flash, doesn't the capability to read out the flash decrypted mean you can read out the app decrypted?

Nespressif
Posts: 89
Joined: Tue Sep 12, 2017 11:25 am

Re: FE I rephrase my question

Postby Nespressif » Fri Feb 28, 2025 7:01 am

the hacker could also read the contents of the flash both encrypted and unencrypted,
[...]
because what the hacker could not decrypt the app that is encrypted without having the key and that is what is important to me in this project.
I don't get your reasoning. Given the fact that the app is per definition written to flash, doesn't the capability to read out the flash decrypted mean you can read out the app decrypted?
All right, I will try to explain my reasoning better. When I enabled flash encryption, in development mode, and did not disable uart download mode, build and flash, the encryption key was generated and burned internally and the app partition was encrypted, at the next boot. So even if someone reads the flash in whole or in part, they will not be able to decrypt the app as they don't have the encryption key.

The app is written in flash, but is encrypted. If you read the flash through uart, you will read the encrypted app and you will not be able to decrypt it without the encryption key, which is burned into the efuse block1 and is not accessible. The only way to decrypt it, as the documentation says, is with an external copy of the key, but that copy does not exist.

Sprite
Espressif staff
Espressif staff
Posts: 10593
Joined: Thu Nov 26, 2015 4:08 am

Re: FE I rephrase my question

Postby Sprite » Fri Feb 28, 2025 8:03 am

All right, I will try to explain my reasoning better. When I enabled flash encryption, in development mode, and did not disable uart download mode, build and flash, the encryption key was generated and burned internally and the app partition was encrypted, at the next boot. So even if someone reads the flash in whole or in part, they will not be able to decrypt the app as they don't have the encryption key.

The app is written in flash, but is encrypted. If you read the flash through uart, you will read the encrypted app and you will not be able to decrypt it without the encryption key, which is burned into the efuse block1 and is not accessible. The only way to decrypt it, as the documentation says, is with an external copy of the key, but that copy does not exist.
No. The 'in development mode' is important here. As the docs state:
Development Mode - recommended for use only during development. In this mode, it is still possible to flash new plaintext firmware to the device, and the bootloader will transparently encrypt this firmware using the key stored in hardware. This allows, indirectly, to read out the plaintext of the firmware in flash.
Specifically, an attacker could use the UART to overwrite a tiny bit of your code with their own program, in plaintext. The bootloader would notice, and (because developer mode) encrypts this tiny program; the ESP32 will happily run from it (because secureboot is not enabled). The tiny program can now read out the rest of the flash, and since it's a program running within the ESP32, the ESP32 does the decryption on-the-fly. The ESP32 acts as an 'oracle' here: even if it's not possible to get the decryption key, you can let the ESP32 do the decryption for you.

Nespressif
Posts: 89
Joined: Tue Sep 12, 2017 11:25 am

Re: FE I rephrase my question

Postby Nespressif » Fri Feb 28, 2025 9:56 am

Specifically, an attacker could use the UART to overwrite a tiny bit of your code with their own program, in plaintext. The bootloader would notice, and (because developer mode) encrypts this tiny program; the ESP32 will happily run from it (because secureboot is not enabled). The tiny program can now read out the rest of the flash, and since it's a program running within the ESP32, the ESP32 does the decryption on-the-fly. The ESP32 acts as an 'oracle' here: even if it's not possible to get the decryption key, you can let the ESP32 do the decryption for you.
Thank you very much ESP_Sprite, now I understand your explanation perfectly, it is not easy but you could decrypt the flash using a kind of trojan.
For this reason, once I have verified that my app works correctly and is encrypted (in development mode) as a last step I burn the security efuses and verify that nothing can be flashed anymore.

Code: Select all

=== Run "summary" command ===
EFUSE_NAME (Block) Description  = [Meaningful Value] [Readable/Writeable] (Hex Value)
----------------------------------------------------------------------------------------
Calibration fuses:
ADC_VREF (BLOCK0)                                  True ADC reference voltage                         = 1149 R/W (0b00111)

Config fuses:
WR_DIS (BLOCK0)                                    Efuse write disable mask                           = 128 R/W (0x0080)
RD_DIS (BLOCK0)                                    Disable reading from BlOCK1-3                      = 1 R/W (0x1)
DISABLE_APP_CPU (BLOCK0)                           Disables APP CPU                                   = False R/W (0b0)
DISABLE_BT (BLOCK0)                                Disables Bluetooth                                 = False R/W (0b0)
DIS_CACHE (BLOCK0)                                 Disables cache                                     = False R/W (0b0)
CHIP_CPU_FREQ_LOW (BLOCK0)                         If set alongside EFUSE_RD_CHIP_CPU_FREQ_RATED; the = False R/W (0b0)
                                                    ESP32's max CPU frequency is rated for 160MHz. 24
                                                   0MHz otherwise                                    
CHIP_CPU_FREQ_RATED (BLOCK0)                       If set; the ESP32's maximum CPU frequency has been = True R/W (0b1)
                                                    rated                                            
BLK3_PART_RESERVE (BLOCK0)                         BLOCK3 partially served for ADC calibration data   = False R/W (0b0)
CLK8M_FREQ (BLOCK0)                                8MHz clock freq override                           = 54 R/W (0x36)
VOL_LEVEL_HP_INV (BLOCK0)                          This field stores the voltage level for CPU to run = 0 R/W (0b00)
                                                    at 240 MHz; or for flash/PSRAM to run at 80 MHz.0
                                                   x0: level 7; 0x1: level 6; 0x2: level 5; 0x3: leve
                                                   l 4. (RO)                                         
CODING_SCHEME (BLOCK0)                             Efuse variable block length scheme                
   = NONE (BLK1-3 len=256 bits) R/W (0b00)
CONSOLE_DEBUG_DISABLE (BLOCK0)                     Disable ROM BASIC interpreter fallback             = True R/W (0b1)
DISABLE_SDIO_HOST (BLOCK0)                                                                            = False R/W (0b0)
DISABLE_DL_CACHE (BLOCK0)                          Disable flash cache in UART bootloader             = True R/W (0b1)

Flash fuses:
FLASH_CRYPT_CNT (BLOCK0)                           Flash encryption is enabled if this field has an o = 1 R/W (0b0000001)
                                                   dd number of bits set                             
FLASH_CRYPT_CONFIG (BLOCK0)                        Flash encryption config (key tweak bits)           = 15 R/W (0xf)

Identity fuses:
CHIP_PACKAGE_4BIT (BLOCK0)                         Chip package identifier #4bit                      = False R/W (0b0)
CHIP_PACKAGE (BLOCK0)                              Chip package identifier                            = 0 R/W (0b000)
CHIP_VER_REV1 (BLOCK0)                             bit is set to 1 for rev1 silicon                   = True R/W (0b1)
CHIP_VER_REV2 (BLOCK0)                                                                                = False R/W (0b0)
WAFER_VERSION_MINOR (BLOCK0)                                                                          = 1 R/W (0b01)
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)                               

Jtag fuses:
JTAG_DISABLE (BLOCK0)                              Disable JTAG                                       = True R/W (0b1)

Mac fuses:
MAC (BLOCK0)                                       MAC address                                       
   = 88:13:bf:97:d1:e0 (CRC 0x55 OK) R/W 
MAC_CRC (BLOCK0)                                   CRC8 for MAC address                               = 85 R/W (0x55)
MAC_VERSION (BLOCK3)                               Version of the MAC field                           = 0 R/W (0x00)

Security fuses:
UART_DOWNLOAD_DIS (BLOCK0)                         Disable UART download mode. Valid for ESP32 V3 and = True R/W (0b1)
                                                    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     = False R/W (0b0)
DISABLE_DL_ENCRYPT (BLOCK0)                        Disable flash encryption in UART bootloader        = True R/W (0b1)
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                              
   = ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? -/- 
BLOCK2 (BLOCK2)                                    Security boot 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 
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 

Spi Pad fuses:
SPI_PAD_CONFIG_HD (BLOCK0)                         read for SPI_pad_config_hd                         = 0 R/W (0b00000)
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_CS0 (BLOCK0)                        Override SD_CMD pad (GPIO11/SPICS0)                = 0 R/W (0b00000)

Vdd fuses:
XPD_SDIO_REG (BLOCK0)                              read for XPD_SDIO_REG                              = False R/W (0b0)
XPD_SDIO_TIEH (BLOCK0)                             If XPD_SDIO_FORCE & XPD_SDIO_REG                   = 1.8V R/W (0b0)
XPD_SDIO_FORCE (BLOCK0)                            Ignore MTDI pin (GPIO12) for VDD_SDIO on reset     = False R/W (0b0)
I think it is properly protected this way, although I know it is not the most orthodox way to do it, but if I do it in release mode either from menuconfig or following the workflows, it messes up my chips. I suppose it has something to do with the size of the partitions, but it is something I need to investigate.
Now when I try to flash it tells me this:

Code: Select all

A fatal error occurred: This chip has encrypt functionality in UART download mode disabled. This is the Flash Encryption configuration for Production mode instead of Development mode.
CMake Error at run_serial_tool.cmake:67 (message):

Who is online

Users browsing this forum: Baidu [Spider] and 12 guests