feat(bootloader_support): Support Secure Boot using ECDSA-P384 curve

This commit is contained in:
harshal.patil
2025-04-29 01:53:24 +05:30
parent 55f693d4dd
commit 476f8f6f51
21 changed files with 333 additions and 86 deletions
@@ -17,7 +17,6 @@
#if !CONFIG_IDF_TARGET_LINUX
#include "rom/secure_boot.h"
#endif
#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"
@@ -33,7 +32,11 @@ extern "C" {
Can be compiled as part of app or bootloader code.
*/
#if CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS
#define ESP_SECURE_BOOT_DIGEST_LEN 48
#else /* !CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS */
#define ESP_SECURE_BOOT_DIGEST_LEN 32
#endif /* CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS */
/* SHA-256 length of the public key digest */
#define ESP_SECURE_BOOT_KEY_DIGEST_SHA_256_LEN 32
@@ -197,7 +200,8 @@ esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *imag
/** @brief Verify the secure boot signature appended to some binary data in flash.
*
* For ECDSA Scheme (Secure Boot V1) - deterministic ECDSA w/ SHA256 image
* For RSA Scheme (Secure Boot V2) - RSA-PSS Verification of the SHA-256 image
* For RSA Scheme (Secure Boot V2) - RSA-PSS Verification of the SHA-256 image digest
* For ECDSA Scheme (Secure Boot V2) - ECDSA Verification of the SHA-256 / SHA-384 (in case of ECDSA-P384 secure boot key) image digest
*
* Public key is compiled into the calling program in the ECDSA Scheme.
* See the apt docs/security/secure-boot-v1.rst or docs/security/secure-boot-v2.rst for details.
@@ -240,13 +244,13 @@ esp_err_t esp_secure_boot_verify_ecdsa_signature_block(const esp_secure_boot_sig
/** @brief Verify the secure boot signature block for Secure Boot V2.
*
* Performs RSA-PSS or ECDSA verification of the SHA-256 image based on the public key
* Performs RSA-PSS or ECDSA verification of the SHA-256 / SHA-384 image based on the public key
* in the signature block, compared against the public key digest stored in efuse.
*
* Similar to esp_secure_boot_verify_signature(), but can be used when the digest is precalculated.
* @param[in] sig_block Pointer to signature block data
* @param[in] image_digest Pointer to 32 byte buffer holding SHA-256 hash.
* @param[out] verified_digest Pointer to 32 byte buffer that will receive verified digest if verification completes. (Used during bootloader implementation only, result is invalid otherwise.)
* @param[in] image_digest Pointer to 32/48 byte buffer holding SHA-256/SHA-384 hash.
* @param[out] verified_digest Pointer to 32/48 byte buffer that will receive verified digest if verification completes. (Used during bootloader implementation only, result is invalid otherwise.)
*
*/
esp_err_t esp_secure_boot_verify_sbv2_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest);
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -12,15 +12,18 @@
Use mbedTLS APIs or include esp32/sha.h to calculate SHA256 in IDF apps.
*/
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include "esp_err.h"
#include "soc/soc_caps.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef void *bootloader_sha256_handle_t;
typedef bootloader_sha256_handle_t bootloader_sha_handle_t;
bootloader_sha256_handle_t bootloader_sha256_start(void);
@@ -28,6 +31,14 @@ void bootloader_sha256_data(bootloader_sha256_handle_t handle, const void *data,
void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest);
#if SOC_SHA_SUPPORT_SHA512
bootloader_sha_handle_t bootloader_sha512_start(bool is384);
void bootloader_sha512_data(bootloader_sha_handle_t handle, const void *data, size_t data_len);
void bootloader_sha512_finish(bootloader_sha_handle_t handle, uint8_t *digest);
#endif /* SOC_SHA_SUPPORT_SHA512 */
#ifdef __cplusplus
}
#endif
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2018-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2018-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -138,6 +138,20 @@ void bootloader_debug_buffer(const void *buffer, size_t length, const char *labe
*/
esp_err_t bootloader_sha256_flash_contents(uint32_t flash_offset, uint32_t len, uint8_t *digest);
/** @brief Generates the digest of the data between offset & offset+length.
*
* This function should be used when the size of the data is larger than 3.2MB.
* The MMU capacity is 3.2MB (50 pages - 64KB each). This function generates the SHA-384
* of the data in chunks of 3.2MB, considering the MMU capacity.
*
* @param[in] flash_offset Offset of the data in flash.
* @param[in] len Length of data in bytes.
* @param[out] digest Pointer to buffer where the digest is written, if ESP_OK is returned.
*
* @return ESP_OK if secure boot digest is generated successfully.
*/
esp_err_t bootloader_sha384_flash_contents(uint32_t flash_offset, uint32_t len, uint8_t *digest);
#ifdef __cplusplus
}
#endif
@@ -29,15 +29,6 @@ bootloader_sha256_handle_t bootloader_sha256_start()
void bootloader_sha256_data(bootloader_sha256_handle_t handle, const void *data, size_t data_len)
{
assert(handle != NULL);
#if !SOC_SECURE_BOOT_V2_ECC
/* For secure boot, the key field consists of 1 byte of curve identifier and 64 bytes of ECDSA public key.
* While verifying the signature block, we need to calculate the SHA of this key field which is of 65 bytes.
* ets_sha_update handles it cleanly so we can safely remove the check:
*/
assert(data_len % 4 == 0);
#endif /* SOC_SECURE_BOOT_V2_ECC */
ets_sha_update(&ctx, data, data_len, false);
}
@@ -51,6 +42,33 @@ void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest
}
ets_sha_finish(&ctx, digest);
}
#if SOC_SHA_SUPPORT_SHA512
bootloader_sha_handle_t bootloader_sha512_start(bool is384)
{
// Enable SHA hardware
ets_sha_enable();
ets_sha_init(&ctx, is384 ? SHA2_384 : SHA2_512);
return &ctx; // Meaningless non-NULL value
}
void bootloader_sha512_data(bootloader_sha_handle_t handle, const void *data, size_t data_len)
{
assert(handle != NULL);
ets_sha_update(&ctx, data, data_len, false);
}
void bootloader_sha512_finish(bootloader_sha_handle_t handle, uint8_t *digest)
{
assert(handle != NULL);
if (digest == NULL) {
bzero(&ctx, sizeof(ctx));
return;
}
ets_sha_finish(&ctx, digest);
}
#endif /* SOC_SHA_SUPPORT_SHA512 */
#else /* !CONFIG_IDF_TARGET_ESP32 */
#include "soc/dport_reg.h"
@@ -162,6 +180,7 @@ void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest
#include "bootloader_flash_priv.h"
#include <mbedtls/sha256.h>
#include <mbedtls/sha512.h>
bootloader_sha256_handle_t bootloader_sha256_start(void)
{
@@ -199,4 +218,43 @@ void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest
free(handle);
handle = NULL;
}
#if SOC_SHA_SUPPORT_SHA512
bootloader_sha_handle_t bootloader_sha512_start(bool is384)
{
mbedtls_sha512_context *ctx = (mbedtls_sha512_context *)malloc(sizeof(mbedtls_sha512_context));
if (!ctx) {
return NULL;
}
mbedtls_sha512_init(ctx);
int ret = mbedtls_sha512_starts(ctx, is384);
if (ret != 0) {
return NULL;
}
return ctx;
}
void bootloader_sha512_data(bootloader_sha_handle_t handle, const void *data, size_t data_len)
{
assert(handle != NULL);
mbedtls_sha512_context *ctx = (mbedtls_sha512_context *)handle;
int ret = mbedtls_sha512_update(ctx, data, data_len);
assert(ret == 0);
(void)ret;
}
void bootloader_sha512_finish(bootloader_sha_handle_t handle, uint8_t *digest)
{
assert(handle != NULL);
mbedtls_sha512_context *ctx = (mbedtls_sha512_context *)handle;
if (digest != NULL) {
int ret = mbedtls_sha512_finish(ctx, digest);
assert(ret == 0);
(void)ret;
}
mbedtls_sha512_free(ctx);
free(handle);
handle = NULL;
}
#endif /* SOC_SHA_SUPPORT_SHA512 */
#endif /* !(NON_OS_BUILD || CONFIG_APP_BUILD_TYPE_RAM) */
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2018-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2018-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -30,6 +30,7 @@
#include "hal/cache_types.h"
#include "hal/cache_ll.h"
#include "hal/cache_hal.h"
#include "hal/sha_types.h"
#include "esp_cpu.h"
#include "esp_image_format.h"
@@ -1213,18 +1214,29 @@ void bootloader_debug_buffer(const void *buffer, size_t length, const char *labe
#endif
}
esp_err_t bootloader_sha256_flash_contents(uint32_t flash_offset, uint32_t len, uint8_t *digest)
static esp_err_t bootloader_sha_flash_contents(esp_sha_type type, uint32_t flash_offset, uint32_t len, uint8_t *digest)
{
if (digest == NULL) {
return ESP_ERR_INVALID_ARG;
}
/* Handling firmware images larger than MMU capacity */
uint32_t mmu_free_pages_count = bootloader_mmap_get_free_pages();
bootloader_sha256_handle_t sha_handle = NULL;
bootloader_sha_handle_t sha_handle = NULL;
if (type == SHA2_256) {
sha_handle = bootloader_sha256_start();
} else
// Using SOC_ECDSA_SUPPORT_CURVE_P384 here so that there is no flash size impact in the case of existing targets like ESP32.
#if SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384
if (type == SHA2_384) {
sha_handle = bootloader_sha512_start(true);
} else
#endif /* SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384 */
{
return ESP_ERR_INVALID_ARG;
}
sha_handle = bootloader_sha256_start();
if (sha_handle == NULL) {
return ESP_ERR_NO_MEM;
}
@@ -1234,7 +1246,14 @@ esp_err_t bootloader_sha256_flash_contents(uint32_t flash_offset, uint32_t len,
uint32_t max_pages = (mmu_free_pages_count > mmu_page_offset) ? (mmu_free_pages_count - mmu_page_offset) : 0;
if (max_pages == 0) {
ESP_LOGE(TAG, "No free MMU pages are available");
bootloader_sha256_finish(sha_handle, NULL);
if (type == SHA2_256) {
bootloader_sha256_finish(sha_handle, NULL);
}
#if SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384
else if (type == SHA2_384) {
bootloader_sha512_finish(sha_handle, NULL);
}
#endif /* SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384 */
return ESP_ERR_NO_MEM;
}
uint32_t max_image_len;
@@ -1245,15 +1264,51 @@ esp_err_t bootloader_sha256_flash_contents(uint32_t flash_offset, uint32_t len,
const void * image = bootloader_mmap(flash_offset, partial_image_len);
if (image == NULL) {
bootloader_sha256_finish(sha_handle, NULL);
if (type == SHA2_256) {
bootloader_sha256_finish(sha_handle, NULL);
}
#if SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384
else if (type == SHA2_384) {
bootloader_sha512_finish(sha_handle, NULL);
}
#endif /* SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384 */
return ESP_FAIL;
}
bootloader_sha256_data(sha_handle, image, partial_image_len);
if (type == SHA2_256) {
bootloader_sha256_data(sha_handle, image, partial_image_len);
}
#if SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384
else if (type == SHA2_384) {
bootloader_sha512_data(sha_handle, image, partial_image_len);
}
#endif /* SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384 */
bootloader_munmap(image);
flash_offset += partial_image_len;
len -= partial_image_len;
}
bootloader_sha256_finish(sha_handle, digest);
if (type == SHA2_256) {
bootloader_sha256_finish(sha_handle, digest);
}
#if SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384
else if (type == SHA2_384) {
bootloader_sha512_finish(sha_handle, digest);
}
#endif /* SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384 */
return ESP_OK;
}
esp_err_t bootloader_sha256_flash_contents(uint32_t flash_offset, uint32_t len, uint8_t *digest)
{
return bootloader_sha_flash_contents(SHA2_256, flash_offset, len, digest);
}
#if SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384
esp_err_t bootloader_sha384_flash_contents(uint32_t flash_offset, uint32_t len, uint8_t *digest)
{
return bootloader_sha_flash_contents(SHA2_384, flash_offset, len, digest);
}
#endif /* SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384 */
@@ -49,6 +49,12 @@ esp_err_t esp_secure_boot_enable_secure_features(void)
esp_efuse_write_field_bit(ESP_EFUSE_SECURE_BOOT_AGGRESSIVE_REVOKE);
#endif
#if CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS
esp_efuse_write_field_bit(ESP_EFUSE_SECURE_BOOT_SHA384_EN);
#endif
esp_efuse_write_field_bit(ESP_EFUSE_WR_DIS_SECURE_BOOT_SHA384_EN);
esp_efuse_write_field_bit(ESP_EFUSE_SECURE_BOOT_EN);
#ifndef CONFIG_SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS
@@ -105,7 +105,6 @@ static esp_err_t verify_segment_header(int index, const esp_image_segment_header
static esp_err_t process_image_header(esp_image_metadata_t *data, uint32_t part_offset, bootloader_sha256_handle_t *sha_handle, bool do_verify, bool silent);
static esp_err_t process_appended_hash_and_sig(esp_image_metadata_t *data, uint32_t part_offset, uint32_t part_len, bool do_verify, bool silent);
static esp_err_t process_checksum(bootloader_sha256_handle_t sha_handle, uint32_t checksum_word, esp_image_metadata_t *data, bool silent, bool skip_check_checksum);
static esp_err_t __attribute__((unused)) verify_secure_boot_signature(bootloader_sha256_handle_t sha_handle, esp_image_metadata_t *data, uint8_t *image_digest, uint8_t *verified_digest);
static esp_err_t __attribute__((unused)) verify_simple_hash(bootloader_sha256_handle_t sha_handle, esp_image_metadata_t *data);
@@ -160,8 +159,8 @@ static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_
bool verify_sha;
#if (SECURE_BOOT_CHECK_SIGNATURE == 1)
/* used for anti-FI checks */
uint8_t image_digest[HASH_LEN] = { [ 0 ... 31] = 0xEE };
uint8_t verified_digest[HASH_LEN] = { [ 0 ... 31 ] = 0x01 };
uint8_t image_digest[ESP_SECURE_BOOT_DIGEST_LEN] = { [ 0 ... ESP_SECURE_BOOT_DIGEST_LEN - 1 ] = 0xEE };
uint8_t verified_digest[ESP_SECURE_BOOT_DIGEST_LEN] = { [ 0 ... ESP_SECURE_BOOT_DIGEST_LEN - 1 ] = 0x01 };
#endif
if (data == NULL || part == NULL) {
@@ -237,7 +236,7 @@ static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_
"only verify signature in bootloader" into the macro so it's tested multiple times.
*/
#if CONFIG_SECURE_BOOT_V2_ENABLED
ESP_FAULT_ASSERT(!esp_secure_boot_enabled() || memcmp(image_digest, verified_digest, HASH_LEN) == 0);
ESP_FAULT_ASSERT(!esp_secure_boot_enabled() || memcmp(image_digest, verified_digest, ESP_SECURE_BOOT_DIGEST_LEN) == 0);
#else // Secure Boot V1 on ESP32, only verify signatures for apps not bootloaders
ESP_FAULT_ASSERT(is_bootloader(data->start_addr) || memcmp(image_digest, verified_digest, HASH_LEN) == 0);
#endif
@@ -1023,43 +1022,14 @@ err:
return err;
}
static esp_err_t verify_secure_boot_signature(bootloader_sha256_handle_t sha_handle, esp_image_metadata_t *data, uint8_t *image_digest, uint8_t *verified_digest)
{
#if (SECURE_BOOT_CHECK_SIGNATURE == 1)
uint32_t end = data->start_addr + data->image_len;
ESP_LOGI(TAG, "Verifying image signature...");
// For secure boot, we calculate the signature hash over the whole file, which includes any "simple" hash
// appended to the image for corruption detection
if (data->image.hash_appended) {
const void *simple_hash = bootloader_mmap(end - HASH_LEN, HASH_LEN);
bootloader_sha256_data(sha_handle, simple_hash, HASH_LEN);
bootloader_munmap(simple_hash);
}
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME || CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
// End of the image needs to be padded all the way to a 4KB boundary, after the simple hash
// (for apps they are usually already padded due to --secure-pad-v2, only a problem if this option was not used.)
uint32_t padded_end = ALIGN_UP(end, FLASH_SECTOR_SIZE);
if (padded_end > end) {
const void *padding = bootloader_mmap(end, padded_end - end);
bootloader_sha256_data(sha_handle, padding, padded_end - end);
bootloader_munmap(padding);
end = padded_end;
}
#endif // CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME || CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
bootloader_sha256_finish(sha_handle, image_digest);
// Log the hash for debugging
bootloader_debug_buffer(image_digest, HASH_LEN, "Calculated secure boot hash");
static esp_err_t verify_signature_and_adjust_image_len(esp_image_metadata_t *data, uint32_t end, uint8_t *image_digest, uint8_t *verified_digest)
{
// Use hash to verify signature block
esp_err_t err = ESP_ERR_IMAGE_INVALID;
#if CONFIG_SECURE_BOOT || CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT
const void *sig_block;
ESP_FAULT_ASSERT(memcmp(image_digest, verified_digest, HASH_LEN) != 0); /* sanity check that these values start differently */
ESP_FAULT_ASSERT(memcmp(image_digest, verified_digest, ESP_SECURE_BOOT_DIGEST_LEN) != 0); /* sanity check that these values start differently */
#if defined(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);
@@ -1076,7 +1046,7 @@ static esp_err_t verify_secure_boot_signature(bootloader_sha256_handle_t sha_han
ESP_LOGI(TAG, "Calculating simple hash to check for corruption...");
const void *whole_image = bootloader_mmap(data->start_addr, data->image_len - HASH_LEN);
if (whole_image != NULL) {
sha_handle = bootloader_sha256_start();
bootloader_sha256_handle_t sha_handle = bootloader_sha256_start();
bootloader_sha256_data(sha_handle, whole_image, data->image_len - HASH_LEN);
bootloader_munmap(whole_image);
if (verify_simple_hash(sha_handle, data) != ESP_OK) {
@@ -1097,6 +1067,64 @@ static esp_err_t verify_secure_boot_signature(bootloader_sha256_handle_t sha_han
}
#endif
return ESP_OK;
}
#endif /* SECURE_BOOT_CHECK_SIGNATURE */
static esp_err_t verify_secure_boot_signature(bootloader_sha256_handle_t sha_handle, esp_image_metadata_t *data, uint8_t *image_digest, uint8_t *verified_digest)
{
#if (SECURE_BOOT_CHECK_SIGNATURE == 1)
uint32_t end = data->start_addr + data->image_len;
ESP_LOGI(TAG, "Verifying image signature...");
#if CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS
(void) sha_handle;
/* Re-calculating image digest using SHA384 */
const void *image_data = bootloader_mmap(data->start_addr, data->image_len - HASH_LEN);
bootloader_sha_handle_t sha384_handle = bootloader_sha512_start(true);
bootloader_sha512_data(sha384_handle, image_data, data->image_len - HASH_LEN);
bootloader_munmap(image_data);
#endif
// For secure boot, we calculate the signature hash over the whole file, which includes any "simple" hash
// appended to the image for corruption detection
if (data->image.hash_appended) {
const void *simple_hash = bootloader_mmap(end - HASH_LEN, HASH_LEN);
#if CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS
bootloader_sha512_data(sha384_handle, simple_hash, HASH_LEN);
#else
bootloader_sha256_data(sha_handle, simple_hash, HASH_LEN);
#endif
bootloader_munmap(simple_hash);
}
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME || CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
// End of the image needs to be padded all the way to a 4KB boundary, after the simple hash
// (for apps they are usually already padded due to --secure-pad-v2, only a problem if this option was not used.)
uint32_t padded_end = ALIGN_UP(end, FLASH_SECTOR_SIZE);
if (padded_end > end) {
const void *padding = bootloader_mmap(end, padded_end - end);
#if CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS
bootloader_sha512_data(sha384_handle, padding, padded_end - end);
#else
bootloader_sha256_data(sha_handle, padding, padded_end - end);
#endif
bootloader_munmap(padding);
end = padded_end;
}
#endif // CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME || CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
#if CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS
bootloader_sha512_finish(sha384_handle, image_digest);
#else
bootloader_sha256_finish(sha_handle, image_digest);
#endif
// Log the hash for debugging
bootloader_debug_buffer(image_digest, ESP_SECURE_BOOT_DIGEST_LEN, "Calculated secure boot hash");
return verify_signature_and_adjust_image_len(data, end, image_digest, verified_digest);
#endif // SECURE_BOOT_CHECK_SIGNATURE
return ESP_OK;
}
@@ -427,7 +427,19 @@ bool esp_secure_boot_cfg_verify_release_mode(void)
#endif
}
}
#if SOC_ECDSA_SUPPORT_CURVE_P384
/* When using Secure Boot with SHA-384, the efuse bit representing Secure Boot with SHA-384 would already be programmed.
* But in the case of the existing Secure Boot V2 schemes using SHA-256, the efuse bit representing
* Secure Boot with SHA-384 needs to be write-protected, so that an attacker cannot perform a denial-of-service
* attack by changing the existing secure boot mode using SHA-256 to SHA-384.
*/
secure = esp_efuse_read_field_bit(ESP_EFUSE_WR_DIS_SECURE_BOOT_SHA384_EN);
result &= secure;
if (!secure) {
ESP_LOGW(TAG, "Not write-protected secure boot using SHA-384 mode (set WR_DIS_SECURE_BOOT_SHA384_EN->1)");
}
#endif
secure = (num_keys != 0);
result &= secure;
@@ -69,7 +69,7 @@ static esp_err_t validate_signature_block(const ets_secure_boot_sig_block_t *blo
*/
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;
esp_err_t ret = ESP_FAIL;
uint8_t image_digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0};
uint8_t __attribute__((aligned(4))) key_digest[ESP_SECURE_BOOT_KEY_DIGEST_SHA_256_LEN] = {0};
size_t sig_block_addr = flash_offset + ALIGN_UP(flash_size, FLASH_SECTOR_SIZE);
@@ -78,7 +78,12 @@ static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uin
bzero(public_key_digests, sizeof(esp_image_sig_public_key_digests_t));
#if CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS
ret = bootloader_sha384_flash_contents(flash_offset, sig_block_addr - flash_offset, image_digest);
#else
ret = bootloader_sha256_flash_contents(flash_offset, sig_block_addr - flash_offset, image_digest);
#endif
if (ret != ESP_OK) {
ESP_LOGE(TAG, "error generating image digest, %d", ret);
return ret;
@@ -81,7 +81,11 @@ static esp_err_t calculate_image_public_key_digests(bool verify_image_digest, bo
bzero(public_key_digests, sizeof(esp_image_sig_public_key_digests_t));
if (verify_image_digest) {
#if CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS
ret = bootloader_sha384_flash_contents(img_metadata.start_addr, sig_block_addr - img_metadata.start_addr, image_digest);
#else
ret = bootloader_sha256_flash_contents(img_metadata.start_addr, sig_block_addr - img_metadata.start_addr, image_digest);
#endif
if (ret != ESP_OK) {
ESP_LOGE(TAG, "error generating image digest, %d", ret);
return ret;
@@ -184,13 +188,19 @@ static esp_err_t get_secure_boot_key_digests(esp_image_sig_public_key_digests_t
esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
{
esp_err_t err = ESP_FAIL;
uint8_t 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%"PRIx32" length 0x%"PRIx32, src_addr, length);
esp_err_t err = bootloader_sha256_flash_contents(src_addr, padded_length, digest);
#if CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS
err = bootloader_sha384_flash_contents(src_addr, padded_length, digest);
#else
err = bootloader_sha256_flash_contents(src_addr, padded_length, digest);
#endif
if (err != ESP_OK) {
ESP_LOGE(TAG, "Digest calculation failed 0x%"PRIx32", 0x%"PRIx32, src_addr, padded_length);
return err;
@@ -26,6 +26,7 @@ static const char* TAG = "secure_boot_v2";
esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
{
esp_err_t err = ESP_FAIL;
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 */
@@ -34,7 +35,12 @@ esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
ESP_LOGD(TAG, "verifying signature src_addr 0x%" PRIx32 " length 0x%" PRIx32, src_addr, length);
/* Calculate digest of main image */
esp_err_t err = bootloader_sha256_flash_contents(src_addr, padded_length, digest);
#if CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS
err = bootloader_sha384_flash_contents(src_addr, padded_length, digest);
#else
err = bootloader_sha256_flash_contents(src_addr, padded_length, digest);
#endif
if (err != ESP_OK) {
ESP_LOGE(TAG, "Digest calculation failed 0x%" PRIx32 ", 0x%" PRIx32, src_addr, padded_length);
return err;