secure boot & flash encryption: Rework configuration options

Add UART bootloader disable options for flash encryption
This commit is contained in:
Angus Gratton 2016-11-25 14:09:26 +11:00
parent 9eb135fd73
commit 506c8cd964
8 changed files with 156 additions and 58 deletions

View File

@ -34,21 +34,22 @@ endmenu
menu "Security features" menu "Security features"
choice SECURE_BOOTLOADER config SECURE_BOOT_ENABLED
bool "Secure bootloader" bool "Enable secure boot in bootloader"
default SECURE_BOOTLOADER_DISABLED default N
help help
Build a bootloader with the secure boot flag enabled. Build a bootloader which enables secure boot on first boot.
Secure bootloader can be one-time-flash (chip will only ever Once enabled, secure boot will not boot a modified bootloader. The bootloader will only load a partition table or boot an app if the data has a verified digital signature.
boot that particular bootloader), or a digest key can be used
to allow the secure bootloader to be re-flashed with When enabling secure boot, JTAG and ROM BASIC Interpreter are permanently disabled by default.
modifications. Secure boot also permanently disables JTAG.
See docs/security/secure-boot.rst for details. See docs/security/secure-boot.rst for details.
config SECURE_BOOTLOADER_DISABLED choice SECURE_BOOTLOADER_MODE
bool "Disabled" bool "Secure bootloader mode"
depends on SECURE_BOOT_ENABLED
default SECURE_BOOTLOADER_ONE_TIME_FLASH
config SECURE_BOOTLOADER_ONE_TIME_FLASH config SECURE_BOOTLOADER_ONE_TIME_FLASH
bool "One-time flash" bool "One-time flash"
@ -70,10 +71,10 @@ endchoice
config SECURE_BOOT_SIGNING_KEY config SECURE_BOOT_SIGNING_KEY
string "Secure boot signing key" string "Secure boot signing key"
depends on SECURE_BOOTLOADER_ENABLED depends on SECURE_BOOT_ENABLED
default secure_boot_signing_key.pem default secure_boot_signing_key.pem
help help
Path to the key file used to sign partition tables and app images for secure boot. Path to the key file used to sign partition tables and app images for secure boot. Once secure boot is enabled, bootloader will only boot if partition table and app image are signed.
Key file is an ECDSA private key (NIST256p curve) in PEM format. Key file is an ECDSA private key (NIST256p curve) in PEM format.
@ -84,44 +85,106 @@ config SECURE_BOOT_SIGNING_KEY
See docs/security/secure-boot.rst for details. See docs/security/secure-boot.rst for details.
config SECURE_BOOT_DISABLE_JTAG config SECURE_BOOT_INSECURE
bool "First boot: Permanently disable JTAG" bool "Allow potentially insecure options"
depends on SECURE_BOOTLOADER_ENABLED depends on SECURE_BOOT_ENABLED
default Y
help
Bootloader permanently disable JTAG (across entire chip) when enabling secure boot. This happens on first boot of the bootloader.
It is recommended this option remains set for production environments.
config SECURE_BOOT_DISABLE_ROM_BASIC
bool "First boot: Permanently disable ROM BASIC fallback"
depends on SECURE_BOOTLOADER_ENABLED
default Y
help
Bootloader permanently disables ROM BASIC (on UART console) as a fallback if the bootloader image becomes invalid. This happens on first boot.
It is recommended this option remains set in production environments.
config SECURE_BOOT_TEST_MODE
bool "Test mode: don't actually enable secure boot"
depends on SECURE_BOOTLOADER_ENABLED
default N default N
help help
If this option is set, all permanent secure boot changes (via Efuse) are disabled. You can disable some of the default protections offered by secure boot, in order to enable testing or a custom combination of security features.
This option is for testing purposes only - it effectively completely disables secure boot protection. Only enable these options if you are very sure.
config SECURE_BOOTLOADER_ENABLED Refer to docs/security/secure-boot.rst and docs/security/flash-encryption.rst for details.
bool
default SECURE_BOOTLOADER_ONE_TIME_FLASH || SECURE_BOOTLOADER_REFLASHABLE
config FLASH_ENCRYPTION_ENABLED config FLASH_ENCRYPTION_ENABLED
bool "Enable flash encryption on boot" bool "Enable flash encryption on boot"
default N
help help
If this option is set, flash contents will be encrypted by the bootloader on first boot. If this option is set, flash contents will be encrypted by the bootloader on first boot.
Note: After first boot, the system will be permanently encrypted. Note: After first boot, the system will be permanently encrypted.
See docs/securityflash-encryption.rst for details. See docs/securityflash-encryption.rst for details.
config FLASH_ENCRYPTION_INSECURE
bool "Allow potentially insecure options"
depends on FLASH_ENCRYPTION_ENABLED
default N
help
You can disable some of the default protections offered by flash encryption, in order to enable testing or a custom combination of security features.
Only enable these options if you are very sure.
Refer to docs/security/secure-boot.rst and docs/security/flash-encryption.rst for details.
menu "Potentially insecure options"
visible if FLASH_ENCRYPTION_INSECURE || SECURE_BOOT_INSECURE
# NOTE: Options in this menu NEED to have SECURE_BOOT_INSECURE
# and/or FLASH_ENCRYPTION_INSECURE in "depends on", as the menu
# itself doesn't enable/disable its children (if it's not set,
# it's possible for the insecure menu to be disabled but the insecure option
# to remain on which is very bad.)
config SECURE_BOOT_ALLOW_ROM_BASIC
bool "Leave ROM BASIC Interpreter available on reset"
depends on SECURE_BOOT_INSECURE
default N
help
If not set (default), bootloader permanently disables ROM BASIC (on UART console) as a fallback if the bootloader image becomes invalid. This happens on first boot.
Only set this option in testing environments.
config SECURE_BOOT_ALLOW_JTAG
bool "Allow JTAG Debugging"
depends on SECURE_BOOT_INSECURE || FLASH_ENCRYPTION_INSECURE
default N
help
If not set (default), the bootloader will permanently disable JTAG (across entire chip) on first boot when either secure boot or flash encryption is enabled.
Setting this option leaves JTAG on for debugging, which negates all protections of flash encryption and some of the protections of secure boot.
Only set this option in testing environments.
config FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_ENCRYPT
bool "Leave UART bootloader encryption enabled"
depends on FLASH_ENCRYPTION_INSECURE
default N
help
If not set (default), the bootloader will permanently disable UART bootloader encryption access on first boot. If set, the UART bootloader will still be able to access hardware encryption.
It is recommended to only set this option in testing environments.
config FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_DECRYPT
bool "Leave UART bootloader decryption enabled"
depends on FLASH_ENCRYPTION_INSECURE
default N
help
If not set (default), the bootloader will permanently disable UART bootloader decryption access on first boot. If set, the UART bootloader will still be able to access hardware decryption.
Only set this option in testing environments. Setting this option allows complete bypass of flash encryption.
config FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_CACHE
bool "Leave UART bootloader flash cache enabled"
depends on FLASH_ENCRYPTION_INSECURE
default N
help
If not set (default), the bootloader will permanently disable UART bootloader flash cache access on first boot. If set, the UART bootloader will still be able to access the flash cache.
Only set this option in testing environments.
config SECURE_BOOT_TEST_MODE
bool "Secure boot test mode: don't permanently set any efuses"
depends on SECURE_BOOT_INSECURE
default N
help
If this option is set, all permanent secure boot changes (via Efuse) are disabled.
Log output will state changes which would be applied, but they will not be.
This option is for testing purposes only - it completely disables secure boot protection.
endmenu # potentially insecure
endmenu endmenu

