mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-04 13:14:32 +02:00
feat(bootloader_support): Support Secure Boot using ECDSA-P384 curve
This commit is contained in:
@@ -559,12 +559,13 @@ menu "Security features"
|
|||||||
depends on SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
|
depends on SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
|
||||||
default SECURE_BOOT_ECDSA_KEY_LEN_256_BITS
|
default SECURE_BOOT_ECDSA_KEY_LEN_256_BITS
|
||||||
help
|
help
|
||||||
Select the ECDSA key size. Two key sizes are supported
|
Select the ECDSA key size. Three key sizes are supported depending upon on the target:
|
||||||
|
|
||||||
- 192 bit key using NISTP192 curve
|
- 192 bit key using NISTP192 curve
|
||||||
- 256 bit key using NISTP256 curve (Recommended)
|
- 256 bit key using NISTP256 curve (Recommended)
|
||||||
|
- 384 bit key using NISTP384 curve (Recommended)
|
||||||
|
|
||||||
The advantage of using 256 bit key is the extra randomness which makes it difficult to be
|
The advantage of using 384 and 256 bit keys is the extra randomness which makes it difficult to be
|
||||||
bruteforced compared to 192 bit key.
|
bruteforced compared to 192 bit key.
|
||||||
At present, both key sizes are practically implausible to bruteforce.
|
At present, both key sizes are practically implausible to bruteforce.
|
||||||
|
|
||||||
@@ -576,6 +577,10 @@ menu "Security features"
|
|||||||
bool "Using ECC curve NISTP256 (Recommended)"
|
bool "Using ECC curve NISTP256 (Recommended)"
|
||||||
depends on SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
|
depends on SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
|
||||||
|
|
||||||
|
config SECURE_BOOT_ECDSA_KEY_LEN_384_BITS
|
||||||
|
bool "Using ECC curve NISTP384 (Recommended)"
|
||||||
|
depends on SECURE_SIGNED_APPS_ECDSA_V2_SCHEME && SOC_ECDSA_SUPPORT_CURVE_P384
|
||||||
|
|
||||||
endchoice
|
endchoice
|
||||||
|
|
||||||
config SECURE_SIGNED_ON_BOOT_NO_SECURE_BOOT
|
config SECURE_SIGNED_ON_BOOT_NO_SECURE_BOOT
|
||||||
|
@@ -70,6 +70,8 @@ if(CONFIG_SECURE_SIGNED_APPS)
|
|||||||
set(scheme "ecdsa192")
|
set(scheme "ecdsa192")
|
||||||
elseif(CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_256_BITS)
|
elseif(CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_256_BITS)
|
||||||
set(scheme "ecdsa256")
|
set(scheme "ecdsa256")
|
||||||
|
elseif(CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS)
|
||||||
|
set(scheme "ecdsa384")
|
||||||
endif()
|
endif()
|
||||||
fail_at_build_time(gen_secure_boot_signing_key
|
fail_at_build_time(gen_secure_boot_signing_key
|
||||||
"Secure Boot Signing Key ${CONFIG_SECURE_BOOT_SIGNING_KEY} does not exist. Generate using:"
|
"Secure Boot Signing Key ${CONFIG_SECURE_BOOT_SIGNING_KEY} does not exist. Generate using:"
|
||||||
|
@@ -17,7 +17,6 @@
|
|||||||
#if !CONFIG_IDF_TARGET_LINUX
|
#if !CONFIG_IDF_TARGET_LINUX
|
||||||
#include "rom/secure_boot.h"
|
#include "rom/secure_boot.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_SECURE_BOOT_V1_ENABLED
|
#ifdef CONFIG_SECURE_BOOT_V1_ENABLED
|
||||||
#if !defined(CONFIG_SECURE_SIGNED_ON_BOOT) || !defined(CONFIG_SECURE_SIGNED_ON_UPDATE) || !defined(CONFIG_SECURE_SIGNED_APPS)
|
#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"
|
#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.
|
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
|
#define ESP_SECURE_BOOT_DIGEST_LEN 32
|
||||||
|
#endif /* CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS */
|
||||||
|
|
||||||
/* SHA-256 length of the public key digest */
|
/* SHA-256 length of the public key digest */
|
||||||
#define ESP_SECURE_BOOT_KEY_DIGEST_SHA_256_LEN 32
|
#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.
|
/** @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 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.
|
* 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.
|
* 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.
|
/** @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.
|
* 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.
|
* 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] sig_block Pointer to signature block data
|
||||||
* @param[in] image_digest Pointer to 32 byte buffer holding SHA-256 hash.
|
* @param[in] image_digest Pointer to 32/48 byte buffer holding SHA-256/SHA-384 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[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);
|
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
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -12,15 +12,18 @@
|
|||||||
Use mbedTLS APIs or include esp32/sha.h to calculate SHA256 in IDF apps.
|
Use mbedTLS APIs or include esp32/sha.h to calculate SHA256 in IDF apps.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
|
#include "soc/soc_caps.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef void *bootloader_sha256_handle_t;
|
typedef void *bootloader_sha256_handle_t;
|
||||||
|
typedef bootloader_sha256_handle_t bootloader_sha_handle_t;
|
||||||
|
|
||||||
bootloader_sha256_handle_t bootloader_sha256_start(void);
|
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);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#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
|
* 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);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#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)
|
void bootloader_sha256_data(bootloader_sha256_handle_t handle, const void *data, size_t data_len)
|
||||||
{
|
{
|
||||||
assert(handle != NULL);
|
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);
|
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);
|
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 */
|
#else /* !CONFIG_IDF_TARGET_ESP32 */
|
||||||
|
|
||||||
#include "soc/dport_reg.h"
|
#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 "bootloader_flash_priv.h"
|
||||||
#include <mbedtls/sha256.h>
|
#include <mbedtls/sha256.h>
|
||||||
|
#include <mbedtls/sha512.h>
|
||||||
|
|
||||||
bootloader_sha256_handle_t bootloader_sha256_start(void)
|
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);
|
free(handle);
|
||||||
handle = NULL;
|
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) */
|
#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
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -30,6 +30,7 @@
|
|||||||
#include "hal/cache_types.h"
|
#include "hal/cache_types.h"
|
||||||
#include "hal/cache_ll.h"
|
#include "hal/cache_ll.h"
|
||||||
#include "hal/cache_hal.h"
|
#include "hal/cache_hal.h"
|
||||||
|
#include "hal/sha_types.h"
|
||||||
|
|
||||||
#include "esp_cpu.h"
|
#include "esp_cpu.h"
|
||||||
#include "esp_image_format.h"
|
#include "esp_image_format.h"
|
||||||
@@ -1213,18 +1214,29 @@ void bootloader_debug_buffer(const void *buffer, size_t length, const char *labe
|
|||||||
#endif
|
#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) {
|
if (digest == NULL) {
|
||||||
return ESP_ERR_INVALID_ARG;
|
return ESP_ERR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handling firmware images larger than MMU capacity */
|
/* Handling firmware images larger than MMU capacity */
|
||||||
uint32_t mmu_free_pages_count = bootloader_mmap_get_free_pages();
|
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) {
|
if (sha_handle == NULL) {
|
||||||
return ESP_ERR_NO_MEM;
|
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;
|
uint32_t max_pages = (mmu_free_pages_count > mmu_page_offset) ? (mmu_free_pages_count - mmu_page_offset) : 0;
|
||||||
if (max_pages == 0) {
|
if (max_pages == 0) {
|
||||||
ESP_LOGE(TAG, "No free MMU pages are available");
|
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;
|
return ESP_ERR_NO_MEM;
|
||||||
}
|
}
|
||||||
uint32_t max_image_len;
|
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);
|
const void * image = bootloader_mmap(flash_offset, partial_image_len);
|
||||||
if (image == NULL) {
|
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;
|
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);
|
bootloader_munmap(image);
|
||||||
|
|
||||||
flash_offset += partial_image_len;
|
flash_offset += partial_image_len;
|
||||||
len -= 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;
|
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);
|
esp_efuse_write_field_bit(ESP_EFUSE_SECURE_BOOT_AGGRESSIVE_REVOKE);
|
||||||
#endif
|
#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);
|
esp_efuse_write_field_bit(ESP_EFUSE_SECURE_BOOT_EN);
|
||||||
|
|
||||||
#ifndef CONFIG_SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS
|
#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_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_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 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_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);
|
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;
|
bool verify_sha;
|
||||||
#if (SECURE_BOOT_CHECK_SIGNATURE == 1)
|
#if (SECURE_BOOT_CHECK_SIGNATURE == 1)
|
||||||
/* used for anti-FI checks */
|
/* used for anti-FI checks */
|
||||||
uint8_t image_digest[HASH_LEN] = { [ 0 ... 31] = 0xEE };
|
uint8_t image_digest[ESP_SECURE_BOOT_DIGEST_LEN] = { [ 0 ... ESP_SECURE_BOOT_DIGEST_LEN - 1 ] = 0xEE };
|
||||||
uint8_t verified_digest[HASH_LEN] = { [ 0 ... 31 ] = 0x01 };
|
uint8_t verified_digest[ESP_SECURE_BOOT_DIGEST_LEN] = { [ 0 ... ESP_SECURE_BOOT_DIGEST_LEN - 1 ] = 0x01 };
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (data == NULL || part == NULL) {
|
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.
|
"only verify signature in bootloader" into the macro so it's tested multiple times.
|
||||||
*/
|
*/
|
||||||
#if CONFIG_SECURE_BOOT_V2_ENABLED
|
#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
|
#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);
|
ESP_FAULT_ASSERT(is_bootloader(data->start_addr) || memcmp(image_digest, verified_digest, HASH_LEN) == 0);
|
||||||
#endif
|
#endif
|
||||||
@@ -1028,43 +1027,14 @@ err:
|
|||||||
return 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)
|
#if (SECURE_BOOT_CHECK_SIGNATURE == 1)
|
||||||
uint32_t end = data->start_addr + data->image_len;
|
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)
|
||||||
|
{
|
||||||
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");
|
|
||||||
|
|
||||||
// Use hash to verify signature block
|
// Use hash to verify signature block
|
||||||
esp_err_t err = ESP_ERR_IMAGE_INVALID;
|
esp_err_t err = ESP_ERR_IMAGE_INVALID;
|
||||||
#if CONFIG_SECURE_BOOT || CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT
|
#if CONFIG_SECURE_BOOT || CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT
|
||||||
const void *sig_block;
|
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)
|
#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));
|
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);
|
err = esp_secure_boot_verify_ecdsa_signature_block(sig_block, image_digest, verified_digest);
|
||||||
@@ -1081,7 +1051,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...");
|
ESP_LOGI(TAG, "Calculating simple hash to check for corruption...");
|
||||||
const void *whole_image = bootloader_mmap(data->start_addr, data->image_len - HASH_LEN);
|
const void *whole_image = bootloader_mmap(data->start_addr, data->image_len - HASH_LEN);
|
||||||
if (whole_image != NULL) {
|
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_sha256_data(sha_handle, whole_image, data->image_len - HASH_LEN);
|
||||||
bootloader_munmap(whole_image);
|
bootloader_munmap(whole_image);
|
||||||
if (verify_simple_hash(sha_handle, data) != ESP_OK) {
|
if (verify_simple_hash(sha_handle, data) != ESP_OK) {
|
||||||
@@ -1102,6 +1072,64 @@ static esp_err_t verify_secure_boot_signature(bootloader_sha256_handle_t sha_han
|
|||||||
}
|
}
|
||||||
#endif
|
#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
|
#endif // SECURE_BOOT_CHECK_SIGNATURE
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
@@ -427,7 +427,19 @@ bool esp_secure_boot_cfg_verify_release_mode(void)
|
|||||||
#endif
|
#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;
|
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);
|
secure = (num_keys != 0);
|
||||||
result &= secure;
|
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)
|
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 image_digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0};
|
||||||
uint8_t __attribute__((aligned(4))) key_digest[ESP_SECURE_BOOT_KEY_DIGEST_SHA_256_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);
|
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));
|
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);
|
ret = bootloader_sha256_flash_contents(flash_offset, sig_block_addr - flash_offset, image_digest);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (ret != ESP_OK) {
|
if (ret != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "error generating image digest, %d", ret);
|
ESP_LOGE(TAG, "error generating image digest, %d", ret);
|
||||||
return 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));
|
bzero(public_key_digests, sizeof(esp_image_sig_public_key_digests_t));
|
||||||
|
|
||||||
if (verify_image_digest) {
|
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);
|
ret = bootloader_sha256_flash_contents(img_metadata.start_addr, sig_block_addr - img_metadata.start_addr, image_digest);
|
||||||
|
#endif
|
||||||
if (ret != ESP_OK) {
|
if (ret != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "error generating image digest, %d", ret);
|
ESP_LOGE(TAG, "error generating image digest, %d", ret);
|
||||||
return 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 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 digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0};
|
||||||
|
|
||||||
/* Rounding off length to the upper 4k boundary */
|
/* Rounding off length to the upper 4k boundary */
|
||||||
uint32_t padded_length = ALIGN_UP(length, FLASH_SECTOR_SIZE);
|
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_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) {
|
if (err != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "Digest calculation failed 0x%"PRIx32", 0x%"PRIx32, src_addr, padded_length);
|
ESP_LOGE(TAG, "Digest calculation failed 0x%"PRIx32", 0x%"PRIx32, src_addr, padded_length);
|
||||||
return err;
|
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 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 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 */
|
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);
|
ESP_LOGD(TAG, "verifying signature src_addr 0x%" PRIx32 " length 0x%" PRIx32, src_addr, length);
|
||||||
|
|
||||||
/* Calculate digest of main image */
|
/* 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) {
|
if (err != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "Digest calculation failed 0x%" PRIx32 ", 0x%" PRIx32, src_addr, padded_length);
|
ESP_LOGE(TAG, "Digest calculation failed 0x%" PRIx32 ", 0x%" PRIx32, src_addr, padded_length);
|
||||||
return err;
|
return err;
|
||||||
|
@@ -16,7 +16,8 @@ extern "C" {
|
|||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ECDSA_CURVE_P192 = 1,
|
ECDSA_CURVE_P192 = 1,
|
||||||
ECDSA_CURVE_P256 = 2
|
ECDSA_CURVE_P256 = 2,
|
||||||
|
ECDSA_CURVE_P384 = 3
|
||||||
} ECDSA_CURVE;
|
} ECDSA_CURVE;
|
||||||
|
|
||||||
int ets_ecdsa_verify(const uint8_t *key, const uint8_t *sig, ECDSA_CURVE curve_id, const uint8_t *digest, uint8_t *verified_digest);
|
int ets_ecdsa_verify(const uint8_t *key, const uint8_t *sig, ECDSA_CURVE curve_id, const uint8_t *digest, uint8_t *verified_digest);
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -88,6 +88,25 @@ struct ets_secure_boot_sig_block {
|
|||||||
|
|
||||||
#elif CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
|
#elif CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
|
||||||
|
|
||||||
|
#if CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS
|
||||||
|
struct __attribute((packed)) ets_secure_boot_sig_block {
|
||||||
|
uint8_t magic_byte;
|
||||||
|
uint8_t version;
|
||||||
|
uint8_t sha_version;
|
||||||
|
uint8_t _reserved2;
|
||||||
|
uint8_t image_digest[48];
|
||||||
|
struct {
|
||||||
|
struct {
|
||||||
|
uint8_t curve_id; /* ETS_ECDSA_CURVE_P192 / ETS_ECDSA_CURVE_P256 */
|
||||||
|
uint8_t point[96]; /* X followed by Y (both little-endian), plus zero bytes if P192 */
|
||||||
|
} key;
|
||||||
|
uint8_t signature[96]; /* r followed by s (both little-endian) */
|
||||||
|
uint8_t padding[951];
|
||||||
|
} ecdsa;
|
||||||
|
uint32_t block_crc; /* note: crc covers all bytes in the structure before it, regardless of version field */
|
||||||
|
uint8_t _padding[16];
|
||||||
|
};
|
||||||
|
#else
|
||||||
struct __attribute((packed)) ets_secure_boot_sig_block {
|
struct __attribute((packed)) ets_secure_boot_sig_block {
|
||||||
uint8_t magic_byte;
|
uint8_t magic_byte;
|
||||||
uint8_t version;
|
uint8_t version;
|
||||||
@@ -105,6 +124,7 @@ struct __attribute((packed)) ets_secure_boot_sig_block {
|
|||||||
uint32_t block_crc; /* note: crc covers all bytes in the structure before it, regardless of version field */
|
uint32_t block_crc; /* note: crc covers all bytes in the structure before it, regardless of version field */
|
||||||
uint8_t _padding[16];
|
uint8_t _padding[16];
|
||||||
};
|
};
|
||||||
|
#endif /* CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ESP_STATIC_ASSERT(sizeof(ets_secure_boot_sig_block_t) == 1216, "invalid sig block size");
|
ESP_STATIC_ASSERT(sizeof(ets_secure_boot_sig_block_t) == 1216, "invalid sig block size");
|
||||||
|
@@ -1119,6 +1119,10 @@ config SOC_ECDSA_SUPPORT_HW_DETERMINISTIC_LOOP
|
|||||||
bool
|
bool
|
||||||
default y
|
default y
|
||||||
|
|
||||||
|
config SOC_ECDSA_SUPPORT_CURVE_P384
|
||||||
|
bool
|
||||||
|
default y
|
||||||
|
|
||||||
config SOC_SDM_GROUPS
|
config SOC_SDM_GROUPS
|
||||||
int
|
int
|
||||||
default 1
|
default 1
|
||||||
|
@@ -442,6 +442,7 @@
|
|||||||
#define SOC_ECDSA_SUPPORT_EXPORT_PUBKEY (1)
|
#define SOC_ECDSA_SUPPORT_EXPORT_PUBKEY (1)
|
||||||
#define SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE (1)
|
#define SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE (1)
|
||||||
#define SOC_ECDSA_SUPPORT_HW_DETERMINISTIC_LOOP (1)
|
#define SOC_ECDSA_SUPPORT_HW_DETERMINISTIC_LOOP (1)
|
||||||
|
#define SOC_ECDSA_SUPPORT_CURVE_P384 (1)
|
||||||
|
|
||||||
/*-------------------------- Sigma Delta Modulator CAPS -----------------*/
|
/*-------------------------- Sigma Delta Modulator CAPS -----------------*/
|
||||||
#define SOC_SDM_GROUPS 1U
|
#define SOC_SDM_GROUPS 1U
|
||||||
|
@@ -2430,13 +2430,13 @@ extern "C" {
|
|||||||
#define EFUSE_XTS_DPA_CLK_ENABLE_ERR_M (EFUSE_XTS_DPA_CLK_ENABLE_ERR_V << EFUSE_XTS_DPA_CLK_ENABLE_ERR_S)
|
#define EFUSE_XTS_DPA_CLK_ENABLE_ERR_M (EFUSE_XTS_DPA_CLK_ENABLE_ERR_V << EFUSE_XTS_DPA_CLK_ENABLE_ERR_S)
|
||||||
#define EFUSE_XTS_DPA_CLK_ENABLE_ERR_V 0x00000001U
|
#define EFUSE_XTS_DPA_CLK_ENABLE_ERR_V 0x00000001U
|
||||||
#define EFUSE_XTS_DPA_CLK_ENABLE_ERR_S 29
|
#define EFUSE_XTS_DPA_CLK_ENABLE_ERR_S 29
|
||||||
/** EFUSE_ECDSA_P384_ENABLE_ERR : RO; bitpos: [31]; default: 0;
|
/** EFUSE_SECURE_BOOT_SHA384_EN_ERR : RO; bitpos: [31]; default: 0;
|
||||||
* Represents the programming error of EFUSE_ECDSA_P384_ENABLE
|
* Represents the programming error of EFUSE_SECURE_BOOT_SHA384_EN
|
||||||
*/
|
*/
|
||||||
#define EFUSE_ECDSA_P384_ENABLE_ERR (BIT(31))
|
#define EFUSE_SECURE_BOOT_SHA384_EN_ERR (BIT(31))
|
||||||
#define EFUSE_ECDSA_P384_ENABLE_ERR_M (EFUSE_ECDSA_P384_ENABLE_ERR_V << EFUSE_ECDSA_P384_ENABLE_ERR_S)
|
#define EFUSE_SECURE_BOOT_SHA384_EN_ERR_M (EFUSE_SECURE_BOOT_SHA384_EN_ERR_V << EFUSE_SECURE_BOOT_SHA384_EN_ERR_S)
|
||||||
#define EFUSE_ECDSA_P384_ENABLE_ERR_V 0x00000001U
|
#define EFUSE_SECURE_BOOT_SHA384_EN_ERR_V 0x00000001U
|
||||||
#define EFUSE_ECDSA_P384_ENABLE_ERR_S 31
|
#define EFUSE_SECURE_BOOT_SHA384_EN_ERR_S 31
|
||||||
|
|
||||||
/** EFUSE_RD_REPEAT_DATA_ERR4_REG register
|
/** EFUSE_RD_REPEAT_DATA_ERR4_REG register
|
||||||
* Represents rd_repeat_data_err
|
* Represents rd_repeat_data_err
|
||||||
|
@@ -1345,10 +1345,10 @@ typedef union {
|
|||||||
*/
|
*/
|
||||||
uint32_t xts_dpa_clk_enable_err:1;
|
uint32_t xts_dpa_clk_enable_err:1;
|
||||||
uint32_t reserved_30:1;
|
uint32_t reserved_30:1;
|
||||||
/** ecdsa_p384_enable_err : RO; bitpos: [31]; default: 0;
|
/** secure_boot_sha384_en_err : RO; bitpos: [31]; default: 0;
|
||||||
* Represents the programming error of EFUSE_ECDSA_P384_ENABLE
|
* Represents the programming error of EFUSE_SECURE_BOOT_SHA384_EN
|
||||||
*/
|
*/
|
||||||
uint32_t ecdsa_p384_enable_err:1;
|
uint32_t secure_boot_sha384_en_err:1;
|
||||||
};
|
};
|
||||||
uint32_t val;
|
uint32_t val;
|
||||||
} efuse_rd_repeat_data_err3_reg_t;
|
} efuse_rd_repeat_data_err3_reg_t;
|
||||||
|
@@ -485,7 +485,8 @@ In this workflow we shall use ``espsecure`` tool to generate signing keys and us
|
|||||||
:SOC_EFUSE_DIS_USB_JTAG: - ``DIS_USB_JTAG``: Disable USB switch to JTAG.
|
:SOC_EFUSE_DIS_USB_JTAG: - ``DIS_USB_JTAG``: Disable USB switch to JTAG.
|
||||||
:SOC_EFUSE_DIS_PAD_JTAG: - ``DIS_PAD_JTAG``: Disable JTAG permanently.
|
:SOC_EFUSE_DIS_PAD_JTAG: - ``DIS_PAD_JTAG``: Disable JTAG permanently.
|
||||||
:SOC_EFUSE_REVOKE_BOOT_KEY_DIGESTS: - ``SECURE_BOOT_AGGRESSIVE_REVOKE``: Aggressive revocation of key digests, see :ref:`secure-boot-v2-aggressive-key-revocation` for more details.
|
:SOC_EFUSE_REVOKE_BOOT_KEY_DIGESTS: - ``SECURE_BOOT_AGGRESSIVE_REVOKE``: Aggressive revocation of key digests, see :ref:`secure-boot-v2-aggressive-key-revocation` for more details.
|
||||||
:SOC_ECDSA_P192_CURVE_DEFAULT_DISABLED: - ``WR_DIS_ECDSA_CURVE_MODE``: Disable ECDSA curve mode.
|
:SOC_ECDSA_P192_CURVE_DEFAULT_DISABLED: - ``WR_DIS_ECDSA_CURVE_MODE``: Write disable ECDSA curve mode.
|
||||||
|
:SOC_ECDSA_SUPPORT_CURVE_P384: - ``WR_DIS_SECURE_BOOT_SHA384_EN``: Disallow writing to the secure boot using SHA-384 efuse bit.
|
||||||
|
|
||||||
The respective eFuses can be burned by running:
|
The respective eFuses can be burned by running:
|
||||||
|
|
||||||
|
@@ -813,9 +813,9 @@ def action_extensions(base_actions: Dict, project_path: str) -> Dict:
|
|||||||
'secure-generate-signing-key': {
|
'secure-generate-signing-key': {
|
||||||
'callback': secure_generate_signing_key,
|
'callback': secure_generate_signing_key,
|
||||||
'help': (
|
'help': (
|
||||||
'Generate a private key for signing secure boot images as per the secure boot version. Key file is '
|
'Generate a private key for signing secure boot images as per the secure boot version.'
|
||||||
'generated in PEM format, Secure Boot V1 - ECDSA NIST256p private key. Secure Boot V2 - RSA 3072, '
|
' Key file is generated in PEM format, Secure Boot V1 - ECDSA NIST256p private key.'
|
||||||
'ECDSA NIST256p, ECDSA NIST192p private key.'
|
' Secure Boot V2 - RSA 3072, ECDSA NIST384p, ECDSA NIST256p, ECDSA NIST192p private key.'
|
||||||
),
|
),
|
||||||
'options': [
|
'options': [
|
||||||
{
|
{
|
||||||
@@ -827,7 +827,7 @@ def action_extensions(base_actions: Dict, project_path: str) -> Dict:
|
|||||||
{
|
{
|
||||||
'names': ['--scheme', '-s'],
|
'names': ['--scheme', '-s'],
|
||||||
'help': ('Scheme of secure boot signing.'),
|
'help': ('Scheme of secure boot signing.'),
|
||||||
'type': click.Choice(['rsa3072', 'ecdsa192', 'ecdsa256']),
|
'type': click.Choice(['rsa3072', 'ecdsa192', 'ecdsa256', 'ecdsa384']),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'arguments': [
|
'arguments': [
|
||||||
@@ -854,8 +854,8 @@ def action_extensions(base_actions: Dict, project_path: str) -> Dict:
|
|||||||
'secure-sign-data': {
|
'secure-sign-data': {
|
||||||
'callback': secure_sign_data,
|
'callback': secure_sign_data,
|
||||||
'help': (
|
'help': (
|
||||||
'Sign a data file for use with secure boot. Signing algorithm is deterministic ECDSA w/ SHA-512 '
|
'Sign a data file for use with secure boot. Signing algorithm is deterministic'
|
||||||
'(V1) or either RSA-PSS or ECDSA w/ SHA-256 (V2).'
|
' ECDSA w/ SHA-512 (V1) or either RSA-PSS or ECDSA w/ SHA-256 (V2) or ECDSA w/ SHA-384 (V2).'
|
||||||
),
|
),
|
||||||
'options': [
|
'options': [
|
||||||
{
|
{
|
||||||
@@ -871,7 +871,9 @@ def action_extensions(base_actions: Dict, project_path: str) -> Dict:
|
|||||||
{
|
{
|
||||||
'names': ['--append-signatures', '-a'],
|
'names': ['--append-signatures', '-a'],
|
||||||
'is_flag': True,
|
'is_flag': True,
|
||||||
'help': ('Append signature block(s) to already signed image. Valid only for ESP32-S2.'),
|
'help': (
|
||||||
|
'Append signature block(s) to already signed image. Not valid for ESP32 and ESP32-C2.'
|
||||||
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'names': ['--pub-key'],
|
'names': ['--pub-key'],
|
||||||
|
Reference in New Issue
Block a user