From 46e85ed0210ac8d2c1949542ed1122efd2fb0cd1 Mon Sep 17 00:00:00 2001 From: KonstantinKondrashov Date: Fri, 5 Mar 2021 22:22:29 +0800 Subject: [PATCH] secure_boot: Secure Boot V2 verify app signature on update (without Secure boot) - ESP32 ECO3, ESP32-S2/C3/S3 --- components/app_update/esp_ota_ops.c | 10 - components/bootloader/Kconfig.projbuild | 6 +- .../subproject/main/ld/esp32/bootloader.ld | 2 +- .../subproject/main/ld/esp32c3/bootloader.ld | 2 +- .../subproject/main/ld/esp32s2/bootloader.ld | 2 +- .../subproject/main/ld/esp32s3/bootloader.ld | 2 +- components/bootloader_support/CMakeLists.txt | 28 +- components/bootloader_support/component.mk | 9 +- .../include/esp_image_format.h | 14 + .../include/esp_secure_boot.h | 22 +- .../src/esp32/secure_boot.c | 25 +- .../src/esp32/secure_boot_signatures.c | 184 ---------- .../src/esp32c3/secure_boot.c | 41 +-- .../src/esp32c3/secure_boot_signatures.c | 94 ----- .../src/esp32s2/secure_boot.c | 41 +-- .../src/esp32s2/secure_boot_signatures.c | 93 ----- .../src/esp32s3/secure_boot.c | 41 +-- .../src/esp32s3/secure_boot_signatures.c | 93 ----- .../bootloader_support/src/esp_image_format.c | 47 ++- .../src/idf/secure_boot_signatures.c | 339 ------------------ .../secure_boot_signatures_app.c | 136 +++++++ .../secure_boot_signatures_bootloader.c | 100 ++++++ .../secure_boot_signatures_app.c | 271 ++++++++++++++ .../secure_boot_signatures_bootloader.c | 172 +++++++++ components/esp_rom/esp32/ld/esp32.rom.eco3.ld | 3 + .../esp_rom/include/esp32/rom/rsa_pss.h | 50 +++ .../esp_rom/include/esp32/rom/secure_boot.h | 41 ++- .../esp_rom/include/esp32c3/rom/secure_boot.h | 2 + .../esp_rom/include/esp32s2/rom/secure_boot.h | 3 + .../esp_rom/include/esp32s3/rom/secure_boot.h | 21 +- 30 files changed, 934 insertions(+), 960 deletions(-) delete mode 100644 components/bootloader_support/src/esp32/secure_boot_signatures.c delete mode 100644 components/bootloader_support/src/esp32c3/secure_boot_signatures.c delete mode 100644 components/bootloader_support/src/esp32s2/secure_boot_signatures.c delete mode 100644 components/bootloader_support/src/esp32s3/secure_boot_signatures.c delete mode 100644 components/bootloader_support/src/idf/secure_boot_signatures.c create mode 100644 components/bootloader_support/src/secure_boot_v1/secure_boot_signatures_app.c create mode 100644 components/bootloader_support/src/secure_boot_v1/secure_boot_signatures_bootloader.c create mode 100644 components/bootloader_support/src/secure_boot_v2/secure_boot_signatures_app.c create mode 100644 components/bootloader_support/src/secure_boot_v2/secure_boot_signatures_bootloader.c create mode 100644 components/esp_rom/include/esp32/rom/rsa_pss.h diff --git a/components/app_update/esp_ota_ops.c b/components/app_update/esp_ota_ops.c index f62605d442..54b6b09943 100644 --- a/components/app_update/esp_ota_ops.c +++ b/components/app_update/esp_ota_ops.c @@ -41,16 +41,6 @@ #include "esp_efuse.h" #include "esp_attr.h" -#ifdef CONFIG_IDF_TARGET_ESP32 -#include "esp32/rom/crc.h" -#elif CONFIG_IDF_TARGET_ESP32S2 -#include "esp32s2/rom/crc.h" -#include "esp32s2/rom/secure_boot.h" -#elif CONFIG_IDF_TARGET_ESP32C3 -#include "esp32c3/rom/crc.h" -#include "esp32c3/rom/secure_boot.h" -#endif - #define SUB_TYPE_ID(i) (i & 0x0F) /* Partial_data is word aligned so no reallocation is necessary for encrypted flash write */ diff --git a/components/bootloader/Kconfig.projbuild b/components/bootloader/Kconfig.projbuild index 0669d433a3..b8124e24ba 100644 --- a/components/bootloader/Kconfig.projbuild +++ b/components/bootloader/Kconfig.projbuild @@ -424,7 +424,7 @@ menu "Security features" 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) + Supported in ESP32-ECO3 (ESP32 Chip Revision 3 onwards), ESP32-S2, ESP32-C3, ESP32-S3. config SECURE_SIGNED_APPS_ECDSA_SCHEME bool "ECDSA" @@ -436,7 +436,7 @@ menu "Security features" config SECURE_SIGNED_APPS_RSA_SCHEME bool "RSA" - depends on SECURE_BOOT_SUPPORTS_RSA && SECURE_BOOT_V2_ENABLED + depends on SECURE_BOOT_SUPPORTS_RSA && (SECURE_SIGNED_APPS_NO_SECURE_BOOT || SECURE_BOOT_V2_ENABLED) help Appends the RSA-3072 based Signature block to the application. Refer to before enabling. @@ -445,7 +445,7 @@ menu "Security features" config SECURE_SIGNED_ON_BOOT_NO_SECURE_BOOT bool "Bootloader verifies app signatures" default n - depends on SECURE_SIGNED_APPS_NO_SECURE_BOOT + depends on SECURE_SIGNED_APPS_NO_SECURE_BOOT && SECURE_SIGNED_APPS_ECDSA_SCHEME help If this option is set, the bootloader will be compiled with code to verify that an app is signed before booting it. diff --git a/components/bootloader/subproject/main/ld/esp32/bootloader.ld b/components/bootloader/subproject/main/ld/esp32/bootloader.ld index 10d586d64c..5619d409e8 100644 --- a/components/bootloader/subproject/main/ld/esp32/bootloader.ld +++ b/components/bootloader/subproject/main/ld/esp32/bootloader.ld @@ -52,7 +52,7 @@ SECTIONS *libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*) *libbootloader_support.a:flash_partitions.*(.literal .text .literal.* .text.*) *libbootloader_support.a:secure_boot.*(.literal .text .literal.* .text.*) - *libbootloader_support.a:secure_boot_signatures.*(.literal .text .literal.* .text.*) + *libbootloader_support.a:secure_boot_signatures_bootloader.*(.literal .text .literal.* .text.*) *libmicro-ecc.a:*.*(.literal .text .literal.* .text.*) *libspi_flash.a:*.*(.literal .text .literal.* .text.*) *libhal.a:wdt_hal_iram.*(.literal .text .literal.* .text.*) diff --git a/components/bootloader/subproject/main/ld/esp32c3/bootloader.ld b/components/bootloader/subproject/main/ld/esp32c3/bootloader.ld index 8af0e142c6..38b8be442d 100644 --- a/components/bootloader/subproject/main/ld/esp32c3/bootloader.ld +++ b/components/bootloader/subproject/main/ld/esp32c3/bootloader.ld @@ -40,7 +40,7 @@ SECTIONS *libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*) *libbootloader_support.a:flash_partitions.*(.literal .text .literal.* .text.*) *libbootloader_support.a:secure_boot.*(.literal .text .literal.* .text.*) - *libbootloader_support.a:secure_boot_signatures.*(.literal .text .literal.* .text.*) + *libbootloader_support.a:secure_boot_signatures_bootloader.*(.literal .text .literal.* .text.*) *libmicro-ecc.a:*.*(.literal .text .literal.* .text.*) *libspi_flash.a:*.*(.literal .text .literal.* .text.*) *libhal.a:wdt_hal_iram.*(.literal .text .literal.* .text.*) diff --git a/components/bootloader/subproject/main/ld/esp32s2/bootloader.ld b/components/bootloader/subproject/main/ld/esp32s2/bootloader.ld index 62b51c9193..0c23769d82 100644 --- a/components/bootloader/subproject/main/ld/esp32s2/bootloader.ld +++ b/components/bootloader/subproject/main/ld/esp32s2/bootloader.ld @@ -39,7 +39,7 @@ SECTIONS *libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*) *libbootloader_support.a:flash_partitions.*(.literal .text .literal.* .text.*) *libbootloader_support.a:secure_boot.*(.literal .text .literal.* .text.*) - *libbootloader_support.a:secure_boot_signatures.*(.literal .text .literal.* .text.*) + *libbootloader_support.a:secure_boot_signatures_bootloader.*(.literal .text .literal.* .text.*) *libmicro-ecc.a:*.*(.literal .text .literal.* .text.*) *libspi_flash.a:*.*(.literal .text .literal.* .text.*) *libhal.a:wdt_hal_iram.*(.literal .text .literal.* .text.*) diff --git a/components/bootloader/subproject/main/ld/esp32s3/bootloader.ld b/components/bootloader/subproject/main/ld/esp32s3/bootloader.ld index 61f0f2770a..2380e4aad2 100644 --- a/components/bootloader/subproject/main/ld/esp32s3/bootloader.ld +++ b/components/bootloader/subproject/main/ld/esp32s3/bootloader.ld @@ -40,7 +40,7 @@ SECTIONS *libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*) *libbootloader_support.a:flash_partitions.*(.literal .text .literal.* .text.*) *libbootloader_support.a:secure_boot.*(.literal .text .literal.* .text.*) - *libbootloader_support.a:secure_boot_signatures.*(.literal .text .literal.* .text.*) + *libbootloader_support.a:secure_boot_signatures_bootloader.*(.literal .text .literal.* .text.*) *libmicro-ecc.a:*.*(.literal .text .literal.* .text.*) *libspi_flash.a:*.*(.literal .text .literal.* .text.*) *libhal.a:wdt_hal_iram.*(.literal .text .literal.* .text.*) diff --git a/components/bootloader_support/CMakeLists.txt b/components/bootloader_support/CMakeLists.txt index 63a77922b8..160400ff33 100644 --- a/components/bootloader_support/CMakeLists.txt +++ b/components/bootloader_support/CMakeLists.txt @@ -35,16 +35,28 @@ else() "src/idf/bootloader_sha.c") set(include_dirs "include") set(priv_include_dirs "include_bootloader") - set(priv_requires spi_flash mbedtls efuse) + set(priv_requires spi_flash mbedtls efuse app_update) 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") +if(BOOTLOADER_BUILD) + if(CONFIG_SECURE_SIGNED_ON_BOOT) + if(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME) + list(APPEND srcs "src/secure_boot_v1/secure_boot_signatures_bootloader.c") + endif() + + if(CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME) + list(APPEND srcs "src/secure_boot_v2/secure_boot_signatures_bootloader.c") + endif() + endif() +else() + if(CONFIG_SECURE_SIGNED_ON_UPDATE) + if(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME) + list(APPEND srcs "src/secure_boot_v1/secure_boot_signatures_app.c") + endif() + + if(CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME) + list(APPEND srcs "src/secure_boot_v2/secure_boot_signatures_app.c") + endif() endif() endif() diff --git a/components/bootloader_support/component.mk b/components/bootloader_support/component.mk index 26b2a59b8b..ecf90dd359 100644 --- a/components/bootloader_support/component.mk +++ b/components/bootloader_support/component.mk @@ -34,10 +34,13 @@ COMPONENT_OBJEXCLUDE += src/bootloader_flash_config_esp32s2.o \ src/bootloader_random_esp32c3.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 +COMPONENT_OBJEXCLUDE += src/secure_boot_v1/secure_boot_signatures_bootloader.o \ + src/secure_boot_v1/secure_boot_signatures_app.o endif + +ifndef CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME +COMPONENT_OBJEXCLUDE += src/secure_boot_v2/secure_boot_signatures_bootloader.o \ + src/secure_boot_v2/secure_boot_signatures_app.o endif ifndef CONFIG_SECURE_BOOT diff --git a/components/bootloader_support/include/esp_image_format.h b/components/bootloader_support/include/esp_image_format.h index f495933a16..7e7e6a28e1 100644 --- a/components/bootloader_support/include/esp_image_format.h +++ b/components/bootloader_support/include/esp_image_format.h @@ -106,6 +106,20 @@ _Static_assert(sizeof(rtc_retain_mem_t) <= ESP_BOOTLOADER_RESERVE_RTC, "Reserved */ esp_err_t esp_image_verify(esp_image_load_mode_t mode, const esp_partition_pos_t *part, esp_image_metadata_t *data); +/** + * @brief Get metadata of app + * + * If encryption is enabled, data will be transparently decrypted. + * + * @param part Partition to load the app from. + * @param[out] metadata Pointer to the image metadata structure which is be filled in by this function. + * Fields will all be initialised by this function. + * + * @return + * - ESP_OK if filling of metadata was successful + */ +esp_err_t esp_image_get_metadata(const esp_partition_pos_t *part, esp_image_metadata_t *metadata); + /** * @brief Verify and load an app image (available only in space of bootloader). * diff --git a/components/bootloader_support/include/esp_secure_boot.h b/components/bootloader_support/include/esp_secure_boot.h index 71e905962b..9e132cd74a 100644 --- a/components/bootloader_support/include/esp_secure_boot.h +++ b/components/bootloader_support/include/esp_secure_boot.h @@ -19,17 +19,22 @@ #include "esp_image_format.h" #include "esp_rom_efuse.h" #include "sdkconfig.h" +#include "esp_rom_crc.h" #if CONFIG_IDF_TARGET_ESP32 +#include "esp32/rom/efuse.h" #include "esp32/rom/secure_boot.h" #elif CONFIG_IDF_TARGET_ESP32S2 #include "esp32s2/rom/efuse.h" +#include "esp32s2/rom/secure_boot.h" #elif CONFIG_IDF_TARGET_ESP32C3 #include "esp32c3/rom/efuse.h" +#include "esp32c3/rom/secure_boot.h" +#elif CONFIG_IDF_TARGET_ESP32S3 +#include "esp32s3/rom/efuse.h" +#include "esp32s3/rom/secure_boot.h" #endif -typedef struct ets_secure_boot_signature ets_secure_boot_signature_t; - #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" @@ -45,6 +50,8 @@ extern "C" { Can be compiled as part of app or bootloader code. */ +#define ESP_SECURE_BOOT_DIGEST_LEN 32 + /** @brief Is secure boot currently enabled in hardware? * * This means that the ROM bootloader code will only boot @@ -181,6 +188,16 @@ typedef struct { */ esp_err_t esp_secure_boot_verify_ecdsa_signature_block(const esp_secure_boot_sig_block_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest); +#if !CONFIG_IDF_TARGET_ESP32 || CONFIG_ESP32_REV_MIN_3 +/** + * @brief Structure to hold public key digests calculated from the signature blocks of a single image. + * + * Each image can have one or more signature blocks (up to SECURE_BOOT_NUM_BLOCKS). Each signature block includes a public key. + */ +typedef struct { + uint8_t key_digests[SECURE_BOOT_NUM_BLOCKS][ESP_SECURE_BOOT_DIGEST_LEN]; /* SHA of the public key components in the signature block */ + unsigned num_digests; /* Number of valid digests, starting at index 0 */ +} esp_image_sig_public_key_digests_t; /** @brief Verify the RSA secure boot signature block for Secure Boot V2. * @@ -194,6 +211,7 @@ esp_err_t esp_secure_boot_verify_ecdsa_signature_block(const esp_secure_boot_sig * */ esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest); +#endif // !CONFIG_IDF_TARGET_ESP32 || CONFIG_ESP32_REV_MIN_3 /** @brief Legacy ECDSA verification function * diff --git a/components/bootloader_support/src/esp32/secure_boot.c b/components/bootloader_support/src/esp32/secure_boot.c index 2df9b95863..bb293ccb06 100644 --- a/components/bootloader_support/src/esp32/secure_boot.c +++ b/components/bootloader_support/src/esp32/secure_boot.c @@ -19,7 +19,6 @@ #include "esp_log.h" #include "esp32/rom/cache.h" -#include "esp_rom_crc.h" #include "soc/efuse_periph.h" #include "soc/rtc_periph.h" @@ -223,16 +222,12 @@ esp_err_t esp_secure_boot_permanently_enable(void) #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 = esp_rom_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)) { + if (sig_block->block[0].magic_byte == ETS_SECURE_BOOT_V2_SIGNATURE_MAGIC + && sig_block->block[0].block_crc == crc + && !memcmp(digest, sig_block->block[0].image_digest, ESP_SECURE_BOOT_DIGEST_LEN)) { ESP_LOGI(TAG, "valid signature block found"); return ESP_OK; } @@ -243,7 +238,7 @@ static esp_err_t secure_boot_v2_digest_generate(uint32_t flash_offset, uint32_t { esp_err_t ret = ESP_FAIL; - uint8_t image_digest[DIGEST_LEN] = {0}; + uint8_t image_digest[ESP_SECURE_BOOT_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) { @@ -266,7 +261,7 @@ static esp_err_t secure_boot_v2_digest_generate(uint32_t flash_offset, uint32_t } /* Verifying Signature block */ - uint8_t verified_digest[DIGEST_LEN] = {0}; + uint8_t verified_digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0}; /* Generating the SHA of the public key components in the signature block */ bootloader_sha256_handle_t sig_block_sha; @@ -318,7 +313,7 @@ esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *imag return ret; } - uint8_t boot_pub_key_digest[DIGEST_LEN]; + uint8_t boot_pub_key_digest[ESP_SECURE_BOOT_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; @@ -350,7 +345,7 @@ esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *imag } ESP_LOGI(TAG, "Burning public key hash to efuse."); - ret = esp_efuse_write_block(EFUSE_BLK2, boot_pub_key_digest, 0, (DIGEST_LEN * 8)); + ret = esp_efuse_write_block(EFUSE_BLK2, boot_pub_key_digest, 0, (ESP_SECURE_BOOT_DIGEST_LEN * 8)); if (ret != ESP_OK) { ESP_LOGE(TAG, "Writing public key hash to efuse failed."); return ret; @@ -366,7 +361,7 @@ esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *imag efuse_blk2_digest[5] = efuse_blk2_r5; efuse_blk2_digest[6] = efuse_blk2_r6; efuse_blk2_digest[7] = efuse_blk2_r7; - memcpy(boot_pub_key_digest, efuse_blk2_digest, DIGEST_LEN); + memcpy(boot_pub_key_digest, efuse_blk2_digest, ESP_SECURE_BOOT_DIGEST_LEN); ESP_LOGW(TAG, "Using pre-loaded secure boot v2 public key digest in EFUSE block 2"); } @@ -380,7 +375,7 @@ esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *imag efuse_key_write_protected = true; } - uint8_t app_pub_key_digest[DIGEST_LEN]; + uint8_t app_pub_key_digest[ESP_SECURE_BOOT_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."); @@ -388,7 +383,7 @@ esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *imag } /* 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) { + if (memcmp(boot_pub_key_digest, app_pub_key_digest, ESP_SECURE_BOOT_DIGEST_LEN) != 0) { ESP_LOGE(TAG, "Application not signed with a valid private key."); return ESP_FAIL; } diff --git a/components/bootloader_support/src/esp32/secure_boot_signatures.c b/components/bootloader_support/src/esp32/secure_boot_signatures.c deleted file mode 100644 index e38e98201b..0000000000 --- a/components/bootloader_support/src/esp32/secure_boot_signatures.c +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#include "sdkconfig.h" - -#include "bootloader_flash_priv.h" -#include "bootloader_sha.h" -#include "bootloader_utility.h" -#include "esp_log.h" -#include "esp_image_format.h" -#include "esp_secure_boot.h" -#include "esp_spi_flash.h" -#include "esp_fault.h" -#include "esp32/rom/sha.h" -#include "uECC_verify_antifault.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 - -esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length) -{ - uint8_t digest[DIGEST_LEN]; - uint8_t verified_digest[DIGEST_LEN] = { 0 }; /* ignored in this function */ - const esp_secure_boot_sig_block_t *sigblock; - - 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, length, digest); - if (err != ESP_OK) { - return err; - } - - // 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) { - ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", src_addr + length, sizeof(esp_secure_boot_sig_block_t)); - return ESP_FAIL; - } - // Verify the signature - err = esp_secure_boot_verify_ecdsa_signature_block(sigblock, digest, verified_digest); - // Unmap - bootloader_munmap(sigblock); - - return err; -} - -esp_err_t esp_secure_boot_verify_signature_block(const esp_secure_boot_sig_block_t *sig_block, const uint8_t *image_digest) -{ - uint8_t verified_digest[DIGEST_LEN] = { 0 }; - return esp_secure_boot_verify_ecdsa_signature_block(sig_block, image_digest, verified_digest); -} - -esp_err_t esp_secure_boot_verify_ecdsa_signature_block(const esp_secure_boot_sig_block_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest) -{ - ptrdiff_t keylen; - - keylen = signature_verification_key_end - signature_verification_key_start; - if (keylen != SIGNATURE_VERIFICATION_KEYLEN) { - ESP_LOGE(TAG, "Embedded public verification key has wrong length %d", keylen); - return ESP_FAIL; - } - - if (sig_block->version != 0) { - ESP_LOGE(TAG, "image has invalid signature version field 0x%08x", sig_block->version); - return ESP_FAIL; - } - - ESP_LOGD(TAG, "Verifying secure boot signature"); - - bool is_valid; - is_valid = uECC_verify_antifault(signature_verification_key_start, - image_digest, - DIGEST_LEN, - sig_block->signature, - uECC_secp256r1(), - verified_digest); - 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}; - uint8_t verified_digest[DIGEST_LEN] = {0}; // ignored in this function - 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_rsa_signature_block(sig_block, digest, verified_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_rsa_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest) -{ - secure_boot_v2_status_t r; - uint8_t efuse_trusted_digest[DIGEST_LEN] = {0}, sig_block_trusted_digest[DIGEST_LEN] = {0}; - - 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 CONFIG_SECURE_BOOT_V2_ENABLED - if (memcmp(efuse_trusted_digest, sig_block_trusted_digest, DIGEST_LEN) != 0) { - /* Most likely explanation for this is that BLK2 is empty, and we're going to burn it - after we verify that the signature is valid. However, if BLK2 is not empty then we need to - fail here. - */ - bool all_zeroes = true; - for (int i = 0; i < DIGEST_LEN; i++) { - all_zeroes = all_zeroes && (efuse_trusted_digest[i] == 0); - } - if (!all_zeroes) { - ESP_LOGE(TAG, "Different public key digest burned to eFuse BLK2"); - return ESP_ERR_INVALID_STATE; - } - } - - ESP_FAULT_ASSERT(!ets_use_secure_boot_v2()); -#endif - - 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 diff --git a/components/bootloader_support/src/esp32c3/secure_boot.c b/components/bootloader_support/src/esp32c3/secure_boot.c index d6adb6f0fb..cdc89f8b80 100644 --- a/components/bootloader_support/src/esp32c3/secure_boot.c +++ b/components/bootloader_support/src/esp32c3/secure_boot.c @@ -31,17 +31,11 @@ static const char *TAG = "secure_boot_v2"; #define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1)) -#define SIG_BLOCK_MAGIC_BYTE 0xe7 -#define CRC_SIGN_BLOCK_LEN 1196 -#define SIG_BLOCK_PADDING 4096 - -#define DIGEST_LEN 32 - /* A signature block is valid when it has correct magic byte, crc and image digest. */ static esp_err_t validate_signature_block(const ets_secure_boot_sig_block_t *block, int block_num, const uint8_t *image_digest) { uint32_t crc = esp_rom_crc32_le(0, (uint8_t *)block, CRC_SIGN_BLOCK_LEN); - if (block->magic_byte != SIG_BLOCK_MAGIC_BYTE) { + if (block->magic_byte != ETS_SECURE_BOOT_V2_SIGNATURE_MAGIC) { // All signature blocks have been parsed, no new signature block present. ESP_LOGD(TAG, "Signature block(%d) invalid/absent.", block_num); return ESP_FAIL; @@ -50,7 +44,7 @@ static esp_err_t validate_signature_block(const ets_secure_boot_sig_block_t *blo ESP_LOGE(TAG, "Magic byte correct but incorrect crc."); return ESP_FAIL; } - if (memcmp(image_digest, block->image_digest, DIGEST_LEN)) { + if (memcmp(image_digest, block->image_digest, ESP_SECURE_BOOT_DIGEST_LEN)) { ESP_LOGE(TAG, "Magic byte & CRC correct but incorrect image digest."); return ESP_FAIL; } else { @@ -61,19 +55,6 @@ static esp_err_t validate_signature_block(const ets_secure_boot_sig_block_t *blo return ESP_FAIL; } -/* Structure to hold public key digests calculated from the signature blocks of a single image. - - Each image can have one or more signature blocks (up to SECURE_BOOT_NUM_BLOCKS). Each signature block - includes a public key. - - Different to the ROM ets_secure_boot_key_digests_t structure which holds pointers to eFuse data with digests, - in this data structure the digest data is included. -*/ -typedef struct { - uint8_t key_digests[SECURE_BOOT_NUM_BLOCKS][DIGEST_LEN]; - unsigned num_digests; /* Number of valid digests, starting at index 0 */ -} image_sig_public_key_digests_t; - /* Generates the public key digests of the valid public keys in an image's signature block, verifies each signature, and stores the key digests in the public_key_digests structure. @@ -89,16 +70,16 @@ typedef struct { @return - ESP_OK if no signatures failed to verify, or if no valid signature blocks are found at all. - ESP_FAIL if there's a valid signature block that doesn't verify using the included public key (unexpected!) */ -static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uint32_t flash_size, image_sig_public_key_digests_t *public_key_digests) +static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uint32_t flash_size, esp_image_sig_public_key_digests_t *public_key_digests) { esp_err_t ret; - uint8_t image_digest[DIGEST_LEN] = {0}; - uint8_t __attribute__((aligned(4))) key_digest[DIGEST_LEN] = {0}; + uint8_t image_digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0}; + uint8_t __attribute__((aligned(4))) key_digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0}; size_t sig_block_addr = flash_offset + ALIGN_UP(flash_size, FLASH_SECTOR_SIZE); ESP_LOGD(TAG, "calculating public key digests for sig blocks of image offset 0x%x (sig block offset 0x%x)", flash_offset, sig_block_addr); - bzero(public_key_digests, sizeof(image_sig_public_key_digests_t)); + bzero(public_key_digests, sizeof(esp_image_sig_public_key_digests_t)); ret = bootloader_sha256_flash_contents(flash_offset, sig_block_addr - flash_offset, image_digest); if (ret != ESP_OK) { @@ -129,7 +110,7 @@ static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uin bootloader_sha256_finish(sig_block_sha, key_digest); // Check we can verify the image using this signature and this key - uint8_t temp_verified_digest[DIGEST_LEN]; + uint8_t temp_verified_digest[ESP_SECURE_BOOT_DIGEST_LEN]; bool verified = ets_rsa_pss_verify(&block->key, block->signature, image_digest, temp_verified_digest); if (!verified) { @@ -142,7 +123,7 @@ static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uin } ESP_LOGD(TAG, "Signature block (%d) is verified", i); /* Copy the key digest to the buffer provided by the caller */ - memcpy((void *)public_key_digests->key_digests[i], key_digest, DIGEST_LEN); + memcpy((void *)public_key_digests->key_digests[i], key_digest, ESP_SECURE_BOOT_DIGEST_LEN); public_key_digests->num_digests++; } @@ -173,8 +154,8 @@ static esp_err_t check_and_generate_secure_boot_keys(const esp_image_metadata_t ESP_LOGI(TAG, "Secure boot digests %s", has_secure_boot_digest ? "already present":"absent, generating.."); if (!has_secure_boot_digest) { - image_sig_public_key_digests_t boot_key_digests = {0}; - image_sig_public_key_digests_t app_key_digests = {0}; + esp_image_sig_public_key_digests_t boot_key_digests = {0}; + esp_image_sig_public_key_digests_t app_key_digests = {0}; /* Generate the bootloader public key digests */ ret = s_calculate_image_public_key_digests(bootloader_data.start_addr, bootloader_data.image_len - SIG_BLOCK_PADDING, &boot_key_digests); @@ -234,7 +215,7 @@ static esp_err_t check_and_generate_secure_boot_keys(const esp_image_metadata_t } for (int j = 0; j < app_key_digests.num_digests; j++) { - if (!memcmp(boot_key_digests.key_digests[i], app_key_digests.key_digests[j], DIGEST_LEN)) { + if (!memcmp(boot_key_digests.key_digests[i], app_key_digests.key_digests[j], ESP_SECURE_BOOT_DIGEST_LEN)) { ESP_LOGI(TAG, "Application key(%d) matches with bootloader key(%d).", j, i); match = true; } diff --git a/components/bootloader_support/src/esp32c3/secure_boot_signatures.c b/components/bootloader_support/src/esp32c3/secure_boot_signatures.c deleted file mode 100644 index 2c489c1e6a..0000000000 --- a/components/bootloader_support/src/esp32c3/secure_boot_signatures.c +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "sdkconfig.h" - -#include -#include "esp_fault.h" -#include "bootloader_flash_priv.h" -#include "bootloader_sha.h" -#include "bootloader_utility.h" -#include "esp_log.h" -#include "esp_image_format.h" -#include "esp_secure_boot.h" -#include "esp32c3/rom/secure_boot.h" - -static const char* TAG = "secure_boot"; - -#define DIGEST_LEN 32 -#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]; - uint8_t verified_digest[DIGEST_LEN] = { 0 }; /* Note: this function doesn't do any anti-FI checks on this buffer */ - const uint8_t *data; - - ESP_LOGD(TAG, "verifying signature src_addr 0x%x length 0x%x", src_addr, length); - - /* 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, length + sizeof(struct ets_secure_boot_sig_block)); - 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; - } - - /* 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 = (const ets_secure_boot_signature_t *)(data + length); - int r = esp_secure_boot_verify_rsa_signature_block(sig, digest, verified_digest); - bootloader_munmap(data); - - return (r == ETS_OK) ? ESP_OK : ESP_FAIL; -} - -esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest) -{ - ets_secure_boot_key_digests_t trusted_keys; - ets_secure_boot_key_digests_t trusted_key_copies[2]; - ETS_STATUS r; - ets_secure_boot_status_t sb_result; - - memset(&trusted_keys, 0, sizeof(ets_secure_boot_key_digests_t)); - memset(trusted_key_copies, 0, 2 * sizeof(ets_secure_boot_key_digests_t)); - - if (!esp_secure_boot_enabled()) { - return ESP_OK; - } - - r = ets_secure_boot_read_key_digests(&trusted_keys); - if (r != ETS_OK) { - ESP_LOGI(TAG, "Could not read secure boot digests!"); - return ESP_FAIL; - } - - // Create the copies for FI checks (assuming result is ETS_OK, if it's not then it'll fail the fault check anyhow) - ets_secure_boot_read_key_digests(&trusted_key_copies[0]); - ets_secure_boot_read_key_digests(&trusted_key_copies[1]); - ESP_FAULT_ASSERT(memcmp(&trusted_keys, &trusted_key_copies[0], sizeof(ets_secure_boot_key_digests_t)) == 0); - ESP_FAULT_ASSERT(memcmp(&trusted_keys, &trusted_key_copies[1], sizeof(ets_secure_boot_key_digests_t)) == 0); - - ESP_LOGI(TAG, "Verifying with RSA-PSS boot..."); - sb_result = ets_secure_boot_verify_signature(sig_block, image_digest, &trusted_keys, verified_digest); - return (sb_result == SB_SUCCESS) ? ESP_OK : ESP_FAIL; -} diff --git a/components/bootloader_support/src/esp32s2/secure_boot.c b/components/bootloader_support/src/esp32s2/secure_boot.c index 7d4264c726..c79203ed84 100644 --- a/components/bootloader_support/src/esp32s2/secure_boot.c +++ b/components/bootloader_support/src/esp32s2/secure_boot.c @@ -31,17 +31,11 @@ static const char *TAG = "secure_boot_v2"; #define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1)) -#define SIG_BLOCK_MAGIC_BYTE 0xe7 -#define CRC_SIGN_BLOCK_LEN 1196 -#define SIG_BLOCK_PADDING 4096 - -#define DIGEST_LEN 32 - /* A signature block is valid when it has correct magic byte, crc and image digest. */ static esp_err_t validate_signature_block(const ets_secure_boot_sig_block_t *block, int block_num, const uint8_t *image_digest) { uint32_t crc = esp_rom_crc32_le(0, (uint8_t *)block, CRC_SIGN_BLOCK_LEN); - if (block->magic_byte != SIG_BLOCK_MAGIC_BYTE) { + if (block->magic_byte != ETS_SECURE_BOOT_V2_SIGNATURE_MAGIC) { // All signature blocks have been parsed, no new signature block present. ESP_LOGD(TAG, "Signature block(%d) invalid/absent.", block_num); return ESP_FAIL; @@ -50,7 +44,7 @@ static esp_err_t validate_signature_block(const ets_secure_boot_sig_block_t *blo ESP_LOGE(TAG, "Magic byte correct but incorrect crc."); return ESP_FAIL; } - if (memcmp(image_digest, block->image_digest, DIGEST_LEN)) { + if (memcmp(image_digest, block->image_digest, ESP_SECURE_BOOT_DIGEST_LEN)) { ESP_LOGE(TAG, "Magic byte & CRC correct but incorrect image digest."); return ESP_FAIL; } else { @@ -61,19 +55,6 @@ static esp_err_t validate_signature_block(const ets_secure_boot_sig_block_t *blo return ESP_FAIL; } -/* Structure to hold public key digests calculated from the signature blocks of a single image. - - Each image can have one or more signature blocks (up to SECURE_BOOT_NUM_BLOCKS). Each signature block - includes a public key. - - Different to the ROM ets_secure_boot_key_digests_t structure which holds pointers to eFuse data with digests, - in this data structure the digest data is included. -*/ -typedef struct { - uint8_t key_digests[SECURE_BOOT_NUM_BLOCKS][DIGEST_LEN]; - unsigned num_digests; /* Number of valid digests, starting at index 0 */ -} image_sig_public_key_digests_t; - /* Generates the public key digests of the valid public keys in an image's signature block, verifies each signature, and stores the key digests in the public_key_digests structure. @@ -89,16 +70,16 @@ typedef struct { @return - ESP_OK if no signatures failed to verify, or if no valid signature blocks are found at all. - ESP_FAIL if there's a valid signature block that doesn't verify using the included public key (unexpected!) */ -static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uint32_t flash_size, image_sig_public_key_digests_t *public_key_digests) +static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uint32_t flash_size, esp_image_sig_public_key_digests_t *public_key_digests) { esp_err_t ret; - uint8_t image_digest[DIGEST_LEN] = {0}; - uint8_t __attribute__((aligned(4))) key_digest[DIGEST_LEN] = {0}; + uint8_t image_digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0}; + uint8_t __attribute__((aligned(4))) key_digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0}; size_t sig_block_addr = flash_offset + ALIGN_UP(flash_size, FLASH_SECTOR_SIZE); ESP_LOGD(TAG, "calculating public key digests for sig blocks of image offset 0x%x (sig block offset 0x%x)", flash_offset, sig_block_addr); - bzero(public_key_digests, sizeof(image_sig_public_key_digests_t)); + bzero(public_key_digests, sizeof(esp_image_sig_public_key_digests_t)); ret = bootloader_sha256_flash_contents(flash_offset, sig_block_addr - flash_offset, image_digest); if (ret != ESP_OK) { @@ -129,7 +110,7 @@ static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uin bootloader_sha256_finish(sig_block_sha, key_digest); // Check we can verify the image using this signature and this key - uint8_t temp_verified_digest[DIGEST_LEN]; + uint8_t temp_verified_digest[ESP_SECURE_BOOT_DIGEST_LEN]; bool verified = ets_rsa_pss_verify(&block->key, block->signature, image_digest, temp_verified_digest); if (!verified) { @@ -142,7 +123,7 @@ static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uin } ESP_LOGD(TAG, "Signature block (%d) is verified", i); /* Copy the key digest to the buffer provided by the caller */ - memcpy((void *)public_key_digests->key_digests[i], key_digest, DIGEST_LEN); + memcpy((void *)public_key_digests->key_digests[i], key_digest, ESP_SECURE_BOOT_DIGEST_LEN); public_key_digests->num_digests++; } @@ -173,8 +154,8 @@ static esp_err_t check_and_generate_secure_boot_keys(const esp_image_metadata_t ESP_LOGI(TAG, "Secure boot digests %s", has_secure_boot_digest ? "already present":"absent, generating.."); if (!has_secure_boot_digest) { - image_sig_public_key_digests_t boot_key_digests = {0}; - image_sig_public_key_digests_t app_key_digests = {0}; + esp_image_sig_public_key_digests_t boot_key_digests = {0}; + esp_image_sig_public_key_digests_t app_key_digests = {0}; /* Generate the bootloader public key digests */ ret = s_calculate_image_public_key_digests(bootloader_data.start_addr, bootloader_data.image_len - SIG_BLOCK_PADDING, &boot_key_digests); @@ -234,7 +215,7 @@ static esp_err_t check_and_generate_secure_boot_keys(const esp_image_metadata_t } for (int j = 0; j < app_key_digests.num_digests; j++) { - if (!memcmp(boot_key_digests.key_digests[i], app_key_digests.key_digests[j], DIGEST_LEN)) { + if (!memcmp(boot_key_digests.key_digests[i], app_key_digests.key_digests[j], ESP_SECURE_BOOT_DIGEST_LEN)) { ESP_LOGI(TAG, "Application key(%d) matches with bootloader key(%d).", j, i); match = true; } diff --git a/components/bootloader_support/src/esp32s2/secure_boot_signatures.c b/components/bootloader_support/src/esp32s2/secure_boot_signatures.c deleted file mode 100644 index 3da88b262c..0000000000 --- a/components/bootloader_support/src/esp32s2/secure_boot_signatures.c +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#include "sdkconfig.h" - -#include -#include "esp_fault.h" -#include "bootloader_flash_priv.h" -#include "bootloader_sha.h" -#include "bootloader_utility.h" -#include "esp_log.h" -#include "esp_image_format.h" -#include "esp_secure_boot.h" -#include "esp32s2/rom/secure_boot.h" - -static const char* TAG = "secure_boot"; - -#define DIGEST_LEN 32 -#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]; - uint8_t verified_digest[DIGEST_LEN] = { 0 }; /* Note: this function doesn't do any anti-FI checks on this buffer */ - const uint8_t *data; - - ESP_LOGD(TAG, "verifying signature src_addr 0x%x length 0x%x", src_addr, length); - - /* 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, length + sizeof(struct ets_secure_boot_sig_block)); - 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; - } - - /* 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 = (const ets_secure_boot_signature_t *)(data + length); - int r = esp_secure_boot_verify_rsa_signature_block(sig, digest, verified_digest); - bootloader_munmap(data); - - return (r == ETS_OK) ? ESP_OK : ESP_FAIL; -} - -esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest) -{ - ets_secure_boot_key_digests_t trusted_keys; - ets_secure_boot_key_digests_t trusted_key_copies[2]; - ETS_STATUS r; - ets_secure_boot_status_t sb_result; - - memset(&trusted_keys, 0, sizeof(ets_secure_boot_key_digests_t)); - memset(trusted_key_copies, 0, 2 * sizeof(ets_secure_boot_key_digests_t)); - - if (!esp_secure_boot_enabled()) { - return ESP_OK; - } - - r = ets_secure_boot_read_key_digests(&trusted_keys); - if (r != ETS_OK) { - ESP_LOGI(TAG, "Could not read secure boot digests!"); - return ESP_FAIL; - } - - // Create the copies for FI checks (assuming result is ETS_OK, if it's not then it'll fail the fault check anyhow) - ets_secure_boot_read_key_digests(&trusted_key_copies[0]); - ets_secure_boot_read_key_digests(&trusted_key_copies[1]); - ESP_FAULT_ASSERT(memcmp(&trusted_keys, &trusted_key_copies[0], sizeof(ets_secure_boot_key_digests_t)) == 0); - ESP_FAULT_ASSERT(memcmp(&trusted_keys, &trusted_key_copies[1], sizeof(ets_secure_boot_key_digests_t)) == 0); - - ESP_LOGI(TAG, "Verifying with RSA-PSS boot..."); - sb_result = ets_secure_boot_verify_signature(sig_block, image_digest, &trusted_keys, verified_digest); - return (sb_result == SB_SUCCESS) ? ESP_OK : ESP_FAIL; -} diff --git a/components/bootloader_support/src/esp32s3/secure_boot.c b/components/bootloader_support/src/esp32s3/secure_boot.c index 184b174899..e501cc7d08 100644 --- a/components/bootloader_support/src/esp32s3/secure_boot.c +++ b/components/bootloader_support/src/esp32s3/secure_boot.c @@ -31,17 +31,11 @@ static const char *TAG = "secure_boot_v2"; #define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1)) -#define SIG_BLOCK_MAGIC_BYTE 0xe7 -#define CRC_SIGN_BLOCK_LEN 1196 -#define SIG_BLOCK_PADDING 4096 - -#define DIGEST_LEN 32 - /* A signature block is valid when it has correct magic byte, crc and image digest. */ static esp_err_t validate_signature_block(const ets_secure_boot_sig_block_t *block, int block_num, const uint8_t *image_digest) { uint32_t crc = esp_rom_crc32_le(0, (uint8_t *)block, CRC_SIGN_BLOCK_LEN); - if (block->magic_byte != SIG_BLOCK_MAGIC_BYTE) { + if (block->magic_byte != ETS_SECURE_BOOT_V2_SIGNATURE_MAGIC) { // All signature blocks have been parsed, no new signature block present. ESP_LOGD(TAG, "Signature block(%d) invalid/absent.", block_num); return ESP_FAIL; @@ -50,7 +44,7 @@ static esp_err_t validate_signature_block(const ets_secure_boot_sig_block_t *blo ESP_LOGE(TAG, "Magic byte correct but incorrect crc."); return ESP_FAIL; } - if (memcmp(image_digest, block->image_digest, DIGEST_LEN)) { + if (memcmp(image_digest, block->image_digest, ESP_SECURE_BOOT_DIGEST_LEN)) { ESP_LOGE(TAG, "Magic byte & CRC correct but incorrect image digest."); return ESP_FAIL; } else { @@ -61,19 +55,6 @@ static esp_err_t validate_signature_block(const ets_secure_boot_sig_block_t *blo return ESP_FAIL; } -/* Structure to hold public key digests calculated from the signature blocks of a single image. - - Each image can have one or more signature blocks (up to SECURE_BOOT_NUM_BLOCKS). Each signature block - includes a public key. - - Different to the ROM ets_secure_boot_key_digests_t structure which holds pointers to eFuse data with digests, - in this data structure the digest data is included. -*/ -typedef struct { - uint8_t key_digests[SECURE_BOOT_NUM_BLOCKS][DIGEST_LEN]; - unsigned num_digests; /* Number of valid digests, starting at index 0 */ -} image_sig_public_key_digests_t; - /* Generates the public key digests of the valid public keys in an image's signature block, verifies each signature, and stores the key digests in the public_key_digests structure. @@ -89,16 +70,16 @@ typedef struct { @return - ESP_OK if no signatures failed to verify, or if no valid signature blocks are found at all. - ESP_FAIL if there's a valid signature block that doesn't verify using the included public key (unexpected!) */ -static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uint32_t flash_size, image_sig_public_key_digests_t *public_key_digests) +static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uint32_t flash_size, esp_image_sig_public_key_digests_t *public_key_digests) { esp_err_t ret; - uint8_t image_digest[DIGEST_LEN] = {0}; - uint8_t __attribute__((aligned(4))) key_digest[DIGEST_LEN] = {0}; + uint8_t image_digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0}; + uint8_t __attribute__((aligned(4))) key_digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0}; size_t sig_block_addr = flash_offset + ALIGN_UP(flash_size, FLASH_SECTOR_SIZE); ESP_LOGD(TAG, "calculating public key digests for sig blocks of image offset 0x%x (sig block offset 0x%x)", flash_offset, sig_block_addr); - bzero(public_key_digests, sizeof(image_sig_public_key_digests_t)); + bzero(public_key_digests, sizeof(esp_image_sig_public_key_digests_t)); ret = bootloader_sha256_flash_contents(flash_offset, sig_block_addr - flash_offset, image_digest); if (ret != ESP_OK) { @@ -129,7 +110,7 @@ static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uin bootloader_sha256_finish(sig_block_sha, key_digest); // Check we can verify the image using this signature and this key - uint8_t temp_verified_digest[DIGEST_LEN]; + uint8_t temp_verified_digest[ESP_SECURE_BOOT_DIGEST_LEN]; bool verified = ets_rsa_pss_verify(&block->key, block->signature, image_digest, temp_verified_digest); if (!verified) { @@ -142,7 +123,7 @@ static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uin } ESP_LOGD(TAG, "Signature block (%d) is verified", i); /* Copy the key digest to the buffer provided by the caller */ - memcpy((void *)public_key_digests->key_digests[i], key_digest, DIGEST_LEN); + memcpy((void *)public_key_digests->key_digests[i], key_digest, ESP_SECURE_BOOT_DIGEST_LEN); public_key_digests->num_digests++; } @@ -173,8 +154,8 @@ static esp_err_t check_and_generate_secure_boot_keys(const esp_image_metadata_t ESP_LOGI(TAG, "Secure boot digests %s", has_secure_boot_digest ? "already present":"absent, generating.."); if (!has_secure_boot_digest) { - image_sig_public_key_digests_t boot_key_digests = {0}; - image_sig_public_key_digests_t app_key_digests = {0}; + esp_image_sig_public_key_digests_t boot_key_digests = {0}; + esp_image_sig_public_key_digests_t app_key_digests = {0}; /* Generate the bootloader public key digests */ ret = s_calculate_image_public_key_digests(bootloader_data.start_addr, bootloader_data.image_len - SIG_BLOCK_PADDING, &boot_key_digests); @@ -234,7 +215,7 @@ static esp_err_t check_and_generate_secure_boot_keys(const esp_image_metadata_t } for (int j = 0; j < app_key_digests.num_digests; j++) { - if (!memcmp(boot_key_digests.key_digests[i], app_key_digests.key_digests[j], DIGEST_LEN)) { + if (!memcmp(boot_key_digests.key_digests[i], app_key_digests.key_digests[j], ESP_SECURE_BOOT_DIGEST_LEN)) { ESP_LOGI(TAG, "Application key(%d) matches with bootloader key(%d).", j, i); match = true; } diff --git a/components/bootloader_support/src/esp32s3/secure_boot_signatures.c b/components/bootloader_support/src/esp32s3/secure_boot_signatures.c deleted file mode 100644 index 7bd377d480..0000000000 --- a/components/bootloader_support/src/esp32s3/secure_boot_signatures.c +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include "sdkconfig.h" -#include "esp_fault.h" -#include "bootloader_flash_priv.h" -#include "bootloader_sha.h" -#include "bootloader_utility.h" -#include "esp_log.h" -#include "esp_image_format.h" -#include "esp_secure_boot.h" -#include "esp32s3/rom/secure_boot.h" - -static const char* TAG = "secure_boot"; - -#define DIGEST_LEN 32 -#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]; - uint8_t verified_digest[DIGEST_LEN] = { 0 }; /* Note: this function doesn't do any anti-FI checks on this buffer */ - const uint8_t *data; - - ESP_LOGD(TAG, "verifying signature src_addr 0x%x length 0x%x", src_addr, length); - - /* 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, length + sizeof(struct ets_secure_boot_sig_block)); - 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; - } - - /* 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 = (const ets_secure_boot_signature_t *)(data + length); - int r = esp_secure_boot_verify_rsa_signature_block(sig, digest, verified_digest); - bootloader_munmap(data); - - return (r == ETS_OK) ? ESP_OK : ESP_FAIL; -} - -esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest) -{ - ets_secure_boot_key_digests_t trusted_keys; - ets_secure_boot_key_digests_t trusted_key_copies[2]; - ETS_STATUS r; - ets_secure_boot_status_t sb_result; - - memset(&trusted_keys, 0, sizeof(ets_secure_boot_key_digests_t)); - memset(trusted_key_copies, 0, 2 * sizeof(ets_secure_boot_key_digests_t)); - - if (!esp_secure_boot_enabled()) { - return ESP_OK; - } - - r = ets_secure_boot_read_key_digests(&trusted_keys); - if (r != ETS_OK) { - ESP_LOGI(TAG, "Could not read secure boot digests!"); - return ESP_FAIL; - } - - // Create the copies for FI checks (assuming result is ETS_OK, if it's not then it'll fail the fault check anyhow) - ets_secure_boot_read_key_digests(&trusted_key_copies[0]); - ets_secure_boot_read_key_digests(&trusted_key_copies[1]); - ESP_FAULT_ASSERT(memcmp(&trusted_keys, &trusted_key_copies[0], sizeof(ets_secure_boot_key_digests_t)) == 0); - ESP_FAULT_ASSERT(memcmp(&trusted_keys, &trusted_key_copies[1], sizeof(ets_secure_boot_key_digests_t)) == 0); - - ESP_LOGI(TAG, "Verifying with RSA-PSS boot..."); - sb_result = ets_secure_boot_verify_signature(sig_block, image_digest, &trusted_keys, verified_digest); - return (sb_result == SB_SUCCESS) ? ESP_OK : ESP_FAIL; -} diff --git a/components/bootloader_support/src/esp_image_format.c b/components/bootloader_support/src/esp_image_format.c index 4ba21cab15..436dbb4902 100644 --- a/components/bootloader_support/src/esp_image_format.c +++ b/components/bootloader_support/src/esp_image_format.c @@ -361,6 +361,45 @@ esp_err_t esp_image_verify(esp_image_load_mode_t mode, const esp_partition_pos_t return image_load(mode, part, data); } +esp_err_t esp_image_get_metadata(const esp_partition_pos_t *part, esp_image_metadata_t *metadata) +{ + if (metadata == NULL || part == NULL || part->size > SIXTEEN_MB) { + return ESP_ERR_INVALID_ARG; + } + + memset(metadata, 0, sizeof(esp_image_metadata_t)); + metadata->start_addr = part->offset; + + esp_err_t err = bootloader_flash_read(metadata->start_addr, &metadata->image, sizeof(esp_image_header_t), true); + if (err != ESP_OK) { + return err; + } + uint32_t next_addr = metadata->start_addr + sizeof(esp_image_header_t); + for (int i = 0; i < metadata->image.segment_count; i++) { + esp_image_segment_header_t *header = &metadata->segments[i]; + err = process_segment(i, next_addr, header, true, false, NULL, NULL); + if (err != ESP_OK) { + return err; + } + next_addr += sizeof(esp_image_segment_header_t); + metadata->segment_data[i] = next_addr; + next_addr += header->data_len; + } + metadata->image_len = next_addr - metadata->start_addr; + + // checksum + uint32_t unpadded_length = metadata->image_len; + uint32_t length = unpadded_length + 1; // Add a byte for the checksum + length = (length + 15) & ~15; // Pad to next full 16 byte block + if (metadata->image.hash_appended) { + // Account for the hash in the total image length + length += HASH_LEN; + } + metadata->image_len = length; + + return ESP_OK; +} + static esp_err_t verify_image_header(uint32_t src_addr, const esp_image_header_t *image, bool silent) { esp_err_t err = ESP_OK; @@ -821,18 +860,18 @@ static esp_err_t verify_secure_boot_signature(bootloader_sha256_handle_t sha_han // Use hash to verify signature block esp_err_t err = ESP_ERR_IMAGE_INVALID; +#if defined(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME) || defined(CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME) const void *sig_block; -#ifdef CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME ESP_FAULT_ASSERT(memcmp(image_digest, verified_digest, HASH_LEN) != 0); /* sanity check that these values start differently */ +#ifdef CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME sig_block = bootloader_mmap(data->start_addr + data->image_len, sizeof(esp_secure_boot_sig_block_t)); err = esp_secure_boot_verify_ecdsa_signature_block(sig_block, image_digest, verified_digest); -#elif CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME - ESP_FAULT_ASSERT(memcmp(image_digest, verified_digest, HASH_LEN) != 0); /* sanity check that these values start differently */ +#else sig_block = bootloader_mmap(end, sizeof(ets_secure_boot_signature_t)); err = esp_secure_boot_verify_rsa_signature_block(sig_block, image_digest, verified_digest); #endif - bootloader_munmap(sig_block); +#endif // CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME or CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME if (err != ESP_OK) { ESP_LOGE(TAG, "Secure boot signature verification failed"); diff --git a/components/bootloader_support/src/idf/secure_boot_signatures.c b/components/bootloader_support/src/idf/secure_boot_signatures.c deleted file mode 100644 index 8c383a4818..0000000000 --- a/components/bootloader_support/src/idf/secure_boot_signatures.c +++ /dev/null @@ -1,339 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#include "sdkconfig.h" - -#include "bootloader_flash_priv.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 -#include "esp_secure_boot.h" - -#ifdef CONFIG_IDF_TARGET_ESP32S2 -#include -#elif CONFIG_IDF_TARGET_ESP32C3 -#include -#endif - -#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 - -esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length) -{ - uint8_t digest[DIGEST_LEN]; - uint8_t verified_digest[DIGEST_LEN]; - const esp_secure_boot_sig_block_t *sigblock; - - 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, length, digest); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Digest calculation failed 0x%x, 0x%x", src_addr, length); - return err; - } - - // Map the signature block and verify the signature - 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_ecdsa_signature_block(sigblock, digest, verified_digest); - bootloader_munmap(sigblock); - return err; -} - -esp_err_t esp_secure_boot_verify_ecdsa_signature_block(const esp_secure_boot_sig_block_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest) -{ -#if !(defined(CONFIG_MBEDTLS_ECDSA_C) && defined(CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED)) - ESP_LOGE(TAG, "Signature verification requires ECDSA & SECP256R1 curve enabled"); - return ESP_ERR_NOT_SUPPORTED; -#else - ptrdiff_t keylen; - - /* Note: in IDF app image verification we don't add any fault injection resistance, boot-time checks only */ - memset(verified_digest, 0, DIGEST_LEN); - - keylen = signature_verification_key_end - signature_verification_key_start; - if (keylen != SIGNATURE_VERIFICATION_KEYLEN) { - ESP_LOGE(TAG, "Embedded public verification key has wrong length %d", keylen); - return ESP_FAIL; - } - - if (sig_block->version != 0) { - ESP_LOGE(TAG, "image has invalid signature version field 0x%08x", sig_block->version); - return ESP_FAIL; - } - - ESP_LOGD(TAG, "Verifying secure boot signature"); - - int ret; - mbedtls_mpi r, s; - - mbedtls_mpi_init(&r); - mbedtls_mpi_init(&s); - - /* Extract r and s components from RAW ECDSA signature of 64 bytes */ -#define ECDSA_INTEGER_LEN 32 - ret = mbedtls_mpi_read_binary(&r, &sig_block->signature[0], ECDSA_INTEGER_LEN); - if (ret != 0) { - ESP_LOGE(TAG, "Failed mbedtls_mpi_read_binary(1), err:%d", ret); - return ESP_FAIL; - } - - ret = mbedtls_mpi_read_binary(&s, &sig_block->signature[ECDSA_INTEGER_LEN], ECDSA_INTEGER_LEN); - if (ret != 0) { - ESP_LOGE(TAG, "Failed mbedtls_mpi_read_binary(2), err:%d", ret); - mbedtls_mpi_free(&r); - return ESP_FAIL; - } - - /* Initialise ECDSA context */ - mbedtls_ecdsa_context ecdsa_context; - mbedtls_ecdsa_init(&ecdsa_context); - - mbedtls_ecp_group_load(&ecdsa_context.grp, MBEDTLS_ECP_DP_SECP256R1); - size_t plen = mbedtls_mpi_size(&ecdsa_context.grp.P); - if (keylen != 2 * plen) { - ESP_LOGE(TAG, "Incorrect ECDSA key length %d", keylen); - ret = ESP_FAIL; - goto cleanup; - } - - /* Extract X and Y components from ECDSA public key */ - MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ecdsa_context.Q.X, signature_verification_key_start, plen)); - MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ecdsa_context.Q.Y, signature_verification_key_start + plen, plen)); - MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&ecdsa_context.Q.Z, 1)); - - ret = mbedtls_ecdsa_verify(&ecdsa_context.grp, image_digest, DIGEST_LEN, &ecdsa_context.Q, &r, &s); - ESP_LOGD(TAG, "Verification result %d", ret); - -cleanup: - mbedtls_mpi_free(&r); - mbedtls_mpi_free(&s); - mbedtls_ecdsa_free(&ecdsa_context); - 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 */ - -#if SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS > 1 -inline static bool digest_matches(const void *trusted, const void *computed) -{ - if (trusted == NULL) { - return false; - } - - // 'trusted' is probably a pointer to read-only efuse registers, - // which only support word reads. memcmp() cannot be guaranteed - // to do word reads, so we make a local copy here (we know that - // memcpy() will do word operations if it can). - uint8_t __attribute__((aligned(4))) trusted_local[ETS_DIGEST_LEN]; - uint8_t __attribute__((aligned(4))) computed_local[ETS_DIGEST_LEN]; - - memcpy(trusted_local, trusted, ETS_DIGEST_LEN); - memcpy(computed_local, computed, ETS_DIGEST_LEN); - return memcmp(trusted_local, computed_local, ETS_DIGEST_LEN) == 0; -} -#endif /* SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS > 1 */ - -esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length) -{ - uint8_t digest[DIGEST_LEN] = {0}; - uint8_t verified_digest[DIGEST_LEN] = {0}; - - /* Rounding off length to the upper 4k boundary */ - uint32_t 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_rsa_signature_block(sig_block, digest, verified_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_rsa_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest) -{ - uint8_t i = 0; -#if CONFIG_SECURE_BOOT_V2_ENABLED /* Verify key against efuse block */ - uint8_t sig_block_key_digest[SECURE_BOOT_NUM_BLOCKS][DIGEST_LEN] = {0}; - - /* Note: in IDF verification we don't add any fault injection resistance, as we don't expect this to be called - during boot-time verification. */ - memset(verified_digest, 0, DIGEST_LEN); - - /* Generating the SHA of the public key components in the signature block */ - for (i = 0; i < SECURE_BOOT_NUM_BLOCKS; i++) { - bootloader_sha256_handle_t sig_block_sha; - sig_block_sha = bootloader_sha256_start(); - bootloader_sha256_data(sig_block_sha, &sig_block->block[i].key, sizeof(sig_block->block[i].key)); - bootloader_sha256_finish(sig_block_sha, (unsigned char *)sig_block_key_digest[i]); - } - -#if SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS == 1 - uint8_t efuse_trusted_digest[DIGEST_LEN] = {0}; - memcpy(efuse_trusted_digest, (uint8_t *) EFUSE_BLK2_RDATA0_REG, sizeof(efuse_trusted_digest)); - - if (memcmp(efuse_trusted_digest, sig_block_key_digest[0], DIGEST_LEN) != 0) { - const uint8_t zeroes[DIGEST_LEN] = {0}; - /* Can't continue if secure boot is enabled, OR if a different digest is already written in efuse BLK2 - - (If BLK2 is empty and Secure Boot is disabled then we assume that it will be enabled later.) - */ - if (esp_secure_boot_enabled() || memcmp(efuse_trusted_digest, zeroes, DIGEST_LEN) != 0) { - ESP_LOGE(TAG, "Public key digest in eFuse BLK2 and the signature block don't match."); - return ESP_FAIL; - } - } -#elif SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS > 1 - bool match = false; - ets_secure_boot_key_digests_t efuse_trusted_digest; - ETS_STATUS r; - r = ets_secure_boot_read_key_digests(&efuse_trusted_digest); - if (r != 0) { - ESP_LOGI(TAG, "Could not read secure boot digests!"); - return ESP_FAIL; - } -#endif /* SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS */ -#endif /* CONFIG_SECURE_BOOT_V2_ENABLED */ - - 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); - mbedtls_ctr_drbg_init(&ctr_drbg); - 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++) { -#if SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS > 1 - for (uint8_t j = 0; j < SECURE_BOOT_NUM_BLOCKS; j++) { - if (digest_matches(efuse_trusted_digest.key_digests[j], sig_block_key_digest[i])) { - ESP_LOGI(TAG, "eFuse key matches(%d) matches the application key(%d).", j, i); - match = true; - break; - } - } - if (match == false) { - continue; // Skip the public keys whose digests don't match. - } -# endif // SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS > 1 - - 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, DIGEST_LEN, - 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); -#if SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS == 1 - return (ret != 0) ? ESP_ERR_IMAGE_INVALID: ESP_OK; -#elif SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS > 1 - return (ret != 0 || match == false) ? ESP_ERR_IMAGE_INVALID: ESP_OK; -#endif /* CONFIG_IDF_TARGET_ESP32 */ -} -#endif diff --git a/components/bootloader_support/src/secure_boot_v1/secure_boot_signatures_app.c b/components/bootloader_support/src/secure_boot_v1/secure_boot_signatures_app.c new file mode 100644 index 0000000000..1ef645812e --- /dev/null +++ b/components/bootloader_support/src/secure_boot_v1/secure_boot_signatures_app.c @@ -0,0 +1,136 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include "sdkconfig.h" + +#include "bootloader_flash_priv.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 + +#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 + +esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length) +{ + uint8_t digest[ESP_SECURE_BOOT_DIGEST_LEN]; + uint8_t verified_digest[ESP_SECURE_BOOT_DIGEST_LEN]; + const esp_secure_boot_sig_block_t *sigblock; + + 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, length, digest); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Digest calculation failed 0x%x, 0x%x", src_addr, length); + return err; + } + + // Map the signature block and verify the signature + 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_ecdsa_signature_block(sigblock, digest, verified_digest); + bootloader_munmap(sigblock); + return err; +} + +esp_err_t esp_secure_boot_verify_ecdsa_signature_block(const esp_secure_boot_sig_block_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest) +{ +#if !(defined(CONFIG_MBEDTLS_ECDSA_C) && defined(CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED)) + ESP_LOGE(TAG, "Signature verification requires ECDSA & SECP256R1 curve enabled"); + return ESP_ERR_NOT_SUPPORTED; +#else + ptrdiff_t keylen; + + /* Note: in IDF app image verification we don't add any fault injection resistance, boot-time checks only */ + memset(verified_digest, 0, ESP_SECURE_BOOT_DIGEST_LEN); + + keylen = signature_verification_key_end - signature_verification_key_start; + if (keylen != SIGNATURE_VERIFICATION_KEYLEN) { + ESP_LOGE(TAG, "Embedded public verification key has wrong length %d", keylen); + return ESP_FAIL; + } + + if (sig_block->version != 0) { + ESP_LOGE(TAG, "image has invalid signature version field 0x%08x", sig_block->version); + return ESP_FAIL; + } + + ESP_LOGD(TAG, "Verifying secure boot signature"); + + int ret; + mbedtls_mpi r, s; + + mbedtls_mpi_init(&r); + mbedtls_mpi_init(&s); + + /* Extract r and s components from RAW ECDSA signature of 64 bytes */ +#define ECDSA_INTEGER_LEN 32 + ret = mbedtls_mpi_read_binary(&r, &sig_block->signature[0], ECDSA_INTEGER_LEN); + if (ret != 0) { + ESP_LOGE(TAG, "Failed mbedtls_mpi_read_binary(1), err:%d", ret); + return ESP_FAIL; + } + + ret = mbedtls_mpi_read_binary(&s, &sig_block->signature[ECDSA_INTEGER_LEN], ECDSA_INTEGER_LEN); + if (ret != 0) { + ESP_LOGE(TAG, "Failed mbedtls_mpi_read_binary(2), err:%d", ret); + mbedtls_mpi_free(&r); + return ESP_FAIL; + } + + /* Initialise ECDSA context */ + mbedtls_ecdsa_context ecdsa_context; + mbedtls_ecdsa_init(&ecdsa_context); + + mbedtls_ecp_group_load(&ecdsa_context.grp, MBEDTLS_ECP_DP_SECP256R1); + size_t plen = mbedtls_mpi_size(&ecdsa_context.grp.P); + if (keylen != 2 * plen) { + ESP_LOGE(TAG, "Incorrect ECDSA key length %d", keylen); + ret = ESP_FAIL; + goto cleanup; + } + + /* Extract X and Y components from ECDSA public key */ + MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ecdsa_context.Q.X, signature_verification_key_start, plen)); + MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ecdsa_context.Q.Y, signature_verification_key_start + plen, plen)); + MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&ecdsa_context.Q.Z, 1)); + + ret = mbedtls_ecdsa_verify(&ecdsa_context.grp, image_digest, ESP_SECURE_BOOT_DIGEST_LEN, &ecdsa_context.Q, &r, &s); + ESP_LOGD(TAG, "Verification result %d", ret); + +cleanup: + mbedtls_mpi_free(&r); + mbedtls_mpi_free(&s); + mbedtls_ecdsa_free(&ecdsa_context); + return ret == 0 ? ESP_OK : ESP_ERR_IMAGE_INVALID; +#endif // CONFIG_MBEDTLS_ECDSA_C && CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED +} +#endif // CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME diff --git a/components/bootloader_support/src/secure_boot_v1/secure_boot_signatures_bootloader.c b/components/bootloader_support/src/secure_boot_v1/secure_boot_signatures_bootloader.c new file mode 100644 index 0000000000..f8bf7b56dd --- /dev/null +++ b/components/bootloader_support/src/secure_boot_v1/secure_boot_signatures_bootloader.c @@ -0,0 +1,100 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include "sdkconfig.h" + +#include "bootloader_flash_priv.h" +#include "bootloader_sha.h" +#include "bootloader_utility.h" +#include "esp_log.h" +#include "esp_image_format.h" +#include "esp_secure_boot.h" +#include "esp_spi_flash.h" +#include "esp_fault.h" +#include "esp32/rom/sha.h" +#include "uECC_verify_antifault.h" + +#include +#include + +static const char *TAG = "secure_boot"; + +#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 + +esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length) +{ + uint8_t digest[ESP_SECURE_BOOT_DIGEST_LEN]; + uint8_t verified_digest[ESP_SECURE_BOOT_DIGEST_LEN] = { 0 }; /* ignored in this function */ + const esp_secure_boot_sig_block_t *sigblock; + + 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, length, digest); + if (err != ESP_OK) { + return err; + } + + // 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) { + ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", src_addr + length, sizeof(esp_secure_boot_sig_block_t)); + return ESP_FAIL; + } + // Verify the signature + err = esp_secure_boot_verify_ecdsa_signature_block(sigblock, digest, verified_digest); + // Unmap + bootloader_munmap(sigblock); + + return err; +} + +esp_err_t esp_secure_boot_verify_signature_block(const esp_secure_boot_sig_block_t *sig_block, const uint8_t *image_digest) +{ + uint8_t verified_digest[ESP_SECURE_BOOT_DIGEST_LEN] = { 0 }; + return esp_secure_boot_verify_ecdsa_signature_block(sig_block, image_digest, verified_digest); +} + +esp_err_t esp_secure_boot_verify_ecdsa_signature_block(const esp_secure_boot_sig_block_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest) +{ + ptrdiff_t keylen; + + keylen = signature_verification_key_end - signature_verification_key_start; + if (keylen != SIGNATURE_VERIFICATION_KEYLEN) { + ESP_LOGE(TAG, "Embedded public verification key has wrong length %d", keylen); + return ESP_FAIL; + } + + if (sig_block->version != 0) { + ESP_LOGE(TAG, "image has invalid signature version field 0x%08x", sig_block->version); + return ESP_FAIL; + } + + ESP_LOGD(TAG, "Verifying secure boot signature"); + + bool is_valid; + is_valid = uECC_verify_antifault(signature_verification_key_start, + image_digest, + ESP_SECURE_BOOT_DIGEST_LEN, + sig_block->signature, + uECC_secp256r1(), + verified_digest); + ESP_LOGD(TAG, "Verification result %d", is_valid); + + return is_valid ? ESP_OK : ESP_ERR_IMAGE_INVALID; +} + +#endif // CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME diff --git a/components/bootloader_support/src/secure_boot_v2/secure_boot_signatures_app.c b/components/bootloader_support/src/secure_boot_v2/secure_boot_signatures_app.c new file mode 100644 index 0000000000..7497971537 --- /dev/null +++ b/components/bootloader_support/src/secure_boot_v2/secure_boot_signatures_app.c @@ -0,0 +1,271 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include "sdkconfig.h" + +#include "bootloader_flash_priv.h" +#include "bootloader_sha.h" +#include "bootloader_utility.h" +#include "esp_log.h" +#include "esp_image_format.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 +#include "esp_secure_boot.h" +#include "esp_ota_ops.h" + +// Secure boot V2 for app + +#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME || CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT + +static const char *TAG = "secure_boot_v2"; +#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1)) + +#ifdef CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT +/* A signature block is valid when it has correct magic byte, crc. */ +static esp_err_t validate_signature_block(const ets_secure_boot_sig_block_t *block) +{ + if (block->magic_byte != ETS_SECURE_BOOT_V2_SIGNATURE_MAGIC + || block->block_crc != esp_rom_crc32_le(0, (uint8_t *)block, CRC_SIGN_BLOCK_LEN)) { + return ESP_FAIL; + } + return ESP_OK; +} + +static esp_err_t get_signing_keys_for_running_app(esp_image_sig_public_key_digests_t *public_key_digests) +{ + esp_image_metadata_t metadata; + const esp_partition_t* running_app_part = esp_ota_get_running_partition(); + if (running_app_part == NULL) { + ESP_LOGE(TAG, "Cannot get running partition"); + return ESP_FAIL; + } + const esp_partition_pos_t part_pos = { + .offset = running_app_part->address, + .size = running_app_part->size, + }; + esp_err_t err = esp_image_get_metadata(&part_pos, &metadata); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Error reading metadata from running app (err=0x%x)", err); + return ESP_FAIL; + } + + // Generating the SHA of the public key components in the signature block + + // metadata.image_len doesn't include any padding to start of the signature sector, so pad it here + size_t sig_block_addr = metadata.start_addr + ALIGN_UP(metadata.image_len, FLASH_SECTOR_SIZE); + ESP_LOGD(TAG, "reading signatures for app address 0x%x sig block address 0x%x", part_pos.offset, sig_block_addr); + for (unsigned i = 0; i < SECURE_BOOT_NUM_BLOCKS; i++) { + ets_secure_boot_sig_block_t block; + size_t addr = sig_block_addr + sizeof(ets_secure_boot_sig_block_t) * i; + esp_err_t err = bootloader_flash_read(addr, &block, sizeof(ets_secure_boot_sig_block_t), true); + if (err == ESP_OK) { + if (validate_signature_block(&block) == ESP_OK) { + bootloader_sha256_handle_t sig_block_sha = bootloader_sha256_start(); + bootloader_sha256_data(sig_block_sha, &block.key, sizeof(block.key)); + bootloader_sha256_finish(sig_block_sha, public_key_digests->key_digests[i]); + public_key_digests->num_digests++; + } + } else { + ESP_LOGE(TAG, "Secure boot sign blocks cannot be read from a running app (err=0x%x)", err); + return ESP_FAIL; + } + } + if (public_key_digests->num_digests > 0) { + return ESP_OK; + } + ESP_LOGE(TAG, "No signatures were found for the running app"); + return ESP_ERR_NOT_FOUND; +} +#endif // CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT + +static esp_err_t get_secure_boot_key_digests(esp_image_sig_public_key_digests_t *public_key_digests) +{ +#ifdef CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT + // Gets key digests from running app + ESP_LOGI(TAG, "Take trusted digest key(s) from running app"); + return get_signing_keys_for_running_app(public_key_digests); +#elif CONFIG_SECURE_BOOT_V2_ENABLED + ESP_LOGI(TAG, "Take trusted digest key(s) from eFuse block(s)"); +#if SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS > 1 + // Read key digests from efuse + ets_secure_boot_key_digests_t efuse_trusted; + if (ets_secure_boot_read_key_digests(&efuse_trusted) == ETS_OK) { + for (unsigned i = 0; i < SECURE_BOOT_NUM_BLOCKS; i++) { + if (efuse_trusted.key_digests[i] != NULL) { + memcpy(public_key_digests->key_digests[i], (uint8_t *)efuse_trusted.key_digests[i], ESP_SECURE_BOOT_DIGEST_LEN); + public_key_digests->num_digests++; + } + } + } + if (public_key_digests->num_digests > 0) { + return ESP_OK; + } + return ESP_ERR_NOT_FOUND; +#else + memcpy(public_key_digests->key_digests[0], (uint8_t *)EFUSE_BLK2_RDATA0_REG, ESP_SECURE_BOOT_DIGEST_LEN); + public_key_digests->num_digests = 1; + return ESP_OK; +#endif // SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS +#endif // CONFIG_SECURE_BOOT_V2_ENABLED +} + +esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length) +{ + uint8_t digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0}; + uint8_t verified_digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0}; + + /* Rounding off length to the upper 4k boundary */ + uint32_t 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_rsa_signature_block(sig_block, digest, verified_digest); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Secure Boot V2 verification failed."); + } + bootloader_munmap(sig_block); + return err; +} + +// This verify function is called only from app, during ota update. +// This function is compiled in case when CONFIG_SECURE_BOOT_V2_ENABLED==y or CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT==y. +// if CONFIG_SECURE_BOOT_V2_ENABLED==y and key digests from eFuse are missing, then FAIL (eFuse blocks should be set). +esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest) +{ + bool match = false; + + /* Note: in IDF verification we don't add any fault injection resistance, as we don't expect this to be called + during boot-time verification. */ + memset(verified_digest, 0, ESP_SECURE_BOOT_DIGEST_LEN); + + esp_image_sig_public_key_digests_t trusted = {0}; + esp_image_sig_public_key_digests_t untrusted; + + if (get_secure_boot_key_digests(&trusted) != ESP_OK) { + ESP_LOGE(TAG, "Could not read secure boot digests!"); + return ESP_FAIL; + } + + /* Generating the SHA of the public key components in the signature block */ + for (unsigned i = 0; i < SECURE_BOOT_NUM_BLOCKS; i++) { + bootloader_sha256_handle_t sig_block_sha = bootloader_sha256_start(); + bootloader_sha256_data(sig_block_sha, &sig_block->block[i].key, sizeof(sig_block->block[i].key)); + bootloader_sha256_finish(sig_block_sha, untrusted.key_digests[i]); + } + + ESP_LOGI(TAG, "Verifying with RSA-PSS..."); + int ret = 0; + mbedtls_rsa_context pk; + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + const unsigned rsa_key_size = sizeof(sig_block->block[0].signature); + 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); + mbedtls_ctr_drbg_init(&ctr_drbg); + 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 (unsigned i = 0; i < SECURE_BOOT_NUM_BLOCKS; i++) { + for (unsigned j = 0; j < SECURE_BOOT_NUM_BLOCKS; j++) { + if (memcmp(trusted.key_digests[j], untrusted.key_digests[i], ESP_SECURE_BOOT_DIGEST_LEN) == 0) { + ESP_LOGI(TAG, "#%d app key digest == #%d trusted key digest", i, j); + match = true; + break; + } + } + if (match == false) { + continue; // Skip the public keys whose digests don't match. + } + + 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, ESP_SECURE_BOOT_DIGEST_LEN, + 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 != 0 || match == false) ? ESP_ERR_IMAGE_INVALID: ESP_OK; +} +#endif // CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME || CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT diff --git a/components/bootloader_support/src/secure_boot_v2/secure_boot_signatures_bootloader.c b/components/bootloader_support/src/secure_boot_v2/secure_boot_signatures_bootloader.c new file mode 100644 index 0000000000..09e167b057 --- /dev/null +++ b/components/bootloader_support/src/secure_boot_v2/secure_boot_signatures_bootloader.c @@ -0,0 +1,172 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include "sdkconfig.h" + +#include +#include "esp_fault.h" +#include "bootloader_flash_priv.h" +#include "bootloader_sha.h" +#include "bootloader_utility.h" +#include "esp_log.h" +#include "esp_image_format.h" +#include "esp_secure_boot.h" + +// Secure boot V2 for bootloader. + +#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME && CONFIG_SECURE_BOOT_V2_ENABLED + +static const char* TAG = "secure_boot_v2"; + +#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[ESP_SECURE_BOOT_DIGEST_LEN] = {0}; + uint8_t verified_digest[ESP_SECURE_BOOT_DIGEST_LEN] = { 0 }; /* Note: this function doesn't do any anti-FI checks on this buffer */ + + /* Rounding off length to the upper 4k boundary */ + uint32_t padded_length = ALIGN_UP(length, FLASH_SECTOR_SIZE); + ESP_LOGD(TAG, "verifying signature src_addr 0x%x length 0x%x", src_addr, length); + + /* 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); + 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_rsa_signature_block(sig_block, digest, verified_digest); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Secure Boot V2 verification failed."); + } + bootloader_munmap(sig_block); + return err; +} + +/* A signature block is valid when it has correct magic byte, crc. */ +static esp_err_t validate_signature_block(const ets_secure_boot_sig_block_t *block) +{ + if (block->magic_byte != ETS_SECURE_BOOT_V2_SIGNATURE_MAGIC + || block->block_crc != esp_rom_crc32_le(0, (uint8_t *)block, CRC_SIGN_BLOCK_LEN)) { + return ESP_FAIL; + } + return ESP_OK; +} + +static esp_err_t get_secure_boot_key_digests(esp_image_sig_public_key_digests_t *public_key_digests) +{ +#if SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS > 1 + // Read key digests from efuse + ets_secure_boot_key_digests_t trusted_keys; + ets_secure_boot_key_digests_t trusted_key_copies[2]; + ETS_STATUS ets_ret; + + memset(&trusted_keys, 0, sizeof(ets_secure_boot_key_digests_t)); + memset(trusted_key_copies, 0, 2 * sizeof(ets_secure_boot_key_digests_t)); + + + ets_ret = ets_secure_boot_read_key_digests(&trusted_keys); + + // Create the copies for FI checks (assuming result is ETS_OK, if it's not then it'll fail the fault check anyhow) + ets_secure_boot_read_key_digests(&trusted_key_copies[0]); + ets_secure_boot_read_key_digests(&trusted_key_copies[1]); + ESP_FAULT_ASSERT(memcmp(&trusted_keys, &trusted_key_copies[0], sizeof(ets_secure_boot_key_digests_t)) == 0); + ESP_FAULT_ASSERT(memcmp(&trusted_keys, &trusted_key_copies[1], sizeof(ets_secure_boot_key_digests_t)) == 0); + + if (ets_ret == ETS_OK) { + for (unsigned i = 0; i < SECURE_BOOT_NUM_BLOCKS; i++) { + if (trusted_keys.key_digests[i] != NULL) { + memcpy(public_key_digests->key_digests[i], (uint8_t *)trusted_keys.key_digests[i], ESP_SECURE_BOOT_DIGEST_LEN); + public_key_digests->num_digests++; + } + } + if (public_key_digests->num_digests > 0) { + return ESP_OK; + } + } + return ESP_ERR_NOT_FOUND; +#else + bool all_zeroes = true; + uint32_t *reg = (uint32_t*)&public_key_digests->key_digests[0]; + for (int i = 0; i < ESP_SECURE_BOOT_DIGEST_LEN / 4; i++) { + *(reg + i) = REG_READ(EFUSE_BLK2_RDATA0_REG + i * 4); + all_zeroes = all_zeroes && (*(reg + i) == 0); + } + if (all_zeroes) { + return ESP_ERR_NOT_FOUND; + } + public_key_digests->num_digests = 1; + return ESP_OK; +#endif // SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS +} + +// if CONFIG_SECURE_BOOT_V2_ENABLED==y and key digests from eFuse are missing, then it is the first boot, +// trusted.key_digests are filled from app sig_block. +esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest) +{ + esp_image_sig_public_key_digests_t trusted = {0}; + bool efuse_keys_are_not_set = false; + if (get_secure_boot_key_digests(&trusted) != ESP_OK) { + if (esp_secure_boot_enabled()) { + ESP_LOGE(TAG, "Could not read eFuse secure boot digests!"); + return ESP_FAIL; + } else { + ESP_LOGI(TAG, "Secure boot V2 is not enabled yet and eFuse digest keys are not set"); + efuse_keys_are_not_set = true; + ESP_FAULT_ASSERT(!esp_secure_boot_enabled()); + } + } + + if (!esp_secure_boot_enabled()) { + // It is the first boot. eFuse secure boot bit is not set yet. eFuse block(s) can be written or not. + // Generating the SHA of the public key components in the signature block + for (unsigned i = 0; i < SECURE_BOOT_NUM_BLOCKS; i++) { + if (validate_signature_block(&sig_block->block[i]) == ESP_OK) { + if (efuse_keys_are_not_set) { + // if efuse key digests are not in eFuse yet due to it is the first boot + // then use digests from app to skip error in ets_secure_boot_verify_signature(). + bootloader_sha256_handle_t sig_block_sha = bootloader_sha256_start(); + bootloader_sha256_data(sig_block_sha, &sig_block->block[i].key, sizeof(sig_block->block[i].key)); + bootloader_sha256_finish(sig_block_sha, trusted.key_digests[i]); + } + } + } + ESP_FAULT_ASSERT(!esp_secure_boot_enabled()); + } + + ESP_LOGI(TAG, "Verifying with RSA-PSS..."); +#if SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS == 1 + int sb_result = ets_secure_boot_verify_signature(sig_block, image_digest, trusted.key_digests[0], verified_digest); +#else + ets_secure_boot_key_digests_t trusted_key_digests; + for (unsigned i = 0; i < SECURE_BOOT_NUM_BLOCKS; i++) { + trusted_key_digests.key_digests[i] = &trusted.key_digests[i]; + } + int sb_result = ets_secure_boot_verify_signature(sig_block, image_digest, &trusted_key_digests, verified_digest); +#endif + if (sb_result != SB_SUCCESS) { + ESP_LOGE(TAG, "Secure Boot V2 verification failed."); + return ESP_ERR_IMAGE_INVALID; + } else { + ESP_LOGI(TAG, "Signature verified successfully!"); + return ESP_OK; + } +} +#endif // CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME && CONFIG_SECURE_BOOT_V2_ENABLED diff --git a/components/esp_rom/esp32/ld/esp32.rom.eco3.ld b/components/esp_rom/esp32/ld/esp32.rom.eco3.ld index fdd7218b85..73d5b549d5 100644 --- a/components/esp_rom/esp32/ld/esp32.rom.eco3.ld +++ b/components/esp_rom/esp32/ld/esp32.rom.eco3.ld @@ -5,3 +5,6 @@ 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); +PROVIDE ( ets_rsa_pss_verify = 0x40065310); +PROVIDE ( ets_mgf1_sha256 = 0x400651a8); +PROVIDE ( ets_emsa_pss_verify = 0x4006520c); diff --git a/components/esp_rom/include/esp32/rom/rsa_pss.h b/components/esp_rom/include/esp32/rom/rsa_pss.h new file mode 100644 index 0000000000..bfc1e68cda --- /dev/null +++ b/components/esp_rom/include/esp32/rom/rsa_pss.h @@ -0,0 +1,50 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "sdkconfig.h" +#ifdef CONFIG_ESP32_REV_MIN_3 + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define ETS_SIG_LEN 384 /* Bytes */ +#define ETS_DIGEST_LEN 32 /* SHA-256, bytes */ + +/* 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; + + +bool ets_rsa_pss_verify(const ets_rsa_pubkey_t *key, const uint8_t *sig, const uint8_t *digest, uint8_t *verified_digest); + +void ets_mgf1_sha256(const uint8_t *mgfSeed, size_t seedLen, size_t maskLen, uint8_t *mask); + +bool ets_emsa_pss_verify(const uint8_t *encoded_message, const uint8_t *mhash, uint8_t *verified_digest); + +#ifdef __cplusplus +} +#endif + +#endif // CONFIG_ESP32_REV_MIN_3 diff --git a/components/esp_rom/include/esp32/rom/secure_boot.h b/components/esp_rom/include/esp32/rom/secure_boot.h index 3e17941be1..fdeb7c7cfa 100644 --- a/components/esp_rom/include/esp32/rom/secure_boot.h +++ b/components/esp_rom/include/esp32/rom/secure_boot.h @@ -18,6 +18,7 @@ #define _ROM_SECURE_BOOT_H_ #include +#include "ets_sys.h" #ifdef __cplusplus extern "C" { @@ -42,21 +43,22 @@ bool ets_secure_boot_check_start(uint8_t abs_index, uint32_t iv_addr); int ets_secure_boot_check_finish(uint32_t *abstract); #ifdef CONFIG_ESP32_REV_MIN_3 +#include "rsa_pss.h" + #define SECURE_BOOT_NUM_BLOCKS 1 +#define CRC_SIGN_BLOCK_LEN 1196 +#define SIG_BLOCK_PADDING 4096 +#define ETS_SECURE_BOOT_V2_SIGNATURE_MAGIC 0xE7 + +// Anti-FI measure: use full words for success/fail internally, instead of 0/non-zero typedef enum { SBV2_SUCCESS = 0x3A5A5AA5, + SB_SUCCESS = 0x3A5A5AA5, SBV2_FAILED = 0xA533885A, + SB_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; @@ -69,20 +71,28 @@ typedef struct { uint32_t block_crc; uint8_t _padding[16]; } ets_secure_boot_sig_block_t; +_Static_assert(sizeof(ets_secure_boot_sig_block_t) == 1216, "invalid sig block size"); + +#define MAX_APPENDED_SIGN_BLOCKS_TO_IMAGE 3 /* 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; +typedef struct { + ets_secure_boot_sig_block_t block[MAX_APPENDED_SIGN_BLOCKS_TO_IMAGE]; + uint8_t _padding[4096 - (sizeof(ets_secure_boot_sig_block_t) * MAX_APPENDED_SIGN_BLOCKS_TO_IMAGE)]; +} ets_secure_boot_signature_t; + +_Static_assert(sizeof(ets_secure_boot_signature_t) == 4096, "invalid sig sector size"); + +typedef struct { + const void *key_digests[SECURE_BOOT_NUM_BLOCKS]; +} ets_secure_boot_key_digests_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 sig The signature block flashed aligned 4096 bytes from the firmware. (ROM implementation expects 3 blocks, sig->block[3]). * @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. @@ -109,6 +119,9 @@ void ets_secure_boot_verify_boot_bootloader(void); */ bool ets_use_secure_boot_v2(void); +#else +#define SECURE_BOOT_NUM_BLOCKS 0 + #endif /* CONFIG_ESP32_REV_MIN_3 */ #ifdef __cplusplus diff --git a/components/esp_rom/include/esp32c3/rom/secure_boot.h b/components/esp_rom/include/esp32c3/rom/secure_boot.h index 5b5b14c73b..71cf7250d2 100644 --- a/components/esp_rom/include/esp32c3/rom/secure_boot.h +++ b/components/esp_rom/include/esp32c3/rom/secure_boot.h @@ -85,6 +85,8 @@ ets_secure_boot_status_t ets_secure_boot_verify_signature(const ets_secure_boot_ */ void ets_secure_boot_revoke_public_key_digest(int index); +#define CRC_SIGN_BLOCK_LEN 1196 +#define SIG_BLOCK_PADDING 4096 #define ETS_SECURE_BOOT_V2_SIGNATURE_MAGIC 0xE7 /* Secure Boot V2 signature block diff --git a/components/esp_rom/include/esp32s2/rom/secure_boot.h b/components/esp_rom/include/esp32s2/rom/secure_boot.h index 469d1b15bb..8e88081786 100644 --- a/components/esp_rom/include/esp32s2/rom/secure_boot.h +++ b/components/esp_rom/include/esp32s2/rom/secure_boot.h @@ -16,6 +16,7 @@ #define _ROM_SECURE_BOOT_H_ #include +#include "ets_sys.h" #include "rsa_pss.h" #ifdef __cplusplus @@ -83,6 +84,8 @@ ets_secure_boot_status_t ets_secure_boot_verify_signature(const ets_secure_boot_ */ void ets_secure_boot_revoke_public_key_digest(int index); +#define CRC_SIGN_BLOCK_LEN 1196 +#define SIG_BLOCK_PADDING 4096 #define ETS_SECURE_BOOT_V2_SIGNATURE_MAGIC 0xE7 /* Secure Boot V2 signature block diff --git a/components/esp_rom/include/esp32s3/rom/secure_boot.h b/components/esp_rom/include/esp32s3/rom/secure_boot.h index 34408a9acc..e720697b3e 100644 --- a/components/esp_rom/include/esp32s3/rom/secure_boot.h +++ b/components/esp_rom/include/esp32s3/rom/secure_boot.h @@ -16,6 +16,7 @@ #include #include +#include "ets_sys.h" #include "rsa_pss.h" #ifdef __cplusplus @@ -29,6 +30,14 @@ typedef struct ets_secure_boot_sig_block ets_secure_boot_sig_block_t; typedef struct ets_secure_boot_signature ets_secure_boot_signature_t; typedef struct ets_secure_boot_key_digests ets_secure_boot_key_digests_t; +/* Anti-FI measure: use full words for success/fail, instead of + 0/non-zero +*/ +typedef enum { + SB_SUCCESS = 0x3A5A5AA5, + SB_FAILED = 0x7533885E, +} secure_boot_status_t; + /* Verify bootloader image (reconfigures cache to map, loads trusted key digests from efuse) @@ -49,22 +58,24 @@ int ets_secure_boot_verify_bootloader(uint8_t *verified_hash, bool allow_key_rev If result is ETS_OK, the "simple hash" of the bootloader is copied into verified_hash. */ -int ets_secure_boot_verify_bootloader_with_keys(uint8_t *verified_hash, const ets_secure_boot_key_digests_t *trusted_keys); +secure_boot_status_t ets_secure_boot_verify_bootloader_with_keys(uint8_t *verified_hash, const ets_secure_boot_key_digests_t *trusted_keys, bool stage_load); /* Verify supplied signature against supplied digest, using supplied trusted key digests. Doesn't reconfigure cache or any other hardware access. */ -int ets_secure_boot_verify_signature(const ets_secure_boot_signature_t *sig, const uint8_t *image_digest, const ets_secure_boot_key_digests_t *trusted_keys); +secure_boot_status_t ets_secure_boot_verify_signature(const ets_secure_boot_signature_t *sig, const uint8_t *image_digest, const ets_secure_boot_key_digests_t *trusted_keys, uint8_t *verified_digest); /* Read key digests from efuse. Any revoked/missing digests will be marked as NULL Returns 0 if at least one valid digest was found. */ -int ets_secure_boot_read_key_digests(ets_secure_boot_key_digests_t *trusted_keys); +ETS_STATUS ets_secure_boot_read_key_digests(ets_secure_boot_key_digests_t *trusted_keys); +#define CRC_SIGN_BLOCK_LEN 1196 +#define SIG_BLOCK_PADDING 4096 #define ETS_SECURE_BOOT_V2_SIGNATURE_MAGIC 0xE7 /* Secure Boot V2 signature block (up to 3 can be appended) */ @@ -92,8 +103,10 @@ struct ets_secure_boot_signature { _Static_assert(sizeof(ets_secure_boot_signature_t) == 4096, "ets_secure_boot_signature_t should occupy 4096 Bytes in memory"); +#define MAX_KEY_DIGESTS 3 + struct ets_secure_boot_key_digests { - const void *key_digests[3]; + const void *key_digests[MAX_KEY_DIGESTS]; bool allow_key_revoke; };