diff --git a/components/bt/CMakeLists.txt b/components/bt/CMakeLists.txt index 5c38b2d89e..9b69e13e0c 100644 --- a/components/bt/CMakeLists.txt +++ b/components/bt/CMakeLists.txt @@ -643,6 +643,7 @@ if(CONFIG_BT_ENABLED) if(NOT (CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS OR CONFIG_BT_NIMBLE_CRYPTO_STACK_MBEDTLS)) list(APPEND include_dirs common/tinycrypt/include + common/tinycrypt/port ) list(APPEND srcs "common/tinycrypt/src/utils.c" "common/tinycrypt/src/sha256.c" @@ -658,7 +659,8 @@ if(CONFIG_BT_ENABLED) "common/tinycrypt/src/hmac_prng.c" "common/tinycrypt/src/ecc_platform_specific.c" "common/tinycrypt/src/hmac.c" - "common/tinycrypt/src/cbc_mode.c") + "common/tinycrypt/src/cbc_mode.c" + "common/tinycrypt/port/esp_tinycrypt_port.c") endif() if(CONFIG_BT_NIMBLE_ENABLED) diff --git a/components/bt/common/tinycrypt/port/esp_tinycrypt_port.c b/components/bt/common/tinycrypt/port/esp_tinycrypt_port.c new file mode 100644 index 0000000000..c4424c56eb --- /dev/null +++ b/components/bt/common/tinycrypt/port/esp_tinycrypt_port.c @@ -0,0 +1,87 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "esp_tinycrypt_port.h" + +#include "esp_crypto_lock.h" +#include "esp_private/esp_crypto_lock_internal.h" + +#if SOC_ECC_SUPPORTED +#include "hal/ecc_hal.h" +#include "hal/ecc_ll.h" +#endif /* SOC_ECC_SUPPORTED */ + + +#if SOC_ECC_SUPPORTED +static void esp_tinycrypt_acquire_ecc_hardware(void) +{ + esp_crypto_ecc_lock_acquire(); + + ECC_RCC_ATOMIC() { + ecc_ll_enable_bus_clock(true); + ecc_ll_power_up(); + ecc_ll_reset_register(); + } +} + +static void esp_tinycrypt_release_ecc_hardware(void) +{ + ECC_RCC_ATOMIC() { + ecc_ll_enable_bus_clock(false); + ecc_ll_power_down(); + } + + esp_crypto_ecc_lock_release(); +} + +int esp_tinycrypt_verify_ecc_point(const uint8_t *pk_x, const uint8_t *pk_y, uint8_t length) +{ + int result; + + esp_tinycrypt_acquire_ecc_hardware(); + + ecc_hal_write_verify_param(pk_x, pk_y, length); + ecc_hal_set_mode(ECC_MODE_VERIFY); + ecc_hal_start_calc(); + while (!ecc_hal_is_calc_finished()); + result = ecc_hal_read_verify_result(); + + esp_tinycrypt_release_ecc_hardware(); + + if (result == 1) { + return 0; + } else { + return -1; + } +} + +int esp_tinycrypt_calc_ecc_mult(const uint8_t *p_x, const uint8_t *p_y, const uint8_t *scalar, + uint8_t *r_x, uint8_t *r_y, uint8_t num_bytes, bool verify_first) +{ + int ret = -1; + ecc_mode_t work_mode = verify_first ? ECC_MODE_VERIFY_THEN_POINT_MUL : ECC_MODE_POINT_MUL; + + esp_tinycrypt_acquire_ecc_hardware(); + + ecc_hal_write_mul_param(scalar, p_x, p_y, num_bytes); + 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(); + + while (!ecc_hal_is_calc_finished()); + + ret = ecc_hal_read_mul_result(r_x, r_y, num_bytes); + + esp_tinycrypt_release_ecc_hardware(); + + return ret; +} +#endif /* SOC_ECC_SUPPORTED */ diff --git a/components/bt/common/tinycrypt/port/esp_tinycrypt_port.h b/components/bt/common/tinycrypt/port/esp_tinycrypt_port.h new file mode 100644 index 0000000000..4fdf82c2f9 --- /dev/null +++ b/components/bt/common/tinycrypt/port/esp_tinycrypt_port.h @@ -0,0 +1,15 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include "soc/soc_caps.h" + +#if SOC_ECC_SUPPORTED +int esp_tinycrypt_verify_ecc_point(const uint8_t *pk_x, const uint8_t *pk_y, uint8_t length); + +int esp_tinycrypt_calc_ecc_mult(const uint8_t *p_x, const uint8_t *p_y, const uint8_t *scalar, + uint8_t *r_x, uint8_t *r_y, uint8_t num_bytes, bool verify_first); +#endif /* SOC_ECC_SUPPORTED */ diff --git a/components/bt/common/tinycrypt/src/ecc.c b/components/bt/common/tinycrypt/src/ecc.c index 97737882e4..1027c9a293 100644 --- a/components/bt/common/tinycrypt/src/ecc.c +++ b/components/bt/common/tinycrypt/src/ecc.c @@ -59,6 +59,9 @@ #include #include #include +#include + +#include "esp_tinycrypt_port.h" /* IMPORTANT: Make sure a cryptographically-secure PRNG is set and the platform * has access to enough entropy in order to feed the PRNG regularly. */ @@ -639,6 +642,7 @@ void apply_z(uECC_word_t * X1, uECC_word_t * Y1, const uECC_word_t * const Z, uECC_vli_modMult_fast(Y1, Y1, t1, curve); /* y1 * z^3 */ } +#if !SOC_ECC_SUPPORTED /* P = (x1, y1) => 2P, (x2, y2) => P' */ static void XYcZ_initial_double(uECC_word_t * X1, uECC_word_t * Y1, uECC_word_t * X2, uECC_word_t * Y2, @@ -662,31 +666,6 @@ static void XYcZ_initial_double(uECC_word_t * X1, uECC_word_t * Y1, apply_z(X2, Y2, z, curve); } -void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1, - uECC_word_t * X2, uECC_word_t * Y2, - uECC_Curve curve) -{ - /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */ - uECC_word_t t5[NUM_ECC_WORDS]; - wordcount_t num_words = curve->num_words; - - uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */ - uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = (x2 - x1)^2 = A */ - uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = x1*A = B */ - uECC_vli_modMult_fast(X2, X2, t5, curve); /* t3 = x2*A = C */ - uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */ - uECC_vli_modSquare_fast(t5, Y2, curve); /* t5 = (y2 - y1)^2 = D */ - - uECC_vli_modSub(t5, t5, X1, curve->p, num_words); /* t5 = D - B */ - uECC_vli_modSub(t5, t5, X2, curve->p, num_words); /* t5 = D - B - C = x3 */ - uECC_vli_modSub(X2, X2, X1, curve->p, num_words); /* t3 = C - B */ - uECC_vli_modMult_fast(Y1, Y1, X2, curve); /* t2 = y1*(C - B) */ - uECC_vli_modSub(X2, X1, t5, curve->p, num_words); /* t3 = B - x3 */ - uECC_vli_modMult_fast(Y2, Y2, X2, curve); /* t4 = (y2 - y1)*(B - x3) */ - uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y3 */ - - uECC_vli_set(X2, t5, num_words); -} /* Input P = (x1, y1, Z), Q = (x2, y2, Z) Output P + Q = (x3, y3, Z3), P - Q = (x3', y3', Z3) @@ -729,12 +708,49 @@ static void XYcZ_addC(uECC_word_t * X1, uECC_word_t * Y1, uECC_vli_set(X1, t7, num_words); } +#endif /* !SOC_ECC_SUPPORTED */ + +void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1, + uECC_word_t * X2, uECC_word_t * Y2, + uECC_Curve curve) +{ + /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */ + uECC_word_t t5[NUM_ECC_WORDS]; + wordcount_t num_words = curve->num_words; + + uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */ + uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = (x2 - x1)^2 = A */ + uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = x1*A = B */ + uECC_vli_modMult_fast(X2, X2, t5, curve); /* t3 = x2*A = C */ + uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */ + uECC_vli_modSquare_fast(t5, Y2, curve); /* t5 = (y2 - y1)^2 = D */ + + uECC_vli_modSub(t5, t5, X1, curve->p, num_words); /* t5 = D - B */ + uECC_vli_modSub(t5, t5, X2, curve->p, num_words); /* t5 = D - B - C = x3 */ + uECC_vli_modSub(X2, X2, X1, curve->p, num_words); /* t3 = C - B */ + uECC_vli_modMult_fast(Y1, Y1, X2, curve); /* t2 = y1*(C - B) */ + uECC_vli_modSub(X2, X1, t5, curve->p, num_words); /* t3 = B - x3 */ + uECC_vli_modMult_fast(Y2, Y2, X2, curve); /* t4 = (y2 - y1)*(B - x3) */ + uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y3 */ + + uECC_vli_set(X2, t5, num_words); +} void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point, const uECC_word_t * scalar, const uECC_word_t * initial_Z, bitcount_t num_bits, uECC_Curve curve) { +#if SOC_ECC_SUPPORTED + wordcount_t num_words = curve->num_words; + + /* Only p256r1 is supported currently. */ + assert (curve == uECC_secp256r1()); + + esp_tinycrypt_calc_ecc_mult((const uint8_t *)&point[0], (const uint8_t *)&point[num_words], + (uint8_t *)scalar, (uint8_t *)&result[0], (uint8_t *)&result[num_words], + num_words * uECC_WORD_SIZE, false); +#else /* R0 and R1 */ uECC_word_t Rx[2][NUM_ECC_WORDS]; uECC_word_t Ry[2][NUM_ECC_WORDS]; @@ -773,6 +789,7 @@ void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point, uECC_vli_set(result, Rx[0], num_words); uECC_vli_set(result + num_words, Ry[0], num_words); +#endif /* SOC_ECC_SUPPORTED */ } uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0, @@ -866,8 +883,6 @@ int uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top, int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve) { - uECC_word_t tmp1[NUM_ECC_WORDS]; - uECC_word_t tmp2[NUM_ECC_WORDS]; wordcount_t num_words = curve->num_words; /* The point at infinity is invalid. */ @@ -881,19 +896,34 @@ int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve) return -2; } +#if SOC_ECC_SUPPORTED + /* Only p256r1 is supported currently. */ + if (curve != uECC_secp256r1()) { + return -5; + } + + if (esp_tinycrypt_verify_ecc_point((const uint8_t *)&point[0], + (const uint8_t *)&point[num_words], + num_words * uECC_WORD_SIZE)) { + return -3; + } +#else + uECC_word_t tmp1[NUM_ECC_WORDS]; + uECC_word_t tmp2[NUM_ECC_WORDS]; + uECC_vli_modSquare_fast(tmp1, point + num_words, curve); curve->x_side(tmp2, point, curve); /* tmp2 = x^3 + ax + b */ /* Make sure that y^2 == x^3 + ax + b */ if (uECC_vli_equal(tmp1, tmp2, num_words) != 0) return -3; +#endif /* SOC_ECC_SUPPORTED */ return 0; } int uECC_valid_public_key(const uint8_t *public_key, uECC_Curve curve) { - uECC_word_t _public[NUM_ECC_WORDS * 2]; uECC_vli_bytesToNative(_public, public_key, curve->num_bytes); @@ -912,7 +942,6 @@ int uECC_valid_public_key(const uint8_t *public_key, uECC_Curve curve) int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key, uECC_Curve curve) { - uECC_word_t _private[NUM_ECC_WORDS]; uECC_word_t _public[NUM_ECC_WORDS * 2];