Jelajahi Sumber

secure_boot: Secure Boot V2 verify app signature on update (without Secure boot)

- ESP32 ECO3, ESP32-S2/C3/S3
KonstantinKondrashov 4 tahun lalu
induk
melakukan
46e85ed021
30 mengubah file dengan 934 tambahan dan 960 penghapusan
  1. 0 10
      components/app_update/esp_ota_ops.c
  2. 3 3
      components/bootloader/Kconfig.projbuild
  3. 1 1
      components/bootloader/subproject/main/ld/esp32/bootloader.ld
  4. 1 1
      components/bootloader/subproject/main/ld/esp32c3/bootloader.ld
  5. 1 1
      components/bootloader/subproject/main/ld/esp32s2/bootloader.ld
  6. 1 1
      components/bootloader/subproject/main/ld/esp32s3/bootloader.ld
  7. 20 8
      components/bootloader_support/CMakeLists.txt
  8. 6 3
      components/bootloader_support/component.mk
  9. 14 0
      components/bootloader_support/include/esp_image_format.h
  10. 20 2
      components/bootloader_support/include/esp_secure_boot.h
  11. 10 15
      components/bootloader_support/src/esp32/secure_boot.c
  12. 0 184
      components/bootloader_support/src/esp32/secure_boot_signatures.c
  13. 11 30
      components/bootloader_support/src/esp32c3/secure_boot.c
  14. 0 94
      components/bootloader_support/src/esp32c3/secure_boot_signatures.c
  15. 11 30
      components/bootloader_support/src/esp32s2/secure_boot.c
  16. 0 93
      components/bootloader_support/src/esp32s2/secure_boot_signatures.c
  17. 11 30
      components/bootloader_support/src/esp32s3/secure_boot.c
  18. 0 93
      components/bootloader_support/src/esp32s3/secure_boot_signatures.c
  19. 43 4
      components/bootloader_support/src/esp_image_format.c
  20. 0 339
      components/bootloader_support/src/idf/secure_boot_signatures.c
  21. 136 0
      components/bootloader_support/src/secure_boot_v1/secure_boot_signatures_app.c
  22. 100 0
      components/bootloader_support/src/secure_boot_v1/secure_boot_signatures_bootloader.c
  23. 271 0
      components/bootloader_support/src/secure_boot_v2/secure_boot_signatures_app.c
  24. 172 0
      components/bootloader_support/src/secure_boot_v2/secure_boot_signatures_bootloader.c
  25. 3 0
      components/esp_rom/esp32/ld/esp32.rom.eco3.ld
  26. 50 0
      components/esp_rom/include/esp32/rom/rsa_pss.h
  27. 27 14
      components/esp_rom/include/esp32/rom/secure_boot.h
  28. 2 0
      components/esp_rom/include/esp32c3/rom/secure_boot.h
  29. 3 0
      components/esp_rom/include/esp32s2/rom/secure_boot.h
  30. 17 4
      components/esp_rom/include/esp32s3/rom/secure_boot.h

+ 0 - 10
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 */

+ 3 - 3
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 <Secure Boot Version 2 documentation link> 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.

+ 1 - 1
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.*)

+ 1 - 1
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.*)

+ 1 - 1
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.*)

+ 1 - 1
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.*)

+ 20 - 8
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()
 

+ 6 - 3
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

+ 14 - 0
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).
  *

+ 20 - 2
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
  *

+ 10 - 15
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;
     }

+ 0 - 184
components/bootloader_support/src/esp32/secure_boot_signatures.c

@@ -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 <sys/param.h>
-#include <string.h>
-
-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

+ 11 - 30
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;
                 }

+ 0 - 94
components/bootloader_support/src/esp32c3/secure_boot_signatures.c

@@ -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 <string.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 "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;
-}

+ 11 - 30
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;
                 }

+ 0 - 93
components/bootloader_support/src/esp32s2/secure_boot_signatures.c

@@ -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 <string.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 "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;
-}

+ 11 - 30
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;
                 }

+ 0 - 93
components/bootloader_support/src/esp32s3/secure_boot_signatures.c

@@ -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 <string.h>
-#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;
-}

+ 43 - 4
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");
 

+ 0 - 339
components/bootloader_support/src/idf/secure_boot_signatures.c

@@ -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 <string.h>
-#include <sys/param.h>
-#include "esp_secure_boot.h"
-
-#ifdef CONFIG_IDF_TARGET_ESP32S2
-#include <esp32s2/rom/secure_boot.h>
-#elif CONFIG_IDF_TARGET_ESP32C3
-#include <esp32c3/rom/secure_boot.h>
-#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

+ 136 - 0
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 <string.h>
+#include <sys/param.h>
+
+#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

+ 100 - 0
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 <sys/param.h>
+#include <string.h>
+
+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

+ 271 - 0
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 <string.h>
+#include <sys/param.h>
+#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

+ 172 - 0
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 <string.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"
+
+// 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

+ 3 - 0
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);

+ 50 - 0
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 <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+
+#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

+ 27 - 14
components/esp_rom/include/esp32/rom/secure_boot.h

@@ -18,6 +18,7 @@
 #define _ROM_SECURE_BOOT_H_
 
 #include <stdint.h>
+#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

+ 2 - 0
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

+ 3 - 0
components/esp_rom/include/esp32s2/rom/secure_boot.h

@@ -16,6 +16,7 @@
 #define _ROM_SECURE_BOOT_H_
 
 #include <stdint.h>
+#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

+ 17 - 4
components/esp_rom/include/esp32s3/rom/secure_boot.h

@@ -16,6 +16,7 @@
 
 #include <stdint.h>
 #include <stdbool.h>
+#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;
 };