Merge branch 'feat/support_ecc_constant_time_mul_operations' into 'master'

feat(mbedtls/ecc): Support ECC hardware constant-time point multiplication operations

Closes IDF-10327

See merge request espressif/esp-idf!31888
This commit is contained in:
Mahavir Jain
2024-09-25 12:53:45 +08:00
15 changed files with 182 additions and 18 deletions

View File

@@ -37,4 +37,17 @@ menu "ESP Security Specific"
default 3 if ESP_CRYPTO_DPA_PROTECTION_LEVEL_HIGH
endmenu
config ESP_CRYPTO_FORCE_ECC_CONSTANT_TIME_POINT_MUL
bool "Forcfully 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.
endmenu

View File

@@ -16,10 +16,12 @@ static inline void esp_crypto_dpa_set_level(esp_crypto_dpa_sec_level_t level)
REG_SET_FIELD(HP_SYSTEM_SEC_DPA_CONF_REG, HP_SYSTEM_SEC_DPA_LEVEL, level);
}
#if CONFIG_ESP_CRYPTO_DPA_PROTECTION_AT_STARTUP
void esp_crypto_dpa_protection_startup(void)
{
esp_crypto_dpa_set_level(CONFIG_ESP_CRYPTO_DPA_PROTECTION_LEVEL);
}
#endif
void esp_crypto_dpa_protection_enable(esp_crypto_dpa_sec_level_t level)
{

View File

@@ -5,7 +5,10 @@
*/
#pragma once
#include "sdkconfig.h"
/* Private interface file */
#if CONFIG_ESP_CRYPTO_DPA_PROTECTION_AT_STARTUP
void esp_crypto_dpa_protection_startup(void);
#endif

View File

@@ -7,7 +7,12 @@
#include "esp_private/startup_internal.h"
#include "sdkconfig.h"
#include "esp_crypto_clk.h"
#include "esp_efuse.h"
#include "esp_efuse_table.h"
#include "esp_security_priv.h"
#include "esp_err.h"
__attribute__((unused)) static const char *TAG = "esp_security";
ESP_SYSTEM_INIT_FN(esp_security_init, SECONDARY, BIT(0), 103)
{
@@ -15,6 +20,17 @@ ESP_SYSTEM_INIT_FN(esp_security_init, SECONDARY, BIT(0), 103)
#if CONFIG_ESP_CRYPTO_DPA_PROTECTION_AT_STARTUP
esp_crypto_dpa_protection_startup();
#endif
#ifdef 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
return ESP_OK;
}

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -177,3 +177,10 @@ int ecc_hal_read_mod_op_result(uint8_t *r, uint16_t len)
}
#endif /* SOC_ECC_EXTENDED_MODES_SUPPORTED */
#ifdef SOC_ECC_CONSTANT_TIME_POINT_MUL
void ecc_hal_enable_constant_time_point_mul(bool enable)
{
ecc_ll_enable_constant_time_point_mul(enable);
}
#endif /* SOC_ECC_CONSTANT_TIME_POINT_MUL */

View File

@@ -148,6 +148,15 @@ static inline void ecc_ll_set_mod_base(ecc_mod_base_t base)
}
}
static inline void ecc_ll_enable_constant_time_point_mul(bool enable)
{
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_write_param(ecc_ll_param_t param, const uint8_t *buf, uint16_t len)
{
uint32_t reg;

View File

@@ -148,6 +148,15 @@ static inline void ecc_ll_set_mod_base(ecc_mod_base_t base)
}
}
static inline void ecc_ll_enable_constant_time_point_mul(bool enable)
{
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_write_param(ecc_ll_param_t param, const uint8_t *buf, uint16_t len)
{
uint32_t reg;

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -195,6 +195,15 @@ int ecc_hal_read_mod_op_result(uint8_t *r, uint16_t len);
#endif /* SOC_ECC_EXTENDED_MODES_SUPPORTED */
#ifdef SOC_ECC_CONSTANT_TIME_POINT_MUL
/**
* @brief Enable constant time multiplication operations
*
* @param true: enable; false: disable
*/
void ecc_hal_enable_constant_time_point_mul(bool enable);
#endif /* SOC_ECC_CONSTANT_TIME_POINT_MUL */
#ifdef __cplusplus
}
#endif

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: CC0-1.0
*/
@@ -7,6 +7,7 @@
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <sys/param.h>
#include "sdkconfig.h"
#include "esp_private/esp_crypto_lock_internal.h"
#include "esp_log.h"
@@ -17,8 +18,8 @@
#include "memory_checks.h"
#include "unity_fixture.h"
#include "ccomp_timer.h"
#define _DEBUG_ 0
#define SOC_ECC_SUPPORT_POINT_MULT 1
#define SOC_ECC_SUPPORT_POINT_VERIFY 1
@@ -86,6 +87,9 @@ 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);
}
#ifdef SOC_ECC_CONSTANT_TIME_POINT_MUL
ecc_hal_enable_constant_time_point_mul(true);
#endif /* SOC_ECC_CONSTANT_TIME_POINT_MUL */
ecc_hal_start_calc();
while (!ecc_hal_is_calc_finished()) {
@@ -118,13 +122,11 @@ static void test_ecc_point_mul_inner(bool verify_first)
ecc_be_to_le(ecc_p256_mul_res_x, x_mul_le, 32);
ecc_be_to_le(ecc_p256_mul_res_y, y_mul_le, 32);
#if _DEBUG_
ESP_LOG_BUFFER_HEX("Expected X:", x_mul_le, 32);
ESP_LOG_BUFFER_HEX("Got X:", x_res_le, 32);
ESP_LOG_BUFFER_HEXDUMP("Expected X:", x_mul_le, 32, ESP_LOG_DEBUG);
ESP_LOG_BUFFER_HEXDUMP("Got X:", x_res_le, 32, ESP_LOG_DEBUG);
ESP_LOG_BUFFER_HEX("Expected Y:", y_mul_le, 32);
ESP_LOG_BUFFER_HEX("Got Y:", y_res_le, 32);
#endif
ESP_LOG_BUFFER_HEXDUMP("Expected Y:", y_mul_le, 32, ESP_LOG_DEBUG);
ESP_LOG_BUFFER_HEXDUMP("Got Y:", y_res_le, 32, ESP_LOG_DEBUG);
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(x_mul_le, x_res_le, 32, "X coordinate of P256 point multiplication ");
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(y_mul_le, y_res_le, 32, "Y coordinate of P256 point multiplication ");
@@ -144,13 +146,11 @@ static void test_ecc_point_mul_inner(bool verify_first)
ecc_be_to_le(ecc_p192_mul_res_x, x_mul_le, 24);
ecc_be_to_le(ecc_p192_mul_res_y, y_mul_le, 24);
#if _DEBUG_
ESP_LOG_BUFFER_HEX("Expected X:", x_mul_le, 32);
ESP_LOG_BUFFER_HEX("Got X:", x_res_le, 32);
ESP_LOG_BUFFER_HEXDUMP("Expected X:", x_mul_le, 32, ESP_LOG_DEBUG);
ESP_LOG_BUFFER_HEXDUMP("Got X:", x_res_le, 32, ESP_LOG_DEBUG);
ESP_LOG_BUFFER_HEX("Expected Y:", y_mul_le, 32);
ESP_LOG_BUFFER_HEX("Got Y:", y_res_le, 32);
#endif
ESP_LOG_BUFFER_HEXDUMP("Expected Y:", y_mul_le, 32, ESP_LOG_DEBUG);
ESP_LOG_BUFFER_HEXDUMP("Got Y:", y_res_le, 32, ESP_LOG_DEBUG);
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(x_mul_le, x_res_le, 24, "X coordinate of P192 point multiplication ");
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(y_mul_le, y_res_le, 24, "Y coordinate of P192 point multiplication ");
@@ -160,6 +160,74 @@ TEST(ecc, ecc_point_multiplication_on_SECP192R1_and_SECP256R1)
{
test_ecc_point_mul_inner(false);
}
#if SOC_ECC_CONSTANT_TIME_POINT_MUL
#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 +561,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
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)
@@ -534,5 +605,4 @@ TEST_GROUP_RUNNER(ecc)
#if SOC_ECC_SUPPORT_MOD_MUL
RUN_TEST_CASE(ecc, ecc_mod_multiplication_using_SECP192R1_and_SECP256R1_order_of_curve);
#endif
}

View File

@@ -0,0 +1,3 @@
## IDF Component Manager Manifest File
dependencies:
espressif/ccomp_timer: ">=1.0.0"

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -12,6 +12,7 @@
#include "ecc_impl.h"
#include "hal/ecc_hal.h"
#include "hal/ecc_ll.h"
#include "soc/soc_caps.h"
static void esp_ecc_acquire_hardware(void)
{
@@ -44,6 +45,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);
#ifdef SOC_ECC_CONSTANT_TIME_POINT_MUL
/* Enable constant-time point multiplication operations for the ECC hardware accelerator
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);
#endif /* SOC_ECC_CONSTANT_TIME_POINT_MUL */
ecc_hal_start_calc();
memset(result, 0, sizeof(ecc_point_t));

View File

@@ -943,6 +943,10 @@ config SOC_SHA_SUPPORT_SHA256
bool
default y
config SOC_ECC_CONSTANT_TIME_POINT_MUL
bool
default y
config SOC_ECDSA_SUPPORT_EXPORT_PUBKEY
bool
default y

View File

@@ -396,6 +396,9 @@
#define SOC_SHA_SUPPORT_SHA224 (1)
#define SOC_SHA_SUPPORT_SHA256 (1)
/*--------------------------- ECC CAPS ---------------------------------------*/
#define SOC_ECC_CONSTANT_TIME_POINT_MUL 1
/*--------------------------- ECDSA CAPS ---------------------------------------*/
#define SOC_ECDSA_SUPPORT_EXPORT_PUBKEY (1)

View File

@@ -523,6 +523,10 @@ config SOC_SHA_SUPPORT_SHA256
bool
default y
config SOC_ECC_CONSTANT_TIME_POINT_MUL
bool
default y
config SOC_ECDSA_SUPPORT_EXPORT_PUBKEY
bool
default y

View File

@@ -288,6 +288,9 @@
#define SOC_SHA_SUPPORT_SHA224 (1)
#define SOC_SHA_SUPPORT_SHA256 (1)
/*--------------------------- ECC CAPS ---------------------------------------*/
#define SOC_ECC_CONSTANT_TIME_POINT_MUL 1
/*--------------------------- ECDSA CAPS ---------------------------------------*/
#define SOC_ECDSA_SUPPORT_EXPORT_PUBKEY (1)
#define SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE (1)