esp32c2: Support Secure Boot V2 based on ECDSA scheme

This commit is contained in:
Sachin Parekh 2022-03-10 10:53:15 +05:30 committed by Mahavir Jain
parent dec3db6913
commit 2c725264f7
No known key found for this signature in database
GPG Key ID: 99324EF4A00734E0
18 changed files with 596 additions and 193 deletions

View File

@ -449,7 +449,12 @@ menu "Security features"
bool bool
default y default y
# RSA secure boot is supported in ESP32 revision >= ECO3 # RSA secure boot is supported in ESP32 revision >= ECO3
depends on ESP32_REV_MIN >= 3 || SOC_SECURE_BOOT_V2_RSA depends on (IDF_TARGET_ESP32 && ESP32_REV_MIN >= 3) || SOC_SECURE_BOOT_V2_RSA
config SECURE_BOOT_V2_ECC_SUPPORTED
bool
default y
depends on SOC_SECURE_BOOT_V2_ECC
config SECURE_BOOT_V1_SUPPORTED config SECURE_BOOT_V1_SUPPORTED
bool bool
@ -461,6 +466,13 @@ menu "Security features"
default y default y
depends on ESP32_REV_MIN >= 3 depends on ESP32_REV_MIN >= 3
config SECURE_BOOT_V2_ECDSA_ENABLED
bool
default y if SECURE_BOOT_V2_ENABLED && SECURE_BOOT_V2_ECC_SUPPORTED
config SECURE_BOOT_V2_RSA_ENABLED
bool
default y if SECURE_BOOT_V2_ENABLED && SECURE_BOOT_V2_RSA_SUPPORTED
config SECURE_SIGNED_APPS_NO_SECURE_BOOT config SECURE_SIGNED_APPS_NO_SECURE_BOOT
bool "Require signed app images" bool "Require signed app images"
@ -477,21 +489,26 @@ menu "Security features"
bool "App Signing Scheme" bool "App Signing Scheme"
depends on SECURE_BOOT || SECURE_SIGNED_APPS_NO_SECURE_BOOT depends on SECURE_BOOT || SECURE_SIGNED_APPS_NO_SECURE_BOOT
default SECURE_SIGNED_APPS_ECDSA_SCHEME if SECURE_BOOT_V1_ENABLED default SECURE_SIGNED_APPS_ECDSA_SCHEME if SECURE_BOOT_V1_ENABLED
default SECURE_SIGNED_APPS_RSA_SCHEME if SECURE_BOOT_V2_ENABLED default SECURE_SIGNED_APPS_RSA_SCHEME if SECURE_BOOT_V2_RSA_SUPPORTED
default SECURE_SIGNED_APPS_ECDSA_V2_SCHEME if SECURE_BOOT_V2_ECC_SUPPORTED
help help
Select the Secure App signing scheme. Depends on the Chip Revision. Select the Secure App signing scheme. Depends on the Chip Revision.
There are two options: There are two secure boot versions:
1. ECDSA based secure boot scheme. (Only choice for Secure Boot V1)
Supported in ESP32 and ESP32-ECO3. 1. Secure boot V1
2. The RSA based secure boot scheme. (Only choice for Secure Boot V2) - Legacy custom secure boot scheme. Supported in ESP32 SoC.
Supported in ESP32-ECO3 (ESP32 Chip Revision 3 onwards), ESP32-S2, ESP32-C3, ESP32-S3.
2. Secure boot V2
- RSA based secure boot scheme.
Supported in ESP32-ECO3 (ESP32 Chip Revision 3 onwards), ESP32-S2, ESP32-C3, ESP32-S3 SoCs.
- ECDSA based secure boot scheme. Supported in ESP32-C2 SoC.
config SECURE_SIGNED_APPS_ECDSA_SCHEME config SECURE_SIGNED_APPS_ECDSA_SCHEME
bool "ECDSA" bool "ECDSA"
depends on SECURE_BOOT_V1_SUPPORTED && (SECURE_SIGNED_APPS_NO_SECURE_BOOT || SECURE_BOOT_V1_ENABLED) depends on SECURE_BOOT_V1_SUPPORTED && (SECURE_SIGNED_APPS_NO_SECURE_BOOT || SECURE_BOOT_V1_ENABLED)
help help
Embeds the ECDSA public key in the bootloader and signs the application with an ECDSA key. Embeds the ECDSA public key in the bootloader and signs the application with an ECDSA key.
Refer to the documentation before enabling. Refer to the documentation before enabling.
config SECURE_SIGNED_APPS_RSA_SCHEME config SECURE_SIGNED_APPS_RSA_SCHEME
@ -500,6 +517,38 @@ menu "Security features"
help help
Appends the RSA-3072 based Signature block to the application. Appends the RSA-3072 based Signature block to the application.
Refer to <Secure Boot Version 2 documentation link> before enabling. Refer to <Secure Boot Version 2 documentation link> before enabling.
config SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
bool "ECDSA (V2)"
depends on SECURE_BOOT_V2_ECC_SUPPORTED && (SECURE_SIGNED_APPS_NO_SECURE_BOOT || SECURE_BOOT_V2_ENABLED)
help
For Secure boot V2 (e.g., ESP32-C2 SoC), appends ECDSA based signature block to the application.
Refer to documentation before enabling.
endchoice
choice SECURE_BOOT_ECDSA_KEY_LEN_SIZE
bool "ECDSA key size"
depends on SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
default SECURE_BOOT_ECDSA_KEY_LEN_256_BITS
help
Select the ECDSA key size. Two key sizes are supported
- 192 bit key using NISTP192 curve
- 256 bit key using NISTP256 curve (Recommended)
The advantage of using 256 bit key is the extra randomness which makes it difficult to be
bruteforced compared to 192 bit key.
At present, both key sizes are practically implausible to bruteforce.
config SECURE_BOOT_ECDSA_KEY_LEN_192_BITS
bool "Using ECC curve NISTP192"
depends on SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
config SECURE_BOOT_ECDSA_KEY_LEN_256_BITS
bool "Using ECC curve NISTP256 (Recommended)"
depends on SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
endchoice endchoice
config SECURE_SIGNED_ON_BOOT_NO_SECURE_BOOT config SECURE_SIGNED_ON_BOOT_NO_SECURE_BOOT
@ -549,10 +598,16 @@ menu "Security features"
depends on SECURE_BOOT depends on SECURE_BOOT
help help
Select the Secure Boot Version. Depends on the Chip Revision. Select the Secure Boot Version. Depends on the Chip Revision.
Secure Boot V2 is the new RSA based secure boot scheme. Secure Boot V2 is the new RSA / ECDSA based secure boot scheme.
Supported in ESP32-ECO3 (ESP32 Chip Revision 3 onwards), ESP32-S2, ESP32-C3 ECO3.
Secure Boot V1 is the AES based secure boot scheme. - RSA based scheme is supported in ESP32 (Revision 3 onwards), ESP32-S2, ESP32-C3 (ECO3), ESP32-S3.
Supported in ESP32 and ESP32-ECO3. - ECDSA based scheme is supported in ESP32-C2 SoC.
Please note that, RSA or ECDSA secure boot is property of specific SoC based on its HW design, supported
crypto accelerators, die-size, cost and similar parameters. Please note that RSA scheme has requirement
for bigger key sizes but at the same time it is comparatively faster than ECDSA verification.
Secure Boot V1 is the AES based (custom) secure boot scheme supported in ESP32 SoC.
config SECURE_BOOT_V1_ENABLED config SECURE_BOOT_V1_ENABLED
bool "Enable Secure Boot version 1" bool "Enable Secure Boot version 1"
@ -563,7 +618,7 @@ menu "Security features"
config SECURE_BOOT_V2_ENABLED config SECURE_BOOT_V2_ENABLED
bool "Enable Secure Boot version 2" bool "Enable Secure Boot version 2"
depends on SECURE_BOOT_V2_RSA_SUPPORTED depends on SECURE_BOOT_V2_RSA_SUPPORTED || SECURE_BOOT_V2_ECC_SUPPORTED
help help
Build a bootloader which enables Secure Boot version 2 on first boot. Build a bootloader which enables Secure Boot version 2 on first boot.
Refer to Secure Boot V2 section of the ESP-IDF Programmer's Guide for this version before enabling. Refer to Secure Boot V2 section of the ESP-IDF Programmer's Guide for this version before enabling.

View File

@ -30,9 +30,9 @@ if(CONFIG_SECURE_SIGNED_APPS)
add_custom_target(gen_secure_boot_keys) add_custom_target(gen_secure_boot_keys)
if(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME) if(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME)
set(secure_apps_signing_scheme "1") set(secure_apps_signing_version "1")
elseif(CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME) elseif(CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME OR CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME)
set(secure_apps_signing_scheme "2") set(secure_apps_signing_version "2")
endif() endif()
if(CONFIG_SECURE_BOOT_V1_ENABLED) if(CONFIG_SECURE_BOOT_V1_ENABLED)
@ -64,10 +64,22 @@ if(CONFIG_SECURE_SIGNED_APPS)
# If the signing key is not found, create a phony gen_secure_boot_signing_key target that # If the signing key is not found, create a phony gen_secure_boot_signing_key target that
# fails the build. fail_at_build_time causes a cmake run next time # fails the build. fail_at_build_time causes a cmake run next time
# (to pick up a new signing key if one exists, etc.) # (to pick up a new signing key if one exists, etc.)
fail_at_build_time(gen_secure_boot_signing_key if(CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME)
"Secure Boot Signing Key ${CONFIG_SECURE_BOOT_SIGNING_KEY} does not exist. Generate using:" fail_at_build_time(gen_secure_boot_signing_key
"\tespsecure.py generate_signing_key --version ${secure_apps_signing_scheme} \ "Secure Boot Signing Key ${CONFIG_SECURE_BOOT_SIGNING_KEY} does not exist. Generate using:"
${CONFIG_SECURE_BOOT_SIGNING_KEY}") "\tespsecure.py generate_signing_key --version ${secure_apps_signing_version} \
${CONFIG_SECURE_BOOT_SIGNING_KEY}")
else()
if(CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_192_BITS)
set(scheme "ecdsa192")
elseif(CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_256_BITS)
set(scheme "ecdsa256")
endif()
fail_at_build_time(gen_secure_boot_signing_key
"Secure Boot Signing Key ${CONFIG_SECURE_BOOT_SIGNING_KEY} does not exist. Generate using:"
"\tespsecure.py generate_signing_key --version ${secure_apps_signing_version} \
--scheme ${scheme} ${CONFIG_SECURE_BOOT_SIGNING_KEY}")
endif()
else() else()
add_custom_target(gen_secure_boot_signing_key) add_custom_target(gen_secure_boot_signing_key)
endif() endif()

View File

@ -55,11 +55,9 @@ if(BOOTLOADER_BUILD)
"src/${IDF_TARGET}/secure_boot_secure_features.c") "src/${IDF_TARGET}/secure_boot_secure_features.c")
endif() endif()
if(CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME)
list(APPEND srcs "src/secure_boot_v2/secure_boot_signatures_bootloader.c")
endif()
if(CONFIG_SECURE_BOOT_V2_ENABLED) if(CONFIG_SECURE_BOOT_V2_ENABLED)
list(APPEND srcs "src/secure_boot_v2/secure_boot.c" list(APPEND srcs "src/secure_boot_v2/secure_boot_signatures_bootloader.c"
"src/secure_boot_v2/secure_boot.c"
"src/${IDF_TARGET}/secure_boot_secure_features.c") "src/${IDF_TARGET}/secure_boot_secure_features.c")
endif() endif()
endif() endif()
@ -71,6 +69,11 @@ else()
if(CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME) if(CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME)
list(APPEND srcs "src/secure_boot_v2/secure_boot_signatures_app.c") list(APPEND srcs "src/secure_boot_v2/secure_boot_signatures_app.c")
list(APPEND srcs "src/secure_boot_v2/secure_boot_rsa_signature.c")
endif()
if(CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME)
list(APPEND srcs "src/secure_boot_v2/secure_boot_signatures_app.c")
list(APPEND srcs "src/secure_boot_v2/secure_boot_ecdsa_signature.c")
endif() endif()
endif() endif()
endif() endif()

View File

