From 9ed60af1f29346f8d8192d68da13485a3eacd5e7 Mon Sep 17 00:00:00 2001 From: Kirill Chalov Date: Fri, 14 Feb 2020 17:05:48 +0800 Subject: [PATCH 1/3] Review security/flash-encryption.rst --- .../protocols/esp_http_client.rst | 2 +- docs/en/security/flash-encryption.rst | 932 ++++++++++-------- 2 files changed, 502 insertions(+), 432 deletions(-) diff --git a/docs/en/api-reference/protocols/esp_http_client.rst b/docs/en/api-reference/protocols/esp_http_client.rst index 83d4909f2..798a79c6e 100644 --- a/docs/en/api-reference/protocols/esp_http_client.rst +++ b/docs/en/api-reference/protocols/esp_http_client.rst @@ -100,7 +100,7 @@ Persistent Connections example HTTPS ----- -The HTTP client supports SSL connections using **mbedtls**, with the **url** configuration starting with ``https`` scheme (or ``transport_type = HTTP_TRANSPORT_OVER_SSL``). HTTPS support can be configured via :ref:CONFIG_ENABLE_HTTPS (enabled by default).. +The HTTP client supports SSL connections using **mbedtls**, with the **url** configuration starting with ``https`` scheme (or ``transport_type = HTTP_TRANSPORT_OVER_SSL``). HTTPS support can be configured via :ref:`CONFIG_ENABLE_HTTPS` (enabled by default).. .. note:: By providing information using HTTPS, the library will use the SSL transport type to connect to the server. If you want to verify server, then need to provide additional certificate in PEM format, and provide to ``cert_pem`` in ``esp_http_client_config_t`` diff --git a/docs/en/security/flash-encryption.rst b/docs/en/security/flash-encryption.rst index c7b471d4e..2bb175ce7 100644 --- a/docs/en/security/flash-encryption.rst +++ b/docs/en/security/flash-encryption.rst @@ -4,149 +4,161 @@ Flash Encryption :link_to_translation:`zh_CN:[中文]` -This document provides introduction to Flash encryption concept on {IDF_TARGET_NAME} and demonstrates how this feature can be used during development as well as production by the user using a sample example. The primary intention of the document is to act as a quick start guide to test and verify flash encryption operations. The details of the flash encryption block can be found in the `{IDF_TARGET_NAME} Technical reference manual`_. - -.. _{IDF_TARGET_NAME} Technical Reference Manual: {IDF_TARGET_TRM_EN_URL} +This document is a quick start guide to {IDF_TARGET_NAME}'s flash encryption feature. Using an application code example, it demonstrates how to test and verify flash encryption operations during development and production. Introduction ------------ -Flash encryption is a feature for encrypting the contents of the {IDF_TARGET_NAME}'s attached SPI flash. When flash encryption is enabled, physical readout of the SPI flash is not sufficient to recover most flash contents. Encryption is applied by flashing the {IDF_TARGET_NAME} with plaintext data, and (if encryption is enabled) the bootloader encrypts the data in place on first boot. +Flash encryption is intended for encrypting the contents of the {IDF_TARGET_NAME}'s off-chip flash memory. Once this feature is enabled, firmware is flashed as plaintext, and then the data is encrypted in place on the first boot. As a result, physical readout of flash will not be sufficient to recover most flash contents. -With flash encryption enabled, following kinds of flash data are encrypted by default: +The following types of data are encrypted by default: - - Bootloader - - Partition Table - - All "app" type partitions +- Firmware bootloader +- Partition Table +- All "app" type partitions - Other types of flash data are encrypted conditionally: +Other types of data can be encrypted conditionally: - - Secure boot bootloader digest (if secure boot is enabled) - - Any partition marked with the "encrypted" flag in the partition table +- Any partition marked with the ``encrypted`` flag in the partition table. For details, see :ref:`encrypted-partition-flag`. +- Secure Boot bootloader digest if Secure Boot is enabled (see below). .. only:: esp32 - Flash encryption is separate from the :doc:`Secure Boot ` feature, and you can use flash encryption without enabling secure boot. However, for a secure environment both should be used simultaneously. + :doc:`Secure Boot ` is a separate feature which can be used together with flash encryption to create an even more secure environment. .. important:: - For production use, flash encryption should be enabled in the "Release" mode only. -.. important:: - Enabling flash encryption limits the options for further updates of the {IDF_TARGET_NAME}. Make sure to read this document (including :ref:`flash-encryption-limitations`) and understand the implications of enabling flash encryption. + Enabling flash encryption limits the options for further updates of {IDF_TARGET_NAME}. Before using this feature, read the document and make sure to understand the implications. + .. _flash-encryption-efuse: -eFuse Used During Flash Encryption Process -------------------------------------------- -The flash encryption operation is controlled by various eFuses available on {IDF_TARGET_NAME}. Below is the list of eFuse and their description: +Relevant eFuses +--------------- - :: +The flash encryption operation is controlled by various eFuses available on {IDF_TARGET_NAME}. The list of eFuses and their descriptions is given in the table below. - eFuse Description Can be locked for Default - reading/writing Value +.. Comment: As text in cells of list-table header rows does not wrap, it is necessary to make 0 header rows and apply bold typeface to the first row. Otherwise, the table goes beyond the html page limits on the right. - .. code-block:: none +.. list-table:: eFuses Used in Flash Encryption + :widths: 25 40 10 15 10 + :header-rows: 0 - Coding scheme This 2 bit wide eFuse controls the Yes 0 - actual number of bits to be used - from BLOCK1 to derive final 256 bit - AES key. The coding scheme value is - decoded as below: - 0: 256 bits - 1: 192 bits - 2: 128 bits - Final AES key is derived based on the - FLASH_CRYPT_CONFIG value - - BLOCK1 256 bit wide eFuse block for storing Yes x - AES key - - FLASH_CRYPT_CONFIG 4 bit wide eFuse which controls the Yes 0xF - AES encryption process - - download_dis_encrypt When set, disables the flash encryption Yes 0 - operation while running in UART - download mode - - download_dis_decrypt When set, disables the flash decryption Yes 0 - operation while running in UART - download mode - - FLASH_CRYPT_CNT 7 bit eFuse which enables/disables Yes 0 - encryption at boot time - - Even number of bits set (0, 2, 4, 6): - encrypt flash at boot time - Odd number of bits set (1, 3, 5, 7): do - not encrypt flash at boot time + * - **eFuse** + - **Description** + - **Bit Depth** + - **Locking for Reading/Writing Available** + - **Default Value** + * - ``CODING_SCHEME`` + - Controls actual number of BLOCK1 bits used to derive final 256-bit AES key. Possible values: ``0`` for 256 bits, ``1`` for 192 bits, ``2`` for 128 bits. Final AES key is derived based on the ``FLASH_CRYPT_CONFIG`` value. + - 2 + - Yes + - 0 + * - ``BLOCK1`` + - AES key storage. + - 256 + - Yes + - x + * - ``FLASH_CRYPT_CONFIG`` + - Controls the AES encryption process. + - 4 + - Yes + - 0xF + * - ``download_dis_encrypt`` + - If set, disables flash encryption operation while running in Firmware Download mode. + - 1 + - Yes + - 0 + * - ``download_dis_decrypt`` + - If set, disables flash decryption while running in UART Firmware Download mode. + - 1 + - Yes + - 0 + * - ``FLASH_CRYPT_CNT`` + - Enables/disables encryption at boot time. If even number of bits set (0, 2, 4, 6) - encrypt flash at boot time. If odd number of bits set (1, 3, 5, 7) - do not encrypt flash at boot time. + - 7 + - Yes + - 0 -Read and write access to above bits is controlled by appropriate bits in ``efuse_wr_disable`` and ``efuse_rd_disable`` registers. More information about {IDF_TARGET_NAME} eFuse can be found at :doc:`eFuse manager <../api-reference/system/efuse>`. +Read and write access to eFuse bits is controlled by appropriate fields in the registers ``efuse_wr_disable`` and ``efuse_rd_disable``. For more information on {IDF_TARGET_NAME} eFuses, see :doc:`eFuse manager <../api-reference/system/efuse>`. Flash Encryption Process ------------------------ -Assuming the eFuse values are in default state and second stage bootloader is compiled to support flash encryption, the flash encryption process executes as below: +Assuming that the eFuse values are in their default states and the firmware bootloader is compiled to support flash encryption, the flash encryption process executes as shown below: -- On first power-on reset, all data in flash is un-encrypted (plaintext). First stage loader (ROM) will load the second stage loader in IRAM. -- Second stage bootloader will read the flash_crypt_cnt (=00000000b) eFuse value and since the value is 0 (even number of bits set) it will configure and enable the flash encryption block. It will also program ``FLASH_CRYPT_CFG`` eFuse to value 0xF. -- The flash encryption block will generate AES-256 bit key and store into BLOCK1 eFuse. This operation is performed in hardware and the key can not be accessed by software. -- Next the flash encryption block will encrypt the flash contents (based on partition table flag value). Encrypting in-place can take some time (up to a minute for large partitions). -- Second stage bootloader then sets the first available bit in flash_crypt_cnt (=00000001b) to mark the flash contents as encrypted (odd number of bits set). -- For :ref:`flash_enc_release_mode` second stage bootloader will program ``download_dis_encrypt``, ``download_dis_decrypt`` & ``download_dis_cache`` eFuse bits to 1 to prevent UART bootloader from decrypting the flash contents. It will also write protect the ``FLASH_CRYPT_CNT`` eFuse bits. -- For :ref:`flash_enc_development_mode` second stage bootloader will program only ``download_dis_decrypt`` & ``download_dis_cache`` eFuse bits to allow UART bootloader reflashing of encrypted binaries. Also ``FLASH_CRYPT_CNT`` eFuse bits will NOT be write protected. -- The second stage bootloader then reboots the device to start executing encrypted image. It will transparently decrypt the flash contents and load into IRAM. +#. On the first power-on reset, all data in flash is un-encrypted (plaintext). The ROM bootloader loads the firmware bootloader. +#. Firmware bootloader reads the ``FLASH_CRYPT_CNT`` eFuse value (``0b00000000``). Since the value is ``0`` (even number of bits set), it configures and enables the flash encryption block. It also sets the ``FLASH_CRYPT_CONFIG`` eFuse to 0xF. For more information on the flash encryption block, see `{IDF_TARGET_NAME} Technical reference manual`_. +#. Flash encryption block generates an AES-256 bit key and writes it into the BLOCK1 eFuse. This operation is done entirely by hardware, and the key cannot be accessed via software. +#. Flash encryption block encrypts the flash contents - partitions encrypted by default and the ones marked as ``encrypted``. Encrypting in-place can take time, up to a minute for large partitions. +#. Firmware bootloader sets the first available bit in ``FLASH_CRYPT_CNT`` (0b00000001) to mark the flash contents as encrypted. Odd number of bits is set. +#. For :ref:`flash-enc-development-mode`, the firmware bootloader sets only the eFuse bits ``download_dis_decrypt`` and ``download_dis_cache`` to allow the UART bootloader to re-flash encrypted binaries. Also, the ``FLASH_CRYPT_CNT`` eFuse bits are NOT write-protected. +#. For :ref:`flash-enc-release-mode`, the firmware bootloader sets the eFuse bits ``download_dis_encrypt``, ``download_dis_decrypt``, and ``download_dis_cache`` to 1 to prevent the UART bootloader from decrypting the flash contents. It also write-protects the ``FLASH_CRYPT_CNT`` eFuse bits. To modify this behavior, see :ref:`uart-bootloader-encryption`. +#. The device is then rebooted to start executing the encrypted image. The firmware bootloader calls the flash decryption block to decrypt the flash contents and then loads the decrypted contents into IRAM. -During development stage there is a frequent need to program different plaintext flash images and test the flash encryption process. This requires UART download mode to be able to load new plaintext images as many number of times as required. However during manufacturing or production UART download mode should not be allowed to access flash contents due to security reason. Hence this requires two different {IDF_TARGET_NAME} configurations: one for development and other for production. Following section describes :ref:`flash_enc_development_mode` and :ref:`flash_enc_release_mode` for flash encryption and a step by step process to use them. +During the development stage, there is a frequent need to program different plaintext flash images and test the flash encryption process. This requires that Firmware Download mode is able to load new plaintext images as many times as it might be needed. However, during manufacturing or production stages, Firmware Download mode should not be allowed to access flash contents for security reasons. -.. important:: - Development mode as the name suggests should be used ONLY DURING DEVELOPMENT as it does not prevent modification and possible read back of encrypted flash contents. +Hence, two different flash encryption configurations were created: for development and for production. For details on these configurations, see Section `Flash Encryption Configuration`_. + +.. _{IDF_TARGET_NAME} Technical Reference Manual: {IDF_TARGET_TRM_EN_URL} -Steps to Setup Flash Encryption -------------------------------- +Flash Encryption Configuration +------------------------------ -.. _flash_enc_development_mode: +The following flash encryption modes are available: + +- :ref:`flash-enc-development-mode` - recommended for use ONLY DURING DEVELOPMENT, as it does not prevent modification and possible readout of encrypted flash contents. +- :ref:`flash-enc-release-mode` - recommended for manufacturing and production to prevent physical readout of encrypted flash contents. + + +This section provides information on the mentioned flash encryption modes and step by step instructions on how to use them. + + +.. _flash-enc-development-mode: Development Mode ^^^^^^^^^^^^^^^^ -It is possible to run flash encryption process for development using either {IDF_TARGET_NAME} internally generated key or external host generated keys. +During development, you can encrypt flash using either an {IDF_TARGET_NAME} generated key or external host-generated key. -Using {IDF_TARGET_NAME} Generated Flash Encryption Key -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -As mentioned above :ref:`flash_enc_development_mode` allows user to download as many plaintext images using UART download mode. Following steps needs to be done to test flash encryption process: +Using {IDF_TARGET_NAME} Generated Key +""""""""""""""""""""""""""""""""""""" -- Ensure you have a {IDF_TARGET_NAME} device with default flash encryption eFuse settings as shown in :ref:`flash-encryption-efuse`. +Development mode allows you to download multiple plaintext images using Firmware Download mode. -- Navigate to flash encryption sample application in ``$IDF_PATH/examples/security/flash_encryption`` folder. This sample application will print the status of flash encryption: enabled or disabled. It will print the ``FLASH_CRYPT_CNT`` eFuse value. +To test flash encryption process, take the following steps: -- Enable flash encryption support in second stage bootloader. In :ref:`project-configuration-menu`, navigate to "Security Features". +1. Ensure that you have an {IDF_TARGET_NAME} device with default flash encryption eFuse settings as shown in :ref:`flash-encryption-efuse`. -- Select :ref:`Enable flash encryption on boot `. + See how to check :ref:`flash-encryption-status`. -- By default the mode is set for **Development**. +2. In :ref:`project-configuration-menu`, do the following: -- Select appropriate Bootloader log verbosity under Bootloader config. + - :ref:`Enable flash encryption on boot ` + - :ref:`Select ecnryption mode ` (**Development mode** by default) + - :ref:`Select the appropriate bootloader log verbosity ` + - Save the configuration and exit. .. only:: esp32 - - Update to the partition table offset may be required since after enabling flash encryption the size of bootloader is increased. See :ref:`secure-boot-bootloader-size` + Enabling flash encryption will increase the size of bootloader, which might require updating partition table offset. See :ref:`secure-boot-bootloader-size` -- Save the configuration and exit. +3. Run the command given below to build and flash the complete image. -Build and flash the complete image including: bootloader, partition table and app. These partitions are initially written to the flash unencrypted. + .. code-block:: bash - :: + idf.py flash monitor - idf.py flash monitor + The image will include the firmware bootloader, partition table, application, and other partitions marked by the user as ``encrypted``. These binaries will be written to flash memory unencrypted. Once the flashing is complete, your device will reset. On the next boot, the firmware bootloader encrypts the flash application partition and then resets. After that, the sample application is decrypted at runtime and executed. -Once the flashing is complete device will reset and on next boot second stage bootloader will encrypt the flash app partition and then reset. Now the sample application would get decrypted at runtime and executed. Below is a sample output when {IDF_TARGET_NAME} boots after flash encryption is enabled for the first time. +A sample output of the first {IDF_TARGET_NAME} boot after enabling flash encryption is given below: - :: +.. code-block:: bash --- idf_monitor on /dev/cu.SLAB_USBtoUART 115200 --- --- Quit: Ctrl+] | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H --- @@ -215,337 +227,353 @@ Once the flashing is complete device will reset and on next boot second stage bo I (13229) flash_encrypt: Flash encryption completed I (13229) boot: Resetting with flash encryption enabled... +A sample output of subsequent {IDF_TARGET_NAME} boots just mentions that flash encryption is already enabled: - Once the flash encryption is enabled, on subsequent boot the output would mention that flash encryption is already enabled. +.. code-block:: bash - :: - - rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) - configsip: 0, SPIWP:0xee - clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 - mode:DIO, clock div:2 - load:0x3fff0018,len:4 - load:0x3fff001c,len:8452 - load:0x40078000,len:13652 - ho 0 tail 12 room 4 - load:0x40080400,len:6664 - entry 0x40080764 - I (30) boot: ESP-IDF v4.0-dev-850-gc4447462d-dirty 2nd stage bootloader - I (30) boot: compile time 16:32:53 - I (31) boot: Enabling RNG early entropy source... - I (37) boot: SPI Speed : 40MHz - I (41) boot: SPI Mode : DIO - I (45) boot: SPI Flash Size : 4MB - I (49) boot: Partition Table: - I (52) boot: ## Label Usage Type ST Offset Length - I (60) boot: 0 nvs WiFi data 01 02 0000a000 00006000 - I (67) boot: 1 phy_init RF data 01 01 00010000 00001000 - I (75) boot: 2 factory factory app 00 00 00020000 00100000 - I (82) boot: End of partition table - I (86) esp_image: segment 0: paddr=0x00020020 vaddr=0x3f400020 size=0x0808c ( 32908) map - I (107) esp_image: segment 1: paddr=0x000280b4 vaddr=0x3ffb0000 size=0x01ea4 ( 7844) load - I (111) esp_image: segment 2: paddr=0x00029f60 vaddr=0x40080000 size=0x00400 ( 1024) load - 0x40080000: _WindowOverflow4 at esp-idf/esp-idf/components/freertos/xtensa_vectors.S:1778 - - I (116) esp_image: segment 3: paddr=0x0002a368 vaddr=0x40080400 size=0x05ca8 ( 23720) load - I (134) esp_image: segment 4: paddr=0x00030018 vaddr=0x400d0018 size=0x126a8 ( 75432) map - 0x400d0018: _flash_cache_start at ??:? - - I (162) esp_image: segment 5: paddr=0x000426c8 vaddr=0x400860a8 size=0x01f4c ( 8012) load - 0x400860a8: prvAddNewTaskToReadyList at esp-idf/esp-idf/components/freertos/tasks.c:4561 - - I (171) boot: Loaded app from partition at offset 0x20000 - I (171) boot: Checking flash encryption... - I (171) flash_encrypt: flash encryption is enabled (3 plaintext flashes left) - I (178) boot: Disabling RNG early entropy source... - I (184) cpu_start: Pro cpu up. - I (188) cpu_start: Application information: - I (193) cpu_start: Project name: flash-encryption - I (198) cpu_start: App version: v4.0-dev-850-gc4447462d-dirty - I (205) cpu_start: Compile time: Jun 17 2019 16:32:52 - I (211) cpu_start: ELF file SHA256: 8770c886bdf561a7... - I (217) cpu_start: ESP-IDF: v4.0-dev-850-gc4447462d-dirty - I (224) cpu_start: Starting app cpu, entry point is 0x40080e4c - 0x40080e4c: call_start_cpu1 at esp-idf/esp-idf/components/{IDF_TARGET_PATH_NAME}/cpu_start.c:265 - - I (0) cpu_start: App cpu up. - I (235) heap_init: Initializing. RAM available for dynamic allocation: - I (241) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM - I (247) heap_init: At 3FFB2EC8 len 0002D138 (180 KiB): DRAM - I (254) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM - I (260) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM - I (266) heap_init: At 40087FF4 len 0001800C (96 KiB): IRAM - I (273) cpu_start: Pro cpu start user code - I (291) cpu_start: Starting scheduler on PRO CPU. - I (0) cpu_start: Starting scheduler on APP CPU. - - Sample program to check Flash Encryption - This is {IDF_TARGET_NAME} chip with 2 CPU cores, WiFi/BT/BLE, silicon revision 1, 4MB external flash - Flash encryption feature is enabled - Flash encryption mode is DEVELOPMENT - Flash in encrypted mode with flash_crypt_cnt = 1 - Halting... - - -At this stage if user wants to update modified plaintext application image to flash in encrypted format it can be done using following command: - - :: - - idf.py encrypted-app-flash monitor - -.. _encrypt_partitions: - -Encrypt Multiple Partitions -^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -If all partitions needs to be updated in encrypted format, it can be done as - - :: - - idf.py encrypted-flash monitor - -.. _pregenerated-flash-encryption-key: - -Using Host Generated Flash Encryption Key -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -It is possible to pregenerate the flash encryption key on the host computer and burn it into the {IDF_TARGET_NAME}'s eFuse key block. This allows data to be pre-encrypted on the host and flashed to the {IDF_TARGET_NAME} without needing a plaintext flash update. This feature allows encrypted flashing in both :ref:`flash_enc_development_mode` and :ref:`flash_enc_release_mode` modes. - -.. note:: This option is not recommended for production unless a separate key is generated for each individual device. - -- Ensure you have a {IDF_TARGET_NAME} device with default flash encryption eFuse settings as shown in :ref:`flash-encryption-efuse`. - -- Generate a random key with espsecure.py:: - - espsecure.py generate_flash_encryption_key my_flash_encryption_key.bin - -- Burn the key to the device (one time only). **This must be done before first encrypted boot**, otherwise the {IDF_TARGET_NAME} will generate a random key that software can't access or modify:: - - espefuse.py --port PORT burn_key flash_encryption my_flash_encryption_key.bin - -- Enable flash encryption support in second stage bootloader. In :ref:`project-configuration-menu`, navigate to "Security Features". - -- Select :ref:`Enable flash encryption on boot `. - -- By default the mode is set for **Development**. - -- Select appropriate Bootloader log verbosity under Bootloader config. - -.. only:: esp32 - - - Update to the partition table offset may be required since after enabling flash encryption the size of bootloader is increased. See :ref:`secure-boot-bootloader-size` - -- Save the configuration and exit. - -Build and flash the complete image including: bootloader, partition table and app. These partitions are initially written to the flash unencrypted - - :: - - idf.py flash monitor - -On next boot second stage bootloader will encrypt the flash app partition and then reset. Now the sample application would get decrypted at runtime and executed. - -At this stage if user wants to update new plaintext application image to flash they should issue following command - - :: - - idf.py encrypted-app-flash monitor - -For reprogramming all partitions in encrypted format follow :ref:`encrypt_partitions`. - - -.. _flash_enc_release_mode: - -Release Mode -^^^^^^^^^^^^ - -In Release mode UART bootloader can not perform flash encryption operations and new plaintext images can be downloaded ONLY using OTA scheme which will encrypt the plaintext image before writing to flash. - -- Ensure you have a {IDF_TARGET_NAME} device with default flash encryption eFuse settings as shown in :ref:`flash-encryption-efuse`. - -- Enable flash encryption support in second stage bootloader. In :ref:`project-configuration-menu`, navigate to "Security Features". - -- Select :ref:`Enable flash encryption on boot `. - -- Select **Release Mode**, by default the mode is set for **Development**. Please note **once the Release mode is selected the ``download_dis_encrypt`` and ``download_dis_decrypt`` eFuse bits will be programmed to disable UART bootloader access to flash contents**. - -- Select appropriate Bootloader log verbosity under Bootloader config. - -.. only:: esp32 - - - Update to the partition table offset may be required since after enabling flash encryption the size of bootloader is increased. See :ref:`secure-boot-bootloader-size` - -- Save the configuration and exit. - -Build and flash the complete image including: bootloader, partition table and app. These partitions are initially written to the flash unencrypted - - :: - - idf.py flash monitor - -On next boot second stage bootloader will encrypt the flash app partition and then reset. Now the sample application should execute correctly. - -Once the flash encryption is enabled in Release mode the bootloader will write protect the ``FLASH_CRYPT_CNT`` eFuse. - -For subsequent plaintext update in field :ref:`OTA scheme ` should be used. - - -Possible Failures -^^^^^^^^^^^^^^^^^ -Once flash encryption is enabled and if the ``FLASH_CRYPT_CNT`` eFuse value has an odd number of bits set then all the partitions (which are marked with encryption flag) are expected to contain encrypted ciphertext. Below are three typical failure cases if the {IDF_TARGET_NAME} is loaded with plaintext data: - -1. In case the bootloader partition is re-updated with plaintext bootloader image the ROM loader will fail to load the bootloader and following type of failure will be displayed: - - :: - - rst:0x3 (SW_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) - flash read err, 1000 - ets_main.c 371 - ets Jun 8 2016 00:22:57 - - rst:0x7 (TG0WDT_SYS_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) - flash read err, 1000 - ets_main.c 371 - ets Jun 8 2016 00:22:57 - - rst:0x7 (TG0WDT_SYS_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) - flash read err, 1000 - ets_main.c 371 - ets Jun 8 2016 00:22:57 - - rst:0x7 (TG0WDT_SYS_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) - flash read err, 1000 - ets_main.c 371 - ets Jun 8 2016 00:22:57 - - rst:0x7 (TG0WDT_SYS_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) - flash read err, 1000 - ets_main.c 371 - ets Jun 8 2016 00:22:57 - -.. note:: This error also appears in the flash contents is erased or corrupted. - -2. In case the bootloader is encrypted but partition table is re-updated with plaintext partition table image the bootloader will fail to read the partition table and following type of failure will be displayed: - - :: - - rst:0x3 (SW_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) - configsip: 0, SPIWP:0xee - clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 - mode:DIO, clock div:2 - load:0x3fff0018,len:4 - load:0x3fff001c,len:10464 - ho 0 tail 12 room 4 - load:0x40078000,len:19168 - load:0x40080400,len:6664 - entry 0x40080764 - I (60) boot: ESP-IDF v4.0-dev-763-g2c55fae6c-dirty 2nd stage bootloader - I (60) boot: compile time 19:15:54 - I (62) boot: Enabling RNG early entropy source... - I (67) boot: SPI Speed : 40MHz - I (72) boot: SPI Mode : DIO - I (76) boot: SPI Flash Size : 4MB - E (80) flash_parts: partition 0 invalid magic number 0x94f6 - E (86) boot: Failed to verify partition table - E (91) boot: load partition table error! - -3. In case the bootloader & partition table are encrypted but application is re-updated with plaintext application image the bootloader will fail load the new application and following type of failure will be displayed: - - :: - - rst:0x3 (SW_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) + rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) configsip: 0, SPIWP:0xee clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 mode:DIO, clock div:2 load:0x3fff0018,len:4 load:0x3fff001c,len:8452 - load:0x40078000,len:13616 + load:0x40078000,len:13652 + ho 0 tail 12 room 4 load:0x40080400,len:6664 entry 0x40080764 - I (56) boot: ESP-IDF v4.0-dev-850-gc4447462d-dirty 2nd stage bootloader - I (56) boot: compile time 15:37:14 - I (58) boot: Enabling RNG early entropy source... - I (64) boot: SPI Speed : 40MHz - I (68) boot: SPI Mode : DIO - I (72) boot: SPI Flash Size : 4MB - I (76) boot: Partition Table: - I (79) boot: ## Label Usage Type ST Offset Length - I (87) boot: 0 nvs WiFi data 01 02 0000a000 00006000 - I (94) boot: 1 phy_init RF data 01 01 00010000 00001000 - I (102) boot: 2 factory factory app 00 00 00020000 00100000 - I (109) boot: End of partition table - E (113) esp_image: image at 0x20000 has invalid magic byte - W (120) esp_image: image at 0x20000 has invalid SPI mode 108 - W (126) esp_image: image at 0x20000 has invalid SPI size 11 - E (132) boot: Factory app partition is not bootable - E (138) boot: No bootable app partitions in the partition table + I (30) boot: ESP-IDF v4.0-dev-850-gc4447462d-dirty 2nd stage bootloader + I (30) boot: compile time 16:32:53 + I (31) boot: Enabling RNG early entropy source... + I (37) boot: SPI Speed : 40MHz + I (41) boot: SPI Mode : DIO + I (45) boot: SPI Flash Size : 4MB + I (49) boot: Partition Table: + I (52) boot: ## Label Usage Type ST Offset Length + I (60) boot: 0 nvs WiFi data 01 02 0000a000 00006000 + I (67) boot: 1 phy_init RF data 01 01 00010000 00001000 + I (75) boot: 2 factory factory app 00 00 00020000 00100000 + I (82) boot: End of partition table + I (86) esp_image: segment 0: paddr=0x00020020 vaddr=0x3f400020 size=0x0808c ( 32908) map + I (107) esp_image: segment 1: paddr=0x000280b4 vaddr=0x3ffb0000 size=0x01ea4 ( 7844) load + I (111) esp_image: segment 2: paddr=0x00029f60 vaddr=0x40080000 size=0x00400 ( 1024) load + 0x40080000: _WindowOverflow4 at esp-idf/esp-idf/components/freertos/xtensa_vectors.S:1778 -Key Points About Flash Encryption ---------------------------------- + I (116) esp_image: segment 3: paddr=0x0002a368 vaddr=0x40080400 size=0x05ca8 ( 23720) load + I (134) esp_image: segment 4: paddr=0x00030018 vaddr=0x400d0018 size=0x126a8 ( 75432) map + 0x400d0018: _flash_cache_start at ??:? -- The contents of the flash are encrypted using AES-256. The flash encryption key is stored in eFuse internal to the chip, and is (by default) protected from software access. + I (162) esp_image: segment 5: paddr=0x000426c8 vaddr=0x400860a8 size=0x01f4c ( 8012) load + 0x400860a8: prvAddNewTaskToReadyList at esp-idf/esp-idf/components/freertos/tasks.c:4561 -- 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. + I (171) boot: Loaded app from partition at offset 0x20000 + I (171) boot: Checking flash encryption... + I (171) flash_encrypt: flash encryption is enabled (3 plaintext flashes left) + I (178) boot: Disabling RNG early entropy source... + I (184) cpu_start: Pro cpu up. + I (188) cpu_start: Application information: + I (193) cpu_start: Project name: flash-encryption + I (198) cpu_start: App version: v4.0-dev-850-gc4447462d-dirty + I (205) cpu_start: Compile time: Jun 17 2019 16:32:52 + I (211) cpu_start: ELF file SHA256: 8770c886bdf561a7... + I (217) cpu_start: ESP-IDF: v4.0-dev-850-gc4447462d-dirty + I (224) cpu_start: Starting app cpu, entry point is 0x40080e4c + 0x40080e4c: call_start_cpu1 at esp-idf/esp-idf/components/{IDF_TARGET_PATH_NAME}/cpu_start.c:265 -- Flash access is transparent via the flash cache mapping feature of {IDF_TARGET_NAME} - any flash regions which are mapped to the address space will be transparently decrypted when read. + I (0) cpu_start: App cpu up. + I (235) heap_init: Initializing. RAM available for dynamic allocation: + I (241) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM + I (247) heap_init: At 3FFB2EC8 len 0002D138 (180 KiB): DRAM + I (254) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM + I (260) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM + I (266) heap_init: At 40087FF4 len 0001800C (96 KiB): IRAM + I (273) cpu_start: Pro cpu start user code + I (291) cpu_start: Starting scheduler on PRO CPU. + I (0) cpu_start: Starting scheduler on APP CPU. - It may be desirable for some data partitions to remain unencrypted for ease of access, or to use flash-friendly update algorithms that are ineffective if the data is encrypted. NVS partitions for non-volatile storage cannot be encrypted since NVS library is not directly compatible with flash encryption. Refer to :ref:`NVS Encryption ` for more details. + Sample program to check Flash Encryption + This is {IDF_TARGET_NAME} chip with 2 CPU cores, WiFi/BT/BLE, silicon revision 1, 4MB external flash + Flash encryption feature is enabled + Flash encryption mode is DEVELOPMENT + Flash in encrypted mode with flash_crypt_cnt = 1 + Halting... + +At this stage, if you need to update and re-flash binaries, see :ref:`encrypt-partitions`. -- If flash encryption may be enabled, the programmer must take certain precautions when writing code that :ref:`uses encrypted flash `. +.. _pregenerated-flash-encryption-key: -- If secure boot is enabled, reflashing the bootloader of an encrypted device requires a "Reflashable" secure boot digest (see :ref:`flash-encryption-and-secure-boot`). +Using Host Generated Key +"""""""""""""""""""""""" + +It is possible to pre-generate a flash encryption key on the host computer and burn it into the {IDF_TARGET_NAME}'s ``BLOCK1`` eFuse. This allows you to pre-encrypt data on the host and flash already encrypted data without needing a plaintext flash update. This feature can be used in both :ref:`flash-enc-development-mode` and :ref:`flash-enc-release-mode`. Without a pre-generated key, data is flashed in plaintext and then {IDF_TARGET_NAME} encrypts the data in-place. + +.. note:: + + This option is not recommended for production, unless a separate key is generated for each individual device. + +To use a host generated key, take the following steps: + +1. Ensure that you have an {IDF_TARGET_NAME} device with default flash encryption eFuse settings as shown in :ref:`flash-encryption-efuse`. + + See how to check :ref:`flash-encryption-status`. + +2. Generate a random key by running: + + .. code-block:: bash + + espsecure.py generate_flash_encryption_key my_flash_encryption_key.bin + +3. **Before the first encrypted boot**, burn the key into your device's BLOCK1 eFuse using the command below. This action can be done **only once**. + + .. code-block:: bash + + espefuse.py --port PORT burn_key flash_encryption my_flash_encryption_key.bin + + If the key is not burned and the device is started after enabling flash encryption, the {IDF_TARGET_NAME} will generate a random key that software cannot access or modify. + +4. In :ref:`project-configuration-menu`, do the following: + + - :ref:`Enable flash encryption on boot ` + - :ref:`Select ecnryption mode ` (**Development mode** by default) + - :ref:`Select the appropriate bootloader log verbosity ` + - Save the configuration and exit. .. only:: esp32 - .. note:: The bootloader app binary ``bootloader.bin`` may become too large when both secure boot and flash encryption are enabled. See :ref:`secure-boot-bootloader-size`. + Enabling flash encryption will increase the size of bootloader, which might require updating partition table offset. See :ref:`secure-boot-bootloader-size` -.. important:: - Do not interrupt power to the {IDF_TARGET_NAME} 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. +5. Run the command given below to build and flash the complete. + + .. code-block:: bash + + idf.py flash monitor + + The image will include the firmware bootloader, partition table, application, and other partitions marked by the user as ``encrypted``. These binaries will be written to flash memory unencrypted. Once the flashing is complete, your device will reset. On the next boot, the firmware bootloader encrypts the flash application partition and then resets. After that, the sample application is decrypted at runtime and executed. + +At this stage, if you need to update and re-flash binaries, see :ref:`encrypt-partitions`. -.. _using-encrypted-flash: +.. _encrypt-partitions: -Using Encrypted Flash ---------------------- +Re-flashing Updated Partitions +"""""""""""""""""""""""""""""" -{IDF_TARGET_NAME} app code can check if flash encryption is currently enabled by calling :cpp:func:`esp_flash_encryption_enabled`. Also, device can identify the flash encryption mode by calling :cpp:func:`esp_get_flash_encryption_mode`. +If you update your application code (done in plaintext) and want to re-flash it, you will need to encrypt it before flashing. To encrypt the application and flash it in one step, run: + +.. code-block:: bash + + idf.py encrypted-app-flash monitor + +If all partitions needs to be updated in encrypted format, run: + +.. code-block:: bash + + idf.py encrypted-flash monitor + + +.. _flash-enc-release-mode: + +Release Mode +^^^^^^^^^^^^ + +In Release mode, UART bootloader cannot perform flash encryption operations. New plaintext images can ONLY be downloaded using the over-the-air (OTA) scheme which will encrypt the plaintext image before writing to flash. + +To use this mode, take the following steps: + +1. Ensure that you have an {IDF_TARGET_NAME} device with default flash encryption eFuse settings as shown in :ref:`flash-encryption-efuse`. + + See how to check :ref:`flash-encryption-status`. + +2. In :ref:`project-configuration-menu`, do the following: + + - :ref:`Enable flash encryption on boot ` + - :ref:`Select Release mode ` (Note that once Release mode is selected, the ``download_dis_encrypt`` and ``download_dis_decrypt`` eFuse bits will be burned to disable UART bootloader access to flash contents) + - :ref:`Select the appropriate bootloader log verbosity ` + - Save the configuration and exit. + +.. only:: esp32 + + Enabling flash encryption will increase the size of bootloader, which might require updating partition table offset. See :ref:`secure-boot-bootloader-size` + +3. Run the command given below to build and flash the complete image. + + .. code-block:: bash + + idf.py flash monitor + + The image will include the firmware bootloader, partition table, application, and other partitions marked by the user as ``encrypted``. These binaries will be written to flash memory unencrypted. Once the flashing is complete, your device will reset. On the next boot, the firmware bootloader encrypts the flash application partition and then resets. After that, the sample application is decrypted at runtime and executed. + +Once the flash encryption is enabled in Release mode, the bootloader will write-protect the ``FLASH_CRYPT_CNT`` eFuse. + +For subsequent plaintext field updates, use :ref:`OTA scheme `. + + +Possible Failures +----------------- + +Once flash encryption is enabled, the ``FLASH_CRYPT_CNT`` eFuse value will have an odd number of bits set. It means that all the partitions marked with the encryption flag are expected to contain encrypted ciphertext. Below are the three typical failure cases if the {IDF_TARGET_NAME} is erroneously loaded with plaintext data: + +1. If the bootloader partition is re-flashed with a **plaintext firmware bootloader image**, the ROM bootloader will fail to load the firmware bootloader resulting in the following failure: + + .. code-block:: bash + + rst:0x3 (SW_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) + flash read err, 1000 + ets_main.c 371 + ets Jun 8 2016 00:22:57 + + rst:0x7 (TG0WDT_SYS_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) + flash read err, 1000 + ets_main.c 371 + ets Jun 8 2016 00:22:57 + + rst:0x7 (TG0WDT_SYS_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) + flash read err, 1000 + ets_main.c 371 + ets Jun 8 2016 00:22:57 + + rst:0x7 (TG0WDT_SYS_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) + flash read err, 1000 + ets_main.c 371 + ets Jun 8 2016 00:22:57 + + rst:0x7 (TG0WDT_SYS_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) + flash read err, 1000 + ets_main.c 371 + ets Jun 8 2016 00:22:57 + +.. note:: + + This error also appears if the flash contents are erased or corrupted. + +2. If the firmware bootloader is encrypted, but the partition table is re-flashed with a **plaintext partition table image**, the bootloader will fail to read the partition table resulting in the following failure: + + .. code-block:: bash + + rst:0x3 (SW_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) + configsip: 0, SPIWP:0xee + clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 + mode:DIO, clock div:2 + load:0x3fff0018,len:4 + load:0x3fff001c,len:10464 + ho 0 tail 12 room 4 + load:0x40078000,len:19168 + load:0x40080400,len:6664 + entry 0x40080764 + I (60) boot: ESP-IDF v4.0-dev-763-g2c55fae6c-dirty 2nd stage bootloader + I (60) boot: compile time 19:15:54 + I (62) boot: Enabling RNG early entropy source... + I (67) boot: SPI Speed : 40MHz + I (72) boot: SPI Mode : DIO + I (76) boot: SPI Flash Size : 4MB + E (80) flash_parts: partition 0 invalid magic number 0x94f6 + E (86) boot: Failed to verify partition table + E (91) boot: load partition table error! + +3. If the bootloader and partition table are encrypted, but the application is re-flashed with a **plaintext application image**, the bootloader will fail to load the application resulting in the following failure: + + .. code-block:: bash + + rst:0x3 (SW_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) + configsip: 0, SPIWP:0xee + clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 + mode:DIO, clock div:2 + load:0x3fff0018,len:4 + load:0x3fff001c,len:8452 + load:0x40078000,len:13616 + load:0x40080400,len:6664 + entry 0x40080764 + I (56) boot: ESP-IDF v4.0-dev-850-gc4447462d-dirty 2nd stage bootloader + I (56) boot: compile time 15:37:14 + I (58) boot: Enabling RNG early entropy source... + I (64) boot: SPI Speed : 40MHz + I (68) boot: SPI Mode : DIO + I (72) boot: SPI Flash Size : 4MB + I (76) boot: Partition Table: + I (79) boot: ## Label Usage Type ST Offset Length + I (87) boot: 0 nvs WiFi data 01 02 0000a000 00006000 + I (94) boot: 1 phy_init RF data 01 01 00010000 00001000 + I (102) boot: 2 factory factory app 00 00 00020000 00100000 + I (109) boot: End of partition table + E (113) esp_image: image at 0x20000 has invalid magic byte + W (120) esp_image: image at 0x20000 has invalid SPI mode 108 + W (126) esp_image: image at 0x20000 has invalid SPI size 11 + E (132) boot: Factory app partition is not bootable + E (138) boot: No bootable app partitions in the partition table + + +.. _flash-encryption-status: + +{IDF_TARGET_NAME} Flash Encryption Status +----------------------------------------- + +1. Ensure that you have an {IDF_TARGET_NAME} device with default flash encryption eFuse settings as shown in :ref:`flash-encryption-efuse`. + +To check if flash encryption on your {IDF_TARGET_NAME} device is enabled, do one of the following: + +- flash the application example :example:`security/flash_encryption` onto your device. This application prints the ``FLASH_CRYPT_CNT`` eFuse value and if flash encryption is enabled or disabled. + +- :doc:`Find the serial port name <../get-started/establish-serial-connection>` under which your {IDF_TARGET_NAME} device is connected, replace ``PORT`` with your port name in the following command, and run it: + + .. code-block:: bash + + espefuse.py -p PORT summary + + +.. _reading-writing-content: + +Reading and Writing Data in Encrypted Flash +------------------------------------------- + +{IDF_TARGET_NAME} application code can check if flash encryption is currently enabled by calling :cpp:func:`esp_flash_encryption_enabled`. Also, a device can identify the flash encryption mode by calling :cpp:func:`esp_get_flash_encryption_mode`. + +Once flash encryption is enabled, be more careful with accessing flash contents from code. -Once flash encryption is enabled, some care needs to be taken when accessing flash contents from code. Scope of Flash Encryption ^^^^^^^^^^^^^^^^^^^^^^^^^ -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: +Whenever the ``FLASH_CRYPT_CNT`` eFuse is set to a value with an odd number of bits, all flash content accessed via the MMU's flash cache is transparently decrypted. It includes: - Executable application code in flash (IROM). - All read-only data stored in flash (DROM). - Any data accessed via :cpp:func:`spi_flash_mmap`. -- The software bootloader image when it is read by the ROM bootloader. +- The firmware 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. -Reading Encrypted Flash -^^^^^^^^^^^^^^^^^^^^^^^ -To read data without using a flash cache MMU mapping, we recommend using the partition read function :cpp: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 :cpp:func:`spi_flash_read` is not decrypted. -- Data read via ROM function :cpp: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 from the perspective of flash encryption. It is up to the library to provide encryption feature if required. Refer to :ref:`NVS Encryption ` for more details. + The MMU flash cache unconditionally decrypts all existing data. Data which is stored unencrypted in flash memory will also be "transparently decrypted" via the flash cache and will appear to software as random garbage. -Writing Encrypted Flash -^^^^^^^^^^^^^^^^^^^^^^^ +Reading from Encrypted Flash +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Where possible, we recommend using the partition write function ``esp_partition_write``. When using this function, data will only be encrypted when writing to encrypted partitions. Data will be written to other partitions unencrypted. In this way, software can access encrypted and non-encrypted flash in the same way. +To read data without using a flash cache MMU mapping, you can use the partition read function :cpp:func:`esp_partition_read`. This function will only decrypt data when it is read from an encrypted partition. Data read from unencrypted partitions will not be decrypted. In this way, software can access encrypted and non-encrypted flash in the same way. -The ``esp_spi_flash_write`` function will write data when the write_encrypted parameter is set to true. Otherwise, data will be written unencrypted. +You can also use the following SPI flash API functions: -The ROM function ``esp_rom_spiflash_write_encrypted`` will write encrypted data to flash, the ROM function ``SPIWrite`` will write unencrypted to flash. (these function are not supported in esp-idf apps). +- :cpp:func:`esp_flash_read` to read raw (encrypted) data which will not be decrypted +- :cpp:func:`esp_flash_read_encrypted` to read and decrypt data + +The ROM function :cpp:func:`SPIRead` can read data without decryption, however, this function is not supported in esp-idf applications. + +Data stored using the Non-Volatile Storage (NVS) API is always stored and read decrypted from the perspective of flash encryption. It is up to the library to provide encryption feature if required. Refer to :ref:`NVS Encryption ` for more details. + + +Writing to Encrypted Flash +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +It is recommended to use the partition write function :cpp:func:`esp_partition_write`. This function will only encrypt data when it is written to an encrypted partition. Data written to unencrypted partitions will not be encrypted. In this way, software can access encrypted and non-encrypted flash in the same way. + +You can also pre-encrypt and write data using the function :cpp:func:`esp_flash_write_encrypted` + +Also, the following ROM function exist but not supported in esp-idf applications: + +- ``esp_rom_spiflash_write_encrypted`` pre-encrypts and writes data to flash +- ``SPIWrite`` writes unencrypted data to flash + +Since data is encrypted in blocks, the minimum write size for encrypted data is 16 bytes and the alignment is also 16 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: @@ -557,80 +585,111 @@ Updating Encrypted Flash OTA Updates ^^^^^^^^^^^ -OTA updates to encrypted partitions will automatically write encrypted, as long as the ``esp_partition_write`` function is used. +OTA updates to encrypted partitions will automatically write encrypted data if the function :cpp:func:`esp_partition_write` is used. -Any app image which will be OTA updated onto a device with flash encryption enabled requires :ref:`Enable flash encryption on boot ` option to be enabled in the app configuration as well, when building the app. +Before building the application image for OTA updating of an already encrypted device, enable the option :ref:`Enable flash encryption on boot ` in project configuration menu. + +For general information about ESP-IDF OTA updates, please refer to :doc:`OTA <../api-reference/system/ota>` -Please refer to :doc:`OTA <../api-reference/system/ota>` for general information about ESP-IDF OTA updates. .. _updating-encrypted-flash-serial: + Disabling Flash Encryption -------------------------- -If you've accidentally enabled flash encryption for some reason, the next flash of plaintext data will soft-brick the {IDF_TARGET_NAME} (the device will reboot continuously, printing the error ``flash read err, 1000``). +If flash encryption was enabled accidentally, flashing of plaintext data will soft-brick the {IDF_TARGET_NAME}. The device will reboot continuously, printing the error ``flash read err, 1000``. -If flash encryption is enabled in Development mode, you can disable flash encryption again by writing ``FLASH_CRYPT_CNT`` eFuse. This can only be done three times per chip. +For flash encryption in Development mode, encryption can be disabled by burning the ``FLASH_CRYPT_CNT`` eFuse. It can only be done three times per chip by taking the following steps: -- First, open :ref:`project-configuration-menu` and disable :ref:`Enable flash encryption boot ` under "Security Features". -- Exit menuconfig and save the new configuration. -- Run ``idf.py 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 ``idf.py 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 FLASH_CRYPT_CNT:: - espefuse.py burn_efuse FLASH_CRYPT_CNT +#. In :ref:`project-configuration-menu`, disable :ref:`Enable flash encryption on boot `, then save and exit. +#. Open project configuration menu again and **double-check** that you have disabled this option! If this option is left enabled, the bootloader will immediately re-enable encryption when it boots. +#. With flash encryption disabled, build and flash the new bootloader and application by running ``idf.py flash``. +#. Use ``espefuse.py`` (in ``components/esptool_py/esptool``) to disable the ``FLASH_CRYPT_CNT`` by running: + + .. code-block:: bash + + espefuse.py burn_efuse FLASH_CRYPT_CNT + +Reset the {IDF_TARGET_NAME}. Flash encryption will be disabled, and the bootloader will boot as usual. + + +Key Points About Flash Encryption +--------------------------------- + +- Flash memory contents are encrypted using AES-256. The flash encryption key is stored in the ``BLOCK1`` eFuse internal to the chip and, by default, is protected from software access. + +- 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 that every 32-byte block (two consecutive 16 byte AES blocks) is encrypted with a unique key derived from the flash encryption key. + +- Flash access is transparent via the flash cache mapping feature of {IDF_TARGET_NAME} - any flash regions which are mapped to the address space will be transparently decrypted when read. + + Some data partitions might need to remain unencrypted for ease of access or might require the use of flash-friendly update algorithms which are ineffective if the data is encrypted. NVS partitions for non-volatile storage cannot be encrypted since the NVS library is not directly compatible with flash encryption. For details, refer to :ref:`NVS Encryption `. + +- If flash encryption might be used in future, the programmer must keep it in mind and take certain precautions when writing code that :ref:`uses encrypted flash `. + +- If secure boot is enabled, re-flashing the bootloader of an encrypted device requires a "Re-flashable" secure boot digest (see :ref:`flash-encryption-and-secure-boot`). + + .. only:: esp32 + + The firmware bootloader app binary ``bootloader.bin`` might become too large if both secure boot and flash encryption are enabled. See :ref:`secure-boot-bootloader-size`. + + .. important:: + + Do not interrupt power to the {IDF_TARGET_NAME} while the first boot encryption pass is running. If power is interrupted, the flash contents will be corrupted and will require flashing with unencrypted data again. In this case, re-flashing will not count towards the flashing limit. -Reset the {IDF_TARGET_NAME} 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 protects firmware against unauthorised readout and modification. It is important to understand the limitations of the flash encryption feature: -- 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, ensure proper procedure is followed and don't share the same key between all production devices. +- **Flash encryption is only as strong as the key**. It is recommended to generate keys on the device during first boot (default behaviour). If generating keys on a host computer, ensure to follow a proper procedure and do not use the same key for produced devices. -- Not all data is stored encrypted. If storing data on flash, check if the method you are using (library, API, etc.) supports flash encryption. +- **Not all data is stored encrypted**. If storing data in flash memory, make sure that 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 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 (i.e. to tell if two devices are probably running the same firmware version). +- **Flash encryption does not mask the high-level layout of flash**. This is because the same AES key is used for every pair of adjacent 16-byte AES blocks. If these blocks have identical content (such as empty or padding areas), these will produce matching pairs of encrypted blocks. It might allow an attacker to make high-level comparisons of firmware on encrypted devices, i.e., to tell if two devices are probably running the same firmware version. -- For the same reason, an attacker can always tell when a pair of adjacent 16 byte blocks (32 byte aligned) contain two identical 16 byte sequences. 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). :ref:`NVS Encryption ` deals with this and is suitable for many uses. +- **Flash encryption does not mask the high-level layout of flash**. Each pair of adjacent 16-byte AES blocks is encrypted with the same AES key. If these blocks have identical content (such as empty or padding areas), the result will be matching pairs of encrypted blocks. It might allow an attacker to make high-level comparisons of firmware on encrypted devices, i.e., to tell if two devices are probably running the same firmware version. + +- **An attacker can tell if a pair of adjacent 16-byte blocks (32 byte aligned) contains two identical 16-byte sequences** (the same reason as the previous bullet point). Keep this in mind if storing sensitive data in flash memory. While designing your flash storage, it is sufficient to use a counter byte or some other non-identical value every 16 bytes. :ref:`NVS Encryption ` deals with this and is suitable for many uses. .. only:: esp32 - - Flash encryption alone may not prevent an attacker from modifying the firmware of the device. To prevent unauthorised firmware from running on the device, use flash encryption in combination with :doc:`Secure Boot `. + - **Flash encryption alone may not prevent an attacker from modifying the firmware on the device**. To prevent unauthorized firmware from running on the device, use flash encryption in combination with :doc:`Secure Boot `. .. _flash-encryption-and-secure-boot: Flash Encryption and Secure Boot --------------------------------- -It is recommended to use flash encryption and secure boot together. However, if Secure Boot is enabled then additional restrictions apply to reflashing the device: +It is recommended to use flash encryption in combination with Secure Boot. However, if Secure Boot is enabled, additional restrictions apply to device re-flashing: -- :ref:`updating-encrypted-flash-ota` are not restricted (provided the new app is signed correctly with the Secure Boot signing key). +- :ref:`updating-encrypted-flash-ota` are not restricted, provided that the new app is signed correctly with the Secure Boot signing key. .. only:: esp32 - - :ref:`Plaintext serial flash updates ` are only possible if the :ref:`Reflashable ` Secure Boot mode is selected and a Secure Boot key was pre-generated and burned to the {IDF_TARGET_NAME} (refer to :ref:`Secure Boot ` docs.). In this configuration, ``idf.py bootloader`` will produce a pre-digested bootloader and secure boot digest file for flashing at offset 0x0. When following the plaintext serial reflashing steps it is necessary to re-flash this file before flashing other plaintext data. + - :ref:`Plaintext serial flash updates ` are only possible if the :ref:`Re-flashable ` Secure Boot mode is selected and a Secure Boot key was pre-generated and burned to the {IDF_TARGET_NAME} (refer to :ref:`Secure Boot `). In such configuration, ``idf.py bootloader`` will produce a pre-digested bootloader and secure boot digest file for flashing at offset 0x0. When following the plaintext serial re-flashing steps it is necessary to re-flash this file before flashing other plaintext data. + - :ref:`Re-flashing via Pregenerated Flash Encryption Key ` is still possible, provided the bootloader is not re-flashed. Re-flashing the bootloader requires the same :ref:`Re-flashable ` option to be enabled in the Secure Boot config. - - :ref:`Reflashing via Pregenerated Flash Encryption Key ` is still possible, provided the bootloader is not reflashed. Reflashing the bootloader requires the same :ref:`Reflashable ` option to be enabled in the Secure Boot config. .. _flash-encryption-advanced-features: Advanced Features ----------------- -The following information is useful for advanced use of flash encryption: +The following section covers advanced features of flash encryption. + +.. _encrypted-partition-flag: Encrypted Partition Flag ^^^^^^^^^^^^^^^^^^^^^^^^ -Some partitions are encrypted by default. Otherwise, it is possible to mark any partition as requiring encryption: +Some partitions are encrypted by default. Other partitions can be marked in the partition table description as requiring encryption by adding the flag ``encrypted`` to the partitions' flag field. As a result, data in these marked partitions will be treated as encrypted in the same manner as an app partition. -In the :doc:`partition table <../api-guides/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):: +.. code-block:: bash # Name, Type, SubType, Offset, Size, Flags nvs, data, nvs, 0x9000, 0x6000 @@ -638,52 +697,62 @@ 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 tables include any encrypted data partitions. +For details on partition table description, see :doc:`partition table <../api-guides/partition-tables>`. -- It is not necessary to mark "app" partitions as encrypted, they are always treated as encrypted. +Further information about encryption of partitions: -- The "encrypted" flag does nothing if flash encryption is not enabled. +- Default partition tables do not include any encrypted data partitions. +- With enabled flash encryption, the ``app`` partition is always treated as encrypted and does not require marking. +- If flash encryption is not enabled, the flag "encrypted" has no effect. +- You can also consider protecting ``phy_init`` data from physical access, readout, or modification, by marking the optional ``phy`` partition with the flag ``encrypted``. +- The ``nvs`` partition cannot be encrypted, because the NVS library is not directly compatible with flash encryption. -- It is possible to mark the optional ``phy`` partition with ``phy_init`` data as encrypted, if you wish to protect this data from physical access readout or modification. - -- It is not possible to mark the ``nvs`` partition as encrypted. .. _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``: +On the first boot, the flash encryption process burns by default the following eFuses: -- ``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_CACHE`` disables the entire MMU flash cache when running in UART bootloader mode. +- ``DISABLE_DL_ENCRYPT`` which disables flash encryption operation when running in UART bootloader boot mode. +- ``DISABLE_DL_DECRYPT`` which disables transparent flash decryption when running in UART bootloader mode, even if the eFuse ``FLASH_CRYPT_CNT`` is set to enable it in normal operation. +- ``DISABLE_DL_CACHE`` which 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. For example:: +However, before the first boot you can choose to keep any of these features enabled by burning only selected eFuses and write-protect the rest of eFuses with unset value 0. For example: + +.. code-block:: bash 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. For this reason, it's necessary to set any bits before write-protecting.) +.. note:: + + Set all appropriate bits before write-protecting! + + Write protection of all the three eFuses is controlled by one bit. It means that write-protecting one eFuse bit will inevitably write-protect all unset eFuse bits. + +Write protecting these eFuses to keep them unset is not currently very useful, as ``esptool.py`` does not support reading encrypted flash. .. important:: - Write protecting these eFuses to keep them unset is not currently very useful, as ``esptool.py`` does not support 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. + Leaving ``DISABLE_DL_DECRYPT`` unset (0) makes flash encryption useless. + + An attacker with physical access to the chip 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. +The eFuse ``FLASH_CRYPT_CONFIG`` determines the number of bits in the flash encryption key which are "tweaked" with the block offset. For details, see :ref:`flash-encryption-algorithm`. -First boot of the bootloader always sets this value to the maximum `0xF`. +On the first boot or the firmware bootloader, this value is set 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 possible to burn this eFuse manually and write protect it before the first boot in order to select different tweak values. However, 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. +It is strongly recommended to never write-protect ``FLASH_CRYPT_CONFIG`` when it is unset. Otherwise, its value will remain zero permanently, and no bits in the flash encryption key will be tweaked. As a result, the flash encryption algorithm will be equivalent to AES ECB mode. JTAG Debugging ^^^^^^^^^^^^^^ @@ -702,29 +771,30 @@ The following sections provide some reference information about the operation of Flash Encryption Algorithm ^^^^^^^^^^^^^^^^^^^^^^^^^^ -- AES-256 operates on 16 byte blocks of data. The flash encryption engine encrypts and decrypts data in 32 byte blocks, two AES blocks in series. +- AES-256 operates on 16-byte blocks of data. The flash encryption engine encrypts and decrypts data in 32-byte blocks - two AES blocks in series. -- The main flash encryption key is stored in eFuse (BLOCK1) and by default is protected from further writes or software readout. +- The main flash encryption key is stored in the ``BLOCK1`` eFuse and, by default, is protected from further writes or software readout. -- AES-256 key size is 256 bits (32 bytes), read from eFuse block 1. The hardware AES engine uses the key in reversed byte order to the order stored in the eFuse block. - - If ``CODING_SCHEME`` eFuse is set to 0 (default "None" Coding Scheme) then the eFuse key block is 256 bits and the key is stored as-is (in reversed byte order). - - If ``CODING_SCHEME`` eFuse is set to 1 (3/4 Encoding) then the eFuse key block is 192 bits (in reversed byte order), so overall entropy is reduced. The hardware flash encryption still operates on a 256-bit key, after being read (and un-reversed), the key is extended by as ``key = key[0:255] + key[64:127]``. +- AES-256 key size is 256 bits (32 bytes) read from the ``BLOCK1`` eFuse. The hardware AES engine uses the key in reversed byte order as compared to the storage order in ``BLOCK1``. -- AES algorithm is used inverted in flash encryption, so the flash encryption "encrypt" operation is AES decrypt and the "decrypt" operation is AES encrypt. This is for performance reasons and does not alter the effectiveness of the algorithm. + - If the ``CODING_SCHEME`` eFuse is set to ``0`` (default, "None" Coding Scheme) then the eFuse key block is 256 bits and the key is stored as-is (in reversed byte order). + - If the ``CODING_SCHEME`` eFuse is set to ``1`` (3/4 Encoding) then the eFuse key block is 192 bits (in reversed byte order), so overall entropy is reduced. The hardware flash encryption still operates on a 256-bit key, after being read (and un-reversed), the key is extended as ``key = key[0:255] + key[64:127]``. -- 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"). +- AES algorithm is used inverted in flash encryption, so the flash encryption "encrypt" operation is AES decrypt and the "decrypt" operation is AES encrypt. This is for performance reasons and does not alter the effeciency of the algorithm. -- 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: +- 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 ``BLOCK1``, XORed with the offset of this block in the flash (a "key tweak"). + +- The specific tweak depends on the ``FLASH_CRYPT_CONFIG`` eFuse setting. This is a 4-bit eFuse where each bit enables XORing of a particular range of the key bits: - Bit 1, bits 0-66 of the key are XORed. - Bit 2, bits 67-131 of the key are XORed. - 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 :ref:`setting-flash-crypt-config` for details. + It is recommended that ``FLASH_CRYPT_CONFIG`` is always left at the default value ``0xF``, so that all key bits are XORed with the block offset. For details, see :ref:`setting-flash-crypt-config`. - 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 the ``espsecure.py`` source code for the complete mapping. +- 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 complete mapping. - To see the full flash encryption algorithm implemented in Python, refer to the `_flash_encryption_operation()` function in the ``espsecure.py`` source code. From 0cc9ffb8f7de417efb59aa8bba115863ce86851d Mon Sep 17 00:00:00 2001 From: Kirill Chalov Date: Mon, 9 Mar 2020 19:21:01 +0800 Subject: [PATCH 2/3] Implement comments and add info on ESP32S2 --- .../protocols/esp_http_client.rst | 2 +- docs/en/security/flash-encryption.rst | 153 ++++++++++++------ 2 files changed, 102 insertions(+), 53 deletions(-) diff --git a/docs/en/api-reference/protocols/esp_http_client.rst b/docs/en/api-reference/protocols/esp_http_client.rst index 798a79c6e..69c0c1734 100644 --- a/docs/en/api-reference/protocols/esp_http_client.rst +++ b/docs/en/api-reference/protocols/esp_http_client.rst @@ -100,7 +100,7 @@ Persistent Connections example HTTPS ----- -The HTTP client supports SSL connections using **mbedtls**, with the **url** configuration starting with ``https`` scheme (or ``transport_type = HTTP_TRANSPORT_OVER_SSL``). HTTPS support can be configured via :ref:`CONFIG_ENABLE_HTTPS` (enabled by default).. +The HTTP client supports SSL connections using **mbedtls**, with the **url** configuration starting with ``https`` scheme (or ``transport_type = HTTP_TRANSPORT_OVER_SSL``). HTTPS support can be configured via :ref:`CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS` (enabled by default). .. note:: By providing information using HTTPS, the library will use the SSL transport type to connect to the server. If you want to verify server, then need to provide additional certificate in PEM format, and provide to ``cert_pem`` in ``esp_http_client_config_t`` diff --git a/docs/en/security/flash-encryption.rst b/docs/en/security/flash-encryption.rst index 2bb175ce7..5b7ab44f3 100644 --- a/docs/en/security/flash-encryption.rst +++ b/docs/en/security/flash-encryption.rst @@ -1,10 +1,9 @@ - Flash Encryption ================ :link_to_translation:`zh_CN:[中文]` -This document is a quick start guide to {IDF_TARGET_NAME}'s flash encryption feature. Using an application code example, it demonstrates how to test and verify flash encryption operations during development and production. +This is a quick start guide to {IDF_TARGET_NAME}'s flash encryption feature. Using an application code example, it demonstrates how to test and verify flash encryption operations during development and production. Introduction @@ -12,7 +11,7 @@ Introduction Flash encryption is intended for encrypting the contents of the {IDF_TARGET_NAME}'s off-chip flash memory. Once this feature is enabled, firmware is flashed as plaintext, and then the data is encrypted in place on the first boot. As a result, physical readout of flash will not be sufficient to recover most flash contents. -The following types of data are encrypted by default: +With flash encryption enabled, the following types of data are encrypted by default: - Firmware bootloader - Partition Table @@ -41,48 +40,84 @@ The flash encryption operation is controlled by various eFuses available on {IDF .. Comment: As text in cells of list-table header rows does not wrap, it is necessary to make 0 header rows and apply bold typeface to the first row. Otherwise, the table goes beyond the html page limits on the right. -.. list-table:: eFuses Used in Flash Encryption - :widths: 25 40 10 15 10 - :header-rows: 0 +.. only:: esp32 - * - **eFuse** - - **Description** - - **Bit Depth** - - **Locking for Reading/Writing Available** - - **Default Value** - * - ``CODING_SCHEME`` - - Controls actual number of BLOCK1 bits used to derive final 256-bit AES key. Possible values: ``0`` for 256 bits, ``1`` for 192 bits, ``2`` for 128 bits. Final AES key is derived based on the ``FLASH_CRYPT_CONFIG`` value. - - 2 - - Yes - - 0 - * - ``BLOCK1`` - - AES key storage. - - 256 - - Yes - - x - * - ``FLASH_CRYPT_CONFIG`` - - Controls the AES encryption process. - - 4 - - Yes - - 0xF - * - ``download_dis_encrypt`` - - If set, disables flash encryption operation while running in Firmware Download mode. - - 1 - - Yes - - 0 - * - ``download_dis_decrypt`` - - If set, disables flash decryption while running in UART Firmware Download mode. - - 1 - - Yes - - 0 - * - ``FLASH_CRYPT_CNT`` - - Enables/disables encryption at boot time. If even number of bits set (0, 2, 4, 6) - encrypt flash at boot time. If odd number of bits set (1, 3, 5, 7) - do not encrypt flash at boot time. - - 7 - - Yes - - 0 + .. list-table:: eFuses Used in Flash Encryption + :widths: 25 40 10 15 10 + :header-rows: 0 + + * - **eFuse** + - **Description** + - **Bit Depth** + - **Locking for Reading/Writing Available** + - **Default Value** + * - ``CODING_SCHEME`` + - Controls actual number of BLOCK1 bits used to derive final 256-bit AES key. Possible values: ``0`` for 256 bits, ``1`` for 192 bits, ``2`` for 128 bits. Final AES key is derived based on the ``FLASH_CRYPT_CONFIG`` value. + - 2 + - Yes + - 0 + * - ``BLOCK1`` + - AES key storage. + - 256 + - Yes + - x + * - ``FLASH_CRYPT_CONFIG`` + - Controls the AES encryption process. + - 4 + - Yes + - 0xF + * - ``download_dis_encrypt`` + - If set, disables flash encryption operation while running in Firmware Download mode. + - 1 + - Yes + - 0 + * - ``download_dis_decrypt`` + - If set, disables flash decryption while running in UART Firmware Download mode. + - 1 + - Yes + - 0 + * - ``FLASH_CRYPT_CNT`` + - Enables/disables encryption at boot time. If even number of bits set (0, 2, 4, 6) - encrypt flash at boot time. If odd number of bits set (1, 3, 5, 7) - do not encrypt flash at boot time. + - 7 + - Yes + - 0 + + Read and write access to eFuse bits is controlled by appropriate fields in the registers ``efuse_wr_disable`` and ``efuse_rd_disable``. For more information on {IDF_TARGET_NAME} eFuses, see :doc:`eFuse manager <../api-reference/system/efuse>`. -Read and write access to eFuse bits is controlled by appropriate fields in the registers ``efuse_wr_disable`` and ``efuse_rd_disable``. For more information on {IDF_TARGET_NAME} eFuses, see :doc:`eFuse manager <../api-reference/system/efuse>`. +.. only:: esp32s2 + + .. list-table:: eFuses Used in Flash Encryption + :widths: 25 40 10 15 10 + :header-rows: 0 + + * - **eFuse** + - **Description** + - **Bit Depth** + - **Locking for Reading/Writing Available** + - **Default Value** + * - ``EFUSE_KEY_PURPOSE_N`` + - Controls the purpose of ``KEYN``, where N is between 0 and 5. Possible values: ``2`` for ``XTS_AES_256_KEY_1`` , ``3`` for ``XTS_AES_256_KEY_2``, and ``4`` for ``XTS_AES_128_KEY``. Final AES key is derived based on TABLE X. + - 4 + - Yes + - 0 + * - ``KEYN`` + - AES key storage. N is between 0 and 5. + - 256 + - Yes + - x + * - ``EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT`` + - If set, disables flash encryption when in download bootmodes. + - 1 + - Yes + - 0 + * - ``EFUSE_SPI_BOOT_CRYPT_CNT`` + - Enables encryption and decryption, when an SPI boot mode is set. Feature is enabled if 1 or 3 bits are set in the eFuse, disabled otherwise. + - 3 + - Yes + - 0 + + Read and write access to eFuse bits is controlled by appropriate fields in the registers ``EFUSE_WR_DIS`` and ``EFUSE_RD_DIS``. For more information on {IDF_TARGET_NAME} eFuses, see :doc:`eFuse manager <../api-reference/system/efuse>`. Flash Encryption Process @@ -90,14 +125,22 @@ Flash Encryption Process Assuming that the eFuse values are in their default states and the firmware bootloader is compiled to support flash encryption, the flash encryption process executes as shown below: -#. On the first power-on reset, all data in flash is un-encrypted (plaintext). The ROM bootloader loads the firmware bootloader. -#. Firmware bootloader reads the ``FLASH_CRYPT_CNT`` eFuse value (``0b00000000``). Since the value is ``0`` (even number of bits set), it configures and enables the flash encryption block. It also sets the ``FLASH_CRYPT_CONFIG`` eFuse to 0xF. For more information on the flash encryption block, see `{IDF_TARGET_NAME} Technical reference manual`_. -#. Flash encryption block generates an AES-256 bit key and writes it into the BLOCK1 eFuse. This operation is done entirely by hardware, and the key cannot be accessed via software. -#. Flash encryption block encrypts the flash contents - partitions encrypted by default and the ones marked as ``encrypted``. Encrypting in-place can take time, up to a minute for large partitions. -#. Firmware bootloader sets the first available bit in ``FLASH_CRYPT_CNT`` (0b00000001) to mark the flash contents as encrypted. Odd number of bits is set. -#. For :ref:`flash-enc-development-mode`, the firmware bootloader sets only the eFuse bits ``download_dis_decrypt`` and ``download_dis_cache`` to allow the UART bootloader to re-flash encrypted binaries. Also, the ``FLASH_CRYPT_CNT`` eFuse bits are NOT write-protected. -#. For :ref:`flash-enc-release-mode`, the firmware bootloader sets the eFuse bits ``download_dis_encrypt``, ``download_dis_decrypt``, and ``download_dis_cache`` to 1 to prevent the UART bootloader from decrypting the flash contents. It also write-protects the ``FLASH_CRYPT_CNT`` eFuse bits. To modify this behavior, see :ref:`uart-bootloader-encryption`. -#. The device is then rebooted to start executing the encrypted image. The firmware bootloader calls the flash decryption block to decrypt the flash contents and then loads the decrypted contents into IRAM. +1. On the first power-on reset, all data in flash is un-encrypted (plaintext). The ROM bootloader loads the firmware bootloader. + +.. only:: esp32 + + 2. Firmware bootloader reads the ``FLASH_CRYPT_CNT`` eFuse value (``0b00000000``). Since the value is ``0`` (even number of bits set), it configures and enables the flash encryption block. It also sets the ``FLASH_CRYPT_CONFIG`` eFuse to 0xF. For more information on the flash encryption block, see `{IDF_TARGET_NAME} Technical reference manual`_. + +.. only:: esp32s2 + + 2. Firmware bootloader reads the ``EFUSE_SPI_BOOT_CRYPT_CNT`` eFuse value (``0b00000000``). Since the value is ``0`` (even number of bits set), it configures and enables the flash encryption block. It also sets the ``FLASH_CRYPT_CONFIG???`` eFuse to 0xF. For more information on the flash encryption block, see `{IDF_TARGET_NAME} Technical reference manual`_. + +3. Flash encryption block generates an AES-256 bit key and writes it into the BLOCK1 eFuse. This operation is done entirely by hardware, and the key cannot be accessed via software. +4. Flash encryption block encrypts the flash contents - partitions encrypted by default and the ones marked as ``encrypted``. Encrypting in-place can take time, up to a minute for large partitions. +5. Firmware bootloader sets the first available bit in ``FLASH_CRYPT_CNT`` (0b00000001) to mark the flash contents as encrypted. Odd number of bits is set. +6. For :ref:`flash-enc-development-mode`, the firmware bootloader sets only the eFuse bits ``download_dis_decrypt`` and ``download_dis_cache`` to allow the UART bootloader to re-flash encrypted binaries. Also, the ``FLASH_CRYPT_CNT`` eFuse bits are NOT write-protected. +7. For :ref:`flash-enc-release-mode`, the firmware bootloader sets the eFuse bits ``download_dis_encrypt``, ``download_dis_decrypt``, and ``download_dis_cache`` to 1 to prevent the UART bootloader from decrypting the flash contents. It also write-protects the ``FLASH_CRYPT_CNT`` eFuse bits. To modify this behavior, see :ref:`uart-bootloader-encryption`. +8. The device is then rebooted to start executing the encrypted image. The firmware bootloader calls the flash decryption block to decrypt the flash contents and then loads the decrypted contents into IRAM. During the development stage, there is a frequent need to program different plaintext flash images and test the flash encryption process. This requires that Firmware Download mode is able to load new plaintext images as many times as it might be needed. However, during manufacturing or production stages, Firmware Download mode should not be allowed to access flash contents for security reasons. @@ -305,7 +348,7 @@ At this stage, if you need to update and re-flash binaries, see :ref:`encrypt-pa Using Host Generated Key """""""""""""""""""""""" -It is possible to pre-generate a flash encryption key on the host computer and burn it into the {IDF_TARGET_NAME}'s ``BLOCK1`` eFuse. This allows you to pre-encrypt data on the host and flash already encrypted data without needing a plaintext flash update. This feature can be used in both :ref:`flash-enc-development-mode` and :ref:`flash-enc-release-mode`. Without a pre-generated key, data is flashed in plaintext and then {IDF_TARGET_NAME} encrypts the data in-place. +It is possible to pre-generate a flash encryption key on the host computer and burn it into the eFuse. This allows you to pre-encrypt data on the host and flash already encrypted data without needing a plaintext flash update. This feature can be used in both :ref:`flash-enc-development-mode` and :ref:`flash-enc-release-mode`. Without a pre-generated key, data is flashed in plaintext and then {IDF_TARGET_NAME} encrypts the data in-place. .. note:: @@ -511,7 +554,13 @@ Once flash encryption is enabled, the ``FLASH_CRYPT_CNT`` eFuse value will have To check if flash encryption on your {IDF_TARGET_NAME} device is enabled, do one of the following: -- flash the application example :example:`security/flash_encryption` onto your device. This application prints the ``FLASH_CRYPT_CNT`` eFuse value and if flash encryption is enabled or disabled. +.. only:: esp32 + + - flash the application example :example:`security/flash_encryption` onto your device. This application prints the ``FLASH_CRYPT_CNT`` eFuse value and if flash encryption is enabled or disabled. + +.. only:: esp32s2 + + - flash the application example :example:`security/flash_encryption` onto your device. This application prints the ``EFUSE_SPI_BOOT_CRYPT_CNT`` eFuse value and if flash encryption is enabled or disabled. - :doc:`Find the serial port name <../get-started/establish-serial-connection>` under which your {IDF_TARGET_NAME} device is connected, replace ``PORT`` with your port name in the following command, and run it: From d193790f85dfb30bdb6caae38ced8cb9639e5768 Mon Sep 17 00:00:00 2001 From: Marius Vikhammer Date: Thu, 12 Mar 2020 19:08:39 +0800 Subject: [PATCH 3/3] doc: update flash encryption with S2 specific content --- docs/en/security/flash-encryption.rst | 273 ++++++++++++++++---------- 1 file changed, 169 insertions(+), 104 deletions(-) diff --git a/docs/en/security/flash-encryption.rst b/docs/en/security/flash-encryption.rst index 5b7ab44f3..3d6522424 100644 --- a/docs/en/security/flash-encryption.rst +++ b/docs/en/security/flash-encryption.rst @@ -26,6 +26,10 @@ Other types of data can be encrypted conditionally: :doc:`Secure Boot ` is a separate feature which can be used together with flash encryption to create an even more secure environment. +.. important:: + For production use, flash encryption should be enabled in the "Release" mode only. + + .. important:: Enabling flash encryption limits the options for further updates of {IDF_TARGET_NAME}. Before using this feature, read the document and make sure to understand the implications. @@ -96,16 +100,16 @@ The flash encryption operation is controlled by various eFuses available on {IDF - **Bit Depth** - **Locking for Reading/Writing Available** - **Default Value** - * - ``EFUSE_KEY_PURPOSE_N`` - - Controls the purpose of ``KEYN``, where N is between 0 and 5. Possible values: ``2`` for ``XTS_AES_256_KEY_1`` , ``3`` for ``XTS_AES_256_KEY_2``, and ``4`` for ``XTS_AES_128_KEY``. Final AES key is derived based on TABLE X. - - 4 - - Yes - - 0 * - ``KEYN`` - AES key storage. N is between 0 and 5. - 256 - Yes - x + * - ``EFUSE_KEY_PURPOSE_N`` + - Controls the purpose of eFuse block ``KEYN``, where N is between 0 and 5. Possible values: ``2`` for ``XTS_AES_256_KEY_1`` , ``3`` for ``XTS_AES_256_KEY_2``, and ``4`` for ``XTS_AES_128_KEY``. Final AES key is derived based on the value of one or two of these purpose eFuses. For a detailed description of the possible combinations see `{IDF_TARGET_NAME} Technical Reference Manual <{IDF_TARGET_TRM_EN_URL}>`_, chapter Flash Encryption. + - 4 + - Yes + - 0 * - ``EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT`` - If set, disables flash encryption when in download bootmodes. - 1 @@ -123,24 +127,46 @@ The flash encryption operation is controlled by various eFuses available on {IDF Flash Encryption Process ------------------------ -Assuming that the eFuse values are in their default states and the firmware bootloader is compiled to support flash encryption, the flash encryption process executes as shown below: +{IDF_TARGET_CRYPT_CNT:default="EFUSE_SPI_BOOT_CRYPT_CNT",esp32="FLASH_CRYPT_CNT",esp32s2="EFUSE_SPI_BOOT_CRYPT_CNT"} -1. On the first power-on reset, all data in flash is un-encrypted (plaintext). The ROM bootloader loads the firmware bootloader. +Assuming that the eFuse values are in their default states and the firmware bootloader is compiled to support flash encryption, the flash encryption process executes as shown below: .. only:: esp32 - 2. Firmware bootloader reads the ``FLASH_CRYPT_CNT`` eFuse value (``0b00000000``). Since the value is ``0`` (even number of bits set), it configures and enables the flash encryption block. It also sets the ``FLASH_CRYPT_CONFIG`` eFuse to 0xF. For more information on the flash encryption block, see `{IDF_TARGET_NAME} Technical reference manual`_. + 1. On the first power-on reset, all data in flash is un-encrypted (plaintext). The ROM bootloader loads the firmware bootloader. + + 2. Firmware bootloader reads the ``FLASH_CRYPT_CNT`` eFuse value (``0b00000000``). Since the value is ``0`` (even number of bits set), it configures and enables the flash encryption block. It also sets the ``FLASH_CRYPT_CONFIG`` eFuse to 0xF. For more information on the flash encryption block, see `{IDF_TARGET_NAME} Technical Reference Manual <{IDF_TARGET_TRM_EN_URL}>`_. + + 3. Flash encryption block generates an AES-256 bit key and writes it into the BLOCK1 eFuse. This operation is done entirely by hardware, and the key cannot be accessed via software. + + 4. Flash encryption block encrypts the flash contents - partitions encrypted by default and the ones marked as ``encrypted``. Encrypting in-place can take time, up to a minute for large partitions. + + 5. Firmware bootloader sets the first available bit in ``FLASH_CRYPT_CNT`` (0b00000001) to mark the flash contents as encrypted. Odd number of bits is set. + + 6. For :ref:`flash-enc-development-mode`, the firmware bootloader sets only the eFuse bits ``download_dis_decrypt`` and ``download_dis_cache`` to allow the UART bootloader to re-flash encrypted binaries. Also, the ``FLASH_CRYPT_CNT`` eFuse bits are NOT write-protected. + + 7. For :ref:`flash-enc-release-mode`, the firmware bootloader sets the eFuse bits ``download_dis_encrypt``, ``download_dis_decrypt``, and ``download_dis_cache`` to 1 to prevent the UART bootloader from decrypting the flash contents. It also write-protects the ``FLASH_CRYPT_CNT`` eFuse bits. To modify this behavior, see :ref:`uart-bootloader-encryption`. + + 8. The device is then rebooted to start executing the encrypted image. The firmware bootloader calls the flash decryption block to decrypt the flash contents and then loads the decrypted contents into IRAM. .. only:: esp32s2 - 2. Firmware bootloader reads the ``EFUSE_SPI_BOOT_CRYPT_CNT`` eFuse value (``0b00000000``). Since the value is ``0`` (even number of bits set), it configures and enables the flash encryption block. It also sets the ``FLASH_CRYPT_CONFIG???`` eFuse to 0xF. For more information on the flash encryption block, see `{IDF_TARGET_NAME} Technical reference manual`_. + 1. On the first power-on reset, all data in flash is un-encrypted (plaintext). The ROM bootloader loads the firmware bootloader. + + 2. Firmware bootloader reads the ``EFUSE_SPI_BOOT_CRYPT_CNT`` eFuse value (``0b00000000``). Since the value is ``0`` (even number of bits set), it configures and enables the flash encryption block. For more information on the flash encryption block, see `{IDF_TARGET_NAME} Technical Reference Manual <{IDF_TARGET_TRM_EN_URL}>`_. + + 3. Flash encryption block generates an 256 bit or 512 bit key, depending on the value of :ref:`Size of generated AES-XTS key `, and writes it into respectively one or two `KEYN` eFuses. The software also updates the ``EFUSE_KEY_PURPOSE_N`` for the blocks where the keys where stored. This operation is done entirely by hardware, and the key cannot be accessed via software. + + 4. Flash encryption block encrypts the flash contents - partitions encrypted by default and the ones marked as ``encrypted``. Encrypting in-place can take time, up to a minute for large partitions. + + 5. Firmware bootloader sets the first available bit in ``EFUSE_SPI_BOOT_CRYPT_CNT`` (0b00000001) to mark the flash contents as encrypted. Odd number of bits is set. + + 6. For :ref:`flash-enc-development-mode`, the firmware bootloader allows the UART bootloader to re-flash encrypted binaries. Also, the ``EFUSE_SPI_BOOT_CRYPT_CNT`` eFuse bits are NOT write-protected. + + 7. For :ref:`flash-enc-release-mode`, the firmware bootloader sets the eFuse bits ``EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT``, ``EFUSE_DIS_BOOT_REMAP``, ``EFUSE_DIS_DOWNLOAD_ICACHE`` and ``EFUSE_DIS_DOWNLOAD_DCACHE``. It also write-protects the ``EFUSE_SPI_BOOT_CRYPT_CNT`` eFuse bits. To modify this behavior, see :ref:`uart-bootloader-encryption`. + + 8. The device is then rebooted to start executing the encrypted image. The firmware bootloader calls the flash decryption block to decrypt the flash contents and then loads the decrypted contents into IRAM. -3. Flash encryption block generates an AES-256 bit key and writes it into the BLOCK1 eFuse. This operation is done entirely by hardware, and the key cannot be accessed via software. -4. Flash encryption block encrypts the flash contents - partitions encrypted by default and the ones marked as ``encrypted``. Encrypting in-place can take time, up to a minute for large partitions. -5. Firmware bootloader sets the first available bit in ``FLASH_CRYPT_CNT`` (0b00000001) to mark the flash contents as encrypted. Odd number of bits is set. -6. For :ref:`flash-enc-development-mode`, the firmware bootloader sets only the eFuse bits ``download_dis_decrypt`` and ``download_dis_cache`` to allow the UART bootloader to re-flash encrypted binaries. Also, the ``FLASH_CRYPT_CNT`` eFuse bits are NOT write-protected. -7. For :ref:`flash-enc-release-mode`, the firmware bootloader sets the eFuse bits ``download_dis_encrypt``, ``download_dis_decrypt``, and ``download_dis_cache`` to 1 to prevent the UART bootloader from decrypting the flash contents. It also write-protects the ``FLASH_CRYPT_CNT`` eFuse bits. To modify this behavior, see :ref:`uart-bootloader-encryption`. -8. The device is then rebooted to start executing the encrypted image. The firmware bootloader calls the flash decryption block to decrypt the flash contents and then loads the decrypted contents into IRAM. During the development stage, there is a frequent need to program different plaintext flash images and test the flash encryption process. This requires that Firmware Download mode is able to load new plaintext images as many times as it might be needed. However, during manufacturing or production stages, Firmware Download mode should not be allowed to access flash contents for security reasons. @@ -182,14 +208,17 @@ To test flash encryption process, take the following steps: 2. In :ref:`project-configuration-menu`, do the following: - - :ref:`Enable flash encryption on boot ` - - :ref:`Select ecnryption mode ` (**Development mode** by default) - - :ref:`Select the appropriate bootloader log verbosity ` - - Save the configuration and exit. + .. list:: -.. only:: esp32 + - :ref:`Enable flash encryption on boot ` + - :ref:`Select encryption mode ` (**Development mode** by default) + :esp32s2: - Set :ref:`Size of generated AES-XTS key ` + - :ref:`Select the appropriate bootloader log verbosity ` + - Save the configuration and exit. - Enabling flash encryption will increase the size of bootloader, which might require updating partition table offset. See :ref:`secure-boot-bootloader-size` + .. only:: esp32 + + Enabling flash encryption will increase the size of bootloader, which might require updating partition table offset. See :ref:`secure-boot-bootloader-size` 3. Run the command given below to build and flash the complete image. @@ -334,7 +363,7 @@ A sample output of subsequent {IDF_TARGET_NAME} boots just mentions that flash e I (0) cpu_start: Starting scheduler on APP CPU. Sample program to check Flash Encryption - This is {IDF_TARGET_NAME} chip with 2 CPU cores, WiFi/BT/BLE, silicon revision 1, 4MB external flash + This is ESP32 chip with 2 CPU cores, WiFi/BT/BLE, silicon revision 1, 4MB external flash Flash encryption feature is enabled Flash encryption mode is DEVELOPMENT Flash in encrypted mode with flash_crypt_cnt = 1 @@ -376,14 +405,14 @@ To use a host generated key, take the following steps: 4. In :ref:`project-configuration-menu`, do the following: - - :ref:`Enable flash encryption on boot ` - - :ref:`Select ecnryption mode ` (**Development mode** by default) - - :ref:`Select the appropriate bootloader log verbosity ` - - Save the configuration and exit. + - :ref:`Enable flash encryption on boot ` + - :ref:`Select encryption mode ` (**Development mode** by default) + - :ref:`Select the appropriate bootloader log verbosity ` + - Save the configuration and exit. -.. only:: esp32 + .. only:: esp32 - Enabling flash encryption will increase the size of bootloader, which might require updating partition table offset. See :ref:`secure-boot-bootloader-size` + Enabling flash encryption will increase the size of bootloader, which might require updating partition table offset. See :ref:`secure-boot-bootloader-size` 5. Run the command given below to build and flash the complete. @@ -429,14 +458,18 @@ To use this mode, take the following steps: 2. In :ref:`project-configuration-menu`, do the following: - - :ref:`Enable flash encryption on boot ` - - :ref:`Select Release mode ` (Note that once Release mode is selected, the ``download_dis_encrypt`` and ``download_dis_decrypt`` eFuse bits will be burned to disable UART bootloader access to flash contents) - - :ref:`Select the appropriate bootloader log verbosity ` - - Save the configuration and exit. + .. list:: -.. only:: esp32 + - :ref:`Enable flash encryption on boot ` + :esp32: - :ref:`Select Release mode ` (Note that once Release mode is selected, the ``download_dis_encrypt`` and ``download_dis_decrypt`` eFuse bits will be burned to disable UART bootloader access to flash contents) + :esp32s2: - :ref:`Select Release mode ` (Note that once Release mode is selected, the ``EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT`` eFuse bit will be burned to disable UART bootloader access to flash contents) + :esp32s2: - Set :ref:`Size of generated AES-XTS key ` + - :ref:`Select the appropriate bootloader log verbosity ` + - Save the configuration and exit. - Enabling flash encryption will increase the size of bootloader, which might require updating partition table offset. See :ref:`secure-boot-bootloader-size` + .. only:: esp32 + + Enabling flash encryption will increase the size of bootloader, which might require updating partition table offset. See :ref:`secure-boot-bootloader-size` 3. Run the command given below to build and flash the complete image. @@ -446,7 +479,7 @@ To use this mode, take the following steps: The image will include the firmware bootloader, partition table, application, and other partitions marked by the user as ``encrypted``. These binaries will be written to flash memory unencrypted. Once the flashing is complete, your device will reset. On the next boot, the firmware bootloader encrypts the flash application partition and then resets. After that, the sample application is decrypted at runtime and executed. -Once the flash encryption is enabled in Release mode, the bootloader will write-protect the ``FLASH_CRYPT_CNT`` eFuse. +Once the flash encryption is enabled in Release mode, the bootloader will write-protect the ``{IDF_TARGET_CRYPT_CNT}`` eFuse. For subsequent plaintext field updates, use :ref:`OTA scheme `. @@ -454,7 +487,7 @@ For subsequent plaintext field updates, use :ref:`OTA scheme ` under which your {IDF_TARGET_NAME} device is connected, replace ``PORT`` with your port name in the following command, and run it: @@ -582,7 +609,7 @@ Once flash encryption is enabled, be more careful with accessing flash contents Scope of Flash Encryption ^^^^^^^^^^^^^^^^^^^^^^^^^ -Whenever the ``FLASH_CRYPT_CNT`` eFuse is set to a value with an odd number of bits, all flash content accessed via the MMU's flash cache is transparently decrypted. It includes: +Whenever the ``{IDF_TARGET_CRYPT_CNT}`` eFuse is set to a value with an odd number of bits, all flash content accessed via the MMU's flash cache is transparently decrypted. It includes: - Executable application code in flash (IROM). - All read-only data stored in flash (DROM). @@ -650,16 +677,22 @@ Disabling Flash Encryption If flash encryption was enabled accidentally, flashing of plaintext data will soft-brick the {IDF_TARGET_NAME}. The device will reboot continuously, printing the error ``flash read err, 1000``. -For flash encryption in Development mode, encryption can be disabled by burning the ``FLASH_CRYPT_CNT`` eFuse. It can only be done three times per chip by taking the following steps: +.. only:: esp32 + + For flash encryption in Development mode, encryption can be disabled by burning the ``{IDF_TARGET_CRYPT_CNT}`` eFuse. It can only be done three times per chip by taking the following steps: + +.. only:: esp32s2 + + For flash encryption in Development mode, encryption can be disabled by burning the ``{IDF_TARGET_CRYPT_CNT}`` eFuse. It can only be done one time per chip by taking the following steps: #. In :ref:`project-configuration-menu`, disable :ref:`Enable flash encryption on boot `, then save and exit. #. Open project configuration menu again and **double-check** that you have disabled this option! If this option is left enabled, the bootloader will immediately re-enable encryption when it boots. #. With flash encryption disabled, build and flash the new bootloader and application by running ``idf.py flash``. -#. Use ``espefuse.py`` (in ``components/esptool_py/esptool``) to disable the ``FLASH_CRYPT_CNT`` by running: +#. Use ``espefuse.py`` (in ``components/esptool_py/esptool``) to disable the ``{IDF_TARGET_CRYPT_CNT}`` by running: .. code-block:: bash - espefuse.py burn_efuse FLASH_CRYPT_CNT + espefuse.py burn_efuse {IDF_TARGET_CRYPT_CNT} Reset the {IDF_TARGET_NAME}. Flash encryption will be disabled, and the bootloader will boot as usual. @@ -667,25 +700,29 @@ Reset the {IDF_TARGET_NAME}. Flash encryption will be disabled, and the bootload Key Points About Flash Encryption --------------------------------- -- Flash memory contents are encrypted using AES-256. The flash encryption key is stored in the ``BLOCK1`` eFuse internal to the chip and, by default, is protected from software access. +.. list:: -- 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 that every 32-byte block (two consecutive 16 byte AES blocks) is encrypted with a unique key derived from the flash encryption key. + :esp32: - Flash memory contents are encrypted using AES-256. The flash encryption key is stored in the ``BLOCK1`` eFuse internal to the chip and, by default, is protected from software access. -- Flash access is transparent via the flash cache mapping feature of {IDF_TARGET_NAME} - any flash regions which are mapped to the address space will be transparently decrypted when read. + :esp32: - 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 that every 32-byte block (two consecutive 16 byte AES blocks) is encrypted with a unique key derived from the flash encryption key. - Some data partitions might need to remain unencrypted for ease of access or might require the use of flash-friendly update algorithms which are ineffective if the data is encrypted. NVS partitions for non-volatile storage cannot be encrypted since the NVS library is not directly compatible with flash encryption. For details, refer to :ref:`NVS Encryption `. + :esp32s2: - Flash memory contents are encrypted using XTS-AES-128 or XTS-AES-256. The flash encryption key is 256 bits and 512 bits respectively and stored one or two ``KEYN`` eFuses internal to the chip and, by default, is protected from software access. -- If flash encryption might be used in future, the programmer must keep it in mind and take certain precautions when writing code that :ref:`uses encrypted flash `. + - Flash access is transparent via the flash cache mapping feature of {IDF_TARGET_NAME} - any flash regions which are mapped to the address space will be transparently decrypted when read. -- If secure boot is enabled, re-flashing the bootloader of an encrypted device requires a "Re-flashable" secure boot digest (see :ref:`flash-encryption-and-secure-boot`). + Some data partitions might need to remain unencrypted for ease of access or might require the use of flash-friendly update algorithms which are ineffective if the data is encrypted. NVS partitions for non-volatile storage cannot be encrypted since the NVS library is not directly compatible with flash encryption. For details, refer to :ref:`NVS Encryption `. - .. only:: esp32 + - If flash encryption might be used in future, the programmer must keep it in mind and take certain precautions when writing code that :ref:`uses encrypted flash `. - The firmware bootloader app binary ``bootloader.bin`` might become too large if both secure boot and flash encryption are enabled. See :ref:`secure-boot-bootloader-size`. + - If secure boot is enabled, re-flashing the bootloader of an encrypted device requires a "Re-flashable" secure boot digest (see :ref:`flash-encryption-and-secure-boot`). - .. important:: + .. only:: esp32 - Do not interrupt power to the {IDF_TARGET_NAME} while the first boot encryption pass is running. If power is interrupted, the flash contents will be corrupted and will require flashing with unencrypted data again. In this case, re-flashing will not count towards the flashing limit. + The firmware bootloader app binary ``bootloader.bin`` might become too large if both secure boot and flash encryption are enabled. See :ref:`secure-boot-bootloader-size`. + + .. important:: + + Do not interrupt power to the {IDF_TARGET_NAME} while the first boot encryption pass is running. If power is interrupted, the flash contents will be corrupted and will require flashing with unencrypted data again. In this case, re-flashing will not count towards the flashing limit. .. _flash-encryption-limitations: @@ -695,19 +732,19 @@ Limitations of Flash Encryption Flash encryption protects firmware against unauthorised readout and modification. It is important to understand the limitations of the flash encryption feature: -- **Flash encryption is only as strong as the key**. It is recommended to generate keys on the device during first boot (default behaviour). If generating keys on a host computer, ensure to follow a proper procedure and do not use the same key for produced devices. +.. list:: -- **Not all data is stored encrypted**. If storing data in flash memory, make sure that the method you are using (library, API, etc.) supports flash encryption. + - **Flash encryption is only as strong as the key**. It is recommended to generate keys on the device during first boot (default behaviour). If generating keys on a host computer, ensure to follow a proper procedure and do not use the same key for produced devices. -- **Flash encryption does not mask the high-level layout of flash**. This is because the same AES key is used for every pair of adjacent 16-byte AES blocks. If these blocks have identical content (such as empty or padding areas), these will produce matching pairs of encrypted blocks. It might allow an attacker to make high-level comparisons of firmware on encrypted devices, i.e., to tell if two devices are probably running the same firmware version. + - **Not all data is stored encrypted**. If storing data in flash memory, make sure that the method you are using (library, API, etc.) supports flash encryption. -- **Flash encryption does not mask the high-level layout of flash**. Each pair of adjacent 16-byte AES blocks is encrypted with the same AES key. If these blocks have identical content (such as empty or padding areas), the result will be matching pairs of encrypted blocks. It might allow an attacker to make high-level comparisons of firmware on encrypted devices, i.e., to tell if two devices are probably running the same firmware version. + :esp32: - **Flash encryption does not mask the high-level layout of flash**. This is because the same AES key is used for every pair of adjacent 16-byte AES blocks. If these blocks have identical content (such as empty or padding areas), these will produce matching pairs of encrypted blocks. It might allow an attacker to make high-level comparisons of firmware on encrypted devices, i.e., to tell if two devices are probably running the same firmware version. -- **An attacker can tell if a pair of adjacent 16-byte blocks (32 byte aligned) contains two identical 16-byte sequences** (the same reason as the previous bullet point). Keep this in mind if storing sensitive data in flash memory. While designing your flash storage, it is sufficient to use a counter byte or some other non-identical value every 16 bytes. :ref:`NVS Encryption ` deals with this and is suitable for many uses. + :esp32: - **Flash encryption does not mask the high-level layout of flash**. Each pair of adjacent 16-byte AES blocks is encrypted with the same AES key. If these blocks have identical content (such as empty or padding areas), the result will be matching pairs of encrypted blocks. It might allow an attacker to make high-level comparisons of firmware on encrypted devices, i.e., to tell if two devices are probably running the same firmware version. -.. only:: esp32 + :esp32: - **An attacker can tell if a pair of adjacent 16-byte blocks (32 byte aligned) contains two identical 16-byte sequences** (the same reason as the previous bullet point). Keep this in mind if storing sensitive data in flash memory. While designing your flash storage, it is sufficient to use a counter byte or some other non-identical value every 16 bytes. :ref:`NVS Encryption ` deals with this and is suitable for many uses. - - **Flash encryption alone may not prevent an attacker from modifying the firmware on the device**. To prevent unauthorized firmware from running on the device, use flash encryption in combination with :doc:`Secure Boot `. + :esp32: - **Flash encryption alone may not prevent an attacker from modifying the firmware on the device**. To prevent unauthorized firmware from running on the device, use flash encryption in combination with :doc:`Secure Boot `. .. _flash-encryption-and-secure-boot: @@ -751,7 +788,7 @@ For details on partition table description, see :doc:`partition table <../api-gu Further information about encryption of partitions: - Default partition tables do not include any encrypted data partitions. -- With enabled flash encryption, the ``app`` partition is always treated as encrypted and does not require marking. +- With flash encryption enabled, the ``app`` partition is always treated as encrypted and does not require marking. - If flash encryption is not enabled, the flag "encrypted" has no effect. - You can also consider protecting ``phy_init`` data from physical access, readout, or modification, by marking the optional ``phy`` partition with the flag ``encrypted``. - The ``nvs`` partition cannot be encrypted, because the NVS library is not directly compatible with flash encryption. @@ -764,44 +801,56 @@ Enabling UART Bootloader Encryption/Decryption On the first boot, the flash encryption process burns by default the following eFuses: -- ``DISABLE_DL_ENCRYPT`` which disables flash encryption operation when running in UART bootloader boot mode. -- ``DISABLE_DL_DECRYPT`` which disables transparent flash decryption when running in UART bootloader mode, even if the eFuse ``FLASH_CRYPT_CNT`` is set to enable it in normal operation. -- ``DISABLE_DL_CACHE`` which disables the entire MMU flash cache when running in UART bootloader mode. +.. only:: esp32 + + - ``DISABLE_DL_ENCRYPT`` which disables flash encryption operation when running in UART bootloader boot mode. + - ``DISABLE_DL_DECRYPT`` which disables transparent flash decryption when running in UART bootloader mode, even if the eFuse ``FLASH_CRYPT_CNT`` is set to enable it in normal operation. + - ``DISABLE_DL_CACHE`` which disables the entire MMU flash cache when running in UART bootloader mode. + +.. only:: esp32s2 + + - ``EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT`` flash encryption operation when running in UART bootloader boot mode. However, before the first boot you can choose to keep any of these features enabled by burning only selected eFuses and write-protect the rest of eFuses with unset value 0. For example: -.. code-block:: bash +.. only:: esp32 - espefuse.py --port PORT burn_efuse DISABLE_DL_DECRYPT - espefuse.py --port PORT write_protect_efuse DISABLE_DL_ENCRYPT + .. code-block:: bash -.. note:: + espefuse.py --port PORT burn_efuse DISABLE_DL_DECRYPT + espefuse.py --port PORT write_protect_efuse DISABLE_DL_ENCRYPT - Set all appropriate bits before write-protecting! + .. note:: - Write protection of all the three eFuses is controlled by one bit. It means that write-protecting one eFuse bit will inevitably write-protect all unset eFuse bits. + Set all appropriate bits before write-protecting! -Write protecting these eFuses to keep them unset is not currently very useful, as ``esptool.py`` does not support reading encrypted flash. + Write protection of all the three eFuses is controlled by one bit. It means that write-protecting one eFuse bit will inevitably write-protect all unset eFuse bits. -.. important:: + Write protecting these eFuses to keep them unset is not currently very useful, as ``esptool.py`` does not support reading encrypted flash. - Leaving ``DISABLE_DL_DECRYPT`` unset (0) makes flash encryption useless. +.. only:: esp32 - An attacker with physical access to the chip can use UART bootloader mode with custom stub code to read out the flash contents. + .. important:: + + Leaving ``DISABLE_DL_DECRYPT`` unset (0) makes flash encryption useless. + + An attacker with physical access to the chip can use UART bootloader mode with custom stub code to read out the flash contents. -.. _setting-flash-crypt-config: +.. only:: esp32 -Setting FLASH_CRYPT_CONFIG -^^^^^^^^^^^^^^^^^^^^^^^^^^ + .. _setting-flash-crypt-config: -The eFuse ``FLASH_CRYPT_CONFIG`` determines the number of bits in the flash encryption key which are "tweaked" with the block offset. For details, see :ref:`flash-encryption-algorithm`. + Setting FLASH_CRYPT_CONFIG + ^^^^^^^^^^^^^^^^^^^^^^^^^^ -On the first boot or the firmware bootloader, this value is set to the maximum ``0xF``. + The eFuse ``FLASH_CRYPT_CONFIG`` determines the number of bits in the flash encryption key which are "tweaked" with the block offset. For details, see :ref:`flash-encryption-algorithm`. -It is possible to burn this eFuse manually and write protect it before the first boot in order to select different tweak values. However, this is not recommended. + On the first boot or the firmware bootloader, this value is set to the maximum ``0xF``. -It is strongly recommended to never write-protect ``FLASH_CRYPT_CONFIG`` when it is unset. Otherwise, its value will remain zero permanently, and no bits in the flash encryption key will be tweaked. As a result, the flash encryption algorithm will be equivalent to AES ECB mode. + It is possible to burn this eFuse manually and write protect it before the first boot in order to select different tweak values. However, this is not recommended. + + It is strongly recommended to never write-protect ``FLASH_CRYPT_CONFIG`` when it is unset. Otherwise, its value will remain zero permanently, and no bits in the flash encryption key will be tweaked. As a result, the flash encryption algorithm will be equivalent to AES ECB mode. JTAG Debugging ^^^^^^^^^^^^^^ @@ -815,35 +864,51 @@ Technical Details The following sections provide some reference information about the operation of flash encryption. -.. _flash-encryption-algorithm: +.. only:: esp32 -Flash Encryption Algorithm -^^^^^^^^^^^^^^^^^^^^^^^^^^ + .. _flash-encryption-algorithm: -- AES-256 operates on 16-byte blocks of data. The flash encryption engine encrypts and decrypts data in 32-byte blocks - two AES blocks in series. + Flash Encryption Algorithm + ^^^^^^^^^^^^^^^^^^^^^^^^^^ -- The main flash encryption key is stored in the ``BLOCK1`` eFuse and, by default, is protected from further writes or software readout. + - AES-256 operates on 16-byte blocks of data. The flash encryption engine encrypts and decrypts data in 32-byte blocks - two AES blocks in series. -- AES-256 key size is 256 bits (32 bytes) read from the ``BLOCK1`` eFuse. The hardware AES engine uses the key in reversed byte order as compared to the storage order in ``BLOCK1``. + - The main flash encryption key is stored in the ``BLOCK1`` eFuse and, by default, is protected from further writes or software readout. - - If the ``CODING_SCHEME`` eFuse is set to ``0`` (default, "None" Coding Scheme) then the eFuse key block is 256 bits and the key is stored as-is (in reversed byte order). - - If the ``CODING_SCHEME`` eFuse is set to ``1`` (3/4 Encoding) then the eFuse key block is 192 bits (in reversed byte order), so overall entropy is reduced. The hardware flash encryption still operates on a 256-bit key, after being read (and un-reversed), the key is extended as ``key = key[0:255] + key[64:127]``. + - AES-256 key size is 256 bits (32 bytes) read from the ``BLOCK1`` eFuse. The hardware AES engine uses the key in reversed byte order as compared to the storage order in ``BLOCK1``. -- AES algorithm is used inverted in flash encryption, so the flash encryption "encrypt" operation is AES decrypt and the "decrypt" operation is AES encrypt. This is for performance reasons and does not alter the effeciency of the algorithm. + - If the ``CODING_SCHEME`` eFuse is set to ``0`` (default, "None" Coding Scheme) then the eFuse key block is 256 bits and the key is stored as-is (in reversed byte order). + - If the ``CODING_SCHEME`` eFuse is set to ``1`` (3/4 Encoding) then the eFuse key block is 192 bits (in reversed byte order), so overall entropy is reduced. The hardware flash encryption still operates on a 256-bit key, after being read (and un-reversed), the key is extended as ``key = key[0:255] + key[64:127]``. -- 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 ``BLOCK1``, XORed with the offset of this block in the flash (a "key tweak"). + - AES algorithm is used inverted in flash encryption, so the flash encryption "encrypt" operation is AES decrypt and the "decrypt" operation is AES encrypt. This is for performance reasons and does not alter the effeciency of the algorithm. -- The specific tweak depends on the ``FLASH_CRYPT_CONFIG`` eFuse setting. This is a 4-bit eFuse where each bit enables XORing of a particular range of the key bits: + - 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 ``BLOCK1``, XORed with the offset of this block in the flash (a "key tweak"). - - Bit 1, bits 0-66 of the key are XORed. - - Bit 2, bits 67-131 of the key are XORed. - - Bit 3, bits 132-194 of the key are XORed. - - Bit 4, bits 195-256 of the key are XORed. + - The specific tweak depends on the ``FLASH_CRYPT_CONFIG`` eFuse setting. This is a 4-bit eFuse where each bit enables XORing of a particular range of the key bits: - It is recommended that ``FLASH_CRYPT_CONFIG`` is always left at the default value ``0xF``, so that all key bits are XORed with the block offset. For details, see :ref:`setting-flash-crypt-config`. + - Bit 1, bits 0-66 of the key are XORed. + - Bit 2, bits 67-131 of the key are XORed. + - Bit 3, bits 132-194 of the key are XORed. + - Bit 4, bits 195-256 of the key are XORed. -- 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. + It is recommended that ``FLASH_CRYPT_CONFIG`` is always left at the default value ``0xF``, so that all key bits are XORed with the block offset. For details, see :ref:`setting-flash-crypt-config`. -- 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 complete mapping. + - 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. -- To see the full flash encryption algorithm implemented in Python, refer to the `_flash_encryption_operation()` function in the ``espsecure.py`` source code. + - 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 complete mapping. + + - To see the full flash encryption algorithm implemented in Python, refer to the `_flash_encryption_operation()` function in the ``espsecure.py`` source code. + +.. only:: esp32s2 + + .. _flash-encryption-algorithm: + + Flash Encryption Algorithm + ^^^^^^^^^^^^^^^^^^^^^^^^^^ + - {IDF_TARGET_NAME} use the XTS-AES block chiper mode with 256 bit or 512 bit key size for flash encryption. + + - XTS-AES is a block chiper mode specifically designed for disc encryption and addresses the weaknesses other potential modes (e.g. AES-CTR) have for this use case. A detailed description of the XTS-AES algorithm can be found in `IEEE Std 1619-2007 `_. + + - The flash encryption key is stored in one or two ``KEYN`` eFuses and, by default, is protected from further writes or software readout. + + - To see the full flash encryption algorithm implemented in Python, refer to the `_flash_encryption_operation()` function in the ``espsecure.py`` source code. \ No newline at end of file