Skip to content

Commit 22adc7e

Browse files
committed
Merge branch 'feat/secure_boot_ecdsa_p384' into 'master'
Support Secure Boot using ECDSA-P384 curve Closes IDF-10016, IDF-10221, and IDF-12990 See merge request espressif/esp-idf!38517
2 parents 1f82b34 + b615ab5 commit 22adc7e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+1031
-271
lines changed

components/bootloader/Kconfig.projbuild

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -559,12 +559,13 @@ menu "Security features"
559559
depends on SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
560560
default SECURE_BOOT_ECDSA_KEY_LEN_256_BITS
561561
help
562-
Select the ECDSA key size. Two key sizes are supported
562+
Select the ECDSA key size. Three key sizes are supported depending upon on the target:
563563

564564
- 192 bit key using NISTP192 curve
565565
- 256 bit key using NISTP256 curve (Recommended)
566+
- 384 bit key using NISTP384 curve (Recommended)
566567

567-
The advantage of using 256 bit key is the extra randomness which makes it difficult to be
568+
The advantage of using 384 and 256 bit keys is the extra randomness which makes it difficult to be
568569
bruteforced compared to 192 bit key.
569570
At present, both key sizes are practically implausible to bruteforce.
570571

@@ -576,6 +577,10 @@ menu "Security features"
576577
bool "Using ECC curve NISTP256 (Recommended)"
577578
depends on SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
578579

580+
config SECURE_BOOT_ECDSA_KEY_LEN_384_BITS
581+
bool "Using ECC curve NISTP384 (Recommended)"
582+
depends on SECURE_SIGNED_APPS_ECDSA_V2_SCHEME && SOC_ECDSA_SUPPORT_CURVE_P384
583+
579584
endchoice
580585

581586
config SECURE_SIGNED_ON_BOOT_NO_SECURE_BOOT

