Skip to content

Commit bfd4085

Browse files
committed
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
2 parents bd08297 + e1cd5b9 commit bfd4085

File tree

15 files changed

+182
-18
lines changed

15 files changed

+182
-18
lines changed

components/esp_security/Kconfig

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,17 @@ menu "ESP Security Specific"
3737
default 3 if ESP_CRYPTO_DPA_PROTECTION_LEVEL_HIGH
3838
endmenu
3939

40+
config ESP_CRYPTO_FORCE_ECC_CONSTANT_TIME_POINT_MUL
41+
bool "Forcfully enable ECC constant time point multiplication operations"
42+
depends on SOC_ECC_CONSTANT_TIME_POINT_MUL
43+
default N
44+
help
45+
If enabled, the app startup code will burn the ECC_FORCE_CONST_TIME efuse bit to force the
46+
ECC peripheral to always perform constant time point multiplication operations,
47+
irrespective of the ECC_MULT_SECURITY_MODE status bit that is present in the ECC_MULT_CONF_REG
48+
register. By default, ESP-IDF configures the ECC peripheral to perform constant time point
49+
multiplication operations, so enabling this config would provide security enhancement only in
50+
the cases when trusted boot is not enabled and the attacker tries carrying out non-constant
51+
time point multiplication operations by changing the default ESP-IDF configurations.
52+
Performing constant time operations protect the ECC multiplication operations from timing attacks.
4053
endmenu

components/esp_security/src/esp_dpa_protection.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,12 @@ static inline void esp_crypto_dpa_set_level(esp_crypto_dpa_sec_level_t level)
1616
REG_SET_FIELD(HP_SYSTEM_SEC_DPA_CONF_REG, HP_SYSTEM_SEC_DPA_LEVEL, level);
1717
}
1818

19+
#if CONFIG_ESP_CRYPTO_DPA_PROTECTION_AT_STARTUP
1920
void esp_crypto_dpa_protection_startup(void)
2021
{
2122
esp_crypto_dpa_set_level(CONFIG_ESP_CRYPTO_DPA_PROTECTION_LEVEL);
2223
}
24+
#endif
2325

2426
void esp_crypto_dpa_protection_enable(esp_crypto_dpa_sec_level_t level)
2527
{

components/esp_security/src/esp_security_priv.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55
*/
66

77
#pragma once
8+
#include "sdkconfig.h"
89

910
/* Private interface file */
1011

12+
#if CONFIG_ESP_CRYPTO_DPA_PROTECTION_AT_STARTUP
1113
void esp_crypto_dpa_protection_startup(void);
14+
#endif

components/esp_security/src/init.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,30 @@
77
#include "esp_private/startup_internal.h"
88
#include "sdkconfig.h"
99
#include "esp_crypto_clk.h"
10+
#include "esp_efuse.h"
11+
#include "esp_efuse_table.h"
1012
#include "esp_security_priv.h"
13+
#include "esp_err.h"
14+
15+
__attribute__((unused)) static const char *TAG = "esp_security";
1116

1217
ESP_SYSTEM_INIT_FN(esp_security_init, SECONDARY, BIT(0), 103)
1318
{
1419
esp_crypto_clk_init();
1520
#if CONFIG_ESP_CRYPTO_DPA_PROTECTION_AT_STARTUP
1621
esp_crypto_dpa_protection_startup();
1722
#endif
23+
24+
#ifdef CONFIG_ESP_CRYPTO_FORCE_ECC_CONSTANT_TIME_POINT_MUL
25+
if (!esp_efuse_read_field_bit(ESP_EFUSE_ECC_FORCE_CONST_TIME)) {
26+
ESP_EARLY_LOGD(TAG, "Forcefully enabling ECC constant time operations");
27+
esp_err_t err = esp_efuse_write_field_bit(ESP_EFUSE_ECC_FORCE_CONST_TIME);
28+
if (err != ESP_OK) {
29+
ESP_EARLY_LOGE(TAG, "Enabling ECC constant time operations forcefully failed.");
30+
return err;
31+
}
32+
}
33+
#endif
1834
return ESP_OK;
1935
}
2036

components/hal/ecc_hal.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -177,3 +177,10 @@ int ecc_hal_read_mod_op_result(uint8_t *r, uint16_t len)
177177
}
178178

