Skip to content

Commit 37521eb

Browse files
fdcavalcantisimbit18
authored andcommitted
documentation: update flash encryption docs for Espressif devices
Adds new subsection under MCUBoot regarding use of flash encryption. Signed-off-by: Filipe Cavalcanti <filipe.cavalcanti@espressif.com>
1 parent 49d6177 commit 37521eb

File tree

6 files changed

+764
-217
lines changed

6 files changed

+764
-217
lines changed

Documentation/platforms/risc-v/esp32c3/index.rst

Lines changed: 84 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,8 @@ functions required to boot the device are built within NuttX. Simple boot does n
9797
require any specific configuration (it is selectable by default if no other
9898
2nd stage bootloader is used).
9999

100-
If other features, like `Secure Boot and Flash Encryption`_, are required, an
101-
externally-built 2nd stage bootloader is needed. The bootloader is built using
100+
If features like `Flash Encryption`_ are required, an externally-built
101+
2nd stage bootloader is needed. The MCUBoot bootloader is built using
102102
the ``make bootloader`` command. This command generates the firmware in the
103103
``nuttx`` folder. The ``ESPTOOL_BINDIR`` is used in the ``make flash`` command
104104
to specify the path to the bootloader. For compatibility among other SoCs and
@@ -497,108 +497,115 @@ Finally, the image is loaded but not confirmed.
497497
To make sure it won't rollback to the previous image, you must confirm with ``mcuboot_confirm`` and reboot the board.
498498
The OTA is now complete.
499499

500-
Secure Boot and Flash Encryption
501-
--------------------------------
502-
503-
Secure Boot
504-
^^^^^^^^^^^
500+
Flash Encryption
501+
----------------
505502

506-
Secure Boot protects a device from running any unauthorized (i.e., unsigned) code by checking that
507-
each piece of software that is being booted is signed. On an ESP32-C3, these pieces of software include
508-
the second stage bootloader and each application binary. Note that the first stage bootloader does not
509-
require signing as it is ROM code thus cannot be changed. This is achieved using specific hardware in
510-
conjunction with MCUboot (read more about MCUboot `here <https://docs.mcuboot.com/>`__).
503+
Flash encryption is intended for encrypting the contents of the ESP32-C3's off-chip flash memory. Once this feature is enabled,
504+
firmware is flashed as plaintext, and then the data is encrypted in place on the first boot. As a result, physical readout
505+
of flash will not be sufficient to recover most flash contents.
511506

512-
The Secure Boot process on the ESP32-C3 involves the following steps performed:
507+
The current state of flash encryption for ESP32-C3 allows the use of Virtual E-Fuses and development mode, which permit users to evaluate and test the firmware before making definitive changes such as burning E-Fuses.
513508

514-
1. The first stage bootloader verifies the second stage bootloader's RSA-PSS signature. If the verification is successful,
515-
the first stage bootloader loads and executes the second stage bootloader.
509+
Flash encryption supports the following features:
516510

517-
2. When the second stage bootloader loads a particular application image, the application's signature (RSA, ECDSA or ED25519) is verified
518-
by MCUboot.
519-
If the verification is successful, the application image is executed.
511+
.. list-table::
512+
:header-rows: 1
520513

521-
.. warning:: Once enabled, Secure Boot will not boot a modified bootloader. The bootloader will only boot an
522-
application firmware image if it has a verified digital signature. There are implications for reflashing
523-
updated images once Secure Boot is enabled. You can find more information about the ESP32-C3's Secure boot
524-
`here <https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/security/secure-boot-v2.html>`__.
514+
* - Feature
515+
- Description
516+
* - **Flash Encryption with Virtual E-Fuses**
517+
- Use flash encryption without burning E-Fuses. Default selection when flash encryption is enabled.
518+
* - **Flash Encryption in Development mode**
519+
- Allows reflashing an encrypted device by appending the ``--encrypt`` argument to the ``esptool.py write_flash`` command. This is done automatically if ``ESPRESSIF_SECURE_FLASH_ENC_FLASH_DEVICE_ENCRYPTED`` is set.
520+
* - **Flash Encryption in Release mode**
521+
- Does not allow reflashing the device. This is a permanent setting.
522+
* - **Flash Encryption key**
523+
- A user-generated key is required by default. Alternatively, a device-generated key is possible, but it will not be recoverable by the user (not recommended). See ``ESPRESSIF_SECURE_FLASH_ENC_USE_HOST_KEY``.
524+
* - **Encrypted MTD Partition**
525+
- If SPI Flash is enabled, an empty user MTD partition will be automatically encrypted on first flash.
525526

526-
.. note:: As the bootloader image is built on top of the Hardware Abstraction Layer component
527-
of `ESP-IDF <https://github.com/espressif/esp-idf>`_, the
528-
`API port by Espressif <https://docs.mcuboot.com/readme-espressif.html>`_ will be used
529-
by MCUboot rather than the original NuttX port.
527+
.. note::
530528