@ -51,6 +51,12 @@ extern "C" {
#define ESP_SECURE_BOOT_DIGEST_LEN 32 #define ESP_SECURE_BOOT_DIGEST_LEN 32
#if CONFIG_IDF_TARGET_ESP32C2
#define ESP_SECURE_BOOT_KEY_DIGEST_LEN 16
#else
#define ESP_SECURE_BOOT_KEY_DIGEST_LEN 32
#endif
#ifdef CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH #ifdef CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH
#include "esp_efuse.h" #include "esp_efuse.h"
#include "esp_efuse_table.h" #include "esp_efuse_table.h"
@ -215,18 +221,30 @@ typedef struct {
unsigned num_digests; /* Number of valid digests, starting at index 0 */ unsigned num_digests; /* Number of valid digests, starting at index 0 */
} esp_image_sig_public_key_digests_t; } esp_image_sig_public_key_digests_t;
/** @brief Verify the RSA secure boot signature block for Secure Boot V2. /** @brief Verify the secure boot signature block for Secure Boot V2.
* *
* Performs RSA-PSS Verification of the SHA-256 image based on the public key * Performs RSA-PSS or ECDSA verification of the SHA-256 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 sig_block Pointer to signature block data
* @param image_digest Pointer to 32 byte buffer holding SHA-256 hash.
* @param verified_digest Pointer to 32 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);
/** @brief Legacy function to verify RSA secure boot signature block for Secure Boot V2.
*
* @note This is kept for backward compatibility. It internally calls esp_secure_boot_verify_sbv2_signature_block.
*
* @param sig_block Pointer to RSA signature block data * @param sig_block Pointer to RSA signature block data
* @param image_digest Pointer to 32 byte buffer holding SHA-256 hash. * @param image_digest Pointer to 32 byte buffer holding SHA-256 hash.
* @param 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 verified_digest Pointer to 32 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_rsa_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_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 #endif // !CONFIG_IDF_TARGET_ESP32 || CONFIG_ESP32_REV_MIN_3
/** @brief Legacy ECDSA verification function /** @brief Legacy ECDSA verification function
@ -259,7 +277,7 @@ typedef struct {
*/ */
void esp_secure_boot_init_checks(void); void esp_secure_boot_init_checks(void);
#if !BOOTLOADER_BUILD && CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME #if !BOOTLOADER_BUILD && (CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME || CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME)
/** @brief Scan the current running app for signature blocks /** @brief Scan the current running app for signature blocks
* *
@ -285,7 +303,7 @@ void esp_secure_boot_init_checks(void);
*/ */
esp_err_t esp_secure_boot_get_signature_blocks_for_running_app(bool digest_public_keys, esp_image_sig_public_key_digests_t *public_key_digests); esp_err_t esp_secure_boot_get_signature_blocks_for_running_app(bool digest_public_keys, esp_image_sig_public_key_digests_t *public_key_digests);
#endif // !BOOTLOADER_BUILD && CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME #endif // !BOOTLOADER_BUILD && (CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME || CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME)
/** @brief Set all secure eFuse features related to secure_boot /** @brief Set all secure eFuse features related to secure_boot
* *

View File

@ -16,7 +16,7 @@ static __attribute__((unused)) const char *TAG = "secure_boot";
esp_err_t esp_secure_boot_enable_secure_features(void) esp_err_t esp_secure_boot_enable_secure_features(void)
{ {
esp_efuse_write_field_bit(ESP_EFUSE_DIS_LEGACY_SPI_BOOT); esp_efuse_write_field_bit(ESP_EFUSE_DIS_DIRECT_BOOT);
#ifdef CONFIG_SECURE_ENABLE_SECURE_ROM_DL_MODE #ifdef CONFIG_SECURE_ENABLE_SECURE_ROM_DL_MODE
ESP_LOGI(TAG, "Enabling Security download mode..."); ESP_LOGI(TAG, "Enabling Security download mode...");
@ -39,16 +39,10 @@ esp_err_t esp_secure_boot_enable_secure_features(void)
#ifndef CONFIG_SECURE_BOOT_ALLOW_JTAG #ifndef CONFIG_SECURE_BOOT_ALLOW_JTAG
ESP_LOGI(TAG, "Disable hardware & software JTAG..."); ESP_LOGI(TAG, "Disable hardware & software JTAG...");
esp_efuse_write_field_bit(ESP_EFUSE_DIS_PAD_JTAG); esp_efuse_write_field_bit(ESP_EFUSE_DIS_PAD_JTAG);
esp_efuse_write_field_bit(ESP_EFUSE_DIS_USB_JTAG);
esp_efuse_write_field_bit(ESP_EFUSE_SOFT_DIS_JTAG);
#else #else
ESP_LOGW(TAG, "Not disabling JTAG - SECURITY COMPROMISED"); ESP_LOGW(TAG, "Not disabling JTAG - SECURITY COMPROMISED");
#endif #endif
#ifdef CONFIG_SECURE_BOOT_ENABLE_AGGRESSIVE_KEY_REVOKE
esp_efuse_write_field_bit(ESP_EFUSE_SECURE_BOOT_AGGRESSIVE_REVOKE);
#endif
esp_efuse_write_field_bit(ESP_EFUSE_SECURE_BOOT_EN); esp_efuse_write_field_bit(ESP_EFUSE_SECURE_BOOT_EN);
return ESP_OK; return ESP_OK;

View File

@ -827,7 +827,7 @@ static esp_err_t verify_secure_boot_signature(bootloader_sha256_handle_t sha_han
bootloader_munmap(simple_hash); bootloader_munmap(simple_hash);
} }
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME #if CONFIG_SECURE_BOOT_V2_ENABLED
// End of the image needs to be padded all the way to a 4KB boundary, after the simple hash // 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.) // (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 = (end + FLASH_SECTOR_SIZE - 1) & ~(FLASH_SECTOR_SIZE-1); uint32_t padded_end = (end + FLASH_SECTOR_SIZE - 1) & ~(FLASH_SECTOR_SIZE-1);
@ -846,18 +846,18 @@ static esp_err_t verify_secure_boot_signature(bootloader_sha256_handle_t sha_han
// 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 defined(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME) || defined(CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME) #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, HASH_LEN) != 0); /* sanity check that these values start differently */
#ifdef 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);
#else #else
sig_block = bootloader_mmap(end, sizeof(ets_secure_boot_signature_t)); 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); err = esp_secure_boot_verify_sbv2_signature_block(sig_block, image_digest, verified_digest);
#endif #endif
bootloader_munmap(sig_block); bootloader_munmap(sig_block);
#endif // CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME or CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME #endif // CONFIG_SECURE_BOOT || CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT
if (err != ESP_OK) { if (err != ESP_OK) {
ESP_LOGE(TAG, "Secure boot signature verification failed"); ESP_LOGE(TAG, "Secure boot signature verification failed");
@ -877,7 +877,7 @@ static esp_err_t verify_secure_boot_signature(bootloader_sha256_handle_t sha_han
return ESP_ERR_IMAGE_INVALID; return ESP_ERR_IMAGE_INVALID;
} }
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME #if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME || CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
// Adjust image length result to include the appended signature // Adjust image length result to include the appended signature
data->image_len = end - data->start_addr + sizeof(ets_secure_boot_signature_t); data->image_len = end - data->start_addr + sizeof(ets_secure_boot_signature_t);
#endif #endif

View File

@ -98,12 +98,20 @@ static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uin
/* Generating the SHA of the public key components in the signature block */ /* Generating the SHA of the public key components in the signature block */
bootloader_sha256_handle_t sig_block_sha; bootloader_sha256_handle_t sig_block_sha;
sig_block_sha = bootloader_sha256_start(); sig_block_sha = bootloader_sha256_start();
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
bootloader_sha256_data(sig_block_sha, &block->key, sizeof(block->key)); bootloader_sha256_data(sig_block_sha, &block->key, sizeof(block->key));
#elif CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
bootloader_sha256_data(sig_block_sha, &block->ecdsa.key, sizeof(block->ecdsa.key));
#endif
bootloader_sha256_finish(sig_block_sha, key_digest); bootloader_sha256_finish(sig_block_sha, key_digest);
// Check we can verify the image using this signature and this key // Check we can verify the image using this signature and this key
uint8_t temp_verified_digest[ESP_SECURE_BOOT_DIGEST_LEN]; uint8_t temp_verified_digest[ESP_SECURE_BOOT_DIGEST_LEN];
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
bool verified = ets_rsa_pss_verify(&block->key, block->signature, image_digest, temp_verified_digest); bool verified = ets_rsa_pss_verify(&block->key, block->signature, image_digest, temp_verified_digest);
#elif CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
bool verified = ets_ecdsa_verify(&block->ecdsa.key.point[0], block->ecdsa.signature, block->ecdsa.key.curve_id, image_digest, temp_verified_digest);
#endif
if (!verified) { if (!verified) {
/* We don't expect this: the signature blocks before we enable secure boot should all be verifiable or invalid, /* We don't expect this: the signature blocks before we enable secure boot should all be verifiable or invalid,

View File

@ -0,0 +1,100 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "esp_log.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 "mbedtls/ecp.h"
#include "rom/ecdsa.h"
static const char *TAG = "secure_boot_v2_ecdsa";
#define ECDSA_INTEGER_LEN 32
esp_err_t verify_ecdsa_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, const ets_secure_boot_sig_block_t *trusted_block)
{
if (!sig_block || !image_digest || !trusted_block) {
return ESP_ERR_INVALID_ARG;
}
esp_err_t ret;
mbedtls_mpi r, s;
mbedtls_mpi_init(&r);
mbedtls_mpi_init(&s);
/* Initialise ECDSA context */
mbedtls_ecdsa_context ecdsa_context;
mbedtls_ecdsa_init(&ecdsa_context);
uint8_t key_size = 0;
switch(trusted_block->ecdsa.key.curve_id) {
case ECDSA_CURVE_P192:
key_size = 24;
mbedtls_ecp_group_load(&ecdsa_context.MBEDTLS_PRIVATE(grp), MBEDTLS_ECP_DP_SECP192R1);
break;
case ECDSA_CURVE_P256:
key_size = 32;
mbedtls_ecp_group_load(&ecdsa_context.MBEDTLS_PRIVATE(grp), MBEDTLS_ECP_DP_SECP256R1);
break;
default:
ESP_LOGE(TAG, "Invalid curve ID");
return ESP_ERR_INVALID_ARG;
}
uint8_t x_point[ECDSA_INTEGER_LEN] = {};
uint8_t y_point[ECDSA_INTEGER_LEN] = {};
uint8_t _r[ECDSA_INTEGER_LEN] = {};
uint8_t _s[ECDSA_INTEGER_LEN] = {};
/* Convert r and s components to big endian format */
for (int i = 0; i < key_size; i++) {
_r[i] = trusted_block->ecdsa.signature[key_size - i - 1];
_s[i] = trusted_block->ecdsa.signature[2 * key_size - i - 1];
}
/* Extract r and s components from RAW ECDSA signature of 64 bytes */
ret = mbedtls_mpi_read_binary(&r, _r, key_size);
if (ret != 0) {
ESP_LOGE(TAG, "Failed mbedtls_mpi_read_binary(r), err:%d", ret);
mbedtls_ecdsa_free(&ecdsa_context);
return ESP_FAIL;
}
ret = mbedtls_mpi_read_binary(&s, _s, key_size);
if (ret != 0) {
ESP_LOGE(TAG, "Failed mbedtls_mpi_read_binary(s), err:%d", ret);
mbedtls_mpi_free(&r);
mbedtls_ecdsa_free(&ecdsa_context);
return ESP_FAIL;
}
size_t plen = mbedtls_mpi_size(&ecdsa_context.MBEDTLS_PRIVATE(grp).P);
for (int i = 0; i < plen; i++) {
x_point[i] = trusted_block->ecdsa.key.point[plen - 1 - i];
y_point[i] = trusted_block->ecdsa.key.point[2 * plen - 1 - i];
}
/* Extract X and Y components from ECDSA public key */
MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ecdsa_context.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X), x_point, plen));
MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ecdsa_context.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y), y_point, plen));
MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&ecdsa_context.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Z), 1));
ret = mbedtls_ecdsa_verify(&ecdsa_context.MBEDTLS_PRIVATE(grp), image_digest, ESP_SECURE_BOOT_DIGEST_LEN, &ecdsa_context.MBEDTLS_PRIVATE(Q), &r, &s);
cleanup:
mbedtls_mpi_free(&r);
mbedtls_mpi_free(&s);
mbedtls_ecdsa_free(&ecdsa_context);
return ret;
}

View File

@ -0,0 +1,99 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "esp_log.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"
static const char *TAG = "secure_boot_v2_rsa";
esp_err_t verify_rsa_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, const ets_secure_boot_sig_block_t *trusted_block)
{
if (!sig_block || !image_digest || !trusted_block) {
return ESP_ERR_INVALID_ARG;
}
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);
if (sig_be == NULL) {
return ESP_ERR_NO_MEM;
}
unsigned char *buf = calloc(1, rsa_key_size);
if (buf == NULL) {
free(sig_be);
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_outer;
}
const mbedtls_mpi N = { .MBEDTLS_PRIVATE(s) = 1,
.MBEDTLS_PRIVATE(n) = sizeof(trusted_block->key.n)/sizeof(mbedtls_mpi_uint),
.MBEDTLS_PRIVATE(p) = (void *)trusted_block->key.n,
};
const mbedtls_mpi e = { .MBEDTLS_PRIVATE(s) = 1,
.MBEDTLS_PRIVATE(n) = sizeof(trusted_block->key.e)/sizeof(mbedtls_mpi_uint), // 1
.MBEDTLS_PRIVATE(p) = (void *)&trusted_block->key.e,
};
mbedtls_rsa_init(&pk);
mbedtls_rsa_set_padding(&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_inner;
}
ret = mbedtls_rsa_complete(&pk);
if (ret != 0) {
ESP_LOGE(TAG, "Failed mbedtls_rsa_complete, err: %d", ret);
goto exit_inner;
}
ret = mbedtls_rsa_check_pubkey(&pk);
if (ret != 0) {
ESP_LOGI(TAG, "Key is not an RSA key -%0x", -ret);
goto exit_inner;
}
/* 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] = trusted_block->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_inner;
}
ret = mbedtls_rsa_rsassa_pss_verify( &pk, 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_inner:
mbedtls_rsa_free(&pk);
exit_outer:
mbedtls_ctr_drbg_free(&ctr_drbg);
mbedtls_entropy_free(&entropy);
free(sig_be);
free(buf);
return ret;
}

View File

@ -0,0 +1,11 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "esp_secure_boot.h"
#include "esp_log.h"
esp_err_t verify_ecdsa_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, const ets_secure_boot_sig_block_t *trusted_block);
esp_err_t verify_rsa_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, const ets_secure_boot_sig_block_t *trusted_block);

View File

@ -22,13 +22,15 @@
#include "esp_ota_ops.h" #include "esp_ota_ops.h"
#include "esp_efuse.h" #include "esp_efuse.h"
#include "secure_boot_signature_priv.h"
// Secure boot V2 for app // Secure boot V2 for app
_Static_assert(SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS == SECURE_BOOT_NUM_BLOCKS, _Static_assert(SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS == SECURE_BOOT_NUM_BLOCKS,
"Parts of this code rely on the max number of signatures appended to an image" "Parts of this code rely on the max number of signatures appended to an image"
"being the same as the max number of trusted keys."); "being the same as the max number of trusted keys.");
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME || CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT #if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME || CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME || CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT
static const char *TAG = "secure_boot_v2"; static const char *TAG = "secure_boot_v2";
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1)) #define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
@ -76,7 +78,11 @@ esp_err_t esp_secure_boot_get_signature_blocks_for_running_app(bool digest_publi
if (validate_signature_block(&block) == ESP_OK) { if (validate_signature_block(&block) == ESP_OK) {
if (digest_public_keys) { if (digest_public_keys) {
bootloader_sha256_handle_t sig_block_sha = bootloader_sha256_start(); bootloader_sha256_handle_t sig_block_sha = bootloader_sha256_start();
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
bootloader_sha256_data(sig_block_sha, &block.key, sizeof(block.key)); bootloader_sha256_data(sig_block_sha, &block.key, sizeof(block.key));
#elif CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
bootloader_sha256_data(sig_block_sha, &block.ecdsa.key, sizeof(block.ecdsa.key));
#endif
bootloader_sha256_finish(sig_block_sha, public_key_digests->key_digests[i]); bootloader_sha256_finish(sig_block_sha, public_key_digests->key_digests[i]);
} }
public_key_digests->num_digests++; public_key_digests->num_digests++;
@ -106,7 +112,7 @@ static esp_err_t get_secure_boot_key_digests(esp_image_sig_public_key_digests_t
if (esp_secure_boot_read_key_digests(&efuse_trusted) == ESP_OK) { if (esp_secure_boot_read_key_digests(&efuse_trusted) == ESP_OK) {
for (unsigned i = 0; i < SECURE_BOOT_NUM_BLOCKS; i++) { for (unsigned i = 0; i < SECURE_BOOT_NUM_BLOCKS; i++) {
if (efuse_trusted.key_digests[i] != NULL) { 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); memcpy(public_key_digests->key_digests[i], (uint8_t *)efuse_trusted.key_digests[i], ESP_SECURE_BOOT_KEY_DIGEST_LEN);
public_key_digests->num_digests++; public_key_digests->num_digests++;
} }
} }
@ -120,8 +126,8 @@ 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)
{ {
uint8_t digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0}; uint8_t digest[ESP_SECURE_BOOT_KEY_DIGEST_LEN] = {0};
uint8_t verified_digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0}; uint8_t verified_digest[ESP_SECURE_BOOT_KEY_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);
@ -139,7 +145,7 @@ esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
return ESP_FAIL; return ESP_FAIL;
} }
err = esp_secure_boot_verify_rsa_signature_block(sig_block, digest, verified_digest); err = esp_secure_boot_verify_sbv2_signature_block(sig_block, digest, verified_digest);
if (err != ESP_OK) { if (err != ESP_OK) {
ESP_LOGE(TAG, "Secure Boot V2 verification failed."); ESP_LOGE(TAG, "Secure Boot V2 verification failed.");
} }
@ -150,13 +156,13 @@ esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
// This verify function is called only from app, during ota update. // 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. // 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). // 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) 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)
{ {
bool any_trusted_key = false; bool any_trusted_key = false;
/* Note: in IDF verification we don't add any fault injection resistance, as we don't expect this to be called /* 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. */ during boot-time verification. */
memset(verified_digest, 0, ESP_SECURE_BOOT_DIGEST_LEN); memset(verified_digest, 0, ESP_SECURE_BOOT_KEY_DIGEST_LEN);
esp_image_sig_public_key_digests_t trusted = {0}; esp_image_sig_public_key_digests_t trusted = {0};
@ -165,26 +171,7 @@ esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signa
return ESP_FAIL; return ESP_FAIL;
} }
int ret = 0; 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_outer;
}
#ifdef CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT #ifdef CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT
const unsigned secure_boot_num_blocks = 1; const unsigned secure_boot_num_blocks = 1;
#else #else
@ -202,12 +189,17 @@ esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signa
/* Generate the SHA of the public key components in the signature block */ /* Generate the SHA of the public key components in the signature block */
bootloader_sha256_handle_t sig_block_sha = bootloader_sha256_start(); bootloader_sha256_handle_t sig_block_sha = bootloader_sha256_start();
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
bootloader_sha256_data(sig_block_sha, &app_blk->key, sizeof(app_blk->key)); bootloader_sha256_data(sig_block_sha, &app_blk->key, sizeof(app_blk->key));
#elif CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
bootloader_sha256_data(sig_block_sha, &app_blk->ecdsa.key, sizeof(app_blk->ecdsa.key));
#endif
bootloader_sha256_finish(sig_block_sha, app_blk_digest); bootloader_sha256_finish(sig_block_sha, app_blk_digest);
/* Check if the key is one we trust */ /* Check if the key is one we trust */
for (unsigned trusted_key_idx = 0; trusted_key_idx < secure_boot_num_blocks; trusted_key_idx++) { for (unsigned trusted_key_idx = 0; trusted_key_idx < secure_boot_num_blocks; trusted_key_idx++) {
if (memcmp(app_blk_digest, trusted.key_digests[trusted_key_idx], ESP_SECURE_BOOT_DIGEST_LEN) == 0) { if (memcmp(app_blk_digest, trusted.key_digests[trusted_key_idx], ESP_SECURE_BOOT_KEY_DIGEST_LEN) == 0) {
ESP_LOGI(TAG, "#%d app key digest == #%d trusted key digest", app_blk_idx, trusted_key_idx); ESP_LOGI(TAG, "#%d app key digest == #%d trusted key digest", app_blk_idx, trusted_key_idx);
trusted_block = app_blk; trusted_block = app_blk;
any_trusted_key = true; any_trusted_key = true;
@ -220,63 +212,26 @@ esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signa
continue; // Skip the signature blocks with no trusted digest continue; // Skip the signature blocks with no trusted digest
} }
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
ESP_LOGI(TAG, "Verifying with RSA-PSS..."); ESP_LOGI(TAG, "Verifying with RSA-PSS...");
ret = verify_rsa_signature_block(sig_block, image_digest, trusted_block);
const mbedtls_mpi N = { .MBEDTLS_PRIVATE(s) = 1, #elif CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
.MBEDTLS_PRIVATE(n) = sizeof(trusted_block->key.n)/sizeof(mbedtls_mpi_uint), ESP_LOGI(TAG, "Verifying with ECDSA...");
.MBEDTLS_PRIVATE(p) = (void *)trusted_block->key.n, ret = verify_ecdsa_signature_block(sig_block, image_digest, trusted_block);
}; #endif
const mbedtls_mpi e = { .MBEDTLS_PRIVATE(s) = 1,
.MBEDTLS_PRIVATE(n) = sizeof(trusted_block->key.e)/sizeof(mbedtls_mpi_uint), // 1
.MBEDTLS_PRIVATE(p) = (void *)&trusted_block->key.e,
};
mbedtls_rsa_init(&pk);
mbedtls_rsa_set_padding(&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_inner;
}
ret = mbedtls_rsa_complete(&pk);
if (ret != 0) {
ESP_LOGE(TAG, "Failed mbedtls_rsa_complete, err: %d", ret);
goto exit_inner;
}
ret = mbedtls_rsa_check_pubkey(&pk);
if (ret != 0) {
ESP_LOGI(TAG, "Key is not an RSA key -%0x", -ret);
goto exit_inner;
}
/* 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] = trusted_block->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_inner;
}
ret = mbedtls_rsa_rsassa_pss_verify( &pk, 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_inner:
mbedtls_rsa_free(&pk);
if (ret == 0) { if (ret == 0) {
break; break;
} }
} }
exit_outer:
free(sig_be);
free(buf);
return (ret != 0 || any_trusted_key == false) ? ESP_ERR_IMAGE_INVALID: ESP_OK; return (ret != 0 || any_trusted_key == false) ? ESP_ERR_IMAGE_INVALID: ESP_OK;
} }
#endif // CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME || CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
// To maintain backward compatibility
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)
{
return esp_secure_boot_verify_sbv2_signature_block(sig_block, image_digest, verified_digest);
}
#endif
#endif // CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME || CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME || CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT

View File

@ -17,7 +17,7 @@
// Secure boot V2 for bootloader. // Secure boot V2 for bootloader.
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME && CONFIG_SECURE_BOOT_V2_ENABLED #if CONFIG_SECURE_BOOT_V2_ENABLED
static const char* TAG = "secure_boot_v2"; static const char* TAG = "secure_boot_v2";
@ -45,7 +45,7 @@ esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
return ESP_FAIL; return ESP_FAIL;
} }
err = esp_secure_boot_verify_rsa_signature_block(sig_block, digest, verified_digest); err = esp_secure_boot_verify_sbv2_signature_block(sig_block, digest, verified_digest);
if (err != ESP_OK) { if (err != ESP_OK) {
ESP_LOGE(TAG, "Secure Boot V2 verification failed."); ESP_LOGE(TAG, "Secure Boot V2 verification failed.");
} }
@ -83,7 +83,7 @@ static esp_err_t get_secure_boot_key_digests(esp_image_sig_public_key_digests_t
if (err == ESP_OK) { if (err == ESP_OK) {
for (unsigned i = 0; i < SECURE_BOOT_NUM_BLOCKS; i++) { for (unsigned i = 0; i < SECURE_BOOT_NUM_BLOCKS; i++) {
if (trusted_keys.key_digests[i] != NULL) { 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); memcpy(public_key_digests->key_digests[i], (uint8_t *)trusted_keys.key_digests[i], ESP_SECURE_BOOT_KEY_DIGEST_LEN);
public_key_digests->num_digests++; public_key_digests->num_digests++;
} }
} }
@ -101,7 +101,7 @@ static esp_err_t get_secure_boot_key_digests(esp_image_sig_public_key_digests_t
// if CONFIG_SECURE_BOOT_V2_ENABLED==y and key digests from eFuse are missing, then it is the first boot, // 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. // 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_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_image_sig_public_key_digests_t trusted = {0}; esp_image_sig_public_key_digests_t trusted = {0};
bool efuse_keys_are_not_set = false; bool efuse_keys_are_not_set = false;
@ -125,7 +125,11 @@ esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signa
// if efuse key digests are not in eFuse yet due to it is the first boot // 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(). // 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_handle_t sig_block_sha = bootloader_sha256_start();
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
bootloader_sha256_data(sig_block_sha, &sig_block->block[i].key, sizeof(sig_block->block[i].key)); bootloader_sha256_data(sig_block_sha, &sig_block->block[i].key, sizeof(sig_block->block[i].key));
#elif CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
bootloader_sha256_data(sig_block_sha, &sig_block->block[i].ecdsa.key, sizeof(sig_block->block[i].ecdsa.key));
#endif
bootloader_sha256_finish(sig_block_sha, trusted.key_digests[i]); bootloader_sha256_finish(sig_block_sha, trusted.key_digests[i]);
} }
} }
@ -133,19 +137,27 @@ esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signa
ESP_FAULT_ASSERT(!esp_secure_boot_enabled()); ESP_FAULT_ASSERT(!esp_secure_boot_enabled());
} }
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
ESP_LOGI(TAG, "Verifying with RSA-PSS..."); ESP_LOGI(TAG, "Verifying with RSA-PSS...");
#if SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS == 1 #else
ESP_LOGI(TAG, "Verifying with ECDSA...");
#endif
#if CONFIG_IDF_TARGET_ESP32
int sb_result = ets_secure_boot_verify_signature(sig_block, image_digest, trusted.key_digests[0], verified_digest); int sb_result = ets_secure_boot_verify_signature(sig_block, image_digest, trusted.key_digests[0], verified_digest);
#else #else
ets_secure_boot_key_digests_t trusted_key_digests = {0}; ets_secure_boot_key_digests_t trusted_key_digests = {0};
for (unsigned i = 0; i < SECURE_BOOT_NUM_BLOCKS; i++) { for (unsigned i = 0; i < SECURE_BOOT_NUM_BLOCKS; i++) {
trusted_key_digests.key_digests[i] = &trusted.key_digests[i]; trusted_key_digests.key_digests[i] = &trusted.key_digests[i];
} }
// Key revocation happens in ROM bootloader. // Key revocation happens in ROM bootloader.
// Do NOT allow key revocation while verifying application // Do NOT allow key revocation while verifying application
trusted_key_digests.allow_key_revoke = false; trusted_key_digests.allow_key_revoke = false;
int sb_result = ets_secure_boot_verify_signature(sig_block, image_digest, &trusted_key_digests, verified_digest); int sb_result = ets_secure_boot_verify_signature(sig_block, image_digest, &trusted_key_digests, verified_digest);
#endif #endif // CONFIG_IDF_TARGET_ESP32
if (sb_result != SB_SUCCESS) { if (sb_result != SB_SUCCESS) {
ESP_LOGE(TAG, "Secure Boot V2 verification failed."); ESP_LOGE(TAG, "Secure Boot V2 verification failed.");
return ESP_ERR_IMAGE_INVALID; return ESP_ERR_IMAGE_INVALID;
@ -154,4 +166,13 @@ esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signa
return ESP_OK; return ESP_OK;
} }
} }
#endif // CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME && CONFIG_SECURE_BOOT_V2_ENABLED
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
// To maintain backward compatibility
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)
{
return esp_secure_boot_verify_sbv2_signature_block(sig_block, image_digest, verified_digest);
}
#endif
#endif // CONFIG_SECURE_BOOT_V2_ENABLED

View File

@ -24,6 +24,7 @@ typedef enum {
EFUSE_BLK3 = 3, /**< Number of eFuse BLOCK3. KEY0. whole block */ EFUSE_BLK3 = 3, /**< Number of eFuse BLOCK3. KEY0. whole block */
EFUSE_BLK_KEY0 = 3, /**< Number of eFuse BLOCK3. KEY0. whole block */ EFUSE_BLK_KEY0 = 3, /**< Number of eFuse BLOCK3. KEY0. whole block */
EFUSE_BLK_SECURE_BOOT = 3,
EFUSE_BLK_KEY_MAX = 4, EFUSE_BLK_KEY_MAX = 4,
EFUSE_BLK_MAX = 4, /**< Number of eFuse blocks */ EFUSE_BLK_MAX = 4, /**< Number of eFuse blocks */

View File

@ -0,0 +1,24 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
ECDSA_CURVE_P192 = 1,
ECDSA_CURVE_P256 = 2
} 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);
#ifdef __cplusplus
}
#endif

View File

@ -10,6 +10,7 @@
#include <stdbool.h> #include <stdbool.h>
#include "ets_sys.h" #include "ets_sys.h"
#include "rsa_pss.h" #include "rsa_pss.h"
#include "ecdsa.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -77,19 +78,25 @@ void ets_secure_boot_revoke_public_key_digest(int index);
#define SIG_BLOCK_PADDING 4096 #define SIG_BLOCK_PADDING 4096
#define ETS_SECURE_BOOT_V2_SIGNATURE_MAGIC 0xE7 #define ETS_SECURE_BOOT_V2_SIGNATURE_MAGIC 0xE7
/* Secure Boot V2 signature block /* Secure Boot V2 signature block (extended to support ECDSA)
(Up to 3 in a signature sector are appended to the image) (Up to 3 in a signature sector are appended to the image)
*/ */
struct 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;
uint8_t _reserved1; uint8_t _reserved1;
uint8_t _reserved2; uint8_t _reserved2;
uint8_t image_digest[32]; uint8_t image_digest[32];
ets_rsa_pubkey_t key; struct {
uint8_t signature[384]; struct {
uint32_t block_crc; uint8_t curve_id; /* ETS_ECDSA_CURVE_P192 / ETS_ECDSA_CURVE_P256 */
uint8_t point[64]; /* X followed by Y (both little-endian), plus zero bytes if P192 */
} key;
uint8_t signature[64]; /* r followed by s (both little-endian) */
uint8_t padding[1031];
} ecdsa;
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];
}; };

View File

@ -40,7 +40,7 @@ if(NOT CONFIG_SECURE_BOOT_ALLOW_SHORT_APP_PARTITION AND
NOT BOOTLOADER_BUILD) NOT BOOTLOADER_BUILD)
if(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME) if(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME)
list(APPEND esptool_elf2image_args --secure-pad) list(APPEND esptool_elf2image_args --secure-pad)
elseif(CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME) elseif(CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME OR CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME)
list(APPEND esptool_elf2image_args --secure-pad-v2) list(APPEND esptool_elf2image_args --secure-pad-v2)
endif() endif()
endif() endif()
@ -110,7 +110,7 @@ endif()
if(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME) if(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME)
set(secure_boot_version "1") set(secure_boot_version "1")
elseif(CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME) elseif(CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME OR CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME)
set(secure_boot_version "2") set(secure_boot_version "2")
endif() endif()

View File

@ -95,7 +95,7 @@ if(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME)
"\t${espsecurepy} sign_data --keyfile KEYFILE ${build_dir}/partition_table/${final_partition_bin}" "\t${espsecurepy} sign_data --keyfile KEYFILE ${build_dir}/partition_table/${final_partition_bin}"
VERBATIM) VERBATIM)
endif() endif()
elseif(CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME) elseif(CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME OR CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME)
add_custom_command(TARGET partition-table POST_BUILD add_custom_command(TARGET partition-table POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo "Partition table built:" COMMAND ${CMAKE_COMMAND} -E echo "Partition table built:"
VERBATIM) VERBATIM)

