From 7b9009ca5c25fa8007a55aa16d40727c0313aec7 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Fri, 13 Jul 2018 15:21:07 +1000 Subject: [PATCH 1/6] bootloader: Fix secure boot & flash encryption functionality Fixes regression in 3e0ac4db79. --- .../subproject/main/esp32.bootloader.ld | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/components/bootloader/subproject/main/esp32.bootloader.ld b/components/bootloader/subproject/main/esp32.bootloader.ld index 385c9a4344..8930d5305f 100644 --- a/components/bootloader/subproject/main/esp32.bootloader.ld +++ b/components/bootloader/subproject/main/esp32.bootloader.ld @@ -41,19 +41,25 @@ SECTIONS *(.iram1 .iram1.*) /* catch stray IRAM_ATTR */ *liblog.a:(.literal .text .literal.* .text.*) *libgcc.a:(.literal .text .literal.* .text.*) - *libbootloader_support.a:bootloader_utility.o(.literal .text .literal.* .text.*) - *libbootloader_support.a:esp_image_format.o(.literal .text .literal.* .text.*) - *libbootloader_support.a:bootloader_random.o(.literal .text .literal.* .text.*) *libbootloader_support.a:bootloader_flash.o(.literal .text .literal.* .text.*) - *libbootloader_support.a:flash_partitions.o(.literal .text .literal.* .text.*) + *libbootloader_support.a:bootloader_random.o(.literal .text .literal.* .text.*) + *libbootloader_support.a:bootloader_utility.o(.literal .text .literal.* .text.*) *libbootloader_support.a:bootloader_sha.o(.literal .text .literal.* .text.*) + *libbootloader_support.a:efuse.o(.literal .text .literal.* .text.*) + *libbootloader_support.a:esp_image_format.o(.literal .text .literal.* .text.*) + *libbootloader_support.a:flash_encrypt.o(.literal .text .literal.* .text.*) + *libbootloader_support.a:flash_partitions.o(.literal .text .literal.* .text.*) + *libbootloader_support.a:secure_boot.o(.literal .text .literal.* .text.*) + *libbootloader_support.a:secure_boot_signatures.o(.literal .text .literal.* .text.*) + *libmicro-ecc.a:*.o(.literal .text .literal.* .text.*) + *libspi_flash.a:*.o(.literal .text .literal.* .text.*) *(.fini.literal) *(.fini) *(.gnu.version) _text_end = ABSOLUTE(.); _etext = .; } > iram_loader_seg - + .iram.text : { . = ALIGN (16); From fb439e48f5b25b7b8d111d26dc5da29829160e75 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Fri, 13 Jul 2018 15:23:04 +1000 Subject: [PATCH 2/6] bootloader: Don't verify Partition Table as part of Secure Boot Partition Tables are still signed for backwards compatibility, but signature is no longer checked as part of bootloader. Closes https://github.com/espressif/esp-idf/issues/1641 --- .../include/esp_flash_partitions.h | 11 +++++++++-- .../bootloader_support/src/bootloader_common.c | 14 +------------- .../bootloader_support/src/bootloader_utility.c | 14 +------------- components/bootloader_support/src/flash_encrypt.c | 2 +- .../bootloader_support/src/flash_partitions.c | 2 +- 5 files changed, 13 insertions(+), 30 deletions(-) diff --git a/components/bootloader_support/include/esp_flash_partitions.h b/components/bootloader_support/include/esp_flash_partitions.h index 24b6f25d2d..b5f37aa5fc 100644 --- a/components/bootloader_support/include/esp_flash_partitions.h +++ b/components/bootloader_support/include/esp_flash_partitions.h @@ -27,7 +27,7 @@ #define ESP_PARTITION_TABLE_MAX_LEN 0xC00 /* Maximum length of partition table data */ #define ESP_PARTITION_TABLE_MAX_ENTRIES (ESP_PARTITION_TABLE_MAX_LEN / sizeof(esp_partition_info_t)) /* Maximum length of partition table data, including terminating entry */ -/* @brief Verify the partition table (does not include verifying secure boot cryptographic signature) +/* @brief Verify the partition table * * @param partition_table Pointer to at least ESP_PARTITION_TABLE_MAX_ENTRIES of potential partition table data. (ESP_PARTITION_TABLE_MAX_LEN bytes.) * @param log_errors Log errors if the partition table is invalid. @@ -35,6 +35,13 @@ * * @return ESP_OK on success, ESP_ERR_INVALID_STATE if partition table is not valid. */ -esp_err_t esp_partition_table_basic_verify(const esp_partition_info_t *partition_table, bool log_errors, int *num_partitions); +esp_err_t esp_partition_table_verify(const esp_partition_info_t *partition_table, bool log_errors, int *num_partitions); + + +/* This function is included for compatibility with the ESP-IDF v3.x API */ +inline static __attribute__((deprecated)) esp_err_t esp_partition_table_basic_verify(const esp_partition_info_t *partition_table, bool log_errors, int *num_partitions) +{ + return esp_partition_table_verify(partition_table, log_errors, num_partitions); +} #endif diff --git a/components/bootloader_support/src/bootloader_common.c b/components/bootloader_support/src/bootloader_common.c index 12f60e9ce1..30a9dac441 100644 --- a/components/bootloader_support/src/bootloader_common.c +++ b/components/bootloader_support/src/bootloader_common.c @@ -100,18 +100,6 @@ bool bootloader_common_erase_part_type_data(const char *list_erase, bool ota_dat int num_partitions; bool ret = true; -#ifdef CONFIG_SECURE_BOOT_ENABLED - if (esp_secure_boot_enabled()) { - ESP_LOGI(TAG, "Verifying partition table signature..."); - err = esp_secure_boot_verify_signature(ESP_PARTITION_TABLE_OFFSET, ESP_PARTITION_TABLE_MAX_LEN); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to verify partition table signature."); - return false; - } - ESP_LOGD(TAG, "Partition table signature verified"); - } -#endif - partitions = bootloader_mmap(ESP_PARTITION_TABLE_OFFSET, ESP_PARTITION_TABLE_MAX_LEN); if (!partitions) { ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", ESP_PARTITION_TABLE_OFFSET, ESP_PARTITION_TABLE_MAX_LEN); @@ -119,7 +107,7 @@ bool bootloader_common_erase_part_type_data(const char *list_erase, bool ota_dat } ESP_LOGD(TAG, "mapped partition table 0x%x at 0x%x", ESP_PARTITION_TABLE_OFFSET, (intptr_t)partitions); - err = esp_partition_table_basic_verify(partitions, true, &num_partitions); + err = esp_partition_table_verify(partitions, true, &num_partitions); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to verify partition table"); ret = false; diff --git a/components/bootloader_support/src/bootloader_utility.c b/components/bootloader_support/src/bootloader_utility.c index 6ab3e50c51..6b0145a629 100644 --- a/components/bootloader_support/src/bootloader_utility.c +++ b/components/bootloader_support/src/bootloader_utility.c @@ -72,18 +72,6 @@ bool bootloader_utility_load_partition_table(bootloader_state_t* bs) esp_err_t err; int num_partitions; -#ifdef CONFIG_SECURE_BOOT_ENABLED - if(esp_secure_boot_enabled()) { - ESP_LOGI(TAG, "Verifying partition table signature..."); - err = esp_secure_boot_verify_signature(ESP_PARTITION_TABLE_OFFSET, ESP_PARTITION_TABLE_MAX_LEN); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to verify partition table signature."); - return false; - } - ESP_LOGD(TAG, "Partition table signature verified"); - } -#endif - partitions = bootloader_mmap(ESP_PARTITION_TABLE_OFFSET, ESP_PARTITION_TABLE_MAX_LEN); if (!partitions) { ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", ESP_PARTITION_TABLE_OFFSET, ESP_PARTITION_TABLE_MAX_LEN); @@ -91,7 +79,7 @@ bool bootloader_utility_load_partition_table(bootloader_state_t* bs) } ESP_LOGD(TAG, "mapped partition table 0x%x at 0x%x", ESP_PARTITION_TABLE_OFFSET, (intptr_t)partitions); - err = esp_partition_table_basic_verify(partitions, true, &num_partitions); + err = esp_partition_table_verify(partitions, true, &num_partitions); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to verify partition table"); return false; diff --git a/components/bootloader_support/src/flash_encrypt.c b/components/bootloader_support/src/flash_encrypt.c index 290a02a911..a9e8f8f9ba 100644 --- a/components/bootloader_support/src/flash_encrypt.c +++ b/components/bootloader_support/src/flash_encrypt.c @@ -254,7 +254,7 @@ static esp_err_t encrypt_and_load_partition_table(esp_partition_info_t *partitio ESP_LOGE(TAG, "Failed to read partition table data"); return err; } - if (esp_partition_table_basic_verify(partition_table, false, num_partitions) == ESP_OK) { + if (esp_partition_table_verify(partition_table, false, num_partitions) == ESP_OK) { ESP_LOGD(TAG, "partition table is plaintext. Encrypting..."); esp_err_t err = esp_flash_encrypt_region(ESP_PARTITION_TABLE_OFFSET, FLASH_SECTOR_SIZE); diff --git a/components/bootloader_support/src/flash_partitions.c b/components/bootloader_support/src/flash_partitions.c index f8a24f26c2..6686457338 100644 --- a/components/bootloader_support/src/flash_partitions.c +++ b/components/bootloader_support/src/flash_partitions.c @@ -20,7 +20,7 @@ static const char *TAG = "flash_parts"; -esp_err_t esp_partition_table_basic_verify(const esp_partition_info_t *partition_table, bool log_errors, int *num_partitions) +esp_err_t esp_partition_table_verify(const esp_partition_info_t *partition_table, bool log_errors, int *num_partitions) { int md5_found = 0; int num_parts; From 6fd6e024fc10d99c7ffe96fb5b4ed58cca48eff3 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Fri, 13 Jul 2018 15:24:11 +1000 Subject: [PATCH 3/6] bootloader: Fix warning building reflashable Secure Boot image --- components/bootloader/Makefile.projbuild | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/bootloader/Makefile.projbuild b/components/bootloader/Makefile.projbuild index 1d569bab3c..11ba9058a4 100644 --- a/components/bootloader/Makefile.projbuild +++ b/components/bootloader/Makefile.projbuild @@ -107,7 +107,7 @@ bootloader: $(BOOTLOADER_DIGEST_BIN) $(BOOTLOADER_DIGEST_BIN): $(BOOTLOADER_BIN) $(SECURE_BOOTLOADER_KEY) @echo "DIGEST $(notdir $@)" - $(Q) $(ESPSECUREPY) digest_secure_bootloader -k $(SECURE_BOOTLOADER_KEY) -o $@ $< + $(ESPSECUREPY) digest_secure_bootloader -k $(SECURE_BOOTLOADER_KEY) -o $@ $< else # CONFIG_SECURE_BOOT_ENABLED && !CONFIG_SECURE_BOOTLOADER_REFLASHABLE && !CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH bootloader: From 8b5a2ccb8db775fdd23e7c3486f586549edf3100 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Fri, 13 Jul 2018 16:18:07 +1000 Subject: [PATCH 4/6] docs: Update Flash Encryption docs to clarify reflashing options --- components/bootloader/Makefile.projbuild | 2 +- docs/en/security/flash-encryption.rst | 23 +++++++++++++++++------ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/components/bootloader/Makefile.projbuild b/components/bootloader/Makefile.projbuild index 11ba9058a4..b283c90445 100644 --- a/components/bootloader/Makefile.projbuild +++ b/components/bootloader/Makefile.projbuild @@ -116,7 +116,7 @@ bootloader: endif ifndef CONFIG_SECURE_BOOT_ENABLED -# don't build bootloader by default is secure boot is enabled +# don't build bootloader by default if secure boot is enabled all_binaries: $(BOOTLOADER_BIN) endif diff --git a/docs/en/security/flash-encryption.rst b/docs/en/security/flash-encryption.rst index 584a6df252..e925ee6182 100644 --- a/docs/en/security/flash-encryption.rst +++ b/docs/en/security/flash-encryption.rst @@ -43,7 +43,7 @@ This is the default (and recommended) flash encryption initialisation process. I **IMPORTANT: Once flash encryption is enabled on first boot, the hardware allows a maximum of 3 subsequent flash updates via serial re-flashing.** A special procedure (documented in :ref:`updating-encrypted-flash-serial`) must be followed to perform these updates. -- If secure boot is enabled, no physical re-flashes are possible. +- If secure boot is enabled, physical reflashing with plaintext data requires a "Reflashable" secure boot digest (see :ref:`flash-encryption-and-secure-boot`). - OTA updates can be used to update flash content without counting towards this limit. - When enabling flash encryption in development, use a `pregenerated flash encryption key` to allow physically re-flashing an unlimited number of times with pre-encrypted data.** @@ -129,14 +129,14 @@ OTA updates to encrypted partitions will automatically write encrypted, as long Serial Flashing ^^^^^^^^^^^^^^^ -Provided secure boot is not used, the :ref:`FLASH_CRYPT_CNT` allows the flash to be updated with new plaintext data via serial flashing (or other physical methods), up to 3 additional times. +The :ref:`FLASH_CRYPT_CNT` allows the flash to be updated with new plaintext data via serial flashing (or other physical methods), up to 3 additional times. The process involves flashing plaintext data, and then bumping the value of :ref:`FLASH_CRYPT_CNT` which causes the bootloader to re-encrypt this data. Limited Updates ~~~~~~~~~~~~~~~ -Only 4 serial flash update cycles of this kind are possible, including the initial encrypted flash. +Only 4 plaintext serial update cycles of this kind are possible, including the initial encrypted flash. After the fourth time encryption is disabled, :ref:`FLASH_CRYPT_CNT` has the maximum value `0xFF` and encryption is permanently disabled. @@ -149,7 +149,7 @@ Cautions With Serial Flashing - Using ``make flash`` should flash all partitions which need to be flashed. -- If secure boot is enabled, you can't reflash via serial at all unless you used the "Reflashable" option for Secure Boot, pre-generated a key and burned it to the ESP32 (refer to :doc:`Secure Boot ` docs.). In this case you can re-flash a plaintext secure boot digest and bootloader image at offset 0x0. It is necessary to re-flash this digest before flashing other plaintext data. +- If secure boot is enabled, you can't reflash plaintext data via serial at all unless you used the "Reflashable" option for Secure Boot. See :ref:`flash-encryption-and-secure-boot`. Serial Re-Flashing Procedure ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -181,7 +181,7 @@ Reflashing via Pregenerated Flash Encryption Key It is possible to pregenerate a flash encryption key on the host computer and burn it into the ESP32's efuse key block. This allows data to be pre-encrypted on the host and flashed to the ESP32 without needing a plaintext flash update. -This is useful for development, because it removes the 4 time reflashing limit. It also allows reflashing with secure boot enabled, because the bootloader doesn't need to be reflashed each time. +This is useful for development, because it removes the 4 time reflashing limit. It also allows reflashing the app with secure boot enabled, because the bootloader doesn't need to be reflashed each time. **IMPORTANT This method is intended to assist with development only, not for production devices. If pre-generating flash encryption for production, ensure the keys are generated from a high quality random number source and do not share the same flash encryption key across multiple devices.** @@ -268,7 +268,18 @@ Flash Encryption prevents plaintext readout of the encrypted flash, to protect f - For the same reason, an attacker can always tell when a pair of adjacent 16 byte blocks (32 byte aligned) contain identical content. Keep this in mind if storing sensitive data on the flash, design your flash storage so this doesn't happen (using a counter byte or some other non-identical value every 16 bytes is sufficient). -- Flash encryption alone may not prevent an attacker from modifying the firmware of the device. To prevent unauthorised firmware from runningon the device, use flash encryption in combination with :doc:`Secure Boot `. +- 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-and-secure-boot: + +Flash Encryption & 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: + +- :ref:`updating-encrypted-flash-ota` are not restricted (provided the new app is signed correctly with the Secure Boot signing key). +- :ref:`Plaintext serial flash updates ` are only possible if the :envvar:`Reflashable ` Secure Boot mode is selected and a Secure Boot key was pre-generated and burned to the ESP32 (refer to :doc:`Secure Boot ` docs.). In this configuration, ``make 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:`pregenerated-flash-encryption-key` is still possible, provided the bootloader is not reflashed. Reflashing the bootloader requires the same :envvar:`Reflashable ` option to be enabled in the Secure Boot config. .. _flash-encryption-advanced-features: From 6a498bfe2bf7a5ac28f0222adc9e598769ded05b Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Fri, 13 Jul 2018 16:19:23 +1000 Subject: [PATCH 5/6] docs: Add note about bootloader size for flash encryption & secure boot --- docs/en/security/flash-encryption.rst | 2 ++ docs/en/security/secure-boot.rst | 14 ++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/docs/en/security/flash-encryption.rst b/docs/en/security/flash-encryption.rst index e925ee6182..c36839ef4a 100644 --- a/docs/en/security/flash-encryption.rst +++ b/docs/en/security/flash-encryption.rst @@ -55,6 +55,8 @@ Process to enable flash encryption: - Build and flash the bootloader, partition table and factory app image as normal. These partitions are initially written to the flash unencrypted. +.. 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`. + - On first boot, the bootloader sees :ref:`FLASH_CRYPT_CNT` is set to 0 (factory default) so it generates a flash encryption key using the hardware random number generator. This key is stored in efuse. The key is read and write protected against further software access. - All of the encrypted partitions are then encrypted in-place by the bootloader. Encrypting in-place can take some time (up to a minute for large partitions.) diff --git a/docs/en/security/secure-boot.rst b/docs/en/security/secure-boot.rst index da9a203d36..7910fa3654 100644 --- a/docs/en/security/secure-boot.rst +++ b/docs/en/security/secure-boot.rst @@ -55,6 +55,20 @@ The following keys are used by the secure boot process: - The private key from this key pair *must be securely kept private*, as anyone who has this key can authenticate to any bootloader that is configured with secure boot and the matching public key. +.. _secure-boot-bootloader-size: + +Bootloader Size +--------------- + +When secure boot is enabled the bootloader app binary ``bootloader.bin`` may exceed the default bootloader size limit. This is especially likely if flash encryption is enabled as well. The default size limit is 0x7000 (28672) bytes (partition table offset 0x8000 - bootloader offset 0x1000). + +If the bootloader becomes too large, the ESP32 will fail to boot - errors will be logged about either invalid partition table or invalid bootloader checksum. + +Options to work around this are: + +- Reduce :envvar:`bootloader log level `. Setting log level to Warning, Error or None all significantly reduce the final binary size (but may make it harder to debug). +- Set :envvar:`partition table offset ` to a higher value than 0x8000, to place the partition table later in the flash. This increases the space available for the bootloader. If the :doc:`partition table ` CSV file contains explicit partition offsets, they will need changing so no partition has an offset lower than ``CONFIG_PARTITION_TABLE_OFFSET + 0x1000``. (This includes the default partition CSV files supplied with ESP-IDF.) + .. _secure-boot-howto: How To Enable Secure Boot From cee6d7d5a9ea0612746e4c3b6b9c38d1f0dd0255 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Fri, 13 Jul 2018 16:44:11 +1000 Subject: [PATCH 6/6] docs: Add more ReST-isms in secure boot & flash encryption docs (Original version of these docs were in Markdown.) --- components/partition_table/Kconfig.projbuild | 4 ++++ docs/en/security/flash-encryption.rst | 25 +++++++++++++------- docs/en/security/secure-boot.rst | 16 ++++++++----- 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/components/partition_table/Kconfig.projbuild b/components/partition_table/Kconfig.projbuild index db311145e0..f50de7aafc 100644 --- a/components/partition_table/Kconfig.projbuild +++ b/components/partition_table/Kconfig.projbuild @@ -43,6 +43,10 @@ config PARTITION_TABLE_OFFSET Allows you to move the partition table, it gives more space for the bootloader. Note that the bootloader and app will both need to be compiled with the same PARTITION_TABLE_OFFSET value. + This number should be a multiple of 0x1000. + + Note that partition offsets in the partition table CSV file may need to be changed if this value is set to a higher value. + config PARTITION_TABLE_MD5 bool "Generate an MD5 checksum for the partition table" default y diff --git a/docs/en/security/flash-encryption.rst b/docs/en/security/flash-encryption.rst index c36839ef4a..6981976a6a 100644 --- a/docs/en/security/flash-encryption.rst +++ b/docs/en/security/flash-encryption.rst @@ -5,7 +5,8 @@ Flash Encryption is a feature for encrypting the contents of the ESP32's attache Flash Encryption is separate from the :doc:`Secure Boot ` feature, and you can use flash encryption without enabling secure boot. However we recommend using both features together for a secure environment. -**IMPORTANT: Enabling flash encryption limits your options for further updates of your ESP32. Make sure to read this document (including :ref:`flash-encryption-limitations`) and understand the implications of enabling flash encryption.** +.. important:: + Enabling flash encryption limits your options for further updates of your ESP32. Make sure to read this document (including :ref:`flash-encryption-limitations`) and understand the implications of enabling flash encryption. Background ---------- @@ -41,7 +42,8 @@ Flash Encryption Initialisation This is the default (and recommended) flash encryption initialisation process. It is possible to customise this process for development or other purposes, see :ref:`flash-encryption-advanced-features` for details. -**IMPORTANT: Once flash encryption is enabled on first boot, the hardware allows a maximum of 3 subsequent flash updates via serial re-flashing.** A special procedure (documented in :ref:`updating-encrypted-flash-serial`) must be followed to perform these updates. +.. important:: + Once flash encryption is enabled on first boot, the hardware allows a maximum of 3 subsequent flash updates via serial re-flashing. A special procedure (documented in :ref:`updating-encrypted-flash-serial`) must be followed to perform these updates. - If secure boot is enabled, physical reflashing with plaintext data requires a "Reflashable" secure boot digest (see :ref:`flash-encryption-and-secure-boot`). - OTA updates can be used to update flash content without counting towards this limit. @@ -61,7 +63,8 @@ Process to enable flash encryption: - All of the encrypted partitions are then encrypted in-place by the bootloader. Encrypting in-place can take some time (up to a minute for large partitions.) -**IMPORTANT: Do not interrupt power to the ESP32 while the first boot encryption pass is running. If power is interrupted, the flash contents will be corrupted and require flashing with unencrypted data again. A reflash like this will not count towards the flashing limit.** +.. important:: + Do not interrupt power to the ESP32 while the first boot encryption pass is running. If power is interrupted, the flash contents will be corrupted and require flashing with unencrypted data again. A reflash like this will not count towards the flashing limit. - Once flashing is complete. efuses are blown (by default) to disable encrypted flash access while the UART bootloader is running. See :ref:`uart-bootloader-encryption` for advanced details. @@ -90,7 +93,8 @@ Whenever the :ref:`FLASH_CRYPT_CNT` is set to a value with an odd number of bits - Any data accessed via :func:`esp_spi_flash_mmap`. - The software bootloader image when it is read by the ROM bootloader. -**IMPORTANT: The MMU flash cache unconditionally decrypts all data. Data which is stored unencrypted in the flash will be "transparently decrypted" via the flash cache and appear to software like random garbage.** +.. 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 ^^^^^^^^^^^^^^^^^^^^^^^ @@ -185,7 +189,8 @@ It is possible to pregenerate a flash encryption key on the host computer and bu This is useful for development, because it removes the 4 time reflashing limit. It also allows reflashing the app with secure boot enabled, because the bootloader doesn't need to be reflashed each time. -**IMPORTANT This method is intended to assist with development only, not for production devices. If pre-generating flash encryption for production, ensure the keys are generated from a high quality random number source and do not share the same flash encryption key across multiple devices.** +.. important:: + This method is intended to assist with development only, not for production devices. If pre-generating flash encryption for production, ensure the keys are generated from a high quality random number source and do not share the same flash encryption key across multiple devices. Pregenerating a Flash Encryption Key ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -196,7 +201,7 @@ Flash encryption keys are 32 bytes of random data. You can generate a random key (The randomness of this data is only as good as the OS and it's Python installation's random data source.) -Alternatively, if you're using :doc:`secure boot ` and have a secure boot signing key then you can generate a deterministic SHA-256 digest of the secure boot private signing key and use this as the flash encryption key:: +Alternatively, if you're using :doc:`secure boot ` and have a :ref:`secure boot signing key ` then you can generate a deterministic SHA-256 digest of the secure boot private signing key and use this as the flash encryption key:: espsecure.py digest_private_key --keyfile secure_boot_signing_key.pem my_flash_encryption_key.bin @@ -280,7 +285,7 @@ Flash Encryption & 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: - :ref:`updating-encrypted-flash-ota` are not restricted (provided the new app is signed correctly with the Secure Boot signing key). -- :ref:`Plaintext serial flash updates ` are only possible if the :envvar:`Reflashable ` Secure Boot mode is selected and a Secure Boot key was pre-generated and burned to the ESP32 (refer to :doc:`Secure Boot ` docs.). In this configuration, ``make 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 :envvar:`Reflashable ` Secure Boot mode is selected and a Secure Boot key was pre-generated and burned to the ESP32 (refer to :ref:`Secure Boot ` docs.). In this configuration, ``make 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:`pregenerated-flash-encryption-key` is still possible, provided the bootloader is not reflashed. Reflashing the bootloader requires the same :envvar:`Reflashable ` option to be enabled in the Secure Boot config. .. _flash-encryption-advanced-features: @@ -333,9 +338,11 @@ It is possible to burn only some of these efuses, and write-protect the rest (wi (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.) -**IMPORTANT**: Write protecting these efuses to keep them unset is not currently very useful, as ``esptool.py`` does not support writing or reading encrypted flash. +.. important:: + Write protecting these efuses to keep them unset is not currently very useful, as ``esptool.py`` does not support writing or reading encrypted flash. -**IMPORTANT**: If ``DISABLE_DL_DECRYPT`` is left unset (0) this effectively makes flash encryption useless, as an attacker with physical access can use UART bootloader mode (with custom stub code) to read out the flash contents. +.. important:: + If ``DISABLE_DL_DECRYPT`` is left unset (0) this effectively makes flash encryption useless, as an attacker with physical access can use UART bootloader mode (with custom stub code) to read out the flash contents. .. _setting-flash-crypt-config: diff --git a/docs/en/security/secure-boot.rst b/docs/en/security/secure-boot.rst index 7910fa3654..dbf0e52679 100644 --- a/docs/en/security/secure-boot.rst +++ b/docs/en/security/secure-boot.rst @@ -82,9 +82,11 @@ How To Enable Secure Boot 4. The first time you run ``make``, if the signing key is not found then an error message will be printed with a command to generate a signing key via ``espsecure.py generate_signing_key``. - **IMPORTANT** A signing key generated this way will use the best random number source available to the OS and its Python installation (`/dev/urandom` on OSX/Linux and `CryptGenRandom()` on Windows). If this random number source is weak, then the private key will be weak. +.. important:: + A signing key generated this way will use the best random number source available to the OS and its Python installation (`/dev/urandom` on OSX/Linux and `CryptGenRandom()` on Windows). If this random number source is weak, then the private key will be weak. - **IMPORTANT** For production environments, we recommend generating the keypair using openssl or another industry standard encryption program. See :ref:`secure-boot-generate-key` for more details. +.. important:: + For production environments, we recommend generating the keypair using openssl or another industry standard encryption program. See :ref:`secure-boot-generate-key` for more details. 5. Run ``make bootloader`` to build a secure boot enabled bootloader. The output of ``make`` will include a prompt for a flashing command, using ``esptool.py write_flash``. @@ -94,11 +96,13 @@ How To Enable Secure Boot 7. Run ``make flash`` to build and flash the partition table and the just-built app image. The app image will be signed using the signing key you generated in step 4. - *NOTE*: ``make flash`` doesn't flash the bootloader if secure boot is enabled. +.. note:: ``make flash`` doesn't flash the bootloader if secure boot is enabled. 8. Reset the ESP32 and it will boot the software bootloader you flashed. The software bootloader will enable secure boot on the chip, and then it verifies the app image signature and boots the app. You should watch the serial console output from the ESP32 to verify that secure boot is enabled and no errors have occurred due to the build configuration. -**NOTE** Secure boot won't be enabled until after a valid partition table and app image have been flashed. This is to prevent accidents before the system is fully configured. +.. note:: Secure boot won't be enabled until after a valid partition table and app image have been flashed. This is to prevent accidents before the system is fully configured. + +.. note:: If the ESP32 is reset or powered down during the first boot, it will start the process again on the next boot. 9. On subsequent boots, the secure boot hardware will verify the software bootloader has not changed (using the secure bootloader key) and then the software bootloader will verify the signed partition table and app image (using the public key portion of the secure boot signing key). @@ -109,11 +113,11 @@ Re-Flashable Software Bootloader Configuration "Secure Boot: One-Time Flash" is the recommended configuration for production devices. In this mode, each device gets a unique key that is never stored outside the device. -However, an alternative mode "Secure Boot: Reflashable" is also available. This mode allows you to supply a 256-bit key file that is used for the secure bootloader key. As you have the key file, you can generate new bootloader images and secure boot digests for them. +However, an alternative mode :envvar:`Secure Boot: Reflashable ` is also available. This mode allows you to supply a 256-bit key file that is used for the secure bootloader key. As you have the key file, you can generate new bootloader images and secure boot digests for them. In the esp-idf build process, this 256-bit key file is derived from the app signing key generated during the generate_signing_key step above. The private key's SHA-256 digest is used as the 256-bit secure bootloader key. This is a convenience so you only need to generate/protect a single private key. -**NOTE**: Although it's possible, we strongly recommend not generating one secure boot key and flashing it to every device in a production environment. The "One-Time Flash" option is recommended for production environments. +.. note:: Although it's possible, we strongly recommend not generating one secure boot key and flashing it to every device in a production environment. The "One-Time Flash" option is recommended for production environments. To enable a reflashable bootloader: