HostBaseEncryption ESP32
HostBaseEncryption ESP32
Introduction
It is recommended to have an uninterrupted power supply while enabling security features on
ESP32 SoCs. Power failures during the secure manufacturing process could cause issues that
are hard to debug and, in some cases, may cause permanent boot-up failures.
This guide highlights an approach where security features are enabled with the assistance of an
external host machine. Security workflows are broken down into various stages and key
material is generated on the host machine; thus, allowing greater recovery chances in case of
power or other failures. It also offers better timings for secure manufacturing, e.g., in the case of
encryption of firmware on the host machine vs. on the device.
Goals
1. Simplify the traditional workflow with stepwise instructions.
2. Design a more flexible workflow as compared to the traditional firmware-based workflow.
3. Improve reliability by dividing the workflow into small operations.
4. Eliminate dependency on Second Stage Bootloader (firmware bootloader).
Pre-requisite
esptool : Please make sure the esptool has been installed. It can be installed by running:
Scope
Important
It is recommended to enable both Flash Encryption and Secure Boot V2 for a production
use case.
When enabling the Flash Encryption and Secure Boot V2 externally we need to enable them in
the following order:
1. Enable the Flash Encryption feature by following the steps listed in Enable Flash Encryption
Externally.
2. Enable the Secure Boot V2 feature by following the steps listed in Enable Secure Boot V2
Externally.
To enable the Secure Boot (SB) V2, it is necessary to keep the SB V2 key readable. To protect
the key's readability, the write protection for RD_DIS ( ESP_EFUSE_WR_DIS_RD_DIS ) is applied.
However, this action poses a challenge when attempting to enable Flash Encryption, as the
Flash Encryption (FE) key needs to remain unreadable. This conflict arises because the RD_DIS
is already write-protected, making it impossible to read protect the FE key.
In this case, all the eFuses related to flash encryption are written with help of the espefuse tool.
More details about flash encryption can be found in the Flash Encryption Guide
1. Ensure that you have an ESP32-S2 device with default flash encryption eFuse settings as
shown in Relevant eFuses.
In this case, the flash on the chip must be erased and flash encryption must not be enabled.
The chip can be erased by running:
where BLOCK is a free keyblock between BLOCK_KEY0 and BLOCK_KEY5 . And KEYPURPOSE is
either XTS_AES_256_KEY_1 , XTS_AES_256_KEY_2 , XTS_AES_128_KEY . See ESP32-S2 Technical
Reference Manual for a description of the key purposes.
If you wish to specify exactly which two blocks are used then it is possible to divide the key
into two 256-bit keys, and manually burn each half with XTS_AES_256_KEY_1 and
XTS_AES_256_KEY_2 as key purposes:
split -b 32 my_flash_encryption_key.bin my_flash_encryption_key.bin
espefuse.py --port PORT burn_key BLOCK my_flash_encryption_key.bin.aa XTS_AES_256_KEY_1
espefuse.py --port PORT burn_key BLOCK+1 my_flash_encryption_key.bin.ab XTS_AES_256_KEY_2
If you only want to enable flash encryption in Development mode and want to keep the
ability to disable it in the future, Update the SPI_BOOT_CRYPT_CNT value in the below
command from 7 to 0x1 (not recommended for production).
Note
At this point, the flash encryption on the device has been enabled. You may test the
flash encryption process as given in step 5. Please note that the security-related eFuses
have not been burned at this point. It is recommended that they should be burned in
production use cases as explained in step 6.
The bootloader and the application binaries for the project must be built with Flash
Encryption Release mode with default configurations.
The above files can then be flashed to their respective offset using esptool.py . To see all of
the command line options recommended for esptool.py , see the output printed when
idf.py build succeeds. In the above command the offsets are used for a sample firmware,
the actual offset for your firmware can be obtained by checking the partition table entry or
by running idf.py partition-table. When the application contains the following partition:
otadata , nvs_encryption_keys they need to be encrypted as well. Please refer to Encrypted
Partitions for more details about encrypted partitions.
Note
If the flashed ciphertext file is not recognized by the ESP32-S2 when it boots, check that
the keys match and that the command line arguments match exactly, including the
correct offset. It is important to provide the correct offset as the ciphertext changes
when the offset changes.
The command espsecure.py decrypt_flash_data can be used with the same options (and
different input/output files), to decrypt ciphertext flash contents or a previously encrypted
file.
Important
For production use cases, it is highly recommended to burn all the eFuses listed
below.
Note
Please update the EFUSE_NAME with the eFuse that you need to burn. Multiple
eFuses can be burned at the same time by appending them to the above command
(e.g., EFUSE_NAME VAL EFUSE_NAME2 VAL2). More documentation about
espefuse.py can be found here.
Note
The write protection of above eFuse also write protects multiple other eFuses, Please
refer to the ESP32-S2 eFuse table for more details.
Warning
Please burn the following bit at the very end. After this bit is burned, the espefuse
tool can no longer be used to burn additional eFuses.
Important
Once the flash encryption has been enabled for the device, the key must be deleted
immediately. This ensures that the host cannot produce encrypted binaries for the
same device going forward. This step is important to reduce the vulnerability of the
flash encryption key.
It is recommended to generate a unique flash encryption key for each device for production
use-cases.
It is recommended to ensure that the RNG used by host machine to generate the flash
encryption key has good entropy.
See Limitations of Flash Encryption for more details.
In this workflow, we shall use espsecure tool to generate signing keys and use the espefuse
tool to burn the relevant eFuses. The details about the Secure Boot V2 process can be found at
Secure Boot V2 Guide
The Secure Boot V2 signing key for the RSA3072 scheme can be generated by running:
A total of 3 keys can be used for Secure Boot V2 at once. These should be computed
independently and stored separately. The same command with different key file names can
be used to generate multiple Secure Boot V2 signing keys. It is recommended to use
multiple keys in order to reduce dependency on a single key.
The public key digest for the private key generated in the previous step can be generated by
running:
In case of multiple digests, the other digests can be burned sequentially by changing the key
purpose to SECURE_BOOT_DIGEST1 and SECURE_BOOT_DIGEST2 respectively.
Note
At this stage the secure boot V2 has been enabled for the ESP32-S2. The ROM
bootloader shall now verify the authenticity of the Second Stage Bootloader on every
bootup. You may test the secure boot process by executing Steps 5 & 6. Please note that
security-related eFuses have not been burned at this point. For production use cases, all
security-related eFuses must be burned as given in step 7.
By default, the ROM bootloader would only verify the Second Stage Bootloader (firmware
bootloader). The firmware bootloader would verify the app partition only when the
CONFIG_SECURE_BOOT option is enabled (and CONFIG_SECURE_BOOT_VERSION is set
to SECURE_BOOT_V2_ENABLED ) while building the bootloader.
a. Open the Project Configuration Menu, in "Security features" set "Enable hardware
Secure Boot in bootloader" to enable Secure Boot.
The "Secure Boot V2" option will be selected and the "App Signing Scheme" will be set to
RSA by default.
The Secure Boot V2 workflow only verifies the bootloader and application binaries, hence
only those binaries need to be signed. The other binaries (e.g., partition-table.bin ) can be
flashed as they are generated in the build stage.
If multiple keys secure boot keys are to be used then the same signed binary can be
appended with a signature block signed with the new key as follows:
The same process can be repeated for the third key. Note that the names of the input and
output files must not be the same.
The above files along with other binaries (e.g., partition table) can then be flashed to their
respective offset using esptool.py . To see all of the command line options recommended
for esptool.py , see the output printed when idf.py build succeeds. The flash offset for
your firmware can be obtained by checking the partition table entry or by running idf.py
partition-table .
For production use cases, it is highly recommended to burn all the eFuses listed
below.
Note
Please update the EFUSE_NAME with the eFuse that you need to burn. Multiple
eFuses can be burned at the same time by appending them to the above command
(e.g., EFUSE_NAME VAL EFUSE_NAME2 VAL2). More documentation about
espefuse.py can be found here
The secure boot digest burned in the eFuse must be kept readable otherwise secure
boot operation would result in a failure. To prevent the accidental enabling of read
protection for this key block we need to burn the following eFuse:
Important
After this eFuse has been burned, read protection cannot be enabled for any key.
E.g., if flash encryption which requires read protection for its key is not enabled at
this point then it cannot be enabled afterwards. Please ensure that no eFuse keys are
going to need read protection after this.
2. Revoke key digests:
The unused digest slots need to be revoked when we are burning the secure boot key.
The respective slots can be revoked by running
Warning
Please burn the following bit at the very end. After this bit is burned, the espefuse
tool can no longer be used to burn additional eFuses.
It is recommended to store the secure boot key in a highly secure place. A physical or a
cloud HSM may be used for secure storage of the secure boot private key. Please take a
look at Remote Signing of Images for more details.
It is recommended to use all the available digest slots to reduce dependency on a single
private key.
Previous Next
Built with Sphinx using a theme based on Read the Docs Sphinx Theme. Download PDF