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"
choice SECURE_BOOTLOADER
bool "Secure bootloader"
default SECURE_BOOTLOADER_DISABLED
config SECURE_BOOT_ENABLED
bool "Enable secure boot in bootloader"
default N
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
boot that particular bootloader), or a digest key can be used
to allow the secure bootloader to be re-flashed with
modifications. Secure boot also permanently disables JTAG.
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.
When enabling secure boot, JTAG and ROM BASIC Interpreter are permanently disabled by default.
See docs/security/secure-boot.rst for details.
config SECURE_BOOTLOADER_DISABLED
bool "Disabled"
choice SECURE_BOOTLOADER_MODE
bool "Secure bootloader mode"
depends on SECURE_BOOT_ENABLED
default SECURE_BOOTLOADER_ONE_TIME_FLASH
config SECURE_BOOTLOADER_ONE_TIME_FLASH
bool "One-time flash"
@ -70,10 +71,10 @@ endchoice
config 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
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.
@ -84,44 +85,106 @@ config SECURE_BOOT_SIGNING_KEY
See docs/security/secure-boot.rst for details.
config SECURE_BOOT_DISABLE_JTAG
bool "First boot: Permanently disable JTAG"
depends on SECURE_BOOTLOADER_ENABLED
default Y
config SECURE_BOOT_INSECURE
bool "Allow potentially insecure options"
depends on SECURE_BOOT_ENABLED
default N
help
You can disable some of the default protections offered by secure boot, 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.
config FLASH_ENCRYPTION_ENABLED
bool "Enable flash encryption on boot"
default N
help
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.
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
Bootloader permanently disable JTAG (across entire chip) when enabling secure boot. This happens on first boot of the bootloader.
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.
It is recommended this option remains set for production environments.
Only set this option in testing environments.
config SECURE_BOOT_DISABLE_ROM_BASIC
bool "First boot: Permanently disable ROM BASIC fallback"
depends on SECURE_BOOTLOADER_ENABLED
default Y
config SECURE_BOOT_ALLOW_JTAG
bool "Allow JTAG Debugging"
depends on SECURE_BOOT_INSECURE || FLASH_ENCRYPTION_INSECURE
default N
help
Bootloader permanently disables ROM BASIC (on UART console) as a fallback if the bootloader image becomes invalid. This happens on first boot.
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.
It is recommended this option remains set in production environments.
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 "Test mode: don't actually enable secure boot"
depends on SECURE_BOOTLOADER_ENABLED
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.
This option is for testing purposes only - it effectively completely disables secure boot protection.
Log output will state changes which would be applied, but they will not be.
config SECURE_BOOTLOADER_ENABLED
bool
default SECURE_BOOTLOADER_ONE_TIME_FLASH || SECURE_BOOTLOADER_REFLASHABLE
This option is for testing purposes only - it completely disables secure boot protection.
config FLASH_ENCRYPTION_ENABLED
bool "Enable flash encryption on boot"
help
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.
See docs/securityflash-encryption.rst for details.
endmenu # potentially insecure
endmenu

View file

@ -32,7 +32,7 @@ $(BOOTLOADER_BIN): $(SDKCONFIG_MAKEFILE)
clean: bootloader-clean
ifdef CONFIG_SECURE_BOOTLOADER_DISABLED
ifndef CONFIG_SECURE_BOOT_ENABLED
# If secure boot disabled, bootloader flashing is integrated
# with 'make flash' and no warnings are printed.
@ -90,7 +90,10 @@ bootloader:
@exit 1
endif
ifndef CONFIG_SECURE_BOOT_ENABLED
# don't build bootloader by default is secure boot is enabled
all_binaries: $(BOOTLOADER_BIN)
endif
bootloader-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, "## Label Usage Type ST Offset Length");
#ifdef CONFIG_SECURE_BOOTLOADER_ENABLED
#ifdef CONFIG_SECURE_BOOT_ENABLED
if(esp_secure_boot_enabled()) {
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);
@ -226,7 +226,7 @@ static bool ota_select_valid(const esp_ota_select_entry_t *s)
void bootloader_main()
{
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;
#endif
esp_image_header_t fhdr;
@ -322,7 +322,7 @@ void bootloader_main()
return;
}
#ifdef CONFIG_SECURE_BOOTLOADER_ENABLED
#ifdef CONFIG_SECURE_BOOT_ENABLED
/* Generate secure digest from this bootloader to protect future
modifications */
ESP_LOGI(TAG, "Checking secure boot...");
@ -374,7 +374,7 @@ static void unpack_load_app(const esp_partition_pos_t* partition)
return;
}
#ifdef CONFIG_SECURE_BOOTLOADER_ENABLED
#ifdef CONFIG_SECURE_BOOT_ENABLED
if (esp_secure_boot_enabled()) {
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);