531-
Flash Encryption
532-
^^^^^^^^^^^^^^^^
529+
It is **strongly suggested** to read the following before working on flash encryption:
533530

534-
Flash encryption is intended for encrypting the contents of the ESP32-C3's off-chip flash memory. Once this feature is enabled,
535-
firmware is flashed as plaintext, and then the data is encrypted in place on the first boot. As a result, physical readout
536-
of flash will not be sufficient to recover most flash contents.
531+
- `MCUBoot Flash Encryption <https://docs.mcuboot.com/readme-espressif.html#flash-encryption>`_
532+
- `General E-Fuse documentation <https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/api-reference/system/efuse.html>`_
533+
- `Flash Encryption Relevant E-Fuses <https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/security/flash-encryption.html#relevant-efuses>`_
537534

538-
.. warning:: After enabling Flash Encryption, an encryption key is generated internally by the device and
539-
cannot be accessed by the user for re-encrypting data and re-flashing the system, hence it will be permanently encrypted.
540-
Re-flashing an encrypted system is complicated and not always possible. You can find more information about the ESP32-C3's Flash Encryption
541-
`here <https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/security/flash-encryption.html>`__.
535+
Flash Encryption Requirements
536+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
542537

543-
Prerequisites
544-
^^^^^^^^^^^^^
538+
Flash encryption requires burning E-Fuses to enable it on chip. This is not a reversible operation and should be done with caution.
539+
There is, however, a way to test the flash encryption by simulating them on flash. Both paths are described below.
545540