View File

@ -3,15 +3,19 @@
Secure Boot V2 Secure Boot V2
============== ==============
{IDF_TARGET_SBV2_SCHEME:default="RSA-PSS", esp32c2="ECDSA"}
{IDF_TARGET_SBV2_KEY:default="RSA-3072", esp32c2="ECDSA-256 or ECDSA-192"}
.. important:: .. important::
This document is about Secure Boot V2, supported on the following chips: ESP32 (ECO3 onwards), ESP32-S2, ESP32-S3 and ESP32-C3 (ECO3 onwards). Except for ESP32, it is the only supported Secure Boot scheme. This document is about Secure Boot V2, supported on the following chips: ESP32 (ECO3 onwards), ESP32-S2, ESP32-S3, ESP32-C3 (ECO3 onwards), and ESP32-C2. Except for ESP32, it is the only supported Secure Boot scheme.
.. only:: esp32 .. only:: esp32
For ESP32 before ECO3, refer to :doc:`Secure Boot <secure-boot-v1>`. It is recommended that users use Secure Boot V2 if they have a chip version that supports it. Secure Boot V2 is safer and more flexible than Secure Boot V1. For ESP32 before ECO3, refer to :doc:`Secure Boot <secure-boot-v1>`. It is recommended that users use Secure Boot V2 if they have a chip version that supports it. Secure Boot V2 is safer and more flexible than Secure Boot V1.
Secure Boot V2 uses RSA based app and bootloader verification. This document can also be used as a reference for signing apps using the RSA scheme without signing the bootloader. Secure Boot V2 uses {IDF_TARGET_SBV2_SCHEME} based app and bootloader verification. This document can also be used as a reference for signing apps using the {IDF_TARGET_SBV2_SCHEME} scheme without signing the bootloader.
.. only:: esp32 .. only:: esp32
@ -27,18 +31,26 @@ Background
Secure Boot protects a device from running any unauthorized (i.e., unsigned) code by checking that each piece of software that is being booted is signed. On an {IDF_TARGET_NAME}, these pieces of software include the second stage bootloader and each application binary. Note that the first stage bootloader does not require signing as it is ROM code thus cannot be changed. Secure Boot protects a device from running any unauthorized (i.e., unsigned) code by checking that each piece of software that is being booted is signed. On an {IDF_TARGET_NAME}, these pieces of software include the second stage bootloader and each application binary. Note that the first stage bootloader does not require signing as it is ROM code thus cannot be changed.
A new RSA based Secure Boot verification scheme (Secure Boot V2) has been introduced on the ESP32 (ECO3 onwards), ESP32-S2, ESP32-S3 and ESP32-C3 (ECO3 onwards). .. only:: not esp32c2
A new RSA based Secure Boot verification scheme (Secure Boot V2) has been introduced on the ESP32 (ECO3 onwards), ESP32-S2, ESP32-S3 and ESP32-C3 (ECO3 onwards).
.. only:: esp32c2
A new ECC based Secure Boot verification scheme (Secure Boot V2) has been introduced on the ESP32-C2.
The Secure Boot process on the {IDF_TARGET_NAME} involves the following steps: The Secure Boot process on the {IDF_TARGET_NAME} involves the following steps:
1. When the first stage bootloader loads the second stage bootloader, the second stage bootloader's RSA-PSS signature is verified. If the verification is successful, the second stage bootloader is executed.
2. When the second stage bootloader loads a particular application image, the application's RSA-PSS signature is verified. If the verification is successful, the application image is executed. 1. When the first stage bootloader loads the second stage bootloader, the second stage bootloader's {IDF_TARGET_SBV2_SCHEME} signature is verified. If the verification is successful, the second stage bootloader is executed.
2. When the second stage bootloader loads a particular application image, the application's {IDF_TARGET_SBV2_SCHEME} signature is verified. If the verification is successful, the application image is executed.
Advantages Advantages
---------- ----------
- The RSA public key is stored on the device. The corresponding RSA private key is kept at a secret place and is never accessed by the device. - The {IDF_TARGET_SBV2_SCHEME} public key is stored on the device. The corresponding {IDF_TARGET_SBV2_SCHEME} private key is kept at a secret place and is never accessed by the device.
.. only:: esp32 .. only:: esp32 or esp32c2
- Only one public key can be generated and stored in the chip during manufacturing. - Only one public key can be generated and stored in the chip during manufacturing.
@ -66,11 +78,15 @@ Secure Boot V2 verifies the bootloader image and application binary images using
Only one signature block can be appended to the bootloader or application image in ESP32 ECO3. Only one signature block can be appended to the bootloader or application image in ESP32 ECO3.
.. only:: esp32c2
Only one signature block can be appended to the bootloader or application image in {IDF_TARGET_NAME}
.. only:: esp32s2 or esp32c3 or esp32s3 .. only:: esp32s2 or esp32c3 or esp32s3
Up to 3 signature blocks can be appended to the bootloader or application image in {IDF_TARGET_NAME}. Up to 3 signature blocks can be appended to the bootloader or application image in {IDF_TARGET_NAME}.
Each signature block contains a signature of the preceding image as well as the corresponding RSA-3072 public key. For more details about the format, refer to :ref:`signature-block-format`. A digest of the RSA-3072 public key is stored in the eFuse. Each signature block contains a signature of the preceding image as well as the corresponding {IDF_TARGET_SBV2_KEY} public key. For more details about the format, refer to :ref:`signature-block-format`. A digest of the {IDF_TARGET_SBV2_KEY} public key is stored in the eFuse.
The application image is not only verified on every boot but also on each over the air (OTA) update. If the currently selected OTA app image cannot be verified, the bootloader will fall back and look for another correctly signed application image. The application image is not only verified on every boot but also on each over the air (OTA) update. If the currently selected OTA app image cannot be verified, the bootloader will fall back and look for another correctly signed application image.
@ -99,50 +115,92 @@ The bootloader and application images are padded to the next 4096 byte boundary,
The content of each signature block is shown in the following table: The content of each signature block is shown in the following table:
.. list-table:: Content of a Signature Block .. only:: not esp32c2
:widths: 10 10 40
:header-rows: 1
* - **Offset** .. list-table:: Content of a Signature Block
- **Size (bytes)** :widths: 10 10 40
- **Description** :header-rows: 1
* - 0
- 1 * - **Offset**
- Magic byte - **Size (bytes)**
* - 1 - **Description**
- 1 * - 0
- Version number byte (currently 0x02), 0x01 is for Secure Boot V1. - 1
* - 2 - Magic byte
- 2 * - 1
- Padding bytes, Reserved. Should be zero. - 1
* - 4 - Version number byte (currently 0x02), 0x01 is for Secure Boot V1.
- 32 * - 2
- SHA-256 hash of only the image content, not including the signature block. - 2
* - 36 - Padding bytes, Reserved. Should be zero.
- 384 * - 4
- RSA Public Modulus used for signature verification. (value n in RFC8017). - 32
* - 420 - SHA-256 hash of only the image content, not including the signature block.
- 4 * - 36
- RSA Public Exponent used for signature verification (value e in RFC8017). - 384
* - 424 - RSA Public Modulus used for signature verification. (value n in RFC8017).
- 384 * - 420
- Pre-calculated R, derived from n. - 4
* - 808 - RSA Public Exponent used for signature verification (value e in RFC8017).
- 4 * - 424
- Pre-calculated M, derived from n - 384
* - 812 - Pre-calculated R, derived from n.
- 384 * - 808
- RSA-PSS Signature result (section 8.1.1 of RFC8017) of image content, computed using following PSS parameters: SHA256 hash, MFG1 function, salt length 32 bytes, default trailer field (0xBC). - 4
* - 1196 - Pre-calculated M, derived from n
- 4 * - 812
- CRC32 of the preceding 1095 bytes. - 384
* - 1200 - RSA-PSS Signature result (section 8.1.1 of RFC8017) of image content, computed using following PSS parameters: SHA256 hash, MFG1 function, salt length 32 bytes, default trailer field (0xBC).
- 16 * - 1196
- Zero padding to length 1216 bytes. - 4
- CRC32 of the preceding 1095 bytes.
* - 1200
- 16
- Zero padding to length 1216 bytes.
.. note:: .. note::
R and M' are used for hardware-assisted Montgomery Multiplication. R and M' are used for hardware-assisted Montgomery Multiplication.
.. only:: esp32c2
.. list-table:: Content of a Signature Block
:widths: 10 10 40
:header-rows: 1
* - **Offset**
- **Size (bytes)**
- **Description**
* - 0
- 1
- Magic byte.
* - 1
- 1
- Version number byte (currently 0x03).
* - 2
- 2
- Padding bytes, Reserved. Should be zero.
* - 4
- 32
- SHA-256 hash of only the image content, not including the signature block.
* - 36
- 1
- Curve ID (1 for NIST192p curve. 2 for NIST256p curve).
* - 37
- 64
- ECDSA Public key: 32 byte X coordinate followed by 32 byte Y coordinate.
* - 101
- 64
- ECDSA Signature result (section 5.3.2 of RFC6090) of the image content: 32 byte R component followed by 32 byte S component.
* - 165
- 1031
- Reserved.
* - 1196
- 4
- CRC32 of the preceding 1095 bytes.
* - 1200
- 16
- Zero padding to length 1216 bytes.
The remainder of the signature sector is erased flash (0xFF) which allows writing other signature blocks after previous signature block. The remainder of the signature sector is erased flash (0xFF) which allows writing other signature blocks after previous signature block.
@ -164,7 +222,15 @@ An image is “verified” if the public key stored in any signature block is va
2. Generate the application image digest and match it with the image digest in the signature block. If the digests don't match, the verification fails. 2. Generate the application image digest and match it with the image digest in the signature block. If the digests don't match, the verification fails.
3. Use the public key to verify the signature of the bootloader image, using RSA-PSS (section 8.1.2 of RFC8017) with the image digest calculated in step (2) for comparison. .. only:: not esp32c2
3. Use the public key to verify the signature of the bootloader image, using RSA-PSS (section 8.1.2 of RFC8017) with the image digest calculated in step (2) for comparison.
.. only:: esp32c2
3. Use the public key to verify the signature of the bootloader image, using ECDSA signature verification (section 5.3.3 of RFC6090) with the image digest calculated in step (2) for comparison.
Bootloader Size Bootloader Size
--------------- ---------------
@ -261,15 +327,39 @@ Restrictions after Secure Boot is enabled
Generating Secure Boot Signing Key Generating Secure Boot Signing Key
---------------------------------- ----------------------------------
The build system will prompt you with a command to generate a new signing key via ``espsecure.py generate_signing_key``. The --version 2 parameter will generate the RSA 3072 private key for Secure Boot V2. The build system will prompt you with a command to generate a new signing key via ``espsecure.py generate_signing_key``.
The strength of the signing key is proportional to (a) the random number source of the system, and (b) the correctness of the algorithm used. For production devices, we recommend generating signing keys from a system with a quality entropy source, and using the best available RSA key generation utilities. .. only:: not esp32c2
The ``--version 2`` parameter will generate the RSA 3072 private key for Secure Boot V2.
.. only:: esp32c2
Select the ECDSA scheme by passing ``--version 2 --scheme ecdsa256`` or ``--version 2 --scheme ecdsa192`` to generate corresponding ECDSA private key
The strength of the signing key is proportional to (a) the random number source of the system, and (b) the correctness of the algorithm used. For production devices, we recommend generating signing keys from a system with a quality entropy source, and using the best available {IDF_TARGET_SBV2_SCHEME} key generation utilities.
For example, to generate a signing key using the openssl command line: For example, to generate a signing key using the openssl command line:
``` .. only:: not esp32c2
openssl genrsa -out my_secure_boot_signing_key.pem 3072
``` ```
openssl genrsa -out my_secure_boot_signing_key.pem 3072
```
.. only:: esp32c2
For NIST192p curve
```
openssl ecparam -name prime192v1 -genkey -noout -out my_secure_boot_signing_key.pem
```
For NIST256p curve
```
openssl ecparam -name prime256v1 -genkey -noout -out my_secure_boot_signing_key.pem
```
Remember that the strength of the Secure Boot system depends on keeping the signing key private. Remember that the strength of the Secure Boot system depends on keeping the signing key private.
@ -374,7 +464,7 @@ To sign a binary image::
espsecure.py sign_data --version 2 --keyfile ./my_signing_key.pem --output ./image_signed.bin image-unsigned.bin espsecure.py sign_data --version 2 --keyfile ./my_signing_key.pem --output ./image_signed.bin image-unsigned.bin
Keyfile is the PEM file containing an RSA-3072 private signing key. Keyfile is the PEM file containing an {IDF_TARGET_SBV2_KEY} private signing key.
.. _secure-boot-v2-and-flash-encr: .. _secure-boot-v2-and-flash-encr:
@ -415,10 +505,15 @@ How To Enable Signed App Verification
2. Ensure `App Signing Scheme` is `RSA`. For ESP32 ECO3 chip, select :ref:`CONFIG_ESP32_REV_MIN` to `Rev 3` to get `RSA` option available 2. Ensure `App Signing Scheme` is `RSA`. For ESP32 ECO3 chip, select :ref:`CONFIG_ESP32_REV_MIN` to `Rev 3` to get `RSA` option available
.. only:: not esp32 .. only:: not esp32 and not esp32c2
2. Ensure `App Signing Scheme` is `RSA` 2. Ensure `App Signing Scheme` is `RSA`
.. only:: esp32c2
2. Ensure `App Signing Scheme` is `ECDSA (V2)`
3. Enable :ref:`CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT` 3. Enable :ref:`CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT`
4. By default, "Sign binaries during build" will be enabled on selecting "Require signed app images" option, which will sign binary files as a part of build process. The file named in "Secure boot private signing key" will be used to sign the image. 4. By default, "Sign binaries during build" will be enabled on selecting "Require signed app images" option, which will sign binary files as a part of build process. The file named in "Secure boot private signing key" will be used to sign the image.