View File

@ -32,7 +32,7 @@ $(BOOTLOADER_BIN): $(SDKCONFIG_MAKEFILE)
clean: bootloader-clean clean: bootloader-clean
ifdef CONFIG_SECURE_BOOTLOADER_DISABLED ifndef CONFIG_SECURE_BOOT_ENABLED
# If secure boot disabled, bootloader flashing is integrated # If secure boot disabled, bootloader flashing is integrated
# with 'make flash' and no warnings are printed. # with 'make flash' and no warnings are printed.
@ -90,7 +90,10 @@ bootloader:
@exit 1 @exit 1
endif endif
ifndef CONFIG_SECURE_BOOT_ENABLED
# don't build bootloader by default is secure boot is enabled
all_binaries: $(BOOTLOADER_BIN) all_binaries: $(BOOTLOADER_BIN)
endif
bootloader-clean: bootloader-clean:
$(BOOTLOADER_MAKE) app-clean $(BOOTLOADER_MAKE) app-clean

View File

@ -118,7 +118,7 @@ bool load_partition_table(bootloader_state_t* bs)
ESP_LOGI(TAG, "Partition Table:"); ESP_LOGI(TAG, "Partition Table:");
ESP_LOGI(TAG, "## Label Usage Type ST Offset Length"); ESP_LOGI(TAG, "## Label Usage Type ST Offset Length");
#ifdef CONFIG_SECURE_BOOTLOADER_ENABLED #ifdef CONFIG_SECURE_BOOT_ENABLED
if(esp_secure_boot_enabled()) { if(esp_secure_boot_enabled()) {
ESP_LOGI(TAG, "Verifying partition table signature..."); ESP_LOGI(TAG, "Verifying partition table signature...");
esp_err_t err = esp_secure_boot_verify_signature(ESP_PARTITION_TABLE_ADDR, ESP_PARTITION_TABLE_DATA_LEN); esp_err_t err = esp_secure_boot_verify_signature(ESP_PARTITION_TABLE_ADDR, ESP_PARTITION_TABLE_DATA_LEN);
@ -226,7 +226,7 @@ static bool ota_select_valid(const esp_ota_select_entry_t *s)
void bootloader_main() void bootloader_main()
{ {
ESP_LOGI(TAG, "Espressif ESP32 2nd stage bootloader v. %s", BOOT_VERSION); ESP_LOGI(TAG, "Espressif ESP32 2nd stage bootloader v. %s", BOOT_VERSION);
#if defined(CONFIG_SECURE_BOOTLOADER_ENABLED) || defined(CONFIG_FLASH_ENCRYPTION_ENABLED) #if defined(CONFIG_SECURE_BOOT_ENABLED) || defined(CONFIG_FLASH_ENCRYPTION_ENABLED)
esp_err_t err; esp_err_t err;
#endif #endif
esp_image_header_t fhdr; esp_image_header_t fhdr;
@ -322,7 +322,7 @@ void bootloader_main()
return; return;
} }
#ifdef CONFIG_SECURE_BOOTLOADER_ENABLED #ifdef CONFIG_SECURE_BOOT_ENABLED
/* Generate secure digest from this bootloader to protect future /* Generate secure digest from this bootloader to protect future
modifications */ modifications */
ESP_LOGI(TAG, "Checking secure boot..."); ESP_LOGI(TAG, "Checking secure boot...");
@ -374,7 +374,7 @@ static void unpack_load_app(const esp_partition_pos_t* partition)
return; return;
} }
#ifdef CONFIG_SECURE_BOOTLOADER_ENABLED #ifdef CONFIG_SECURE_BOOT_ENABLED
if (esp_secure_boot_enabled()) { if (esp_secure_boot_enabled()) {
ESP_LOGI(TAG, "Verifying app signature @ 0x%x (length 0x%x)", partition->offset, image_length); ESP_LOGI(TAG, "Verifying app signature @ 0x%x (length 0x%x)", partition->offset, image_length);
err = esp_secure_boot_verify_signature(partition->offset, image_length); err = esp_secure_boot_verify_signature(partition->offset, image_length);

View File

@ -12,7 +12,7 @@ COMPONENT_SRCDIRS := src
# #
# Secure boot signing key support # Secure boot signing key support
# #
ifdef CONFIG_SECURE_BOOTLOADER_ENABLED ifdef CONFIG_SECURE_BOOT_ENABLED
# this path is created relative to the component build directory # this path is created relative to the component build directory
SECURE_BOOT_VERIFICATION_KEY := $(abspath signature_verification_key.bin) SECURE_BOOT_VERIFICATION_KEY := $(abspath signature_verification_key.bin)

View File

@ -114,11 +114,37 @@ static esp_err_t initialise_flash_encryption(void)
REG_WRITE(EFUSE_BLK0_WDATA5_REG, EFUSE_FLASH_CRYPT_CONFIG_M); REG_WRITE(EFUSE_BLK0_WDATA5_REG, EFUSE_FLASH_CRYPT_CONFIG_M);
esp_efuse_burn_new_values(); esp_efuse_burn_new_values();
#ifndef CONFIG_FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_WRITE uint32_t new_wdata6 = 0;
ESP_LOGI(TAG, "Disable UART bootloader write..."); #ifndef CONFIG_FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_ENCRYPT
//REG_WRITE(EFUSE_BLK0_ ESP_LOGI(TAG, "Disable UART bootloader encryption...");
new_wdata6 |= EFUSE_DISABLE_DL_ENCRYPT;
#else
ESP_LOGW(TAG, "Not disabling UART bootloader encryption");
#endif #endif
#ifndef CONFIG_FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_DECRYPT
ESP_LOGI(TAG, "Disable UART bootloader decryption...");
new_wdata6 |= EFUSE_DISABLE_DL_DECRYPT;
#else
ESP_LOGW(TAG, "Not disabling UART bootloader decryption - SECURITY COMPROMISED");
#endif
#ifndef CONFIG_FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_CACHE
ESP_LOGI(TAG, "Disable UART bootloader MMU cache...");
new_wdata6 |= EFUSE_DISABLE_DL_CACHE;
#else
ESP_LOGW(TAG, "Not disabling UART bootloader MMU cache - SECURITY COMPROMISED");
#endif
#ifndef CONFIG_SECURE_BOOT_ALLOW_JTAG
ESP_LOGI(TAG, "Disable JTAG...");
new_wdata6 |= EFUSE_RD_DISABLE_JTAG;
#else
ESP_LOGW(TAG, "Not disabling JTAG - SECURITY COMPROMISED");
#endif
if (new_wdata6 != 0) {
REG_WRITE(EFUSE_BLK0_WDATA6_REG, new_wdata6);
esp_efuse_burn_new_values();
}
return ESP_OK; return ESP_OK;
} }

