flash encryption/secure boot: Restructure documentation

Also add steps to disable flash encryption, as some people seem to
accidentally enable it.

Explicitly mark the flash encryption and secure boot as "READ DOCS
FIRST" in menuconfig.
pull/157/merge
Angus Gratton 2017-02-14 12:48:28 +11:00
rodzic a65944a8cb
commit 7c7edab328
7 zmienionych plików z 273 dodań i 178 usunięć

Wyświetl plik

@ -59,7 +59,7 @@ After the initial flash, you may just want to build and flash just your app, not
`make app-flash` will automatically rebuild the app if it needs it.
(There's no downside to reflashing the bootloader and partition table each time, if they haven't changed.)
(In normal development there's no downside to reflashing the bootloader and partition table each time, if they haven't changed.)
## Parallel Builds

Wyświetl plik

@ -35,16 +35,16 @@ endmenu
menu "Security features"
config SECURE_BOOT_ENABLED
bool "Enable secure boot in bootloader"
bool "Enable secure boot in bootloader (READ DOCS FIRST)"
default N
help
Build a bootloader which enables secure boot on first boot.
Once enabled, secure boot will not boot a modified bootloader. The bootloader will only load a partition table or boot an app if the data has a verified digital signature.
Once enabled, secure boot will not boot a modified bootloader. The bootloader will only load a partition table or boot an app if the data has a verified digital signature. There are implications for reflashing updated apps once secure boot is enabled.
When enabling secure boot, JTAG and ROM BASIC Interpreter are permanently disabled by default.
See docs/security/secure-boot.rst for details.
Refer to http://esp-idf.readthedocs.io/en/latest/security/secure-boot.html before enabling.
choice SECURE_BOOTLOADER_MODE
bool "Secure bootloader mode"
@ -108,7 +108,7 @@ config SECURE_BOOT_VERIFICATION_KEY
PEM formatted private key using the espsecure.py
extract_public_key command.
See docs/security/secure-boot.rst for details.
Refer to http://esp-idf.readthedocs.io/en/latest/security/secure-boot.html before enabling.
config SECURE_BOOT_INSECURE
bool "Allow potentially insecure options"
@ -119,16 +119,18 @@ config SECURE_BOOT_INSECURE
Only enable these options if you are very sure.
Refer to docs/security/secure-boot.rst and docs/security/flash-encryption.rst for details.
Refer to http://esp-idf.readthedocs.io/en/latest/security/secure-boot.html before enabling.
config FLASH_ENCRYPTION_ENABLED
bool "Enable flash encryption on boot"
bool "Enable flash encryption on boot (READ DOCS FIRST)"
default N
help
If this option is set, flash contents will be encrypted by the bootloader on first boot.
Note: After first boot, the system will be permanently encrypted.
See docs/securityflash-encryption.rst for details.
Note: After first boot, the system will be permanently encrypted. Re-flashing an encrypted
system is complicated and not always possible.
Read http://esp-idf.readthedocs.io/en/latest/security/flash-encryption.html before enabling.
config FLASH_ENCRYPTION_INSECURE
bool "Allow potentially insecure options"

Wyświetl plik