components/bootloader/project_include.cmake

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ if(CONFIG_SECURE_SIGNED_APPS)
7070
set(scheme "ecdsa192")
7171
elseif(CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_256_BITS)
7272
set(scheme "ecdsa256")
73+
elseif(CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS)
74+
set(scheme "ecdsa384")
7375
endif()
7476
fail_at_build_time(gen_secure_boot_signing_key
7577
"Secure Boot Signing Key ${CONFIG_SECURE_BOOT_SIGNING_KEY} does not exist. Generate using:"

components/bootloader_support/include/esp_secure_boot.h

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
#if !CONFIG_IDF_TARGET_LINUX
1818
#include "rom/secure_boot.h"
1919
#endif
20-
2120
#ifdef CONFIG_SECURE_BOOT_V1_ENABLED
2221
#if !defined(CONFIG_SECURE_SIGNED_ON_BOOT) || !defined(CONFIG_SECURE_SIGNED_ON_UPDATE) || !defined(CONFIG_SECURE_SIGNED_APPS)
2322
#error "internal sdkconfig error, secure boot should always enable all signature options"
@@ -33,12 +32,20 @@ extern "C" {
3332
Can be compiled as part of app or bootloader code.
3433
*/
3534

35+
#if CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS
36+
#define ESP_SECURE_BOOT_DIGEST_LEN 48
37+
#else /* !CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS */
3638
#define ESP_SECURE_BOOT_DIGEST_LEN 32
39+
#endif /* CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS */
40+
41+
/* SHA-256 length of the public key digest */
42+
#define ESP_SECURE_BOOT_KEY_DIGEST_SHA_256_LEN 32
3743

44+
/* Length of the public key digest that is stored in efuses */
3845
#if CONFIG_IDF_TARGET_ESP32C2
39-
#define ESP_SECURE_BOOT_KEY_DIGEST_LEN 16
46+
#define ESP_SECURE_BOOT_KEY_DIGEST_LEN ESP_SECURE_BOOT_KEY_DIGEST_SHA_256_LEN / 2
4047
#else
41-
#define ESP_SECURE_BOOT_KEY_DIGEST_LEN 32
48+
#define ESP_SECURE_BOOT_KEY_DIGEST_LEN ESP_SECURE_BOOT_KEY_DIGEST_SHA_256_LEN
4249
#endif
4350

4451
#ifdef CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH
@@ -193,7 +200,8 @@ esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *imag
193200
/** @brief Verify the secure boot signature appended to some binary data in flash.
194201
*
195202
* For ECDSA Scheme (Secure Boot V1) - deterministic ECDSA w/ SHA256 image
196-
* For RSA Scheme (Secure Boot V2) - RSA-PSS Verification of the SHA-256 image
203+
* For RSA Scheme (Secure Boot V2) - RSA-PSS Verification of the SHA-256 image digest
204+
* For ECDSA Scheme (Secure Boot V2) - ECDSA Verification of the SHA-256 / SHA-384 (in case of ECDSA-P384 secure boot key) image digest
197205
*
198206
* Public key is compiled into the calling program in the ECDSA Scheme.
199207
* See the apt docs/security/secure-boot-v1.rst or docs/security/secure-boot-v2.rst for details.
@@ -236,13 +244,13 @@ esp_err_t esp_secure_boot_verify_ecdsa_signature_block(const esp_secure_boot_sig
236244

237245
/** @brief Verify the secure boot signature block for Secure Boot V2.
238246
*
239-
* Performs RSA-PSS or ECDSA verification of the SHA-256 image based on the public key
247+
* Performs RSA-PSS or ECDSA verification of the SHA-256 / SHA-384 image based on the public key
240248
* in the signature block, compared against the public key digest stored in efuse.
241249
*
242250
* Similar to esp_secure_boot_verify_signature(), but can be used when the digest is precalculated.
243251
* @param[in] sig_block Pointer to signature block data
244-
* @param[in] image_digest Pointer to 32 byte buffer holding SHA-256 hash.
245-
* @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.)
252+
* @param[in] image_digest Pointer to 32/48 byte buffer holding SHA-256/SHA-384 hash.
253+
* @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.)
246254
*
247255
*/
248256
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);
@@ -255,7 +263,7 @@ esp_err_t esp_secure_boot_verify_sbv2_signature_block(const ets_secure_boot_sign
255263
* Each image can have one or more signature blocks (up to SECURE_BOOT_NUM_BLOCKS). Each signature block includes a public key.
256264
*/
257265
typedef struct {
258-
uint8_t key_digests[SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS][ESP_SECURE_BOOT_DIGEST_LEN]; /* SHA of the public key components in the signature block */
266+
uint8_t key_digests[SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS][ESP_SECURE_BOOT_KEY_DIGEST_SHA_256_LEN]; /* SHA of the public key components in the signature block */
259267
unsigned num_digests; /* Number of valid digests, starting at index 0 */
260268
} esp_image_sig_public_key_digests_t;
261269

components/bootloader_support/private_include/bootloader_sha.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -12,22 +12,33 @@
1212
Use mbedTLS APIs or include esp32/sha.h to calculate SHA256 in IDF apps.
1313
*/
1414

15+
#include <stdbool.h>
1516
#include <stdint.h>
1617
#include <stdlib.h>
1718
#include "esp_err.h"
19+
#include "soc/soc_caps.h"
1820

1921
#ifdef __cplusplus
2022
extern "C" {
2123
#endif
2224

2325
typedef void *bootloader_sha256_handle_t;
26+
typedef bootloader_sha256_handle_t bootloader_sha_handle_t;
2427

2528
bootloader_sha256_handle_t bootloader_sha256_start(void);
2629

2730
void bootloader_sha256_data(bootloader_sha256_handle_t handle, const void *data, size_t data_len);
2831

2932
void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest);
3033

34+
#if SOC_SHA_SUPPORT_SHA512
35+
bootloader_sha_handle_t bootloader_sha512_start(bool is384);
36+
37+
void bootloader_sha512_data(bootloader_sha_handle_t handle, const void *data, size_t data_len);
38+
39+
void bootloader_sha512_finish(bootloader_sha_handle_t handle, uint8_t *digest);
40+
#endif /* SOC_SHA_SUPPORT_SHA512 */
41+
3142
#ifdef __cplusplus
3243
}
3344
#endif

components/bootloader_support/private_include/bootloader_utility.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2018-2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2018-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -138,6 +138,20 @@ void bootloader_debug_buffer(const void *buffer, size_t length, const char *labe
138138
*/
139139
esp_err_t bootloader_sha256_flash_contents(uint32_t flash_offset, uint32_t len, uint8_t *digest);
140140

141+
/** @brief Generates the digest of the data between offset & offset+length.
142+
*
143+
* This function should be used when the size of the data is larger than 3.2MB.
144+
* The MMU capacity is 3.2MB (50 pages - 64KB each). This function generates the SHA-384
145+
* of the data in chunks of 3.2MB, considering the MMU capacity.
146+
*
147+
* @param[in] flash_offset Offset of the data in flash.
148+
* @param[in] len Length of data in bytes.
149+
* @param[out] digest Pointer to buffer where the digest is written, if ESP_OK is returned.
150+
*
151+
* @return ESP_OK if secure boot digest is generated successfully.
152+
*/
153+
esp_err_t bootloader_sha384_flash_contents(uint32_t flash_offset, uint32_t len, uint8_t *digest);
154+
141155
#ifdef __cplusplus
142156
}
143157
#endif

components/bootloader_support/src/bootloader_sha.c

Lines changed: 66 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,19 +29,36 @@ bootloader_sha256_handle_t bootloader_sha256_start()
2929
void bootloader_sha256_data(bootloader_sha256_handle_t handle, const void *data, size_t data_len)
3030
{
3131
assert(handle != NULL);
32+
ets_sha_update(&ctx, data, data_len, false);
33+
}
3234

33-
#if !SOC_SECURE_BOOT_V2_ECC
34-
/* For secure boot, the key field consists of 1 byte of curve identifier and 64 bytes of ECDSA public key.
35-
* While verifying the signature block, we need to calculate the SHA of this key field which is of 65 bytes.
36-
* ets_sha_update handles it cleanly so we can safely remove the check:
37-
*/
38-
assert(data_len % 4 == 0);
39-
#endif /* SOC_SECURE_BOOT_V2_ECC */
35+
void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest)
36+
{
37+
assert(handle != NULL);
38+
39+
if (digest == NULL) {
40+
bzero(&ctx, sizeof(ctx));
41+
return;
42+
}
43+
ets_sha_finish(&ctx, digest);
44+
}
45+
46+
#if SOC_SHA_SUPPORT_SHA512
47+
bootloader_sha_handle_t bootloader_sha512_start(bool is384)
48+
{
49+
// Enable SHA hardware
50+
ets_sha_enable();
51+
ets_sha_init(&ctx, is384 ? SHA2_384 : SHA2_512);
52+
return &ctx; // Meaningless non-NULL value
53+
}
4054

55+
void bootloader_sha512_data(bootloader_sha_handle_t handle, const void *data, size_t data_len)
56+
{
57+
assert(handle != NULL);
4158
ets_sha_update(&ctx, data, data_len, false);
4259
}
4360

44-
void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest)
61+
void bootloader_sha512_finish(bootloader_sha_handle_t handle, uint8_t *digest)
4562
{
4663
assert(handle != NULL);
4764

@@ -51,6 +68,7 @@ void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest
5168
}
5269
ets_sha_finish(&ctx, digest);
5370
}
71+
#endif /* SOC_SHA_SUPPORT_SHA512 */
5472
#else /* !CONFIG_IDF_TARGET_ESP32 */
5573

5674
#include "soc/dport_reg.h"
@@ -162,6 +180,7 @@ void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest
162180

163181
#include "bootloader_flash_priv.h"
164182
#include <mbedtls/sha256.h>
183+
#include <mbedtls/sha512.h>
165184

166185
bootloader_sha256_handle_t bootloader_sha256_start(void)
167186
{
@@ -199,4 +218,43 @@ void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest
199218
free(handle);
200219
handle = NULL;
201220
}
221+
222+
#if SOC_SHA_SUPPORT_SHA512
223+
bootloader_sha_handle_t bootloader_sha512_start(bool is384)
224+
{
225+
mbedtls_sha512_context *ctx = (mbedtls_sha512_context *)malloc(sizeof(mbedtls_sha512_context));
226+
if (!ctx) {
227+
return NULL;
228+
}
229+
mbedtls_sha512_init(ctx);
230+
int ret = mbedtls_sha512_starts(ctx, is384);
231+
if (ret != 0) {
232+
return NULL;
233+
}
234+
return ctx;
235+
}
236+
237+
void bootloader_sha512_data(bootloader_sha_handle_t handle, const void *data, size_t data_len)
238+
{
239+
assert(handle != NULL);
240+
mbedtls_sha512_context *ctx = (mbedtls_sha512_context *)handle;
241+
int ret = mbedtls_sha512_update(ctx, data, data_len);
242+
assert(ret == 0);
243+
(void)ret;
244+
}
245+
246+
void bootloader_sha512_finish(bootloader_sha_handle_t handle, uint8_t *digest)
247+
{
248+
assert(handle != NULL);
249+
mbedtls_sha512_context *ctx = (mbedtls_sha512_context *)handle;
250+
if (digest != NULL) {
251+
int ret = mbedtls_sha512_finish(ctx, digest);
252+
assert(ret == 0);
253+
(void)ret;
254+
}
255+
mbedtls_sha512_free(ctx);
256+
free(handle);
257+
handle = NULL;
258+
}
259+
#endif /* SOC_SHA_SUPPORT_SHA512 */
202260
#endif /* !(NON_OS_BUILD || CONFIG_APP_BUILD_TYPE_RAM) */

components/bootloader_support/src/bootloader_utility.c

Lines changed: 64 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2018-2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2018-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -30,6 +30,7 @@
3030
#include "hal/cache_types.h"
3131
#include "hal/cache_ll.h"
3232
#include "hal/cache_hal.h"
33+
#include "hal/sha_types.h"
3334

3435
#include "esp_cpu.h"
3536
#include "esp_image_format.h"
@@ -1213,18 +1214,29 @@ void bootloader_debug_buffer(const void *buffer, size_t length, const char *labe
12131214
#endif
12141215
}
12151216

1216-
esp_err_t bootloader_sha256_flash_contents(uint32_t flash_offset, uint32_t len, uint8_t *digest)
1217+
static esp_err_t bootloader_sha_flash_contents(esp_sha_type type, uint32_t flash_offset, uint32_t len, uint8_t *digest)
12171218
{
1218-
12191219
if (digest == NULL) {
12201220
return ESP_ERR_INVALID_ARG;
12211221
}
12221222

12231223
/* Handling firmware images larger than MMU capacity */
12241224
uint32_t mmu_free_pages_count = bootloader_mmap_get_free_pages();
1225-
bootloader_sha256_handle_t sha_handle = NULL;
1225+
bootloader_sha_handle_t sha_handle = NULL;
1226+
1227+
if (type == SHA2_256) {
1228+
sha_handle = bootloader_sha256_start();
1229+
} else
1230+
// Using SOC_ECDSA_SUPPORT_CURVE_P384 here so that there is no flash size impact in the case of existing targets like ESP32.
1231+
#if SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384
1232+
if (type == SHA2_384) {
1233+
sha_handle = bootloader_sha512_start(true);
1234+
} else
1235+
#endif /* SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384 */
1236+
{
1237+
return ESP_ERR_INVALID_ARG;
1238+
}
12261239

1227-
sha_handle = bootloader_sha256_start();
12281240
if (sha_handle == NULL) {
12291241
return ESP_ERR_NO_MEM;
12301242
}
@@ -1234,7 +1246,14 @@ esp_err_t bootloader_sha256_flash_contents(uint32_t flash_offset, uint32_t len,
12341246
uint32_t max_pages = (mmu_free_pages_count > mmu_page_offset) ? (mmu_free_pages_count - mmu_page_offset) : 0;
12351247
if (max_pages == 0) {
12361248
ESP_LOGE(TAG, "No free MMU pages are available");
1237-
bootloader_sha256_finish(sha_handle, NULL);
1249+
if (type == SHA2_256) {
1250+
bootloader_sha256_finish(sha_handle, NULL);
1251+
}
1252+
#if SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384
1253+
else if (type == SHA2_384) {
1254+
bootloader_sha512_finish(sha_handle, NULL);
1255+
}
1256+
#endif /* SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384 */
12381257
return ESP_ERR_NO_MEM;
12391258
}
12401259
uint32_t max_image_len;
@@ -1245,15 +1264,51 @@ esp_err_t bootloader_sha256_flash_contents(uint32_t flash_offset, uint32_t len,
12451264

12461265
const void * image = bootloader_mmap(flash_offset, partial_image_len);
12471266
if (image == NULL) {
1248-
bootloader_sha256_finish(sha_handle, NULL);
1267+
if (type == SHA2_256) {
1268+
bootloader_sha256_finish(sha_handle, NULL);
1269+
}
1270+
#if SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384
1271+
else if (type == SHA2_384) {
1272+
bootloader_sha512_finish(sha_handle, NULL);
1273+
}
1274+
#endif /* SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384 */
12491275
return ESP_FAIL;
12501276
}
1251-
bootloader_sha256_data(sha_handle, image, partial_image_len);
1277+
1278+
if (type == SHA2_256) {
1279+
bootloader_sha256_data(sha_handle, image, partial_image_len);
1280+
}
1281+
#if SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384
1282+
else if (type == SHA2_384) {
1283+
bootloader_sha512_data(sha_handle, image, partial_image_len);
1284+
}
1285+
#endif /* SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384 */
1286+
12521287
bootloader_munmap(image);
12531288

12541289
flash_offset += partial_image_len;
12551290
len -= partial_image_len;
12561291
}
1257-
bootloader_sha256_finish(sha_handle, digest);
1292+
1293+
if (type == SHA2_256) {
1294+
bootloader_sha256_finish(sha_handle, digest);
1295+
}
1296+
#if SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384
1297+
else if (type == SHA2_384) {
1298+
bootloader_sha512_finish(sha_handle, digest);
1299+
}
1300+
#endif /* SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384 */
12581301
return ESP_OK;
12591302
}
1303+
1304+
esp_err_t bootloader_sha256_flash_contents(uint32_t flash_offset, uint32_t len, uint8_t *digest)
1305+
{
1306+
return bootloader_sha_flash_contents(SHA2_256, flash_offset, len, digest);
1307+
}
1308+
1309+
#if SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384
1310+
esp_err_t bootloader_sha384_flash_contents(uint32_t flash_offset, uint32_t len, uint8_t *digest)
1311+
{
1312+
return bootloader_sha_flash_contents(SHA2_384, flash_offset, len, digest);
1313+
}
1314+
#endif /* SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384 */

0 commit comments

Comments
 (0)