mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 11:10:54 +03:00
fix(secure_boot): range-check ECDSA r,s in bootloader before ROM verify
This commit is contained in:
@@ -61,6 +61,11 @@ static inline void ecc_ll_power_up(void)
|
|||||||
ESP_FAULT_ASSERT(REG_GET_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_FORCE_PD) == 0);
|
ESP_FAULT_ASSERT(REG_GET_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_FORCE_PD) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool ecc_ll_mem_force_pd_is_clear(void)
|
||||||
|
{
|
||||||
|
return REG_GET_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_FORCE_PD) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void ecc_ll_power_down(void)
|
static inline void ecc_ll_power_down(void)
|
||||||
{
|
{
|
||||||
/* Power down the ECC peripheral */
|
/* Power down the ECC peripheral */
|
||||||
|
|||||||
@@ -56,6 +56,11 @@ static inline void ecc_ll_power_up(void)
|
|||||||
ESP_FAULT_ASSERT(REG_GET_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_FORCE_PD) == 0);
|
ESP_FAULT_ASSERT(REG_GET_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_FORCE_PD) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool ecc_ll_mem_force_pd_is_clear(void)
|
||||||
|
{
|
||||||
|
return REG_GET_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_FORCE_PD) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void ecc_ll_power_down(void)
|
static inline void ecc_ll_power_down(void)
|
||||||
{
|
{
|
||||||
/* Power down the ECC peripheral */
|
/* Power down the ECC peripheral */
|
||||||
|
|||||||
@@ -58,6 +58,11 @@ static inline void ecc_ll_power_up(void)
|
|||||||
ESP_FAULT_ASSERT(REG_GET_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_FORCE_PD) == 0);
|
ESP_FAULT_ASSERT(REG_GET_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_FORCE_PD) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool ecc_ll_mem_force_pd_is_clear(void)
|
||||||
|
{
|
||||||
|
return REG_GET_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_FORCE_PD) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void ecc_ll_power_down(void)
|
static inline void ecc_ll_power_down(void)
|
||||||
{
|
{
|
||||||
REG_CLR_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_FORCE_PU);
|
REG_CLR_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_FORCE_PU);
|
||||||
|
|||||||
@@ -75,6 +75,11 @@ static inline void ecc_ll_power_up(void)
|
|||||||
ESP_FAULT_ASSERT(REG_GET_BIT(HP_SYSTEM_ECC_PD_CTRL_REG, HP_SYSTEM_ECC_MEM_FORCE_PD) == 0);
|
ESP_FAULT_ASSERT(REG_GET_BIT(HP_SYSTEM_ECC_PD_CTRL_REG, HP_SYSTEM_ECC_MEM_FORCE_PD) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool ecc_ll_mem_force_pd_is_clear(void)
|
||||||
|
{
|
||||||
|
return REG_GET_BIT(HP_SYSTEM_ECC_PD_CTRL_REG, HP_SYSTEM_ECC_MEM_FORCE_PD) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void ecc_ll_power_down(void)
|
static inline void ecc_ll_power_down(void)
|
||||||
{
|
{
|
||||||
/* Power down the ECC peripheral */
|
/* Power down the ECC peripheral */
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
list(APPEND private_required_comp soc hal esp_hal_uart)
|
list(APPEND private_required_comp soc hal esp_hal_uart esp_hal_security)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CONFIG_IDF_TARGET_ARCH_XTENSA)
|
if(CONFIG_IDF_TARGET_ARCH_XTENSA)
|
||||||
|
|||||||
@@ -413,8 +413,7 @@ esp_rom_km_huk_risk = 0x40000898;
|
|||||||
ets_emsa_pss_verify = 0x4000089c;
|
ets_emsa_pss_verify = 0x4000089c;
|
||||||
ets_rsa_pss_verify = 0x400008a0;
|
ets_rsa_pss_verify = 0x400008a0;
|
||||||
_rom_ets_ecdsa_verify = 0x400008a4;
|
_rom_ets_ecdsa_verify = 0x400008a4;
|
||||||
ets_secure_boot_verify_bootloader_with_keys = 0x400008a8;
|
_rom_ets_secure_boot_verify_signature = 0x400008ac;
|
||||||
ets_secure_boot_verify_signature = 0x400008ac;
|
|
||||||
ets_secure_boot_read_key_digests = 0x400008b0;
|
ets_secure_boot_read_key_digests = 0x400008b0;
|
||||||
ets_mgf1_sha256 = 0x400008b4;
|
ets_mgf1_sha256 = 0x400008b4;
|
||||||
ets_secure_boot_revoke_public_key_digest = 0x400008b8;
|
ets_secure_boot_revoke_public_key_digest = 0x400008b8;
|
||||||
|
|||||||
@@ -371,8 +371,7 @@ ets_efuse_usb_device_disabled = 0x40000808;
|
|||||||
|
|
||||||
/* Functions */
|
/* Functions */
|
||||||
_rom_ets_ecdsa_verify = 0x40000810;
|
_rom_ets_ecdsa_verify = 0x40000810;
|
||||||
ets_secure_boot_verify_bootloader_with_keys = 0x40000814;
|
_rom_ets_secure_boot_verify_signature = 0x40000818;
|
||||||
ets_secure_boot_verify_signature = 0x40000818;
|
|
||||||
ets_secure_boot_read_key_digests = 0x4000081c;
|
ets_secure_boot_read_key_digests = 0x4000081c;
|
||||||
ets_secure_boot_revoke_public_key_digest = 0x40000820;
|
ets_secure_boot_revoke_public_key_digest = 0x40000820;
|
||||||
|
|
||||||
|
|||||||
@@ -362,8 +362,7 @@ ets_efuse_secure_boot_fast_wake_enabled = 0x40000830;
|
|||||||
ets_emsa_pss_verify = 0x40000834;
|
ets_emsa_pss_verify = 0x40000834;
|
||||||
ets_rsa_pss_verify = 0x40000838;
|
ets_rsa_pss_verify = 0x40000838;
|
||||||
_rom_ets_ecdsa_verify = 0x4000083c;
|
_rom_ets_ecdsa_verify = 0x4000083c;
|
||||||
ets_secure_boot_verify_bootloader_with_keys = 0x40000840;
|
_rom_ets_secure_boot_verify_signature = 0x40000844;
|
||||||
ets_secure_boot_verify_signature = 0x40000844;
|
|
||||||
ets_secure_boot_read_key_digests = 0x40000848;
|
ets_secure_boot_read_key_digests = 0x40000848;
|
||||||
ets_secure_boot_revoke_public_key_digest = 0x4000084c;
|
ets_secure_boot_revoke_public_key_digest = 0x4000084c;
|
||||||
|
|
||||||
|
|||||||
@@ -79,10 +79,6 @@ config ESP_ROM_RAM_APP_NEEDS_MMU_INIT
|
|||||||
bool
|
bool
|
||||||
default y
|
default y
|
||||||
|
|
||||||
config ESP_ROM_ECDSA_VERIFY_PATCH
|
|
||||||
bool
|
|
||||||
default y
|
|
||||||
|
|
||||||
config ESP_ROM_CACHE_WRITEBACK_NEEDS_SYNC_TWICE_NO_MAP
|
config ESP_ROM_CACHE_WRITEBACK_NEEDS_SYNC_TWICE_NO_MAP
|
||||||
bool
|
bool
|
||||||
default y
|
default y
|
||||||
|
|||||||
@@ -25,5 +25,4 @@
|
|||||||
#define ESP_ROM_USB_OTG_NUM (-1) // No USB_OTG CDC in the ROM, set -1 for Kconfig usage.
|
#define ESP_ROM_USB_OTG_NUM (-1) // No USB_OTG CDC in the ROM, set -1 for Kconfig usage.
|
||||||
#define ESP_ROM_WDT_INIT_PATCH (1) // ROM version does not configure the clock
|
#define ESP_ROM_WDT_INIT_PATCH (1) // ROM version does not configure the clock
|
||||||
#define ESP_ROM_RAM_APP_NEEDS_MMU_INIT (1) // ROM doesn't init cache MMU when it's a RAM APP, needs MMU hal to init
|
#define ESP_ROM_RAM_APP_NEEDS_MMU_INIT (1) // ROM doesn't init cache MMU when it's a RAM APP, needs MMU hal to init
|
||||||
#define ESP_ROM_ECDSA_VERIFY_PATCH (1) // ROM ets_ecdsa_verify API requires a software patch
|
|
||||||
#define ESP_ROM_CACHE_WRITEBACK_NEEDS_SYNC_TWICE_NO_MAP (1) // ROM cache writeback related needs patch to avoid sync loss, no map parameter
|
#define ESP_ROM_CACHE_WRITEBACK_NEEDS_SYNC_TWICE_NO_MAP (1) // ROM cache writeback related needs patch to avoid sync loss, no map parameter
|
||||||
|
|||||||
@@ -448,9 +448,8 @@ esp_rom_km_huk_risk = 0x4fc00710;
|
|||||||
/* Functions */
|
/* Functions */
|
||||||
ets_emsa_pss_verify = 0x4fc00714;
|
ets_emsa_pss_verify = 0x4fc00714;
|
||||||
ets_rsa_pss_verify = 0x4fc00718;
|
ets_rsa_pss_verify = 0x4fc00718;
|
||||||
ets_ecdsa_verify = 0x4fc0071c;
|
_rom_ets_ecdsa_verify = 0x4fc0071c;
|
||||||
ets_secure_boot_verify_bootloader_with_keys = 0x4fc00720;
|
_rom_ets_secure_boot_verify_signature = 0x4fc00724;
|
||||||
ets_secure_boot_verify_signature = 0x4fc00724;
|
|
||||||
ets_secure_boot_read_key_digests = 0x4fc00728;
|
ets_secure_boot_read_key_digests = 0x4fc00728;
|
||||||
ets_secure_boot_revoke_public_key_digest = 0x4fc0072c;
|
ets_secure_boot_revoke_public_key_digest = 0x4fc0072c;
|
||||||
|
|
||||||
|
|||||||
@@ -450,9 +450,8 @@ esp_rom_km_huk_risk = 0x4fc0071c;
|
|||||||
/* Functions */
|
/* Functions */
|
||||||
ets_emsa_pss_verify = 0x4fc00720;
|
ets_emsa_pss_verify = 0x4fc00720;
|
||||||
ets_rsa_pss_verify = 0x4fc00724;
|
ets_rsa_pss_verify = 0x4fc00724;
|
||||||
ets_ecdsa_verify = 0x4fc00728;
|
_rom_ets_ecdsa_verify = 0x4fc00728;
|
||||||
ets_secure_boot_verify_bootloader_with_keys = 0x4fc0072c;
|
_rom_ets_secure_boot_verify_signature = 0x4fc00730;
|
||||||
ets_secure_boot_verify_signature = 0x4fc00730;
|
|
||||||
ets_secure_boot_read_key_digests = 0x4fc00734;
|
ets_secure_boot_read_key_digests = 0x4fc00734;
|
||||||
ets_secure_boot_revoke_public_key_digest = 0x4fc00738;
|
ets_secure_boot_revoke_public_key_digest = 0x4fc00738;
|
||||||
|
|
||||||
|
|||||||
@@ -6,12 +6,15 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "sdkconfig.h"
|
||||||
#include "esp_rom_caps.h"
|
#include "esp_rom_caps.h"
|
||||||
#if ESP_ROM_ECDSA_VERIFY_PATCH
|
#if ESP_ROM_ECDSA_VERIFY_PATCH
|
||||||
#include "soc/soc_caps.h"
|
#include "soc/soc_caps.h"
|
||||||
#include "esp_fault.h"
|
#include "esp_fault.h"
|
||||||
|
#include "hal/ecc_ll.h"
|
||||||
#include "rom/ecdsa.h"
|
#include "rom/ecdsa.h"
|
||||||
|
|
||||||
#define VALID_MAGIC_OK 0x6A6A6A6AU
|
#define VALID_MAGIC_OK 0x6A6A6A6AU
|
||||||
@@ -69,6 +72,19 @@ static bool ecdsa_scalars_in_range(const uint32_t *r, const uint32_t *s, const u
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: IDF-15721
|
||||||
|
/*
|
||||||
|
* Runtime gate that decides whether the ROM ECDSA verification routines
|
||||||
|
* (ets_ecdsa_verify / ets_secure_boot_verify_signature) need the software patch
|
||||||
|
* in this file, or whether the ROM implementation is safe to call directly.
|
||||||
|
*
|
||||||
|
* When a future revision of one of these chips ships a ROM with these ECDSA
|
||||||
|
* verification issues fixed, add a ROM-version check here (e.g. compare the
|
||||||
|
* _rom_eco_version symbol against the first fixed ROM ECO version for that
|
||||||
|
* target) and return false for the fixed ROMs, so they skip the patch and jump
|
||||||
|
* straight to the _rom_ routine.
|
||||||
|
*/
|
||||||
|
|
||||||
extern int _rom_ets_ecdsa_verify(const uint8_t *key, const uint8_t *sig,
|
extern int _rom_ets_ecdsa_verify(const uint8_t *key, const uint8_t *sig,
|
||||||
ECDSA_CURVE curve_id, const uint8_t *image_digest,
|
ECDSA_CURVE curve_id, const uint8_t *image_digest,
|
||||||
uint8_t *verified_digest);
|
uint8_t *verified_digest);
|
||||||
@@ -113,6 +129,9 @@ int ets_ecdsa_verify(const uint8_t *key, const uint8_t *sig,
|
|||||||
|
|
||||||
ESP_FAULT_ASSERT(ok && ret_status == VALID_MAGIC_OK);
|
ESP_FAULT_ASSERT(ok && ret_status == VALID_MAGIC_OK);
|
||||||
|
|
||||||
|
ecc_ll_power_up();
|
||||||
|
ESP_FAULT_ASSERT(ecc_ll_mem_force_pd_is_clear());
|
||||||
|
|
||||||
int ret = _rom_ets_ecdsa_verify(key, sig, curve_id, image_digest, verified_digest);
|
int ret = _rom_ets_ecdsa_verify(key, sig, curve_id, image_digest, verified_digest);
|
||||||
|
|
||||||
if (ret == 1) {
|
if (ret == 1) {
|
||||||
@@ -125,4 +144,88 @@ int ets_ecdsa_verify(const uint8_t *key, const uint8_t *sig,
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if CONFIG_SECURE_BOOT_V2_ENABLED || CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT
|
||||||
|
#include "rom/secure_boot.h"
|
||||||
|
|
||||||
|
#if CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
|
||||||
|
static bool esp_rom_ecdsa_scalars_in_range(const uint8_t *r_le, const uint8_t *s_le, size_t component_len)
|
||||||
|
{
|
||||||
|
const uint32_t *n;
|
||||||
|
int words;
|
||||||
|
switch (component_len) {
|
||||||
|
case 24: n = ecdsa_n_p192; words = 6; break;
|
||||||
|
case 32: n = ecdsa_n_p256; words = 8; break;
|
||||||
|
#if SOC_ECDSA_SUPPORT_CURVE_P384
|
||||||
|
case 48: n = ecdsa_n_p384; words = 12; break;
|
||||||
|
#endif
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t r[12] = { 0 };
|
||||||
|
uint32_t s[12] = { 0 };
|
||||||
|
memcpy(r, r_le, component_len);
|
||||||
|
memcpy(s, s_le, component_len);
|
||||||
|
|
||||||
|
uint32_t result = VALID_MAGIC_FAIL;
|
||||||
|
bool ok = ecdsa_scalars_in_range(r, s, n, words, &result);
|
||||||
|
if (!ok || result != VALID_MAGIC_OK) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ESP_FAULT_ASSERT(ok && result == VALID_MAGIC_OK);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool esp_rom_ecdsa_sig_block_in_range(const ets_secure_boot_sig_block_t *block)
|
||||||
|
{
|
||||||
|
if (block->magic_byte != ETS_SECURE_BOOT_V2_SIGNATURE_MAGIC) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
size_t component_len;
|
||||||
|
switch (block->ecdsa.key.curve_id) {
|
||||||
|
case ECDSA_CURVE_P256: component_len = 32; break;
|
||||||
|
#if SOC_ECDSA_SUPPORT_CURVE_P384
|
||||||
|
case ECDSA_CURVE_P384: component_len = 48; break;
|
||||||
|
#endif
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
return esp_rom_ecdsa_scalars_in_range(&block->ecdsa.signature[0],
|
||||||
|
&block->ecdsa.signature[component_len],
|
||||||
|
component_len);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME */
|
||||||
|
|
||||||
|
extern ets_secure_boot_status_t _rom_ets_secure_boot_verify_signature(const ets_secure_boot_signature_t *sig,
|
||||||
|
const uint8_t *image_digest,
|
||||||
|
const ets_secure_boot_key_digests_t *trusted_keys,
|
||||||
|
uint8_t *verified_digest);
|
||||||
|
|
||||||
|
ets_secure_boot_status_t ets_secure_boot_verify_signature(const ets_secure_boot_signature_t *sig,
|
||||||
|
const uint8_t *image_digest,
|
||||||
|
const ets_secure_boot_key_digests_t *trusted_keys,
|
||||||
|
uint8_t *verified_digest)
|
||||||
|
{
|
||||||
|
#if CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
|
||||||
|
volatile ets_secure_boot_status_t range_status = SB_FAILED;
|
||||||
|
unsigned blocks_in_range = 0;
|
||||||
|
for (unsigned i = 0; i < SECURE_BOOT_NUM_BLOCKS; i++) {
|
||||||
|
if (esp_rom_ecdsa_sig_block_in_range(&sig->block[i])) {
|
||||||
|
blocks_in_range++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (blocks_in_range == SECURE_BOOT_NUM_BLOCKS) {
|
||||||
|
range_status = SB_SUCCESS;
|
||||||
|
}
|
||||||
|
if (range_status != SB_SUCCESS) {
|
||||||
|
return SB_FAILED;
|
||||||
|
}
|
||||||
|
ESP_FAULT_ASSERT(range_status == SB_SUCCESS);
|
||||||
|
ESP_FAULT_ASSERT(blocks_in_range == SECURE_BOOT_NUM_BLOCKS);
|
||||||
|
|
||||||
|
ecc_ll_power_up();
|
||||||
|
ESP_FAULT_ASSERT(ecc_ll_mem_force_pd_is_clear());
|
||||||
|
#endif /* CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME */
|
||||||
|
return _rom_ets_secure_boot_verify_signature(sig, image_digest, trusted_keys, verified_digest);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_SECURE_BOOT_V2_ENABLED || CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT */
|
||||||
#endif /* ESP_ROM_ECDSA_VERIFY_PATCH */
|
#endif /* ESP_ROM_ECDSA_VERIFY_PATCH */
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
CONFIG_IDF_TARGET="esp32c5"
|
CONFIG_IDF_TARGET="esp32c5"
|
||||||
|
|
||||||
CONFIG_PARTITION_TABLE_OFFSET=0xE000
|
CONFIG_PARTITION_TABLE_OFFSET=0xF000
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="test/partitions_efuse_emul.csv"
|
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="test/partitions_efuse_emul.csv"
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
CONFIG_IDF_TARGET="esp32c5"
|
CONFIG_IDF_TARGET="esp32c5"
|
||||||
|
|
||||||
CONFIG_PARTITION_TABLE_OFFSET=0xE000
|
CONFIG_PARTITION_TABLE_OFFSET=0xF000
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="test/partitions_efuse_emul.csv"
|
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="test/partitions_efuse_emul.csv"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user