View file

@ -12,7 +12,7 @@ COMPONENT_SRCDIRS := src
#
# 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
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);
esp_efuse_burn_new_values();
#ifndef CONFIG_FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_WRITE
ESP_LOGI(TAG, "Disable UART bootloader write...");
//REG_WRITE(EFUSE_BLK0_
uint32_t new_wdata6 = 0;
#ifndef CONFIG_FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_ENCRYPT
ESP_LOGI(TAG, "Disable UART bootloader encryption...");
new_wdata6 |= EFUSE_DISABLE_DL_ENCRYPT;
#else
ESP_LOGW(TAG, "Not disabling UART bootloader encryption");
#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;
}

View file

@ -96,7 +96,7 @@ static bool secure_boot_generate(uint32_t image_len){
static inline void burn_efuses()
{
#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
esp_efuse_burn_new_values();
#endif
@ -156,6 +156,7 @@ esp_err_t esp_secure_boot_permanently_enable(void) {
}
ESP_LOGI(TAG, "Digest generation complete.");
#ifndef CONFIG_SECURE_BOOT_TEST_MODE
if (!efuse_key_read_protected) {
ESP_LOGE(TAG, "Pre-loaded key is not read protected. Refusing to blow secure boot efuse.");
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.");
return ESP_ERR_INVALID_STATE;
}
#endif
ESP_LOGI(TAG, "blowing secure boot efuse...");
ESP_LOGD(TAG, "before updating, EFUSE_BLK0_RDATA6 %x", REG_READ(EFUSE_BLK0_RDATA6_REG));
uint32_t new_wdata6 = EFUSE_RD_ABS_DONE_0;
#ifdef CONFIG_SECURE_BOOT_DISABLE_JTAG
ESP_LOGI(TAG, "disabling JTAG...");
#ifndef CONFIG_SECURE_BOOT_ALLOW_JTAG
ESP_LOGI(TAG, "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
ESP_LOGI(TAG, "disabling UART bootloader...");
new_wdata6 |= EFUSE_RD_CONSOLE_DEBUG_DISABLE_S;
#endif
#ifndef CONFIG_SECURE_BOOT_ALLOW_ROM_BASIC
ESP_LOGI(TAG, "Disable ROM BASIC interpreter fallback...");
new_wdata6 |= EFUSE_RD_CONSOLE_DEBUG_DISABLE;
#else
ESP_LOGW(TAG, "Not disabling ROM BASIC fallback - SECURITY COMPROMISED");
#endif
REG_WRITE(EFUSE_BLK0_WDATA6_REG, new_wdata6);
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)
ifdef CONFIG_SECURE_BOOTLOADER_ENABLED
ifdef CONFIG_SECURE_BOOT_ENABLED
ifndef IS_BOOTLOADER_BUILD
# for secure boot, add a signing step to get from unsiged app to signed app
APP_BIN_UNSIGNED := $(APP_BIN:.bin=-unsigned.bin)
@ -45,7 +45,7 @@ $(APP_BIN_UNSIGNED): $(APP_ELF) $(ESPTOOLPY_SRC)
flash: all_binaries $(ESPTOOLPY_SRC)
@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)"
endif
$(ESPTOOLPY_WRITE_FLASH) $(ESPTOOL_ALL_FLASH_ARGS)

View file

@ -139,7 +139,7 @@ export COMPONENT_INCLUDES
include $(IDF_PATH)/make/common.mk
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 "To flash app & partition table, run 'make flash' or:"
else