Flash Encryption Process

After flashing the plaintext firmware to the device with flash encryption enabled for the first time, and subsequently starting the device, the flash encryption feature will be automatically enabled. The following outlines the basic workflow for the initial automatic enabling of flash encryption:

  1. Firmware bootloader reads the SPI_BOOT_CRYPT_CNT eFuse value. If flash encryption is not enabled, the bootloader will enable flash encryption. By default, the value is 0, meaning flash encryption is not enabled yet.

  2. Bootloader checks if BLOCK_KEY stores the flash encryption key. If the key is not pre-flashed (see Section 13.3.3), it will be generated automatically and written to BLOCK_KEY. The write and read protection bits for BLOCK_KEY will be set, so that software cannot access the key.

  3. Flash encryption block encrypts the flash contents – the firmware bootloader, applications and partitions marked as encrypted.

  4. Firmware bootloader sets the first available bit in SPI_BOOT_CRYPT_CNT to 1 to mark the flash contents as encrypted.

  5. In Development mode, SPI_BOOT_CRYPT_CNT and DIS_DOWNLOAD_MANUAL_ENCRYPT are not write-protected. The firmware bootloader allows to disable flash encryption and re-flash encrypted binaries.

  6. In Release mode, SPI_BOOT_CRYPT_CNT and DIS_DOWNLOAD_MANUAL_ENCRYPT are write-protected. Flash encryption is enabled permanently and re-flashing firmware is forbidden.

  7. The device is rebooted to start executing the encrypted bootloader and app firmware.

📌 Tip

By default, when flash encryption is enabled, some flag bits of eFuse will be set, thus disabling some system functions, such as JTAG. Keeping these system functions may bring security risks. During test phase, if you need to keep these flags, please refer to the instructions related to flash encryption in the ESP-IDF Programming Guide.

With flash encryption enabled, when the device loads and runs encrypted bootloader and app firmware, it first automatically decrypts the data through the hardware module, and then loads the decrypted data into its iRAM and cache. Furthermore, certain APIs are designed to seamlessly handle the encryption and decryption of data when performing read and write operations within encrypted partitions in the flash memory. The APIs responsible for automatic decryption of data include esp_partition_read(), esp_flash_read_encrypted(), and bootloader_flash_read(); the APIs responsible for automatic encryption of data include esp_partition_write(), esp_flash_write_encrypted(), and bootloader_flash_write().

Particularly, with flash encryption enabled, during OTA upgrades, the device receives plaintext data, and then calls esp_partition_write() to automatically encrypt the data before writing it into the flash memory.

📌 Tip

For mass-produced devices, OTA upgrade function can be used to update app firmware remotely, but not the bootloader. Therefore, it is crucial to carefully configure the bootloader settings, including parameters like the log level, before enabling flash encryption.