mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
efuse: Add ESP32 V3 'disable Download Mode' functionality
This commit is contained in:
parent
363589e849
commit
5a4091a2c0
@ -535,5 +535,23 @@ menu "Security features"
|
||||
the wrong device. The device needs to have flash encryption already enabled using espefuse.py.
|
||||
|
||||
endmenu # Potentially Insecure
|
||||
|
||||
config SECURE_DISABLE_ROM_DL_MODE
|
||||
bool "Permanently disable ROM Download Mode"
|
||||
depends on ESP32_REV_MIN_3
|
||||
default n
|
||||
help
|
||||
If set, during startup the app will burn an eFuse bit to permanently disable the UART ROM
|
||||
Download Mode. This prevents any future use of esptool.py, espefuse.py and similar tools.
|
||||
|
||||
Once disabled, if the SoC is booted with strapping pins set for ROM Download Mode
|
||||
then an error is printed instead.
|
||||
|
||||
It is recommended to enable this option in any production application where Flash
|
||||
Encryption and/or Secure Boot is enabled and access to Download Mode is not required.
|
||||
|
||||
It is also possible to permanently disable Download Mode by calling
|
||||
esp_efuse_disable_rom_download_mode() at runtime.
|
||||
|
||||
endmenu # Security features
|
||||
|
||||
|
@ -121,6 +121,10 @@ esp_err_t esp_flash_encrypt_region(uint32_t src_addr, size_t data_length);
|
||||
* is enabled but secure boot is not used. This should protect against
|
||||
* serial re-flashing of an unauthorised code in absence of secure boot.
|
||||
*
|
||||
* @note On ESP32 V3 only, write protecting FLASH_CRYPT_CNT will also prevent
|
||||
* disabling UART Download Mode. If both are wanted, call
|
||||
* esp_efuse_disable_rom_download_mode() before calling this function.
|
||||
*
|
||||
*/
|
||||
void esp_flash_write_protect_crypt_cnt();
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
#include <assert.h>
|
||||
#include "esp_efuse_table.h"
|
||||
|
||||
// md5_digest_table 2e23344575b3d07f01ecb695294e9770
|
||||
// md5_digest_table 11b691b6fa8546a3862a7a876be5f758
|
||||
// This file was generated from the file esp_efuse_table.csv. DO NOT CHANGE THIS FILE MANUALLY.
|
||||
// If you want to change some fields, you need to change esp_efuse_table.csv file
|
||||
// then run `efuse_common_table` or `efuse_custom_table` command it will generate this file.
|
||||
@ -87,20 +87,24 @@ static const esp_efuse_desc_t DISABLE_DL_CACHE[] = {
|
||||
{EFUSE_BLK0, 201, 1}, // Flash encrypt. Disable UART bootloader MMU cache. EFUSE_DISABLE_DL_CACHE.,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t DISABLE_JTAG[] = {
|
||||
{EFUSE_BLK0, 198, 1}, // Flash encrypt. Disable JTAG. EFUSE_RD_DISABLE_JTAG.,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t CONSOLE_DEBUG_DISABLE[] = {
|
||||
{EFUSE_BLK0, 194, 1}, // Flash encrypt. Disable ROM BASIC interpreter fallback. EFUSE_RD_CONSOLE_DEBUG_DISABLE.,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t FLASH_CRYPT_CNT[] = {
|
||||
{EFUSE_BLK0, 20, 7}, // Flash encrypt. Flash encryption is enabled if this field has an odd number of bits set. EFUSE_FLASH_CRYPT_CNT.,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t DISABLE_JTAG[] = {
|
||||
{EFUSE_BLK0, 198, 1}, // Disable JTAG. EFUSE_RD_DISABLE_JTAG.,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t CONSOLE_DEBUG_DISABLE[] = {
|
||||
{EFUSE_BLK0, 194, 1}, // Disable ROM BASIC interpreter fallback. EFUSE_RD_CONSOLE_DEBUG_DISABLE.,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t UART_DOWNLOAD_DIS[] = {
|
||||
{EFUSE_BLK0, 27, 1}, // Disable UART download mode. Valid for ESP32 V3 and newer,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t WR_DIS_FLASH_CRYPT_CNT[] = {
|
||||
{EFUSE_BLK0, 2, 1}, // Flash encrypt. Write protection FLASH_CRYPT_CNT. EFUSE_WR_DIS_FLASH_CRYPT_CNT,
|
||||
{EFUSE_BLK0, 2, 1}, // Flash encrypt. Write protection FLASH_CRYPT_CNT,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t WR_DIS_BLK1[] = {
|
||||
@ -260,23 +264,28 @@ const esp_efuse_desc_t* ESP_EFUSE_DISABLE_DL_CACHE[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_DISABLE_JTAG[] = {
|
||||
&DISABLE_JTAG[0], // Flash encrypt. Disable JTAG. EFUSE_RD_DISABLE_JTAG.
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_CONSOLE_DEBUG_DISABLE[] = {
|
||||
&CONSOLE_DEBUG_DISABLE[0], // Flash encrypt. Disable ROM BASIC interpreter fallback. EFUSE_RD_CONSOLE_DEBUG_DISABLE.
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_FLASH_CRYPT_CNT[] = {
|
||||
&FLASH_CRYPT_CNT[0], // Flash encrypt. Flash encryption is enabled if this field has an odd number of bits set. EFUSE_FLASH_CRYPT_CNT.
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_DISABLE_JTAG[] = {
|
||||
&DISABLE_JTAG[0], // Disable JTAG. EFUSE_RD_DISABLE_JTAG.
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_CONSOLE_DEBUG_DISABLE[] = {
|
||||
&CONSOLE_DEBUG_DISABLE[0], // Disable ROM BASIC interpreter fallback. EFUSE_RD_CONSOLE_DEBUG_DISABLE.
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_UART_DOWNLOAD_DIS[] = {
|
||||
&UART_DOWNLOAD_DIS[0], // Disable UART download mode. Valid for ESP32 V3 and newer
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_FLASH_CRYPT_CNT[] = {
|
||||
&WR_DIS_FLASH_CRYPT_CNT[0], // Flash encrypt. Write protection FLASH_CRYPT_CNT. EFUSE_WR_DIS_FLASH_CRYPT_CNT
|
||||
&WR_DIS_FLASH_CRYPT_CNT[0], // Flash encrypt. Write protection FLASH_CRYPT_CNT
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -39,13 +39,16 @@ ENCRYPT_CONFIG, EFUSE_BLK0, 188, 4, Flash encrypt. EFUSE_FLASH_C
|
||||
DISABLE_DL_ENCRYPT, EFUSE_BLK0, 199, 1, Flash encrypt. Disable UART bootloader encryption. EFUSE_DISABLE_DL_ENCRYPT.
|
||||
DISABLE_DL_DECRYPT, EFUSE_BLK0, 200, 1, Flash encrypt. Disable UART bootloader decryption. EFUSE_DISABLE_DL_DECRYPT.
|
||||
DISABLE_DL_CACHE, EFUSE_BLK0, 201, 1, Flash encrypt. Disable UART bootloader MMU cache. EFUSE_DISABLE_DL_CACHE.
|
||||
DISABLE_JTAG, EFUSE_BLK0, 198, 1, Flash encrypt. Disable JTAG. EFUSE_RD_DISABLE_JTAG.
|
||||
CONSOLE_DEBUG_DISABLE, EFUSE_BLK0, 194, 1, Flash encrypt. Disable ROM BASIC interpreter fallback. EFUSE_RD_CONSOLE_DEBUG_DISABLE.
|
||||
FLASH_CRYPT_CNT, EFUSE_BLK0, 20, 7, Flash encrypt. Flash encryption is enabled if this field has an odd number of bits set. EFUSE_FLASH_CRYPT_CNT.
|
||||
|
||||
# Misc Security #
|
||||
DISABLE_JTAG, EFUSE_BLK0, 198, 1, Disable JTAG. EFUSE_RD_DISABLE_JTAG.
|
||||
CONSOLE_DEBUG_DISABLE, EFUSE_BLK0, 194, 1, Disable ROM BASIC interpreter fallback. EFUSE_RD_CONSOLE_DEBUG_DISABLE.
|
||||
UART_DOWNLOAD_DIS, EFUSE_BLK0, 27, 1, Disable UART download mode. Valid for ESP32 V3 and newer, only.
|
||||
|
||||
# Write protection #
|
||||
####################
|
||||
WR_DIS_FLASH_CRYPT_CNT, EFUSE_BLK0, 2, 1, Flash encrypt. Write protection FLASH_CRYPT_CNT. EFUSE_WR_DIS_FLASH_CRYPT_CNT
|
||||
WR_DIS_FLASH_CRYPT_CNT, EFUSE_BLK0, 2, 1, Flash encrypt. Write protection FLASH_CRYPT_CNT, UART_DOWNLOAD_DIS. EFUSE_WR_DIS_FLASH_CRYPT_CNT
|
||||
WR_DIS_BLK1, EFUSE_BLK0, 7, 1, Flash encrypt. Write protection encryption key. EFUSE_WR_DIS_BLK1
|
||||
WR_DIS_BLK2, EFUSE_BLK0, 8, 1, Security boot. Write protection security key. EFUSE_WR_DIS_BLK2
|
||||
WR_DIS_BLK3, EFUSE_BLK0, 9, 1, Write protection for EFUSE_BLK3. EFUSE_WR_DIS_BLK3
|
||||
|
Can't render this file because it contains an unexpected character in line 7 and column 87.
|
@ -17,7 +17,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
// md5_digest_table 2e23344575b3d07f01ecb695294e9770
|
||||
// md5_digest_table 11b691b6fa8546a3862a7a876be5f758
|
||||
// This file was generated from the file esp_efuse_table.csv. DO NOT CHANGE THIS FILE MANUALLY.
|
||||
// If you want to change some fields, you need to change esp_efuse_table.csv file
|
||||
// then run `efuse_common_table` or `efuse_custom_table` command it will generate this file.
|
||||
@ -36,9 +36,10 @@ extern const esp_efuse_desc_t* ESP_EFUSE_ENCRYPT_CONFIG[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_DISABLE_DL_ENCRYPT[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_DISABLE_DL_DECRYPT[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_DISABLE_DL_CACHE[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_FLASH_CRYPT_CNT[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_DISABLE_JTAG[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_CONSOLE_DEBUG_DISABLE[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_FLASH_CRYPT_CNT[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_UART_DOWNLOAD_DIS[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_FLASH_CRYPT_CNT[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_BLK1[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_BLK2[];
|
||||
|
@ -335,6 +335,23 @@ void esp_efuse_disable_basic_rom_console(void);
|
||||
*/
|
||||
esp_err_t esp_efuse_apply_34_encoding(const uint8_t *in_bytes, uint32_t *out_words, size_t in_bytes_len);
|
||||
|
||||
/* @brief Disable ROM Download Mode via eFuse
|
||||
*
|
||||
* Permanently disables the ROM Download Mode feature. Once disabled, if the SoC is booted with
|
||||
* strapping pins set for ROM Download Mode then an error is printed instead.
|
||||
*
|
||||
* @note Not all SoCs support this option. An error will be returned if called on an ESP32
|
||||
* with a silicon revision lower than 3, as these revisions do not support this option.
|
||||
*
|
||||
* @note If ROM Download Mode is already disabled, this function does nothing and returns success.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK If the eFuse was successfully burned, or had already been burned.
|
||||
* - ESP_ERR_NOT_SUPPORTED (ESP32 only) This SoC is not capable of disabling UART download mode
|
||||
* - ESP_ERR_INVALID_STATE (ESP32 only) This eFuse is write protected and cannot be written
|
||||
*/
|
||||
esp_err_t esp_efuse_disable_rom_download_mode(void);
|
||||
|
||||
/* @brief Write random data to efuse key block write registers
|
||||
*
|
||||
* @note Caller is responsible for ensuring efuse
|
||||
|
@ -115,6 +115,33 @@ esp_err_t esp_efuse_apply_34_encoding(const uint8_t *in_bytes, uint32_t *out_wor
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_efuse_disable_rom_download_mode(void)
|
||||
{
|
||||
uint8_t dl_dis = 0;
|
||||
uint8_t wr_dis_flash_crypt_cnt = 0;
|
||||
#ifndef CONFIG_ESP32_REV_MIN_3
|
||||
/* Check if we support this revision at all */
|
||||
if(esp_efuse_get_chip_ver() < 3) {
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
#endif
|
||||
|
||||
esp_efuse_read_field_blob(ESP_EFUSE_UART_DOWNLOAD_DIS, &dl_dis, 1);
|
||||
if (dl_dis) {
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/* WR_DIS_FLASH_CRYPT_CNT also covers UART_DOWNLOAD_DIS on ESP32 */
|
||||
esp_efuse_read_field_blob(ESP_EFUSE_WR_DIS_FLASH_CRYPT_CNT, &wr_dis_flash_crypt_cnt, 1);
|
||||
if(wr_dis_flash_crypt_cnt) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
dl_dis = 1;
|
||||
return esp_efuse_write_field_blob(ESP_EFUSE_UART_DOWNLOAD_DIS, &dl_dis, 1);
|
||||
}
|
||||
|
||||
|
||||
void esp_efuse_write_random_key(uint32_t blk_wdata0_reg)
|
||||
{
|
||||
uint32_t buf[8];
|
||||
|
@ -350,6 +350,14 @@ void start_cpu0_default(void)
|
||||
#if CONFIG_ESP32_BROWNOUT_DET
|
||||
esp_brownout_init();
|
||||
#endif
|
||||
|
||||
#if CONFIG_ESP32_DISABLE_BASIC_ROM_CONSOLE
|
||||
esp_efuse_disable_basic_rom_console();
|
||||
#endif
|
||||
#if CONFIG_SECURE_DISABLE_ROM_DL_MODE
|
||||
esp_efuse_disable_rom_download_mode();
|
||||
#endif
|
||||
|
||||
rtc_gpio_force_hold_dis_all();
|
||||
esp_vfs_dev_uart_register();
|
||||
esp_reent_init(_GLOBAL_REENT);
|
||||
|
@ -377,6 +377,17 @@ Once the flash encryption is enabled in Release mode the bootloader will write p
|
||||
|
||||
For subsequent plaintext update in field OTA scheme should be used. Please refer :doc:`OTA <../api-reference/system/ota>` for further details.
|
||||
|
||||
. _flash-encrypt-best-practices:
|
||||
|
||||
Best Practices
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
When using Flash Encryption in production:
|
||||
|
||||
- Do not reuse the same flash encryption key between multiple devices. This means that an attacker who copies encrypted data from one device cannot transfer it to a second device.
|
||||
- When using ESP32 V3, if the UART ROM Download Mode is not needed for a production device then it should be disabled to provide an extra level of protection. Do this by calling :cpp:func:`esp_efuse_disable_rom_download_mode` during application startup. Alternatively, configure the project :ref:`CONFIG_ESP32_REV_MIN` level to 3 (targeting ESP32 V3 only) and enable :ref:`CONFIG_SECURE_DISABLE_ROM_DL_MODE`. The ability to disable ROM Download Mode is not available on earlier ESP32 versions.
|
||||
- Enable :doc:`Secure Boot <secure-boot>` as an extra layer of protection, and to prevent an attacker from selectively corrupting any part of the flash before boot.
|
||||
|
||||
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 ESP32 is loaded with plaintext data:
|
||||
@ -569,16 +580,12 @@ Reset the ESP32 and flash encryption should be disabled, the bootloader will boo
|
||||
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.
|
||||
|
||||
- Not all data is stored encrypted. If storing data on flash, check if the method you are using (library, API, etc.) supports flash encryption.
|
||||
|
||||
- Flash encryption does not prevent an attacker from understanding the high-level layout of the flash. This is because the same AES key is used for every 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).
|
||||
|
||||
- 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 <nvs_encryption>` deals with this and is suitable for many uses.
|
||||
|
||||
- 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 <secure-boot>`.
|
||||
|
||||
.. _flash-encryption-and-secure-boot:
|
||||
|
Loading…
Reference in New Issue
Block a user