546-
First of all, we need to install ``imgtool`` (the MCUboot utility application to manipulate binary
547-
images)::
541+
Build System Features
542+
'''''''''''''''''''''
548543

549-
$ pip install imgtool
544+
The build system contains some safeguards to avoid accidentally burning E-Fuses and automations for convenience. Those are summarized below:
550545

551-
We also need to make sure that the python modules are added to ``PATH``::
546+
1. A yellow warning will show up during build alerting that flash encryption is enabled (same for Virtual E-Fuses).
547+
2. If ``ESPRESSIF_SECURE_FLASH_ENC_USE_HOST_KEY`` is set, build will fail if the flash encryption key is not found.
548+
3. If SPI Flash is enabled, the user MTD partition is automatically encrypted with the provided encryption key.
549+
4. ``make flash`` command will prompt the user for confirmation before burning the E-Fuse, if Virtual E-Fuses are disabled.
552550

553-
$ echo "PATH=$PATH:/home/$USER/.local/bin" >> ~/.bashrc
554551

555-
Now, we will create a folder to store the generated keys (such as ``~/signing_keys``)::
552+
Simulating Flash Encryption with Virtual E-Fuses
553+
'''''''''''''''''''''''''''''''''''''''''''''''''
556554

557-
$ mkdir ~/signing_keys && cd ~/signing_keys
555+
It is highly recommended to use this method for testing the flash encryption before actually burning the E-Fuses.
556+
The E-Fuses are stored in flash and persist between reboots. No real E-Fuses are changed.
558557

559-
With all set up, we can now generate keys to sign the bootloader and application binary images,
560-
respectively, of the compiled project::
558+
To enable virtual E-Fuses for flash encryption testing, open ``menuconfig`` and:
559+
1. Enable flash encryption on boot on: :menuselection:`System Type --> Bootloader and Image Configuration`
560+
2. Verify Virtual E-Fuses are enabled (this is done by default): :menuselection:`System Type --> Peripheral Support --> E-Fuse support`
561561

562-
$ espsecure.py generate_signing_key --version 2 bootloader_signing_key.pem
563-
$ imgtool keygen --key app_signing_key.pem --type rsa-3072
562+
.. note:: On ESP32-C3, testing is possible with QEMU. If that is the case, on step 2 disable Virtual E-Fuse and use normal E-Fuse support.
563+
See `ESP32-C3 QEMU <https://github.com/espressif/esp-toolchain-docs/tree/main/qemu/esp32c3>`_.
564564

565-
.. important:: The contents of the key files must be stored securely and kept secret.
565+
Now build the bootloader and the firmware. Flashing the device (or opening on QEMU) will trigger the following:
566+
1. On the first boot, the bootloader will encrypt the flash::
566567

567-
Enabling Secure Boot and Flash Encryption
568-
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
568+
...
569+
[esp32c3] [WRN] eFuse virtual mode is enabled. If Secure boot or Flash encryption is enabled then it does not provide any security. FOR TESTING ONLY!
570+
[esp32c3] [WRN] [efuse] [Virtual] try loading efuses from flash: 0x10000 (offset)
571+
...
572+
[esp32c3] [INF] [flash_encrypt] Encrypting bootloader...
573+
[esp32c3] [INF] [flash_encrypt] Bootloader encrypted successfully
574+
[esp32c3] [INF] [flash_encrypt] Encrypting primary slot...
575+
[esp32c3] [INF] [flash_encrypt] Encrypting remaining flash...
576+
[esp32c3] [INF] [flash_encrypt] Flash encryption completed
577+
...
578+
[esp32c3] [INF] Resetting with flash encryption enabled...
569579

570-
To enable Secure Boot for the current project, go to the project's NuttX directory, execute ``make menuconfig`` and the following steps:
580+
2. Device will reset and it should be now operating similar to an actual encrypted device::
571581

572-
1. Enable experimental features in :menuselection:`Build Setup --> Show experimental options`;
573-
2. Enable MCUboot in :menuselection:`Application Configuration --> Bootloader Utilities --> MCUboot`;
574-
3. Change image type to ``MCUboot-bootable format`` in :menuselection:`System Type --> Application Image Configuration --> Application Image Format`;
575-
4. Enable building MCUboot from the source code by selecting ``Build binaries from source``;
576-
in :menuselection:`System Type --> Application Image Configuration --> Source for bootloader binaries`;
577-
5. Enable Secure Boot in :menuselection:`System Type --> Application Image Configuration --> Enable hardware Secure Boot in bootloader`;
578-
6. If you want to protect the SPI Bus against data sniffing, you can enable Flash Encryption in
579-
:menuselection:`System Type --> Application Image Configuration --> Enable Flash Encryption on boot`.
582+
...
583+
[esp32c3] [INF] Checking flash encryption...
584+
[esp32c3] [INF] [flash_encrypt] flash encryption is enabled (1 plaintext flashes left)
585+
[esp32c3] [INF] Disabling RNG early entropy source...
586+
[esp32c3] [INF] br_image_off = 0x20000
587+
[esp32c3] [INF] ih_hdr_size = 0x20
588+
[esp32c3] [INF] Loading image 0 - slot 0 from flash, area id: 1
589+
...
590+
NuttShell (NSH) NuttX-12.8.0
591+
nsh>
580592

581-
Now you can design an update and confirm agent to your application. Check the `MCUboot design guide <https://docs.mcuboot.com/design.html>`_ and the
582-
`MCUboot Espressif port documentation <https://docs.mcuboot.com/readme-espressif.html>`_ for
583-
more information on how to apply MCUboot. Also check some `notes about the NuttX MCUboot port <https://github.com/mcu-tools/mcuboot/blob/main/docs/readme-nuttx.md>`_,
584-
the `MCUboot porting guide <https://github.com/mcu-tools/mcuboot/blob/main/docs/PORTING.md>`_ and some
585-
`examples of MCUboot applied in NuttX applications <https://github.com/apache/nuttx-apps/tree/master/examples/mcuboot>`_.
593+
Actual encryption and burning E-Fuses
594+
'''''''''''''''''''''''''''''''''''''
586595

587-
After you developed an application which implements all desired functions, you need to flash it into the primary image slot
588-
of the device (it will automatically be in the confirmed state, you can learn more about image
589-
confirmation `here <https://docs.mcuboot.com/design.html#image-swapping>`_).
590-
To flash to the primary image slot, select ``Application image primary slot`` in
591-
:menuselection:`System Type --> Application Image Configuration --> Target slot for image flashing`
592-
and compile it using ``make -j ESPSEC_KEYDIR=~/signing_keys``.
596+
E-Fuses are burned by esptool and the bootloader on the first boot after flashing with encryption enabled.
597+
This process is automated on NuttX build system.
593598

594-
When creating update images, make sure to change :menuselection:`System Type --> Application Image Configuration --> Target slot for image flashing`
595-
to ``Application image secondary slot``.
599+
.. warning:: Burning E-Fuses is NOT a reversible operation and should be done with caution.
596600

597-
.. important:: When deploying your application, make sure to disable UART Download Mode by selecting ``Permanently disabled`` in
598-
:menuselection:`System Type --> Application Image Configuration --> UART ROM download mode`
599-
and change usage mode to ``Release`` in `System Type --> Application Image Configuration --> Enable usage mode`.
600-
**After disabling UART Download Mode you will not be able to flash other images through UART.**
601+
To build a firmware with E-Fuse support and flash encryption enabled, open ``menuconfig`` and:
602+
1. Enable flash encryption on boot on: :menuselection:`System Type --> Bootloader and Image Configuration`
603+
2. Disable Virtual E-Fuses :menuselection:`System Type --> Peripheral Support --> E-Fuse support`
604+
3. Check usage mode is Development (this allows reflashing, while Release mode does not).
601605

606+
.. note:: If using development mode of flash encryption (see menuconfig and documentation above), it is still possible to re-flash the device with esptool by
607+
setting ``ESPRESSIF_SECURE_FLASH_ENC_FLASH_DEVICE_ENCRYPTED`` which adds ``--encrypt`` argument to the ``esptool.py write_flash`` command.
608+
This will apply the burned encryption key to the image while flashing.
602609

603610
Flash Allocation for MCUBoot
604611
----------------------------

0 commit comments

Comments
 (0)