From a9ccc5e5c8cdeb6a051023101bb11b577d971823 Mon Sep 17 00:00:00 2001 From: Supreet Deshpande Date: Tue, 25 Feb 2020 01:21:41 +0530 Subject: [PATCH] feat/secure_boot_v2: Adding secure boot v2 support for ESP32-ECO3 --- components/bootloader/CMakeLists.txt | 6 +- components/bootloader/Kconfig.projbuild | 98 +++++++-- components/bootloader/Makefile.projbuild | 33 ++- components/bootloader/project_include.cmake | 19 +- components/bootloader/sdkconfig.rename | 3 + .../bootloader/subproject/CMakeLists.txt | 47 ++++ .../bootloader/subproject/main/component.mk | 3 + components/bootloader_support/CMakeLists.txt | 32 ++- components/bootloader_support/component.mk | 15 +- .../include/esp_secure_boot.h | 85 ++++++-- .../include_bootloader/bootloader_flash.h | 2 + .../include_bootloader/bootloader_utility.h | 14 ++ .../bootloader_support/src/bootloader_flash.c | 1 - .../src/bootloader_utility.c | 48 ++++- .../src/esp32/flash_encrypt.c | 2 +- .../src/esp32/secure_boot.c | 204 +++++++++++++++++- .../src/esp32/secure_boot_signatures.c | 111 +++++++--- .../src/esp32s2/secure_boot.c | 2 +- .../src/esp32s2/secure_boot_signatures.c | 17 +- .../bootloader_support/src/esp_image_format.c | 31 ++- .../bootloader_support/src/flash_encrypt.c | 4 +- .../src/idf/bootloader_sha.c | 1 + .../src/idf/secure_boot_signatures.c | 167 ++++++++++++-- components/esp_rom/CMakeLists.txt | 9 + components/esp_rom/component.mk | 4 + components/esp_rom/esp32/ld/esp32.rom.eco3.ld | 7 + .../esp_rom/include/esp32/rom/secure_boot.h | 76 ++++++- components/esptool_py/CMakeLists.txt | 2 +- components/esptool_py/Makefile.projbuild | 20 +- components/esptool_py/esptool | 2 +- components/esptool_py/project_include.cmake | 28 ++- components/partition_table/CMakeLists.txt | 12 +- components/partition_table/Makefile.projbuild | 9 +- make/project.mk | 21 +- 34 files changed, 950 insertions(+), 185 deletions(-) create mode 100644 components/esp_rom/esp32/ld/esp32.rom.eco3.ld diff --git a/components/bootloader/CMakeLists.txt b/components/bootloader/CMakeLists.txt index 1cdd13091c..410f9efba4 100644 --- a/components/bootloader/CMakeLists.txt +++ b/components/bootloader/CMakeLists.txt @@ -6,11 +6,15 @@ if(BOOTLOADER_BUILD OR NOT CONFIG_APP_BUILD_BOOTLOADER) endif() add_dependencies(bootloader partition_table) +# When secure boot is enabled, do not flash bootloader along with invocation of `idf.py flash` +if(NOT CONFIG_SECURE_BOOT) + set(flash_bootloader FLASH_IN_PROJECT) +endif() esptool_py_custom_target(bootloader-flash bootloader "bootloader") esptool_py_flash_target_image(bootloader-flash bootloader "0x1000" "${BOOTLOADER_BUILD_DIR}/bootloader.bin") # Also attach an image to the project flash target -if(NOT CONFIG_SECURE_BOOT_ENABLED) +if(NOT CONFIG_SECURE_BOOT) esptool_py_flash_target_image(flash bootloader "0x1000" "${BOOTLOADER_BUILD_DIR}/bootloader.bin") endif() \ No newline at end of file diff --git a/components/bootloader/Kconfig.projbuild b/components/bootloader/Kconfig.projbuild index df75c8e80c..cc64d89962 100644 --- a/components/bootloader/Kconfig.projbuild +++ b/components/bootloader/Kconfig.projbuild @@ -224,7 +224,7 @@ menu "Bootloader config" config BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP bool "Skip image validation when exiting deep sleep" - depends on (SECURE_BOOT_ENABLED && SECURE_BOOT_INSECURE) || !SECURE_BOOT_ENABLED + depends on (SECURE_BOOT && SECURE_BOOT_INSECURE) || !SECURE_BOOT default n help This option disables the normal validation of an image coming out of @@ -279,12 +279,12 @@ menu "Security features" config SECURE_SIGNED_ON_BOOT bool default y - depends on SECURE_BOOT_ENABLED || SECURE_SIGNED_ON_BOOT_NO_SECURE_BOOT + depends on SECURE_BOOT || SECURE_SIGNED_ON_BOOT_NO_SECURE_BOOT config SECURE_SIGNED_ON_UPDATE bool default y - depends on SECURE_BOOT_ENABLED || SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT + depends on SECURE_BOOT || SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT config SECURE_SIGNED_APPS bool @@ -298,8 +298,7 @@ menu "Security features" config SECURE_SIGNED_APPS_NO_SECURE_BOOT bool "Require signed app images" - default n - depends on !SECURE_BOOT_ENABLED + depends on !SECURE_BOOT help Require apps to be signed to verify their integrity. @@ -308,6 +307,35 @@ menu "Security features" against remote network access, but not physical access. Compared to using hardware Secure Boot this option is much simpler to implement. + choice SECURE_SIGNED_APPS_SCHEME + bool "App Signing Scheme" + depends on SECURE_BOOT || SECURE_SIGNED_APPS_NO_SECURE_BOOT + default SECURE_SIGNED_APPS_ECDSA_SCHEME if SECURE_BOOT_V1_ENABLED + default SECURE_SIGNED_APPS_RSA_SCHEME if SECURE_BOOT_V2_ENABLED + help + Select the Secure App signing scheme. Depends on the Chip Revision. + There are two options: + 1. ECDSA based secure boot scheme. (Only choice for Secure Boot V1) + Supported in ESP32 and ESP32-ECO3. + 2. The RSA based secure boot scheme. (Only choice for Secure Boot V2) + Supported in ESP32-ECO3. (ESP32 Chip Revision 3 onwards) + + config SECURE_SIGNED_APPS_ECDSA_SCHEME + bool "ECDSA" + depends on IDF_TARGET_ESP32 && (SECURE_SIGNED_APPS_NO_SECURE_BOOT || SECURE_BOOT_V1_ENABLED) + help + Embeds the ECDSA public key in the bootloader and signs the application with an ECDSA key. + + Refer to the documentation before enabling. + + config SECURE_SIGNED_APPS_RSA_SCHEME + bool "RSA" + depends on ESP32_REV_MIN_3 && SECURE_BOOT_V2_ENABLED + help + Appends the RSA-3072 based Signature block to the application. + Refer to before enabling. + endchoice + config SECURE_SIGNED_ON_BOOT_NO_SECURE_BOOT bool "Bootloader verifies app signatures" default n @@ -334,23 +362,48 @@ menu "Security features" If hardware secure boot is not enabled, this option still adds significant security against network-based attackers by preventing spoofing of OTA updates. - config SECURE_BOOT_ENABLED - bool "Enable hardware secure boot in bootloader (READ DOCS FIRST)" + config SECURE_BOOT + bool "Enable hardware Secure Boot in bootloader (READ DOCS FIRST)" default n help - Build a bootloader which enables secure boot on first boot. + Build a bootloader which enables Secure Boot on first boot. - Once enabled, secure boot will not boot a modified bootloader. The bootloader will only load a partition + 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. There are implications for reflashing updated apps once secure boot is enabled. When enabling secure boot, JTAG and ROM BASIC Interpreter are permanently disabled by default. - Refer to https://docs.espressif.com/projects/esp-idf/en/latest/security/secure-boot.html before enabling. + choice SECURE_BOOT_VERSION + bool "Select secure boot version" + default SECURE_BOOT_V2_ENABLED if ESP32_REV_MIN_3 + depends on SECURE_BOOT + help + Select the Secure Boot Version. Depends on the Chip Revision. + Secure Boot V2 is the new RSA based secure boot scheme. + Supported in ESP32-ECO3. (ESP32 Chip Revision 3 onwards) + Secure Boot V1 is the AES based secure boot scheme. + Supported in ESP32 and ESP32-ECO3. + + config SECURE_BOOT_V1_ENABLED + bool "Enable Secure Boot version 1" + depends on IDF_TARGET_ESP32 + help + Build a bootloader which enables secure boot version 1 on first boot. + Refer to the Secure Boot section of the ESP-IDF Programmer's Guide for this version before enabling. + + config SECURE_BOOT_V2_ENABLED + bool "Enable Secure Boot version 2" + depends on ESP32_REV_MIN_3 + help + Build a bootloader which enables Secure Boot version 2 on first boot. + Refer to Secure Boot V2 section of the ESP-IDF Programmer's Guide for this version before enabling. + + endchoice choice SECURE_BOOTLOADER_MODE bool "Secure bootloader mode" - depends on SECURE_BOOT_ENABLED + depends on SECURE_BOOT_V1_ENABLED default SECURE_BOOTLOADER_ONE_TIME_FLASH config SECURE_BOOTLOADER_ONE_TIME_FLASH @@ -385,7 +438,8 @@ menu "Security features" If enabled (default), 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 + If disabled, unsigned app/partition data will be built. They must be signed manually using espsecure.py. + Version 1 to enable ECDSA Based Secure Boot and Version 2 to enable RSA based Secure Boot. (for example, on a remote signing server.) config SECURE_BOOT_SIGNING_KEY @@ -395,28 +449,32 @@ menu "Security features" help Path to the key file used to sign app images. - Key file is an ECDSA private key (NIST256p curve) in PEM format. + Key file is an ECDSA private key (NIST256p curve) in PEM format for Secure Boot V1. + Key file is an RSA private key in PEM format for Secure Boot V2. Path is evaluated relative to the project directory. You can generate a new signing key by running the following command: espsecure.py generate_signing_key secure_boot_signing_key.pem - See https://docs.espressif.com/projects/esp-idf/en/latest/security/secure-boot.html for details. + See the Secure Boot section of the ESP-IDF Programmer's Guide for this version for details. config SECURE_BOOT_VERIFICATION_KEY string "Secure boot public signature verification key" - depends on SECURE_SIGNED_APPS && !SECURE_BOOT_BUILD_SIGNED_BINARIES + depends on SECURE_SIGNED_APPS && !SECURE_BOOT_BUILD_SIGNED_BINARIES && !SECURE_SIGNED_APPS_RSA_SCHEME 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/or + Path to a public key file used to verify signed images. + Secure Boot V1: This ECDSA public key is compiled into the bootloader and/or app, to verify app images. + Secure Boot V2: This RSA public key is compiled into the signature block at + the end of the bootloader/app. 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. - Refer to https://docs.espressif.com/projects/esp-idf/en/latest/security/secure-boot.html before enabling. + Refer to the Secure Boot section of the ESP-IDF Programmer's Guide for this version before enabling. choice SECURE_BOOTLOADER_KEY_ENCODING bool "Hardware Key Encoding" @@ -443,7 +501,7 @@ menu "Security features" config SECURE_BOOT_INSECURE bool "Allow potentially insecure options" - depends on SECURE_BOOT_ENABLED + depends on SECURE_BOOT default N help You can disable some of the default protections offered by secure boot, in order to enable testing or a @@ -451,7 +509,7 @@ menu "Security features" Only enable these options if you are very sure. - Refer to https://docs.espressif.com/projects/esp-idf/en/latest/security/secure-boot.html before enabling. + Refer to the Secure Boot section of the ESP-IDF Programmer's Guide for this version before enabling. config SECURE_FLASH_ENC_ENABLED bool "Enable flash encryption on boot (READ DOCS FIRST)" @@ -495,7 +553,7 @@ menu "Security features" Select Release mode only for production or manufacturing. Once enabled you can not reflash using UART bootloader - Refer to https://docs.espressif.com/projects/esp-idf/en/latest/security/secure-boot.html and + Refer to the Secure Boot section of the ESP-IDF Programmer's Guide for this version and https://docs.espressif.com/projects/esp-idf/en/latest/security/flash-encryption.html for details. config SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT diff --git a/components/bootloader/Makefile.projbuild b/components/bootloader/Makefile.projbuild index 1bbbf55298..60c1626caa 100644 --- a/components/bootloader/Makefile.projbuild +++ b/components/bootloader/Makefile.projbuild @@ -45,7 +45,7 @@ clean: bootloader-clean bootloader-list-components: $(BOOTLOADER_MAKE) list-components -ifndef CONFIG_SECURE_BOOT_ENABLED +ifndef CONFIG_SECURE_BOOT # If secure boot disabled, bootloader flashing is integrated # with 'make flash' and no warnings are printed. @@ -115,13 +115,35 @@ $(BOOTLOADER_DIGEST_BIN): $(BOOTLOADER_BIN) $(SECURE_BOOTLOADER_KEY) | check_pyt @echo "DIGEST $(notdir $@)" $(ESPSECUREPY) digest_secure_bootloader -k $(SECURE_BOOTLOADER_KEY) -o $@ $< -else # CONFIG_SECURE_BOOT_ENABLED && !CONFIG_SECURE_BOOTLOADER_REFLASHABLE && !CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH +else ifdef CONFIG_SECURE_BOOT_V2_ENABLED +BOOTLOADER_SIGNED_BIN := $(BOOTLOADER_BUILD_DIR)/bootloader-signed.bin +ifdef CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES +bootloader: $(BOOTLOADER_BIN) $(SDKCONFIG_MAKEFILE) | check_python_dependencies + $(ESPSECUREPY) sign_data --keyfile $(SECURE_BOOT_SIGNING_KEY) --version 2 \ + -o $(BOOTLOADER_SIGNED_BIN) $(BOOTLOADER_BIN) +else +bootloader: $(BOOTLOADER_BIN) $(SDKCONFIG_MAKEFILE) | check_python_dependencies + @echo "Bootloader not signed. Sign the bootloader before flashing." + @echo "To sign the bootloader, you can use this command:" + @echo "espsecure.py sign_data --keyfile SECURE_BOOT_SIGNING_KEY --version 2 $(BOOTLOADER_BIN)" +endif + @echo $(SEPARATOR) + @echo "Use the following command to flash the bootloader:" +ifdef CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES + @echo "$(ESPTOOLPY_WRITE_FLASH) $(BOOTLOADER_OFFSET) $(BOOTLOADER_SIGNED_BIN)" +else + @echo "$(ESPTOOLPY_WRITE_FLASH) $(BOOTLOADER_OFFSET) $(BOOTLOADER_BIN)" +endif + @echo $(SEPARATOR) + +else # CONFIG_SECURE_BOOT && !CONFIG_SECURE_BOOTLOADER_REFLASHABLE \ +&& !CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH && !CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME bootloader: @echo "Invalid bootloader target: bad sdkconfig?" @exit 1 endif -ifndef CONFIG_SECURE_BOOT_ENABLED +ifndef CONFIG_SECURE_BOOT # don't build bootloader by default if secure boot is enabled all_binaries: $(BOOTLOADER_BIN) endif @@ -131,3 +153,8 @@ bootloader-clean: $(SDKCONFIG_MAKEFILE) ifdef CONFIG_SECURE_BOOTLOADER_REFLASHABLE rm -f $(SECURE_BOOTLOADER_KEY) $(BOOTLOADER_DIGEST_BIN) endif +ifdef CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME +ifdef CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES + rm -f $(BOOTLOADER_SIGNED_BIN) +endif +endif \ No newline at end of file diff --git a/components/bootloader/project_include.cmake b/components/bootloader/project_include.cmake index 003a2b0b6a..8d34f70f32 100644 --- a/components/bootloader/project_include.cmake +++ b/components/bootloader/project_include.cmake @@ -19,8 +19,8 @@ set(bootloader_binary_files idf_build_get_property(project_dir PROJECT_DIR) -# There are some additional processing when CONFIG_CONFIG_SECURE_SIGNED_APPS. This happens -# when either CONFIG_SECURE_BOOT_ENABLED or SECURE_BOOT_BUILD_SIGNED_BINARIES. +# There are some additional processing when CONFIG_SECURE_SIGNED_APPS. This happens +# when either CONFIG_SECURE_BOOT_V1_ENABLED or CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES. # For both cases, the user either sets binaries to be signed during build or not # using CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES. # @@ -29,7 +29,13 @@ idf_build_get_property(project_dir PROJECT_DIR) if(CONFIG_SECURE_SIGNED_APPS) add_custom_target(gen_secure_boot_keys) - if(CONFIG_SECURE_BOOT_ENABLED) + if(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME) + set(secure_apps_signing_scheme "1") + elseif(CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME) + set(secure_apps_signing_scheme "2") + endif() + + if(CONFIG_SECURE_BOOT_V1_ENABLED) # Check that the configuration is sane if((CONFIG_SECURE_BOOTLOADER_REFLASHABLE AND CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH) OR (NOT CONFIG_SECURE_BOOTLOADER_REFLASHABLE AND NOT CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH)) @@ -60,7 +66,8 @@ if(CONFIG_SECURE_SIGNED_APPS) # (to pick up a new signing key if one exists, etc.) fail_at_build_time(gen_secure_boot_signing_key "Secure Boot Signing Key ${CONFIG_SECURE_BOOT_SIGNING_KEY} does not exist. Generate using:" - "\tespsecure.py generate_signing_key ${CONFIG_SECURE_BOOT_SIGNING_KEY}") + "\tespsecure.py generate_signing_key --version ${secure_apps_signing_scheme} \ + ${CONFIG_SECURE_BOOT_SIGNING_KEY}") else() add_custom_target(gen_secure_boot_signing_key) endif() @@ -70,7 +77,7 @@ if(CONFIG_SECURE_SIGNED_APPS) set(ver_key_arg) add_dependencies(gen_secure_boot_keys gen_secure_boot_signing_key) - else() + elseif(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME) get_filename_component(secure_boot_verification_key ${CONFIG_SECURE_BOOT_VERIFICATION_KEY} @@ -83,7 +90,7 @@ if(CONFIG_SECURE_SIGNED_APPS) fail_at_build_time(gen_secure_boot_verification_key "Secure Boot Verification Public Key ${CONFIG_SECURE_BOOT_VERIFICATION_KEY} does not exist." "\tThis can be extracted from the private signing key." - "\tSee docs/security/secure-boot.rst for details.") + "\tSee docs/security/secure-boot-v1.rst for details.") else() add_custom_target(gen_secure_boot_verification_key) endif() diff --git a/components/bootloader/sdkconfig.rename b/components/bootloader/sdkconfig.rename index 7d2277283a..bdcfe36487 100644 --- a/components/bootloader/sdkconfig.rename +++ b/components/bootloader/sdkconfig.rename @@ -20,3 +20,6 @@ CONFIG_FLASH_ENCRYPTION_INSECURE CONFIG_SECURE_FLASH_ CONFIG_FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_ENCRYPT CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC CONFIG_FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_DECRYPT CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_DEC CONFIG_FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_CACHE CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_CACHE + +# Secure Boot Scheme +CONFIG_SECURE_BOOT_ENABLED CONFIG_SECURE_BOOT_V1_ENABLED diff --git a/components/bootloader/subproject/CMakeLists.txt b/components/bootloader/subproject/CMakeLists.txt index 2133518702..06c0b26b83 100644 --- a/components/bootloader/subproject/CMakeLists.txt +++ b/components/bootloader/subproject/CMakeLists.txt @@ -90,6 +90,39 @@ if(CONFIG_SECURE_BOOTLOADER_REFLASHABLE) add_custom_target (gen_bootloader_digest_bin ALL DEPENDS "${bootloader_digest_bin}") endif() +if(CONFIG_SECURE_BOOT_V2_ENABLED) + if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES) + get_filename_component(secure_boot_signing_key + "${SECURE_BOOT_SIGNING_KEY}" ABSOLUTE BASE_DIR "${project_dir}") + + if(NOT EXISTS "${secure_boot_signing_key}") + message(FATAL_ERROR + "Secure Boot Signing Key Not found." + "\nGenerate the Secure Boot V2 RSA-PSS 3072 Key." + "\nTo generate one, you can use this command:" + "\n\t${espsecurepy} generate_signing_key --version 2 ${SECURE_BOOT_SIGNING_KEY}") + endif() + + set(bootloader_unsigned_bin "bootloader-unsigned.bin") + add_custom_command(OUTPUT ".signed_bin_timestamp" + COMMAND cp "${CMAKE_BINARY_DIR}/${PROJECT_BIN}" "${CMAKE_BINARY_DIR}/${bootloader_unsigned_bin}" + COMMAND ${ESPSECUREPY} sign_data --version 2 --keyfile "${secure_boot_signing_key}" + -o "${CMAKE_BINARY_DIR}/${PROJECT_BIN}" "${CMAKE_BINARY_DIR}/${bootloader_unsigned_bin}" + COMMAND ${CMAKE_COMMAND} -E echo "Generated signed binary image ${build_dir}/${PROJECT_BIN}" + "from ${CMAKE_BINARY_DIR}/${bootloader_unsigned_bin}" + COMMAND ${CMAKE_COMMAND} -E md5sum "${CMAKE_BINARY_DIR}/${PROJECT_BIN}" > "${CMAKE_BINARY_DIR}/.signed_bin_timestamp" + DEPENDS "${build_dir}/.bin_timestamp" + VERBATIM + COMMENT "Generated the signed Bootloader") + else() + add_custom_command(OUTPUT ".signed_bin_timestamp" + VERBATIM + COMMENT "Bootloader generated but not signed") + endif() + + add_custom_target (gen_signed_bootloader ALL DEPENDS "${build_dir}/.signed_bin_timestamp") +endif() + if(CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH) add_custom_command(TARGET bootloader.elf POST_BUILD COMMAND ${CMAKE_COMMAND} -E echo @@ -133,4 +166,18 @@ elseif(CONFIG_SECURE_BOOTLOADER_REFLASHABLE) "* Not recommended to re-use the same secure boot keyfile on multiple production devices." DEPENDS gen_secure_bootloader_key gen_bootloader_digest_bin VERBATIM) +elseif(CONFIG_SECURE_BOOT_V2_ENABLED) + add_custom_command(TARGET bootloader.elf POST_BUILD + COMMAND ${CMAKE_COMMAND} -E echo + "==============================================================================" + COMMAND ${CMAKE_COMMAND} -E echo + "Bootloader built. Secure boot enabled, so bootloader not flashed automatically." + COMMAND ${CMAKE_COMMAND} -E echo + "Secure boot enabled, so bootloader not flashed automatically." + COMMAND ${CMAKE_COMMAND} -E echo + "\t${esptoolpy_write_flash} ${BOOTLOADER_OFFSET} ${CMAKE_BINARY_DIR}/bootloader.bin" + COMMAND ${CMAKE_COMMAND} -E echo + "==============================================================================" + DEPENDS gen_signed_bootloader + VERBATIM) endif() diff --git a/components/bootloader/subproject/main/component.mk b/components/bootloader/subproject/main/component.mk index 535b78e6aa..9745b6a713 100644 --- a/components/bootloader/subproject/main/component.mk +++ b/components/bootloader/subproject/main/component.mk @@ -17,6 +17,9 @@ ifdef CONFIG_IDF_TARGET_ESP32 ifndef CONFIG_SPI_FLASH_ROM_DRIVER_PATCH LINKER_SCRIPTS += $(IDF_PATH)/components/esp_rom/$(IDF_TARGET)/ld/$(IDF_TARGET).rom.spiflash.ld endif + ifdef CONFIG_ESP32_REV_MIN_3 + LINKER_SCRIPTS += $(IDF_PATH)/components/esp_rom/$(IDF_TARGET)/ld/$(IDF_TARGET).rom.eco3.ld + endif endif COMPONENT_ADD_LDFLAGS += -L $(COMPONENT_PATH) $(addprefix -T ,$(LINKER_SCRIPTS)) diff --git a/components/bootloader_support/CMakeLists.txt b/components/bootloader_support/CMakeLists.txt index a207084d00..f48430c72b 100644 --- a/components/bootloader_support/CMakeLists.txt +++ b/components/bootloader_support/CMakeLists.txt @@ -20,22 +20,34 @@ if(BOOTLOADER_BUILD) set(include_dirs "include" "include_bootloader") set(priv_requires micro-ecc spi_flash efuse) list(APPEND srcs - "src/bootloader_init.c" - "src/${IDF_TARGET}/bootloader_sha.c" - "src/${IDF_TARGET}/flash_encrypt.c" - "src/${IDF_TARGET}/secure_boot_signatures.c" - "src/${IDF_TARGET}/secure_boot.c" - "src/${IDF_TARGET}/bootloader_${IDF_TARGET}.c" - ) + "src/bootloader_init.c" + "src/${IDF_TARGET}/bootloader_sha.c" + "src/${IDF_TARGET}/flash_encrypt.c" + "src/${IDF_TARGET}/bootloader_${IDF_TARGET}.c" + ) else() list(APPEND srcs - "src/idf/bootloader_sha.c" - "src/idf/secure_boot_signatures.c") + "src/idf/bootloader_sha.c") set(include_dirs "include") set(priv_include_dirs "include_bootloader") set(priv_requires spi_flash mbedtls efuse) endif() +if(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME OR CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME) + if(BOOTLOADER_BUILD) + list(APPEND srcs + "src/${IDF_TARGET}/secure_boot_signatures.c") + else() + list(APPEND srcs + "src/idf/secure_boot_signatures.c") + endif() +endif() + +if(CONFIG_SECURE_BOOT AND BOOTLOADER_BUILD) + list(APPEND srcs + "src/${IDF_TARGET}/secure_boot.c") +endif() + set(requires soc) #unfortunately the header directly uses SOC registers idf_component_register(SRCS "${srcs}" @@ -44,7 +56,7 @@ idf_component_register(SRCS "${srcs}" REQUIRES "${requires}" PRIV_REQUIRES "${priv_requires}") -if(CONFIG_SECURE_SIGNED_APPS) +if(CONFIG_SECURE_SIGNED_APPS AND (CONFIG_SECURE_BOOT_V1_ENABLED OR CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME)) if(BOOTLOADER_BUILD) # Whether CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES or not, we need verification key to embed # in the library. diff --git a/components/bootloader_support/component.mk b/components/bootloader_support/component.mk index 538cacfa79..aab6890ec2 100644 --- a/components/bootloader_support/component.mk +++ b/components/bootloader_support/component.mk @@ -22,11 +22,23 @@ endif COMPONENT_OBJEXCLUDE += src/bootloader_flash_config_esp32s2.o \ src/bootloader_efuse_esp32s2.o +ifndef CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME +ifndef CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME +COMPONENT_OBJEXCLUDE += src/$(IDF_TARGET)/secure_boot_signatures.o \ + src/idf/secure_boot_signatures.o +endif +endif + +ifndef CONFIG_SECURE_BOOT +COMPONENT_OBJEXCLUDE += src/$(IDF_TARGET)/secure_boot.o +endif + # # Secure boot signing key support # ifdef CONFIG_SECURE_SIGNED_APPS +ifdef CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME # this path is created relative to the component build directory SECURE_BOOT_VERIFICATION_KEY := $(abspath signature_verification_key.bin) @@ -41,7 +53,7 @@ ORIG_SECURE_BOOT_VERIFICATION_KEY := $(call resolvepath,$(call dequote,$(CONFIG_ $(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." + @echo "docs/security/secure-boot-v1.rst for details." exit 1 # copy it into the build dir, so the secure boot verification key has @@ -55,4 +67,5 @@ COMPONENT_EXTRA_CLEAN += $(SECURE_BOOT_VERIFICATION_KEY) COMPONENT_EMBED_FILES := $(SECURE_BOOT_VERIFICATION_KEY) +endif #CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME endif #CONFIG_SECURE_SIGNED_APPS diff --git a/components/bootloader_support/include/esp_secure_boot.h b/components/bootloader_support/include/esp_secure_boot.h index 389b19b51e..59b81df14f 100644 --- a/components/bootloader_support/include/esp_secure_boot.h +++ b/components/bootloader_support/include/esp_secure_boot.h @@ -16,13 +16,16 @@ #include #include #include "soc/efuse_periph.h" +#include "esp_image_format.h" #include "sdkconfig.h" #if CONFIG_IDF_TARGET_ESP32S2 #include "esp32s2/rom/efuse.h" +#else +#include "esp32/rom/secure_boot.h" #endif -#ifdef CONFIG_SECURE_BOOT_ENABLED +#ifdef CONFIG_SECURE_BOOT_V1_ENABLED #if !defined(CONFIG_SECURE_SIGNED_ON_BOOT) || !defined(CONFIG_SECURE_SIGNED_ON_UPDATE) || !defined(CONFIG_SECURE_SIGNED_APPS) #error "internal sdkconfig error, secure boot should always enable all signature options" #endif @@ -47,16 +50,23 @@ extern "C" { static inline bool esp_secure_boot_enabled(void) { #if CONFIG_IDF_TARGET_ESP32 - return REG_READ(EFUSE_BLK0_RDATA6_REG) & EFUSE_RD_ABS_DONE_0; + #ifdef CONFIG_SECURE_BOOT_V1_ENABLED + return REG_READ(EFUSE_BLK0_RDATA6_REG) & EFUSE_RD_ABS_DONE_0; + #elif CONFIG_SECURE_BOOT_V2_ENABLED + return ets_use_secure_boot_v2(); + #endif #elif CONFIG_IDF_TARGET_ESP32S2 return ets_efuse_secure_boot_enabled(); #endif + return false; /* Secure Boot not enabled in menuconfig */ } /** @brief Generate secure digest from bootloader image * * @important This function is intended to be called from bootloader code only. * + * This function is only used in the context of the Secure Boot V1 scheme. + * * If secure boot is not yet enabled for bootloader, this will: * 1) generate the secure boot key and burn it on EFUSE * (without enabling R/W protection) @@ -73,18 +83,17 @@ static inline bool esp_secure_boot_enabled(void) */ esp_err_t esp_secure_boot_generate_digest(void); -/** @brief Enable secure boot if it is not already enabled. +/** @brief Enable secure boot V1 if it is not already enabled. * - * @important If this function succeeds, secure boot is permanently + * @important If this function succeeds, secure boot V1 is permanently * enabled on the chip via efuse. * * @important This function is intended to be called from bootloader code only. * - * @important This will enable r/w protection of secure boot key on EFUSE, - * therefore it is to be ensured that esp_secure_boot_generate_digest() - * is called before this - * - * If secure boot is not yet enabled for bootloader, this will + * @important In case of Secure Boot V1, this will enable r/w protection + * of secure boot key on EFUSE, therefore it is to be ensured that + * esp_secure_boot_generate_digest() is called before this .If secure boot is not + * yet enabled for bootloader, this will * 1) enable R/W protection of secure boot key on EFUSE * 2) enable secure boot by blowing the EFUSE_RD_ABS_DONE_0 efuse. * @@ -100,9 +109,40 @@ esp_err_t esp_secure_boot_generate_digest(void); */ esp_err_t esp_secure_boot_permanently_enable(void); -/** @brief Verify the secure boot signature (determinstic ECDSA w/ SHA256) appended to some binary data in flash. +/** @brief Enables secure boot V2 if it is not already enabled. * - * Public key is compiled into the calling program. See docs/security/secure-boot.rst for details. + * @important If this function succeeds, secure boot V2 is permanently + * enabled on the chip via efuse. + * + * @important This function is intended to be called from bootloader code only. + * + * @important In case of Secure Boot V2, this will enable write protection + * of secure boot key on EFUSE in BLK2. .If secure boot is not + * yet enabled for bootloader, this will + * 1) enable W protection of secure boot key on EFUSE + * 2) enable secure boot by blowing the EFUSE_RD_ABS_DONE_1 efuse. + * + * This function does not verify secure boot of the bootloader (the + * ROM bootloader does this.) + * + * @param image_data Image metadata of the application to be loaded. + * + * Will fail if efuses have been part-burned in a way that indicates + * secure boot should not or could not be correctly enabled. + * + * @return ESP_ERR_INVALID_STATE if efuse state doesn't allow + * secure boot to be enabled cleanly. ESP_OK if secure boot + * is enabled on this chip from now on. + */ +esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *image_data); + +/** @brief Verify the secure boot signature appended to some binary data in flash. + * + * For ECDSA Scheme (Secure Boot V1) - deterministic ECDSA w/ SHA256 image + * For RSA Scheme (Secure Boot V2) - RSA-PSS Verification of the SHA-256 image + * + * Public key is compiled into the calling program in the ECDSA Scheme. + * See the apt docs/security/secure-boot-v1.rst or docs/security/secure-boot-v2.rst for details. * * @param src_addr Starting offset of the data in flash. * @param length Length of data in bytes. Signature is appended -after- length bytes. @@ -114,21 +154,28 @@ esp_err_t esp_secure_boot_permanently_enable(void); */ esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length); -/** @brief Verify the secure boot signature block (deterministic ECDSA w/ SHA256) based on the SHA256 hash of some data. - * - * Similar to esp_secure_boot_verify_signature(), but can be used when the digest is precalculated. - * @param sig_block Pointer to signature block data - * @param image_digest Pointer to 32 byte buffer holding SHA-256 hash. - * - */ - /** @brief Secure boot verification block, on-flash data format. */ typedef struct { uint32_t version; uint8_t signature[64]; } esp_secure_boot_sig_block_t; +/** @brief Verify the secure boot signature block. + * + * For ECDSA Scheme (Secure Boot V1) - Deterministic ECDSA w/ SHA256 based on the SHA256 hash of the image. + * For RSA Scheme (Secure Boot V2) - RSA-PSS Verification of the SHA-256 image based on the public key + * in the signature block. + * + * Similar to esp_secure_boot_verify_signature(), but can be used when the digest is precalculated. + * @param sig_block Pointer to RSA or ECDSA signature block data + * @param image_digest Pointer to 32 byte buffer holding SHA-256 hash. + * + */ +#ifdef CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME esp_err_t esp_secure_boot_verify_signature_block(const esp_secure_boot_sig_block_t *sig_block, const uint8_t *image_digest); +#elif CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME +esp_err_t esp_secure_boot_verify_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest); +#endif #define FLASH_OFFS_SECURE_BOOT_IV_DIGEST 0 diff --git a/components/bootloader_support/include_bootloader/bootloader_flash.h b/components/bootloader_support/include_bootloader/bootloader_flash.h index 12bef10b36..6482dde99e 100644 --- a/components/bootloader_support/include_bootloader/bootloader_flash.h +++ b/components/bootloader_support/include_bootloader/bootloader_flash.h @@ -18,9 +18,11 @@ #include #include #include +#include /* including in bootloader for error values */ #define FLASH_SECTOR_SIZE 0x1000 #define FLASH_BLOCK_SIZE 0x10000 +#define MMAP_ALIGNED_MASK 0x0000FFFF /* Provide a Flash API for bootloader_support code, that can be used from bootloader or app code. diff --git a/components/bootloader_support/include_bootloader/bootloader_utility.h b/components/bootloader_support/include_bootloader/bootloader_utility.h index d505e17e71..40af41e544 100644 --- a/components/bootloader_support/include_bootloader/bootloader_utility.h +++ b/components/bootloader_support/include_bootloader/bootloader_utility.h @@ -108,3 +108,17 @@ esp_err_t bootloader_sha256_hex_to_str(char *out_str, const uint8_t *in_array_he * @param label Label to print at beginning of log line. */ void bootloader_debug_buffer(const void *buffer, size_t length, const char *label); + +/** @brief Generates the digest of the data between offset & offset+length. + * + * This function should be used when the size of the data is larger than 3.2MB. + * The MMU capacity is 3.2MB (50 pages - 64KB each). This function generates the SHA-256 + * of the data in chunks of 3.2MB, considering the MMU capacity. + * + * @param[in] flash_offset Offset of the data in flash. + * @param[in] len Length of data in bytes. + * @param[out] digest Pointer to buffer where the digest is written, if ESP_OK is returned. + * + * @return ESP_OK if secure boot digest is generated successfully. + */ +esp_err_t bootloader_sha256_flash_contents(uint32_t flash_offset, uint32_t len, uint8_t *digest); diff --git a/components/bootloader_support/src/bootloader_flash.c b/components/bootloader_support/src/bootloader_flash.c index 02fc3e752b..9aadb8fc14 100644 --- a/components/bootloader_support/src/bootloader_flash.c +++ b/components/bootloader_support/src/bootloader_flash.c @@ -15,7 +15,6 @@ #include #include -#include /* including in bootloader for error values */ #include #if CONFIG_IDF_TARGET_ESP32S2 #include "esp32s2/rom/spi_flash.h" diff --git a/components/bootloader_support/src/bootloader_utility.c b/components/bootloader_support/src/bootloader_utility.c index 2b8c1497a4..d36ef1802d 100644 --- a/components/bootloader_support/src/bootloader_utility.c +++ b/components/bootloader_support/src/bootloader_utility.c @@ -557,11 +557,19 @@ static void load_image(const esp_image_metadata_t *image_data) * then Step 6 enables secure boot. */ -#if defined(CONFIG_SECURE_BOOT_ENABLED) || defined(CONFIG_SECURE_FLASH_ENC_ENABLED) +#if defined(CONFIG_SECURE_BOOT) || defined(CONFIG_SECURE_FLASH_ENC_ENABLED) esp_err_t err; #endif -#ifdef CONFIG_SECURE_BOOT_ENABLED +#ifdef CONFIG_SECURE_BOOT_V2_ENABLED + err = esp_secure_boot_v2_permanently_enable(image_data); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Secure Boot v2 failed (%d)", err); + return; + } +#endif + +#ifdef CONFIG_SECURE_BOOT_V1_ENABLED /* Steps 1 & 2 (see above for full description): * 1) Generate secure boot EFUSE key * 2) Compute digest of plaintext bootloader @@ -588,7 +596,7 @@ static void load_image(const esp_image_metadata_t *image_data) } #endif -#ifdef CONFIG_SECURE_BOOT_ENABLED +#ifdef CONFIG_SECURE_BOOT_V1_ENABLED /* Step 6 (see above for full description): * 6) Burn EFUSE to enable secure boot */ @@ -810,3 +818,37 @@ void bootloader_debug_buffer(const void *buffer, size_t length, const char *labe ESP_LOGD(TAG, "%s: %s", label, hexbuf); #endif } + +esp_err_t bootloader_sha256_flash_contents(uint32_t flash_offset, uint32_t len, uint8_t *digest) +{ + if (digest == NULL) { + return ESP_ERR_INVALID_ARG; + } + + /* Handling firmware images larger than MMU capacity */ + uint32_t mmu_free_pages_count = bootloader_mmap_get_free_pages(); + bootloader_sha256_handle_t sha_handle = NULL; + + sha_handle = bootloader_sha256_start(); + if (sha_handle == NULL) { + return ESP_ERR_NO_MEM; + } + + while (len > 0) { + uint32_t mmu_page_offset = ((flash_offset & MMAP_ALIGNED_MASK) != 0) ? 1 : 0; /* Skip 1st MMU Page if it is already populated */ + uint32_t partial_image_len = MIN(len, ((mmu_free_pages_count - mmu_page_offset) * SPI_FLASH_MMU_PAGE_SIZE)); /* Read the image that fits in the free MMU pages */ + + const void * image = bootloader_mmap(flash_offset, partial_image_len); + if (image == NULL) { + bootloader_sha256_finish(sha_handle, NULL); + return ESP_FAIL; + } + bootloader_sha256_data(sha_handle, image, partial_image_len); + bootloader_munmap(image); + + flash_offset += partial_image_len; + len -= partial_image_len; + } + bootloader_sha256_finish(sha_handle, digest); + return ESP_OK; +} diff --git a/components/bootloader_support/src/esp32/flash_encrypt.c b/components/bootloader_support/src/esp32/flash_encrypt.c index 5c72636db8..93bed505c9 100644 --- a/components/bootloader_support/src/esp32/flash_encrypt.c +++ b/components/bootloader_support/src/esp32/flash_encrypt.c @@ -242,7 +242,7 @@ static esp_err_t encrypt_bootloader(void) return err; } -#ifdef CONFIG_SECURE_BOOT_ENABLED +#ifdef CONFIG_SECURE_BOOT_V1_ENABLED /* If secure boot is enabled and bootloader was plaintext, also * need to encrypt secure boot IV+digest. */ diff --git a/components/bootloader_support/src/esp32/secure_boot.c b/components/bootloader_support/src/esp32/secure_boot.c index 023d281426..0a2c573b28 100644 --- a/components/bootloader_support/src/esp32/secure_boot.c +++ b/components/bootloader_support/src/esp32/secure_boot.c @@ -20,10 +20,12 @@ #include "esp32/rom/cache.h" #include "esp32/rom/ets_sys.h" -#include "esp32/rom/secure_boot.h" +#include "esp32/rom/crc.h" #include "soc/efuse_periph.h" #include "soc/rtc_periph.h" +#include "bootloader_sha.h" +#include "bootloader_utility.h" #include "sdkconfig.h" @@ -37,9 +39,14 @@ /* The following API implementations are used only when called * from the bootloader code. */ +/* Burn values written to the efuse write registers */ +static inline void burn_efuses(void) +{ + esp_efuse_burn_new_values(); +} -static const char* TAG = "secure_boot"; - +#ifdef CONFIG_SECURE_BOOT_V1_ENABLED +static const char *TAG = "secure_boot_v1"; /** * @function : secure_boot_generate * @description: generate boot digest (aka "abstract") & iv @@ -94,12 +101,6 @@ static bool secure_boot_generate(uint32_t image_len){ return true; } -/* Burn values written to the efuse write registers */ -static inline void burn_efuses(void) -{ - esp_efuse_burn_new_values(); -} - esp_err_t esp_secure_boot_generate_digest(void) { esp_err_t err; @@ -219,3 +220,188 @@ esp_err_t esp_secure_boot_permanently_enable(void) return ESP_ERR_INVALID_STATE; } } +#elif CONFIG_SECURE_BOOT_V2_ENABLED + +#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1)) +static const char *TAG = "secure_boot_v2"; + +#define SIG_BLOCK_MAGIC_BYTE 0xe7 +#define CRC_SIGN_BLOCK_LEN 1196 +#define SIG_BLOCK_PADDING 4096 + +#define DIGEST_LEN 32 + +static esp_err_t validate_signature_block(const ets_secure_boot_signature_t *sig_block, uint8_t *digest) +{ + uint32_t crc = crc32_le(0, (uint8_t *)sig_block, CRC_SIGN_BLOCK_LEN); + if (sig_block->block[0].magic_byte == SIG_BLOCK_MAGIC_BYTE && sig_block->block[0].block_crc == crc && !memcmp(digest, sig_block->block[0].image_digest, DIGEST_LEN)) { + ESP_LOGI(TAG, "valid signature block found"); + return ESP_OK; + } + return ESP_FAIL; +} + +static esp_err_t secure_boot_v2_digest_generate(uint32_t flash_offset, uint32_t flash_size, uint8_t *public_key_digest) +{ + esp_err_t ret = ESP_FAIL; + + uint8_t image_digest[DIGEST_LEN] = {0}; + size_t sig_block_addr = flash_offset + ALIGN_UP(flash_size, FLASH_SECTOR_SIZE); + ret = bootloader_sha256_flash_contents(flash_offset, sig_block_addr - flash_offset, image_digest); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "error generating image digest, %d", ret); + return ret; + } + + ESP_LOGD(TAG, "reading signature block"); + const ets_secure_boot_signature_t *sig_block = bootloader_mmap(sig_block_addr, sizeof(ets_secure_boot_signature_t)); + if (sig_block == NULL) { + ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", sig_block_addr, sizeof(ets_secure_boot_signature_t)); + return ret; + } + + /* Validating Signature block */ + ret = validate_signature_block(sig_block, image_digest); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "signature block validation failed %d", ret); + goto done; + } + + /* Verifying Signature block */ + uint8_t verified_digest[DIGEST_LEN] = {0}; + + /* Generating the SHA of the public key components in the signature block */ + bootloader_sha256_handle_t sig_block_sha; + sig_block_sha = bootloader_sha256_start(); + bootloader_sha256_data(sig_block_sha, &sig_block->block[0].key, sizeof(sig_block->block[0].key)); + bootloader_sha256_finish(sig_block_sha, public_key_digest); + + secure_boot_v2_status_t error; + error = ets_secure_boot_verify_signature(sig_block, image_digest, public_key_digest, verified_digest); + if (error != SBV2_SUCCESS) { + ESP_LOGE(TAG, "secure boot v2 verification failed %d", error); + ret = ESP_FAIL; + goto done; + } else { + ret = ESP_OK; + } + +done: + bootloader_munmap(sig_block); + return ret; +} + +esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *image_data) +{ + ESP_LOGI(TAG, "enabling secure boot v2..."); + esp_err_t ret; + if (esp_secure_boot_enabled()) { + ESP_LOGI(TAG, "secure boot v2 is already enabled. Continuing.."); + return ESP_OK; + } + + uint32_t coding_scheme = REG_GET_FIELD(EFUSE_BLK0_RDATA6_REG, EFUSE_CODING_SCHEME); + if (coding_scheme != EFUSE_CODING_SCHEME_VAL_NONE) { + ESP_LOGE(TAG, "No coding schemes are supported in secure boot v2.(Detected scheme: 0x%x)", coding_scheme); + return ESP_ERR_NOT_SUPPORTED; + } + + /* Verify the bootloader */ + esp_image_metadata_t bootloader_data = { 0 }; + ret = esp_image_verify_bootloader_data(&bootloader_data); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "bootloader image appears invalid! error %d", ret); + return ret; + } + + uint8_t boot_pub_key_digest[DIGEST_LEN]; + uint32_t dis_reg = REG_READ(EFUSE_BLK0_RDATA0_REG); + bool efuse_key_read_protected = dis_reg & EFUSE_RD_DIS_BLK2; + bool efuse_key_write_protected = dis_reg & EFUSE_WR_DIS_BLK2; + if (efuse_key_write_protected == false + && efuse_key_read_protected == false + && REG_READ(EFUSE_BLK2_RDATA0_REG) == 0 + && REG_READ(EFUSE_BLK2_RDATA1_REG) == 0 + && REG_READ(EFUSE_BLK2_RDATA2_REG) == 0 + && REG_READ(EFUSE_BLK2_RDATA3_REG) == 0 + && REG_READ(EFUSE_BLK2_RDATA4_REG) == 0 + && REG_READ(EFUSE_BLK2_RDATA5_REG) == 0 + && REG_READ(EFUSE_BLK2_RDATA6_REG) == 0 + && REG_READ(EFUSE_BLK2_RDATA7_REG) == 0) { + /* Verifies the signature block appended to the image matches with the signature block of the app to be loaded */ + ret = secure_boot_v2_digest_generate(bootloader_data.start_addr, bootloader_data.image_len, boot_pub_key_digest); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Public key digest generation failed"); + return ret; + } + + ESP_LOGI(TAG, "Burning public key hash to efuse."); + uint32_t *boot_public_key_digest_ptr = (uint32_t *) boot_pub_key_digest; + for (int i = 0; i < 8 ; i++) { + REG_WRITE(EFUSE_BLK2_WDATA0_REG + 4 * i, boot_public_key_digest_ptr[i]); + ESP_LOGD(TAG, "EFUSE_BLKx_WDATA%d_REG = 0x%08x", i, boot_public_key_digest_ptr[i]); + } + + ESP_LOGI(TAG, "Write protecting public key digest..."); + REG_WRITE(EFUSE_BLK0_WDATA0_REG, EFUSE_WR_DIS_BLK2); + efuse_key_write_protected = true; + efuse_key_read_protected = false; + } else { + ESP_LOGW(TAG, "Using pre-loaded secure boot v2 public key digest in EFUSE block 2"); + } + + uint8_t app_pub_key_digest[DIGEST_LEN]; + ret = secure_boot_v2_digest_generate(image_data->start_addr, image_data->image_len - SIG_BLOCK_PADDING, app_pub_key_digest); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Application signature block is invalid."); + return ret; + } + + /* Confirming if the public key in the bootloader's signature block matches with the one in the application's signature block */ + if (memcmp(boot_pub_key_digest, app_pub_key_digest, DIGEST_LEN) != 0) { + ESP_LOGE(TAG, "Application not signed with a valid private key."); + return ESP_FAIL; + } + + if (efuse_key_read_protected) { + ESP_LOGE(TAG, "Efuse BLK2 (public key digest) is read protected. Refusing to blow secure boot efuse."); + return ESP_ERR_INVALID_STATE; + } + if (!efuse_key_write_protected) { + ESP_LOGE(TAG, "Efuse BLK2 (public key digest) is not write protected. Refusing to blow secure boot efuse."); + return ESP_ERR_INVALID_STATE; + } + + 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_1; + +#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 + +#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(); + uint32_t after = REG_READ(EFUSE_BLK0_RDATA6_REG); + ESP_LOGD(TAG, "after updating, EFUSE_BLK0_RDATA6 %x", after); + if (after & EFUSE_RD_ABS_DONE_1) { + ESP_LOGI(TAG, "secure boot v2 is now enabled."); + return ESP_OK; + } else { + ESP_LOGE(TAG, " secure boot v2 not enabled, EFUSE_RD_ABS_DONE_1 is probably write protected!"); + return ESP_ERR_INVALID_STATE; + } +} + +#endif // CONFIG_SECURE_BOOT_V2_ENABLED diff --git a/components/bootloader_support/src/esp32/secure_boot_signatures.c b/components/bootloader_support/src/esp32/secure_boot_signatures.c index 6b54aa40c8..00ecdcdfb8 100644 --- a/components/bootloader_support/src/esp32/secure_boot_signatures.c +++ b/components/bootloader_support/src/esp32/secure_boot_signatures.c @@ -15,6 +15,7 @@ #include "bootloader_flash.h" #include "bootloader_sha.h" +#include "bootloader_utility.h" #include "esp_log.h" #include "esp_image_format.h" #include "esp_secure_boot.h" @@ -23,54 +24,29 @@ #include "uECC.h" #include +#include static const char *TAG = "secure_boot"; +#define DIGEST_LEN 32 +#ifdef CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME extern const uint8_t signature_verification_key_start[] asm("_binary_signature_verification_key_bin_start"); extern const uint8_t signature_verification_key_end[] asm("_binary_signature_verification_key_bin_end"); #define SIGNATURE_VERIFICATION_KEYLEN 64 -#define DIGEST_LEN 32 - -/* Mmap source address mask */ -#define MMAP_ALIGNED_MASK 0x0000FFFF - esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length) { uint8_t digest[DIGEST_LEN]; - const uint8_t *data; const esp_secure_boot_sig_block_t *sigblock; ESP_LOGD(TAG, "verifying signature src_addr 0x%x length 0x%x", src_addr, length); - - bootloader_sha256_handle_t handle = bootloader_sha256_start(); - - uint32_t free_page_count = bootloader_mmap_get_free_pages(); - ESP_LOGD(TAG, "free data page_count 0x%08x", free_page_count); - - int32_t data_len_remain = length; - uint32_t data_addr = src_addr; - while (data_len_remain > 0) { - uint32_t offset_page = ((data_addr & MMAP_ALIGNED_MASK) != 0) ? 1 : 0; - /* Data we could map in case we are not aligned to PAGE boundary is one page size lesser. */ - uint32_t data_len = MIN(data_len_remain, ((free_page_count - offset_page) * SPI_FLASH_MMU_PAGE_SIZE)); - data = (const uint8_t *) bootloader_mmap(data_addr, data_len); - if(!data) { - ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", data_addr, data_len); - bootloader_sha256_finish(handle, NULL); - return ESP_FAIL; - } - bootloader_sha256_data(handle, data, data_len); - bootloader_munmap(data); - - data_addr += data_len; - data_len_remain -= data_len; + + esp_err_t err = bootloader_sha256_flash_contents(src_addr, length, digest); + if (err != ESP_OK) { + return err; } - /* Done! Get the digest */ - bootloader_sha256_finish(handle, digest); - // Map the signature block sigblock = (const esp_secure_boot_sig_block_t *) bootloader_mmap(src_addr + length, sizeof(esp_secure_boot_sig_block_t)); if(!sigblock) { @@ -78,7 +54,7 @@ esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length) return ESP_FAIL; } // Verify the signature - esp_err_t err = esp_secure_boot_verify_signature_block(sigblock, digest); + err = esp_secure_boot_verify_signature_block(sigblock, digest); // Unmap bootloader_munmap(sigblock); @@ -111,3 +87,72 @@ esp_err_t esp_secure_boot_verify_signature_block(const esp_secure_boot_sig_block ESP_LOGD(TAG, "Verification result %d", is_valid); return is_valid ? ESP_OK : ESP_ERR_IMAGE_INVALID; } + +#elif CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME +#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1)) + +esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length) +{ + uint8_t digest[DIGEST_LEN] = {0}; + const uint8_t *data; + + /* Padding to round off the input to the nearest 4k boundary */ + int padded_length = ALIGN_UP(length, FLASH_SECTOR_SIZE); + ESP_LOGD(TAG, "verifying src_addr 0x%x length", src_addr, padded_length); + + data = bootloader_mmap(src_addr, padded_length + sizeof(ets_secure_boot_signature_t)); + if (data == NULL) { + ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", src_addr, padded_length); + return ESP_FAIL; + } + + /* Calculate digest of main image */ + esp_err_t err = bootloader_sha256_flash_contents(src_addr, padded_length, digest); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Digest calculation failed 0x%x, 0x%x", src_addr, padded_length); + bootloader_munmap(data); + return err; + } + + const ets_secure_boot_signature_t *sig_block = (const ets_secure_boot_signature_t *)(data + padded_length); + err = esp_secure_boot_verify_signature_block(sig_block, digest); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Secure Boot V2 verification failed."); + } + + bootloader_munmap(data); + return err; +} + +esp_err_t esp_secure_boot_verify_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest) +{ + uint8_t efuse_trusted_digest[DIGEST_LEN] = {0}, sig_block_trusted_digest[DIGEST_LEN] = {0}, verified_digest[DIGEST_LEN] = {0}; + + secure_boot_v2_status_t r; + memcpy(efuse_trusted_digest, (uint8_t *)EFUSE_BLK2_RDATA0_REG, DIGEST_LEN); /* EFUSE_BLK2_RDATA0_REG - Stores the Secure Boot Public Key Digest */ + + if (!ets_use_secure_boot_v2()) { + ESP_LOGI(TAG, "Secure Boot EFuse bit(ABS_DONE_1) not yet programmed."); + + /* Generating the SHA of the public key components in the signature block */ + bootloader_sha256_handle_t sig_block_sha; + sig_block_sha = bootloader_sha256_start(); + bootloader_sha256_data(sig_block_sha, &sig_block->block[0].key, sizeof(sig_block->block[0].key)); + bootloader_sha256_finish(sig_block_sha, (unsigned char *)sig_block_trusted_digest); + + if (memcmp(efuse_trusted_digest, sig_block_trusted_digest, DIGEST_LEN) != 0) { + ESP_LOGW(TAG, "Public key digest in eFuse BLK2 and the signature block don't match."); + } + + memcpy(efuse_trusted_digest, sig_block_trusted_digest, DIGEST_LEN); + } + + ESP_LOGI(TAG, "Verifying with RSA-PSS..."); + r = ets_secure_boot_verify_signature(sig_block, image_digest, efuse_trusted_digest, verified_digest); + if (r != SBV2_SUCCESS) { + ESP_LOGE(TAG, "Secure Boot V2 verification failed."); + } + + return (r == SBV2_SUCCESS) ? ESP_OK : ESP_ERR_IMAGE_INVALID; +} +#endif \ No newline at end of file diff --git a/components/bootloader_support/src/esp32s2/secure_boot.c b/components/bootloader_support/src/esp32s2/secure_boot.c index f1d96c49a0..47e55dde42 100644 --- a/components/bootloader_support/src/esp32s2/secure_boot.c +++ b/components/bootloader_support/src/esp32s2/secure_boot.c @@ -15,7 +15,7 @@ #include "esp_log.h" #include "esp32s2/rom/secure_boot.h" -#define TAG "secure_boot" +static const char *TAG = "secure_boot"; esp_err_t esp_secure_boot_permanently_enable(void) { diff --git a/components/bootloader_support/src/esp32s2/secure_boot_signatures.c b/components/bootloader_support/src/esp32s2/secure_boot_signatures.c index 27d98340c2..c8ba9a0b5b 100644 --- a/components/bootloader_support/src/esp32s2/secure_boot_signatures.c +++ b/components/bootloader_support/src/esp32s2/secure_boot_signatures.c @@ -37,7 +37,7 @@ esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length) } data = bootloader_mmap(src_addr, length + sizeof(struct ets_secure_boot_sig_block)); - if(data == NULL) { + if (data == NULL) { ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", src_addr, length+sizeof(ets_secure_boot_signature_t)); return ESP_FAIL; } @@ -64,29 +64,18 @@ esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length) return (r == ETS_OK) ? ESP_OK : ESP_FAIL; } -esp_err_t esp_secure_boot_verify_signature_block(uint32_t sig_block_flash_offs, const uint8_t *image_digest) +esp_err_t esp_secure_boot_verify_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest) { ets_secure_boot_key_digests_t trusted_keys; - assert(sig_block_flash_offs % 4096 == 0); // TODO: enforce this in a better way - - const ets_secure_boot_signature_t *sig = bootloader_mmap(sig_block_flash_offs, sizeof(ets_secure_boot_signature_t)); - - if (sig == NULL) { - ESP_LOGE(TAG, "Failed to mmap data at offset 0x%x", sig_block_flash_offs); - return ESP_FAIL; - } - int r = ets_secure_boot_read_key_digests(&trusted_keys); if (r != 0) { ESP_LOGE(TAG, "No trusted key digests were found in efuse!"); } else { ESP_LOGD(TAG, "Verifying with RSA-PSS..."); // TODO: calling this function in IDF app context is unsafe - r = ets_secure_boot_verify_signature(sig, image_digest, &trusted_keys); + r = ets_secure_boot_verify_signature(sig_block, image_digest, &trusted_keys); } - bootloader_munmap(sig); - return (r == 0) ? ESP_OK : ESP_ERR_IMAGE_INVALID; } diff --git a/components/bootloader_support/src/esp_image_format.c b/components/bootloader_support/src/esp_image_format.c index c9c63c49f3..61ea3f7b32 100644 --- a/components/bootloader_support/src/esp_image_format.c +++ b/components/bootloader_support/src/esp_image_format.c @@ -55,9 +55,6 @@ static const char *TAG = "esp_image"; /* Headroom to ensure between stack SP (at time of checking) and data loaded from flash */ #define STACK_LOAD_HEADROOM 32768 -/* Mmap source address mask */ -#define MMAP_ALIGNED_MASK 0x0000FFFF - #ifdef BOOTLOADER_BUILD /* 64 bits of random data to obfuscate loaded RAM with, until verification is complete (Means loaded code isn't executable until after the secure boot check.) @@ -204,7 +201,7 @@ static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_ esptool.py may have rewritten the header - rely on esptool.py having verified the bootloader at flashing time, instead.) */ bool verify_sha; -#if CONFIG_SECURE_BOOT_ENABLED && CONFIG_IDF_TARGET_ESP32S2 +#if CONFIG_SECURE_BOOT_V2_ENABLED && CONFIG_IDF_TARGET_ESP32S2 verify_sha = true; #else // ESP32, or ESP32S2 without secure boot enabled verify_sha = (data->start_addr != ESP_BOOTLOADER_OFFSET); @@ -637,26 +634,21 @@ static esp_err_t verify_secure_boot_signature(bootloader_sha256_handle_t sha_han bootloader_sha256_data(sha_handle, simple_hash, HASH_LEN); bootloader_munmap(simple_hash); } - -#if CONFIG_IDF_TARGET_ESP32S2 - // Pad to 4096 byte sector boundary - if (end % FLASH_SECTOR_SIZE != 0) { - uint32_t pad_len = FLASH_SECTOR_SIZE - (end % FLASH_SECTOR_SIZE); - const void *padding = bootloader_mmap(end, pad_len); - bootloader_sha256_data(sha_handle, padding, pad_len); - bootloader_munmap(padding); - end += pad_len; - } -#endif - bootloader_sha256_finish(sha_handle, image_hash); // Log the hash for debugging bootloader_debug_buffer(image_hash, HASH_LEN, "Calculated secure boot hash"); +#ifdef SECURE_BOOT_CHECK_SIGNATURE // Use hash to verify signature block - const esp_secure_boot_sig_block_t *sig_block = bootloader_mmap(data->start_addr + data->image_len, sizeof(esp_secure_boot_sig_block_t)); - esp_err_t err = esp_secure_boot_verify_signature_block(sig_block, image_hash); + esp_err_t err = ESP_ERR_IMAGE_INVALID; + const void *sig_block; + #ifdef CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME + sig_block = bootloader_mmap(data->start_addr + data->image_len, sizeof(esp_secure_boot_sig_block_t)); + #elif CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME + sig_block = bootloader_mmap(end, sizeof(ets_secure_boot_signature_t)); + #endif + err = esp_secure_boot_verify_signature_block(sig_block, image_hash); bootloader_munmap(sig_block); if (err != ESP_OK) { ESP_LOGE(TAG, "Secure boot signature verification failed"); @@ -676,8 +668,9 @@ static esp_err_t verify_secure_boot_signature(bootloader_sha256_handle_t sha_han } return ESP_ERR_IMAGE_INVALID; } +#endif -#if CONFIG_IDF_TARGET_ESP32S2 +#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME // Adjust image length result to include the appended signature data->image_len = end - data->start_addr + sizeof(ets_secure_boot_signature_t); #endif diff --git a/components/bootloader_support/src/flash_encrypt.c b/components/bootloader_support/src/flash_encrypt.c index 5a76fc0fda..98438bf123 100644 --- a/components/bootloader_support/src/flash_encrypt.c +++ b/components/bootloader_support/src/flash_encrypt.c @@ -31,7 +31,7 @@ void esp_flash_encryption_init_checks() // FLASH_CRYPT_CNT *must* be write protected. This will have happened automatically // if bootloader is IDF V4.0 or newer but may not have happened for previous ESP-IDF bootloaders. #ifdef CONFIG_SECURE_FLASH_ENCRYPTION_MODE_RELEASE -#ifdef CONFIG_SECURE_BOOT_ENABLED +#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(ESP_EFUSE_WR_DIS_FLASH_CRYPT_CNT, &flash_crypt_cnt_wr_dis, 1); @@ -40,7 +40,7 @@ void esp_flash_encryption_init_checks() esp_flash_write_protect_crypt_cnt(); } } -#endif // CONFIG_SECURE_BOOT_ENABLED +#endif // CONFIG_SECURE_BOOT #endif // CONFIG_SECURE_FLASH_ENCRYPTION_MODE_RELEASE // Second check is to print a warning or error if the current running flash encryption mode diff --git a/components/bootloader_support/src/idf/bootloader_sha.c b/components/bootloader_support/src/idf/bootloader_sha.c index 849c86b387..06fdc358d2 100644 --- a/components/bootloader_support/src/idf/bootloader_sha.c +++ b/components/bootloader_support/src/idf/bootloader_sha.c @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. #include "bootloader_sha.h" +#include "bootloader_flash.h" #include #include #include diff --git a/components/bootloader_support/src/idf/secure_boot_signatures.c b/components/bootloader_support/src/idf/secure_boot_signatures.c index df1424124b..1521c253ca 100644 --- a/components/bootloader_support/src/idf/secure_boot_signatures.c +++ b/components/bootloader_support/src/idf/secure_boot_signatures.c @@ -15,42 +15,50 @@ #include "bootloader_flash.h" #include "bootloader_sha.h" +#include "bootloader_utility.h" #include "esp_log.h" #include "esp_image_format.h" #include "esp_secure_boot.h" #include "mbedtls/sha256.h" #include "mbedtls/x509.h" +#include "mbedtls/md.h" +#include "mbedtls/platform.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include +#include -static const char *TAG = "secure_boot"; +#define DIGEST_LEN 32 + +#ifdef CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME +static const char *TAG = "secure_boot_v1"; extern const uint8_t signature_verification_key_start[] asm("_binary_signature_verification_key_bin_start"); extern const uint8_t signature_verification_key_end[] asm("_binary_signature_verification_key_bin_end"); #define SIGNATURE_VERIFICATION_KEYLEN 64 -#define DIGEST_LEN 32 - esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length) { uint8_t digest[DIGEST_LEN]; - const uint8_t *data; const esp_secure_boot_sig_block_t *sigblock; ESP_LOGD(TAG, "verifying signature src_addr 0x%x length 0x%x", src_addr, length); - data = bootloader_mmap(src_addr, length + sizeof(esp_secure_boot_sig_block_t)); - if (data == NULL) { - ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", src_addr, length + sizeof(esp_secure_boot_sig_block_t)); - return ESP_FAIL; + esp_err_t err = bootloader_sha256_flash_contents(src_addr, length, digest); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Digest calculation failed 0x%x, 0x%x", src_addr, length); + return err; } - // Calculate digest of main image - mbedtls_sha256_ret(data, length, digest, 0); - // Map the signature block and verify the signature - sigblock = (const esp_secure_boot_sig_block_t *)(data + length); - esp_err_t err = esp_secure_boot_verify_signature_block(sigblock, digest); - bootloader_munmap(data); + sigblock = (const esp_secure_boot_sig_block_t *)bootloader_mmap(src_addr + length, sizeof(esp_secure_boot_sig_block_t)); + if (sigblock == NULL) { + ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", src_addr + length, sizeof(esp_secure_boot_sig_block_t)); + return ESP_FAIL; + } + err = esp_secure_boot_verify_signature_block(sigblock, digest); + bootloader_munmap(sigblock); return err; } @@ -123,3 +131,134 @@ cleanup: return ret == 0 ? ESP_OK : ESP_ERR_IMAGE_INVALID; #endif // CONFIG_MBEDTLS_ECDSA_C && CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED } + +#elif CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME + +static const char *TAG = "secure_boot_v2"; +#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1)) +#define RSA_KEY_SIZE 384 /* RSA 3072 Bits */ + +esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length) +{ + uint8_t digest[DIGEST_LEN] = {0}; + + /* Rounding off length to the upper 4k boundary */ + int padded_length = ALIGN_UP(length, FLASH_SECTOR_SIZE); + ESP_LOGD(TAG, "verifying signature src_addr 0x%x length 0x%x", src_addr, length); + + esp_err_t err = bootloader_sha256_flash_contents(src_addr, padded_length, digest); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Digest calculation failed 0x%x, 0x%x", src_addr, padded_length); + return err; + } + + const ets_secure_boot_signature_t *sig_block = bootloader_mmap(src_addr + padded_length, sizeof(ets_secure_boot_signature_t)); + if (sig_block == NULL) { + ESP_LOGE(TAG, "Failed to mmap data at offset 0x%x", src_addr + padded_length); + return ESP_FAIL; + } + + err = esp_secure_boot_verify_signature_block(sig_block, digest); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Secure Boot V2 verification failed."); + } + bootloader_munmap(sig_block); + return err; +} + +esp_err_t esp_secure_boot_verify_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest) +{ + uint8_t i = 0, efuse_trusted_digest[DIGEST_LEN] = {0}, sig_block_trusted_digest[DIGEST_LEN] = {0}; + memcpy(efuse_trusted_digest, (uint8_t *) EFUSE_BLK2_RDATA0_REG, sizeof(efuse_trusted_digest)); + + /* Generating the SHA of the public key components in the signature block */ + bootloader_sha256_handle_t sig_block_sha; + sig_block_sha = bootloader_sha256_start(); + bootloader_sha256_data(sig_block_sha, &sig_block->block[0].key, sizeof(sig_block->block[0].key)); + bootloader_sha256_finish(sig_block_sha, (unsigned char *)sig_block_trusted_digest); + + if (memcmp(efuse_trusted_digest, sig_block_trusted_digest, DIGEST_LEN) != 0) { + if (esp_secure_boot_enabled()) { + ESP_LOGE(TAG, "Public key digest in eFuse BLK2 and the signature block don't match."); + return ESP_FAIL; + } else { + ESP_LOGW(TAG, "Public key digest in eFuse BLK2 and the signature block don't match."); + } + } + + ESP_LOGI(TAG, "Verifying with RSA-PSS..."); + int ret = 0; + mbedtls_rsa_context pk; + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + unsigned char *sig_be = calloc(1, RSA_KEY_SIZE); + unsigned char *buf = calloc(1, RSA_KEY_SIZE); + if (sig_be == NULL || buf == NULL) { + return ESP_ERR_NO_MEM; + } + + mbedtls_entropy_init(&entropy); + ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0); + if (ret != 0) { + ESP_LOGE(TAG, "mbedtls_ctr_drbg_seed returned -0x%04x\n", ret); + goto exit; + } + + for (i = 0; i < SECURE_BOOT_NUM_BLOCKS; i++) { + const mbedtls_mpi N = { .s = 1, + .n = sizeof(sig_block->block[i].key.n)/sizeof(mbedtls_mpi_uint), + .p = (void *)sig_block->block[i].key.n, + }; + const mbedtls_mpi e = { .s = 1, + .n = sizeof(sig_block->block[i].key.e)/sizeof(mbedtls_mpi_uint), // 1 + .p = (void *)&sig_block->block[i].key.e, + }; + mbedtls_rsa_init(&pk, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256); + ret = mbedtls_rsa_import(&pk, &N, NULL, NULL, NULL, &e); + if (ret != 0) { + ESP_LOGE(TAG, "Failed mbedtls_rsa_import, err: %d", ret); + goto exit; + } + + ret = mbedtls_rsa_complete(&pk); + if (ret != 0) { + ESP_LOGE(TAG, "Failed mbedtls_rsa_complete, err: %d", ret); + goto exit; + } + + ret = mbedtls_rsa_check_pubkey(&pk); + if (ret != 0) { + ESP_LOGI(TAG, "Key is not an RSA key -%0x", -ret); + goto exit; + } + + /* Signature needs to be byte swapped into BE representation */ + for (int j = 0; j < RSA_KEY_SIZE; j++) { + sig_be[RSA_KEY_SIZE- j - 1] = sig_block->block[i].signature[j]; + } + + ret = mbedtls_rsa_public( &pk, sig_be, buf); + if (ret != 0) { + ESP_LOGE(TAG, "mbedtls_rsa_public failed, err: %d", ret); + goto exit; + } + + ret = mbedtls_rsa_rsassa_pss_verify( &pk, mbedtls_ctr_drbg_random, &ctr_drbg, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA256, 32, + sig_block->block[i].image_digest, sig_be); + if (ret != 0) { + ESP_LOGE(TAG, "Failed mbedtls_rsa_rsassa_pss_verify, err: %d", ret); + } else { + ESP_LOGI(TAG, "Signature verified successfully!"); + } + exit: + mbedtls_rsa_free(&pk); + if (ret == 0) { + break; + } + } + + free(sig_be); + free(buf); + return (!ret) ? ESP_OK : ESP_ERR_IMAGE_INVALID; +} +#endif diff --git a/components/esp_rom/CMakeLists.txt b/components/esp_rom/CMakeLists.txt index 499e822a7f..c00a7aa283 100644 --- a/components/esp_rom/CMakeLists.txt +++ b/components/esp_rom/CMakeLists.txt @@ -12,6 +12,10 @@ if(BOOTLOADER_BUILD) list(APPEND scripts "esp32s2/ld/esp32s2.rom.spiflash.ld") endif() + if(CONFIG_ESP32_REV_MIN_3) + list(APPEND scripts "esp32/ld/esp32.rom.eco3.ld") + endif() + target_linker_script(${COMPONENT_LIB} INTERFACE "${scripts}") else() # Regular app build set(scripts @@ -42,8 +46,13 @@ else() # Regular app build list(APPEND scripts "esp32/ld/esp32.rom.spiflash.ld") endif() + if(CONFIG_ESP32_REV_MIN_3) + list(APPEND scripts "esp32/ld/esp32.rom.eco3.ld") + endif() + elseif(target STREQUAL "esp32s2") # no SPIRAM workaround for esp32s2 + # no nano formatting function in ROM list(APPEND scripts "esp32s2/ld/esp32s2.rom.newlib-funcs.ld" "esp32s2/ld/esp32s2.rom.spiflash.ld") diff --git a/components/esp_rom/component.mk b/components/esp_rom/component.mk index 8c99306c9d..40f327e247 100644 --- a/components/esp_rom/component.mk +++ b/components/esp_rom/component.mk @@ -11,6 +11,10 @@ LINKER_SCRIPTS += esp32.rom.ld \ ifndef CONFIG_SPIRAM_CACHE_WORKAROUND LINKER_SCRIPTS += esp32.rom.newlib-funcs.ld +ifdef CONFIG_ESP32_REV_MIN_3 +LINKER_SCRIPTS += esp32.rom.eco3.ld +endif + # Include in newlib nano from ROM only if SPIRAM cache workaround is disabled ifdef CONFIG_NEWLIB_NANO_FORMAT LINKER_SCRIPTS += esp32.rom.newlib-nano.ld diff --git a/components/esp_rom/esp32/ld/esp32.rom.eco3.ld b/components/esp_rom/esp32/ld/esp32.rom.eco3.ld new file mode 100644 index 0000000000..fdd7218b85 --- /dev/null +++ b/components/esp_rom/esp32/ld/esp32.rom.eco3.ld @@ -0,0 +1,7 @@ +/* +ESP32 ECO3 ROM address table +Secure Boot Version 2 API's imported from the ROM +*/ +PROVIDE ( ets_secure_boot_verify_signature = 0x4006543c); +PROVIDE ( ets_secure_boot_verify_boot_bootloader = 0x400655ec); +PROVIDE ( ets_use_secure_boot_v2 = 0x4000f8d4); diff --git a/components/esp_rom/include/esp32/rom/secure_boot.h b/components/esp_rom/include/esp32/rom/secure_boot.h index bd4f32ed95..04ffec0a2c 100644 --- a/components/esp_rom/include/esp32/rom/secure_boot.h +++ b/components/esp_rom/include/esp32/rom/secure_boot.h @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "sdkconfig.h" + #ifndef _ROM_SECURE_BOOT_H_ #define _ROM_SECURE_BOOT_H_ @@ -39,8 +41,74 @@ bool ets_secure_boot_check_start(uint8_t abs_index, uint32_t iv_addr); int ets_secure_boot_check_finish(uint32_t *abstract); -#ifdef __cplusplus -} -#endif +#ifdef CONFIG_ESP32_REV_MIN_3 +#define SECURE_BOOT_NUM_BLOCKS 1 -#endif /* _ROM_SECURE_BOOT_H_ */ +typedef enum { + SBV2_SUCCESS = 0x3A5A5AA5, + SBV2_FAILED = 0xA533885A, +} secure_boot_v2_status_t; + +/* Secure Boot Version 2 - Public Key format */ +typedef struct { + uint8_t n[384]; /* Public key modulus */ + uint32_t e; /* Public key exponent */ + uint8_t rinv[384]; + uint32_t mdash; +} ets_rsa_pubkey_t; + +/* Secure Boot Version 2 signature format for ESP32 ECO3 */ +typedef struct { + uint8_t magic_byte; + uint8_t version; + uint8_t _reserved1; + uint8_t _reserved2; + uint8_t image_digest[32]; + ets_rsa_pubkey_t key; + uint8_t signature[384]; + uint32_t block_crc; + uint8_t _padding[16]; +} ets_secure_boot_sig_block_t; + +/* Multiple key block support */ +struct ets_secure_boot_signature { + ets_secure_boot_sig_block_t block[SECURE_BOOT_NUM_BLOCKS]; + uint8_t _padding[4096 - (sizeof(ets_secure_boot_sig_block_t) * SECURE_BOOT_NUM_BLOCKS)]; +}; +typedef struct ets_secure_boot_signature ets_secure_boot_signature_t; + +/** @brief Verifies the signature block appended to a firmware image. Implemented in the ROM. + * + * This function is used to verify the bootloader before burning its public key hash into Efuse. + * Also, it is used to verify the app on loading the image on boot and on OTA. + * + * @param sig The signature block flashed aligned 4096 bytes from the firmware. + * @param image_digest The SHA-256 Digest of the firmware to be verified + * @param trusted_key_digest The SHA-256 Digest of the public key (ets_rsa_pubkey_t) of a single signature block. + * @param verified_digest RSA-PSS signature of image_digest. Pass an uninitialised array. + * + * @return SBV2_SUCCESS if signature is valid + * SBV2_FAILED for failures. + */ +secure_boot_v2_status_t ets_secure_boot_verify_signature(const ets_secure_boot_signature_t *sig, const uint8_t *image_digest, const uint8_t *trusted_key_digest, uint8_t *verified_digest); + +/** @brief This function verifies the 1st stage bootloader. Implemented in the ROM. + * Reboots post verification. It reads the Efuse key for verification of the public key. + * + * This function is not used in the current workflow. + * + */ +void ets_secure_boot_verify_boot_bootloader(void); + +/** @brief Confirms if the secure boot V2 has been enabled. Implemented in the ROM. + * + * In ESP32-ECO3 - It checks the value of ABS_DONE_1 in EFuse. + * + * @return true if is Secure boot v2 has been enabled + * False if Secure boot v2 has not been enabled. + */ +bool ets_use_secure_boot_v2(); + +#endif /* CONFIG_ESP32_REV_MIN_3 */ + +#endif /* _ROM_SECURE_BOOT_H_ */ \ No newline at end of file diff --git a/components/esptool_py/CMakeLists.txt b/components/esptool_py/CMakeLists.txt index 174de18acc..6d3b01c80b 100644 --- a/components/esptool_py/CMakeLists.txt +++ b/components/esptool_py/CMakeLists.txt @@ -29,7 +29,7 @@ if(NOT BOOTLOADER_BUILD) set(ESPTOOLPY_CHIP "${target}") set(ESPTOOLPY_WITH_STUB TRUE) - if(CONFIG_SECURE_BOOT_ENABLED OR CONFIG_SECURE_FLASH_ENC_ENABLED) + if(CONFIG_SECURE_BOOT OR CONFIG_SECURE_FLASH_ENC_ENABLED) # If security enabled then override post flash option set(ESPTOOLPY_AFTER "no_reset") endif() diff --git a/components/esptool_py/Makefile.projbuild b/components/esptool_py/Makefile.projbuild index 940e6b4f46..2e380b394d 100644 --- a/components/esptool_py/Makefile.projbuild +++ b/components/esptool_py/Makefile.projbuild @@ -29,16 +29,22 @@ else ESPTOOL_WRITE_FLASH_OPTIONS := $(ESPTOOL_FLASH_OPTIONS) endif +ifdef CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME +ESPTOOL_WRITE_FLASH_OPTIONS := --flash_mode $(ESPFLASHMODE) --flash_freq $(ESPFLASHFREQ) --flash_size keep +endif + ESPTOOL_ELF2IMAGE_OPTIONS := ifdef CONFIG_ESP32_REV_MIN ESPTOOL_ELF2IMAGE_OPTIONS += --min-rev $(CONFIG_ESP32_REV_MIN) endif -ifdef CONFIG_SECURE_BOOT_ENABLED ifndef CONFIG_SECURE_BOOT_ALLOW_SHORT_APP_PARTITION ifndef IS_BOOTLOADER_BUILD +ifdef CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME ESPTOOL_ELF2IMAGE_OPTIONS += --secure-pad +else ifdef CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME +ESPTOOL_ELF2IMAGE_OPTIONS += --secure-pad-v2 endif endif endif @@ -47,6 +53,12 @@ ifndef IS_BOOTLOADER_BUILD ESPTOOL_ELF2IMAGE_OPTIONS += --elf-sha256-offset 0xb0 endif +ifdef CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME +SECURE_APPS_SIGNING_SCHEME = "1" +else ifdef CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME +SECURE_APPS_SIGNING_SCHEME = "2" +endif + ESPTOOLPY_WRITE_FLASH=$(ESPTOOLPY_SERIAL) write_flash $(if $(CONFIG_ESPTOOLPY_COMPRESSED),-z,-u) $(ESPTOOL_WRITE_FLASH_OPTIONS) ifdef CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT @@ -61,7 +73,7 @@ ifndef IS_BOOTLOADER_BUILD APP_BIN_UNSIGNED := $(APP_BIN:.bin=-unsigned.bin) $(APP_BIN): $(APP_BIN_UNSIGNED) $(SECURE_BOOT_SIGNING_KEY) $(SDKCONFIG_MAKEFILE) - $(ESPSECUREPY) sign_data --keyfile $(SECURE_BOOT_SIGNING_KEY) -o $@ $< + $(ESPSECUREPY) sign_data --version $(SECURE_APPS_SIGNING_SCHEME) --keyfile $(SECURE_BOOT_SIGNING_KEY) -o $@ $< endif endif # non-secure boot (or bootloader), both these files are the same @@ -77,7 +89,7 @@ endif ifdef CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT encrypted-flash: all_binaries $(ESPTOOLPY_SRC) $(call prereq_if_explicit,erase_flash) partition_table_get_info | check_python_dependencies @echo "Flashing binaries to serial port $(ESPPORT) (app at offset $(APP_OFFSET))..." -ifdef CONFIG_SECURE_BOOT_ENABLED +ifdef CONFIG_SECURE_BOOT @echo "(Secure boot enabled, so bootloader not flashed automatically. See 'make bootloader' output)" endif $(ESPTOOLPY_WRITE_FLASH_ENCRYPT) $(ESPTOOL_ALL_FLASH_ARGS) @@ -89,7 +101,7 @@ endif flash: all_binaries $(ESPTOOLPY_SRC) $(call prereq_if_explicit,erase_flash) partition_table_get_info | check_python_dependencies @echo "Flashing binaries to serial port $(ESPPORT) (app at offset $(APP_OFFSET))..." -ifdef CONFIG_SECURE_BOOT_ENABLED +ifdef CONFIG_SECURE_BOOT @echo "(Secure boot enabled, so bootloader not flashed automatically. See 'make bootloader' output)" endif $(ESPTOOLPY_WRITE_FLASH) $(ESPTOOL_ALL_FLASH_ARGS) diff --git a/components/esptool_py/esptool b/components/esptool_py/esptool index 939b3e987a..91bdc71841 160000 --- a/components/esptool_py/esptool +++ b/components/esptool_py/esptool @@ -1 +1 @@ -Subproject commit 939b3e987ac6efde171add89ee26a34031058760 +Subproject commit 91bdc71841d1b4e561e8e896405b58db86d5fd72 diff --git a/components/esptool_py/project_include.cmake b/components/esptool_py/project_include.cmake index 67ffd464d0..4b6994b12f 100644 --- a/components/esptool_py/project_include.cmake +++ b/components/esptool_py/project_include.cmake @@ -22,10 +22,13 @@ if(NOT BOOTLOADER_BUILD) set(esptool_elf2image_args --elf-sha256-offset 0xb0) endif() -if(CONFIG_SECURE_BOOT_ENABLED AND - NOT CONFIG_SECURE_BOOT_ALLOW_SHORT_APP_PARTITION - AND NOT BOOTLOADER_BUILD) - list(APPEND esptool_elf2image_args --secure-pad) +if(NOT CONFIG_SECURE_BOOT_ALLOW_SHORT_APP_PARTITION AND + NOT BOOTLOADER_BUILD) + if(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME) + list(APPEND esptool_elf2image_args --secure-pad) + elseif(CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME) + list(APPEND esptool_elf2image_args --secure-pad-v2) + endif() endif() if(CONFIG_ESP32_REV_MIN) @@ -38,6 +41,10 @@ if(CONFIG_ESPTOOLPY_FLASHSIZE_DETECT) set(ESPFLASHSIZE detect) endif() +if(CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME) + set(ESPFLASHSIZE keep) +endif() + idf_build_get_property(build_dir BUILD_DIR) idf_build_get_property(elf_name EXECUTABLE_NAME GENERATOR_EXPRESSION) @@ -77,11 +84,17 @@ if(CONFIG_APP_BUILD_GENERATE_BINARIES) add_custom_target(app ALL DEPENDS gen_project_binary) endif() +if(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME) + set(secure_boot_version "1") +elseif(CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME) + set(secure_boot_version "2") +endif() + if(NOT BOOTLOADER_BUILD AND CONFIG_SECURE_SIGNED_APPS) if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES) # for locally signed secure boot image, add a signing step to get from unsigned app to signed app add_custom_command(OUTPUT "${build_dir}/.signed_bin_timestamp" - COMMAND ${ESPSECUREPY} sign_data --keyfile ${secure_boot_signing_key} + COMMAND ${ESPSECUREPY} sign_data --version ${secure_boot_version} --keyfile ${secure_boot_signing_key} -o "${build_dir}/${PROJECT_BIN}" "${build_dir}/${unsigned_project_binary}" COMMAND ${CMAKE_COMMAND} -E echo "Generated signed binary image ${build_dir}/${PROJECT_BIN}" "from ${build_dir}/${unsigned_project_binary}" @@ -103,7 +116,8 @@ if(NOT BOOTLOADER_BUILD AND CONFIG_SECURE_SIGNED_APPS) COMMAND ${CMAKE_COMMAND} -E echo "App built but not signed. Sign app before flashing" COMMAND ${CMAKE_COMMAND} -E echo - "\t${espsecurepy} sign_data --keyfile KEYFILE ${build_dir}/${PROJECT_BIN}" + "\t${espsecurepy} sign_data --keyfile KEYFILE --version ${secure_boot_version} \ + ${build_dir}/${PROJECT_BIN}" VERBATIM) endif() endif() @@ -131,7 +145,7 @@ add_custom_target(monitor set(esptool_flash_main_args "--before=${CONFIG_ESPTOOLPY_BEFORE}") -if(CONFIG_SECURE_BOOT_ENABLED OR CONFIG_SECURE_FLASH_ENC_ENABLED) +if(CONFIG_SECURE_BOOT OR CONFIG_SECURE_FLASH_ENC_ENABLED) # If security enabled then override post flash option list(APPEND esptool_flash_main_args "--after=no_reset") else() diff --git a/components/partition_table/CMakeLists.txt b/components/partition_table/CMakeLists.txt index fe7d61b08d..27021c9597 100644 --- a/components/partition_table/CMakeLists.txt +++ b/components/partition_table/CMakeLists.txt @@ -6,7 +6,7 @@ endif() set(partition_csv "${PARTITION_CSV_PATH}") -if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES) +if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES AND CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME) set(unsigned_partition_bin "partition-table-unsigned.bin") set(final_partition_bin "partition-table.bin") set(final_partition_target "sign_partition_table") @@ -24,7 +24,7 @@ if(CONFIG_ESPTOOLPY_FLASHSIZE) set(flashsize_opt --flash-size ${CONFIG_ESPTOOLPY_FLASHSIZE}) endif() -if(CONFIG_SECURE_BOOT_ENABLED AND NOT CONFIG_SECURE_BOOT_ALLOW_SHORT_APP_PARTITION) +if(CONFIG_SECURE_BOOT AND NOT CONFIG_SECURE_BOOT_ALLOW_SHORT_APP_PARTITION) set(partition_secure_opt --secure) else() set(partition_secure_opt "") @@ -52,13 +52,13 @@ else() endif() # Add signing steps -if(CONFIG_SECURE_SIGNED_APPS) +if(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME) if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES) add_custom_target(gen_unsigned_partition_bin ALL DEPENDS "${build_dir}/partition_table/${unsigned_partition_bin}") add_custom_command(OUTPUT "${build_dir}/partition_table/${final_partition_bin}" - COMMAND ${ESPSECUREPY} sign_data --keyfile "${SECURE_BOOT_SIGNING_KEY}" + COMMAND ${ESPSECUREPY} sign_data --version 1 --keyfile "${SECURE_BOOT_SIGNING_KEY}" -o "${build_dir}/partition_table/${final_partition_bin}" "${build_dir}/partition_table/${unsigned_partition_bin}" DEPENDS "${build_dir}/partition_table/${unsigned_partition_bin}" @@ -72,6 +72,10 @@ if(CONFIG_SECURE_SIGNED_APPS) "\t${espsecurepy} sign_data --keyfile KEYFILE ${build_dir}/partition_table/${final_partition_bin}" VERBATIM) endif() +elseif(CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME) + add_custom_command(TARGET partition_table POST_BUILD + COMMAND ${CMAKE_COMMAND} -E echo "Partition table built:" + VERBATIM) endif() idf_component_get_property(main_args esptool_py FLASH_ARGS) diff --git a/components/partition_table/Makefile.projbuild b/components/partition_table/Makefile.projbuild index 6b28b093f5..a6585f8353 100644 --- a/components/partition_table/Makefile.projbuild +++ b/components/partition_table/Makefile.projbuild @@ -19,7 +19,7 @@ PARTITION_FLASHSIZE_OPT := --flash-size $(CONFIG_ESPTOOLPY_FLASHSIZE) endif PARTITION_SECURE_OPT := -ifdef CONFIG_SECURE_BOOT_ENABLED +ifdef CONFIG_SECURE_BOOT ifndef CONFIG_SECURE_BOOT_ALLOW_SHORT_APP_PARTITION PARTITION_SECURE_OPT += --secure endif @@ -46,11 +46,16 @@ PARTITION_TABLE_CSV_NAME := $(notdir $(PARTITION_TABLE_CSV_PATH)) PARTITION_TABLE_BIN := $(BUILD_DIR_BASE)/$(PARTITION_TABLE_CSV_NAME:.csv=.bin) +ifdef CONFIG_SECURE_BOOT_V1_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) - $(ESPSECUREPY) sign_data --keyfile $(SECURE_BOOT_SIGNING_KEY) -o $@ $< + $(ESPSECUREPY) sign_data --version 1 --keyfile $(SECURE_BOOT_SIGNING_KEY) -o $@ $< +else +# secure bootloader disabled, both files are the same +PARTITION_TABLE_BIN_UNSIGNED := $(PARTITION_TABLE_BIN) +endif else # secure bootloader disabled, both files are the same PARTITION_TABLE_BIN_UNSIGNED := $(PARTITION_TABLE_BIN) diff --git a/make/project.mk b/make/project.mk index 9817d50506..f6a036f190 100644 --- a/make/project.mk +++ b/make/project.mk @@ -311,12 +311,17 @@ COMPONENT_INCLUDES += $(abspath $(BUILD_DIR_BASE)/include/) export COMPONENT_INCLUDES all: -ifdef CONFIG_SECURE_BOOT_ENABLED +ifdef CONFIG_SECURE_BOOT @echo "(Secure boot enabled, so bootloader not flashed automatically. See 'make bootloader' output)" ifndef CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES +ifdef SECURE_SIGNED_APPS_ECDSA_SCHEME @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)" + @echo "espsecure.py sign_data --version 1 --keyfile KEYFILE $(APP_BIN)" + @echo "espsecure.py sign_data --version 1 --keyfile KEYFILE $(PARTITION_TABLE_BIN)" +else + @echo "App built but not signed. Sign app & partition data before flashing, via espsecure.py:" + @echo "espsecure.py sign_data --version 2 --keyfile KEYFILE $(APP_BIN)" +endif endif @echo "To flash app & partition table, run 'make flash' or:" else @@ -538,11 +543,17 @@ $(APP_ELF): $(foreach libcomp,$(COMPONENT_LIBRARIES),$(BUILD_DIR_BASE)/$(libcomp $(summary) LD $(patsubst $(PWD)/%,%,$@) $(CC) $(LDFLAGS) -o $@ -Wl,-Map=$(APP_MAP) +ifdef CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME +SECURE_APPS_SIGNING_SCHEME = "1" +else ifdef CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME +SECURE_APPS_SIGNING_SCHEME = "2" +endif + app: $(APP_BIN) partition_table_get_info ifeq ("$(CONFIG_APP_BUILD_GENERATE_BINARIES)","y") -ifeq ("$(CONFIG_SECURE_BOOT_ENABLED)$(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)","y") # secure boot enabled, but remote sign app image +ifeq ("$(CONFIG_SECURE_BOOT)$(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 "espsecure.py sign_data --version $(SECURE_APPS_SIGNING_SCHEME) --keyfile KEYFILE $(APP_BIN)" @echo "Then flash app command is:" @echo $(ESPTOOLPY_WRITE_FLASH) $(APP_OFFSET) $(APP_BIN) else