mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'feature/dis_uart_dl_mode' into 'master'
feature: Disable UART download mode Closes IDF-1386 See merge request espressif/esp-idf!8590
This commit is contained in:
commit
baedfab382
@ -587,6 +587,7 @@ menu "Security features"
|
||||
|
||||
config SECURE_FLASH_ENCRYPTION_MODE_RELEASE
|
||||
bool "Release"
|
||||
select SECURE_ENABLE_SECURE_ROM_DL_MODE
|
||||
|
||||
endchoice
|
||||
|
||||
@ -698,5 +699,48 @@ 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 !IDF_TARGET_ESP32 || 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.
|
||||
|
||||
config SECURE_ENABLE_SECURE_ROM_DL_MODE
|
||||
bool "Permanently switch to ROM UART Secure Download mode"
|
||||
depends on IDF_TARGET_ESP32S2 && !SECURE_DISABLE_ROM_DL_MODE
|
||||
help
|
||||
If set, during startup the app will burn an eFuse bit to permanently switch the UART ROM
|
||||
Download Mode into a separate Secure Download mode. This option can only work if
|
||||
Download Mode is not already disabled by eFuse.
|
||||
|
||||
Secure Download mode limits the use of Download Mode functions to simple flash read,
|
||||
write and erase operations, plus a command to return a summary of currently enabled
|
||||
security features.
|
||||
|
||||
Secure Download mode is not compatible with the esptool.py flasher stub feature,
|
||||
espefuse.py, read/writing memory or registers, encrypted download, or any other
|
||||
features that interact with unsupported Download Mode commands.
|
||||
|
||||
Secure Download mode should be enabled in any application where Flash Encryption
|
||||
and/or Secure Boot is enabled. Disabling this option does not immediately cancel
|
||||
the benefits of the security features, but it increases the potential "attack
|
||||
surface" for an attacker to try and bypass them with a successful physical attack.
|
||||
|
||||
It is also possible to enable secure download mode at runtime by calling
|
||||
esp_efuse_enable_rom_secure_download_mode()
|
||||
|
||||
|
||||
endmenu # Security features
|
||||
|
||||
|
@ -128,6 +128,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(void);
|
||||
|
||||
|
@ -188,31 +188,28 @@ static esp_err_t initialise_flash_encryption(void)
|
||||
|
||||
#ifndef CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC
|
||||
ESP_LOGI(TAG, "Disable UART bootloader encryption...");
|
||||
const uint8_t dis_manual_encrypt = 1;
|
||||
esp_efuse_write_field_blob(ESP_EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT, &dis_manual_encrypt, 1);
|
||||
esp_efuse_write_field_bit(ESP_EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT);
|
||||
#else
|
||||
ESP_LOGW(TAG, "Not disabling UART bootloader encryption");
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_CACHE
|
||||
ESP_LOGI(TAG, "Disable UART bootloader cache...");
|
||||
const uint8_t dis_download_caches = 1;
|
||||
esp_efuse_write_field_blob(ESP_EFUSE_DIS_DOWNLOAD_DCACHE, &dis_download_caches, 1);
|
||||
esp_efuse_write_field_blob(ESP_EFUSE_DIS_DOWNLOAD_ICACHE, &dis_download_caches, 1);
|
||||
esp_efuse_write_field_bit(ESP_EFUSE_DIS_DOWNLOAD_DCACHE);
|
||||
esp_efuse_write_field_bit(ESP_EFUSE_DIS_DOWNLOAD_ICACHE);
|
||||
#else
|
||||
ESP_LOGW(TAG, "Not disabling UART bootloader cache - SECURITY COMPROMISED");
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SECURE_BOOT_ALLOW_JTAG
|
||||
ESP_LOGI(TAG, "Disable JTAG...");
|
||||
const uint8_t dis_jtag = 1;
|
||||
esp_efuse_write_field_blob(ESP_EFUSE_HARD_DIS_JTAG, &dis_jtag, 1);
|
||||
esp_efuse_write_field_bit(ESP_EFUSE_HARD_DIS_JTAG);
|
||||
#else
|
||||
ESP_LOGW(TAG, "Not disabling JTAG - SECURITY COMPROMISED");
|
||||
#endif
|
||||
|
||||
const uint8_t dis_boot_remap = 1;
|
||||
esp_efuse_write_field_blob(ESP_EFUSE_DIS_BOOT_REMAP, &dis_boot_remap, 1);
|
||||
esp_efuse_write_field_bit(ESP_EFUSE_DIS_BOOT_REMAP);
|
||||
esp_efuse_write_field_bit(ESP_EFUSE_DIS_LEGACY_SPI_BOOT);
|
||||
|
||||
esp_err_t err = esp_efuse_batch_write_commit();
|
||||
|
||||
|
@ -34,12 +34,20 @@ esp_err_t esp_secure_boot_permanently_enable(void)
|
||||
return r;
|
||||
}
|
||||
|
||||
ets_efuse_clear_program_registers();
|
||||
REG_SET_BIT(EFUSE_PGM_DATA3_REG, EFUSE_SECURE_BOOT_EN);
|
||||
ets_efuse_program(ETS_EFUSE_BLOCK0);
|
||||
esp_efuse_batch_write_begin(); /* Batch all efuse writes at the end of this function */
|
||||
|
||||
assert(ets_efuse_secure_boot_enabled());
|
||||
ESP_LOGI(TAG, "Secure boot permanently enabled");
|
||||
esp_efuse_write_field_bit(ESP_EFUSE_SECURE_BOOT_EN);
|
||||
esp_efuse_write_field_bit(ESP_EFUSE_DIS_BOOT_REMAP);
|
||||
esp_efuse_write_field_bit(ESP_EFUSE_DIS_LEGACY_SPI_BOOT);
|
||||
|
||||
// TODO: also disable JTAG here, etc
|
||||
|
||||
esp_err_t err = esp_efuse_batch_write_commit();
|
||||
|
||||
if (err == ESP_OK) {
|
||||
assert(ets_efuse_secure_boot_enabled());
|
||||
ESP_LOGI(TAG, "Secure boot permanently enabled");
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
@ -41,8 +41,7 @@ void esp_flash_encryption_init_checks()
|
||||
#ifdef CONFIG_SECURE_FLASH_ENCRYPTION_MODE_RELEASE
|
||||
#ifdef CONFIG_SECURE_BOOT
|
||||
if (esp_secure_boot_enabled() && esp_flash_encryption_enabled()) {
|
||||
uint8_t flash_crypt_cnt_wr_dis = 0;
|
||||
esp_efuse_read_field_blob(WR_DIS_CRYPT_CNT, &flash_crypt_cnt_wr_dis, 1);
|
||||
bool flash_crypt_cnt_wr_dis = esp_efuse_read_field_bit(WR_DIS_CRYPT_CNT);
|
||||
if (!flash_crypt_cnt_wr_dis) {
|
||||
uint8_t flash_crypt_cnt = 0;
|
||||
esp_efuse_read_field_blob(CRYPT_CNT, &flash_crypt_cnt, CRYPT_CNT[0]->bit_count);
|
||||
@ -76,13 +75,7 @@ void esp_flash_encryption_init_checks()
|
||||
|
||||
void esp_flash_write_protect_crypt_cnt(void)
|
||||
{
|
||||
uint8_t flash_crypt_cnt_wr_dis = 0;
|
||||
|
||||
esp_efuse_read_field_blob(WR_DIS_CRYPT_CNT, &flash_crypt_cnt_wr_dis, 1);
|
||||
|
||||
if (!flash_crypt_cnt_wr_dis) {
|
||||
esp_efuse_write_field_cnt(WR_DIS_CRYPT_CNT, 1);
|
||||
}
|
||||
esp_efuse_write_field_bit(WR_DIS_CRYPT_CNT);
|
||||
}
|
||||
|
||||
esp_flash_enc_mode_t esp_get_flash_encryption_mode(void)
|
||||
@ -101,27 +94,27 @@ esp_flash_enc_mode_t esp_get_flash_encryption_mode(void)
|
||||
|
||||
if (esp_flash_encryption_enabled()) {
|
||||
/* Check if FLASH CRYPT CNT is write protected */
|
||||
esp_efuse_read_field_blob(WR_DIS_CRYPT_CNT, &efuse_flash_crypt_cnt_wr_protected, 1);
|
||||
efuse_flash_crypt_cnt_wr_protected = esp_efuse_read_field_bit(WR_DIS_CRYPT_CNT);
|
||||
|
||||
if (efuse_flash_crypt_cnt_wr_protected) {
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
esp_efuse_read_field_blob(ESP_EFUSE_DISABLE_DL_CACHE, &dis_dl_cache, 1);
|
||||
esp_efuse_read_field_blob(ESP_EFUSE_DISABLE_DL_ENCRYPT, &dis_dl_enc, 1);
|
||||
esp_efuse_read_field_blob(ESP_EFUSE_DISABLE_DL_DECRYPT, &dis_dl_dec, 1);
|
||||
dis_dl_cache = esp_efuse_read_field_bit(ESP_EFUSE_DISABLE_DL_CACHE);
|
||||
dis_dl_enc = esp_efuse_read_field_bit(ESP_EFUSE_DISABLE_DL_ENCRYPT);
|
||||
dis_dl_dec = esp_efuse_read_field_bit(ESP_EFUSE_DISABLE_DL_DECRYPT);
|
||||
/* Check if DISABLE_DL_DECRYPT, DISABLE_DL_ENCRYPT & DISABLE_DL_CACHE are set */
|
||||
if ( dis_dl_cache && dis_dl_enc && dis_dl_dec ) {
|
||||
mode = ESP_FLASH_ENC_MODE_RELEASE;
|
||||
}
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
esp_efuse_read_field_blob(ESP_EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT, &dis_dl_enc, 1);
|
||||
esp_efuse_read_field_blob(ESP_EFUSE_DIS_DOWNLOAD_ICACHE, &dis_dl_icache, 1);
|
||||
esp_efuse_read_field_blob(ESP_EFUSE_DIS_DOWNLOAD_DCACHE, &dis_dl_dcache, 1);
|
||||
dis_dl_enc = esp_efuse_read_field_bit(ESP_EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT);
|
||||
dis_dl_icache = esp_efuse_read_field_bit(ESP_EFUSE_DIS_DOWNLOAD_ICACHE);
|
||||
dis_dl_dcache = esp_efuse_read_field_bit(ESP_EFUSE_DIS_DOWNLOAD_DCACHE);
|
||||
|
||||
if (dis_dl_enc && dis_dl_icache && dis_dl_dcache) {
|
||||
mode = ESP_FLASH_ENC_MODE_RELEASE;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
mode = ESP_FLASH_ENC_MODE_DISABLED;
|
||||
|
@ -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[];
|
||||
|
@ -21,6 +21,7 @@ extern "C" {
|
||||
#include <stdint.h>
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "sdkconfig.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/esp_efuse.h"
|
||||
@ -66,6 +67,23 @@ typedef struct esp_efuse_desc_s esp_efuse_desc_t;
|
||||
*/
|
||||
esp_err_t esp_efuse_read_field_blob(const esp_efuse_desc_t* field[], void* dst, size_t dst_size_bits);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Read a single bit eFuse field as a boolean value.
|
||||
*
|
||||
* @note The value must exist and must be a single bit wide. If there is any possibility of an error
|
||||
* in the provided arguments, call esp_efuse_read_field_blob() and check the returned value instead.
|
||||
*
|
||||
* @note If assertions are enabled and the parameter is invalid, execution will abort
|
||||
*
|
||||
* @param[in] field A pointer to the structure describing the fields of efuse.
|
||||
* @return
|
||||
* - true: The field parameter is valid and the bit is set.
|
||||
* - false: The bit is not set, or the parameter is invalid and assertions are disabled.
|
||||
*
|
||||
*/
|
||||
bool esp_efuse_read_field_bit(const esp_efuse_desc_t *field[]);
|
||||
|
||||
/**
|
||||
* @brief Reads bits from EFUSE field and returns number of bits programmed as "1".
|
||||
*
|
||||
@ -114,6 +132,23 @@ esp_err_t esp_efuse_write_field_blob(const esp_efuse_desc_t* field[], const void
|
||||
*/
|
||||
esp_err_t esp_efuse_write_field_cnt(const esp_efuse_desc_t* field[], size_t cnt);
|
||||
|
||||
/**
|
||||
* @brief Write a single bit eFuse field to 1
|
||||
*
|
||||
* For use with eFuse fields that are a single bit. This function will write the bit to value 1 if
|
||||
* it is not already set, or does nothing if the bit is already set.
|
||||
*
|
||||
* This is equivalent to calling esp_efuse_write_field_cnt() with the cnt parameter equal to 1,
|
||||
* except that it will return ESP_OK if the field is already set to 1.
|
||||
*
|
||||
* @param[in] field Pointer to the structure describing the efuse field.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: The operation was successfully completed, or the bit was already set to value 1.
|
||||
* - ESP_ERR_INVALID_ARG: Error in the passed arugments, including if the efuse field is not 1 bit wide.
|
||||
*/
|
||||
esp_err_t esp_efuse_write_field_bit(const esp_efuse_desc_t* field[]);
|
||||
|
||||
/**
|
||||
* @brief Sets a write protection for the whole block.
|
||||
*
|
||||
@ -274,15 +309,48 @@ void esp_efuse_reset(void);
|
||||
* By default, if booting from flash fails the ESP32 will boot a
|
||||
* BASIC console in ROM.
|
||||
*
|
||||
* Call this function (from bootloader or app) to permanently
|
||||
* disable the console on this chip.
|
||||
*
|
||||
* Call this function (from bootloader or app) to permanently disable the console on this chip.
|
||||
*
|
||||
*/
|
||||
void esp_efuse_disable_basic_rom_console(void);
|
||||
#endif
|
||||
|
||||
|
||||
/* @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);
|
||||
|
||||
#if SOC_SUPPORTS_SECURE_DL_MODE
|
||||
/* @brief Switch ROM Download Mode to Secure Download mode via eFuse
|
||||
*
|
||||
* Permanently enables Secure Download mode. This mode limits the use of ROM Download Mode functions
|
||||
* to simple flash read, write and erase operations, plus a command to return a summary of currently
|
||||
* enabled security features.
|
||||
*
|
||||
* @note If Secure Download mode is already enabled, this function does nothing and returns success.
|
||||
*
|
||||
* @note Disabling the ROM Download Mode also disables Secure Download Mode.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK If the eFuse was successfully burned, or had already been burned.
|
||||
* - ESP_ERR_INVALID_STATE ROM Download Mode has been disabled via eFuse, so Secure Download mode is unavailable.
|
||||
*/
|
||||
esp_err_t esp_efuse_enable_rom_secure_download_mode(void);
|
||||
#endif
|
||||
|
||||
/* @brief Write random data to efuse key block write registers
|
||||
*
|
||||
* @note Caller is responsible for ensuring efuse
|
||||
|
@ -70,14 +70,33 @@ uint32_t esp_efuse_get_pkg_ver(void)
|
||||
// Disable BASIC ROM Console via efuse
|
||||
void esp_efuse_disable_basic_rom_console(void)
|
||||
{
|
||||
uint8_t console_debug_disable = 0;
|
||||
esp_efuse_read_field_blob(ESP_EFUSE_CONSOLE_DEBUG_DISABLE, &console_debug_disable, 1);
|
||||
if (console_debug_disable == 0) {
|
||||
if (!esp_efuse_read_field_bit(ESP_EFUSE_CONSOLE_DEBUG_DISABLE)) {
|
||||
esp_efuse_write_field_cnt(ESP_EFUSE_CONSOLE_DEBUG_DISABLE, 1);
|
||||
ESP_EARLY_LOGI(TAG, "Disable BASIC ROM Console fallback via efuse...");
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t esp_efuse_disable_rom_download_mode(void)
|
||||
{
|
||||
#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
|
||||
|
||||
if (esp_efuse_read_field_bit(ESP_EFUSE_UART_DOWNLOAD_DIS)) {
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/* WR_DIS_FLASH_CRYPT_CNT also covers UART_DOWNLOAD_DIS on ESP32 */
|
||||
if(esp_efuse_read_field_bit(ESP_EFUSE_WR_DIS_FLASH_CRYPT_CNT)) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
return esp_efuse_write_field_bit(ESP_EFUSE_UART_DOWNLOAD_DIS);
|
||||
}
|
||||
|
||||
void esp_efuse_write_random_key(uint32_t blk_wdata0_reg)
|
||||
{
|
||||
uint32_t buf[8];
|
||||
|
@ -60,3 +60,17 @@ void esp_efuse_write_random_key(uint32_t blk_wdata0_reg)
|
||||
bzero(buf, sizeof(buf));
|
||||
bzero(raw, sizeof(raw));
|
||||
}
|
||||
|
||||
esp_err_t esp_efuse_disable_rom_download_mode(void)
|
||||
{
|
||||
return esp_efuse_write_field_bit(ESP_EFUSE_DIS_DOWNLOAD_MODE);
|
||||
}
|
||||
|
||||
esp_err_t esp_efuse_enable_rom_secure_download_mode(void)
|
||||
{
|
||||
if (esp_efuse_read_field_bit(ESP_EFUSE_DIS_DOWNLOAD_MODE)) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
return esp_efuse_write_field_bit(ESP_EFUSE_ENABLE_SECURITY_DOWNLOAD);
|
||||
}
|
||||
|
||||
|
@ -54,6 +54,14 @@ esp_err_t esp_efuse_read_field_blob(const esp_efuse_desc_t* field[], void* dst,
|
||||
return err;
|
||||
}
|
||||
|
||||
bool esp_efuse_read_field_bit(const esp_efuse_desc_t *field[])
|
||||
{
|
||||
uint8_t value = 0;
|
||||
esp_err_t err = esp_efuse_read_field_blob(field, &value, 1);
|
||||
assert(err == ESP_OK);
|
||||
return (err == ESP_OK) && value;
|
||||
}
|
||||
|
||||
// read number of bits programmed as "1" in the particular field
|
||||
esp_err_t esp_efuse_read_field_cnt(const esp_efuse_desc_t* field[], size_t* out_cnt)
|
||||
{
|
||||
@ -131,6 +139,25 @@ esp_err_t esp_efuse_write_field_cnt(const esp_efuse_desc_t* field[], size_t cnt)
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t esp_efuse_write_field_bit(const esp_efuse_desc_t* field[])
|
||||
{
|
||||
esp_err_t err;
|
||||
uint8_t existing = 0;
|
||||
const uint8_t one = 1;
|
||||
|
||||
if (field == NULL || field[0]->bit_count != 1) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
/* Check existing value. esp_efuse_write_field_blob() also checks this, but will log an error */
|
||||
err = esp_efuse_read_field_blob(field, &existing, 1);
|
||||
if (err != ESP_OK || existing) {
|
||||
return err; // Error reading, or the bit is already written and we can no-op this
|
||||
}
|
||||
|
||||
return esp_efuse_write_field_blob(field, &one, 1);
|
||||
}
|
||||
|
||||
// get the length of the field in bits
|
||||
int esp_efuse_get_field_size(const esp_efuse_desc_t* field[])
|
||||
{
|
||||
|
@ -267,6 +267,32 @@ TEST_CASE("efuse test write_field_cnt", "[efuse]")
|
||||
test_write_cnt();
|
||||
}
|
||||
|
||||
TEST_CASE("efuse test single bit functions", "[efuse]")
|
||||
{
|
||||
esp_efuse_utility_erase_virt_blocks();
|
||||
esp_efuse_utility_debug_dump_blocks();
|
||||
|
||||
uint8_t test_bit;
|
||||
TEST_ESP_OK(esp_efuse_read_field_blob(ESP_EFUSE_TEST5_LEN_1, &test_bit, 1));
|
||||
TEST_ASSERT_EQUAL_HEX8(0, test_bit);
|
||||
|
||||
test_bit = esp_efuse_read_field_bit(ESP_EFUSE_TEST5_LEN_1);
|
||||
TEST_ASSERT_EQUAL_HEX8(0, test_bit);
|
||||
|
||||
TEST_ESP_OK(esp_efuse_write_field_bit(ESP_EFUSE_TEST5_LEN_1));
|
||||
TEST_ESP_OK(esp_efuse_read_field_blob(ESP_EFUSE_TEST5_LEN_1, &test_bit, 1));
|
||||
TEST_ASSERT_EQUAL_HEX8(1, test_bit);
|
||||
|
||||
test_bit = esp_efuse_read_field_bit(ESP_EFUSE_TEST5_LEN_1);
|
||||
TEST_ASSERT_EQUAL_HEX8(1, test_bit);
|
||||
|
||||
// Can write the bit again and it's a no-op
|
||||
TEST_ESP_OK(esp_efuse_write_field_bit(ESP_EFUSE_TEST5_LEN_1));
|
||||
TEST_ASSERT_EQUAL_HEX8(1, esp_efuse_read_field_bit(ESP_EFUSE_TEST5_LEN_1));
|
||||
|
||||
esp_efuse_utility_debug_dump_blocks();
|
||||
}
|
||||
|
||||
void cut_tail_arr(uint8_t *arr, int num_used_bits, size_t count_bits)
|
||||
{
|
||||
if ((num_used_bits + count_bits) % 8) {
|
||||
|
@ -366,6 +366,10 @@ void start_cpu0_default(void)
|
||||
#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();
|
||||
|
||||
#ifdef CONFIG_VFS_SUPPORT_IO
|
||||
|
@ -292,6 +292,16 @@ void start_cpu0_default(void)
|
||||
#if CONFIG_ESP32S2_BROWNOUT_DET
|
||||
esp_brownout_init();
|
||||
#endif
|
||||
|
||||
#if CONFIG_SECURE_DISABLE_ROM_DL_MODE
|
||||
err = esp_efuse_disable_rom_download_mode();
|
||||
assert(err == ESP_OK && "Failed to disable ROM download mode");
|
||||
#endif
|
||||
#if CONFIG_SECURE_ENABLE_SECURE_ROM_DL_MODE
|
||||
err = esp_efuse_enable_rom_secure_download_mode();
|
||||
assert(err == ESP_OK && "Failed to enable Secure Download mode");
|
||||
#endif
|
||||
|
||||
rtc_gpio_force_hold_dis_all();
|
||||
|
||||
#ifdef CONFIG_VFS_SUPPORT_IO
|
||||
|
@ -27,7 +27,11 @@ if(NOT BOOTLOADER_BUILD)
|
||||
set(ESPTOOLPY_BEFORE "${CONFIG_ESPTOOLPY_BEFORE}")
|
||||
set(ESPTOOLPY_AFTER "${CONFIG_ESPTOOLPY_AFTER}")
|
||||
set(ESPTOOLPY_CHIP "${target}")
|
||||
set(ESPTOOLPY_WITH_STUB TRUE)
|
||||
if(CONFIG_ESPTOOLPY_WITH_STUB)
|
||||
set(ESPTOOLPY_WITH_STUB true)
|
||||
else()
|
||||
set(ESPTOOLPY_WITH_STUB false)
|
||||
endif()
|
||||
|
||||
if(CONFIG_SECURE_BOOT OR CONFIG_SECURE_FLASH_ENC_ENABLED)
|
||||
# If security enabled then override post flash option
|
||||
|
@ -54,6 +54,12 @@ menu "Serial flasher config"
|
||||
decompress it on the fly before flashing it. For most payloads, this should result in a
|
||||
speed increase.
|
||||
|
||||
config ESPTOOLPY_WITH_STUB
|
||||
# Only real reason to disable this is when ESP32-S2 Secure Download Mode is set
|
||||
bool
|
||||
default "y"
|
||||
depends on !SECURE_ENABLE_SECURE_ROM_DL_MODE
|
||||
|
||||
choice ESPTOOLPY_FLASHMODE
|
||||
prompt "Flash SPI mode"
|
||||
default ESPTOOLPY_FLASHMODE_DIO
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 988b9a24414bba694ae9994728865148ee95848a
|
||||
Subproject commit 5eada56341f3a74c3e09eef3b1266f1072145059
|
@ -16,7 +16,7 @@
|
||||
"extra_esptool_args" : {
|
||||
"after" : "${ESPTOOLPY_AFTER}",
|
||||
"before" : "${ESPTOOLPY_BEFORE}",
|
||||
"stub" : "${ESPTOOLPY_WITH_STUB}",
|
||||
"stub" : ${ESPTOOLPY_WITH_STUB},
|
||||
"chip" : "${ESPTOOLPY_CHIP}"
|
||||
}
|
||||
}
|
||||
|
@ -153,6 +153,9 @@ else()
|
||||
list(APPEND esptool_flash_main_args "--after=${CONFIG_ESPTOOLPY_AFTER}")
|
||||
endif()
|
||||
|
||||
if(NOT CONFIG_ESPTOOLPY_WITH_STUB)
|
||||
list(APPEND esptool_flash_main_args "--no-stub")
|
||||
endif()
|
||||
|
||||
idf_component_set_property(esptool_py FLASH_ARGS "${esptool_flash_main_args}")
|
||||
idf_component_set_property(esptool_py FLASH_SUB_ARGS "${ESPTOOLPY_FLASH_OPTIONS}")
|
||||
|
@ -5,4 +5,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#define SOC_CPU_CORES_NUM 1
|
||||
#define SOC_CPU_CORES_NUM 1
|
||||
|
||||
#define SOC_SUPPORTS_SECURE_DL_MODE 1
|
||||
|
@ -484,6 +484,21 @@ Once the flash encryption is enabled in Release mode, the bootloader will write-
|
||||
For subsequent plaintext field updates, use :ref:`OTA scheme <updating-encrypted-flash-ota>`.
|
||||
|
||||
|
||||
. _flash-encrypt-best-practices:
|
||||
|
||||
Best Practices
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
When using Flash Encryption in production:
|
||||
|
||||
.. list::
|
||||
|
||||
- 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.
|
||||
:esp32: - 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.
|
||||
:esp32s2: - The UART ROM Download Mode should be disabled entirely if it is not needed, or permanently set to "Secure Download Mode" otherwise. Secure Download Mode permanently limits the available commands to basic flash read and write only. The default behaviour is to set Secure Download Mode on first boot in Release mode. To disable Download Mode entirely, enable configuration option :ref:`CONFIG_SECURE_DISABLE_ROM_DL_MODE` or call :cpp:func:`esp_efuse_disable_rom_download_mode` at runtime.
|
||||
:esp32: - Enable :doc:`Secure Boot <secure-boot-v2>` as an extra layer of protection, and to prevent an attacker from selectively corrupting any part of the flash before boot.
|
||||
:esp32s2: - Enable 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
|
||||
-----------------
|
||||
|
||||
@ -733,18 +748,12 @@ 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:
|
||||
|
||||
.. list::
|
||||
|
||||
- **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 in flash memory, make sure that the method you are using (library, API, etc.) supports flash encryption.
|
||||
|
||||
: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.
|
||||
|
||||
: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.
|
||||
|
||||
: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 <nvs_encryption>` deals with this and is suitable for many uses.
|
||||
|
||||
: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 <secure-boot-v2>`.
|
||||
- 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).
|
||||
:esp32: - 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.
|
||||
: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 <secure-boot-v2>`.
|
||||
:esp32s2: - 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 Secure Boot.
|
||||
|
||||
.. _flash-encryption-and-secure-boot:
|
||||
|
||||
@ -911,4 +920,4 @@ The following sections provide some reference information about the operation of
|
||||
|
||||
- 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.
|
||||
- To see the full flash encryption algorithm implemented in Python, refer to the `_flash_encryption_operation()` function in the ``espsecure.py`` source code.
|
||||
|
Loading…
Reference in New Issue
Block a user