feat(ecc): enable ECC constant time mode for ESP32-H2 ECO5

This commit is contained in:
Mahavir Jain 2024-10-22 15:17:16 +05:30 committed by Aditya Patwardhan
parent d4bb0e2aa3
commit e97c51ea24
No known key found for this signature in database
GPG Key ID: E628B2648FBF0DD8
15 changed files with 166 additions and 6 deletions

View File

@ -95,6 +95,19 @@ static esp_err_t init_efuse_secure(void)
}
#endif
#if CONFIG_ESP_CRYPTO_FORCE_ECC_CONSTANT_TIME_POINT_MUL
bool force_constant_time = true;
#if CONFIG_IDF_TARGET_ESP32H2
if (!ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 102)) {
force_constant_time = false;
}
#endif
if (!esp_efuse_read_field_bit(ESP_EFUSE_ECC_FORCE_CONST_TIME) && force_constant_time) {
ESP_EARLY_LOGD(TAG, "Forcefully enabling ECC constant time operations");
ESP_RETURN_ON_ERROR(esp_efuse_write_field_bit(ESP_EFUSE_ECC_FORCE_CONST_TIME), TAG, "Failed to enable ECC constant time operations");
}
#endif
#if CONFIG_SECURE_DISABLE_ROM_DL_MODE
// Permanently disable ROM download mode
ESP_RETURN_ON_ERROR(esp_efuse_disable_rom_download_mode(), TAG, "Failed to disable ROM download mode");

View File

@ -325,6 +325,20 @@ menu "Hardware Settings"
endmenu
config ESP_CRYPTO_FORCE_ECC_CONSTANT_TIME_POINT_MUL
bool "Forcefully enable ECC constant time point multiplication operations"
depends on SOC_ECC_CONSTANT_TIME_POINT_MUL
default N
help
If enabled, the app startup code will burn the ECC_FORCE_CONST_TIME efuse bit to force the
ECC peripheral to always perform constant time point multiplication operations,
irrespective of the ECC_MULT_SECURITY_MODE status bit that is present in the ECC_MULT_CONF_REG
register. By default, ESP-IDF configures the ECC peripheral to perform constant time point
multiplication operations, so enabling this config would provide security enhancement only in
the cases when trusted boot is not enabled and the attacker tries carrying out non-constant
time point multiplication operations by changing the default ESP-IDF configurations.
Performing constant time operations protect the ECC multiplication operations from timing attacks.
orsource "./port/$IDF_TARGET/Kconfig.dcdc"
orsource "./port/$IDF_TARGET/Kconfig.ldo"

View File

@ -15,6 +15,8 @@ choice ESP32H2_REV_MIN
bool "Rev v0.1 (ECO1)"
config ESP32H2_REV_MIN_2
bool "Rev v0.2 (ECO2)"
config ESP32H2_REV_MIN_102
bool "Rev v1.2 (ECO5)"
endchoice
config ESP32H2_REV_MIN_FULL
@ -22,6 +24,7 @@ config ESP32H2_REV_MIN_FULL
default 0 if ESP32H2_REV_MIN_0
default 1 if ESP32H2_REV_MIN_1
default 2 if ESP32H2_REV_MIN_2
default 102 if ESP32H2_REV_MIN_102
config ESP_REV_MIN_FULL
int
@ -31,7 +34,7 @@ config ESP_REV_MIN_FULL
# MAX Revision
#
comment "Maximum Supported ESP32-H2 Revision (Rev v0.99)"
comment "Maximum Supported ESP32-H2 Revision (Rev v1.99)"
# Maximum revision that IDF supports.
# It can not be changed by user.
# Only Espressif can change it when a new version will be supported in IDF.

View File

@ -105,8 +105,8 @@ menu "Hardware Abstraction Layer (HAL) and Low Level (LL)"
config HAL_ECDSA_GEN_SIG_CM
bool "Enable countermeasure for ECDSA signature generation"
depends on IDF_TARGET_ESP32H2 && ESP32H2_REV_MIN_FULL < 102
default n
# ToDo - IDF-11051
help
Enable this option to apply the countermeasure for ECDSA signature operation
This countermeasure masks the real ECDSA sign operation

View File

@ -177,3 +177,8 @@ int ecc_hal_read_mod_op_result(uint8_t *r, uint16_t len)
}
#endif /* SOC_ECC_EXTENDED_MODES_SUPPORTED */
void ecc_hal_enable_constant_time_point_mul(bool enable)
{
ecc_ll_enable_constant_time_point_mul(enable);
}

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -171,6 +171,12 @@ static inline void ecc_ll_read_param(ecc_ll_param_t param, uint8_t *buf, uint16_
memcpy(buf, (void *)reg, len);
}
static inline void ecc_ll_enable_constant_time_point_mul(bool enable)
{
// Not supported for ESP32-C2
(void) enable; //unused
}
#ifdef __cplusplus
}
#endif

View File

@ -173,6 +173,12 @@ static inline void ecc_ll_read_param(ecc_ll_param_t param, uint8_t *buf, uint16_
memcpy(buf, (void *)reg, len);
}
static inline void ecc_ll_enable_constant_time_point_mul(bool enable)
{
// Not supported for ESP32-C6
(void) enable; //unused
}
#ifdef __cplusplus
}
#endif

View File

@ -12,6 +12,8 @@
#include "soc/ecc_mult_reg.h"
#include "soc/pcr_struct.h"
#include "soc/pcr_reg.h"
#include "soc/chip_revision.h"
#include "hal/efuse_ll.h"
#ifdef __cplusplus
extern "C" {
@ -211,6 +213,18 @@ static inline ecc_mod_base_t ecc_ll_get_mod_base(void)
return (ecc_mod_base_t)(REG_GET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_MOD_BASE));
}
static inline void ecc_ll_enable_constant_time_point_mul(bool enable)
{
// ECC constant time point multiplication is supported only on rev 1.2 and above
if ((efuse_ll_get_chip_wafer_version_major() >= 1) && (efuse_ll_get_chip_wafer_version_minor() >= 2)) {
if (enable) {
REG_SET_BIT(ECC_MULT_CONF_REG, ECC_MULT_SECURITY_MODE);
} else {
REG_CLR_BIT(ECC_MULT_CONF_REG, ECC_MULT_SECURITY_MODE);
}
}
}
static inline void ecc_ll_read_param(ecc_ll_param_t param, uint8_t *buf, uint16_t len)
{
uint32_t reg;

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -240,6 +240,12 @@ static inline void ecc_ll_read_param(ecc_ll_param_t param, uint8_t *buf, uint16_
memcpy(buf, (void *)reg, len);
}
static inline void ecc_ll_enable_constant_time_point_mul(bool enable)
{
// Not supported for ESP32-P4
(void) enable; //unused
}
#ifdef __cplusplus
}
#endif

View File

@ -195,6 +195,13 @@ int ecc_hal_read_mod_op_result(uint8_t *r, uint16_t len);
#endif /* SOC_ECC_EXTENDED_MODES_SUPPORTED */
/**
* @brief Enable constant time multiplication operations
*
* @param true: enable; false: disable
*/
void ecc_hal_enable_constant_time_point_mul(bool enable);
#ifdef __cplusplus
}
#endif

View File

@ -86,6 +86,7 @@ static void ecc_point_mul(const uint8_t *k_le, const uint8_t *x_le, const uint8_
} else {
ecc_hal_set_mode(ECC_MODE_POINT_MUL);
}
ecc_hal_enable_constant_time_point_mul(true);
ecc_hal_start_calc();
while (!ecc_hal_is_calc_finished()) {
@ -160,6 +161,74 @@ TEST(ecc, ecc_point_multiplication_on_SECP192R1_and_SECP256R1)
{
test_ecc_point_mul_inner(false);
}
#if SOC_ECC_CONSTANT_TIME_POINT_MUL || (CONFIG_IDF_TARGET_ESP32H2 && CONFIG_ESP32H2_REV_MIN_FULL >= 102)
#define CONST_TIME_DEVIATION_PERCENT 0.002
static void test_ecc_point_mul_inner_constant_time(void)
{
uint8_t scalar_le[32];
uint8_t x_le[32];
uint8_t y_le[32];
/* P256 */
ecc_be_to_le(ecc_p256_scalar, scalar_le, 32);
ecc_be_to_le(ecc_p256_point_x, x_le, 32);
ecc_be_to_le(ecc_p256_point_y, y_le, 32);
uint8_t x_res_le[32];
uint8_t y_res_le[32];
double deviation = 0;
uint32_t elapsed_time, mean_elapsed_time, total_elapsed_time = 0;
uint32_t max_time = 0, min_time = UINT32_MAX;
int loop_count = 10;
for (int i = 0; i < loop_count; i++) {
ccomp_timer_start();
ecc_point_mul(scalar_le, x_le, y_le, 32, 0, x_res_le, y_res_le);
elapsed_time = ccomp_timer_stop();
max_time = MAX(elapsed_time, max_time);
min_time = MIN(elapsed_time, min_time);
total_elapsed_time += elapsed_time;
}
mean_elapsed_time = total_elapsed_time / loop_count;
deviation = ((double)(max_time - mean_elapsed_time) / mean_elapsed_time);
TEST_ASSERT_LESS_THAN_DOUBLE(CONST_TIME_DEVIATION_PERCENT, deviation);
/* P192 */
ecc_be_to_le(ecc_p192_scalar, scalar_le, 24);
ecc_be_to_le(ecc_p192_point_x, x_le, 24);
ecc_be_to_le(ecc_p192_point_y, y_le, 24);
max_time = 0;
min_time = UINT32_MAX;
total_elapsed_time = 0;
for (int i = 0; i < loop_count; i++) {
ccomp_timer_start();
ecc_point_mul(scalar_le, x_le, y_le, 24, 0, x_res_le, y_res_le);
elapsed_time = ccomp_timer_stop();
max_time = MAX(elapsed_time, max_time);
min_time = MIN(elapsed_time, min_time);
total_elapsed_time += elapsed_time;
}
mean_elapsed_time = total_elapsed_time / loop_count;
deviation = ((double)(max_time - mean_elapsed_time) / mean_elapsed_time);
TEST_ASSERT_LESS_THAN_DOUBLE(CONST_TIME_DEVIATION_PERCENT, deviation);
}
TEST(ecc, ecc_point_multiplication_const_time_check_on_SECP192R1_and_SECP256R1)
{
test_ecc_point_mul_inner_constant_time();
}
#endif
#endif
#if SOC_ECC_SUPPORT_POINT_VERIFY && !defined(SOC_ECC_SUPPORT_POINT_VERIFY_QUIRK)
@ -493,6 +562,9 @@ TEST_GROUP_RUNNER(ecc)
{
#if SOC_ECC_SUPPORT_POINT_MULT
RUN_TEST_CASE(ecc, ecc_point_multiplication_on_SECP192R1_and_SECP256R1);
#if SOC_ECC_CONSTANT_TIME_POINT_MUL || (CONFIG_IDF_TARGET_ESP32H2 && CONFIG_ESP32H2_REV_MIN_FULL >= 102)
RUN_TEST_CASE(ecc, ecc_point_multiplication_const_time_check_on_SECP192R1_and_SECP256R1);
#endif
#endif
#if SOC_ECC_SUPPORT_POINT_VERIFY && !defined(SOC_ECC_SUPPORT_POINT_VERIFY_QUIRK)

View File

@ -586,11 +586,10 @@ menu "mbedTLS"
menu "Enable Software Countermeasure for ECDSA signing using on-chip ECDSA peripheral"
depends on MBEDTLS_HARDWARE_ECDSA_SIGN
depends on IDF_TARGET_ESP32H2
depends on IDF_TARGET_ESP32H2 && ESP32H2_REV_MIN_FULL < 102
config MBEDTLS_HARDWARE_ECDSA_SIGN_MASKING_CM
bool "Mask original ECDSA sign operation under dummy sign operations"
select HAL_ECDSA_GEN_SIG_CM
# ToDo: IDF-11051
default y
help
The ECDSA peripheral before ECO5 does not offer constant time ECDSA sign operation.

View File

@ -44,6 +44,14 @@ int esp_ecc_point_multiply(const ecc_point_t *point, const uint8_t *scalar, ecc_
ecc_hal_write_mul_param(scalar, point->x, point->y, len);
ecc_hal_set_mode(work_mode);
/*
* Enable constant-time point multiplication operations for the ECC hardware accelerator,
* if supported for the given target. This protects the ECC multiplication operation from
* timing attacks. This increases the time taken (by almost 50%) for some point
* multiplication operations performed by the ECC hardware accelerator.
*/
ecc_hal_enable_constant_time_point_mul(true);
ecc_hal_start_calc();
memset(result, 0, sizeof(ecc_point_t));

View File

@ -1239,6 +1239,10 @@ config SOC_CRYPTO_DPA_PROTECTION_SUPPORTED
bool
default y
config SOC_ECC_CONSTANT_TIME_POINT_MUL
bool
default y
config SOC_ECDSA_USES_MPI
bool
default y

View File

@ -502,6 +502,9 @@
/*------------------------ Anti DPA (Security) CAPS --------------------------*/
#define SOC_CRYPTO_DPA_PROTECTION_SUPPORTED 1
/*--------------------------- ECC CAPS ---------------------------------------*/
#define SOC_ECC_CONSTANT_TIME_POINT_MUL 1
/*------------------------- ECDSA CAPS -------------------------*/
#define SOC_ECDSA_USES_MPI (1)