mirror of
https://github.com/espressif/esp-idf.git
synced 2026-09-22 13:01:16 +03:00
Merge branch 'bugfix/fix_nimble_issue_2608' into 'release/v5.2'
fix(nimble): Fix few nimble issues 2608 (v5.2) See merge request espressif/esp-idf!52110
This commit is contained in:
@@ -1,24 +1,47 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "esp_tinycrypt_port.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "esp_crypto_lock.h"
|
||||
#include "esp_private/esp_crypto_lock_internal.h"
|
||||
#include <tinycrypt/ecc.h>
|
||||
|
||||
#if SOC_ECC_SUPPORTED
|
||||
#include "hal/ecc_hal.h"
|
||||
#include "hal/ecc_ll.h"
|
||||
#endif /* SOC_ECC_SUPPORTED */
|
||||
|
||||
#define ECC_MAX_PARAM_BYTES 48
|
||||
|
||||
#if SOC_ECC_SUPPORTED
|
||||
static void esp_tinycrypt_acquire_ecc_hardware(void)
|
||||
static void uecc_vli_native_to_le(uint8_t *le, const uECC_word_t *native, uint16_t len)
|
||||
{
|
||||
uint8_t be[ECC_MAX_PARAM_BYTES];
|
||||
|
||||
uECC_vli_nativeToBytes(be, len, native);
|
||||
for (uint16_t i = 0; i < len; i++) {
|
||||
le[i] = be[len - 1 - i];
|
||||
}
|
||||
}
|
||||
|
||||
static void uecc_vli_le_to_native(uECC_word_t *native, const uint8_t *le, uint16_t len)
|
||||
{
|
||||
uint8_t be[ECC_MAX_PARAM_BYTES];
|
||||
|
||||
for (uint16_t i = 0; i < len; i++) {
|
||||
be[i] = le[len - 1 - i];
|
||||
}
|
||||
uECC_vli_bytesToNative(native, be, len);
|
||||
}
|
||||
|
||||
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();
|
||||
@@ -26,23 +49,29 @@ static void esp_tinycrypt_acquire_ecc_hardware(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void esp_tinycrypt_release_ecc_hardware(void)
|
||||
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();
|
||||
}
|
||||
#endif /* SOC_ECC_SUPPORTED */
|
||||
|
||||
int esp_tinycrypt_verify_ecc_point(const uint8_t *pk_x, const uint8_t *pk_y, uint8_t length)
|
||||
{
|
||||
#if SOC_ECC_SUPPORTED
|
||||
int result;
|
||||
uint8_t px_le[ECC_MAX_PARAM_BYTES];
|
||||
uint8_t py_le[ECC_MAX_PARAM_BYTES];
|
||||
|
||||
uecc_vli_native_to_le(px_le, (const uECC_word_t *)pk_x, length);
|
||||
uecc_vli_native_to_le(py_le, (const uECC_word_t *)pk_y, length);
|
||||
|
||||
esp_tinycrypt_acquire_ecc_hardware();
|
||||
|
||||
ecc_hal_write_verify_param(pk_x, pk_y, length);
|
||||
ecc_hal_write_verify_param(px_le, py_le, length);
|
||||
ecc_hal_set_mode(ECC_MODE_VERIFY);
|
||||
ecc_hal_start_calc();
|
||||
while (!ecc_hal_is_calc_finished());
|
||||
@@ -55,17 +84,40 @@ int esp_tinycrypt_verify_ecc_point(const uint8_t *pk_x, const uint8_t *pk_y, uin
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
(void)pk_x;
|
||||
(void)pk_y;
|
||||
(void)length;
|
||||
return -1;
|
||||
#endif /* SOC_ECC_SUPPORTED */
|
||||
}
|
||||
|
||||
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 esp_tinycrypt_calc_ecc_mult(const uECC_word_t *point_x, const uECC_word_t *point_y,
|
||||
const uECC_word_t *scalar, uECC_word_t *result_x,
|
||||
uECC_word_t *result_y, uint8_t num_bytes, bool verify_first)
|
||||
{
|
||||
int ret = -1;
|
||||
#if SOC_ECC_SUPPORTED
|
||||
int ret;
|
||||
ecc_mode_t work_mode = verify_first ? ECC_MODE_VERIFY_THEN_POINT_MUL : ECC_MODE_POINT_MUL;
|
||||
uint8_t k_le[ECC_MAX_PARAM_BYTES];
|
||||
uint8_t px_le[ECC_MAX_PARAM_BYTES];
|
||||
uint8_t py_le[ECC_MAX_PARAM_BYTES];
|
||||
uint8_t rx_le[ECC_MAX_PARAM_BYTES];
|
||||
uint8_t ry_le[ECC_MAX_PARAM_BYTES];
|
||||
|
||||
memset(k_le, 0, sizeof(k_le));
|
||||
memset(px_le, 0, sizeof(px_le));
|
||||
memset(py_le, 0, sizeof(py_le));
|
||||
memset(rx_le, 0, sizeof(rx_le));
|
||||
memset(ry_le, 0, sizeof(ry_le));
|
||||
|
||||
uecc_vli_native_to_le(k_le, scalar, num_bytes);
|
||||
uecc_vli_native_to_le(px_le, point_x, num_bytes);
|
||||
uecc_vli_native_to_le(py_le, point_y, num_bytes);
|
||||
|
||||
esp_tinycrypt_acquire_ecc_hardware();
|
||||
|
||||
ecc_hal_write_mul_param(scalar, p_x, p_y, num_bytes);
|
||||
ecc_hal_write_mul_param(k_le, px_le, py_le, num_bytes);
|
||||
ecc_hal_set_mode(work_mode);
|
||||
/*
|
||||
* Enable constant-time point multiplication operations for the ECC hardware accelerator,
|
||||
@@ -78,10 +130,25 @@ int esp_tinycrypt_calc_ecc_mult(const uint8_t *p_x, const uint8_t *p_y, const ui
|
||||
|
||||
while (!ecc_hal_is_calc_finished());
|
||||
|
||||
ret = ecc_hal_read_mul_result(r_x, r_y, num_bytes);
|
||||
ret = ecc_hal_read_mul_result(rx_le, ry_le, num_bytes);
|
||||
|
||||
esp_tinycrypt_release_ecc_hardware();
|
||||
|
||||
return ret;
|
||||
}
|
||||
if (ret != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
uecc_vli_le_to_native(result_x, rx_le, num_bytes);
|
||||
uecc_vli_le_to_native(result_y, ry_le, num_bytes);
|
||||
return 0;
|
||||
#else
|
||||
(void)point_x;
|
||||
(void)point_y;
|
||||
(void)scalar;
|
||||
(void)result_x;
|
||||
(void)result_y;
|
||||
(void)num_bytes;
|
||||
(void)verify_first;
|
||||
return -1;
|
||||
#endif /* SOC_ECC_SUPPORTED */
|
||||
}
|
||||
|
||||
@@ -1,15 +1,20 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#if SOC_ECC_SUPPORTED
|
||||
#include <tinycrypt/ecc.h>
|
||||
|
||||
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);
|
||||
int esp_tinycrypt_calc_ecc_mult(const uECC_word_t *point_x, const uECC_word_t *point_y,
|
||||
const uECC_word_t *scalar, uECC_word_t *result_x,
|
||||
uECC_word_t *result_y, uint8_t num_bytes, bool verify_first);
|
||||
#endif /* SOC_ECC_SUPPORTED */
|
||||
|
||||
@@ -663,8 +663,6 @@ 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 || SOC_ESP_NIMBLE_CONTROLLER
|
||||
/* Keep ESP32-C6 on the software micro-ecc path for BLE SC compatibility. */
|
||||
/* 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,
|
||||
@@ -730,7 +728,6 @@ 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,
|
||||
@@ -763,16 +760,24 @@ void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point,
|
||||
const uECC_word_t * initial_Z,
|
||||
bitcount_t num_bits, uECC_Curve curve)
|
||||
{
|
||||
#if SOC_ECC_SUPPORTED && !SOC_ESP_NIMBLE_CONTROLLER
|
||||
wordcount_t num_words = curve->num_words;
|
||||
#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
|
||||
/*
|
||||
* The ECC peripheral accepts canonical scalars only. Calls using the
|
||||
* regularized software scalar use one additional bit and must stay on
|
||||
* the software ladder.
|
||||
*/
|
||||
if (initial_Z == 0 && num_bits == curve->num_n_bits &&
|
||||
curve == uECC_secp256r1()) {
|
||||
if (esp_tinycrypt_calc_ecc_mult(point, point + num_words, scalar,
|
||||
result, result + num_words,
|
||||
num_words * uECC_WORD_SIZE, false) == 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif /* SOC_ECC_SUPPORTED */
|
||||
{
|
||||
/* R0 and R1 */
|
||||
uECC_word_t Rx[2][NUM_ECC_WORDS];
|
||||
uECC_word_t Ry[2][NUM_ECC_WORDS];
|
||||
@@ -811,7 +816,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,
|
||||
@@ -847,22 +852,29 @@ uECC_word_t EccPoint_compute_public_key(uECC_word_t *result,
|
||||
uECC_word_t *private_key,
|
||||
uECC_Curve curve)
|
||||
{
|
||||
#if !SOC_ECC_SUPPORTED || SOC_ESP_NIMBLE_CONTROLLER
|
||||
#if SOC_ECC_SUPPORTED
|
||||
/*
|
||||
* The ECC peripheral requires a canonical scalar. regularize_k()
|
||||
* produces k + n or k + 2n for the software constant-time ladder,
|
||||
* which is mathematically equivalent but outside the HW input range.
|
||||
*/
|
||||
if (curve == uECC_secp256r1()) {
|
||||
EccPoint_mult(result, curve->G, private_key, 0,
|
||||
curve->num_n_bits, curve);
|
||||
return !EccPoint_isZero(result, curve);
|
||||
}
|
||||
#endif /* SOC_ECC_SUPPORTED */
|
||||
|
||||
uECC_word_t tmp1[NUM_ECC_WORDS];
|
||||
uECC_word_t tmp2[NUM_ECC_WORDS];
|
||||
uECC_word_t tmp2[NUM_ECC_WORDS];
|
||||
uECC_word_t *p2[2] = {tmp1, tmp2};
|
||||
uECC_word_t carry;
|
||||
#endif
|
||||
|
||||
#if SOC_ECC_SUPPORTED && !SOC_ESP_NIMBLE_CONTROLLER
|
||||
EccPoint_mult(result, curve->G, private_key, 0, curve->num_n_bits, curve);
|
||||
#else
|
||||
/* Regularize the bitcount for the private key so that attackers cannot
|
||||
* use a side channel attack to learn the number of leading zeros. */
|
||||
carry = regularize_k(private_key, tmp1, tmp2, curve);
|
||||
|
||||
EccPoint_mult(result, curve->G, p2[!carry], 0, curve->num_n_bits + 1, curve);
|
||||
#endif
|
||||
|
||||
if (EccPoint_isZero(result, curve)) {
|
||||
return 0;
|
||||
@@ -936,17 +948,15 @@ int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve)
|
||||
}
|
||||
|
||||
#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
|
||||
if (curve == uECC_secp256r1()) {
|
||||
if (esp_tinycrypt_verify_ecc_point((const uint8_t *)&point[0],
|
||||
(const uint8_t *)&point[num_words],
|
||||
num_words * uECC_WORD_SIZE) == 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif /* SOC_ECC_SUPPORTED */
|
||||
{
|
||||
uECC_word_t tmp1[NUM_ECC_WORDS];
|
||||
uECC_word_t tmp2[NUM_ECC_WORDS];
|
||||
|
||||
@@ -954,9 +964,10 @@ int uECC_valid_point(const uECC_word_t *point, uECC_Curve 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)
|
||||
if (uECC_vli_equal(tmp1, tmp2, num_words) != 0) {
|
||||
return -3;
|
||||
#endif /* SOC_ECC_SUPPORTED */
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -147,11 +147,9 @@ int uECC_shared_secret(const uint8_t *public_key, const uint8_t *private_key,
|
||||
uECC_word_t _private[NUM_ECC_WORDS];
|
||||
|
||||
uECC_word_t tmp[NUM_ECC_WORDS];
|
||||
#if !SOC_ECC_SUPPORTED
|
||||
uECC_word_t *p2[2] = {_private, tmp};
|
||||
uECC_word_t *initial_Z = 0;
|
||||
uECC_word_t carry;
|
||||
#endif
|
||||
wordcount_t num_words = curve->num_words;
|
||||
wordcount_t num_bytes = curve->num_bytes;
|
||||
int r;
|
||||
@@ -167,11 +165,11 @@ int uECC_shared_secret(const uint8_t *public_key, const uint8_t *private_key,
|
||||
public_key + num_bytes,
|
||||
num_bytes);
|
||||
|
||||
#if SOC_ECC_SUPPORTED
|
||||
EccPoint_mult(_public, _public, _private, 0, curve->num_n_bits, curve);
|
||||
#else
|
||||
/* Regularize the bitcount for the private key so that attackers cannot use a
|
||||
* side channel attack to learn the number of leading zeros. */
|
||||
/*
|
||||
* Use the software ladder for ECDH. Its regularized scalar is unsuitable
|
||||
* for the ECC peripheral, and EccPoint_mult() can otherwise silently fall
|
||||
* back to the software ladder with an unregularized scalar.
|
||||
*/
|
||||
carry = regularize_k(_private, _private, tmp, curve);
|
||||
|
||||
/* If an RNG function was specified, try to get a random initial Z value to
|
||||
@@ -187,17 +185,14 @@ int uECC_shared_secret(const uint8_t *public_key, const uint8_t *private_key,
|
||||
|
||||
EccPoint_mult(_public, _public, p2[!carry], initial_Z, curve->num_n_bits + 1,
|
||||
curve);
|
||||
#endif
|
||||
|
||||
uECC_vli_nativeToBytes(secret, num_bytes, _public);
|
||||
r = !EccPoint_isZero(_public, curve);
|
||||
|
||||
clear_and_out:
|
||||
/* erasing temporary buffer used to store secret: */
|
||||
#if !SOC_ECC_SUPPORTED
|
||||
memset(p2, 0, sizeof(p2));
|
||||
__asm__ __volatile__("" :: "g"(p2) : "memory");
|
||||
#endif
|
||||
memset(_public, 0, sizeof(_public));
|
||||
__asm__ __volatile__("" :: "g"(_public) : "memory");
|
||||
memset(tmp, 0, sizeof(tmp));
|
||||
|
||||
@@ -101,10 +101,8 @@ int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash,
|
||||
|
||||
uECC_word_t tmp[NUM_ECC_WORDS];
|
||||
uECC_word_t s[NUM_ECC_WORDS];
|
||||
#if !SOC_ECC_SUPPORTED
|
||||
uECC_word_t *k2[2] = {tmp, s};
|
||||
uECC_word_t carry;
|
||||
#endif
|
||||
uECC_word_t p[NUM_ECC_WORDS * 2];
|
||||
wordcount_t num_words = curve->num_words;
|
||||
wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
|
||||
@@ -116,12 +114,8 @@ int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if SOC_ECC_SUPPORTED
|
||||
EccPoint_mult(p, curve->G, k, 0, num_n_bits, curve);
|
||||
#else
|
||||
carry = regularize_k(k, tmp, s, curve);
|
||||
EccPoint_mult(p, curve->G, k2[!carry], 0, num_n_bits + 1, curve);
|
||||
#endif
|
||||
if (uECC_vli_isZero(p, num_words)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1262,6 +1262,14 @@ menu "Extra Features"
|
||||
instead of DRAM (.iram.text/.text in internal RAM). Suitable for low-speed
|
||||
GAP/GATT operations to reduce RAM usage.
|
||||
|
||||
config BT_NIMBLE_GAP_ALLOW_ADV_RESTART
|
||||
bool "Allow restarting ongoing advertising"
|
||||
default n
|
||||
help
|
||||
If enabled, stop ongoing advertising before starting it again with
|
||||
new parameters,if any. If disabled, starting advertising while it is already
|
||||
active returns BLE_HS_EALREADY.
|
||||
|
||||
endmenu
|
||||
|
||||
menu "NimBLE Mesh"
|
||||
|
||||
Submodule components/bt/host/nimble/nimble updated: 44dcef6d6e...133a0d4ba4
@@ -2304,4 +2304,12 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_GAP_ALLOW_ADV_RESTART
|
||||
#ifdef CONFIG_BT_NIMBLE_GAP_ALLOW_ADV_RESTART
|
||||
#define MYNEWT_VAL_BLE_GAP_ALLOW_ADV_RESTART CONFIG_BT_NIMBLE_GAP_ALLOW_ADV_RESTART
|
||||
#else
|
||||
#define MYNEWT_VAL_BLE_GAP_ALLOW_ADV_RESTART (0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -18,6 +18,10 @@
|
||||
#define BLE_PAWR_RSP_SLOT_SPACING (10) /*!< Time between response slots (N * 0.125 ms) */
|
||||
#define BLE_PAWR_NUM_RSP_SLOTS (25) /*!< Number of subevent response slots */
|
||||
#define BLE_PAWR_SUB_DATA_LEN (20)
|
||||
/* Give the controller a few periodic intervals to report the outcome of a
|
||||
* synchronized connection attempt before retrying from another subevent.
|
||||
*/
|
||||
#define BLE_PAWR_CONN_TIMEOUT_MS (3 * BLE_PAWR_EVENT_PERIODIC_INTERVAL_MS)
|
||||
|
||||
#define TAG "NimBLE_BLE_PAwR_CONN"
|
||||
|
||||
@@ -162,7 +166,7 @@ gap_event_cb(struct ble_gap_event *event, void *arg)
|
||||
phy_mask = 0x01;
|
||||
|
||||
if (conn == 0) {
|
||||
rc = ble_gap_connect_with_synced(own_addr_type,adv_handle,subevent,&peer_addr,30000,phy_mask,NULL,NULL,NULL,gap_event_cb,NULL);
|
||||
rc = ble_gap_connect_with_synced(own_addr_type,adv_handle,subevent,&peer_addr,BLE_PAWR_CONN_TIMEOUT_MS,phy_mask,NULL,NULL,NULL,gap_event_cb,NULL);
|
||||
if (rc != 0 ) {
|
||||
ESP_LOGI(TAG,"Error: Failed to connect to device , rc = %d\n",rc);
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user