@ -19,10 +19,12 @@
#include "esp_spi_flash.h"
#include "soc/efuse_reg.h"
/* Support functions for flash encryption features.
Can be compiled as part of app or bootloader code.
*/
/**
* @file esp_partition.h
* @brief Support functions for flash encryption features
*
* Can be compiled as part of app or bootloader code.
*/
/** @brief Is flash encryption currently enabled in hardware?
*

Wyświetl plik

@ -37,7 +37,8 @@ INPUT = ../components/esp32/include/esp_wifi.h \
../components/fatfs/src/esp_vfs_fat.h \
../components/fatfs/src/diskio.h \
../components/esp32/include/esp_core_dump.h \
../components/mdns/include/mdns.h
../components/mdns/include/mdns.h \
../components/bootloader_support/include/esp_flash_encrypt.h
## Get warnings for functions that have no documentation for their parameters or return value
##

Wyświetl plik

@ -8,7 +8,7 @@ Header Files
* :component_file:`spi_flash/include/esp_spi_flash.h`
* :component_file:`spi_flash/include/esp_partition.h`
* :component_file:`esp32/include/esp_flash_encrypt.h`
* :component_file:`bootloader_support/include/esp_flash_encrypt.h`
Macros
^^^^^^

Wyświetl plik

@ -3,9 +3,9 @@ Flash Encryption
Flash Encryption is a feature for encrypting the contents of the ESP32's attached SPI flash. When flash encryption is enabled, physical readout of the SPI flash is not sufficient to recover most flash contents.
Flash Encryption is separate from the `Secure Boot` feature, and you can use flash encryption without enabling secure boot. However we recommend using both features together for a secure environment.
Flash Encryption is separate from the :doc:`Secure Boot <secure-boot>` feature, and you can use flash encryption without enabling secure boot. However we recommend using both features together for a secure environment.
**IMPORTANT: Enabling flash encryption limits your options for further updates of your ESP32. Make sure to read this document (including `Limitations of Flash Encryption` and understand the implications of enabling flash encryption.**
**IMPORTANT: Enabling flash encryption limits your options for further updates of your ESP32. Make sure to read this document (including :ref:`flash-encryption-limitations`) and understand the implications of enabling flash encryption.**
Background
----------
@ -17,6 +17,7 @@ Background
- Encryption is applied by flashing the ESP32 with plaintext data, and (if encryption is enabled) the bootloader encrypts the data in place on first boot.
- Not all of the flash is encrypted. The following kinds of flash data are encrypted:
- Bootloader
- Secure boot bootloader digest (if secure boot is enabled)
- Partition Table
@ -29,58 +30,75 @@ Background
- The `flash encryption algorithm` is AES-256, where the key is "tweaked" with the offset address of each 32 byte block of flash. This means every 32 byte block (two consecutive 16 byte AES blocks) is encrypted with a unique key derived from the flash encryption key.
- Although software running on the chip can transparently decrypt flash contents, by default it is made possible for the UART bootloader to decrypt (or encrypt) data when flash encryption is enabled.
- Although software running on the chip can transparently decrypt flash contents, by default it is made impossible for the UART bootloader to decrypt (or encrypt) data when flash encryption is enabled.
- If flash encrption may be enabled, the programmer must take certain precautions when writing code that :ref:`uses encrypted flash <using-encrypted-flash>`.
.. _flash-encryption-initialisation:
Flash Encryption Initialisation
-------------------------------
This is the default (and recommended) flash encryption initialisation process. It is possible to customise this process for development or other purposes, see `Flash Encryption Advanced Features` for details.
This is the default (and recommended) flash encryption initialisation process. It is possible to customise this process for development or other purposes, see :ref:`flash-encryption-advanced-features` for details.
**IMPORTANT: Once flash encryption is enabled on first boot, the hardware allows a maximum of 3 subsequent flash updates via physical re-flashing. If secure boot is enabled, no physical re-flashes are possible. OTA updates can be used to update flash content without counting towards this limit. When enabling flash encryption in development, use a `precalculated flash encryption key` to allow physically re-flashing an unlimited number of times with pre-encrypted data.**
**IMPORTANT: Once flash encryption is enabled on first boot, the hardware allows a maximum of 3 subsequent flash updates via serial re-flashing.** A special procedure (documented in :ref:`updating-encrypted-flash-serial`) must be followed to perform these updates.
- The bootloader must be compiled with flash encryption support enabled. In ``make menuconfig``, navigate to "Security Features" and select "Yes" for "Enable flash nencryption on boot".
- If secure boot is enabled, no physical re-flashes are possible.
- OTA updates can be used to update flash content without counting towards this limit.
- When enabling flash encryption in development, use a `pregenerated flash encryption key` to allow physically re-flashing an unlimited number of times with pre-encrypted data.**
- If enabling Secure Boot at the same time, you can simultaneously select those options now. See the `Secure Boot` documentation for details.
Process to enable flash encryption:
- The bootloader must be compiled with flash encryption support enabled. In ``make menuconfig``, navigate to "Security Features" and select "Yes" for "Enable flash encryption on boot".
- If enabling Secure Boot at the same time, it is best to simultaneously select those options now. Read the :doc:`Secure Boot <secure-boot>` documentation first.
- Build and flash the bootloader, partition table and factory app image as normal. These partitions are initially written to the flash unencrypted.
- On first boot, the bootloader sees ``FLASH_CRYPT_CNT`` efuse is set to 0 so it generates a flash encryption key using the hardware random number generator. This key is stored in efuse. The key is read and write protected against further software access.
- On first boot, the bootloader sees :ref:`FLASH_CRYPT_CNT` is set to 0 (factory default) so it generates a flash encryption key using the hardware random number generator. This key is stored in efuse. The key is read and write protected against further software access.
- All of the encrypted partitions are then encrypted in-place by the bootloader. Encrypting in-place can take some time (up to a minute for large partitions.)
**IMPORTANT: Do not interrupt power to the ESP32 while the first boot encryption pass is running. If power is interrupted, the flash contents will be corrupted and require flashing with unencrypted data again. This re-flash will not count towards the flashing limit, as ``FLASH_CRYPT_CNT`` is only updated after this process finishes.**
**IMPORTANT: Do not interrupt power to the ESP32 while the first boot encryption pass is running. If power is interrupted, the flash contents will be corrupted and require flashing with unencrypted data again. A reflash like this will not count towards the flashing limit.**
- Once flashing is complete. efuses are blown (by default) to disable encrypted flash access while the UART bootloader is running.
- Once flashing is complete. efuses are blown (by default) to disable encrypted flash access while the UART bootloader is running. See :ref:`uart-bootloader-encryption` for advanced details.
- If not already write-protected, the ``FLASH_CRYPT_CONFIG`` efuse is also burned to the maximum value (``0xF``) to maximise the number of key bits which are tweaked in the flash algorithm. See `Setting FLASH_CRYPT_CONFIG` for details of this efuse.
- The ``FLASH_CRYPT_CONFIG`` efuse is also burned to the maximum value (``0xF``) to maximise the number of key bits which are tweaked in the flash algorithm. See :ref:`setting-flash-crypt-config` for advanced details.
- Finally, the ``FLASH_CRYPT_CNT`` efuse is burned with the initial value 1. It is this efuse which activates the transparent flash encryption layer, and limits the number of subsequent reflashes. See the `Updating Encrypted Flash` section for details about ``FLASH_CRYPT_CNT``.
- Finally, the :ref:`FLASH_CRYPT_CNT` is burned with the initial value 1. It is this efuse which activates the transparent flash encryption layer, and limits the number of subsequent reflashes. See the :ref:`updating-encrypted-flash` section for details about :ref:`FLASH_CRYPT_CNT`.
- The bootloader resets itself to reboot from the newly encrypted flash.
.. _using-encrypted-flash:
Encrypted Flash Access
----------------------
Using Encrypted Flash
---------------------
Reading Encrypted Flash
^^^^^^^^^^^^^^^^^^^^^^^
ESP32 app code can check if flash encryption is currently enabled by calling :func:`esp_flash_encryption_enabled`.
Whenever the ``FLASH_CRYPT_CNT`` efuse is set to a value with an odd number of bits set, all flash content which is accessed via the MMU's flash cache is transparently decrypted. This includes:
Once flash encryption is enabled, some care needs to be taken when accessing flash contents from code.
Scope of Flash Encryption
^^^^^^^^^^^^^^^^^^^^^^^^^
Whenever the :ref:`FLASH_CRYPT_CNT` is set to a value with an odd number of bits set, all flash content which is accessed via the MMU's flash cache is transparently decrypted. This includes:
- Executable application code in flash (IROM).
- All read-only data stored in flash (DROM).
- Any data accessed via ``esp_spi_flash_mmap``.
- Any data accessed via :func:`esp_spi_flash_mmap`.
- The software bootloader image when it is read by the ROM bootloader.
**IMPORTANT: The MMU flash cache unconditionally decrypts all data. Data which is stored unencrypted in the flash will be "transparently decrypted" via the flash cache and appear to software like random garbage.**
To read data without using a flash cache MMU mapping, we recommend using the partition read function ``esp_partition_read``. When using this function, data will only be decrypted when it is read from an encrypted partition. Other partitions will be read unencrypted. In this way, software can access encrypted and non-encrypted flash in the same way.
Reading Encrypted Flash
^^^^^^^^^^^^^^^^^^^^^^^
To read data without using a flash cache MMU mapping, we recommend using the partition read function :func:`esp_partition_read`. When using this function, data will only be decrypted when it is read from an encrypted partition. Other partitions will be read unencrypted. In this way, software can access encrypted and non-encrypted flash in the same way.
Data which is read via other SPI read APIs are not decrypted:
- Data read via ``esp_spi_flash_read`` is not decrypted
- Data read via ROM function ``SPIRead`` is not decrypted (this function is not supported in esp-idf apps).
- Data stored using the Non-Volatile Storage (NVS) API is always stored decrypted.
- Data read via :func:`esp_spi_flash_read` is not decrypted
- Data read via ROM function :func:`SPIRead` is not decrypted (this function is not supported in esp-idf apps).
- Data stored using the Non-Volatile Storage (NVS) API is always stored and read decrypted.
Writing Encrypted Flash
@ -92,92 +110,179 @@ The ``esp_spi_flash_write`` function will write data when the write_encrypted pa
The ROM function ``SPI_Encrypt_Write`` will write encrypted data to flash, the ROM function ``SPIWrite`` will write unencrypted to flash. (these function are not supported in esp-idf apps).
The minimum write size for unencrypted data is 4 bytes (and the alignment is 4 bytes). Because data is encrypted in blocks, the minimum write size for encrypted data is 32 bytes (and the alignment is 32 bytes.)
The minimum write size for unencrypted data is 4 bytes (and the alignment is 4 bytes). Because data is encrypted in blocks, the minimum write size for encrypted data is 16 bytes (and the alignment is 16 bytes.)
.. _updating-encrypted-flash:
Updating Encrypted Flash
------------------------
.. _updating-encrypted-flash-ota:
OTA Updates
^^^^^^^^^^^
OTA updates to encrypted partitions will automatically write encrypted, as long as the ``esp_partition_write`` function is used.
.. _updating-encrypted-flash-serial:
Serial Flashing
^^^^^^^^^^^^^^^
Provided secure boot is not used, the ``FLASH_CRYPT_CNT`` registers allow the flash to be updated with new plaintext data via serial flashing (or other physical methods), up to 3 additional times. ``FLASH_CRYPT_CNT`` efuse is an 8-bit value, and the flash encryption enables or disables based on the number of bits which are set to "1":
Provided secure boot is not used, the :ref:`FLASH_CRYPT_CNT` allows the flash to be updated with new plaintext data via serial flashing (or other physical methods), up to 3 additional times.
- Even number (0-6) bits are set: Transparent reading of encrypted flash is disabled, any encrypted data cannot be decrypted. If the bootloader was built with "Enable flash encryption on boot" then it will see this situation and immediately re-encrypt the flash wherever it finds unencrypted data. Once done, it sets another bit in the efuse to '1' meaning an odd number of bits are now set.
- Odd number (1-7) bits are set: Transparent reading of encrypted flash is enabled.
- All 8 bits are set (valuye 0: Transparent reading of encrypted flash is disabled, any encrypted data is inaccessible. Bootloader will normally detect this condition and halt. To avoid use of this state to load unauthorised code, secure boot must be used or ``FLASH_CRYPT_CNT`` must be write-protected.
The espefuse.py tool can be used to manually change the number of bits set in ``FLASH_CRYPT_CNT``, via serial bootloader.
The process involves flashing plaintext data, and then bumping the value of :ref:`FLASH_CRYPT_CNT` which causes the bootloader to re-encrypt this data.
Limited Updates
^^^^^^^^^^^^^^^
~~~~~~~~~~~~~~~
Only 4 physical flash updates (writing plaintext data which is then encrypted) are possible:
Only 4 serial flash update cycles of this kind are possible, including the initial encrypted flash.
1. On first plaintext boot, bit count has brand new value 0 and bootloader changes to 1 (0x01) following encryption.
2. On next plaintext flash update, bit count is manually updated to 2 (0x03) and bootloader changes to 4 (0x07) following encryption.
3. Then bit count is manually updated to 4 (0x0F) and the bootloader changes efuse bit count to 5 (0x1F).
4. Finally bootloader is manually updated to 6 (0x3F) and bootloader changes efuse bit count to 7 (0x7F).
After the fourth time encryption is disabled, :ref:`FLASH_CRYPT_CNT` has the maximum value `0xFF` and encryption is permanently disabled.
Cautions With Re-Flashing
^^^^^^^^^^^^^^^^^^^^^^^^^^
Using :ref:`updating-encrypted-flash-ota` or :ref:`pregenerated-flash-encryption-key` allows you to exceed this limit.
- When reflashing via serial, reflash every partition that was previously written with plaintext (including bootloader). It is possible to skip app partitions which are not the "currently selected" OTA partition (these will not be re-encrypted unless a plaintext app image is found there.) However any partition marked with the "encrypt" flag will be unconditionally re-encrypted, meaning that any already encrypted data will be encrypted twice and corrupted.
Cautions With Serial Flashing
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- If secure boot is enabled, you can't reflash via serial at all unless you used chosen the "Reflashable" option for Secure Boot, pre-generated a key and burned it to the ESP32. In this case you can re-flash a plaintext secure boot digest and bootloader image at offset 0 (see `Secure Boot` documentation.) In production secure boot configuration, the secure boot digest is stored encrypted - so if ``FLASH_CRYPT_CNT`` is set to an even value then the ROM bootloader will read the encrypted digest as-is and therefore will fail to verify any bootloader image as valid.
- When reflashing via serial, reflash every partition that was initially written with plaintext data (including bootloader). It is possible to skip app partitions which are not the "currently selected" OTA partition (these will not be re-encrypted unless a plaintext app image is found there.) However any partition marked with the "encrypt" flag will be unconditionally re-encrypted, meaning that any already encrypted data will be encrypted twice and corrupted.
Re-Flashing Procedure
^^^^^^^^^^^^^^^^^^^^^
- Using ``make flash`` should flash all partitions which need to be flashed.
The steps to update a device with plaintext via UART bootloader, when flash encryption is enabled are:
- If secure boot is enabled, you can't reflash via serial at all unless you used the "Reflashable" option for Secure Boot, pre-generated a key and burned it to the ESP32 (refer to :doc:`Secure Boot <secure-boot>` docs.). In this case you can re-flash a plaintext secure boot digest and bootloader image at offset 0x0. It is necessary to re-flash this digest before flashing other plaintext data.
Serial Re-Flashing Procedure
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Build the application as usual.
- Burn the ``FLASH_CRYPT_CNT`` efuse by running the command ``espefuse.py burn_efuse FLASH_CRYPT_CNT``. espefuse.py will automatically increment the bit count by 1.
- Flash the device with plaintext data as usual (``make flash`` or ``esptool.py`` commands.) Flash all previously encrypted partitions, including the bootloader (see previous section).
- Flash the device with plaintext data as usual (``make flash`` or ``esptool.py`` commands.) Flash all previously encrypted partitions, including the bootloader. If secure boot is enabled, it must be enabled in "Reflashable" mode and a pre-generated key burned to the ESP32 - flash the bootloader-reflash-digest.bin file at offset 0x0.
- At this point, the device will fail to boot (message is ``flash read err, 1000``) because it expects to see an encrypted bootloader, but the bootloader is plaintext.
- Reset the device and it will re-encrypt plaintext partitions, burn the ``FLASH_CRYPT_CNT`` flag to re-enable encryption.
- Burn the :ref:`FLASH_CRYPT_CNT` by running the command ``espefuse.py burn_efuse FLASH_CRYPT_CNT``. espefuse.py will automatically increment the bit count by 1, which disables encryption.
- Reset the device and it will re-encrypt plaintext partitions, then burn the :ref:`FLASH_CRYPT_CNT` again to re-enable encryption.
Disabling Updates
^^^^^^^^^^^^^^^^^
Disabling Serial Updates
~~~~~~~~~~~~~~~~~~~~~~~~
To prevent further plaintext updates via physical access, use espefuse.py to write protect the ``FLASH_CRYPT_CNT`` efuse after flash encryption has been enabled (ie after first boot is complete)::
To prevent further plaintext updates via serial, use espefuse.py to write protect the :ref:`FLASH_CRYPT_CNT` after flash encryption has been enabled (ie after first boot is complete)::
espefuse.py write_protect_efuse FLASH_CRYPT_CNT
espefuse.py --port PORT write_protect_efuse FLASH_CRYPT_CNT
This prevents any further modifications to disable or re-enable flash encryption.
.. _pregenerated-flash-encryption-key:
Reflashing via Pregenerated Flash Encryption Key
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
It is possible to pregenerate a flash encryption key on the host computer and burn it into the ESP32's efuse key block. This allows data to be pre-encrypted on the host and flashed to the ESP32 without needing a plaintext flash update.
This is useful for development, because it removes the 4 time reflashing limit. It also allows reflashing with secure boot enabled, because the bootloader doesn't need to be reflashed each time.
**IMPORTANT This method is intended to assist with development only, not for production devices. If pre-generating flash encryption for production, ensure the keys are generated from a high quality random number source and do not share the same flash encryption key across multiple devices.**
Pregenerating a Flash Encryption Key
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Flash encryption keys are 32 bytes of random data. You can generate a random key with espsecure.py::
espsecure.py generate_flash_encryption_key my_flash_encryption_key.bin
(The randomness of this data is only as good as the OS and it's Python installation's random data source.)
Alternatively, if you're using :doc:`secure boot <secure-boot>` and have a secure boot signing key then you can generate a deterministic SHA-256 digest of the secure boot private signing key and use this as the flash encryption key::
espsecure.py digest_private-key --keyfile secure_boot_signing_key.pem my_flash_encryption_key.bin
(The same 32 bytes is used as the secure boot digest key if you enable :ref:`reflashable mode<secure-boot-reflashable>` for secure boot.)
Generating the flash encryption key from the secure boot signing key in this way means that you only need to store one key file. However this method is **not at all suitable** for production devices.
Burning Flash Encryption Key
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Once you have generated a flash encryption key, you need to burn it to the ESP32's efuse key block. **This must be done before first encrypted boot**, otherwise the ESP32 will generate a random key that software can't access or modify.
To burn a key to the device (one time only)::
espefuse.py --port PORT burn_key flash_encryption my_flash_encryption_key.bin
First Flash with pregenerated key
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
After flashing the key, follow the same steps as for default :ref:`flash-encryption-initialisation` and flash a plaintext image for the first boot. The bootloader will enable flash encryption using the pre-burned key and encrypt all partitions.
Reflashing with pregenerated key
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
After encryption is enabled on first boot, reflashing an encrypted image requires an additional manual step. This is where we pre-encrypt the data that we wish to update in flash.
Suppose that this is the normal command used to flash plaintext data::
esptool.py --port /dev/ttyUSB0 --baud 115200 write_flash 0x10000 build/my-app.bin
Binary app image ``build/my-app.bin`` is written to offset ``0x10000``. This file name and offset need to be used to encrypt the data, as follows::
espsecure.py encrypt_flash_data --keyfile my_flash_encryption_key.bin --address 0x10000 -o build/my-app-encrypted.bin build/my-app.bin
This example command will encrypts ``my-app.bin`` using the supplied key, and produce an encrypted file ``my-app-encrypted.bin``. Be sure that the address argument matches the address where you plan to flash the binary.
Then, flash the encrypted binary with esptool.py::
esptool.py --port /dev/ttyUSB0 --baud 115200 write_flash 0x10000 build/my-app-encrypted.bin
No further steps or efuse manipulation is necessary, because the data is already encrypted when we flash it.
Disabling Flash Encryption
--------------------------
If you've accidentally enabled flash encryption for some reason, the next flash of plaintext data will soft-brick the ESP32 (the device will reboot continously, printing the error ``flash read err, 1000``).
You can disable flash encryption again by writing :ref:`FLASH_CRYPT_CNT`:
- First, run ``make menuconfig`` and uncheck "Enable flash encryption boot" under "Security Features".
- Exit menuconfig and save the new configuration.
- Run ``make menuconfig`` again and double-check you really disabled this option! *If this option is left enabled, the bootloader will immediately re-enable encryption when it boots*.
- Run ``make flash`` to build and flash a new bootloader and app, without flash encryption enabled.
- Run ``espefuse.py`` (in ``components/esptool_py/esptool``) to disable the :ref:`FLASH_CRYPT_CNT`)::
espefuse.py burn_efuse FLASH_CRYPT_CNT
Reset the ESP32 and flash encryption should be disabled, the bootloader will boot as normal.
.. _flash-encryption-limitations:
Limitations of Flash Encryption
-------------------------------
Flash Encryption prevents plaintext readout of the encrypted flash, to protect firmware against unauthorised readout and modification. It is important to understand the limitations of the flash encryption system:
- Flash encryption is only as strong as the key. For this reason, we recommend keys are generated on the device during first boot (default behaviour). If generating keys off-device to burn with ``esp_efuse.py burn_key``, ensure they are generated from a quality random number source, kept secure, and never shared between devices.
- Flash encryption is only as strong as the key. For this reason, we recommend keys are generated on the device during first boot (default behaviour). If generating keys off-device (see :ref:`pregenerated-flash-encryption-key`), ensure proper procedure is followed.
- Not all data is stored encrypted. If storing data on flash, check if the method you are using (library, API, etc.) supports flash encryption.
- Flash encryption does not prevent an attacker from understanding the high-level layout of the flash. This is because the same AES key is used for every two 16 byte AES blocks. When both adjacent 16 byte blocks contain identical content (such as empty or padding areas), these blocks will encrypt to produce matching pairs of encrypted blocks. This may allow an attacker to make high-level comparisons between encrypted devices (ie to tell if two devices are probably running the same firmware version).
- Flash encryption does not prevent an attacker from understanding the high-level layout of the flash. This is because the same AES key is used for every pair of adjacent 16 byte AES blocks. When these adjacent 16 byte blocks contain identical content (such as empty or padding areas), these blocks will encrypt to produce matching pairs of encrypted blocks. This may allow an attacker to make high-level comparisons between encrypted devices (ie to tell if two devices are probably running the same firmware version).
- For the same reason, an attacker can always guess when two adjacent 16 byte blocks (32 byte aligned) contain identical content. Keep this in mind if storing sensitive data on the flash, design your flash storage so this doesn't happen (using a counter byte or some other non-identical value every 16 bytes is sufficient).
- For the same reason, an attacker can always tell when a pair of adjacent 16 byte blocks (32 byte aligned) contain identical content. Keep this in mind if storing sensitive data on the flash, design your flash storage so this doesn't happen (using a counter byte or some other non-identical value every 16 bytes is sufficient).
- Flash encryption alone may not prevent an attacker from modifying the firmware of the device. Always use flash encryption in combination with Secure Boot.
- Flash encryption alone may not prevent an attacker from modifying the firmware of the device. To prevent unauthorised firmware from runningon the device, use flash encryption in combination with :doc:`Secure Boot <secure-boot>`.
.. _flash-encryption-advanced-features:
Flash Encryption Advanced Features
----------------------------------
The following information is useful for advanced use of flash encryption:
Encrypted Partition Flag
^^^^^^^^^^^^^^^^^^^^^^^^
In the `partition table` description CSV files, there is a field for flags.
Some partitions are encrypted by default. Otherwise, it is possible to mark any partition as requiring encryption:
In the :doc:`partition table </partition-tables>` description CSV files, there is a field for flags.
Usually left blank, if you write "encrypted" in this field then the partition will be marked as encrypted in the partition table, and data written here will be treated as encrypted (same as an app partition)::
@ -187,7 +292,7 @@ Usually left blank, if you write "encrypted" in this field then the partition wi
factory, app, factory, 0x10000, 1M
secret_data, 0x40, 0x01, 0x20000, 256K, encrypted
- None of the default partition formats have any encrypted data partitions.
- None of the default partition tables include any encrypted data partitions.
- It is not necessary to mark "app" partitions as encrypted, they are always treated as encrypted.
@ -197,88 +302,70 @@ Usually left blank, if you write "encrypted" in this field then the partition wi
- It is not possible to mark the ``nvs`` partition as encrypted.
Precalculated Flash Encryption Key
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
It is possible to pre-generate a flash encryption key on the host computer and burn it into the ESP32 efuse. This allows data to be per-encrypted on the host and flashed to the ESP32 without needing a plaintext flash update.
This is useful for development, because it removes the 4 flash limit and allows reflashing with secure boot enabled.
**IMPORTANT** This method is intended to assist with development only, not for production devices. If pre-generating flash encryption for production, ensure the keys are generated from a high quality random number source and do not share the same flash encryption key across multiple devices.
Obtaining Flash Encryption Key
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Flash encryption keys are 32 bytes of random data. You can generate a random key with espsecure.py::
espsecure.py generate_flash_encryption_key my_flash_encryption_key.bin
(The randomness of this data is only as good as the OS and it's Python installation's random data source.)
Alternatively, if you're using `secure boot` and have a secure boot signing key then you can generate a deterministic SHA-256 digest of the secure boot private key to use::
espsecure.py digest_private-key --keyfile secure_boot_signing_key.pem my_flash_encryption_key.bin
The same key is used as the secure boot digest key if you enabled "Reflashable" mode for secure boot.
This means you can always re-calculate the flash encryption key from the secure boot private signing key. This method is **not at all suitable** for production devices.
Burning Flash Encryption Key
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Once you have generated a flash encryption key, you need to burn it to efuse on the device. This **must be done before first boot**, otherwise the ESP32 will generate a random key that software can't access.
To burn a key to the device (possible one time only)::
espefuse.py burn_key flash_encryption my_flash_encryption_key.bin
First Flash
~~~~~~~~~~~
For the first flash, follow the same steps as for default `Flash Encryption Initialisation` and flash a plaintext image. The bootloader will enable flash encryption using the pre-burned key and encrypt all partitions.
Reflashing
~~~~~~~~~~
To reflash an encrypted image requires an additional manual update step, to encrypt the data you wish to flash.
Suppose that this is the normal flashing non-encrypted flashing step::
esptool.py --port /dev/ttyUSB0 --baud 115200 write_flash -z 0x10000 build/my-app.bin
The data needs to be pre-encrypted with knowledge of the address (0x10000) and the binary file name::
espsecure.py encrypt_flash_data --keyfile my_flash_encryption_key.bin --address 0x10000 -o build/my-app-encrypted.bin build/my-app.bin
This step will encrypt ``my-app.bin`` using the supplied key, and produce an encrypted file ``my-app-encrypted.bin``. Be sure that the address argument matches the address where you plan to flash the binary.
Then, flash the encrypted binary with esptool.py::
esptool.py --port /dev/ttyUSB0 --baud 115200 write_flash -z 0x10000 build/my-app-encrypted.bin
.. _uart-bootloader-encryption:
Enabling UART Bootloader Encryption/Decryption
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
By default, on first boot the flash encryption process will burn efuses ``DISABLE_DL_ENCRYPT``, ``DISABLE_DL_DECRYPT`` and ``DISABLE_DL_CACHE``.
By default, on first boot the flash encryption process will burn efuses ``DISABLE_DL_ENCRYPT``, ``DISABLE_DL_DECRYPT`` and ``DISABLE_DL_CACHE``:
- ``DISABLE_DL_ENCRYPT`` disables the flash encryption operations when running in UART bootloader boot mode.
- ``DISABLE_DL_DECRYPT`` disables transparent flash decryption when running in UART bootloader mode, even if ``FLASH_CRYPT_CNT`` is set to enable it in normal operation.
- ``DISABLE_DL_DECRYPT`` disables transparent flash decryption when running in UART bootloader mode, even if :ref:`FLASH_CRYPT_CNT` is set to enable it in normal operation.
- ``DISABLE_DL_CACHE`` disables the entire MMU flash cache when running in UART bootloader mode.
It is possible to burn only some of these efuses, and write-protect the rest (with unset value 0) before the first boot, in order to preserve them::
It is possible to burn only some of these efuses, and write-protect the rest (with unset value 0) before the first boot, in order to preserve them. For example::
espefuse.py burn_efuse DISABLE_DL_DECRYPT
espefuse.py write_protect_efuse DISABLE_DL_ENCRYPT
espefuse.py --port PORT burn_efuse DISABLE_DL_DECRYPT
espefuse.py --port PORT write_protect_efuse DISABLE_DL_ENCRYPT
(Note that all 3 of these efuses are disabled via one write protect bit, so write protecting one will write protect all of them.)
(Note that all 3 of these efuses are disabled via one write protect bit, so write protecting one will write protect all of them. For this reason, it's necessary to set any bits before write-protecting.)
Write protecting these efuses when they are unset (0) is not currently useful, as ``esptool.py`` does not support flash encryption functions.
**IMPORTANT**: Write protecting these efuses to keep them unset is not currently very useful, as ``esptool.py`` does not support writing or reading encrypted flash.
**IMPORTANT**: If ``DISABLE_DL_DECRYPT`` is left unset (0) this effectively makes flash encryption useless, as an attacker with physical access can use UART bootloader mode (with custom stub code) to read out the flash contents.
.. _setting-flash-crypt-config:
Setting FLASH_CRYPT_CONFIG
^^^^^^^^^^^^^^^^^^^^^^^^^^
The ``FLASH_CRYPT_CONFIG`` efuse determines the number of bits in the flash encryption key which are "tweaked" with the block offset. See :ref:`flash-encryption-algorithm` for details.
First boot of the bootloader always sets this value to the maximum `0xF`.
It is possible to write these efuse manually, and write protect it before first boot in order to select different tweak values. This is not recommended.
It is strongly recommended to never write protect ``FLASH_CRYPT_CONFIG`` when it the value is zero. If this efuse is set to zero, no bits in the flash encryption key are tweaked and the flash encryption algorithm is equivalent to AES ECB mode.
However, note that write protecting ``DISABLE_DL_DECRYPT`` when it is unset (0) effectively makes flash encryption useless, as an attacker with physical access can use UART bootloader mode to read out the flash.
Technical Details
-----------------
The following sections provide some reference information about the operation of flash encryption.
.. _FLASH_CRYPT_CNT:
FLASH_CRYPT_CNT efuse
^^^^^^^^^^^^^^^^^^^^^
``FLASH_CRYPT_CNT`` is an 8-bit efuse field which controls flash encryption. Flash encryption enables or disables based on the number of bits in this efuse which are set to "1":
- When an even number of bits (0,2,4,6,8) are set: Flash encryption is disabled, any encrypted data cannot be decrypted.
- If the bootloader was built with "Enable flash encryption on boot" then it will see this situation and immediately re-encrypt the flash wherever it finds unencrypted data. Once done, it sets another bit in the efuse to '1' meaning an odd number of bits are now set.
1. On first plaintext boot, bit count has brand new value 0 and bootloader changes it to bit count 1 (value 0x01) following encryption.
2. After next plaintext flash update, bit count is manually updated to 2 (value 0x03). After re-encrypting the bootloader changes efuse bit count to 3 (value 0x07).
3. After next plaintext flash, bit count is manually updated to 4 (value 0x0F). After re-encrypting the bootloader changes efuse bit count to 5 (value 0x1F).
4. After final plaintext flash, bit count is manually updated to 6 (value 0x3F). After re-encrypting the bootloader changes efuse bit count to 7 (value 0x7F).
- When an odd number of bits (1,3,5,7) are set: Transparent reading of encrypted flash is enabled.
- After all 8 bits are set (efuse value 0xFF): Transparent reading of encrypted flash is disabled, any encrypted data is permanently inaccessible. Bootloader will normally detect this condition and halt. To avoid use of this state to load unauthorised code, secure boot must be used or :ref:`FLASH_CRYPT_CNT` must be write-protected.
.. _flash-encryption-algorithm:
Flash Encryption Algorithm
^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -288,7 +375,7 @@ Flash Encryption Algorithm
- The main flash encryption key is stored in efuse (BLK2) and by default is protected from further writes or software readout.
- Each 32 byte block is encrypted with a unique key which is derived from this main flash encryption key XORed with the offset of this block in the flash (a "key tweak").
- Each 32 byte block (two adjacent 16 byte AES blocks) is encrypted with a unique key. The key is derived from the main flash encryption key in efuse, XORed with the offset of this block in the flash (a "key tweak").
- The specific tweak depends on the setting of ``FLASH_CRYPT_CONFIG`` efuse. This is a 4 bit efuse, where each bit enables XORing of a particular range of the key bits:
@ -297,24 +384,11 @@ Flash Encryption Algorithm
- Bit 3, bits 132-194 of the key are XORed.
- Bit 4, bits 195-256 of the key are XORed.
It is recommended that ``FLASH_CRYPT_CONFIG`` is always left to set the default value `0xF`, so that all key bits are XORed with the block offset. See `Setting FLASH_CRYPT_CONFIG` for details.
It is recommended that ``FLASH_CRYPT_CONFIG`` is always left to set the default value `0xF`, so that all key bits are XORed with the block offset. See :ref:`setting-flash-crypt-config` for details.
- The high 19 bits of the block offset (bit 5 to bit 23) are XORed with the main flash encryption key. This range is chosen for two reasons: the maximum flash size is 16MB (24 bits), and each block is 32 bytes so the least significant 5 bits are always zero.
- There is a particular mapping from each of the 19 block offset bits to the 256 bits of the flash encryption key, to determine which bit is XORed with which. See the variable _FLASH_ENCRYPTION_TWEAK_PATTERN in espsecure.py for a list of these.
- There is a particular mapping from each of the 19 block offset bits to the 256 bits of the flash encryption key, to determine which bit is XORed with which. See the variable ``_FLASH_ENCRYPTION_TWEAK_PATTERN`` in the espsecure.py source code for the complete mapping.
- For the full algorithm implemented in Python, see `_flash_encryption_operation()` in the espsecure.py source code.
- To see the full flash encryption algorithm implemented in Python, refer to the `_flash_encryption_operation()` function in the espsecure.py source code.
Setting FLASH_CRYPT_CONFIG
^^^^^^^^^^^^^^^^^^^^^^^^^^
The ``FLASH_CRYPT_CONFIG`` efuse determines the number of bits in the flash encryption key which are "tweaked" with the block offset. See `Flash Encryption Algorithm` for details.
First boot of the bootloader always sets this value to the maximum `0xF`.
It is possible to write these efuse manually, and write protect it before first boot in order to select different tweak values. This is not recommended.
It is strongly recommended to never write protect ``FLASH_CRYPT_CONFIG`` when it the value is zero. If this efuse is set to zero, no bits in the flash encryption key are tweaked and the flash encryption algorithm is equivalent to AES ECB mode.
.. _Secure Boot: secure-boot.rst
.. _partition table: ../partition-tables.rst

Wyświetl plik

@ -3,7 +3,9 @@ Secure Boot
Secure Boot is a feature for ensuring only your code can run on the chip. Data loaded from flash is verified on each reset.
Secure Boot is separate from the `Flash Encryption` feature, and you can use secure boot without encrypting the flash contents. However we recommend using both features together for a secure environment.
Secure Boot is separate from the :doc:`Flash Encryption <flash-encryption>` feature, and you can use secure boot without encrypting the flash contents. However we recommend using both features together for a secure environment.
**IMPORTANT: Enabling secure boot limits your options for further updates of your ESP32. Make sure to read this document throughly and understand the implications of enabling secure boot.**
Background
----------
@ -19,7 +21,7 @@ Background
Secure Boot Process Overview
----------------------------
This is a high level overview of the secure boot process. Step by step instructions are supplied under `How To Enable Secure Boot`. Further in-depth details are supplied under `Technical Details`:
This is a high level overview of the secure boot process. Step by step instructions are supplied under :ref:`secure-boot-howto`. Further in-depth details are supplied under :ref:`secure-boot-technical-details`:
1. The options to enable secure boot are provided in the ``make menuconfig`` hierarchy, under "Secure Boot Configuration".
@ -34,7 +36,7 @@ This is a high level overview of the secure boot process. Step by step instructi
- Depending on Secure Boot Configuration, efuses are burned to disable JTAG and the ROM BASIC interpreter (it is strongly recommended these options are turned on.)
- Bootloader permanently enables secure boot by burning the ABS_DONE_0 efuse. The software bootloader then becomes protected (the chip will only boot a bootloader image if the digest matches.)
5. On subsequent boots the ROM bootloader sees that the secure boot efuse is burned, reads the saved digest at 0x0 and uses hardware secure boot support to compare it with a newly calculated digest. If the digest does not match then booting will not continue. The digest and comparison are performed entirely by hardware, and the calculated digest is not readable by software. For technical details see `Hardware Secure Boot Support`.
5. On subsequent boots the ROM bootloader sees that the secure boot efuse is burned, reads the saved digest at 0x0 and uses hardware secure boot support to compare it with a newly calculated digest. If the digest does not match then booting will not continue. The digest and comparison are performed entirely by hardware, and the calculated digest is not readable by software. For technical details see :ref:`secure-boot-hardware-support`.
6. When running in secure boot mode, the software bootloader uses the secure boot signing key (the public key of which is embedded in the bootloader itself, and therefore validated as part of the bootloader) to verify the signature appended to all subsequent partition tables and app images before they are booted.
@ -43,19 +45,20 @@ Keys
The following keys are used by the secure boot process:
- "secure bootloader key" is a 256-bit AES key that is stored in Efuse block 2. The bootloader can generate this key itself from the internal hardware random number generator, the user does not need to supply it (it is optionally possible to supply this key, see `Re-Flashable Software Bootloader`). The Efuse holding this key is read & write protected (preventing software access) before secure boot is enabled.
- "secure bootloader key" is a 256-bit AES key that is stored in Efuse block 2. The bootloader can generate this key itself from the internal hardware random number generator, the user does not need to supply it (it is optionally possible to supply this key, see :ref:`secure-boot-reflashable`). The Efuse holding this key is read & write protected (preventing software access) before secure boot is enabled.
- "secure boot signing key" is a standard ECDSA public/private key pair (see `Image Signing Algorithm`) in PEM format.
- "secure boot signing key" is a standard ECDSA public/private key pair (see :ref:`secure-boot-image-signing-algorithm`) in PEM format.
- The public key from this key pair (for signature verificaton but not signature creation) is compiled into the software bootloader and used to verify the second stage of booting (partition table, app image) before booting continues. The public key can be freely distributed, it does not need to be kept secret.
- The private key from this key pair *must be securely kept private*, as anyone who has this key can authenticate to any bootloader that is configured with secure boot and the matching public key.
.. _secure-boot-howto:
How To Enable Secure Boot
-------------------------
1. Run ``make menuconfig``, navigate to "Secure Boot Configuration" and select the option "One-time Flash". (To understand the alternative "Reflashable" choice, see `Re-Flashable Software Bootloader`.)
1. Run ``make menuconfig``, navigate to "Secure Boot Configuration" and select the option "One-time Flash". (To understand the alternative "Reflashable" choice, see :ref:`secure-boot-reflashable`.)
2. Select a name for the secure boot signing key. This option will appear after secure boot is enabled. The file can be anywhere on your system. A relative path will be evaluated from the project directory. The file does not need to exist yet.
@ -65,22 +68,26 @@ How To Enable Secure Boot
**IMPORTANT** A signing key generated this way will use the best random number source available to the OS and its Python installation (`/dev/urandom` on OSX/Linux and `CryptGenRandom()` on Windows). If this random number source is weak, then the private key will be weak.
**IMPORTANT** For production environments, we recommend generating the keypair using openssl or another industry standard encryption program. See `Generating Secure Boot Signing Key` for more details.
**IMPORTANT** For production environments, we recommend generating the keypair using openssl or another industry standard encryption program. See :ref:`secure-boot-generate-key` for more details.
5. Run ``make bootloader`` to build a secure boot enabled bootloader. The output of `make` will include a prompt for a flashing command, using `esptool.py write_flash`.
5. Run ``make bootloader`` to build a secure boot enabled bootloader. The output of ``make`` will include a prompt for a flashing command, using ``esptool.py write_flash``.
.. _secure-boot-resume-normal-flashing:
6. When you're ready to flash the bootloader, run the specified command (you have to enter it yourself, this step is not performed by make) and then wait for flashing to complete. **Remember this is a one time flash, you can't change the bootloader after this!**.
7. Run `make flash` to build and flash the partition table and the just-built app image. The app image will be signed using the signing key you generated in step 4.
7. Run ``make flash`` to build and flash the partition table and the just-built app image. The app image will be signed using the signing key you generated in step 4.
*NOTE*: `make flash` doesn't flash the bootloader if secure boot is enabled.
*NOTE*: ``make flash`` doesn't flash the bootloader if secure boot is enabled.
8. Reset the ESP32 and it will boot the software bootloader you flashed. The software bootloader will enable secure boot on the chip, and then it verifies the app image signature and boots the app. You should watch the serial console output from the ESP32 to verify that secure boot is enabled and no errors have occured due to the build configuration.
*NOTE* Secure boot won't be enabled until after a valid partition table and app image have been flashed. This is to prevent accidents before the system is fully configured.
**NOTE** Secure boot won't be enabled until after a valid partition table and app image have been flashed. This is to prevent accidents before the system is fully configured.
9. On subsequent boots, the secure boot hardware will verify the software bootloader has not changed (using the secure bootloader key) and then the software bootloader will verify the signed partition table and app image (using the public key portion of the secure boot signing key).
.. _secure-boot-reflashable:
Re-Flashable Software Bootloader
--------------------------------
@ -90,7 +97,7 @@ However, an alternative mode "Secure Boot: Reflashable" is also available. This
In the esp-idf build process, this 256-bit key file is derived from the app signing key generated during the generate_signing_key step above. The private key's SHA-256 digest is used as the 256-bit secure bootloader key. This is a convenience so you only need to generate/protect a single private key.
*NOTE*: Although it's possible, we strongly recommend not generating one secure boot key and flashing it to every device in a production environment. The "One-Time Flash" option is recommended for production environments.
**NOTE**: Although it's possible, we strongly recommend not generating one secure boot key and flashing it to every device in a production environment. The "One-Time Flash" option is recommended for production environments.
To enable a reflashable bootloader:
@ -100,7 +107,9 @@ To enable a reflashable bootloader:
3. Run ``make bootloader``. A 256-bit key file will be created, derived from the private key that is used for signing. Two sets of flashing steps will be printed - the first set of steps includes an ``espefuse.py burn_key`` command which is used to write the bootloader key to efuse. (Flashing this key is a one-time-only process.) The second set of steps can be used to reflash the bootloader with a pre-calculated digest (generated during the build process).
4. Resume from `Step 6<Secure Boot Process Overview>` of the one-time process, to flash the bootloader and enable secure boot. Watch the console log output closely to ensure there were no errors in the secure boot configuration.
4. Resume from :ref:`Step 6 of the one-time flashing process <secure-boot-resume-normal-flashing>`, to flash the bootloader and enable secure boot. Watch the console log output closely to ensure there were no errors in the secure boot configuration.
.. _secure-boot-generate-key:
Generating Secure Boot Signing Key
----------------------------------
@ -134,7 +143,7 @@ After the app image and partition table are built, the build system will print s
espsecure.py sign_data --keyfile PRIVATE_SIGNING_KEY BINARY_FILE
The above command appends the image signature to the existing binary. You can use the --output argument to place the binary with signature appended into a separate file::
The above command appends the image signature to the existing binary. You can use the `--output` argument to write the signed binary to a separate file::
espsecure.py sign_data --keyfile PRIVATE_SIGNING_KEY --output SIGNED_BINARY_FILE BINARY_FILE
@ -145,16 +154,21 @@ Secure Boot Best Practices
* Keep the signing key private at all times. A leak of this key will compromise the secure boot system.
* Do not allow any third party to observe any aspects of the key generation or signing process using espsecure.py. Both processes are vulnerable to timing or other side-channel attacks.
* Enable all secure boot options in the Secure Boot Configuration. These include flash encryption, disabling of JTAG, disabling BASIC ROM interpeter, and disabling the UART bootloader encrypted flash access.
* Use secure boot in combination with :doc:`flash encryption<flash-encryption>` to prevent local readout of the flash contents.
.. _secure-boot-technical-details:
Technical Details
-----------------
The following sections contain low-level descriptions of various technical functions:
The following sections contain low-level reference descriptions of various secure boot elements:
Hardware Secure Boot Support
.. _secure-boot-hardware-support:
Secure Boot Hardware Support
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The Secure Boot support hardware can perform three basic operations:
The first stage of secure boot verification (checking the software bootloader) is done via hardware. The ESP32's Secure Boot support hardware can perform three basic operations:
1. Generate a random sequence of bytes from a hardware random number generator.
@ -167,7 +181,7 @@ Secure Bootloader Digest Algorithm
Starting with an "image" of binary data as input, this algorithm generates a digest as output. The digest is sometimes referred to as an "abstract" in hardware documentation.
For a Python version of this algorithm, see the `espsecure.py` tool in the components/esptool_py directory.
For a Python version of this algorithm, see the ``espsecure.py`` tool in the components/esptool_py directory (specifically, the ``digest_secure_bootloader`` command).
Items marked with (^) are to fulfill hardware restrictions, as opposed to cryptographic restrictions.
@ -183,23 +197,27 @@ Items marked with (^) are to fulfill hardware restrictions, as opposed to crypto
Output digest is 192 bytes of data: The 128 byte IV, followed by the 64 byte SHA-512 digest.
.. _secure-boot-image-signing-algorithm:
Image Signing Algorithm
~~~~~~~~~~~~~~~~~~~~~~~
Deterministic ECDSA as specified by `RFC6979`.
Deterministic ECDSA as specified by `RFC 6979 <https://tools.ietf.org/html/rfc6979>`_.
- Curve is NIST256p (openssl calls this curve "prime256v1", it is also sometimes called secp256r1).
- Hash function is SHA256.
- Key format used for storage is PEM.
- In the bootloader, the public key (for signature verification) is flashed as 64 raw bytes.
- Image signature is 68 bytes - a 4 byte version word (currently zero), followed by a 64 bytes of signature data. These 68 bytes are appended to an app image or partition table data.
Manual Commands
~~~~~~~~~~~~~~~
Secure boot is integrated into the esp-idf build system, so `make` will automatically sign an app image if secure boot is enabled. `make bootloader` will produce a bootloader digest if menuconfig is configured for it.
Secure boot is integrated into the esp-idf build system, so ``make`` will automatically sign an app image if secure boot is enabled. ``make bootloader`` will produce a bootloader digest if menuconfig is configured for it.
However, it is possible to use the `espsecure.py` tool to make standalone signatures and digests.
However, it is possible to use the ``espsecure.py`` tool to make standalone signatures and digests.
To sign a binary image::
@ -215,5 +233,3 @@ Keyfile is the 32 byte raw secure boot key for the device. To flash this digest
esptool.py write_flash 0x0 bootloader-digest.bin
.. _RFC6979: https://tools.ietf.org/html/rfc6979
.. _Flash Encryption: flash-encryption.rst