View File

@ -96,7 +96,7 @@ static bool secure_boot_generate(uint32_t image_len){
static inline void burn_efuses() static inline void burn_efuses()
{ {
#ifdef CONFIG_SECURE_BOOT_TEST_MODE #ifdef CONFIG_SECURE_BOOT_TEST_MODE
ESP_LOGE(TAG, "SECURE BOOT TEST MODE. Not really burning any efuses!"); ESP_LOGE(TAG, "SECURE BOOT TEST MODE. Not really burning any efuses! NOT SECURE");
#else #else
esp_efuse_burn_new_values(); esp_efuse_burn_new_values();
#endif #endif
@ -156,6 +156,7 @@ esp_err_t esp_secure_boot_permanently_enable(void) {
} }
ESP_LOGI(TAG, "Digest generation complete."); ESP_LOGI(TAG, "Digest generation complete.");
#ifndef CONFIG_SECURE_BOOT_TEST_MODE
if (!efuse_key_read_protected) { if (!efuse_key_read_protected) {
ESP_LOGE(TAG, "Pre-loaded key is not read protected. Refusing to blow secure boot efuse."); ESP_LOGE(TAG, "Pre-loaded key is not read protected. Refusing to blow secure boot efuse.");
return ESP_ERR_INVALID_STATE; return ESP_ERR_INVALID_STATE;
@ -164,21 +165,26 @@ esp_err_t esp_secure_boot_permanently_enable(void) {
ESP_LOGE(TAG, "Pre-loaded key is not write protected. Refusing to blow secure boot efuse."); ESP_LOGE(TAG, "Pre-loaded key is not write protected. Refusing to blow secure boot efuse.");
return ESP_ERR_INVALID_STATE; return ESP_ERR_INVALID_STATE;
} }
#endif
ESP_LOGI(TAG, "blowing secure boot efuse..."); ESP_LOGI(TAG, "blowing secure boot efuse...");
ESP_LOGD(TAG, "before updating, EFUSE_BLK0_RDATA6 %x", REG_READ(EFUSE_BLK0_RDATA6_REG)); ESP_LOGD(TAG, "before updating, EFUSE_BLK0_RDATA6 %x", REG_READ(EFUSE_BLK0_RDATA6_REG));
uint32_t new_wdata6 = EFUSE_RD_ABS_DONE_0; uint32_t new_wdata6 = EFUSE_RD_ABS_DONE_0;
#ifdef CONFIG_SECURE_BOOT_DISABLE_JTAG #ifndef CONFIG_SECURE_BOOT_ALLOW_JTAG
ESP_LOGI(TAG, "disabling JTAG..."); ESP_LOGI(TAG, "Disable JTAG...");
new_wdata6 |= EFUSE_RD_DISABLE_JTAG; new_wdata6 |= EFUSE_RD_DISABLE_JTAG;
#endif #else
ESP_LOGW(TAG, "Not disabling JTAG - SECURITY COMPROMISED");
#endif
#ifdef CONFIG_SECURE_BOOT_DISABLE_ROM_BASIC #ifndef CONFIG_SECURE_BOOT_ALLOW_ROM_BASIC
ESP_LOGI(TAG, "disabling UART bootloader..."); ESP_LOGI(TAG, "Disable ROM BASIC interpreter fallback...");
new_wdata6 |= EFUSE_RD_CONSOLE_DEBUG_DISABLE_S; new_wdata6 |= EFUSE_RD_CONSOLE_DEBUG_DISABLE;
#endif #else
ESP_LOGW(TAG, "Not disabling ROM BASIC fallback - SECURITY COMPROMISED");
#endif
REG_WRITE(EFUSE_BLK0_WDATA6_REG, new_wdata6); REG_WRITE(EFUSE_BLK0_WDATA6_REG, new_wdata6);
burn_efuses(); burn_efuses();

View File

@ -28,7 +28,7 @@ ESPTOOLPY_WRITE_FLASH=$(ESPTOOLPY_SERIAL) write_flash $(if $(CONFIG_ESPTOOLPY_CO
ESPTOOL_ALL_FLASH_ARGS += $(CONFIG_APP_OFFSET) $(APP_BIN) ESPTOOL_ALL_FLASH_ARGS += $(CONFIG_APP_OFFSET) $(APP_BIN)
ifdef CONFIG_SECURE_BOOTLOADER_ENABLED ifdef CONFIG_SECURE_BOOT_ENABLED
ifndef IS_BOOTLOADER_BUILD ifndef IS_BOOTLOADER_BUILD
# for secure boot, add a signing step to get from unsiged app to signed app # for secure boot, add a signing step to get from unsiged app to signed app
APP_BIN_UNSIGNED := $(APP_BIN:.bin=-unsigned.bin) APP_BIN_UNSIGNED := $(APP_BIN:.bin=-unsigned.bin)
@ -45,7 +45,7 @@ $(APP_BIN_UNSIGNED): $(APP_ELF) $(ESPTOOLPY_SRC)
flash: all_binaries $(ESPTOOLPY_SRC) flash: all_binaries $(ESPTOOLPY_SRC)
@echo "Flashing binaries to serial port $(ESPPORT) (app at offset $(CONFIG_APP_OFFSET))..." @echo "Flashing binaries to serial port $(ESPPORT) (app at offset $(CONFIG_APP_OFFSET))..."
ifdef CONFIG_SECURE_BOOTLOADER_ENABLED ifdef CONFIG_SECURE_BOOT_ENABLED
@echo "(Secure boot enabled, so bootloader not flashed automatically. See 'make bootloader' output)" @echo "(Secure boot enabled, so bootloader not flashed automatically. See 'make bootloader' output)"
endif endif
$(ESPTOOLPY_WRITE_FLASH) $(ESPTOOL_ALL_FLASH_ARGS) $(ESPTOOLPY_WRITE_FLASH) $(ESPTOOL_ALL_FLASH_ARGS)

View File

@ -139,7 +139,7 @@ export COMPONENT_INCLUDES
include $(IDF_PATH)/make/common.mk include $(IDF_PATH)/make/common.mk
all: all:
ifdef CONFIG_SECURE_BOOTLOADER_ENABLED ifdef CONFIG_SECURE_BOOT_ENABLED
@echo "(Secure boot enabled, so bootloader not flashed automatically. See 'make bootloader' output)" @echo "(Secure boot enabled, so bootloader not flashed automatically. See 'make bootloader' output)"
@echo "To flash app & partition table, run 'make flash' or:" @echo "To flash app & partition table, run 'make flash' or:"
else else