179179
#endif /* SOC_ECC_EXTENDED_MODES_SUPPORTED */
180+
181+
#ifdef SOC_ECC_CONSTANT_TIME_POINT_MUL
182+
void ecc_hal_enable_constant_time_point_mul(bool enable)
183+
{
184+
ecc_ll_enable_constant_time_point_mul(enable);
185+
}
186+
#endif /* SOC_ECC_CONSTANT_TIME_POINT_MUL */

components/hal/esp32c5/include/hal/ecc_ll.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,15 @@ static inline void ecc_ll_set_mod_base(ecc_mod_base_t base)
148148
}
149149
}
150150

151+
static inline void ecc_ll_enable_constant_time_point_mul(bool enable)
152+
{
153+
if (enable) {
154+
REG_SET_BIT(ECC_MULT_CONF_REG, ECC_MULT_SECURITY_MODE);
155+
} else {
156+
REG_CLR_BIT(ECC_MULT_CONF_REG, ECC_MULT_SECURITY_MODE);
157+
}
158+
}
159+
151160
static inline void ecc_ll_write_param(ecc_ll_param_t param, const uint8_t *buf, uint16_t len)
152161
{
153162
uint32_t reg;

components/hal/esp32c61/include/hal/ecc_ll.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,15 @@ static inline void ecc_ll_set_mod_base(ecc_mod_base_t base)
148148
}
149149
}
150150

151+
static inline void ecc_ll_enable_constant_time_point_mul(bool enable)
152+
{
153+
if (enable) {
154+
REG_SET_BIT(ECC_MULT_CONF_REG, ECC_MULT_SECURITY_MODE);
155+
} else {
156+
REG_CLR_BIT(ECC_MULT_CONF_REG, ECC_MULT_SECURITY_MODE);
157+
}
158+
}
159+
151160
static inline void ecc_ll_write_param(ecc_ll_param_t param, const uint8_t *buf, uint16_t len)
152161
{
153162
uint32_t reg;

components/hal/include/hal/ecc_hal.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -195,6 +195,15 @@ int ecc_hal_read_mod_op_result(uint8_t *r, uint16_t len);
195195

196196
#endif /* SOC_ECC_EXTENDED_MODES_SUPPORTED */
197197

198+
#ifdef SOC_ECC_CONSTANT_TIME_POINT_MUL
199+
/**
200+
* @brief Enable constant time multiplication operations
201+
*
202+
* @param true: enable; false: disable
203+
*/
204+
void ecc_hal_enable_constant_time_point_mul(bool enable);
205+
#endif /* SOC_ECC_CONSTANT_TIME_POINT_MUL */
206+
198207
#ifdef __cplusplus
199208
}
200209
#endif

components/hal/test_apps/crypto/main/ecc/test_ecc.c

Lines changed: 85 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
/*
2-
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: CC0-1.0
55
*/
66

77
#include <stdio.h>
88
#include <stdbool.h>
99
#include <string.h>
10+
#include <sys/param.h>
1011
#include "sdkconfig.h"
1112
#include "esp_private/esp_crypto_lock_internal.h"
1213
#include "esp_log.h"
@@ -17,8 +18,8 @@
1718

1819
#include "memory_checks.h"
1920
#include "unity_fixture.h"
21+
#include "ccomp_timer.h"
2022

21-
#define _DEBUG_ 0
2223
#define SOC_ECC_SUPPORT_POINT_MULT 1
2324
#define SOC_ECC_SUPPORT_POINT_VERIFY 1
2425

@@ -86,6 +87,9 @@ static void ecc_point_mul(const uint8_t *k_le, const uint8_t *x_le, const uint8_
8687
} else {
8788
ecc_hal_set_mode(ECC_MODE_POINT_MUL);
8889
}
90+
#ifdef SOC_ECC_CONSTANT_TIME_POINT_MUL
91+
ecc_hal_enable_constant_time_point_mul(true);
92+
#endif /* SOC_ECC_CONSTANT_TIME_POINT_MUL */
8993
ecc_hal_start_calc();
9094

9195
while (!ecc_hal_is_calc_finished()) {
@@ -118,13 +122,11 @@ static void test_ecc_point_mul_inner(bool verify_first)
118122
ecc_be_to_le(ecc_p256_mul_res_x, x_mul_le, 32);
119123
ecc_be_to_le(ecc_p256_mul_res_y, y_mul_le, 32);
120124

121-
#if _DEBUG_
122-
ESP_LOG_BUFFER_HEX("Expected X:", x_mul_le, 32);
123-
ESP_LOG_BUFFER_HEX("Got X:", x_res_le, 32);
125+
ESP_LOG_BUFFER_HEXDUMP("Expected X:", x_mul_le, 32, ESP_LOG_DEBUG);
126+
ESP_LOG_BUFFER_HEXDUMP("Got X:", x_res_le, 32, ESP_LOG_DEBUG);
124127

125-
ESP_LOG_BUFFER_HEX("Expected Y:", y_mul_le, 32);
126-
ESP_LOG_BUFFER_HEX("Got Y:", y_res_le, 32);
127-
#endif
128+
ESP_LOG_BUFFER_HEXDUMP("Expected Y:", y_mul_le, 32, ESP_LOG_DEBUG);
129+
ESP_LOG_BUFFER_HEXDUMP("Got Y:", y_res_le, 32, ESP_LOG_DEBUG);
128130

129131
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(x_mul_le, x_res_le, 32, "X coordinate of P256 point multiplication ");
130132
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)
144146
ecc_be_to_le(ecc_p192_mul_res_x, x_mul_le, 24);
145147
ecc_be_to_le(ecc_p192_mul_res_y, y_mul_le, 24);
146148

147-
#if _DEBUG_
148-
ESP_LOG_BUFFER_HEX("Expected X:", x_mul_le, 32);
149-
ESP_LOG_BUFFER_HEX("Got X:", x_res_le, 32);
149+
ESP_LOG_BUFFER_HEXDUMP("Expected X:", x_mul_le, 32, ESP_LOG_DEBUG);
150+
ESP_LOG_BUFFER_HEXDUMP("Got X:", x_res_le, 32, ESP_LOG_DEBUG);
150151

151-
ESP_LOG_BUFFER_HEX("Expected Y:", y_mul_le, 32);
152-
ESP_LOG_BUFFER_HEX("Got Y:", y_res_le, 32);
153-
#endif
152+
ESP_LOG_BUFFER_HEXDUMP("Expected Y:", y_mul_le, 32, ESP_LOG_DEBUG);
153+
ESP_LOG_BUFFER_HEXDUMP("Got Y:", y_res_le, 32, ESP_LOG_DEBUG);
154154

