risc-v/esp32c3: Add Secure Boot support on top of MCUboot

Signed-off-by: Gustavo Henrique Nihei <gustavo.nihei@espressif.com>
This commit is contained in:
Gustavo Henrique Nihei 2021-11-19 18:02:22 -03:00 committed by Xiang Xiao
parent f542ab4564
commit 1c8e84b341
4 changed files with 416 additions and 68 deletions

View File

@ -31,66 +31,124 @@ BOOTLOADER_CONFIG = $(CHIPDIR)/bootloader.conf
$(BOOTLOADER_SRCDIR):
$(Q) git clone $(BOOTLOADER_URL) $(BOOTLOADER_SRCDIR) -b $(BOOTLOADER_VERSION)
# Helpers for creating the configuration file
cfg_en = echo "$(1)=$(if $(CONFIG_ESP32C3_APP_FORMAT_MCUBOOT),1,y)";
cfg_val = echo "$(1)=$(2)";
# Commands for colored and formatted output
RED = \033[1;31m
YELLOW = \033[1;33m
BOLD = \033[1m
RST = \033[0m
$(BOOTLOADER_CONFIG): $(TOPDIR)/.config
ifeq ($(CONFIG_ESP32C3_SECURE_BOOT),y)
$(Q) if [ -z "$(ESPSEC_KEYDIR)" ]; then \
echo ""; \
echo "$(RED)bootloader error:$(RST) Missing argument for secure boot keys directory."; \
echo "USAGE: make bootloader ESPSEC_KEYDIR=<dir>"; \
echo ""; \
exit 1; \
fi
endif
$(Q) echo "Creating Bootloader configuration"
$(Q) { \
[ "$(CONFIG_ESP32C3_FLASH_2M)" = "y" ] && echo "CONFIG_ESPTOOLPY_FLASHSIZE_2MB=y"; \
[ "$(CONFIG_ESP32C3_FLASH_4M)" = "y" ] && echo "CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y"; \
[ "$(CONFIG_ESP32C3_FLASH_8M)" = "y" ] && echo "CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y"; \
[ "$(CONFIG_ESP32C3_FLASH_16M)" = "y" ] && echo "CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y"; \
[ "$(CONFIG_ESP32C3_FLASH_MODE_DIO)" = "y" ] && echo "CONFIG_ESPTOOLPY_FLASHMODE_DIO=y"; \
[ "$(CONFIG_ESP32C3_FLASH_MODE_DOUT)" = "y" ] && echo "CONFIG_ESPTOOLPY_FLASHMODE_DOUT=y"; \
[ "$(CONFIG_ESP32C3_FLASH_MODE_QIO)" = "y" ] && echo "CONFIG_ESPTOOLPY_FLASHMODE_QIO=y"; \
[ "$(CONFIG_ESP32C3_FLASH_MODE_QOUT)" = "y" ] && echo "CONFIG_ESPTOOLPY_FLASHMODE_QOUT=y"; \
[ "$(CONFIG_ESP32C3_FLASH_FREQ_80M)" = "y" ] && echo "CONFIG_ESPTOOLPY_FLASHFREQ_80M=y"; \
[ "$(CONFIG_ESP32C3_FLASH_FREQ_40M)" = "y" ] && echo "CONFIG_ESPTOOLPY_FLASHFREQ_40M=y"; \
[ "$(CONFIG_ESP32C3_FLASH_FREQ_26M)" = "y" ] && echo "CONFIG_ESPTOOLPY_FLASHFREQ_26M=y"; \
[ "$(CONFIG_ESP32C3_FLASH_FREQ_20M)" = "y" ] && echo "CONFIG_ESPTOOLPY_FLASHFREQ_20M=y"; \
true; \
$(Q) { \
$(if $(CONFIG_ESP32C3_FLASH_2M),$(call cfg_en,CONFIG_ESPTOOLPY_FLASHSIZE_2MB)) \
$(if $(CONFIG_ESP32C3_FLASH_4M),$(call cfg_en,CONFIG_ESPTOOLPY_FLASHSIZE_4MB)) \
$(if $(CONFIG_ESP32C3_FLASH_8M),$(call cfg_en,CONFIG_ESPTOOLPY_FLASHSIZE_8MB)) \
$(if $(CONFIG_ESP32C3_FLASH_16M),$(call cfg_en,CONFIG_ESPTOOLPY_FLASHSIZE_16MB)) \
$(if $(CONFIG_ESP32C3_FLASH_MODE_DIO),$(call cfg_en,CONFIG_ESPTOOLPY_FLASHMODE_DIO)) \
$(if $(CONFIG_ESP32C3_FLASH_MODE_DOUT),$(call cfg_en,CONFIG_ESPTOOLPY_FLASHMODE_DOUT)) \
$(if $(CONFIG_ESP32C3_FLASH_MODE_QIO),$(call cfg_en,CONFIG_ESPTOOLPY_FLASHMODE_QIO)) \
$(if $(CONFIG_ESP32C3_FLASH_MODE_QOUT),$(call cfg_en,CONFIG_ESPTOOLPY_FLASHMODE_QOUT)) \
$(if $(CONFIG_ESP32C3_FLASH_FREQ_80M),$(call cfg_en,CONFIG_ESPTOOLPY_FLASHFREQ_80M)) \
$(if $(CONFIG_ESP32C3_FLASH_FREQ_40M),$(call cfg_en,CONFIG_ESPTOOLPY_FLASHFREQ_40M)) \
$(if $(CONFIG_ESP32C3_FLASH_FREQ_26M),$(call cfg_en,CONFIG_ESPTOOLPY_FLASHFREQ_26M)) \
$(if $(CONFIG_ESP32C3_FLASH_FREQ_20M),$(call cfg_en,CONFIG_ESPTOOLPY_FLASHFREQ_20M)) \
} > $(BOOTLOADER_CONFIG)
ifeq ($(CONFIG_ESP32C3_APP_FORMAT_MCUBOOT),y)
$(Q) { \
echo "CONFIG_ESP_BOOTLOADER_SIZE=0xF000"; \
echo "CONFIG_ESP_APPLICATION_PRIMARY_START_ADDRESS=$(CONFIG_ESP32C3_OTA_PRIMARY_SLOT_OFFSET)"; \
echo "CONFIG_ESP_APPLICATION_SIZE=$(CONFIG_ESP32C3_OTA_SLOT_SIZE)"; \
echo "CONFIG_ESP_APPLICATION_SECONDARY_START_ADDRESS=$(CONFIG_ESP32C3_OTA_SECONDARY_SLOT_OFFSET)";\
echo "CONFIG_ESP_MCUBOOT_WDT_ENABLE=y"; \
echo "CONFIG_ESP_SCRATCH_OFFSET=$(CONFIG_ESP32C3_OTA_SCRATCH_OFFSET)"; \
echo "CONFIG_ESP_SCRATCH_SIZE=$(CONFIG_ESP32C3_OTA_SCRATCH_SIZE)"; \
$(Q) { \
$(if $(CONFIG_ESP32C3_SECURE_BOOT),$(call cfg_en,CONFIG_SECURE_BOOT)$(call cfg_en,CONFIG_SECURE_BOOT_V2_ENABLED)$(call cfg_val,CONFIG_ESP_SIGN_KEY_FILE,$(abspath $(TOPDIR)/$(ESPSEC_KEYDIR)/$(subst ",,$(CONFIG_ESP32C3_SECURE_BOOT_APP_SIGNING_KEY))))) \
$(if $(CONFIG_ESP32C3_SECURE_SIGNED_APPS_SCHEME_RSA_2048),$(call cfg_en,CONFIG_ESP_USE_MBEDTLS)$(call cfg_en,CONFIG_ESP_SIGN_RSA)$(call cfg_val,CONFIG_ESP_SIGN_RSA_LEN,2048)) \
$(if $(CONFIG_ESP32C3_SECURE_SIGNED_APPS_SCHEME_RSA_3072),$(call cfg_en,CONFIG_ESP_USE_MBEDTLS)$(call cfg_en,CONFIG_ESP_SIGN_RSA)$(call cfg_val,CONFIG_ESP_SIGN_RSA_LEN,3072)) \
$(if $(CONFIG_ESP32C3_SECURE_SIGNED_APPS_SCHEME_ECDSA_P256),$(call cfg_en,CONFIG_ESP_USE_TINYCRYPT)$(call cfg_en,CONFIG_ESP_SIGN_EC256)) \
$(if $(CONFIG_ESP32C3_SECURE_SIGNED_APPS_SCHEME_ED25519),$(call cfg_en,CONFIG_ESP_USE_TINYCRYPT)$(call cfg_en,CONFIG_ESP_SIGN_ED25519)) \
$(if $(CONFIG_ESP32C3_SECURE_BOOT_ALLOW_ROM_BASIC),$(call cfg_en,CONFIG_SECURE_BOOT_ALLOW_ROM_BASIC)) \
$(if $(CONFIG_ESP32C3_SECURE_BOOT_ALLOW_JTAG),$(call cfg_en,CONFIG_SECURE_BOOT_ALLOW_JTAG)) \
$(if $(CONFIG_ESP32C3_SECURE_BOOT_ALLOW_EFUSE_RD_DIS),$(call cfg_en,CONFIG_SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS)) \
$(if $(CONFIG_ESP32C3_SECURE_DISABLE_ROM_DL_MODE),$(call cfg_en,CONFIG_SECURE_DISABLE_ROM_DL_MODE)) \
$(if $(CONFIG_ESP32C3_SECURE_INSECURE_ALLOW_DL_MODE),$(call cfg_en,CONFIG_SECURE_INSECURE_ALLOW_DL_MODE)) \
$(call cfg_val,CONFIG_ESP_BOOTLOADER_SIZE,0xF000) \
$(call cfg_val,CONFIG_ESP_APPLICATION_PRIMARY_START_ADDRESS,$(CONFIG_ESP32C3_OTA_PRIMARY_SLOT_OFFSET)) \
$(call cfg_val,CONFIG_ESP_APPLICATION_SIZE,$(CONFIG_ESP32C3_OTA_SLOT_SIZE)) \
$(call cfg_val,CONFIG_ESP_APPLICATION_SECONDARY_START_ADDRESS,$(CONFIG_ESP32C3_OTA_SECONDARY_SLOT_OFFSET)) \
$(call cfg_en,CONFIG_ESP_MCUBOOT_WDT_ENABLE) \
$(call cfg_val,CONFIG_ESP_SCRATCH_OFFSET,$(CONFIG_ESP32C3_OTA_SCRATCH_OFFSET)) \
$(call cfg_val,CONFIG_ESP_SCRATCH_SIZE,$(CONFIG_ESP32C3_OTA_SCRATCH_SIZE)) \
} >> $(BOOTLOADER_CONFIG)
else ifeq ($(CONFIG_ESP32C3_APP_FORMAT_LEGACY),y)
$(Q) { \
echo "CONFIG_PARTITION_TABLE_CUSTOM=y"; \
echo "CONFIG_PARTITION_TABLE_CUSTOM_FILENAME=\"partitions.csv\""; \
echo "CONFIG_PARTITION_TABLE_OFFSET=$(CONFIG_ESP32C3_PARTITION_TABLE_OFFSET)"; \
$(Q) { \
$(call cfg_en,CONFIG_PARTITION_TABLE_CUSTOM) \
$(call cfg_val,CONFIG_PARTITION_TABLE_CUSTOM_FILENAME,\"partitions.csv\") \
$(call cfg_val,CONFIG_PARTITION_TABLE_OFFSET,$(CONFIG_ESP32C3_PARTITION_TABLE_OFFSET)) \
} >> $(BOOTLOADER_CONFIG)
endif
ifeq ($(CONFIG_ESP32C3_APP_FORMAT_MCUBOOT),y)
bootloader: $(BOOTLOADER_SRCDIR) $(BOOTLOADER_CONFIG)
$(Q) echo "Building Bootloader binaries"
BOOTLOADER_BIN = $(TOPDIR)/mcuboot-esp32c3.bin
BOOTLOADER_SIGNED_BIN = $(TOPDIR)/mcuboot-esp32c3.signed.bin
$(BOOTLOADER_BIN): $(BOOTLOADER_CONFIG)
$(Q) echo "Building Bootloader"
$(Q) $(BOOTLOADER_SRCDIR)/build_mcuboot.sh -c esp32c3 -s -f $(BOOTLOADER_CONFIG)
$(call COPYFILE, $(BOOTLOADER_SRCDIR)/$(BOOTLOADER_OUTDIR)/mcuboot-esp32c3.bin, $(TOPDIR))
bootloader: $(BOOTLOADER_CONFIG) $(BOOTLOADER_SRCDIR) $(BOOTLOADER_BIN)
ifeq ($(CONFIG_ESP32C3_SECURE_BOOT),y)
$(eval KEYDIR := $(TOPDIR)/$(ESPSEC_KEYDIR))
$(eval BOOTLOADER_SIGN_KEY := $(abspath $(KEYDIR)/$(subst ",,$(CONFIG_ESP32C3_SECURE_BOOT_BOOTLOADER_SIGNING_KEY))))
ifeq ($(CONFIG_ESP32C3_SECURE_BOOT_BUILD_SIGNED_BINARIES),y)
$(Q) if [ ! -f "$(BOOTLOADER_SIGN_KEY)" ]; then \
echo ""; \
echo "$(RED)bootloader error:$(RST) Bootloader signing key $(BOLD)$(CONFIG_ESP32C3_SECURE_BOOT_BOOTLOADER_SIGNING_KEY)$(RST) does not exist."; \
echo "Generate using:"; \
echo " espsecure.py generate_signing_key --version 2 $(CONFIG_ESP32C3_SECURE_BOOT_BOOTLOADER_SIGNING_KEY)"; \
echo ""; \
exit 1; \
fi
$(Q) echo "Signing Bootloader"
espsecure.py sign_data --version 2 --keyfile $(BOOTLOADER_SIGN_KEY) -o $(BOOTLOADER_SIGNED_BIN) $(BOOTLOADER_BIN)
else
$(Q) echo ""
$(Q) echo "$(YELLOW)Bootloader not signed. Sign the bootloader before flashing.$(RST)"
$(Q) echo "To sign the bootloader, you can use this command:"
$(Q) echo " espsecure.py sign_data --version 2 --keyfile $(BOOTLOADER_SIGN_KEY) -o mcuboot-esp32c3.signed.bin mcuboot-esp32c3.bin"
$(Q) echo ""
endif
endif
clean_bootloader:
$(call DELDIR, $(BOOTLOADER_SRCDIR))
$(call DELFILE, $(BOOTLOADER_CONFIG))
$(call DELFILE, $(TOPDIR)/mcuboot-esp32c3.bin)
$(call DELDIR,$(BOOTLOADER_SRCDIR))
$(call DELFILE,$(BOOTLOADER_CONFIG))
$(call DELFILE,$(BOOTLOADER_BIN))
$(if $(CONFIG_ESP32C3_SECURE_BOOT_BUILD_SIGNED_BINARIES),$(call DELFILE,$(BOOTLOADER_SIGNED_BIN)))
else ifeq ($(CONFIG_ESP32C3_APP_FORMAT_LEGACY),y)
bootloader: $(BOOTLOADER_SRCDIR) $(BOOTLOADER_CONFIG)
$(Q) echo "Building Bootloader binaries"
$(Q) $(BOOTLOADER_SRCDIR)/build_idfboot.sh -c esp32c3 -s -f $(BOOTLOADER_CONFIG)
$(call COPYFILE, $(BOOTLOADER_SRCDIR)/$(BOOTLOADER_OUTDIR)/bootloader-esp32c3.bin, $(TOPDIR))
$(call COPYFILE, $(BOOTLOADER_SRCDIR)/$(BOOTLOADER_OUTDIR)/partition-table-esp32c3.bin, $(TOPDIR))
$(call COPYFILE,$(BOOTLOADER_SRCDIR)/$(BOOTLOADER_OUTDIR)/bootloader-esp32c3.bin,$(TOPDIR))
$(call COPYFILE,$(BOOTLOADER_SRCDIR)/$(BOOTLOADER_OUTDIR)/partition-table-esp32c3.bin,$(TOPDIR))
clean_bootloader:
$(call DELDIR, $(BOOTLOADER_SRCDIR))
$(call DELFILE, $(BOOTLOADER_CONFIG))
$(call DELFILE, $(TOPDIR)/bootloader-esp32c3.bin)
$(call DELFILE, $(TOPDIR)/partition-table-esp32c3.bin)
$(call DELDIR,$(BOOTLOADER_SRCDIR))
$(call DELFILE,$(BOOTLOADER_CONFIG))
$(call DELFILE,$(TOPDIR)/bootloader-esp32c3.bin)
$(call DELFILE,$(TOPDIR)/partition-table-esp32c3.bin)
endif
@ -106,7 +164,7 @@ bootloader:
$(Q) curl -L $(BOOTLOADER_URL)/mcuboot-esp32c3.bin -o $(TOPDIR)/mcuboot-esp32c3.bin
clean_bootloader:
$(call DELFILE, $(TOPDIR)/mcuboot-esp32c3.bin)
$(call DELFILE,$(TOPDIR)/mcuboot-esp32c3.bin)
else ifeq ($(CONFIG_ESP32C3_APP_FORMAT_LEGACY),y)
@ -116,8 +174,8 @@ bootloader:
$(Q) curl -L $(BOOTLOADER_URL)/partition-table-esp32c3.bin -o $(TOPDIR)/partition-table-esp32c3.bin
clean_bootloader:
$(call DELFILE, $(TOPDIR)/bootloader-esp32c3.bin)
$(call DELFILE, $(TOPDIR)/partition-table-esp32c3.bin)
$(call DELFILE,$(TOPDIR)/bootloader-esp32c3.bin)
$(call DELFILE,$(TOPDIR)/partition-table-esp32c3.bin)
endif

View File

@ -70,6 +70,14 @@ config ESP32C3_FLASH_16M
bool
default n
config ESP32C3_ESPTOOLPY_NO_STUB
bool "Disable download stub"
default n
---help---
The flasher tool sends a precompiled download stub first by default.
That stub allows things like compressed downloads and more.
Usually you should not need to disable that feature.
config ESP32C3_FLASH_DETECT
bool "Auto-detect FLASH size (to be used with master esptool)"
default n
@ -1089,6 +1097,8 @@ config ESP32C3_PARTITION_TABLE_OFFSET
default 0x8000
depends on ESP32C3_APP_FORMAT_LEGACY
source "arch/risc-v/src/esp32c3/Kconfig.security"
endmenu # Application Image Configuration
menu "Brownout Detect Configuration"

View File

@ -0,0 +1,212 @@
#
# For a description of the syntax of this configuration file,
# see the file kconfig-language.txt in the NuttX tools repository.
#
comment "Secure Boot"
config ESP32C3_SECURE_BOOT
bool "Enable hardware Secure Boot in bootloader (READ HELP FIRST)"
default n
depends on ESP32C3_APP_FORMAT_MCUBOOT
select ESP32C3_ESPTOOLPY_NO_STUB
---help---
Build a bootloader which enables Secure Boot on first boot.
Once enabled, Secure Boot will not boot a modified bootloader. The bootloader will only boot an
application firmware image if it has a verified digital signature. There are implications for reflashing
updated images once Secure Boot is enabled.
When enabling Secure Boot, JTAG and ROM BASIC Interpreter are permanently disabled by default.
if ESP32C3_SECURE_BOOT
comment "Secure Boot support requires building bootloader from source (ESP32C3_BOOTLOADER_BUILD_FROM_SOURCE)"
depends on !ESP32C3_BOOTLOADER_BUILD_FROM_SOURCE
config ESP32C3_SECURE_BOOT_BUILD_SIGNED_BINARIES
bool "Sign binaries during build"
default y
---help---
Once Secure Boot is enabled, bootloader and application images are required to be signed.
If enabled (default), these binary files are signed as part of the build process.
The files named in "Bootloader private signing key" and "Application private signing key" will
be used to sign the bootloader and application images, respectively.
If disabled, unsigned firmware images will be built.
They must be then signed manually using imgtool (e.g., on a remote signing server).
config ESP32C3_SECURE_BOOT_BOOTLOADER_SIGNING_KEY
string "Bootloader private signing key"
default "bootloader_signing_key.pem"
---help---
Path to the key file used to sign the bootloader image.
Key file is an RSA private key in PEM format.
Path is evaluated relative to the directory indicated by the ESPSEC_KEYDIR environment
variable.
You can generate a new signing key by running the following command:
$ espsecure.py generate_signing_key --version 2 bootloader_signing_key.pem
See the Secure Boot section of the ESP-IDF Programmer's Guide for this version for details.
choice ESP32C3_SECURE_SIGNED_APPS_SCHEME
prompt "Application image signing scheme"
default ESP32C3_SECURE_SIGNED_APPS_SCHEME_ECDSA_P256
---help---
Select the secure application signing scheme.
config ESP32C3_SECURE_SIGNED_APPS_SCHEME_RSA_2048
bool "RSA-2048"
config ESP32C3_SECURE_SIGNED_APPS_SCHEME_RSA_3072
bool "RSA-3072"
config ESP32C3_SECURE_SIGNED_APPS_SCHEME_ECDSA_P256
bool "ECDSA-P256"
config ESP32C3_SECURE_SIGNED_APPS_SCHEME_ED25519
bool "ED25519"
endchoice
config ESP32C3_SECURE_BOOT_APP_SIGNING_KEY
string "Application private signing key"
default "app_signing_key.pem"
---help---
Path to the key file used to sign NuttX application images.
Key file is in PEM format and its type shall be specified by the configuration defined in
"Application image signing scheme".
Path is evaluated relative to the directory indicated by the ESPSEC_KEYDIR environment
variable.
You can generate a new signing key by running the following command:
$ imgtool keygen --key app_signing_key.pem --type <ESP32C3_SECURE_SIGNED_APPS_SCHEME>
config ESP32C3_SECURE_BOOT_INSECURE
bool "Allow potentially insecure options"
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 the Secure Boot section of the ESP-IDF Programmer's Guide for this version before enabling.
endif # ESP32C3_SECURE_BOOT
menu "Potentially insecure options"
visible if ESP32C3_SECURE_BOOT_INSECURE
# NOTE: Options in this menu NEED to have ESP32C3_SECURE_BOOT_INSECURE
# and/or ESP32C3_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT 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 ESP32C3_SECURE_BOOT_ALLOW_ROM_BASIC
bool "Leave ROM BASIC Interpreter available on reset"
default n
depends on ESP32C3_SECURE_BOOT_INSECURE
---help---
By default, the BASIC ROM Console starts on reset if no valid bootloader is
read from the flash.
When either Flash Encryption or Secure Boot are enabled, the default is to
disable this BASIC fallback mode permanently via eFuse.
If this option is set, this eFuse is not burned and the BASIC ROM Console may
remain accessible. Only set this option in testing environments.
config ESP32C3_SECURE_BOOT_ALLOW_JTAG
bool "Allow JTAG Debugging"
default n
depends on ESP32C3_SECURE_BOOT_INSECURE
---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 ESP32C3_SECURE_BOOT_ALLOW_EFUSE_RD_DIS
bool "Allow additional read protecting of efuses"
default n
depends on ESP32C3_SECURE_BOOT_INSECURE
---help---
If not set (default, recommended), on first boot the bootloader will burn the WR_DIS_RD_DIS
efuse when Secure Boot is enabled. This prevents any more efuses from being read protected.
If this option is set, it will remain possible to write the EFUSE_RD_DIS efuse field after Secure
Boot is enabled. This may allow an attacker to read-protect the BLK2 efuse (for ESP32) and
BLOCK4-BLOCK10 (i.e. BLOCK_KEY0-BLOCK_KEY5)(for other chips) holding the public key digest, causing an
immediate denial of service and possibly allowing an additional fault injection attack to
bypass the signature protection.
NOTE: Once a BLOCK is read-protected, the application will read all zeros from that block
NOTE: If UART ROM download mode "Permanently disabled (recommended)" is set,
then it is __NOT__ possible to read/write efuses using espefuse.py utility.
However, efuse can be read/written from the application.
endmenu # Potentially insecure options
choice ESP32C3_SECURE_UART_ROM_DL_MODE
bool "UART ROM download mode"
default ESP32C3_SECURE_INSECURE_ALLOW_DL_MODE
depends on ESP32C3_SECURE_BOOT
config ESP32C3_SECURE_DISABLE_ROM_DL_MODE
bool "Permanently disabled (recommended)"
---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 ESP32C3_SECURE_ENABLE_SECURE_ROM_DL_MODE
bool "Permanently switch to Secure mode (recommended)"
---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()
config ESP32C3_SECURE_INSECURE_ALLOW_DL_MODE
bool "Enabled (not recommended)"
---help---
This is a potentially insecure option.
Enabling this option will allow the full UART download mode to stay enabled.
This option SHOULD NOT BE ENABLED for production use cases.
endchoice

View File

@ -58,6 +58,10 @@ else
ESPTOOL_WRITEFLASH_OPTS := -fs $(FLASH_SIZE) -fm dio -ff $(FLASH_FREQ)
endif
ifeq ($(CONFIG_ESP32C3_SECURE_BOOT),y)
ESPTOOL_RESET_OPTS += --after no_reset
endif
ESPTOOL_FLASH_OPTS := -fs $(FLASH_SIZE) -fm $(FLASH_MODE) -ff $(FLASH_FREQ)
# Configure the variables according to build environment
@ -73,9 +77,15 @@ ifdef ESPTOOL_BINDIR
ESPTOOL_BINS := $(FLASH_BL) $(FLASH_PT)
else ifeq ($(CONFIG_ESP32C3_APP_FORMAT_MCUBOOT),y)
BL_OFFSET := 0x0
BOOTLOADER := $(ESPTOOL_BINDIR)/mcuboot-esp32c3.bin
FLASH_BL := $(BL_OFFSET) $(BOOTLOADER)
ESPTOOL_BINS := $(FLASH_BL)
ifeq ($(CONFIG_ESP32C3_SECURE_BOOT),y)
BOOTLOADER := $(ESPTOOL_BINDIR)/mcuboot-esp32c3.signed.bin
FLASH_BL := $(BL_OFFSET) $(BOOTLOADER)
ESPTOOL_BINS :=
else
BOOTLOADER := $(ESPTOOL_BINDIR)/mcuboot-esp32c3.bin
FLASH_BL := $(BL_OFFSET) $(BOOTLOADER)
ESPTOOL_BINS := $(FLASH_BL)
endif
endif
endif
@ -92,15 +102,43 @@ else ifeq ($(CONFIG_ESP32C3_APP_FORMAT_MCUBOOT),y)
APP_OFFSET := $(CONFIG_ESP32C3_OTA_SECONDARY_SLOT_OFFSET)
endif
APP_IMAGE := nuttx.signed.bin
ifeq ($(CONFIG_ESP32C3_SECURE_BOOT),y)
APP_IMAGE := nuttx.signed.bin
else
APP_IMAGE := nuttx.bin
endif
FLASH_APP := $(APP_OFFSET) $(APP_IMAGE)
endif
ESPTOOL_BINS += $(FLASH_APP)
# Commands for colored and formatted output
RED = \033[1;31m
YELLOW = \033[1;33m
BOLD = \033[1m
RST = \033[0m
# Functions for printing help messages
define HELP_SIGN_APP
$(Q) echo ""
$(Q) echo "$(YELLOW)Application not signed. Sign the application before flashing.$(RST)"
$(Q) echo "To sign the application, you can use this command:"
$(Q) echo " imgtool sign -k $(ESPSEC_KEYDIR)/$(CONFIG_ESP32C3_SECURE_BOOT_APP_SIGNING_KEY) --public-key-format hash --pad $(VERIFIED) --align 4 -v 0 -s auto -H $(CONFIG_ESP32C3_APP_MCUBOOT_HEADER_SIZE) --pad-header -S $(CONFIG_ESP32C3_OTA_SLOT_SIZE) nuttx.hex nuttx.signed.bin"
$(Q) echo ""
endef
define HELP_FLASH_BOOTLOADER
$(Q) echo ""
$(Q) echo "$(YELLOW)Secure boot enabled, so bootloader not flashed automatically.$(RST)"
$(Q) echo "Use the following command to flash the bootloader:"
$(Q) echo " esptool.py $(ESPTOOL_OPTS) write_flash $(ESPTOOL_WRITEFLASH_OPTS) $(FLASH_BL)"
$(Q) echo ""
endef
# MERGEBIN -- Merge raw binary files into a single file
ifeq ($(CONFIG_ESP32C3_MERGE_BINS),y)
define MERGEBIN
$(Q) if [ -z $(ESPTOOL_BINDIR) ]; then \
echo "MERGEBIN error: Missing argument for binary files directory."; \
@ -115,17 +153,11 @@ define MERGEBIN
$(Q) echo nuttx.merged.bin >> nuttx.manifest
$(Q) echo "Generated: nuttx.merged.bin"
endef
else
define MERGEBIN
endef
endif
# SIGNBIN -- Create the signed binary image file for Secure Boot
# SIGNBIN -- Sign the binary image file
ifeq ($(CONFIG_ESP32C3_APP_FORMAT_MCUBOOT),y)
define SIGNBIN
$(Q) echo "MKIMAGE: ESP32-C3 binary"
$(Q) echo "SIGNBIN: ESP32-C3 signed binary"
$(Q) if ! imgtool version 1>/dev/null 2>&1; then \
echo ""; \
echo "imgtool not found. Please run: \"pip install imgtool\""; \
@ -133,19 +165,41 @@ define SIGNBIN
echo "Run make again to create the nuttx.signed.bin image."; \
exit 1; \
fi
imgtool sign --pad --pad-sig $(VERIFIED) --align 4 -v 0 \
$(Q) if [ -z "$(ESPSEC_KEYDIR)" ]; then \
echo "SIGNBIN error: Missing argument for secure boot keys directory."; \
echo "USAGE: make ESPSEC_KEYDIR=<dir>"; \
exit 1; \
fi
$(eval APP_SIGN_KEY := $(ESPSEC_KEYDIR)/$(subst ",,$(CONFIG_ESP32C3_SECURE_BOOT_APP_SIGNING_KEY)))
$(Q) if [ ! -f "$(APP_SIGN_KEY)" ]; then \
echo ""; \
echo "$(RED)SIGNBIN error:$(RST) Application signing key $(BOLD)$(CONFIG_ESP32C3_SECURE_BOOT_APP_SIGNING_KEY)$(RST) does not exist."; \
echo "Generate using:"; \
echo " imgtool keygen --key $(CONFIG_ESP32C3_SECURE_BOOT_APP_SIGNING_KEY) --type <ESP32C3_SECURE_SIGNED_APPS_SCHEME>"; \
echo ""; \
exit 1; \
fi
$(if $(CONFIG_ESP32C3_SECURE_BOOT_BUILD_SIGNED_BINARIES), \
$(eval IMGTOOL_KEY_ARGS := -k $(APP_SIGN_KEY) --public-key-format hash))
imgtool sign $(IMGTOOL_KEY_ARGS) --pad $(VERIFIED) --align 4 -v 0 -s auto \
-H $(CONFIG_ESP32C3_APP_MCUBOOT_HEADER_SIZE) --pad-header \
-S $(CONFIG_ESP32C3_OTA_SLOT_SIZE) \
nuttx.bin nuttx.signed.bin
nuttx.hex nuttx.signed.bin
$(Q) echo nuttx.signed.bin >> nuttx.manifest
$(Q) echo "Generated: nuttx.signed.bin (MCUboot compatible)"
endef
endif
# ELF2IMAGE -- Convert an ELF file into a binary file in Espressif application image format
# MKIMAGE -- Convert an ELF file into a compatible binary file
ifeq ($(CONFIG_ESP32C3_SECURE_BOOT),y)
define MKIMAGE
$(if $(CONFIG_ESP32C3_SECURE_BOOT_BUILD_SIGNED_BINARIES),$(call SIGNBIN),$(call HELP_SIGN_APP))
endef
else
ifeq ($(CONFIG_ESP32C3_APP_FORMAT_LEGACY),y)
define ELF2IMAGE
define MKIMAGE
$(Q) echo "MKIMAGE: ESP32-C3 binary"
$(Q) if ! esptool.py version 1>/dev/null 2>&1; then \
echo ""; \
@ -161,21 +215,31 @@ define ELF2IMAGE
esptool.py -c esp32c3 elf2image $(ESPTOOL_FLASH_OPTS) -o nuttx.bin nuttx
$(Q) echo "Generated: nuttx.bin (ESP32-C3 compatible)"
endef
else ifeq ($(CONFIG_ESP32C3_APP_FORMAT_MCUBOOT),y)
define MKIMAGE
$(Q) echo "MKIMAGE: ESP32-C3 binary"
$(Q) if ! imgtool version 1>/dev/null 2>&1; then \
echo ""; \
echo "imgtool not found. Please run: \"pip install imgtool\""; \
echo ""; \
echo "Run make again to create the nuttx.bin image."; \
exit 1; \
fi
imgtool sign --pad $(VERIFIED) --align 4 -v 0 -s auto \
-H $(CONFIG_ESP32C3_APP_MCUBOOT_HEADER_SIZE) --pad-header \
-S $(CONFIG_ESP32C3_OTA_SLOT_SIZE) \
nuttx.hex nuttx.bin
$(Q) echo "Generated: nuttx.bin (MCUboot compatible)"
endef
endif
endif
# POSTBUILD -- Perform post build operations
ifeq ($(CONFIG_ESP32C3_APP_FORMAT_MCUBOOT),y)
define POSTBUILD
$(call SIGNBIN)
$(call MERGEBIN)
$(call MKIMAGE)
$(if $(CONFIG_ESP32C3_MERGE_BINS),$(call MERGEBIN))
endef
else ifeq ($(CONFIG_ESP32C3_APP_FORMAT_LEGACY),y)
define POSTBUILD
$(call ELF2IMAGE)
$(call MERGEBIN)
endef
endif
# ESPTOOL_BAUD -- Serial port baud rate used when flashing/reading via esptool.py
@ -189,5 +253,9 @@ define FLASH
echo "USAGE: make flash ESPTOOL_PORT=<port> [ ESPTOOL_BAUD=<baud> ]"; \
exit 1; \
fi
esptool.py -c esp32c3 -p $(ESPTOOL_PORT) -b $(ESPTOOL_BAUD) write_flash $(ESPTOOL_WRITEFLASH_OPTS) $(ESPTOOL_BINS)
$(eval ESPTOOL_OPTS := -c esp32c3 -p $(ESPTOOL_PORT) -b $(ESPTOOL_BAUD) $(ESPTOOL_RESET_OPTS) $(if $(CONFIG_ESP32C3_ESPTOOLPY_NO_STUB),--no-stub))
esptool.py $(ESPTOOL_OPTS) write_flash $(ESPTOOL_WRITEFLASH_OPTS) $(ESPTOOL_BINS)
$(if $(CONFIG_ESP32C3_SECURE_BOOT),$(call HELP_FLASH_BOOTLOADER))
endef