esp32c6: Enable ECDSA based secure boot

- Updated documentation for C6
This commit is contained in:
Sachin Parekh 2023-01-09 22:32:19 +05:30
parent a3c341384f
commit 2bb9499a7e
14 changed files with 192 additions and 37 deletions

View File

@ -41,6 +41,8 @@
#include "esp32h4/rom/secure_boot.h"
#elif CONFIG_IDF_TARGET_ESP32C2
#include "esp32c2/rom/secure_boot.h"
#elif CONFIG_IDF_TARGET_ESP32C6
#include "esp32c6/rom/secure_boot.h"
#endif
#define SUB_TYPE_ID(i) (i & 0x0F)

View File

@ -40,6 +40,10 @@ if(BOOTLOADER_BUILD OR CONFIG_APP_BUILD_TYPE_RAM)
"src/${IDF_TARGET}/bootloader_${IDF_TARGET}.c"
)
list(APPEND priv_requires hal)
if(CONFIG_ESP_ROM_REV0_HAS_NO_ECDSA_INTERFACE)
list(APPEND srcs
"src/${IDF_TARGET}/bootloader_ecdsa.c")
endif()
else()
list(APPEND srcs
"src/idf/bootloader_sha.c")

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -29,6 +29,8 @@
#if !CONFIG_IDF_TARGET_ESP32 || CONFIG_ESP32_REV_MIN_FULL >= 300
#if CONFIG_SECURE_BOOT_V2_ENABLED || CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT
/** @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
@ -53,4 +55,6 @@ esp_err_t esp_secure_boot_verify_sbv2_signature_block(const ets_secure_boot_sign
*/
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_SECURE_BOOT_V2_ENABLED || CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT */
#endif

View File

@ -0,0 +1,35 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdbool.h>
#include <string.h>
#include <sys/param.h>
#include "rom/ecdsa.h"
#define ROM_FUNC_TYPECAST int(*)(const uint8_t*, const uint8_t*, int, const uint8_t*, uint8_t*)
extern uint32_t _rom_eco_version;
int (*_rom_ets_ecdsa_verify)(const uint8_t*, const uint8_t*, int, const uint8_t*, uint8_t*);
/* On ESP32-C6 ECO 0, the ROM interface hasn't exposed ets_ecdsa_verify symbol, so for that we have defined
* the function here and then jump to the absolute address in ROM.
*
* There is a possibility of updating the ROM in the future chip revisions without any major upgrades,
* in that case, the same binary should work as is on the new chip revision. For that, we check the _rom_eco_version
* and if its a newer one, we jump to the new ROM interface. These addresses won't change in the future
*
* ets_ecdsa_verify symbol will be present in the upcoming ROM ECO versions so even though we have defined it here,
* linker will pick the symbol address from rom.ld file
*/
int ets_ecdsa_verify(const uint8_t *key, const uint8_t *sig, ECDSA_CURVE curve_id, const uint8_t *image_digest, uint8_t *verified_digest)
{
if (_rom_eco_version == 0) {
_rom_ets_ecdsa_verify = (ROM_FUNC_TYPECAST)0x4001a824;
return _rom_ets_ecdsa_verify(key, sig, curve_id, image_digest, verified_digest);
} else {
_rom_ets_ecdsa_verify = (ROM_FUNC_TYPECAST)0x40001490;
return _rom_ets_ecdsa_verify(key, sig, curve_id, image_digest, verified_digest);
}
}

View File

@ -27,6 +27,8 @@
#include "esp32h4/rom/secure_boot.h"
#elif CONFIG_IDF_TARGET_ESP32C2
#include "esp32c2/rom/secure_boot.h"
#elif CONFIG_IDF_TARGET_ESP32C6
#include "esp32c6/rom/secure_boot.h"
#endif
/* The following API implementations are used only when called

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -17,6 +17,8 @@
#include "esp32h4/rom/secure_boot.h"
#elif CONFIG_IDF_TARGET_ESP32C2
#include "esp32c2/rom/secure_boot.h"
#elif CONFIG_IDF_TARGET_ESP32C6
#include "esp32c6/rom/secure_boot.h"
#endif
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);

View File

@ -120,6 +120,7 @@ if(BOOTLOADER_BUILD)
# The linking of the bootloader needs to use the rom_i2c_writeReg_Mask in esp32c6.rom.phy.ld
rom_linker_script("phy")
rom_linker_script("wdt")
rom_linker_script("version")
elseif(target STREQUAL "esp32h2")
rom_linker_script("newlib")

View File

@ -62,3 +62,7 @@ config ESP_ROM_HAS_REGI2C_BUG
config ESP_ROM_HAS_NEWLIB_NORMAL_FORMAT
bool
default y
config ESP_ROM_REV0_HAS_NO_ECDSA_INTERFACE
bool
default y

View File

@ -21,3 +21,4 @@
#define ESP_ROM_HAS_SPI_FLASH (1) // ROM has the implementation of SPI Flash driver
#define ESP_ROM_HAS_REGI2C_BUG (1) // ROM has the regi2c bug
#define ESP_ROM_HAS_NEWLIB_NORMAL_FORMAT (1) // ROM has the newlib normal/full version of formatting functions (as opposed to the nano versions)
#define ESP_ROM_REV0_HAS_NO_ECDSA_INTERFACE (1) // ECO 0 does not have ets_ecdsa_verify symbol, future revision will have it

View File

@ -0,0 +1,26 @@
/*
* 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
#define ETS_DIGEST_LEN 32 /* SHA-256, bytes */
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

@ -9,6 +9,7 @@
#include <stdint.h>
#include <stdbool.h>
#include "ets_sys.h"
#include "ecdsa.h"
#include "rsa_pss.h"
#include "esp_assert.h"
@ -16,6 +17,8 @@
extern "C" {
#endif
#if CONFIG_SECURE_BOOT_V2_ENABLED || CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT
typedef struct ets_secure_boot_sig_block ets_secure_boot_sig_block_t;
typedef struct ets_secure_boot_signature ets_secure_boot_signature_t;
typedef struct ets_secure_boot_key_digests ets_secure_boot_key_digests_t;
@ -69,6 +72,8 @@ void ets_secure_boot_revoke_public_key_digest(int index);
(Up to 3 in a signature sector are appended to the image)
*/
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
struct ets_secure_boot_sig_block {
uint8_t magic_byte;
uint8_t version;
@ -81,6 +86,27 @@ struct ets_secure_boot_sig_block {
uint8_t _padding[16];
};
#elif CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
struct __attribute((packed)) ets_secure_boot_sig_block {
uint8_t magic_byte;
uint8_t version;
uint8_t _reserved1;
uint8_t _reserved2;
uint8_t image_digest[32];
struct {
struct {
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];
};
#endif
ESP_STATIC_ASSERT(sizeof(ets_secure_boot_sig_block_t) == 1216, "invalid sig block size");
#define SECURE_BOOT_NUM_BLOCKS 3
@ -100,6 +126,8 @@ struct ets_secure_boot_key_digests {
bool allow_key_revoke;
};
#endif /* CONFIG_SECURE_BOOT_V2_ENABLED || CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT */
#ifdef __cplusplus
}
#endif

View File

@ -379,7 +379,6 @@
#define SOC_EFUSE_DIS_DIRECT_BOOT 1
#define SOC_EFUSE_SOFT_DIS_JTAG 1
// TODO: IDF-5357 (Copy from esp32c3, need check)
/*-------------------------- Secure Boot CAPS----------------------------*/
#define SOC_SECURE_BOOT_V2_RSA 1
#define SOC_SECURE_BOOT_V2_ECC 1
@ -387,7 +386,6 @@
#define SOC_EFUSE_REVOKE_BOOT_KEY_DIGESTS 1
#define SOC_SUPPORT_SECURE_BOOT_REVOKE_KEY 1
// TODO: IDF-5358 (Copy from esp32c3, need check)
/*-------------------------- Flash Encryption CAPS----------------------------*/
#define SOC_FLASH_ENCRYPTED_XTS_AES_BLOCK_MAX (32)
#define SOC_FLASH_ENCRYPTION_XTS_AES 1

View File

@ -117,7 +117,3 @@ api-reference/protocols
api-reference/protocols/esp_serial_slave_link
api-reference/protocols/esp_spi_slave_protocol
api-reference/protocols/index
security
security/security
security/secure-boot-v2
security/secure-boot-v1

View File

@ -3,13 +3,25 @@
Secure Boot V2
==============
{IDF_TARGET_SBV2_SCHEME:default="RSA-PSS", esp32c2="ECDSA"}
{IDF_TARGET_SBV2_SCHEME:default="RSA-PSS", esp32c2="ECDSA", esp32c6="RSA-PSS or ECDSA"}
{IDF_TARGET_SBV2_KEY:default="RSA-3072", esp32c2="ECDSA-256 or ECDSA-192"}
{IDF_TARGET_SBV2_KEY:default="RSA-3072", esp32c2="ECDSA-256 or ECDSA-192", esp32c6="RSA-3072, ECDSA-256, or ECDSA-192"}
{IDF_TARGET_SECURE_BOOT_OPTION_TEXT:default="", esp32c6="RSA is recommended because of faster verification time. You can choose between RSA and ECDSA scheme from the menu."}
{IDF_TARGET_ECO_VERSION:default="", esp32="(ECO 3 onwards)", esp32c3="(ECO 3 onwards)"}
{IDF_TARGET_RSA_TIME:default="", esp32c6="~2.7 ms"}
{IDF_TARGET_ECDSA_TIME:default="", esp32c6="~21.5 ms"}
{IDF_TARGET_CPU_FREQ:default="", esp32c6="160 MHz"}
{IDF_TARGET_SBV2_DEFAULT_SCHEME:default="RSA", esp32c2="ECDSA (V2)"}
.. important::
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.
This document is about Secure Boot V2, supported on {IDF_TARGET_NAME} {IDF_TARGET_ECO_VERSION}
.. only:: esp32
@ -17,7 +29,6 @@ Secure Boot V2
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
``Secure Boot V2`` and RSA scheme (``App Signing Scheme``) options are available for ESP32 from ECO3 onwards. To use these options in menuconfig, set :ref:`CONFIG_ESP32_REV_MIN` greater than or equal to `Rev 3`.
@ -31,13 +42,17 @@ 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.
.. only:: SOC_SECURE_BOOT_V2_RSA
.. only:: esp32 or (SOC_SECURE_BOOT_V2_RSA and not SOC_SECURE_BOOT_V2_ECC)
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).
A RSA based Secure Boot verification scheme (Secure Boot V2) is implemented on {IDF_TARGET_NAME} {IDF_TARGET_ECO_VERSION}.
.. only:: SOC_SECURE_BOOT_V2_ECC
.. only:: SOC_SECURE_BOOT_V2_ECC and not SOC_SECURE_BOOT_V2_RSA
A new ECC based Secure Boot verification scheme (Secure Boot V2) has been introduced on the ESP32-C2.
A ECC based Secure Boot verification scheme (Secure Boot V2) has been introduce on {IDF_TARGET_NAME}
.. only:: SOC_SECURE_BOOT_V2_RSA and SOC_SECURE_BOOT_V2_ECC
{IDF_TARGET_NAME} has provision to choose between a {IDF_TARGET_SBV2_SCHEME} based secure boot verification scheme.
The Secure Boot process on the {IDF_TARGET_NAME} involves the following steps:
@ -54,7 +69,7 @@ Advantages
- Only one public key can be generated and stored in the chip during manufacturing.
.. only:: esp32s2 or esp32c3 or esp32s3
.. only:: SOC_EFUSE_REVOKE_BOOT_KEY_DIGESTS
- Up to three public keys can be generated and stored in the chip during manufacturing.
@ -82,7 +97,7 @@ 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 {IDF_TARGET_NAME}
.. only:: esp32s2 or esp32c3 or esp32s3
.. only:: SOC_EFUSE_REVOKE_BOOT_KEY_DIGESTS
Up to 3 signature blocks can be appended to the bootloader or application image in {IDF_TARGET_NAME}.
@ -113,11 +128,37 @@ Signature Block Format
The signature block starts on a 4KB aligned boundary and has a flash sector of its own. The signature is calculated over all bytes in the image including the padding bytes (:ref:`secure_padding`).
.. only:: SOC_SECURE_BOOT_V2_RSA and SOC_SECURE_BOOT_V2_ECC
.. note::
{IDF_TARGET_NAME} has a provision to choose between RSA scheme and ECDSA scheme. Only one scheme can be used per device.
ECDSA provides similar security strength, compared to RSA, with shorter key lengths. Current estimates are that ECDSA with curve P-256 has an approximate equivalent strength to RSA with 3072-bit keys. However, ECDSA signature verification takes considerably more amount of time as compared to RSA signature verification.
RSA is recommended for use cases where fast bootup time is required whereas ECDSA is recommended for use cases where shorter key length is required.
.. list-table:: Comparison between signature verification time
:widths: 10 10 20
:header-rows: 1
* - **Verification scheme**
- **Time**
- **CPU Frequency**
* - RSA-3072
- {IDF_TARGET_RSA_TIME}
- {IDF_TARGET_CPU_FREQ}
* - ECDSA-P256
- {IDF_TARGET_ECDSA_TIME}
- {IDF_TARGET_CPU_FREQ}
The above table compares the time taken to verify a signature in a particular scheme. It does not indicate the bootup time.
The content of each signature block is shown in the following table:
.. only:: not esp32c2
.. only:: esp32 or SOC_SECURE_BOOT_V2_RSA
.. list-table:: Content of a Signature Block
.. list-table:: Content of a RSA Signature Block
:widths: 10 10 40
:header-rows: 1
@ -164,7 +205,7 @@ The content of each signature block is shown in the following table:
.. only:: SOC_SECURE_BOOT_V2_ECC
.. list-table:: Content of a Signature Block
.. list-table:: Content of a ECDSA Signature Block
:widths: 10 10 40
:header-rows: 1
@ -257,14 +298,17 @@ 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.
.. only:: not esp32c2
.. only:: esp32 or (SOC_SECURE_BOOT_V2_RSA and not SOC_SECURE_BOOT_V2_ECC)
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
.. only:: SOC_SECURE_BOOT_V2_ECC and not SOC_SECURE_BOOT_V2_RSA
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.
.. only:: SOC_SECURE_BOOT_V2_ECC and SOC_SECURE_BOOT_V2_RSA
3. Use the public key to verify the signature of the bootloader image, using either RSA-PSS (section 8.1.2 of RFC8017) or ECDSA signature verification (section 5.3.3 of RFC6090) with the image digest calculated in step (2) for comparison.
Bootloader Size
@ -287,10 +331,12 @@ eFuse usage
- BLK2 - Stores the SHA-256 digest of the public key. SHA-256 hash of public key modulus, exponent, pre-calculated R & M values (represented as 776 bytes offsets 36 to 812 - as per the :ref:`signature-block-format`) is written to an eFuse key block. The write-protection bit must be set, but the read-protection bit must not.
.. only:: esp32s2 or esp32c3 or esp32s3
.. only:: not esp32
- SECURE_BOOT_EN - Enables Secure Boot protection on boot.
.. only:: SOC_EFUSE_KEY_PURPOSE_FIELD
- KEY_PURPOSE_X - Set the purpose of the key block on {IDF_TARGET_NAME} by programming SECURE_BOOT_DIGESTX (X = 0, 1, 2) into KEY_PURPOSE_X (X = 0, 1, 2, 3, 4, 5). Example: If KEY_PURPOSE_2 is set to SECURE_BOOT_DIGEST1, then BLOCK_KEY2 will have the Secure Boot V2 public key digest. The write-protection bit must be set (this field does not have a read-protection bit).
- BLOCK_KEYX - The block contains the data corresponding to its purpose programmed in KEY_PURPOSE_X. Stores the SHA-256 digest of the public key. SHA-256 hash of public key modulus, exponent, pre-calculated R & M values (represented as 776 bytes offsets 36 to 812 - as per the :ref:`signature-block-format`) is written to an eFuse key block. The write-protection bit must be set, but the read-protection bit must not.
@ -318,9 +364,9 @@ How To Enable Secure Boot V2
4. Select the desired UART ROM download mode in "UART ROM download mode". By default the UART ROM download mode has been kept enabled in order to prevent permanently disabling it in the development phase, this option is a potentially insecure option. It is recommended to disable the UART download mode for better security.
.. only:: esp32s2 or esp32c3 or esp32s3
.. only:: SOC_SECURE_BOOT_V2_RSA or SOC_SECURE_BOOT_V2_ECC
2. The "Secure Boot V2" option will be selected and the "App Signing Scheme" would be set to RSA by default.
2. The "Secure Boot V2" option will be selected and the "App Signing Scheme" would be set to {IDF_TARGET_SBV2_DEFAULT_SCHEME} by default. {IDF_TARGET_SECURE_BOOT_OPTION_TEXT}
3. Specify the path to Secure Boot signing key, relative to the project directory.
@ -368,11 +414,11 @@ 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``.
.. only:: not esp32c2
.. only:: esp32 or SOC_SECURE_BOOT_V2_RSA
The ``--version 2`` parameter will generate the RSA 3072 private key for Secure Boot V2.
The ``--version 2`` parameter will generate the RSA 3072 private key for Secure Boot V2. Additionally ``--scheme rsa3072`` can be passed as well to generate RSA 3072 private key
.. only:: esp32c2
.. only:: SOC_SECURE_BOOT_V2_ECC
Select the ECDSA scheme by passing ``--version 2 --scheme ecdsa256`` or ``--version 2 --scheme ecdsa192`` to generate corresponding ECDSA private key
@ -380,21 +426,23 @@ The strength of the signing key is proportional to (a) the random number source
For example, to generate a signing key using the openssl command line:
.. only:: not esp32c2
.. only:: esp32 or SOC_SECURE_BOOT_V2_RSA
For RSA 3072
```
openssl genrsa -out my_secure_boot_signing_key.pem 3072
```
.. only:: esp32c2
.. only:: SOC_SECURE_BOOT_V2_ECC
For NIST192p curve
For ECC NIST192p curve
```
openssl ecparam -name prime192v1 -genkey -noout -out my_secure_boot_signing_key.pem
```
For NIST256p curve
For ECC NIST256p curve
```
openssl ecparam -name prime256v1 -genkey -noout -out my_secure_boot_signing_key.pem
@ -460,12 +508,12 @@ Secure Boot Best Practices
* Enable all Secure Boot options in the Secure Boot Configuration. These include flash encryption, disabling of JTAG, disabling BASIC ROM interpreter, and disabling the UART bootloader encrypted flash access.
* Use Secure Boot in combination with :doc:`flash encryption<flash-encryption>` to prevent local readout of the flash contents.
.. only:: esp32s2 or esp32c3 or esp32s3
.. only:: SOC_EFUSE_REVOKE_BOOT_KEY_DIGESTS
Key Management
--------------
* Between 1 and 3 RSA-3072 public key pairs (Keys #0, #1, #2) should be computed independently and stored separately.
* Between 1 and 3 {IDF_TARGET_SBV2_KEY} public key pairs (Keys #0, #1, #2) should be computed independently and stored separately.
* The KEY_DIGEST eFuses should be write protected after being programmed.
* The unused KEY_DIGEST slots must have their corresponding KEY_REVOKE eFuse burned to permanently disable them. This must happen before the device leaves the factory.
* The eFuses can either be written by the software bootloader during during first boot after enabling "Secure Boot V2" from menuconfig or can be done using `espefuse.py` which communicates with the serial bootloader program in ROM.
@ -581,14 +629,18 @@ 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
.. only:: not esp32 and not esp32c2
.. only:: SOC_SECURE_BOOT_V2_RSA and not SOC_SECURE_BOOT_V2_ECC
2. Ensure `App Signing Scheme` is `RSA`
.. only:: esp32c2
.. only:: SOC_SECURE_BOOT_V2_ECC and not SOC_SECURE_BOOT_V2_RSA
2. Ensure `App Signing Scheme` is `ECDSA (V2)`
.. only:: SOC_SECURE_BOOT_V2_RSA and SOC_SECURE_BOOT_V2_ECC
2. Choose `App Signing Scheme`. Either `RSA` or `ECDSA (V2)`
3. Enable :ref:`CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT`