Understanding the flash protection in development mode

ahmedwahdan
Posts: 9
Joined: Mon Jan 04, 2021 4:32 pm

Understanding the flash protection in development mode

Postby ahmedwahdan » Tue Mar 23, 2021 11:14 pm

Hello,

I enabled the flash protection with pre-generated key.
And this is my config

Code: Select all

Detecting chip type... ESP32
espefuse.py v3.0
EFUSE_NAME (Block)                       Description  = [Meaningful Value] [Readable/Writeable] (Hex Value)
----------------------------------------------------------------------------------------
Calibration fuses:
BLK3_PART_RESERVE (BLOCK0):              BLOCK3 partially served for ADC calibration data   = False R/W (0b0)
ADC_VREF (BLOCK0):                       Voltage reference calibration                      = 1100 R/W (0b00000)

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                           = 48 R/W (0x30)
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                           = 128 R/W (0x0080)
RD_DIS (BLOCK0):                         Efuse read disable mask                            = 1 R/W (0x1)
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                               
   = 30:ae:a4:22:ce:80 (CRC 0xe4 OK) R/W 
MAC_CRC (BLOCK0):                        CRC8 for factory MAC address                       = 228 R/W (0xe4)
CHIP_VER_REV1 (BLOCK0):                  Silicon Revision 1                                 = True R/W (0b1)
CHIP_VER_REV2 (BLOCK0):                  Silicon Revision 2                                 = False R/W (0b0)
CHIP_VERSION (BLOCK0):                   Reserved for future chip versions                  = 0 R/W (0b00)
CHIP_PACKAGE (BLOCK0):                   Chip package identifier                            = 0 R/W (0b000)
MAC_VERSION (BLOCK3):                    Version of the MAC field                           = 0 R/W (0x00)

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     = False R/W (0b0)
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        = True R/W (0b1)
DISABLE_DL_CACHE (BLOCK0):               Disable flash cache in UART bootloader             = True R/W (0b1)
BLOCK1 (BLOCK1):                         Flash encryption key                              
   = ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? -/- 
BLOCK2 (BLOCK2):                         Secure 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 
The point that I don't understand here that the flashing only works when using:
idf.py encrypted-flash but idf.py flash doesn't work, what is the difference?
I don't provide the key with the encrypted** option, so what is the difference here?

Regards,
Wahdan

ESP_Angus
Posts: 2344
Joined: Sun May 08, 2016 4:11 am

Re: Understanding the flash protection in development mode

Postby ESP_Angus » Tue Mar 23, 2021 11:33 pm

Hi Wahdan,

The difference between Development and Release mode is that this efuse is not burned: DISABLE_DL_ENCRYPT

This means that when the chip boots into download mode, the internal hardware of the ESP32 is still able to encrypt data when writing it to flash. The key isn't needed for this because the encryption happens inside the ESP32. i.e. esptool.py sends plaintext to the ESP32, and tells it "encrypt this when you write it".

In release mode, the DISABLE_DL_ENCRYPT efuse is burned so the ESP32 isn't able to encrypt anything when in download mode.

The "idf.py flash" and "idf.py encrypted-flash" targets are separate because esptool has to differentiate between which flashing command to send, and currently this happens via a command line option which is chosen from the target. We might be able to improve the "idf.py flash" target in the future so it can detect the chip is already encrypted and make an encrypted flash, but currently the build+flash system is not this sophisticated.

Development Mode is not secure because an attacker can write a small program that dumps the flash contents (with decryption), flash it, and boot it[*]. However it gives an option to work with flash encryption while developing, and either burn this efuse or switch the config to Release Mode once ready for production.

You can read more about development and release mode here:
https://docs.espressif.com/projects/esp ... pment-mode

[*] If you also enable Secure Boot in development mode then it gives some protection against this specific attack, but in general it should be considered insecure whenever Development Mode is on and production devices should use flash encryption in Release Mode.

ahmedwahdan
Posts: 9
Joined: Mon Jan 04, 2021 4:32 pm

Re: Understanding the flash protection in development mode

Postby ahmedwahdan » Thu Oct 28, 2021 3:43 pm

Thanks @ESP_Angus for your response. You cleared this point out.
I have another question related to Nvs and Nvs encryption.
I know that it's needed to have separate partition to hold keys used for encrypting the Nvs itself.

My configuration is like that:

Code: Select all

# Name,   Type, SubType, Offset,  Size, Flags
# Note: Firmware partition offset needs to be 64K aligned, initial 49K (16 sectors) are reserved for bootloader and partition table
sec_cert   , 0x3F,          , 0xe000    , 0x3000,           ,  # Never mark this as an encrypted partition
nvs        , data, nvs      , 0x11000   , 0x6000, 
otadata    , data, ota      , 0x17000   , 0x2000, encrypted
phy_init   , data, phy      , 0x19000   , 0x1000, encrypted
ota_0      , app , ota_0    , 0x20000   , 4992K , 
ota_1      , app , ota_1    , 0x500000  , 4992K , 
factory_nvs, data, nvs      , 0x9f2000  , 0x6000, 
nvs_keys   , data, nvs_keys , 0x9f8000  , 0x1000, encrypted
1- Do I need to mark (otadata and phy_init) as encrypted?
2- I have factory_nvs, sec_cert, and nvs, Do I need nvs_keys partition for every partition on Nvs?
3- I will write some information during production (UID, Tokens, ...), and later I will have some information like (Provisioning data, run time settings, ...) so Do I need to generate the keys and encrypt the data before flashing at production, or the ESP will generate the keys and handle both factory and run-time data?
4- Any step order to follow to have Nvs encryption along with encryption and secure boot?

Regards,
Wahdan

Who is online

Users browsing this forum: No registered users and 141 guests