Flash Encryption Key Storage

The flash encryption key is stored in BLOCK_KEY. There are two methods to write the key into eFuse:

Manual method

Use espsecure.py to manually generate a key and write it into eFuse. This method can only be used before enabling flash encryption for the first time.

Automatic method

After flash encryption is enabled in menuconfig, the device will automatically generate a key in the bootloader when it starts up for the first time, and automatically save the key in eFuse.

To manually write the flash encryption key into eFuse, first run the following command to generate the key:

$ espsecure.py generate_flash_encryption_key my_flash_encryption_key.bin

Then, run the following command to write the key into eFuse:

$ espefuse.py --port PORT burn_key BLOCK my_flash_encryption_key.bin XTS_AES_128_KEY

📌 Tip

Since writing eFuse is irreversible, manual writing of the key into eFuse can only be performed once.

Flash encryption can be enabled through menuconfig → Security features → Enable flash encryption on boot. If flash encryption is enabled in building stage and the key has not been manually written into eFuse in advance, then after the firmware is flashed, the device will enable flash encryption, automatically generate a key, and write it into eFuse.

The main difference between the manual method and automatic method is that with the manual method, you can know the content of the key and use a script tool to encrypt the data before flashing it into the device. With the automatic method, if the read protection of BLOCK_KEY is enabled in the eFuse (which is enabled by default), the key is generated inside the device and stored directly in the read-protected eFuse, making it impossible for external developers to obtain the key or manually encrypt/decrypt the data.

In manual mode, use the following command to encrypt the app firmware, and flash it to the device:

$ espsecure.py encrypt_flash_data --aes_xts --keyfile /path/to/key.bin --address 0x10000 --output my-app-ciphertext.bin build/my-app

It is important to note that when using the aforementioned command for data encryption, you must specify the storage address of the data in the partition table. In the command provided, the data being encrypted is my-app, with its address set to 0x10000. As emphasised in Section 13.3.2, flash encryption relies on the tweakable block cipher AES-XTS, and therefore, the accurate data address must be specified. Failure to specify or incorrectly specifying the address will result in device failure after flashing the encrypted firmware.

Furthermore, it is worth mentioning that if the encryption key is known, the script tool espsecure.py can also be used to decrypt the data. Running the command espsecure.py-h will provide helpful information regarding the usage of the script tool.

During the mass production of devices, it is highly recommended to utilise the automatic method for key writing. This ensures that each device is assigned a unique key that remains inaccessible from external sources, thus maximising the overall security of the device.