kopia lustrzana https://github.com/espressif/esp-idf
Merge branch 'feature/secure_boot_remote_sign' into 'master'
Secure boot: Option for app & partition table signing to happen outside build system Allows for a remote signing server, private signing key does not need to be on the build system. See merge request !320pull/155/merge
commit
7ba6be782e
|
@ -69,9 +69,20 @@ config SECURE_BOOTLOADER_REFLASHABLE
|
|||
|
||||
endchoice
|
||||
|
||||
config SECURE_BOOT_SIGNING_KEY
|
||||
string "Secure boot signing key"
|
||||
config SECURE_BOOT_BUILD_SIGNED_BINARIES
|
||||
bool "Sign binaries during build"
|
||||
depends on SECURE_BOOT_ENABLED
|
||||
default y
|
||||
help
|
||||
Once secure boot is enabled, bootloader will only boot if partition table and app image are signed.
|
||||
|
||||
If enabled, these binary files are signed as part of the build process. The file named in "Secure boot private signing key" will be used to sign the image.
|
||||
|
||||
If disabled, unsigned app/partition data will be built. They must be signed manually using espsecure.py (for example, on a remote signing server.)
|
||||
|
||||
config SECURE_BOOT_SIGNING_KEY
|
||||
string "Secure boot private signing key"
|
||||
depends on SECURE_BOOT_BUILD_SIGNED_BINARIES
|
||||
default secure_boot_signing_key.pem
|
||||
help
|
||||
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.
|
||||
|
@ -85,6 +96,20 @@ config SECURE_BOOT_SIGNING_KEY
|
|||
|
||||
See docs/security/secure-boot.rst for details.
|
||||
|
||||
config SECURE_BOOT_VERIFICATION_KEY
|
||||
string "Secure boot public signature verification key"
|
||||
depends on SECURE_BOOT_ENABLED && !SECURE_BOOT_BUILD_SIGNED_BINARIES
|
||||
default signature_verification_key.bin
|
||||
help
|
||||
Path to a public key file used to verify signed images. This key is compiled into the bootloader,
|
||||
and may also be used to verify signatures on OTA images after download.
|
||||
|
||||
Key file is in raw binary format, and can be extracted from a
|
||||
PEM formatted private key using the espsecure.py
|
||||
extract_public_key command.
|
||||
|
||||
See docs/security/secure-boot.rst for details.
|
||||
|
||||
config SECURE_BOOT_INSECURE
|
||||
bool "Allow potentially insecure options"
|
||||
depends on SECURE_BOOT_ENABLED
|
||||
|
|
|
@ -65,8 +65,17 @@ else ifdef CONFIG_SECURE_BOOTLOADER_REFLASHABLE
|
|||
BOOTLOADER_DIGEST_BIN := $(BOOTLOADER_BUILD_DIR)/bootloader-reflash-digest.bin
|
||||
SECURE_BOOTLOADER_KEY := $(BOOTLOADER_BUILD_DIR)/secure-bootloader-key.bin
|
||||
|
||||
ifdef CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES
|
||||
$(SECURE_BOOTLOADER_KEY): $(SECURE_BOOT_SIGNING_KEY)
|
||||
$(Q) $(ESPSECUREPY) digest_private_key -k $< $@
|
||||
$(ESPSECUREPY) digest_private_key -k $< $@
|
||||
else
|
||||
$(SECURE_BOOTLOADER_KEY):
|
||||
@echo "No pre-generated key for a reflashable secure bootloader is available, due to signing configuration."
|
||||
@echo "To generate one, you can use this command:"
|
||||
@echo "espsecure.py generate_flash_encryption_key $@"
|
||||
@echo "then re-run make."
|
||||
exit 1
|
||||
endif
|
||||
|
||||
bootloader: $(BOOTLOADER_DIGEST_BIN)
|
||||
@echo $(SEPARATOR)
|
||||
|
|
|
@ -17,8 +17,26 @@ ifdef CONFIG_SECURE_BOOT_ENABLED
|
|||
# this path is created relative to the component build directory
|
||||
SECURE_BOOT_VERIFICATION_KEY := $(abspath signature_verification_key.bin)
|
||||
|
||||
$(SECURE_BOOT_VERIFICATION_KEY): $(SECURE_BOOT_SIGNING_KEY)
|
||||
ifdef CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES
|
||||
# verification key derived from signing key.
|
||||
$(SECURE_BOOT_VERIFICATION_KEY): $(SECURE_BOOT_SIGNING_KEY) $(SDKCONFIG_MAKEFILE)
|
||||
$(ESPSECUREPY) extract_public_key --keyfile $< $@
|
||||
else
|
||||
# find the configured public key file
|
||||
ORIG_SECURE_BOOT_VERIFICATION_KEY := $(call resolvepath,$(call dequote,$(CONFIG_SECURE_BOOT_VERIFICATION_KEY)),$(PROJECT_PATH))
|
||||
|
||||
$(ORIG_SECURE_BOOT_VERIFICATION_KEY):
|
||||
@echo "Secure boot verification public key '$@' missing."
|
||||
@echo "This can be extracted from the private signing key, see"
|
||||
@echo "docs/security/secure-boot.rst for details."
|
||||
exit 1
|
||||
|
||||
# copy it into the build dir, so the secure boot verification key has
|
||||
# a predictable file name
|
||||
$(SECURE_BOOT_VERIFICATION_KEY): $(ORIG_SECURE_BOOT_VERIFICATION_KEY) $(SDKCONFIG_MAKEFILE)
|
||||
$(summary) CP $< $@
|
||||
cp $< $@
|
||||
endif
|
||||
|
||||
COMPONENT_EXTRA_CLEAN += $(SECURE_BOOT_VERIFICATION_KEY)
|
||||
|
||||
|
|
|
@ -28,12 +28,12 @@ ESPTOOLPY_WRITE_FLASH=$(ESPTOOLPY_SERIAL) write_flash $(if $(CONFIG_ESPTOOLPY_CO
|
|||
|
||||
ESPTOOL_ALL_FLASH_ARGS += $(CONFIG_APP_OFFSET) $(APP_BIN)
|
||||
|
||||
ifdef CONFIG_SECURE_BOOT_ENABLED
|
||||
ifdef CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES
|
||||
ifndef IS_BOOTLOADER_BUILD
|
||||
# for secure boot, add a signing step to get from unsiged app to signed app
|
||||
# for locally signed secure boot image, add a signing step to get from unsigned app to signed app
|
||||
APP_BIN_UNSIGNED := $(APP_BIN:.bin=-unsigned.bin)
|
||||
|
||||
$(APP_BIN): $(APP_BIN_UNSIGNED) $(SECURE_BOOT_SIGNING_KEY)
|
||||
$(APP_BIN): $(APP_BIN_UNSIGNED) $(SECURE_BOOT_SIGNING_KEY) $(SDKCONFIG_MAKEFILE)
|
||||
$(ESPSECUREPY) sign_data --keyfile $(SECURE_BOOT_SIGNING_KEY) -o $@ $<
|
||||
endif
|
||||
endif
|
||||
|
|
|
@ -21,7 +21,7 @@ PARTITION_TABLE_CSV_PATH := $(call dequote,$(abspath $(PARTITION_TABLE_ROOT)/$(s
|
|||
|
||||
PARTITION_TABLE_BIN := $(BUILD_DIR_BASE)/$(notdir $(PARTITION_TABLE_CSV_PATH:.csv=.bin))
|
||||
|
||||
ifdef CONFIG_SECURE_BOOT_ENABLED
|
||||
ifdef CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES
|
||||
PARTITION_TABLE_BIN_UNSIGNED := $(PARTITION_TABLE_BIN:.bin=-unsigned.bin)
|
||||
# add an extra signing step for secure partition table
|
||||
$(PARTITION_TABLE_BIN): $(PARTITION_TABLE_BIN_UNSIGNED) $(SDKCONFIG_MAKEFILE) $(SECURE_BOOT_SIGNING_KEY)
|
||||
|
|
|
@ -25,7 +25,7 @@ This is a high level overview of the secure boot process. Step by step instructi
|
|||
|
||||
1. The options to enable secure boot are provided in the ``make menuconfig`` hierarchy, under "Secure Boot Configuration".
|
||||
|
||||
2. Secure Boot Configuration includes "Secure boot signing key", which is a file path. This file is a ECDSA public/private key pair in a PEM format file.
|
||||
2. Secure Boot defaults to signing images and partition table data during the build process. The "Secure boot private signing key" config item is a file path to a ECDSA public/private key pair in a PEM format file.
|
||||
|
||||
3. The software bootloader image is built by esp-idf with secure boot support enabled and the public key (signature verification) portion of the secure boot signing key compiled in. This software bootloader image is flashed at offset 0x1000.
|
||||
|
||||
|
@ -119,6 +119,27 @@ openssl ecparam -name prime256v1 -genkey -noout -out my_secure_boot_signing_key.
|
|||
|
||||
Remember that the strength of the secure boot system depends on keeping the signing key private.
|
||||
|
||||
Remote Signing of Images
|
||||
------------------------
|
||||
|
||||
For production builds, it can be good practice to use a remote signing server rather than have the signing key on the build machine (which is the default esp-idf secure boot configuration). The espsecure.py command line program can be used to sign app images & partition table data for secure boot, on a remote system.
|
||||
|
||||
To use remote signing, disable the option "Sign binaries during build". The private signing key does not need to be present on the build system. However, the public (signature verification) key is required because it is compiled into the bootloader (and can be used to verify image signatures during OTA updates.
|
||||
|
||||
To extract the public key from the private key::
|
||||
|
||||
espsecure.py extract_public_key --keyfile PRIVATE_SIGNING_KEY PUBLIC_VERIFICATION_KEY
|
||||
|
||||
The path to the public signature verification key needs to be specified in the menuconfig under "Secure boot public signature verification key" in order to build the secure bootloader.
|
||||
|
||||
After the app image and partition table are built, the build system will print signing steps using espsecure.py::
|
||||
|
||||
espsecure.py sign_data --keyfile PRIVATE_SIGNING_KEY BINARY_FILE
|
||||
|
||||
The above command appends the image signature to the existing binary. You can use the --output argument to place the binary with signature appended into a separate file::
|
||||
|
||||
espsecure.py sign_data --keyfile PRIVATE_SIGNING_KEY --output SIGNED_BINARY_FILE BINARY_FILE
|
||||
|
||||
Secure Boot Best Practices
|
||||
--------------------------
|
||||
|
||||
|
|
|
@ -74,7 +74,6 @@ endif
|
|||
# Correspond to the files named in COMPONENT_EMBED_FILES & COMPONENT_EMBED_TXTFILES
|
||||
COMPONENT_EMBED_OBJS ?= $(addsuffix .bin.o,$(COMPONENT_EMBED_FILES)) $(addsuffix .txt.o,$(COMPONENT_EMBED_TXTFILES))
|
||||
|
||||
|
||||
# If we're called to compile something, we'll get passed the COMPONENT_INCLUDES
|
||||
# variable with all the include dirs from all the components in random order. This
|
||||
# means we can accidentally grab a header from another component before grabbing our own.
|
||||
|
|
|
@ -142,6 +142,11 @@ include $(IDF_PATH)/make/common.mk
|
|||
all:
|
||||
ifdef CONFIG_SECURE_BOOT_ENABLED
|
||||
@echo "(Secure boot enabled, so bootloader not flashed automatically. See 'make bootloader' output)"
|
||||
ifndef CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES
|
||||
@echo "App built but not signed. Sign app & partition data before flashing, via espsecure.py:"
|
||||
@echo "espsecure.py sign_data --keyfile KEYFILE $(APP_BIN)"
|
||||
@echo "espsecure.py sign_data --keyfile KEYFILE $(PARTITION_TABLE_BIN)"
|
||||
endif
|
||||
@echo "To flash app & partition table, run 'make flash' or:"
|
||||
else
|
||||
@echo "To flash all build output, run 'make flash' or:"
|
||||
|
@ -283,8 +288,15 @@ $(APP_ELF): $(foreach libcomp,$(COMPONENT_LIBRARIES),$(BUILD_DIR_BASE)/$(libcomp
|
|||
# Generation of $(APP_BIN) from $(APP_ELF) is added by the esptool
|
||||
# component's Makefile.projbuild
|
||||
app: $(APP_BIN)
|
||||
ifeq ("$(CONFIG_SECURE_BOOT_ENABLED)$(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)","y") # secure boot enabled, but remote sign app image
|
||||
@echo "App built but not signed. Signing step via espsecure.py:"
|
||||
@echo "espsecure.py sign_data --keyfile KEYFILE $(APP_BIN)"
|
||||
@echo "Then flash app command is:"
|
||||
@echo $(ESPTOOLPY_WRITE_FLASH) $(CONFIG_APP_OFFSET) $(APP_BIN)
|
||||
else
|
||||
@echo "App built. Default flash app command is:"
|
||||
@echo $(ESPTOOLPY_WRITE_FLASH) $(CONFIG_APP_OFFSET) $(APP_BIN)
|
||||
endif
|
||||
|
||||
all_binaries: $(APP_BIN)
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue