mirror of
				https://github.com/espressif/esp-idf.git
				synced 2025-11-03 22:08:28 +00:00 
			
		
		
		
	feat(ecc): enable ECC constant time mode for ESP32-H2 ECO5
This commit is contained in:
		
				
					committed by
					
						
						Aditya Patwardhan
					
				
			
			
				
	
			
			
			
						parent
						
							c3611f701e
						
					
				
				
					commit
					58e5f48368
				
			@@ -331,4 +331,33 @@ menu "Hardware Settings"
 | 
			
		||||
            default 3 if ESP_CRYPTO_DPA_PROTECTION_LEVEL_HIGH
 | 
			
		||||
 | 
			
		||||
    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"
 | 
			
		||||
 | 
			
		||||
    # Invisible bringup bypass options for esp_hw_support component
 | 
			
		||||
    config ESP_BRINGUP_BYPASS_CPU_CLK_SETTING
 | 
			
		||||
        bool
 | 
			
		||||
        default y if !SOC_CLK_TREE_SUPPORTED
 | 
			
		||||
        default n
 | 
			
		||||
        help
 | 
			
		||||
            This option is only used for new chip bringup, when
 | 
			
		||||
            clock support isn't done yet. So with this option,
 | 
			
		||||
            we use xtal on FPGA as the clock source.
 | 
			
		||||
 | 
			
		||||
endmenu
 | 
			
		||||
 
 | 
			
		||||
@@ -247,6 +247,18 @@ static void start_other_core(void)
 | 
			
		||||
        REG_CLR_BIT(SYSTEM_CORE_1_CONTROL_0_REG, SYSTEM_CONTROL_CORE_1_RESETING);
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if CONFIG_ESP_CRYPTO_FORCE_ECC_CONSTANT_TIME_POINT_MUL
 | 
			
		||||
    if (!esp_efuse_read_field_bit(ESP_EFUSE_ECC_FORCE_CONST_TIME)) {
 | 
			
		||||
        ESP_EARLY_LOGD(TAG, "Forcefully enabling ECC constant time operations");
 | 
			
		||||
        esp_err_t err = esp_efuse_write_field_bit(ESP_EFUSE_ECC_FORCE_CONST_TIME);
 | 
			
		||||
        if (err != ESP_OK) {
 | 
			
		||||
            ESP_EARLY_LOGE(TAG, "Enabling ECC constant time operations forcefully failed.");
 | 
			
		||||
            return err;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    ets_set_appcpu_boot_addr((uint32_t)call_start_cpu1);
 | 
			
		||||
 | 
			
		||||
    bool cpus_up = false;
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
 | 
			
		||||
 * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 */
 | 
			
		||||
@@ -142,6 +142,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
 | 
			
		||||
 
 | 
			
		||||
@@ -153,6 +153,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
 | 
			
		||||
 
 | 
			
		||||
@@ -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" {
 | 
			
		||||
@@ -189,6 +191,18 @@ static inline ecc_mod_base_t ecc_ll_get_mod_base(void)
 | 
			
		||||
    return 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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -59,6 +59,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()) {
 | 
			
		||||
@@ -132,6 +133,74 @@ TEST_CASE("ECC point multiplication on SECP192R1 and SECP256R1", "[ecc][hal]")
 | 
			
		||||
{
 | 
			
		||||
    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
 | 
			
		||||
 
 | 
			
		||||
@@ -549,11 +549,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.
 | 
			
		||||
 
 | 
			
		||||
@@ -39,6 +39,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));
 | 
			
		||||
 
 | 
			
		||||
@@ -1067,6 +1067,14 @@ 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
 | 
			
		||||
 | 
			
		||||
config SOC_UART_NUM
 | 
			
		||||
    int
 | 
			
		||||
    default 2
 | 
			
		||||
 
 | 
			
		||||
@@ -457,6 +457,12 @@
 | 
			
		||||
/*------------------------ 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)
 | 
			
		||||
 | 
			
		||||
/*-------------------------- UART CAPS ---------------------------------------*/
 | 
			
		||||
// ESP32-H2 has 2 UARTs
 | 
			
		||||
#define SOC_UART_NUM                (2)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user