155155
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(x_mul_le, x_res_le, 24, "X coordinate of P192 point multiplication ");
156156
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)
160160
{
161161
test_ecc_point_mul_inner(false);
162162
}
163+
164+
#if SOC_ECC_CONSTANT_TIME_POINT_MUL
165+
166+
#define CONST_TIME_DEVIATION_PERCENT 0.002
167+
168+
static void test_ecc_point_mul_inner_constant_time(void)
169+
{
170+
uint8_t scalar_le[32];
171+
uint8_t x_le[32];
172+
uint8_t y_le[32];
173+
174+
/* P256 */
175+
ecc_be_to_le(ecc_p256_scalar, scalar_le, 32);
176+
ecc_be_to_le(ecc_p256_point_x, x_le, 32);
177+
ecc_be_to_le(ecc_p256_point_y, y_le, 32);
178+
179+
uint8_t x_res_le[32];
180+
uint8_t y_res_le[32];
181+
182+
double deviation = 0;
183+
uint32_t elapsed_time, mean_elapsed_time, total_elapsed_time = 0;
184+
uint32_t max_time = 0, min_time = UINT32_MAX;
185+
int loop_count = 10;
186+
187+
for (int i = 0; i < loop_count; i++) {
188+
ccomp_timer_start();
189+
ecc_point_mul(scalar_le, x_le, y_le, 32, 0, x_res_le, y_res_le);
190+
elapsed_time = ccomp_timer_stop();
191+
192+
max_time = MAX(elapsed_time, max_time);
193+
min_time = MIN(elapsed_time, min_time);
194+
total_elapsed_time += elapsed_time;
195+
}
196+
mean_elapsed_time = total_elapsed_time / loop_count;
197+
deviation = ((double)(max_time - mean_elapsed_time) / mean_elapsed_time);
198+
199+
TEST_ASSERT_LESS_THAN_DOUBLE(CONST_TIME_DEVIATION_PERCENT, deviation);
200+
201+
/* P192 */
202+
ecc_be_to_le(ecc_p192_scalar, scalar_le, 24);
203+
ecc_be_to_le(ecc_p192_point_x, x_le, 24);
204+
ecc_be_to_le(ecc_p192_point_y, y_le, 24);
205+
206+
max_time = 0;
207+
min_time = UINT32_MAX;
208+
total_elapsed_time = 0;
209+
210+
for (int i = 0; i < loop_count; i++) {
211+
ccomp_timer_start();
212+
ecc_point_mul(scalar_le, x_le, y_le, 24, 0, x_res_le, y_res_le);
213+
elapsed_time = ccomp_timer_stop();
214+
215+
max_time = MAX(elapsed_time, max_time);
216+
min_time = MIN(elapsed_time, min_time);
217+
total_elapsed_time += elapsed_time;
218+
}
219+
mean_elapsed_time = total_elapsed_time / loop_count;
220+
deviation = ((double)(max_time - mean_elapsed_time) / mean_elapsed_time);
221+
222+
TEST_ASSERT_LESS_THAN_DOUBLE(CONST_TIME_DEVIATION_PERCENT, deviation);
223+
}
224+
225+
TEST(ecc, ecc_point_multiplication_const_time_check_on_SECP192R1_and_SECP256R1)
226+
{
227+
test_ecc_point_mul_inner_constant_time();
228+
}
229+
#endif
230+
163231
#endif
164232

165233
#if SOC_ECC_SUPPORT_POINT_VERIFY && !defined(SOC_ECC_SUPPORT_POINT_VERIFY_QUIRK)
@@ -493,6 +561,9 @@ TEST_GROUP_RUNNER(ecc)
493561
{
494562
#if SOC_ECC_SUPPORT_POINT_MULT
495563
RUN_TEST_CASE(ecc, ecc_point_multiplication_on_SECP192R1_and_SECP256R1);
564+
#if SOC_ECC_CONSTANT_TIME_POINT_MUL
565+
RUN_TEST_CASE(ecc, ecc_point_multiplication_const_time_check_on_SECP192R1_and_SECP256R1);
566+
#endif
496567
#endif
497568

498569
#if SOC_ECC_SUPPORT_POINT_VERIFY && !defined(SOC_ECC_SUPPORT_POINT_VERIFY_QUIRK)
@@ -534,5 +605,4 @@ TEST_GROUP_RUNNER(ecc)
534605
#if SOC_ECC_SUPPORT_MOD_MUL
535606
RUN_TEST_CASE(ecc, ecc_mod_multiplication_using_SECP192R1_and_SECP256R1_order_of_curve);
536607
#endif
537-
538608
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
## IDF Component Manager Manifest File
2+
dependencies:
3+
espressif/ccomp_timer: ">=1.0.0"

0 commit comments

Comments
 (0)