Merge branch 'espressif:release/v5.5' into release/v5.5

This commit is contained in:
Jason2866
2026-02-08 23:31:37 +01:00
committed by GitHub
269 changed files with 5942 additions and 1769 deletions
@@ -69,7 +69,7 @@ idf_build_set_property(__OUTPUT_SDKCONFIG 0)
set(LD_DEFAULT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/main/ld/${IDF_TARGET}")
idf_build_set_property(BOOTLOADER_LINKER_SCRIPT "${LD_DEFAULT_PATH}/bootloader.rom.ld" APPEND)
project(bootloader)
if(CONFIG_ESP32P4_REV_MIN_300)
if(CONFIG_IDF_TARGET_ESP32P4 AND NOT CONFIG_ESP32P4_SELECTS_REV_LESS_V3)
target_linker_script("__idf_main" INTERFACE "${LD_DEFAULT_PATH}/bootloader.rev3.ld")
else()
target_linker_script("__idf_main" INTERFACE "${LD_DEFAULT_PATH}/bootloader.ld")
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -537,16 +537,8 @@ static esp_err_t bootloader_flash_read_allow_decrypt(size_t src_addr, void *dest
esp_err_t bootloader_flash_read(size_t src_addr, void *dest, size_t size, bool allow_decrypt)
{
if (src_addr & 3) {
ESP_EARLY_LOGE(TAG, "bootloader_flash_read src_addr 0x%x not 4-byte aligned", src_addr);
return ESP_FAIL;
}
if (size & 3) {
ESP_EARLY_LOGE(TAG, "bootloader_flash_read size 0x%x not 4-byte aligned", size);
return ESP_FAIL;
}
if ((intptr_t)dest & 3) {
ESP_EARLY_LOGE(TAG, "bootloader_flash_read dest 0x%x not 4-byte aligned", (intptr_t)dest);
if ((src_addr & 3) || (size & 3) || ((intptr_t)dest & 3)) {
ESP_EARLY_LOGE(TAG, "bootloader_flash_read src_addr 0x%x, size 0x%x or dest 0x%x not 4-byte aligned", src_addr, size, (intptr_t)dest);
return ESP_FAIL;
}
@@ -210,8 +210,7 @@ void esp_flash_encryption_set_release_mode(void)
#endif // CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES_128_DERIVED
#endif // !CONFIG_IDF_TARGET_ESP32
#if !(CONFIG_IDF_TARGET_ESP32P4 && CONFIG_ESP32P4_REV_MIN_FULL < 300)
#ifdef SOC_FLASH_ENCRYPTION_XTS_AES_SUPPORT_PSEUDO_ROUND
#if SOC_FLASH_ENCRYPTION_XTS_AES_SUPPORT_PSEUDO_ROUND && !CONFIG_ESP32P4_SELECTS_REV_LESS_V3
if (spi_flash_encrypt_ll_is_pseudo_rounds_function_supported()) {
uint8_t xts_pseudo_level = 0;
esp_efuse_read_field_blob(ESP_EFUSE_XTS_DPA_PSEUDO_LEVEL, &xts_pseudo_level, ESP_EFUSE_XTS_DPA_PSEUDO_LEVEL[0]->bit_count);
@@ -222,7 +221,6 @@ void esp_flash_encryption_set_release_mode(void)
}
}
#endif
#endif
#ifdef CONFIG_IDF_TARGET_ESP32
esp_efuse_write_field_bit(ESP_EFUSE_WR_DIS_DIS_CACHE);
#else
@@ -484,8 +482,7 @@ bool esp_flash_encryption_cfg_verify_release_mode(void)
}
result &= secure;
#if !(CONFIG_IDF_TARGET_ESP32P4 && CONFIG_ESP32P4_REV_MIN_FULL < 300)
#if SOC_FLASH_ENCRYPTION_XTS_AES_SUPPORT_PSEUDO_ROUND
#if SOC_FLASH_ENCRYPTION_XTS_AES_SUPPORT_PSEUDO_ROUND && !CONFIG_ESP32P4_SELECTS_REV_LESS_V3
if (spi_flash_encrypt_ll_is_pseudo_rounds_function_supported()) {
uint8_t xts_pseudo_level = 0;
esp_efuse_read_field_blob(ESP_EFUSE_XTS_DPA_PSEUDO_LEVEL, &xts_pseudo_level, ESP_EFUSE_XTS_DPA_PSEUDO_LEVEL[0]->bit_count);
@@ -494,7 +491,6 @@ bool esp_flash_encryption_cfg_verify_release_mode(void)
ESP_LOGW(TAG, "Not enabled XTS-AES pseudo rounds function (set XTS_DPA_PSEUDO_LEVEL->1 or more)");
}
}
#endif
#endif
return result;
}
+49 -25
View File
@@ -29,7 +29,6 @@ set(common_include_dirs
set(ble_mesh_include_dirs
"esp_ble_mesh/common/include"
"esp_ble_mesh/common/tinycrypt/include"
"esp_ble_mesh/core"
"esp_ble_mesh/core/include"
"esp_ble_mesh/core/storage"
@@ -42,6 +41,10 @@ set(ble_mesh_include_dirs
"esp_ble_mesh/api"
)
set(ble_mesh_tinycrypt_dirs
"esp_ble_mesh/common/tinycrypt/include"
)
set(ble_mesh_v11_include_dirs
"esp_ble_mesh/lib/include"
"esp_ble_mesh/v1.1/api/core/include"
@@ -546,21 +549,6 @@ if(CONFIG_BT_ENABLED)
"esp_ble_mesh/btc/btc_ble_mesh_prov.c"
"esp_ble_mesh/btc/btc_ble_mesh_sensor_model.c"
"esp_ble_mesh/btc/btc_ble_mesh_time_scene_model.c"
"esp_ble_mesh/common/tinycrypt/src/aes_decrypt.c"
"esp_ble_mesh/common/tinycrypt/src/aes_encrypt.c"
"esp_ble_mesh/common/tinycrypt/src/cbc_mode.c"
"esp_ble_mesh/common/tinycrypt/src/ccm_mode.c"
"esp_ble_mesh/common/tinycrypt/src/cmac_mode.c"
"esp_ble_mesh/common/tinycrypt/src/ctr_mode.c"
"esp_ble_mesh/common/tinycrypt/src/ctr_prng.c"
"esp_ble_mesh/common/tinycrypt/src/ecc_dh.c"
"esp_ble_mesh/common/tinycrypt/src/ecc_dsa.c"
"esp_ble_mesh/common/tinycrypt/src/ecc_platform_specific.c"
"esp_ble_mesh/common/tinycrypt/src/ecc.c"
"esp_ble_mesh/common/tinycrypt/src/hmac_prng.c"
"esp_ble_mesh/common/tinycrypt/src/hmac.c"
"esp_ble_mesh/common/tinycrypt/src/sha256.c"
"esp_ble_mesh/common/tinycrypt/src/utils.c"
"esp_ble_mesh/common/atomic.c"
"esp_ble_mesh/common/buf.c"
"esp_ble_mesh/common/common.c"
@@ -568,8 +556,21 @@ if(CONFIG_BT_ENABLED)
"esp_ble_mesh/common/mutex.c"
"esp_ble_mesh/common/queue.c"
"esp_ble_mesh/common/timer.c"
"esp_ble_mesh/common/utils.c"
"esp_ble_mesh/core/storage/settings_nvs.c"
"esp_ble_mesh/common/utils.c")
# Select crypto implementation based on config
if(CONFIG_BT_SMP_CRYPTO_STACK_TINYCRYPT OR
CONFIG_BT_SMP_CRYPTO_STACK_NATIVE)
list(APPEND srcs "esp_ble_mesh/common/crypto_tc.c")
elseif(CONFIG_BT_SMP_CRYPTO_STACK_MBEDTLS)
if(CONFIG_MBEDTLS_VER_4_X_SUPPORT)
list(APPEND srcs "esp_ble_mesh/common/crypto_psa.c")
else()
list(APPEND srcs "esp_ble_mesh/common/crypto_mbedtls.c")
endif()
endif()
list(APPEND srcs "esp_ble_mesh/core/storage/settings_nvs.c"
"esp_ble_mesh/core/storage/settings_uid.c"
"esp_ble_mesh/core/storage/settings.c"
"esp_ble_mesh/core/access.c"
@@ -610,6 +611,26 @@ if(CONFIG_BT_ENABLED)
"esp_ble_mesh/models/server/state_binding.c"
"esp_ble_mesh/models/server/state_transition.c"
"esp_ble_mesh/models/server/time_scene_server.c")
if(CONFIG_BT_SMP_CRYPTO_STACK_NATIVE)
list(APPEND include_dirs ${ble_mesh_tinycrypt_dirs})
list(APPEND srcs
"esp_ble_mesh/common/tinycrypt/src/aes_decrypt.c"
"esp_ble_mesh/common/tinycrypt/src/aes_encrypt.c"
"esp_ble_mesh/common/tinycrypt/src/cbc_mode.c"
"esp_ble_mesh/common/tinycrypt/src/ccm_mode.c"
"esp_ble_mesh/common/tinycrypt/src/cmac_mode.c"
"esp_ble_mesh/common/tinycrypt/src/ctr_mode.c"
"esp_ble_mesh/common/tinycrypt/src/ctr_prng.c"
"esp_ble_mesh/common/tinycrypt/src/ecc_dh.c"
"esp_ble_mesh/common/tinycrypt/src/ecc_dsa.c"
"esp_ble_mesh/common/tinycrypt/src/ecc_platform_specific.c"
"esp_ble_mesh/common/tinycrypt/src/ecc.c"
"esp_ble_mesh/common/tinycrypt/src/hmac_prng.c"
"esp_ble_mesh/common/tinycrypt/src/hmac.c"
"esp_ble_mesh/common/tinycrypt/src/sha256.c"
"esp_ble_mesh/common/tinycrypt/src/utils.c")
endif()
if(CONFIG_BLE_MESH_V11_SUPPORT)
list(APPEND include_dirs ${ble_mesh_v11_include_dirs})
@@ -1084,26 +1105,29 @@ if(CONFIG_BT_ENABLED)
endif()
if(CONFIG_BLE_MESH_V11_SUPPORT)
set(BLE_MESH_LIB_NAME "libble_mesh.a")
if(CONFIG_IDF_TARGET_ESP32)
add_prebuilt_library(ble_mesh "esp_ble_mesh/lib/lib/esp32/libble_mesh.a")
add_prebuilt_library(ble_mesh "esp_ble_mesh/lib/lib/esp32/${BLE_MESH_LIB_NAME}")
target_link_libraries(${COMPONENT_LIB} PRIVATE ble_mesh)
elseif(CONFIG_IDF_TARGET_ESP32S3)
add_prebuilt_library(ble_mesh "esp_ble_mesh/lib/lib/esp32s3/libble_mesh.a")
add_prebuilt_library(ble_mesh "esp_ble_mesh/lib/lib/esp32s3/${BLE_MESH_LIB_NAME}")
target_link_libraries(${COMPONENT_LIB} PRIVATE ble_mesh)
elseif(CONFIG_IDF_TARGET_ESP32C3)
add_prebuilt_library(ble_mesh "esp_ble_mesh/lib/lib/esp32c3/libble_mesh.a")
add_prebuilt_library(ble_mesh "esp_ble_mesh/lib/lib/esp32c3/${BLE_MESH_LIB_NAME}")
target_link_libraries(${COMPONENT_LIB} PRIVATE ble_mesh)
elseif(CONFIG_IDF_TARGET_ESP32C6)
add_prebuilt_library(ble_mesh "esp_ble_mesh/lib/lib/esp32c6/libble_mesh.a")
add_prebuilt_library(ble_mesh "esp_ble_mesh/lib/lib/esp32c6/${BLE_MESH_LIB_NAME}")
target_link_libraries(${COMPONENT_LIB} PRIVATE ble_mesh)
elseif(CONFIG_IDF_TARGET_ESP32C61)
add_prebuilt_library(ble_mesh "esp_ble_mesh/lib/lib/esp32c61/libble_mesh.a")
add_prebuilt_library(ble_mesh "esp_ble_mesh/lib/lib/esp32c61/${BLE_MESH_LIB_NAME}")
target_link_libraries(${COMPONENT_LIB} PRIVATE ble_mesh)
elseif(CONFIG_IDF_TARGET_ESP32H2)
add_prebuilt_library(ble_mesh "esp_ble_mesh/lib/lib/esp32h2/libble_mesh.a")
add_prebuilt_library(ble_mesh "esp_ble_mesh/lib/lib/esp32h2/${BLE_MESH_LIB_NAME}")
target_link_libraries(${COMPONENT_LIB} PRIVATE ble_mesh)
elseif(CONFIG_IDF_TARGET_ESP32C5)
add_prebuilt_library(ble_mesh "esp_ble_mesh/lib/lib/esp32c5/libble_mesh.a")
add_prebuilt_library(ble_mesh "esp_ble_mesh/lib/lib/esp32c5/${BLE_MESH_LIB_NAME}")
target_link_libraries(${COMPONENT_LIB} PRIVATE ble_mesh)
endif()
endif()
+1 -1
View File
@@ -9,7 +9,7 @@ config BT_ALARM_MAX_NUM
choice BT_SMP_CRYPTO_STACK
prompt "SMP cryptographic stack"
depends on (BT_BLE_SMP_ENABLE || BT_SMP_ENABLE || BT_NIMBLE_SECURITY_ENABLE)
default BT_SMP_CRYPTO_STACK_NATIVE
default BT_SMP_CRYPTO_STACK_TINYCRYPT
help
Select the cryptographic library to use for SMP operations (AES, AES-CMAC, ECDH P-256).
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -61,6 +61,7 @@ int ble_compressed_log_cb_get(uint8_t source, ble_cp_log_buffer_mgmt_t **mgmt)
{
#if CONFIG_BLE_MESH_COMPRESSED_LOG_ENABLE
case BLE_COMPRESSED_LOG_OUT_SOURCE_MESH:
case BLE_COMPRESSED_LOG_OUT_SOURCE_MESH_LIB:
buffer_mgmt = BUF_MGMT_NAME(mesh);
last_handle = &mesh_last_task_handle;
break;
@@ -102,23 +103,10 @@ static inline int ble_compressed_log_buffer_free(ble_cp_log_buffer_mgmt_t *mgmt)
return 0;
}
int ble_log_compressed_hex_print(uint8_t source, uint32_t log_index, size_t args_cnt, ...)
static inline
int ble_log_compressed_hex_print_internal(ble_cp_log_buffer_mgmt_t *mgmt, uint32_t log_index, size_t args_cnt, va_list args)
{
ble_cp_log_buffer_mgmt_t *mgmt = NULL;
uint8_t arg_type = 0;
va_list args;
ble_compressed_log_cb_get(source, &mgmt);
if (args_cnt == 0) {
ble_log_cp_push_u8(mgmt, LOG_HEADER(LOG_TYPE_HEX_ARGS, 0));
ble_log_cp_push_u16(mgmt, log_index);
ble_compressed_log_output(source, mgmt->buffer, mgmt->idx);
ble_compressed_log_buffer_free(mgmt);
return 0;
}
va_start(args, args_cnt);
ble_log_cp_push_u8(mgmt, LOG_HEADER(LOG_TYPE_HEX_ARGS, args_cnt));
ble_log_cp_push_u16(mgmt, log_index);
@@ -142,7 +130,7 @@ int ble_log_compressed_hex_print(uint8_t source, uint32_t log_index, size_t args
}
if (arg_type >= ARG_SIZE_TYPE_MAX) {
printf("Found invalid arg type %08lx type %d", log_index, arg_type);
assert(0);
return 0;
}
}
@@ -232,10 +220,43 @@ int ble_log_compressed_hex_print(uint8_t source, uint32_t log_index, size_t args
break;
}
}
return 0;
}
int ble_log_compressed_hex_printv(uint8_t source, uint32_t log_index, size_t args_cnt, va_list args)
{
ble_cp_log_buffer_mgmt_t *mgmt = NULL;
if (ble_compressed_log_cb_get(source, &mgmt)) {
return 0;
}
ble_log_compressed_hex_print_internal(mgmt, log_index, args_cnt, args);
ble_compressed_log_output(source, mgmt->buffer, mgmt->idx);
ble_compressed_log_buffer_free(mgmt);
return 0;
}
int ble_log_compressed_hex_print(uint8_t source, uint32_t log_index, size_t args_cnt, ...)
{
ble_cp_log_buffer_mgmt_t *mgmt = NULL;
if (ble_compressed_log_cb_get(source, &mgmt)) {
return 0;
}
if (args_cnt == 0) {
ble_log_cp_push_u8(mgmt, LOG_HEADER(LOG_TYPE_HEX_ARGS, 0));
ble_log_cp_push_u16(mgmt, log_index);
} else {
va_list args;
va_start(args, args_cnt);
ble_log_compressed_hex_print_internal(mgmt, log_index, args_cnt, args);
va_end(args);
}
ble_compressed_log_output(source, mgmt->buffer, mgmt->idx);
ble_compressed_log_buffer_free(mgmt);
va_end(args);
return 0;
}
@@ -243,7 +264,9 @@ int ble_log_compressed_hex_print_buf(uint8_t source, uint32_t log_index, uint8_t
{
ble_cp_log_buffer_mgmt_t *mgmt = NULL;
ble_compressed_log_cb_get(source, &mgmt);
if (ble_compressed_log_cb_get(source, &mgmt)) {
return 0;
}
if (buf == NULL && len != 0) {
ble_log_cp_push_u8(mgmt, LOG_HEADER(LOG_TYPE_INFO, LOG_TYPE_INFO_NULL_BUF));
@@ -7,6 +7,7 @@
#define _BLE_LOG_COMPRESSION_UTILS_H
#include "ble_log.h"
#include <stdio.h>
#define CONCAT(a, b) a##b
#define _CONCAT(a, b) CONCAT(a, b)
@@ -47,6 +48,7 @@
enum {
BLE_COMPRESSED_LOG_OUT_SOURCE_HOST,
BLE_COMPRESSED_LOG_OUT_SOURCE_MESH,
BLE_COMPRESSED_LOG_OUT_SOURCE_MESH_LIB,
};
enum {
@@ -195,11 +195,6 @@ config BTDM_CTRL_BR_EDR_MAX_ACL_CONN_EFF
default BTDM_CTRL_BR_EDR_MAX_ACL_CONN if BTDM_CTRL_MODE_BR_EDR_ONLY || BTDM_CTRL_MODE_BTDM
default 0
config BTDM_CTRL_BR_EDR_MAX_SYNC_CONN_EFF
int
default BTDM_CTRL_BR_EDR_MAX_SYNC_CONN if BTDM_CTRL_MODE_BR_EDR_ONLY || BTDM_CTRL_MODE_BTDM
default 0
choice BTDM_CTRL_PINNED_TO_CORE_CHOICE
prompt "The cpu core which bluetooth controller run"
depends on !FREERTOS_UNICORE
+1 -1
View File
@@ -1674,7 +1674,7 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
}
//overwrite some parameters
cfg->bt_max_sync_conn = CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN_EFF;
cfg->bt_max_sync_conn = UT_BR_EDR_CTRL_MAX_SYNC_CONN_EFF;
cfg->magic = ESP_BT_CONTROLLER_CONFIG_MAGIC_VAL;
if (((cfg->mode & ESP_BT_MODE_BLE) && (cfg->ble_max_conn <= 0 || cfg->ble_max_conn > BTDM_CONTROLLER_BLE_MAX_CONN_LIMIT))
@@ -0,0 +1,33 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "sdkconfig.h"
#ifdef __cplusplus
extern "C" {
#endif
#if defined(CONFIG_BT_BLUEDROID_ENABLED) && (CONFIG_BT_BLUEDROID_ENABLED) && (CONFIG_BT_HFP_ENABLE) && \
defined(CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN) && (CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN == 0)
#pragma message ("BT: forcing BR/EDR max sync conn eff to 1 (Bluedroid HFP requires SCO/eSCO)")
#define UT_BR_EDR_CTRL_MAX_SYNC_CONN_EFF (1)
#elif defined(CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN)
#define UT_BR_EDR_CTRL_MAX_SYNC_CONN_EFF (CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN)
#else
#define UT_BR_EDR_CTRL_MAX_SYNC_CONN_EFF (0)
#endif
#ifdef __cplusplus
}
#endif
+24 -1
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -27,6 +27,11 @@ void extAdv_stack_deinitEnv(void);
int extAdv_stack_enable(void);
void extAdv_stack_disable(void);
int scan_stack_initEnv(void);
void scan_stack_deinitEnv(void);
int scan_stack_enable(void);
void scan_stack_disable(void);
int sync_stack_initEnv(void);
void sync_stack_deinitEnv(void);
int sync_stack_enable(void);
@@ -84,6 +89,12 @@ void winWiden_stack_enableSetConstPeerScaVsCmd(bool en);
void adv_stack_enableScanReqRxdVsEvent(bool en);
void conn_stack_enableChanMapUpdCompVsEvent(bool en);
void sleep_stack_enableWakeupVsEvent(bool en);
#if DEFAULT_BT_SCAN_ALLOW_ENH_ADI_FILTER
void scan_stack_enableSetScanADIOnlyFilterVsCmd(bool en);
#endif // DEFAULT_BT_SCAN_ALLOW_ENH_ADI_FILTER
#if DEFAULT_BT_ADV_SEND_CONSTANT_DID
void extAdv_stack_setExtAdvConstantDidVsCmd(bool en);
#endif // DEFAULT_BT_ADV_SEND_CONSTANT_DID
#endif // (CONFIG_BT_NIMBLE_ENABLED || CONFIG_BT_BLUEDROID_ENABLED)
#if CONFIG_BT_LE_RXBUF_OPT_ENABLED
extern void mmgmt_enableRxbufOptFeature(void);
@@ -136,6 +147,11 @@ int ble_stack_initEnv(void)
return rc;
}
rc = scan_stack_initEnv();
if (rc) {
return rc;
}
rc = sync_stack_initEnv();
if (rc) {
return rc;
@@ -210,6 +226,7 @@ void ble_stack_deinitEnv(void)
#endif // CONFIG_BT_LE_DTM_ENABLED
sync_stack_deinitEnv();
scan_stack_deinitEnv();
extAdv_stack_deinitEnv();
adv_stack_deinitEnv();
base_stack_deinitEnv();
@@ -234,6 +251,11 @@ int ble_stack_enable(void)
return rc;
}
rc = scan_stack_enable();
if (rc) {
return rc;
}
rc = sync_stack_enable();
if (rc) {
return rc;
@@ -302,6 +324,7 @@ void ble_stack_disable(void)
dtm_stack_disable();
#endif // CONFIG_BT_LE_DTM_ENABLED
sync_stack_disable();
scan_stack_disable();
extAdv_stack_disable();
adv_stack_disable();
base_stack_disable();
+13 -1
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -50,6 +50,16 @@ extern "C" {
#else
#define DEFAULT_BT_LE_PAWR_SUPPORTED (0)
#endif // CONFIG_BT_NIMBLE_PERIODIC_ADV_WITH_RESPONSES
#if CONFIG_BT_NIMBLE_ADV_SEND_CONSTANT_DID
#define DEFAULT_BT_ADV_SEND_CONSTANT_DID (1)
#else
#define DEFAULT_BT_ADV_SEND_CONSTANT_DID (0)
#endif // CONFIG_BT_NIMBLE_ADV_SEND_CONSTANT_DID
#if CONFIG_BT_NIMBLE_SCAN_ALLOW_ENH_ADI_FILTER
#define DEFAULT_BT_SCAN_ALLOW_ENH_ADI_FILTER (1)
#else
#define DEFAULT_BT_SCAN_ALLOW_ENH_ADI_FILTER (0)
#endif // CONFIG_BT_NIMBLE_SCAN_ALLOW_ENH_ADI_FILTER
#else
#if CONFIG_BT_LE_LL_CFG_FEAT_LE_CODED_PHY
@@ -155,6 +165,8 @@ extern "C" {
#define DEFAULT_BT_LE_HCI_UART_CTS_PIN (-1)
#define DEFAULT_BT_LE_HCI_UART_RTS_PIN (-1)
#endif
#define DEFAULT_BT_ADV_SEND_CONSTANT_DID (0)
#define DEFAULT_BT_SCAN_ALLOW_ENH_ADI_FILTER (0)
#endif
#define DEFAULT_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF CONFIG_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF
+35 -1
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -27,6 +27,16 @@ void extAdv_stack_deinitEnv(void);
int extAdv_stack_enable(void);
void extAdv_stack_disable(void);
int scan_stack_initEnv(void);
void scan_stack_deinitEnv(void);
int scan_stack_enable(void);
void scan_stack_disable(void);
int scan_stack_initEnv(void);
void scan_stack_deinitEnv(void);
int scan_stack_enable(void);
void scan_stack_disable(void);
int sync_stack_initEnv(void);
void sync_stack_deinitEnv(void);
int sync_stack_enable(void);
@@ -84,6 +94,12 @@ void winWiden_stack_enableSetConstPeerScaVsCmd(bool en);
void adv_stack_enableScanReqRxdVsEvent(bool en);
void conn_stack_enableChanMapUpdCompVsEvent(bool en);
void sleep_stack_enableWakeupVsEvent(bool en);
#if DEFAULT_BT_SCAN_ALLOW_ENH_ADI_FILTER
void scan_stack_enableSetScanADIOnlyFilterVsCmd(bool en);
#endif // DEFAULT_BT_SCAN_ALLOW_ENH_ADI_FILTER
#if DEFAULT_BT_ADV_SEND_CONSTANT_DID
void extAdv_stack_setExtAdvConstantDidVsCmd(bool en);
#endif // DEFAULT_BT_ADV_SEND_CONSTANT_DID
#endif // (CONFIG_BT_NIMBLE_ENABLED || CONFIG_BT_BLUEDROID_ENABLED)
#if CONFIG_BT_LE_RXBUF_OPT_ENABLED
extern void mmgmt_enableRxbufOptFeature(void);
@@ -104,6 +120,12 @@ void ble_stack_enableVsCmds(bool en)
log_stack_enableLogsRelatedVsCmd(en);
hci_stack_enableSetVsEvtMaskVsCmd(en);
winWiden_stack_enableSetConstPeerScaVsCmd(en);
#if DEFAULT_BT_SCAN_ALLOW_ENH_ADI_FILTER
scan_stack_enableSetScanADIOnlyFilterVsCmd(en);
#endif // DEFAULT_BT_SCAN_ALLOW_ENH_ADI_FILTER
#if DEFAULT_BT_ADV_SEND_CONSTANT_DID
extAdv_stack_setExtAdvConstantDidVsCmd(en);
#endif // DEFAULT_BT_ADV_SEND_CONSTANT_DID
}
void ble_stack_enableVsEvents(bool en)
@@ -136,6 +158,11 @@ int ble_stack_initEnv(void)
return rc;
}
rc = scan_stack_initEnv();
if (rc) {
return rc;
}
rc = sync_stack_initEnv();
if (rc) {
return rc;
@@ -210,6 +237,7 @@ void ble_stack_deinitEnv(void)
#endif // CONFIG_BT_LE_DTM_ENABLED
sync_stack_deinitEnv();
scan_stack_deinitEnv();
extAdv_stack_deinitEnv();
adv_stack_deinitEnv();
base_stack_deinitEnv();
@@ -234,6 +262,11 @@ int ble_stack_enable(void)
return rc;
}
rc = scan_stack_enable();
if (rc) {
return rc;
}
rc = sync_stack_enable();
if (rc) {
return rc;
@@ -302,6 +335,7 @@ void ble_stack_disable(void)
dtm_stack_disable();
#endif // CONFIG_BT_LE_DTM_ENABLED
sync_stack_disable();
scan_stack_disable();
extAdv_stack_disable();
adv_stack_disable();
base_stack_disable();
+13 -1
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -51,6 +51,16 @@ extern "C" {
#else
#define DEFAULT_BT_LE_PAWR_SUPPORTED (0)
#endif // CONFIG_BT_NIMBLE_PERIODIC_ADV_WITH_RESPONSES
#if CONFIG_BT_NIMBLE_ADV_SEND_CONSTANT_DID
#define DEFAULT_BT_ADV_SEND_CONSTANT_DID (1)
#else
#define DEFAULT_BT_ADV_SEND_CONSTANT_DID (0)
#endif // CONFIG_BT_NIMBLE_ADV_SEND_CONSTANT_DID
#if CONFIG_BT_NIMBLE_SCAN_ALLOW_ENH_ADI_FILTER
#define DEFAULT_BT_SCAN_ALLOW_ENH_ADI_FILTER (1)
#else
#define DEFAULT_BT_SCAN_ALLOW_ENH_ADI_FILTER (0)
#endif // CONFIG_BT_NIMBLE_SCAN_ALLOW_ENH_ADI_FILTER
#else
#if CONFIG_BT_LE_LL_CFG_FEAT_LE_CODED_PHY
@@ -158,6 +168,8 @@ extern "C" {
#endif
#define DEFAULT_BT_LE_SUBRATE_ENABLED 0
#define DEFAULT_BT_ADV_SEND_CONSTANT_DID (0)
#define DEFAULT_BT_SCAN_ALLOW_ENH_ADI_FILTER (0)
#endif
#define DEFAULT_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF CONFIG_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF
+22 -1
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -27,6 +27,11 @@ void extAdv_stack_deinitEnv(void);
int extAdv_stack_enable(void);
void extAdv_stack_disable(void);
int scan_stack_initEnv(void);
void scan_stack_deinitEnv(void);
int scan_stack_enable(void);
void scan_stack_disable(void);
int sync_stack_initEnv(void);
void sync_stack_deinitEnv(void);
int sync_stack_enable(void);
@@ -84,6 +89,10 @@ void winWiden_stack_enableSetConstPeerScaVsCmd(bool en);
void adv_stack_enableScanReqRxdVsEvent(bool en);
void conn_stack_enableChanMapUpdCompVsEvent(bool en);
void sleep_stack_enableWakeupVsEvent(bool en);
#if DEFAULT_BT_SCAN_ALLOW_ENH_ADI_FILTER
void scan_stack_enableSetScanADIOnlyFilterVsCmd(bool en);
#endif // DEFAULT_BT_SCAN_ALLOW_ENH_ADI_FILTER
void extAdv_stack_setExtAdvConstantDidVsCmd(bool en);
#endif // (CONFIG_BT_NIMBLE_ENABLED || CONFIG_BT_BLUEDROID_ENABLED)
#if CONFIG_BT_LE_RXBUF_OPT_ENABLED
extern void mmgmt_enableRxbufOptFeature(void);
@@ -136,6 +145,11 @@ int ble_stack_initEnv(void)
return rc;
}
rc = scan_stack_initEnv();
if (rc) {
return rc;
}
rc = sync_stack_initEnv();
if (rc) {
return rc;
@@ -210,6 +224,7 @@ void ble_stack_deinitEnv(void)
#endif // CONFIG_BT_LE_DTM_ENABLED
sync_stack_deinitEnv();
scan_stack_deinitEnv();
extAdv_stack_deinitEnv();
adv_stack_deinitEnv();
base_stack_deinitEnv();
@@ -234,6 +249,11 @@ int ble_stack_enable(void)
return rc;
}
rc = scan_stack_enable();
if (rc) {
return rc;
}
rc = sync_stack_enable();
if (rc) {
return rc;
@@ -302,6 +322,7 @@ void ble_stack_disable(void)
dtm_stack_disable();
#endif // CONFIG_BT_LE_DTM_ENABLED
sync_stack_disable();
scan_stack_disable();
extAdv_stack_disable();
adv_stack_disable();
base_stack_disable();
+13 -1
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -50,6 +50,16 @@ extern "C" {
#else
#define DEFAULT_BT_LE_PAWR_SUPPORTED (0)
#endif // CONFIG_BT_NIMBLE_PERIODIC_ADV_WITH_RESPONSES
#if CONFIG_BT_NIMBLE_ADV_SEND_CONSTANT_DID
#define DEFAULT_BT_ADV_SEND_CONSTANT_DID (1)
#else
#define DEFAULT_BT_ADV_SEND_CONSTANT_DID (0)
#endif // CONFIG_BT_NIMBLE_ADV_SEND_CONSTANT_DID
#if CONFIG_BT_NIMBLE_SCAN_ALLOW_ENH_ADI_FILTER
#define DEFAULT_BT_SCAN_ALLOW_ENH_ADI_FILTER (1)
#else
#define DEFAULT_BT_SCAN_ALLOW_ENH_ADI_FILTER (0)
#endif // CONFIG_BT_NIMBLE_SCAN_ALLOW_ENH_ADI_FILTER
#else
#if CONFIG_BT_LE_LL_CFG_FEAT_LE_CODED_PHY
@@ -155,6 +165,8 @@ extern "C" {
#define DEFAULT_BT_LE_HCI_UART_CTS_PIN (-1)
#define DEFAULT_BT_LE_HCI_UART_RTS_PIN (-1)
#endif
#define DEFAULT_BT_ADV_SEND_CONSTANT_DID (0)
#define DEFAULT_BT_SCAN_ALLOW_ENH_ADI_FILTER (0)
#endif
#define DEFAULT_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF CONFIG_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF
+9
View File
@@ -22,6 +22,15 @@ if BLE_MESH
for mesh packets. And this could help avoid collision of
advertising packets.
config BLE_MESH_USE_UNIFIED_CRYPTO
bool "Use the unified BLE tinycrypt implementation"
depends on !BT_LE_CRYPTO_STACK_MBEDTLS && !BT_NIMBLE_CRYPTO_STACK_MBEDTLS
default y if BT_SMP_CRYPTO_STACK_TINYCRYPT
default n
help
Enable this option to use the unified BLE tinycrypt solution
instead of the default one in BLE Mesh stack.
menuconfig BLE_MESH_USE_BLE_50
bool "Support using BLE 5.0 APIs for BLE Mesh"
depends on BLE_MESH_EXPERIMENTAL
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -67,9 +67,9 @@ esp_err_t esp_ble_mesh_node_prov_disable(esp_ble_mesh_prov_bearer_t bearers);
* So as an unprovisioned device, it should use this function to input
* the Public Key exchanged through the out-of-band mechanism.
*
* @param[in] pub_key_x: Unprovisioned device's Public Key X
* @param[in] pub_key_y: Unprovisioned device's Public Key Y
* @param[in] private_key: Unprovisioned device's Private Key
* @param[in] pub_key_x: Unprovisioned device's Public Key X(Little Endian)
* @param[in] pub_key_y: Unprovisioned device's Public Key Y(Little Endian)
* @param[in] private_key: Unprovisioned device's Private Key(Little Endian)
*
* @return ESP_OK on success or error code otherwise.
*/
@@ -0,0 +1,543 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <errno.h>
#include "esp_random.h"
#include "mbedtls/aes.h"
#include "mbedtls/cmac.h"
#include "mbedtls/md.h"
#include "mbedtls/ecp.h"
#include "mbedtls/ecdh.h"
#include "mbedtls/ccm.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mesh/common.h"
#include "mesh/crypto.h"
#include "mesh/trace.h"
#include "mesh/config.h"
/* ECC key storage
*
* MbedTLS functions expect BIG-ENDIAN format.
*/
static struct {
bool is_ready;
uint8_t private_key[PRIV_KEY_SIZE]; /* Big-endian */
uint8_t public_key[PUB_KEY_SIZE]; /* Big-endian */
} dh_pair;
int bt_mesh_crypto_init(void)
{
memset(&dh_pair, 0, sizeof(dh_pair));
dh_pair.is_ready = false;
return 0;
}
int bt_mesh_encrypt(const struct bt_mesh_key *key, const uint8_t plaintext[16],
uint8_t enc_data[16])
{
mbedtls_aes_context ctx;
int ret;
mbedtls_aes_init(&ctx);
ret = mbedtls_aes_setkey_enc(&ctx, key->key, 128);
if (ret != 0) {
mbedtls_aes_free(&ctx);
return -EIO;
}
ret = mbedtls_aes_crypt_ecb(&ctx, MBEDTLS_AES_ENCRYPT, plaintext, enc_data);
mbedtls_aes_free(&ctx);
return ret == 0 ? 0 : -EIO;
}
int bt_mesh_ccm_encrypt(const struct bt_mesh_key *key, uint8_t nonce[13],
const uint8_t *plaintext, size_t len,
const uint8_t *aad, size_t aad_len,
uint8_t *enc_data, size_t mic_size)
{
mbedtls_ccm_context ctx;
int ret;
mbedtls_ccm_init(&ctx);
ret = mbedtls_ccm_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, key->key, 128);
if (ret != 0) {
mbedtls_ccm_free(&ctx);
return -EIO;
}
ret = mbedtls_ccm_encrypt_and_tag(&ctx, len, nonce, 13, aad, aad_len,
plaintext, enc_data, enc_data + len, mic_size);
mbedtls_ccm_free(&ctx);
return ret == 0 ? 0 : -EIO;
}
int bt_mesh_ccm_decrypt(const struct bt_mesh_key *key, uint8_t nonce[13],
const uint8_t *enc_data, size_t len,
const uint8_t *aad, size_t aad_len,
uint8_t *plaintext, size_t mic_size)
{
mbedtls_ccm_context ctx;
int ret;
mbedtls_ccm_init(&ctx);
ret = mbedtls_ccm_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, key->key, 128);
if (ret != 0) {
mbedtls_ccm_free(&ctx);
return -EIO;
}
ret = mbedtls_ccm_auth_decrypt(&ctx, len, nonce, 13, aad, aad_len,
enc_data, plaintext, enc_data + len, mic_size);
mbedtls_ccm_free(&ctx);
return ret == 0 ? 0 : -EIO;
}
int bt_mesh_ccm_encrypt_raw_key(const uint8_t key[16], uint8_t nonce[13],
const uint8_t *plaintext, size_t len,
const uint8_t *aad, size_t aad_len,
uint8_t *enc_data, size_t mic_size)
{
struct bt_mesh_key mesh_key;
memcpy(mesh_key.key, key, 16);
return bt_mesh_ccm_encrypt(&mesh_key, nonce, plaintext, len, aad, aad_len,
enc_data, mic_size);
}
int bt_mesh_ccm_decrypt_raw_key(const uint8_t key[16], uint8_t nonce[13],
const uint8_t *enc_data, size_t len,
const uint8_t *aad, size_t aad_len,
uint8_t *plaintext, size_t mic_size)
{
struct bt_mesh_key mesh_key;
memcpy(mesh_key.key, key, 16);
return bt_mesh_ccm_decrypt(&mesh_key, nonce, enc_data, len, aad, aad_len,
plaintext, mic_size);
}
int bt_mesh_aes_cmac_mesh_key(const struct bt_mesh_key *key,
struct bt_mesh_sg *sg, size_t sg_len,
uint8_t mac[16])
{
return bt_mesh_aes_cmac_raw_key(key->key, sg, sg_len, mac);
}
int bt_mesh_aes_cmac_raw_key(const uint8_t key[16], struct bt_mesh_sg *sg,
size_t sg_len, uint8_t mac[16])
{
mbedtls_cipher_context_t ctx;
const mbedtls_cipher_info_t *info;
int ret;
info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB);
if (info == NULL) {
return -EIO;
}
mbedtls_cipher_init(&ctx);
ret = mbedtls_cipher_setup(&ctx, info);
if (ret != 0) {
mbedtls_cipher_free(&ctx);
return -EIO;
}
ret = mbedtls_cipher_cmac_starts(&ctx, key, 128);
if (ret != 0) {
mbedtls_cipher_free(&ctx);
return -EIO;
}
for (; sg_len; sg_len--, sg++) {
ret = mbedtls_cipher_cmac_update(&ctx, sg->data, sg->len);
if (ret != 0) {
mbedtls_cipher_free(&ctx);
return -EIO;
}
}
ret = mbedtls_cipher_cmac_finish(&ctx, mac);
mbedtls_cipher_free(&ctx);
return ret == 0 ? 0 : -EIO;
}
int bt_mesh_sha256_hmac_raw_key(const uint8_t key[32], struct bt_mesh_sg *sg,
size_t sg_len, uint8_t mac[32])
{
mbedtls_md_context_t ctx;
const mbedtls_md_info_t *info;
int ret;
info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
if (info == NULL) {
return -EIO;
}
mbedtls_md_init(&ctx);
ret = mbedtls_md_setup(&ctx, info, 1); /* 1 = HMAC mode */
if (ret != 0) {
mbedtls_md_free(&ctx);
return -EIO;
}
ret = mbedtls_md_hmac_starts(&ctx, key, 32);
if (ret != 0) {
mbedtls_md_free(&ctx);
return -EIO;
}
for (; sg_len; sg_len--, sg++) {
ret = mbedtls_md_hmac_update(&ctx, sg->data, sg->len);
if (ret != 0) {
mbedtls_md_free(&ctx);
return -EIO;
}
}
ret = mbedtls_md_hmac_finish(&ctx, mac);
mbedtls_md_free(&ctx);
return ret == 0 ? 0 : -EIO;
}
int bt_mesh_pub_key_gen(void)
{
mbedtls_ecp_group grp;
mbedtls_mpi d;
mbedtls_ecp_point Q;
uint8_t private_key_be[PRIV_KEY_SIZE];
uint8_t public_key_be[PUB_KEY_SIZE];
int ret;
int err;
dh_pair.is_ready = false;
do {
err = bt_mesh_rand(dh_pair.private_key, sizeof(dh_pair.private_key));
if (err) {
BT_ERR("Failed to generate random private key");
return err;
}
/* Ensure the private key is valid (non-zero last bytes in LE) */
} while (dh_pair.private_key[0] == 0 &&
dh_pair.private_key[1] == 0);
mbedtls_ecp_group_init(&grp);
mbedtls_mpi_init(&d);
mbedtls_ecp_point_init(&Q);
ret = mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SECP256R1);
if (ret != 0) {
goto cleanup;
}
/* Read private key into MPI (MbedTLS expects big-endian) */
ret = mbedtls_mpi_read_binary(&d, dh_pair.private_key, PRIV_KEY_SIZE);
if (ret != 0) {
goto cleanup;
}
/* Compute public key: Q = d * G */
ret = mbedtls_ecp_mul(&grp, &Q, &d, &grp.G, NULL, NULL);
if (ret != 0) {
goto cleanup;
}
/* Export public key point in big-endian */
ret = mbedtls_mpi_write_binary(&Q.MBEDTLS_PRIVATE(X), dh_pair.public_key, 32);
if (ret != 0) {
goto cleanup;
}
ret = mbedtls_mpi_write_binary(&Q.MBEDTLS_PRIVATE(Y), dh_pair.public_key + 32, 32);
if (ret != 0) {
goto cleanup;
}
dh_pair.is_ready = true;
cleanup:
mbedtls_ecp_group_free(&grp);
mbedtls_mpi_free(&d);
mbedtls_ecp_point_free(&Q);
return ret == 0 ? 0 : -EIO;
}
const uint8_t *bt_mesh_pub_key_get_raw(void)
{
if (!dh_pair.is_ready) {
if (bt_mesh_pub_key_gen() != 0) {
return NULL;
}
}
return dh_pair.public_key;
}
void bt_mesh_set_private_key_raw(const uint8_t pri_key[32])
{
mbedtls_ecp_group grp;
mbedtls_mpi d;
mbedtls_ecp_point Q;
int ret;
dh_pair.is_ready = false;
memcpy(dh_pair.private_key, pri_key, PRIV_KEY_SIZE);
/* Compute public key from private key */
mbedtls_ecp_group_init(&grp);
mbedtls_mpi_init(&d);
mbedtls_ecp_point_init(&Q);
ret = mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SECP256R1);
if (ret != 0) {
goto cleanup;
}
ret = mbedtls_mpi_read_binary(&d, pri_key, PRIV_KEY_SIZE);
if (ret != 0) {
goto cleanup;
}
/* Compute public key: Q = d * G (no RNG needed for deterministic computation) */
ret = mbedtls_ecp_mul(&grp, &Q, &d, &grp.G, NULL, NULL);
if (ret != 0) {
goto cleanup;
}
/* Export public key point in big-endian */
ret = mbedtls_mpi_write_binary(&Q.MBEDTLS_PRIVATE(X), dh_pair.public_key, 32);
if (ret != 0) {
goto cleanup;
}
ret = mbedtls_mpi_write_binary(&Q.MBEDTLS_PRIVATE(Y), dh_pair.public_key + 32, 32);
if (ret != 0) {
goto cleanup;
}
BT_DBG("Pubkey:%s", bt_hex(dh_pair.public_key, PUB_KEY_SIZE));
BT_DBG("Privkey:%s", bt_hex(dh_pair.private_key, PRIV_KEY_SIZE));
dh_pair.is_ready = true;
cleanup:
mbedtls_ecp_group_free(&grp);
mbedtls_mpi_free(&d);
mbedtls_ecp_point_free(&Q);
}
bool bt_mesh_check_public_key_raw(const uint8_t key[64])
{
mbedtls_ecp_group grp;
mbedtls_ecp_point Q;
uint8_t pub_key_be[PUB_KEY_SIZE];
int ret;
mbedtls_ecp_group_init(&grp);
mbedtls_ecp_point_init(&Q);
ret = mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SECP256R1);
if (ret != 0) {
goto cleanup;
}
ret = mbedtls_mpi_read_binary(&Q.MBEDTLS_PRIVATE(X), dh_pair.public_key, 32);
if (ret != 0) {
goto cleanup;
}
ret = mbedtls_mpi_read_binary(&Q.MBEDTLS_PRIVATE(Y), dh_pair.public_key + 32, 32);
if (ret != 0) {
goto cleanup;
}
ret = mbedtls_mpi_lset(&Q.MBEDTLS_PRIVATE(Z), 1);
if (ret != 0) {
goto cleanup;
}
ret = mbedtls_ecp_check_pubkey(&grp, &Q);
cleanup:
mbedtls_ecp_group_free(&grp);
mbedtls_ecp_point_free(&Q);
return ret == 0;
}
int bt_mesh_dhkey_gen_raw(const uint8_t *pub_key, const uint8_t *priv_key,
uint8_t *dhkey)
{
mbedtls_ecp_group grp;
mbedtls_mpi d;
mbedtls_ecp_point Q;
mbedtls_ecp_point result;
int ret;
mbedtls_ecp_group_init(&grp);
mbedtls_mpi_init(&d);
mbedtls_ecp_point_init(&Q);
mbedtls_ecp_point_init(&result);
ret = mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SECP256R1);
if (ret != 0) {
goto cleanup;
}
ret = mbedtls_mpi_read_binary(&d, priv_key ? priv_key : dh_pair.private_key, PRIV_KEY_SIZE);
if (ret != 0) {
goto cleanup;
}
/* Load public key point */
ret = mbedtls_mpi_read_binary(&Q.MBEDTLS_PRIVATE(X), dh_pair.public_key, 32);
if (ret != 0) {
goto cleanup;
}
ret = mbedtls_mpi_read_binary(&Q.MBEDTLS_PRIVATE(Y), dh_pair.public_key + 32, 32);
if (ret != 0) {
goto cleanup;
}
ret = mbedtls_mpi_lset(&Q.MBEDTLS_PRIVATE(Z), 1);
if (ret != 0) {
goto cleanup;
}
/* Check the peer's public key */
ret = mbedtls_ecp_check_pubkey(&grp, &Q);
if (ret != 0) {
goto cleanup;
}
/* Calculate shared secret: result = d * Q (no RNG needed for deterministic computation) */
ret = mbedtls_ecp_mul(&grp, &result, &d, &Q, NULL, NULL);
if (ret != 0) {
goto cleanup;
}
/* Export X coordinate as DH key (big-endian) */
ret = mbedtls_mpi_write_binary(&result.MBEDTLS_PRIVATE(X), dhkey, DH_KEY_SIZE);
cleanup:
mbedtls_ecp_group_free(&grp);
mbedtls_mpi_free(&d);
mbedtls_ecp_point_free(&Q);
mbedtls_ecp_point_free(&result);
return ret == 0 ? 0 : -EIO;
}
int bt_mesh_key_import(enum bt_mesh_key_type type, const uint8_t in[16],
struct bt_mesh_key *out)
{
(void)type; /* Not used for non-PSA implementation */
memcpy(out->key, in, 16);
return 0;
}
int bt_mesh_key_export(uint8_t out[16], const struct bt_mesh_key *in)
{
memcpy(out, in->key, 16);
return 0;
}
void bt_mesh_key_assign(struct bt_mesh_key *dst, const struct bt_mesh_key *src)
{
memcpy(dst, src, sizeof(struct bt_mesh_key));
}
int bt_mesh_key_destroy(const struct bt_mesh_key *key)
{
(void)key; /* No cleanup needed for non-PSA implementation */
return 0;
}
int bt_mesh_key_compare(const uint8_t raw_key[16], const struct bt_mesh_key *key)
{
return memcmp(raw_key, key->key, 16);
}
int bt_mesh_encrypt_le(const uint8_t key[16], const uint8_t plaintext[16],
uint8_t enc_data[16])
{
mbedtls_aes_context ctx;
uint8_t tmp[16];
int ret;
BT_DBG("key %s plaintext %s", bt_hex(key, 16), bt_hex(plaintext, 16));
mbedtls_aes_init(&ctx);
/* Swap key bytes (LE to BE) */
sys_memcpy_swap(tmp, key, 16);
ret = mbedtls_aes_setkey_enc(&ctx, tmp, 128);
if (ret != 0) {
mbedtls_aes_free(&ctx);
return -EINVAL;
}
/* Swap plaintext bytes and encrypt */
sys_memcpy_swap(tmp, plaintext, 16);
ret = mbedtls_aes_crypt_ecb(&ctx, MBEDTLS_AES_ENCRYPT, tmp, enc_data);
mbedtls_aes_free(&ctx);
if (ret != 0) {
return -EINVAL;
}
/* Swap result bytes (BE to LE) */
sys_mem_swap(enc_data, 16);
BT_DBG("enc_data %s", bt_hex(enc_data, 16));
return 0;
}
int bt_mesh_encrypt_be(const uint8_t key[16], const uint8_t plaintext[16],
uint8_t enc_data[16])
{
mbedtls_aes_context ctx;
int ret;
BT_DBG("key %s plaintext %s", bt_hex(key, 16), bt_hex(plaintext, 16));
mbedtls_aes_init(&ctx);
ret = mbedtls_aes_setkey_enc(&ctx, key, 128);
if (ret != 0) {
mbedtls_aes_free(&ctx);
return -EINVAL;
}
ret = mbedtls_aes_crypt_ecb(&ctx, MBEDTLS_AES_ENCRYPT, plaintext, enc_data);
mbedtls_aes_free(&ctx);
if (ret != 0) {
return -EINVAL;
}
BT_DBG("enc_data %s", bt_hex(enc_data, 16));
return 0;
}
@@ -0,0 +1,713 @@
/*
* SPDX-FileCopyrightText: 2023 Nordic Semiconductor ASA
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <errno.h>
#include "esp_random.h"
#include "psa/crypto.h"
#include "mesh/common.h"
#include "mesh/crypto.h"
#include "mesh/trace.h"
#include "mesh/config.h"
/* PSA Key ID range for BLE Mesh */
#define BT_MESH_PSA_KEY_ID_MIN 0x0001A000
#define BT_MESH_PSA_KEY_ID_RANGE_SIZE \
(2 * CONFIG_BLE_MESH_SUBNET_COUNT + 2 * CONFIG_BLE_MESH_APP_KEY_COUNT + 2)
/* Internal DH key pair storage
*
* PSA functions expect BIG-ENDIAN format.
*/
static struct {
bool is_ready;
psa_key_id_t priv_key_id;
uint8_t public_key[PUB_KEY_SIZE + 1]; /* Big-endian, PSA format: 0x04 + X + Y */
} dh_pair;
/* Bitmap for tracking allocated key IDs */
static uint32_t pst_keys[(BT_MESH_PSA_KEY_ID_RANGE_SIZE + 31) / 32];
static psa_key_id_t keyid_alloc(void)
{
for (int i = 0; i < BT_MESH_PSA_KEY_ID_RANGE_SIZE; i++) {
int word = i / 32;
int bit = i % 32;
if (!(pst_keys[word] & (1U << bit))) {
pst_keys[word] |= (1U << bit);
return BT_MESH_PSA_KEY_ID_MIN + i;
}
}
return PSA_KEY_ID_NULL;
}
static int keyid_free(psa_key_id_t key_id)
{
if (key_id >= BT_MESH_PSA_KEY_ID_MIN &&
key_id < BT_MESH_PSA_KEY_ID_MIN + BT_MESH_PSA_KEY_ID_RANGE_SIZE) {
int idx = key_id - BT_MESH_PSA_KEY_ID_MIN;
int word = idx / 32;
int bit = idx % 32;
pst_keys[word] &= ~(1U << bit);
return 0;
}
return -EIO;
}
static void keyid_assign(psa_key_id_t key_id)
{
if (key_id >= BT_MESH_PSA_KEY_ID_MIN &&
key_id < BT_MESH_PSA_KEY_ID_MIN + BT_MESH_PSA_KEY_ID_RANGE_SIZE) {
int idx = key_id - BT_MESH_PSA_KEY_ID_MIN;
int word = idx / 32;
int bit = idx % 32;
pst_keys[word] |= (1U << bit);
}
}
int bt_mesh_crypto_init(void)
{
psa_status_t status = psa_crypto_init();
if (status != PSA_SUCCESS) {
BT_ERR("PSA crypto init failed: %d", status);
return -EIO;
}
dh_pair.is_ready = false;
dh_pair.priv_key_id = PSA_KEY_ID_NULL;
memset(pst_keys, 0, sizeof(pst_keys));
return 0;
}
int bt_mesh_encrypt(const struct bt_mesh_key *key, const uint8_t plaintext[16],
uint8_t enc_data[16])
{
size_t output_len;
psa_status_t status;
status = psa_cipher_encrypt(key->key, PSA_ALG_ECB_NO_PADDING,
plaintext, 16, enc_data, 16, &output_len);
if (status != PSA_SUCCESS || output_len != 16) {
BT_ERR("PSA cipher encrypt failed: %d", status);
return -EIO;
}
return 0;
}
int bt_mesh_ccm_encrypt(const struct bt_mesh_key *key, uint8_t nonce[13],
const uint8_t *plaintext, size_t len,
const uint8_t *aad, size_t aad_len,
uint8_t *enc_data, size_t mic_size)
{
size_t output_len;
psa_status_t status;
psa_algorithm_t alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, mic_size);
status = psa_aead_encrypt(key->key, alg, nonce, 13, aad, aad_len,
plaintext, len, enc_data, len + mic_size, &output_len);
if (status != PSA_SUCCESS || output_len != len + mic_size) {
BT_ERR("PSA AEAD encrypt failed: %d", status);
return -EIO;
}
return 0;
}
int bt_mesh_ccm_decrypt(const struct bt_mesh_key *key, uint8_t nonce[13],
const uint8_t *enc_data, size_t len,
const uint8_t *aad, size_t aad_len,
uint8_t *plaintext, size_t mic_size)
{
size_t output_len;
psa_status_t status;
psa_algorithm_t alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, mic_size);
status = psa_aead_decrypt(key->key, alg, nonce, 13, aad, aad_len,
enc_data, len + mic_size, plaintext, len, &output_len);
if (status != PSA_SUCCESS || output_len != len) {
BT_ERR("PSA AEAD decrypt failed: %d", status);
return -EIO;
}
return 0;
}
int bt_mesh_ccm_encrypt_raw_key(const uint8_t key[16], uint8_t nonce[13],
const uint8_t *plaintext, size_t len,
const uint8_t *aad, size_t aad_len,
uint8_t *enc_data, size_t mic_size)
{
struct bt_mesh_key mesh_key;
int err;
err = bt_mesh_key_import(BT_MESH_KEY_TYPE_CCM, key, &mesh_key);
if (err) {
return err;
}
err = bt_mesh_ccm_encrypt(&mesh_key, nonce, plaintext, len, aad, aad_len,
enc_data, mic_size);
psa_destroy_key(mesh_key.key);
return err;
}
int bt_mesh_ccm_decrypt_raw_key(const uint8_t key[16], uint8_t nonce[13],
const uint8_t *enc_data, size_t len,
const uint8_t *aad, size_t aad_len,
uint8_t *plaintext, size_t mic_size)
{
struct bt_mesh_key mesh_key;
int err;
err = bt_mesh_key_import(BT_MESH_KEY_TYPE_CCM, key, &mesh_key);
if (err) {
return err;
}
err = bt_mesh_ccm_decrypt(&mesh_key, nonce, enc_data, len, aad, aad_len,
plaintext, mic_size);
psa_destroy_key(mesh_key.key);
return err;
}
int bt_mesh_aes_cmac_mesh_key(const struct bt_mesh_key *key,
struct bt_mesh_sg *sg, size_t sg_len,
uint8_t mac[16])
{
psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
psa_status_t status;
size_t mac_len;
status = psa_mac_sign_setup(&operation, key->key, PSA_ALG_CMAC);
if (status != PSA_SUCCESS) {
BT_ERR("PSA MAC setup failed: %d", status);
return -EIO;
}
for (; sg_len; sg_len--, sg++) {
status = psa_mac_update(&operation, sg->data, sg->len);
if (status != PSA_SUCCESS) {
psa_mac_abort(&operation);
BT_ERR("PSA MAC update failed: %d", status);
return -EIO;
}
}
status = psa_mac_sign_finish(&operation, mac, 16, &mac_len);
if (status != PSA_SUCCESS || mac_len != 16) {
BT_ERR("PSA MAC finish failed: %d", status);
return -EIO;
}
return 0;
}
int bt_mesh_aes_cmac_raw_key(const uint8_t key[16], struct bt_mesh_sg *sg,
size_t sg_len, uint8_t mac[16])
{
struct bt_mesh_key key_id;
int err;
err = bt_mesh_key_import(BT_MESH_KEY_TYPE_CMAC, key, &key_id);
if (err) {
return err;
}
err = bt_mesh_aes_cmac_mesh_key(&key_id, sg, sg_len, mac);
psa_destroy_key(key_id.key);
return err;
}
int bt_mesh_sha256_hmac_raw_key(const uint8_t key[32], struct bt_mesh_sg *sg,
size_t sg_len, uint8_t mac[32])
{
psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id;
psa_status_t status;
size_t mac_len;
int err = 0;
/* Import HMAC key */
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE);
psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_VOLATILE);
psa_set_key_algorithm(&attributes, PSA_ALG_HMAC(PSA_ALG_SHA_256));
psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC);
psa_set_key_bits(&attributes, 256);
status = psa_import_key(&attributes, key, 32, &key_id);
if (status != PSA_SUCCESS) {
BT_ERR("PSA import HMAC key failed: %d", status);
return -EIO;
}
psa_reset_key_attributes(&attributes);
status = psa_mac_sign_setup(&operation, key_id, PSA_ALG_HMAC(PSA_ALG_SHA_256));
if (status != PSA_SUCCESS) {
BT_ERR("PSA HMAC setup failed: %d", status);
err = -EIO;
goto end;
}
for (; sg_len; sg_len--, sg++) {
status = psa_mac_update(&operation, sg->data, sg->len);
if (status != PSA_SUCCESS) {
psa_mac_abort(&operation);
BT_ERR("PSA HMAC update failed: %d", status);
err = -EIO;
goto end;
}
}
status = psa_mac_sign_finish(&operation, mac, 32, &mac_len);
if (status != PSA_SUCCESS || mac_len != 32) {
BT_ERR("PSA HMAC finish failed: %d", status);
err = -EIO;
}
end:
psa_destroy_key(key_id);
return err;
}
int bt_mesh_pub_key_gen(void)
{
psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_status_t status;
uint8_t private_key[PRIV_KEY_SIZE];
size_t key_len;
int err;
/* Destroy any existing key */
if (dh_pair.priv_key_id != PSA_KEY_ID_NULL) {
psa_destroy_key(dh_pair.priv_key_id);
dh_pair.priv_key_id = PSA_KEY_ID_NULL;
}
dh_pair.is_ready = false;
/* Generate a random private key (in little-endian format for storage) */
do {
err = bt_mesh_rand(private_key, sizeof(private_key));
if (err) {
BT_ERR("Failed to generate random private key");
return err;
}
/* Ensure the private key is valid (non-zero first bytes in BE) */
} while (private_key[0] == 0 && private_key[1] == 0);
/* Configure key attributes for ECDH with P-256 */
psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE);
psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_VOLATILE);
psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDH);
psa_set_key_type(&key_attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
psa_set_key_bits(&key_attributes, 256);
/* Import the private key */
status = psa_import_key(&key_attributes, private_key, sizeof(private_key),
&dh_pair.priv_key_id);
if (status != PSA_SUCCESS) {
BT_ERR("PSA import private key failed: %d", status);
psa_reset_key_attributes(&key_attributes);
return -EIO;
}
/* Export public key (PSA computes it from the private key) */
status = psa_export_public_key(dh_pair.priv_key_id, dh_pair.public_key,
sizeof(dh_pair.public_key), &key_len);
if (status != PSA_SUCCESS || key_len != PUB_KEY_SIZE + 1) {
BT_ERR("PSA export public key failed: %d", status);
psa_destroy_key(dh_pair.priv_key_id);
dh_pair.priv_key_id = PSA_KEY_ID_NULL;
psa_reset_key_attributes(&key_attributes);
return -EIO;
}
dh_pair.is_ready = true;
psa_reset_key_attributes(&key_attributes);
return 0;
}
const uint8_t *bt_mesh_pub_key_get_raw(void)
{
if (!dh_pair.is_ready) {
if (bt_mesh_pub_key_gen() != 0) {
return NULL;
}
}
return &dh_pair.public_key[1];
}
void bt_mesh_set_private_key_raw(const uint8_t pri_key[32])
{
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_status_t status;
size_t key_len;
/* Destroy any existing key */
if (dh_pair.priv_key_id != PSA_KEY_ID_NULL) {
psa_destroy_key(dh_pair.priv_key_id);
dh_pair.priv_key_id = PSA_KEY_ID_NULL;
}
dh_pair.is_ready = false;
/* Import the provided private key */
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE);
psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_VOLATILE);
psa_set_key_algorithm(&attributes, PSA_ALG_ECDH);
psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
psa_set_key_bits(&attributes, 256);
status = psa_import_key(&attributes, pri_key, PRIV_KEY_SIZE, &dh_pair.priv_key_id);
if (status != PSA_SUCCESS) {
BT_ERR("PSA import private key failed: %d", status);
psa_reset_key_attributes(&attributes);
return;
}
/* Export public key (PSA computes it from the private key) */
status = psa_export_public_key(dh_pair.priv_key_id, dh_pair.public_key,
sizeof(dh_pair.public_key), &key_len);
if (status != PSA_SUCCESS || key_len != PUB_KEY_SIZE + 1) {
BT_ERR("PSA export public key failed: %d", status);
psa_destroy_key(dh_pair.priv_key_id);
dh_pair.priv_key_id = PSA_KEY_ID_NULL;
psa_reset_key_attributes(&attributes);
return;
}
BT_DBG("Pubkey:%s", bt_hex(&dh_pair.public_key[1], PUB_KEY_SIZE));
BT_DBG("Privkey:%s", bt_hex(pri_key, PRIV_KEY_SIZE));
dh_pair.is_ready = true;
psa_reset_key_attributes(&attributes);
}
bool bt_mesh_check_public_key_raw(const uint8_t key[64])
{
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id;
psa_status_t status;
uint8_t pub_be[PUB_KEY_SIZE + 1];
/* PSA requires 0x04 prefix for uncompressed point */
pub_be[0] = 0x04;
/* Convert from little-endian to big-endian */
memcpy(&pub_be[1], key, 32);
memcpy(&pub_be[33], key + 32, 32);
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH);
psa_set_key_algorithm(&attributes, PSA_ALG_ECDSA(PSA_ALG_SHA_256));
psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1));
psa_set_key_bits(&attributes, 256);
status = psa_import_key(&attributes, pub_be, sizeof(pub_be), &key_id);
psa_reset_key_attributes(&attributes);
if (status != PSA_SUCCESS) {
return false;
}
psa_destroy_key(key_id);
return true;
}
int bt_mesh_dhkey_gen_raw(const uint8_t *pub_key, const uint8_t *priv_key,
uint8_t *dhkey)
{
psa_key_id_t priv_key_id = PSA_KEY_ID_NULL;
uint8_t public_key_be[PUB_KEY_SIZE + 1];
psa_status_t status;
size_t dh_key_len;
int err = 0;
if (priv_key) {
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
/* Import custom private key */
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE);
psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_VOLATILE);
psa_set_key_algorithm(&attributes, PSA_ALG_ECDH);
psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
psa_set_key_bits(&attributes, 256);
status = psa_import_key(&attributes, priv_key, PRIV_KEY_SIZE, &priv_key_id);
psa_reset_key_attributes(&attributes);
if (status != PSA_SUCCESS) {
BT_ERR("PSA import private key failed: %d", status);
return -EIO;
}
} else {
priv_key_id = dh_pair.priv_key_id;
}
/* Prepare public key with 0x04 prefix in big-endian format */
public_key_be[0] = 0x04;
/* Convert from little-endian to big-endian */
memcpy(public_key_be + 1, pub_key, 32);
memcpy(public_key_be + 33, pub_key + 32, 32);
/* Calculate shared secret */
status = psa_raw_key_agreement(PSA_ALG_ECDH, priv_key_id, public_key_be,
PUB_KEY_SIZE + 1, dhkey, DH_KEY_SIZE, &dh_key_len);
if (status != PSA_SUCCESS || dh_key_len != DH_KEY_SIZE) {
BT_ERR("PSA ECDH failed: %d", status);
err = -EIO;
}
if (priv_key && priv_key_id != PSA_KEY_ID_NULL) {
psa_destroy_key(priv_key_id);
}
return err;
}
int bt_mesh_key_import(enum bt_mesh_key_type type, const uint8_t in[16],
struct bt_mesh_key *out)
{
psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_status_t status;
psa_key_id_t key_id = PSA_KEY_ID_NULL;
switch (type) {
case BT_MESH_KEY_TYPE_ECB:
psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_VOLATILE);
psa_set_key_usage_flags(&key_attributes,
PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
psa_set_key_algorithm(&key_attributes, PSA_ALG_ECB_NO_PADDING);
break;
case BT_MESH_KEY_TYPE_CCM:
psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_VOLATILE);
psa_set_key_usage_flags(&key_attributes,
PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
psa_set_key_algorithm(&key_attributes,
PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 4));
break;
case BT_MESH_KEY_TYPE_CMAC:
psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_VOLATILE);
psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_SIGN_MESSAGE);
psa_set_key_algorithm(&key_attributes, PSA_ALG_CMAC);
break;
case BT_MESH_KEY_TYPE_NET:
#if CONFIG_BT_SETTINGS
key_id = keyid_alloc();
if (key_id == PSA_KEY_ID_NULL) {
return -ENOMEM;
}
psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_PERSISTENT);
psa_set_key_id(&key_attributes, key_id);
#else
psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_VOLATILE);
#endif
psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_EXPORT);
break;
case BT_MESH_KEY_TYPE_APP:
case BT_MESH_KEY_TYPE_DEV:
#if CONFIG_BT_SETTINGS
key_id = keyid_alloc();
if (key_id == PSA_KEY_ID_NULL) {
return -ENOMEM;
}
psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_PERSISTENT);
psa_set_key_id(&key_attributes, key_id);
#else
psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_VOLATILE);
#endif
psa_set_key_usage_flags(&key_attributes,
PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_EXPORT);
psa_set_key_algorithm(&key_attributes,
PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 4));
break;
default:
return -EINVAL;
}
psa_set_key_type(&key_attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&key_attributes, 128);
status = psa_import_key(&key_attributes, in, 16, &out->key);
if (status == PSA_ERROR_ALREADY_EXISTS) {
BT_WARN("Key 0x%04x already exists, destroying and reimporting", key_id);
psa_destroy_key(key_id);
status = psa_import_key(&key_attributes, in, 16, &out->key);
}
psa_reset_key_attributes(&key_attributes);
if (status != PSA_SUCCESS) {
BT_ERR("PSA import key failed: %d", status);
if (key_id != PSA_KEY_ID_NULL) {
keyid_free(key_id);
}
return -EIO;
}
return 0;
}
int bt_mesh_key_export(uint8_t out[16], const struct bt_mesh_key *in)
{
size_t data_length;
psa_status_t status;
status = psa_export_key(in->key, out, 16, &data_length);
if (status != PSA_SUCCESS || data_length != 16) {
BT_ERR("PSA export key failed: %d", status);
return -EIO;
}
return 0;
}
void bt_mesh_key_assign(struct bt_mesh_key *dst, const struct bt_mesh_key *src)
{
memcpy(dst, src, sizeof(struct bt_mesh_key));
#if CONFIG_BT_SETTINGS
keyid_assign(dst->key);
#endif
}
int bt_mesh_key_destroy(const struct bt_mesh_key *key)
{
psa_status_t status;
status = psa_destroy_key(key->key);
if (status != PSA_SUCCESS) {
BT_ERR("PSA destroy key failed: %d", status);
return -EIO;
}
#if CONFIG_BT_SETTINGS
return keyid_free(key->key);
#else
return 0;
#endif
}
int bt_mesh_key_compare(const uint8_t raw_key[16], const struct bt_mesh_key *key)
{
uint8_t out[16];
int err;
err = bt_mesh_key_export(out, key);
if (err) {
return err;
}
return memcmp(out, raw_key, 16);
}
int bt_mesh_encrypt_le(const uint8_t key[16], const uint8_t plaintext[16],
uint8_t enc_data[16])
{
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id;
psa_status_t status;
uint8_t tmp[16];
size_t output_len;
BT_DBG("key %s plaintext %s", bt_hex(key, 16), bt_hex(plaintext, 16));
/* Swap key bytes (LE to BE) */
sys_memcpy_swap(tmp, key, 16);
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
psa_set_key_algorithm(&attributes, PSA_ALG_ECB_NO_PADDING);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, 128);
status = psa_import_key(&attributes, tmp, 16, &key_id);
psa_reset_key_attributes(&attributes);
if (status != PSA_SUCCESS) {
BT_ERR("PSA import key failed: %d", status);
return -EINVAL;
}
/* Swap plaintext bytes and encrypt */
sys_memcpy_swap(tmp, plaintext, 16);
status = psa_cipher_encrypt(key_id, PSA_ALG_ECB_NO_PADDING,
tmp, 16, enc_data, 16, &output_len);
psa_destroy_key(key_id);
if (status != PSA_SUCCESS || output_len != 16) {
BT_ERR("PSA encrypt failed: %d", status);
return -EINVAL;
}
/* Swap result bytes (BE to LE) */
sys_mem_swap(enc_data, 16);
BT_DBG("enc_data %s", bt_hex(enc_data, 16));
return 0;
}
int bt_mesh_encrypt_be(const uint8_t key[16], const uint8_t plaintext[16],
uint8_t enc_data[16])
{
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id;
psa_status_t status;
size_t output_len;
BT_DBG("key %s plaintext %s", bt_hex(key, 16), bt_hex(plaintext, 16));
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
psa_set_key_algorithm(&attributes, PSA_ALG_ECB_NO_PADDING);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, 128);
status = psa_import_key(&attributes, key, 16, &key_id);
psa_reset_key_attributes(&attributes);
if (status != PSA_SUCCESS) {
BT_ERR("PSA import key failed: %d", status);
return -EINVAL;
}
status = psa_cipher_encrypt(key_id, PSA_ALG_ECB_NO_PADDING,
plaintext, 16, enc_data, 16, &output_len);
psa_destroy_key(key_id);
if (status != PSA_SUCCESS || output_len != 16) {
BT_ERR("PSA encrypt failed: %d", status);
return -EINVAL;
}
BT_DBG("enc_data %s", bt_hex(enc_data, 16));
return 0;
}
#if 0
int bt_mesh_rand(void *buf, size_t len)
{
psa_status_t status;
if (buf == NULL || len == 0) {
return -EINVAL;
}
status = psa_generate_random(buf, len);
return status == PSA_SUCCESS ? 0 : -EIO;
}
#endif
@@ -0,0 +1,342 @@
/*
* SPDX-FileCopyrightText: 2017 Intel Corporation
* SPDX-FileCopyrightText: 2023 Nordic Semiconductor ASA
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <errno.h>
#include "esp_random.h"
#include <tinycrypt/aes.h>
#include <tinycrypt/constants.h>
#include <tinycrypt/cmac_mode.h>
#include <tinycrypt/ccm_mode.h>
#include <tinycrypt/ecc.h>
#include <tinycrypt/ecc_dh.h>
#include <tinycrypt/hmac.h>
#include "mesh/common.h"
#include "mesh/crypto.h"
#include "mesh/trace.h"
/* Internal DH key pair storage
*
* TinyCrypt's uECC functions expect BIG-ENDIAN format.
*/
static struct {
bool is_ready;
uint8_t private_key[PRIV_KEY_SIZE]; /* Big-endian */
uint8_t public_key[PUB_KEY_SIZE]; /* Big-endian */
} dh_pair;
int bt_mesh_crypto_init(void)
{
memset(&dh_pair, 0, sizeof(dh_pair));
dh_pair.is_ready = false;
return 0;
}
int bt_mesh_encrypt(const struct bt_mesh_key *key, const uint8_t plaintext[16],
uint8_t enc_data[16])
{
struct tc_aes_key_sched_struct sched;
if (tc_aes128_set_encrypt_key(&sched, key->key) == TC_CRYPTO_FAIL) {
return -EIO;
}
if (tc_aes_encrypt(enc_data, plaintext, &sched) == TC_CRYPTO_FAIL) {
return -EIO;
}
return 0;
}
int bt_mesh_ccm_encrypt(const struct bt_mesh_key *key, uint8_t nonce[13],
const uint8_t *plaintext, size_t len,
const uint8_t *aad, size_t aad_len,
uint8_t *enc_data, size_t mic_size)
{
struct tc_ccm_mode_struct ccm;
struct tc_aes_key_sched_struct sched;
if (tc_aes128_set_encrypt_key(&sched, key->key) == TC_CRYPTO_FAIL) {
return -EIO;
}
if (tc_ccm_config(&ccm, &sched, nonce, 13, mic_size) == TC_CRYPTO_FAIL) {
return -EIO;
}
if (tc_ccm_generation_encryption(enc_data, len + mic_size, aad, aad_len,
plaintext, len, &ccm) == TC_CRYPTO_FAIL) {
return -EIO;
}
return 0;
}
int bt_mesh_ccm_decrypt(const struct bt_mesh_key *key, uint8_t nonce[13],
const uint8_t *enc_data, size_t len,
const uint8_t *aad, size_t aad_len,
uint8_t *plaintext, size_t mic_size)
{
struct tc_ccm_mode_struct ccm;
struct tc_aes_key_sched_struct sched;
if (tc_aes128_set_encrypt_key(&sched, key->key) == TC_CRYPTO_FAIL) {
return -EIO;
}
if (tc_ccm_config(&ccm, &sched, nonce, 13, mic_size) == TC_CRYPTO_FAIL) {
return -EIO;
}
if (tc_ccm_decryption_verification(plaintext, len, aad, aad_len,
enc_data, len + mic_size, &ccm) == TC_CRYPTO_FAIL) {
return -EIO;
}
return 0;
}
int bt_mesh_ccm_encrypt_raw_key(const uint8_t key[16], uint8_t nonce[13],
const uint8_t *plaintext, size_t len,
const uint8_t *aad, size_t aad_len,
uint8_t *enc_data, size_t mic_size)
{
struct bt_mesh_key mesh_key;
memcpy(mesh_key.key, key, 16);
return bt_mesh_ccm_encrypt(&mesh_key, nonce, plaintext, len, aad, aad_len,
enc_data, mic_size);
}
int bt_mesh_ccm_decrypt_raw_key(const uint8_t key[16], uint8_t nonce[13],
const uint8_t *enc_data, size_t len,
const uint8_t *aad, size_t aad_len,
uint8_t *plaintext, size_t mic_size)
{
struct bt_mesh_key mesh_key;
memcpy(mesh_key.key, key, 16);
return bt_mesh_ccm_decrypt(&mesh_key, nonce, enc_data, len, aad, aad_len,
plaintext, mic_size);
}
int bt_mesh_aes_cmac_raw_key(const uint8_t key[16], struct bt_mesh_sg *sg,
size_t sg_len, uint8_t mac[16])
{
struct tc_aes_key_sched_struct sched;
struct tc_cmac_struct state;
if (tc_cmac_setup(&state, key, &sched) == TC_CRYPTO_FAIL) {
return -EIO;
}
for (; sg_len; sg_len--, sg++) {
if (tc_cmac_update(&state, sg->data, sg->len) == TC_CRYPTO_FAIL) {
return -EIO;
}
}
if (tc_cmac_final(mac, &state) == TC_CRYPTO_FAIL) {
return -EIO;
}
return 0;
}
int bt_mesh_aes_cmac_mesh_key(const struct bt_mesh_key *key,
struct bt_mesh_sg *sg, size_t sg_len,
uint8_t mac[16])
{
return bt_mesh_aes_cmac_raw_key(key->key, sg, sg_len, mac);
}
int bt_mesh_sha256_hmac_raw_key(const uint8_t key[32], struct bt_mesh_sg *sg,
size_t sg_len, uint8_t mac[32])
{
struct tc_hmac_state_struct h;
if (tc_hmac_set_key(&h, key, 32) == TC_CRYPTO_FAIL) {
return -EIO;
}
if (tc_hmac_init(&h) == TC_CRYPTO_FAIL) {
return -EIO;
}
for (; sg_len; sg_len--, sg++) {
if (tc_hmac_update(&h, sg->data, sg->len) == TC_CRYPTO_FAIL) {
return -EIO;
}
}
if (tc_hmac_final(mac, 32, &h) == TC_CRYPTO_FAIL) {
return -EIO;
}
return 0;
}
int bt_mesh_pub_key_gen(void)
{
int rc;
/* Generate a random private key */
do {
rc = bt_mesh_rand(dh_pair.private_key, sizeof(dh_pair.private_key));
if (rc) {
BT_ERR("Failed to generate random private key");
return rc;
}
/* Ensure the private key is valid (first bytes in BE shall be non-zero) */
} while (dh_pair.private_key[0] == 0 &&
dh_pair.private_key[1] == 0);
/* Compute the public key from the private key */
rc = uECC_compute_public_key(dh_pair.private_key, dh_pair.public_key, uECC_secp256r1());
if (rc != TC_CRYPTO_SUCCESS) {
dh_pair.is_ready = false;
BT_ERR("Failed to compute public key");
return -EIO;
}
dh_pair.is_ready = true;
return 0;
}
const uint8_t *bt_mesh_pub_key_get_raw(void)
{
if (!dh_pair.is_ready) {
if (bt_mesh_pub_key_gen() != 0) {
return NULL;
}
}
return dh_pair.public_key;
}
void bt_mesh_set_private_key_raw(const uint8_t pri_key[32])
{
int rc;
memcpy(dh_pair.private_key, pri_key, PRIV_KEY_SIZE);
/* Compute the public key from the provided private key */
rc = uECC_compute_public_key(dh_pair.private_key, dh_pair.public_key, uECC_secp256r1());
if (rc != TC_CRYPTO_SUCCESS) {
dh_pair.is_ready = false;
BT_ERR("Failed to compute public key from private key");
return;
}
BT_DBG("Pubkey:%s", bt_hex(dh_pair.public_key, PUB_KEY_SIZE));
BT_DBG("Privkey:%s", bt_hex(dh_pair.private_key, PRIV_KEY_SIZE));
dh_pair.is_ready = true;
}
bool bt_mesh_check_public_key_raw(const uint8_t key[64])
{
return uECC_valid_public_key(key, uECC_secp256r1()) == 0;
}
int bt_mesh_dhkey_gen_raw(const uint8_t *pub_key, const uint8_t *priv_key,
uint8_t *dhkey)
{
if (uECC_valid_public_key(pub_key, uECC_secp256r1()) != 0) {
BT_ERR("Public key is not valid");
return -EIO;
}
if (uECC_shared_secret(pub_key, priv_key ? priv_key : dh_pair.private_key,
dhkey, uECC_secp256r1()) != TC_CRYPTO_SUCCESS) {
BT_ERR("DHKey generation failed");
return -EIO;
}
return 0;
}
int bt_mesh_key_import(enum bt_mesh_key_type type, const uint8_t in[16],
struct bt_mesh_key *out)
{
(void)type; /* Type is not used for TinyCrypt, just store raw key */
memcpy(out->key, in, 16);
return 0;
}
int bt_mesh_key_export(uint8_t out[16], const struct bt_mesh_key *in)
{
memcpy(out, in->key, 16);
return 0;
}
void bt_mesh_key_assign(struct bt_mesh_key *dst, const struct bt_mesh_key *src)
{
memcpy(dst->key, src->key, 16);
}
int bt_mesh_key_destroy(const struct bt_mesh_key *key)
{
(void)key; /* Nothing to destroy for TinyCrypt */
return 0;
}
int bt_mesh_key_compare(const uint8_t raw_key[16], const struct bt_mesh_key *key)
{
return memcmp(raw_key, key->key, 16);
}
int bt_mesh_encrypt_le(const uint8_t key[16], const uint8_t plaintext[16],
uint8_t enc_data[16])
{
struct tc_aes_key_sched_struct sched;
uint8_t tmp[16];
BT_DBG("key %s plaintext %s", bt_hex(key, 16), bt_hex(plaintext, 16));
/* Swap key bytes (LE to BE) */
sys_memcpy_swap(tmp, key, 16);
if (tc_aes128_set_encrypt_key(&sched, tmp) == TC_CRYPTO_FAIL) {
return -EINVAL;
}
/* Swap plaintext bytes (LE to BE) */
sys_memcpy_swap(tmp, plaintext, 16);
if (tc_aes_encrypt(enc_data, tmp, &sched) == TC_CRYPTO_FAIL) {
return -EINVAL;
}
/* Swap result bytes (BE to LE) */
sys_mem_swap(enc_data, 16);
BT_DBG("enc_data %s", bt_hex(enc_data, 16));
return 0;
}
int bt_mesh_encrypt_be(const uint8_t key[16], const uint8_t plaintext[16],
uint8_t enc_data[16])
{
struct tc_aes_key_sched_struct sched;
BT_DBG("key %s plaintext %s", bt_hex(key, 16), bt_hex(plaintext, 16));
if (tc_aes128_set_encrypt_key(&sched, key) == TC_CRYPTO_FAIL) {
return -EINVAL;
}
if (tc_aes_encrypt(enc_data, plaintext, &sched) == TC_CRYPTO_FAIL) {
return -EINVAL;
}
BT_DBG("enc_data %s", bt_hex(enc_data, 16));
return 0;
}
@@ -22,6 +22,7 @@
#include "mesh/trace.h"
#include "mesh/mutex.h"
#include "mesh/access.h"
#include "mesh/crypto.h"
#ifdef __cplusplus
extern "C" {
@@ -0,0 +1,514 @@
/*
* SPDX-FileCopyrightText: 2017 Intel Corporation
* SPDX-FileCopyrightText: 2023 Nordic Semiconductor ASA
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _BLE_MESH_CRYPTO_H_
#define _BLE_MESH_CRYPTO_H_
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include "sdkconfig.h"
#include "mesh/common.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Key sizes */
#define PRIV_KEY_SIZE 32
#define PUB_KEY_SIZE 64
#define DH_KEY_SIZE 32
/**
* @brief Crypto module endianness definitions
*
* BLE Mesh protocol uses big-endian format for ECC operations.
* These macros define whether the underlying crypto implementation
* expects big-endian or little-endian input.
*
* - BT_MESH_CRYPTO_ENDIAN_BIG: Module expects big-endian (TinyCrypt, MbedTLS, PSA)
* - BT_MESH_CRYPTO_ENDIAN_LITTLE: Module expects little-endian (future implementations)
*/
#define BT_MESH_CRYPTO_ENDIAN_BIG 0
#define BT_MESH_CRYPTO_ENDIAN_LITTLE 1
/**
* @brief Current crypto module endianness
*
* This macro should be defined by the crypto implementation.
* Default is big-endian (matching TinyCrypt, MbedTLS, PSA).
*/
#ifndef BT_MESH_CRYPTO_ENDIAN
#define BT_MESH_CRYPTO_ENDIAN BT_MESH_CRYPTO_ENDIAN_BIG
#endif
/**
* @brief Parameter conversion macros for endianness handling
*
* These macros automatically handle byte order conversion between
* BLE Mesh's big-endian format and the crypto module's expected format.
*
* For public keys (64 bytes = X + Y), the X and Y coordinates must be
* swapped separately, not as a single 64-byte block.
*/
#if (BT_MESH_CRYPTO_ENDIAN == BT_MESH_CRYPTO_ENDIAN_LITTLE)
/* Little-endian mode: need byte order conversion */
#define CRYPTO_PARAM_DECLARE(name, size) \
uint8_t _##name[size]
#define CRYPTO_PARAM_IN(name, size) \
sys_memcpy_swap(_##name, name, size)
#define CRYPTO_PARAM_OUT(name, size) \
sys_memcpy_swap((uint8_t *)(name), _##name, size)
#define CRYPTO_PARAM(name) (_##name)
/* Public key (64 bytes) needs special handling: swap X and Y separately */
#define CRYPTO_PARAM_PUBKEY_IN(name) \
do { \
sys_memcpy_swap(_##name, name, 32); \
sys_memcpy_swap(_##name + 32, (name) + 32, 32); \
} while (0)
#define CRYPTO_PARAM_PUBKEY_OUT(name) \
do { \
sys_memcpy_swap((uint8_t *)(name), _##name, 32); \
sys_memcpy_swap((uint8_t *)(name) + 32, _##name + 32, 32); \
} while (0)
#else /* BT_MESH_CRYPTO_ENDIAN_BIG */
/* Big-endian mode: no conversion needed, use original parameters directly */
#define CRYPTO_PARAM_DECLARE(name, size) \
(void)0
#define CRYPTO_PARAM_IN(name, size) \
(void)0
#define CRYPTO_PARAM_OUT(name, size) \
(void)0
#define CRYPTO_PARAM(name) (name)
#define CRYPTO_PARAM_PUBKEY_IN(name) \
(void)0
#define CRYPTO_PARAM_PUBKEY_OUT(name) \
(void)0
#endif /* BT_MESH_CRYPTO_ENDIAN */
/**
* @brief Scatter-Gather data structure for cryptographic operations
*/
struct bt_mesh_sg {
const void *data;
size_t len;
};
/**
* @brief Mesh key type enumeration
*/
enum bt_mesh_key_type {
BT_MESH_KEY_TYPE_ECB, /**< AES-ECB encryption/decryption */
BT_MESH_KEY_TYPE_CCM, /**< AES-CCM AEAD */
BT_MESH_KEY_TYPE_CMAC, /**< AES-CMAC */
BT_MESH_KEY_TYPE_NET, /**< Network key */
BT_MESH_KEY_TYPE_APP, /**< Application key */
BT_MESH_KEY_TYPE_DEV, /**< Device key */
};
/**
* @brief Mesh key structure
*
* For TinyCrypt/MbedTLS: stores raw key bytes
* For PSA: stores PSA key ID
*/
struct bt_mesh_key {
#if CONFIG_BT_SMP_CRYPTO_STACK_MBEDTLS && CONFIG_MBEDTLS_VER_4_X_SUPPORT
uint32_t key; /* PSA key ID */
#else
uint8_t key[16]; /* Raw key bytes */
#endif
};
/**
* @brief Initialize the cryptographic subsystem
*
* @return 0 on success, negative error code otherwise
*/
int bt_mesh_crypto_init(void);
/**
* @brief AES-ECB encryption (big-endian)
*
* @param key Pointer to mesh key structure
* @param plaintext 16-byte plaintext
* @param enc_data 16-byte output buffer for encrypted data
*
* @return 0 on success, negative error code otherwise
*/
int bt_mesh_encrypt(const struct bt_mesh_key *key, const uint8_t plaintext[16],
uint8_t enc_data[16]);
/**
* @brief AES-CCM encryption
*
* @param key Pointer to mesh key structure
* @param nonce 13-byte nonce
* @param plaintext Input plaintext
* @param len Length of plaintext
* @param aad Additional authenticated data
* @param aad_len Length of AAD
* @param enc_data Output buffer (must be len + mic_size bytes)
* @param mic_size Size of MIC (4, 8, or 16 bytes)
*
* @return 0 on success, negative error code otherwise
*/
int bt_mesh_ccm_encrypt(const struct bt_mesh_key *key, uint8_t nonce[13],
const uint8_t *plaintext, size_t len,
const uint8_t *aad, size_t aad_len,
uint8_t *enc_data, size_t mic_size);
/**
* @brief AES-CCM decryption
*
* @param key Pointer to mesh key structure
* @param nonce 13-byte nonce
* @param enc_data Encrypted data with MIC
* @param len Length of plaintext (without MIC)
* @param aad Additional authenticated data
* @param aad_len Length of AAD
* @param plaintext Output buffer for plaintext
* @param mic_size Size of MIC (4, 8, or 16 bytes)
*
* @return 0 on success, negative error code otherwise
*/
int bt_mesh_ccm_decrypt(const struct bt_mesh_key *key, uint8_t nonce[13],
const uint8_t *enc_data, size_t len,
const uint8_t *aad, size_t aad_len,
uint8_t *plaintext, size_t mic_size);
/**
* @brief AES-CCM encryption using raw key bytes
*
* @param key 16-byte raw key
* @param nonce 13-byte nonce
* @param plaintext Input plaintext
* @param len Length of plaintext
* @param aad Additional authenticated data
* @param aad_len Length of AAD
* @param enc_data Output buffer (must be len + mic_size bytes)
* @param mic_size Size of MIC (4, 8, or 16 bytes)
*
* @return 0 on success, negative error code otherwise
*/
int bt_mesh_ccm_encrypt_raw_key(const uint8_t key[16], uint8_t nonce[13],
const uint8_t *plaintext, size_t len,
const uint8_t *aad, size_t aad_len,
uint8_t *enc_data, size_t mic_size);
/**
* @brief AES-CCM decryption using raw key bytes
*
* @param key 16-byte raw key
* @param nonce 13-byte nonce
* @param enc_data Encrypted data with MIC
* @param len Length of plaintext (without MIC)
* @param aad Additional authenticated data
* @param aad_len Length of AAD
* @param plaintext Output buffer for plaintext
* @param mic_size Size of MIC (4, 8, or 16 bytes)
*
* @return 0 on success, negative error code otherwise
*/
int bt_mesh_ccm_decrypt_raw_key(const uint8_t key[16], uint8_t nonce[13],
const uint8_t *enc_data, size_t len,
const uint8_t *aad, size_t aad_len,
uint8_t *plaintext, size_t mic_size);
/**
* @brief AES-CMAC using mesh key structure
*
* @param key Pointer to mesh key structure
* @param sg Scatter-gather list of input data
* @param sg_len Number of scatter-gather entries
* @param mac 16-byte output buffer for MAC
*
* @return 0 on success, negative error code otherwise
*/
int bt_mesh_aes_cmac_mesh_key(const struct bt_mesh_key *key,
struct bt_mesh_sg *sg, size_t sg_len,
uint8_t mac[16]);
/**
* @brief AES-CMAC using raw key bytes
*
* @param key 16-byte raw key
* @param sg Scatter-gather list of input data
* @param sg_len Number of scatter-gather entries
* @param mac 16-byte output buffer for MAC
*
* @return 0 on success, negative error code otherwise
*/
int bt_mesh_aes_cmac_raw_key(const uint8_t key[16], struct bt_mesh_sg *sg,
size_t sg_len, uint8_t mac[16]);
/**
* @brief AES-CMAC with single data input (convenience wrapper)
*/
static inline int bt_mesh_aes_cmac_one(const uint8_t key[16], const void *m,
size_t len, uint8_t mac[16])
{
struct bt_mesh_sg sg = { m, len };
return bt_mesh_aes_cmac_raw_key(key, &sg, 1, mac);
}
/**
* @brief HMAC-SHA256 using raw key bytes
*
* @param key 32-byte raw key
* @param sg Scatter-gather list of input data
* @param sg_len Number of scatter-gather entries
* @param mac 32-byte output buffer for MAC
*
* @return 0 on success, negative error code otherwise
*/
int bt_mesh_sha256_hmac_raw_key(const uint8_t key[32], struct bt_mesh_sg *sg,
size_t sg_len, uint8_t mac[32]);
/**
* @brief HMAC-SHA256 with single data input (convenience wrapper)
*/
static inline int bt_mesh_sha256_hmac_one(const uint8_t key[32], const void *m,
size_t len, uint8_t mac[32])
{
struct bt_mesh_sg sg = { m, len };
return bt_mesh_sha256_hmac_raw_key(key, &sg, 1, mac);
}
/* ============================================================================
* Internal Low-Level ECC APIs
* ============================================================================
* These functions operate in the crypto module's native byte order.
* Do NOT call these directly - use the public wrapper functions below.
*/
const uint8_t *bt_mesh_pub_key_get_raw(void);
void bt_mesh_set_private_key_raw(const uint8_t pri_key[32]);
bool bt_mesh_check_public_key_raw(const uint8_t key[64]);
int bt_mesh_dhkey_gen_raw(const uint8_t *pub_key, const uint8_t *priv_key,
uint8_t *dhkey);
/* ============================================================================
* Public ECC APIs (with automatic endianness conversion)
* ============================================================================
* All public key and DHKey parameters use big-endian format (BLE Mesh protocol).
* For little-endian crypto modules, conversion is handled automatically.
*/
/**
* @brief Generate a new ECC public key pair
*
* Generates a new P-256 key pair for ECDH operations.
* The private key is stored internally.
*
* @return 0 on success, negative error code otherwise
*/
int bt_mesh_pub_key_gen(void);
/**
* @brief Get the current public key (raw pointer)
*
* Returns pointer to the internal public key storage.
* Note: The byte order depends on crypto module's native format.
* Use bt_mesh_pub_key_copy() to get big-endian format.
*
* @return Pointer to 64-byte public key, or NULL if not ready
*/
#define bt_mesh_pub_key_get() bt_mesh_pub_key_get_raw()
/**
* @brief Copy current public key to user buffer (big-endian output)
*
* Copies the public key to the provided buffer, converting to big-endian
* format (BLE Mesh protocol format) if necessary.
*
* @param buf 64-byte output buffer for public key (big-endian output)
*
* @return 0 on success, -EAGAIN if public key not ready
*/
static inline int bt_mesh_pub_key_copy(uint8_t *buf)
{
const uint8_t *key = bt_mesh_pub_key_get_raw();
if (key == NULL || buf == NULL) {
return -EAGAIN;
}
#if (BT_MESH_CRYPTO_ENDIAN == BT_MESH_CRYPTO_ENDIAN_LITTLE)
/* Swap X and Y coordinates separately to big-endian */
sys_memcpy_swap(buf, key, 32);
sys_memcpy_swap(buf + 32, key + 32, 32);
#else
memcpy(buf, key, PUB_KEY_SIZE);
#endif
return 0;
}
/**
* @brief Set a custom private key
*
* @param pri_key 32-byte private key (big-endian, BLE Mesh format)
*/
static inline void bt_mesh_set_private_key(const uint8_t pri_key[32])
{
CRYPTO_PARAM_DECLARE(pri_key, PRIV_KEY_SIZE);
CRYPTO_PARAM_IN(pri_key, PRIV_KEY_SIZE);
bt_mesh_set_private_key_raw(CRYPTO_PARAM(pri_key));
}
/**
* @brief Check if a public key is valid
*
* Verifies that the given public key is a valid point on the P-256 curve.
*
* @param key 64-byte public key (X || Y, big-endian, BLE Mesh format)
*
* @return true if valid, false otherwise
*/
static inline bool bt_mesh_check_public_key(const uint8_t key[64])
{
CRYPTO_PARAM_DECLARE(key, PUB_KEY_SIZE);
CRYPTO_PARAM_PUBKEY_IN(key);
return bt_mesh_check_public_key_raw(CRYPTO_PARAM(key));
}
/**
* @brief Generate ECDH shared secret (DHKey)
*
* @param pub_key 64-byte remote public key (X || Y, big-endian, BLE Mesh format)
* @param priv_key 32-byte private key (NULL to use internal key)
* @param dhkey 32-byte output buffer for shared secret (big-endian output)
*
* @return 0 on success, negative error code otherwise
*/
static inline int bt_mesh_dhkey_gen(const uint8_t *pub_key, const uint8_t *priv_key,
uint8_t *dhkey)
{
int rc;
CRYPTO_PARAM_DECLARE(pub_key, PUB_KEY_SIZE);
CRYPTO_PARAM_DECLARE(priv_key, PRIV_KEY_SIZE);
CRYPTO_PARAM_DECLARE(dhkey, DH_KEY_SIZE);
/* Public key: swap X and Y coordinates separately */
CRYPTO_PARAM_PUBKEY_IN(pub_key);
if (priv_key != NULL) {
CRYPTO_PARAM_IN(priv_key, PRIV_KEY_SIZE);
}
rc = bt_mesh_dhkey_gen_raw(CRYPTO_PARAM(pub_key),
priv_key ? CRYPTO_PARAM(priv_key) : NULL,
CRYPTO_PARAM(dhkey));
if (rc) {
return rc;
}
CRYPTO_PARAM_OUT(dhkey, DH_KEY_SIZE);
return rc;
}
#define bt_mesh_dh_key_gen(pubkey, dhkey) bt_mesh_dhkey_gen(pubkey, NULL, dhkey)
/**
* @brief Import a raw key into mesh key structure
*
* @param type Key type (determines key usage)
* @param in 16-byte raw key
* @param out Output mesh key structure
*
* @return 0 on success, negative error code otherwise
*/
int bt_mesh_key_import(enum bt_mesh_key_type type, const uint8_t in[16],
struct bt_mesh_key *out);
/**
* @brief Export raw key bytes from mesh key structure
*
* @param out 16-byte output buffer
* @param in Input mesh key structure
*
* @return 0 on success, negative error code otherwise
*/
int bt_mesh_key_export(uint8_t out[16], const struct bt_mesh_key *in);
/**
* @brief Assign (copy) a mesh key
*
* @param dst Destination mesh key
* @param src Source mesh key
*/
void bt_mesh_key_assign(struct bt_mesh_key *dst, const struct bt_mesh_key *src);
/**
* @brief Destroy a mesh key
*
* Releases any resources associated with the key.
*
* @param key Mesh key to destroy
*
* @return 0 on success, negative error code otherwise
*/
int bt_mesh_key_destroy(const struct bt_mesh_key *key);
/**
* @brief Compare a raw key with a mesh key
*
* @param raw_key 16-byte raw key
* @param key Mesh key structure to compare
*
* @return 0 if equal, non-zero otherwise
*/
int bt_mesh_key_compare(const uint8_t raw_key[16], const struct bt_mesh_key *key);
/**
* @brief AES encryption (little-endian byte order)
*
* The key and plaintext are byte-swapped before encryption,
* and the result is byte-swapped after encryption.
*
* @param key 16-byte key
* @param plaintext 16-byte plaintext
* @param enc_data 16-byte output buffer
*
* @return 0 on success, negative error code otherwise
*/
int bt_mesh_encrypt_le(const uint8_t key[16], const uint8_t plaintext[16],
uint8_t enc_data[16]);
/**
* @brief AES encryption (big-endian byte order)
*
* Standard AES-ECB encryption without byte swapping.
*
* @param key 16-byte key
* @param plaintext 16-byte plaintext
* @param enc_data 16-byte output buffer
*
* @return 0 on success, negative error code otherwise
*/
int bt_mesh_encrypt_be(const uint8_t key[16], const uint8_t plaintext[16],
uint8_t enc_data[16]);
#ifdef __cplusplus
}
#endif
#endif /* _BLE_MESH_CRYPTO_H_ */
@@ -1,7 +1,7 @@
/*
* SPDX-FileCopyrightText: 2017 Nordic Semiconductor ASA
* SPDX-FileCopyrightText: 2015-2016 Intel Corporation
* SPDX-FileContributor: 2018-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileContributor: 2018-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -17,14 +17,6 @@
#include "p_256_ecc_pp.h"
#include "osi/future.h"
#include "device/controller.h"
#if CONFIG_MBEDTLS_HARDWARE_AES
#include "mbedtls/aes.h"
#endif
#include <tinycrypt/aes.h>
#include <tinycrypt/constants.h>
#include "mesh/hci.h"
#include "mesh/adapter.h"
#include "mesh/common.h"
@@ -56,10 +48,6 @@ struct bt_mesh_dev bt_mesh_dev;
*/
#define BLE_MESH_DEV 0
/* P-256 Variables */
static uint8_t bt_mesh_public_key[64];
static uint8_t bt_mesh_private_key[32];
/* Scan related functions */
static bt_mesh_scan_cb_t *bt_mesh_scan_dev_found_cb;
@@ -2481,185 +2469,9 @@ void bt_mesh_gatt_deinit(void)
void bt_mesh_adapt_init(void)
{
/* initialization of P-256 parameters */
p_256_init_curve(KEY_LENGTH_DWORDS_P256);
/* Set "bt_mesh_dev.flags" to 0 (only the "BLE_MESH_DEV_HAS_PUB_KEY"
* flag is used) here, because we need to make sure each time after
* the private key is initialized, a corresponding public key must
* be generated.
*/
/* Use unified crypto module initialization */
bt_mesh_crypto_init();
bt_mesh_atomic_set(bt_mesh_dev.flags, 0);
bt_mesh_rand(bt_mesh_private_key, sizeof(bt_mesh_private_key));
}
void bt_mesh_set_private_key(const uint8_t pri_key[32])
{
memcpy(bt_mesh_private_key, pri_key, 32);
}
const uint8_t *bt_mesh_pub_key_get(void)
{
uint8_t private_key[32] = {0};
Point public_key = {0};
if (bt_mesh_atomic_test_bit(bt_mesh_dev.flags, BLE_MESH_DEV_HAS_PUB_KEY)) {
return bt_mesh_public_key;
}
/* BLE Mesh BQB test case MESH/NODE/PROV/UPD/BV-12-C requires
* different public key for each provisioning procedure.
* Note: if enabled, when Provisioner provision multiple devices
* at the same time, this may cause invalid confirmation value.
*
* Use the following code for generating different private key
* for each provisioning procedure.
*
* if (bt_mesh_rand(bt_mesh_private_key, BT_OCTET32_LEN)) {
* BT_ERR("%s, Unable to generate bt_mesh_private_key", __func__);
* return NULL;
* }
*/
memcpy(private_key, bt_mesh_private_key, BT_OCTET32_LEN);
ECC_PointMult(&public_key, &(curve_p256.G), (DWORD *)private_key, KEY_LENGTH_DWORDS_P256);
memcpy(bt_mesh_public_key, public_key.x, BT_OCTET32_LEN);
memcpy(bt_mesh_public_key + BT_OCTET32_LEN, public_key.y, BT_OCTET32_LEN);
bt_mesh_atomic_set_bit(bt_mesh_dev.flags, BLE_MESH_DEV_HAS_PUB_KEY);
BT_DBG("Public Key %s", bt_hex(bt_mesh_public_key, sizeof(bt_mesh_public_key)));
return bt_mesh_public_key;
}
bool bt_mesh_check_public_key(const uint8_t key[64])
{
struct p256_pub_key {
uint8_t x[32];
uint8_t y[32];
} check = {0};
sys_memcpy_swap(check.x, key, 32);
sys_memcpy_swap(check.y, key + 32, 32);
return ECC_CheckPointIsInElliCur_P256((Point *)&check);
}
int bt_mesh_dh_key_gen(const uint8_t remote_pub_key[64], uint8_t dhkey[32])
{
uint8_t private_key[32] = {0};
Point peer_pub_key = {0};
Point new_pub_key = {0};
BT_DBG("private key = %s", bt_hex(bt_mesh_private_key, BT_OCTET32_LEN));
memcpy(private_key, bt_mesh_private_key, BT_OCTET32_LEN);
memcpy(peer_pub_key.x, remote_pub_key, BT_OCTET32_LEN);
memcpy(peer_pub_key.y, &remote_pub_key[BT_OCTET32_LEN], BT_OCTET32_LEN);
BT_DBG("remote public key x = %s", bt_hex(peer_pub_key.x, BT_OCTET32_LEN));
BT_DBG("remote public key y = %s", bt_hex(peer_pub_key.y, BT_OCTET32_LEN));
ECC_PointMult(&new_pub_key, &peer_pub_key, (DWORD *)private_key, KEY_LENGTH_DWORDS_P256);
BT_DBG("new public key x = %s", bt_hex(new_pub_key.x, 32));
BT_DBG("new public key y = %s", bt_hex(new_pub_key.y, 32));
memcpy(dhkey, new_pub_key.x, 32);
return 0;
}
int bt_mesh_encrypt_le(const uint8_t key[16], const uint8_t plaintext[16],
uint8_t enc_data[16])
{
uint8_t tmp[16] = {0};
BT_DBG("key %s plaintext %s", bt_hex(key, 16), bt_hex(plaintext, 16));
#if CONFIG_MBEDTLS_HARDWARE_AES
mbedtls_aes_context ctx = {0};
mbedtls_aes_init(&ctx);
sys_memcpy_swap(tmp, key, 16);
if (mbedtls_aes_setkey_enc(&ctx, tmp, 128) != 0) {
mbedtls_aes_free(&ctx);
return -EINVAL;
}
sys_memcpy_swap(tmp, plaintext, 16);
if (mbedtls_aes_crypt_ecb(&ctx, MBEDTLS_AES_ENCRYPT,
tmp, enc_data) != 0) {
mbedtls_aes_free(&ctx);
return -EINVAL;
}
mbedtls_aes_free(&ctx);
#else /* CONFIG_MBEDTLS_HARDWARE_AES */
struct tc_aes_key_sched_struct s = {0};
sys_memcpy_swap(tmp, key, 16);
if (tc_aes128_set_encrypt_key(&s, tmp) == TC_CRYPTO_FAIL) {
return -EINVAL;
}
sys_memcpy_swap(tmp, plaintext, 16);
if (tc_aes_encrypt(enc_data, tmp, &s) == TC_CRYPTO_FAIL) {
return -EINVAL;
}
#endif /* CONFIG_MBEDTLS_HARDWARE_AES */
sys_mem_swap(enc_data, 16);
BT_DBG("enc_data %s", bt_hex(enc_data, 16));
return 0;
}
int bt_mesh_encrypt_be(const uint8_t key[16], const uint8_t plaintext[16],
uint8_t enc_data[16])
{
BT_DBG("key %s plaintext %s", bt_hex(key, 16), bt_hex(plaintext, 16));
#if CONFIG_MBEDTLS_HARDWARE_AES
mbedtls_aes_context ctx = {0};
mbedtls_aes_init(&ctx);
if (mbedtls_aes_setkey_enc(&ctx, key, 128) != 0) {
mbedtls_aes_free(&ctx);
return -EINVAL;
}
if (mbedtls_aes_crypt_ecb(&ctx, MBEDTLS_AES_ENCRYPT,
plaintext, enc_data) != 0) {
mbedtls_aes_free(&ctx);
return -EINVAL;
}
mbedtls_aes_free(&ctx);
#else /* CONFIG_MBEDTLS_HARDWARE_AES */
struct tc_aes_key_sched_struct s = {0};
if (tc_aes128_set_encrypt_key(&s, key) == TC_CRYPTO_FAIL) {
return -EINVAL;
}
if (tc_aes_encrypt(enc_data, plaintext, &s) == TC_CRYPTO_FAIL) {
return -EINVAL;
}
#endif /* CONFIG_MBEDTLS_HARDWARE_AES */
BT_DBG("enc_data %s", bt_hex(enc_data, 16));
return 0;
}
#if CONFIG_BLE_MESH_USE_DUPLICATE_SCAN
+5 -350
View File
@@ -2,7 +2,7 @@
/*
* SPDX-FileCopyrightText: 2017 Intel Corporation
* SPDX-FileContributor: 2018-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileContributor: 2018-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -11,12 +11,6 @@
#include <stdbool.h>
#include <errno.h>
#include <tinycrypt/aes.h>
#include <tinycrypt/constants.h>
#include <tinycrypt/cmac_mode.h>
#include <tinycrypt/hmac.h>
#include <tinycrypt/sha256.h>
#include "crypto.h"
#include "mesh/config.h"
#include "mesh/common.h"
@@ -29,29 +23,7 @@
#define NET_MIC_LEN(pdu) (((pdu)[1] & 0x80) ? 8 : 4)
#define APP_MIC_LEN(aszmic) ((aszmic) ? 8 : 4)
int bt_mesh_aes_cmac(const uint8_t key[16], struct bt_mesh_sg *sg,
size_t sg_len, uint8_t mac[16])
{
struct tc_aes_key_sched_struct sched = {0};
struct tc_cmac_struct state = {0};
if (tc_cmac_setup(&state, key, &sched) == TC_CRYPTO_FAIL) {
return -EIO;
}
for (; sg_len; sg_len--, sg++) {
if (tc_cmac_update(&state, sg->data,
sg->len) == TC_CRYPTO_FAIL) {
return -EIO;
}
}
if (tc_cmac_final(mac, &state) == TC_CRYPTO_FAIL) {
return -EIO;
}
return 0;
}
/* bt_mesh_aes_cmac is now mapped to bt_mesh_aes_cmac_raw_key from common crypto module */
int bt_mesh_k1(const uint8_t *ikm, size_t ikm_len, const uint8_t salt[16],
const char *info, uint8_t okm[16])
@@ -199,326 +171,9 @@ int bt_mesh_id128(const uint8_t n[16], const char *s, uint8_t out[16])
return bt_mesh_k1(n, 16, salt, id128, out);
}
static int bt_mesh_ccm_decrypt(const uint8_t key[16], uint8_t nonce[13],
const uint8_t *enc_msg, size_t msg_len,
const uint8_t *aad, size_t aad_len,
uint8_t *out_msg, size_t mic_size)
{
uint8_t msg[16] = {0}, pmsg[16] = {0}, cmic[16] = {0},
cmsg[16] = {0}, Xn[16] = {0}, mic[16] = {0};
uint16_t last_blk = 0U, blk_cnt = 0U;
size_t i = 0U, j = 0U;
int err = 0;
if (msg_len < 1 || aad_len >= 0xff00) {
return -EINVAL;
}
/* C_mic = e(AppKey, 0x01 || nonce || 0x0000) */
pmsg[0] = 0x01;
memcpy(pmsg + 1, nonce, 13);
sys_put_be16(0x0000, pmsg + 14);
err = bt_mesh_encrypt_be(key, pmsg, cmic);
if (err) {
return err;
}
/* X_0 = e(AppKey, 0x09 || nonce || length) */
if (mic_size == sizeof(uint64_t)) {
pmsg[0] = 0x19 | (aad_len ? 0x40 : 0x00);
} else {
pmsg[0] = 0x09 | (aad_len ? 0x40 : 0x00);
}
memcpy(pmsg + 1, nonce, 13);
sys_put_be16(msg_len, pmsg + 14);
err = bt_mesh_encrypt_be(key, pmsg, Xn);
if (err) {
return err;
}
/* If AAD is being used to authenticate, include it here */
if (aad_len) {
sys_put_be16(aad_len, pmsg);
for (i = 0; i < sizeof(uint16_t); i++) {
pmsg[i] = Xn[i] ^ pmsg[i];
}
j = 0;
aad_len += sizeof(uint16_t);
while (aad_len > 16) {
do {
pmsg[i] = Xn[i] ^ aad[j];
i++, j++;
} while (i < 16);
aad_len -= 16;
i = 0;
err = bt_mesh_encrypt_be(key, pmsg, Xn);
if (err) {
return err;
}
}
for (; i < aad_len; i++, j++) {
pmsg[i] = Xn[i] ^ aad[j];
}
for (i = aad_len; i < 16; i++) {
pmsg[i] = Xn[i];
}
err = bt_mesh_encrypt_be(key, pmsg, Xn);
if (err) {
return err;
}
}
last_blk = msg_len % 16;
blk_cnt = (msg_len + 15) / 16;
if (!last_blk) {
last_blk = 16U;
}
for (j = 0; j < blk_cnt; j++) {
if (j + 1 == blk_cnt) {
/* C_1 = e(AppKey, 0x01 || nonce || 0x0001) */
pmsg[0] = 0x01;
memcpy(pmsg + 1, nonce, 13);
sys_put_be16(j + 1, pmsg + 14);
err = bt_mesh_encrypt_be(key, pmsg, cmsg);
if (err) {
return err;
}
/* Encrypted = Payload[0-15] ^ C_1 */
for (i = 0; i < last_blk; i++) {
msg[i] = enc_msg[(j * 16) + i] ^ cmsg[i];
}
memcpy(out_msg + (j * 16), msg, last_blk);
/* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */
for (i = 0; i < last_blk; i++) {
pmsg[i] = Xn[i] ^ msg[i];
}
for (i = last_blk; i < 16; i++) {
pmsg[i] = Xn[i] ^ 0x00;
}
err = bt_mesh_encrypt_be(key, pmsg, Xn);
if (err) {
return err;
}
/* MIC = C_mic ^ X_1 */
for (i = 0; i < sizeof(mic); i++) {
mic[i] = cmic[i] ^ Xn[i];
}
} else {
/* C_1 = e(AppKey, 0x01 || nonce || 0x0001) */
pmsg[0] = 0x01;
memcpy(pmsg + 1, nonce, 13);
sys_put_be16(j + 1, pmsg + 14);
err = bt_mesh_encrypt_be(key, pmsg, cmsg);
if (err) {
return err;
}
/* Encrypted = Payload[0-15] ^ C_1 */
for (i = 0; i < 16; i++) {
msg[i] = enc_msg[(j * 16) + i] ^ cmsg[i];
}
memcpy(out_msg + (j * 16), msg, 16);
/* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */
for (i = 0; i < 16; i++) {
pmsg[i] = Xn[i] ^ msg[i];
}
err = bt_mesh_encrypt_be(key, pmsg, Xn);
if (err) {
return err;
}
}
}
if (memcmp(mic, enc_msg + msg_len, mic_size)) {
return -EBADMSG;
}
return 0;
}
static int bt_mesh_ccm_encrypt(const uint8_t key[16], uint8_t nonce[13],
const uint8_t *msg, size_t msg_len,
const uint8_t *aad, size_t aad_len,
uint8_t *out_msg, size_t mic_size)
{
uint8_t pmsg[16] = {0}, cmic[16] = {0}, cmsg[16] = {0},
mic[16] = {0}, Xn[16] = {0};
uint16_t blk_cnt = 0U, last_blk = 0U;
size_t i = 0U, j = 0U;
int err = 0;
BT_DBG("CCMEncrypt");
BT_DBG("Key %s", bt_hex(key, 16));
BT_DBG("Nonce %s", bt_hex(nonce, 13));
BT_DBG("Len %u: %s", msg_len, bt_hex(msg, msg_len));
BT_DBG("AADLen %u MicSize %u", aad_len, mic_size);
/* Unsupported AAD size */
if (aad_len >= 0xff00) {
return -EINVAL;
}
/* C_mic = e(AppKey, 0x01 || nonce || 0x0000) */
pmsg[0] = 0x01;
memcpy(pmsg + 1, nonce, 13);
sys_put_be16(0x0000, pmsg + 14);
err = bt_mesh_encrypt_be(key, pmsg, cmic);
if (err) {
return err;
}
/* X_0 = e(AppKey, 0x09 || nonce || length) */
if (mic_size == sizeof(uint64_t)) {
pmsg[0] = 0x19 | (aad_len ? 0x40 : 0x00);
} else {
pmsg[0] = 0x09 | (aad_len ? 0x40 : 0x00);
}
memcpy(pmsg + 1, nonce, 13);
sys_put_be16(msg_len, pmsg + 14);
err = bt_mesh_encrypt_be(key, pmsg, Xn);
if (err) {
return err;
}
/* If AAD is being used to authenticate, include it here */
if (aad_len) {
sys_put_be16(aad_len, pmsg);
for (i = 0; i < sizeof(uint16_t); i++) {
pmsg[i] = Xn[i] ^ pmsg[i];
}
j = 0;
aad_len += sizeof(uint16_t);
while (aad_len > 16) {
do {
pmsg[i] = Xn[i] ^ aad[j];
i++, j++;
} while (i < 16);
aad_len -= 16;
i = 0;
err = bt_mesh_encrypt_be(key, pmsg, Xn);
if (err) {
return err;
}
}
for (; i < aad_len; i++, j++) {
pmsg[i] = Xn[i] ^ aad[j];
}
for (i = aad_len; i < 16; i++) {
pmsg[i] = Xn[i];
}
err = bt_mesh_encrypt_be(key, pmsg, Xn);
if (err) {
return err;
}
}
last_blk = msg_len % 16;
blk_cnt = (msg_len + 15) / 16;
if (!last_blk) {
last_blk = 16U;
}
for (j = 0; j < blk_cnt; j++) {
if (j + 1 == blk_cnt) {
/* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */
for (i = 0; i < last_blk; i++) {
pmsg[i] = Xn[i] ^ msg[(j * 16) + i];
}
for (i = last_blk; i < 16; i++) {
pmsg[i] = Xn[i] ^ 0x00;
}
err = bt_mesh_encrypt_be(key, pmsg, Xn);
if (err) {
return err;
}
/* MIC = C_mic ^ X_1 */
for (i = 0; i < sizeof(mic); i++) {
mic[i] = cmic[i] ^ Xn[i];
}
/* C_1 = e(AppKey, 0x01 || nonce || 0x0001) */
pmsg[0] = 0x01;
memcpy(pmsg + 1, nonce, 13);
sys_put_be16(j + 1, pmsg + 14);
err = bt_mesh_encrypt_be(key, pmsg, cmsg);
if (err) {
return err;
}
/* Encrypted = Payload[0-15] ^ C_1 */
for (i = 0; i < last_blk; i++) {
out_msg[(j * 16) + i] =
msg[(j * 16) + i] ^ cmsg[i];
}
} else {
/* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */
for (i = 0; i < 16; i++) {
pmsg[i] = Xn[i] ^ msg[(j * 16) + i];
}
err = bt_mesh_encrypt_be(key, pmsg, Xn);
if (err) {
return err;
}
/* C_1 = e(AppKey, 0x01 || nonce || 0x0001) */
pmsg[0] = 0x01;
memcpy(pmsg + 1, nonce, 13);
sys_put_be16(j + 1, pmsg + 14);
err = bt_mesh_encrypt_be(key, pmsg, cmsg);
if (err) {
return err;
}
/* Encrypted = Payload[0-15] ^ C_N */
for (i = 0; i < 16; i++) {
out_msg[(j * 16) + i] =
msg[(j * 16) + i] ^ cmsg[i];
}
}
}
memcpy(out_msg + msg_len, mic, mic_size);
return 0;
}
/* Use the unified crypto module for CCM operations */
#define bt_mesh_ccm_decrypt bt_mesh_ccm_decrypt_raw_key
#define bt_mesh_ccm_encrypt bt_mesh_ccm_encrypt_raw_key
#if CONFIG_BLE_MESH_PROXY
static void create_proxy_nonce(uint8_t nonce[13], const uint8_t *pdu,
+6 -15
View File
@@ -2,7 +2,7 @@
/*
* SPDX-FileCopyrightText: 2017 Intel Corporation
* SPDX-FileContributor: 2018-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileContributor: 2018-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -12,26 +12,17 @@
#include <string.h>
#include "mesh/buf.h"
#include "mesh/crypto.h" /* Include common crypto API */
#ifdef __cplusplus
extern "C" {
#endif
struct bt_mesh_sg {
const void *data;
size_t len;
};
/* Map bt_mesh_aes_cmac to bt_mesh_aes_cmac_raw_key from common crypto module.
* struct bt_mesh_sg is defined in mesh/crypto.h */
#define bt_mesh_aes_cmac bt_mesh_aes_cmac_raw_key
int bt_mesh_aes_cmac(const uint8_t key[16], struct bt_mesh_sg *sg,
size_t sg_len, uint8_t mac[16]);
static inline int bt_mesh_aes_cmac_one(const uint8_t key[16], const void *m,
size_t len, uint8_t mac[16])
{
struct bt_mesh_sg sg = { m, len };
return bt_mesh_aes_cmac(key, &sg, 1, mac);
}
/* bt_mesh_aes_cmac_one is defined as inline in mesh/crypto.h */
static inline bool bt_mesh_s1(const char *m, uint8_t salt[16])
{
@@ -1,7 +1,7 @@
/*
* SPDX-FileCopyrightText: 2017 Nordic Semiconductor ASA
* SPDX-FileCopyrightText: 2015-2017 Intel Corporation
* SPDX-FileContributor: 2018-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileContributor: 2018-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -15,6 +15,7 @@
#include "mesh/utils.h"
#include "mesh/uuid.h"
#include "mesh/buf.h"
#include "mesh/crypto.h"
#ifdef __cplusplus
extern "C" {
@@ -932,20 +933,6 @@ void bt_mesh_gatt_deinit(void);
void bt_mesh_adapt_init(void);
void bt_mesh_set_private_key(const uint8_t pri_key[32]);
const uint8_t *bt_mesh_pub_key_get(void);
bool bt_mesh_check_public_key(const uint8_t key[64]);
int bt_mesh_dh_key_gen(const uint8_t remote_pub_key[64], uint8_t dhkey[32]);
int bt_mesh_encrypt_le(const uint8_t key[16], const uint8_t plaintext[16],
uint8_t enc_data[16]);
int bt_mesh_encrypt_be(const uint8_t key[16], const uint8_t plaintext[16],
uint8_t enc_data[16]);
enum {
BLE_MESH_EXCEP_LIST_SUB_CODE_ADD = 0,
BLE_MESH_EXCEP_LIST_SUB_CODE_REMOVE,
@@ -1,7 +1,7 @@
/*
* SPDX-FileCopyrightText: 2017 Nordic Semiconductor ASA
* SPDX-FileCopyrightText: 2015-2016 Intel Corporation
* SPDX-FileContributor: 2018-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileContributor: 2018-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -10,20 +10,12 @@
#include "btc/btc_task.h"
#include "osi/alarm.h"
#include "mbedtls/aes.h"
#include "mbedtls/ecp.h"
#include "host/ble_hs.h"
#include "host/ble_uuid.h"
#include "host/ble_att.h"
#include "host/ble_gatt.h"
#include "services/gap/ble_svc_gap.h"
#include "services/gatt/ble_svc_gatt.h"
#include <tinycrypt/aes.h>
#include <tinycrypt/constants.h>
#include "mesh/hci.h"
#include "mesh/common.h"
#include "prov_pvnr.h"
@@ -65,10 +57,6 @@
static uint16_t proxy_svc_start_handle, prov_svc_start_handle;
struct bt_mesh_dev bt_mesh_dev;
/* P-256 Variables */
static uint8_t bt_mesh_public_key[64];
static uint8_t bt_mesh_private_key[32];
/* Scan related functions */
static bt_mesh_scan_cb_t *bt_mesh_scan_dev_found_cb;
#if CONFIG_BLE_MESH_NODE
@@ -2606,199 +2594,11 @@ void bt_mesh_gatt_deinit(void)
}
#endif /* CONFIG_BLE_MESH_DEINIT */
void ble_sm_alg_ecc_init(void);
void bt_mesh_adapt_init(void)
{
/* initialization of P-256 parameters */
ble_sm_alg_ecc_init();
/* Set "bt_mesh_dev.flags" to 0 (only the "BLE_MESH_DEV_HAS_PUB_KEY"
* flag is used) here, because we need to make sure each time after
* the private key is initialized, a corresponding public key must
* be generated.
*/
/* Use unified crypto module initialization */
bt_mesh_crypto_init();
bt_mesh_atomic_set(bt_mesh_dev.flags, 0);
bt_mesh_rand(bt_mesh_private_key, sizeof(bt_mesh_private_key));
}
void bt_mesh_set_private_key(const uint8_t pri_key[32])
{
memcpy(bt_mesh_private_key, pri_key, 32);
}
int ble_sm_alg_gen_key_pair(uint8_t *pub, uint8_t *priv);
const uint8_t *bt_mesh_pub_key_get(void)
{
uint8_t pri_key[32] = {0};
#if 1
if (bt_mesh_atomic_test_bit(bt_mesh_dev.flags, BLE_MESH_DEV_HAS_PUB_KEY)) {
return bt_mesh_public_key;
}
#else
/* BLE Mesh BQB test case MESH/NODE/PROV/UPD/BV-12-C requires
* different public key for each provisioning procedure.
* Note: if enabled, when Provisioner provision multiple devices
* at the same time, this may cause invalid confirmation value.
*/
if (bt_mesh_rand(bt_mesh_private_key, 32)) {
BT_ERR("%s, Unable to generate bt_mesh_private_key", __func__);
return NULL;
}
#endif
int rc = ble_sm_alg_gen_key_pair(bt_mesh_public_key, pri_key);
if (rc != 0) {
BT_ERR("Failed to generate the key pair");
return NULL;
}
memcpy(bt_mesh_private_key, pri_key, 32);
bt_mesh_atomic_set_bit(bt_mesh_dev.flags, BLE_MESH_DEV_HAS_PUB_KEY);
BT_DBG("Public Key %s", bt_hex(bt_mesh_public_key, sizeof(bt_mesh_public_key)));
return bt_mesh_public_key;
}
bool bt_mesh_check_public_key(const uint8_t key[64])
{
struct mbedtls_ecp_point pt = {0};
mbedtls_ecp_group grp = {0};
bool rc = false;
uint8_t pub[65] = {0};
/* Hardcoded first byte of pub key for MBEDTLS_ECP_PF_UNCOMPRESSED */
pub[0] = 0x04;
memcpy(&pub[1], key, 64);
/* Initialize the required structures here */
mbedtls_ecp_point_init(&pt);
mbedtls_ecp_group_init(&grp);
/* Below 3 steps are to validate public key on curve secp256r1 */
if (mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SECP256R1) != 0) {
goto exit;
}
if (mbedtls_ecp_point_read_binary(&grp, &pt, pub, 65) != 0) {
goto exit;
}
if (mbedtls_ecp_check_pubkey(&grp, &pt) != 0) {
goto exit;
}
rc = true;
exit:
mbedtls_ecp_point_free(&pt);
mbedtls_ecp_group_free(&grp);
return rc;
}
int ble_sm_alg_gen_dhkey(uint8_t *peer_pub_key_x, uint8_t *peer_pub_key_y,
uint8_t *our_priv_key, uint8_t *out_dhkey);
int bt_mesh_dh_key_gen(const uint8_t remote_pub_key[64], uint8_t dhkey[32])
{
BT_DBG("private key = %s", bt_hex(bt_mesh_private_key, 32));
return ble_sm_alg_gen_dhkey((uint8_t *)&remote_pub_key[0], (uint8_t *)&remote_pub_key[32],
bt_mesh_private_key, dhkey);
}
int bt_mesh_encrypt_le(const uint8_t key[16], const uint8_t plaintext[16],
uint8_t enc_data[16])
{
uint8_t tmp[16] = {0};
BT_DBG("key %s plaintext %s", bt_hex(key, 16), bt_hex(plaintext, 16));
#if CONFIG_MBEDTLS_HARDWARE_AES
mbedtls_aes_context ctx = {0};
mbedtls_aes_init(&ctx);
sys_memcpy_swap(tmp, key, 16);
if (mbedtls_aes_setkey_enc(&ctx, tmp, 128) != 0) {
mbedtls_aes_free(&ctx);
return -EINVAL;
}
sys_memcpy_swap(tmp, plaintext, 16);
if (mbedtls_aes_crypt_ecb(&ctx, MBEDTLS_AES_ENCRYPT,
tmp, enc_data) != 0) {
mbedtls_aes_free(&ctx);
return -EINVAL;
}
mbedtls_aes_free(&ctx);
#else /* CONFIG_MBEDTLS_HARDWARE_AES */
struct tc_aes_key_sched_struct s = {0};
sys_memcpy_swap(tmp, key, 16);
if (tc_aes128_set_encrypt_key(&s, tmp) == TC_CRYPTO_FAIL) {
return -EINVAL;
}
sys_memcpy_swap(tmp, plaintext, 16);
if (tc_aes_encrypt(enc_data, tmp, &s) == TC_CRYPTO_FAIL) {
return -EINVAL;
}
#endif /* CONFIG_MBEDTLS_HARDWARE_AES */
sys_mem_swap(enc_data, 16);
BT_DBG("enc_data %s", bt_hex(enc_data, 16));
return 0;
}
int bt_mesh_encrypt_be(const uint8_t key[16], const uint8_t plaintext[16],
uint8_t enc_data[16])
{
BT_DBG("key %s plaintext %s", bt_hex(key, 16), bt_hex(plaintext, 16));
#if CONFIG_MBEDTLS_HARDWARE_AES
mbedtls_aes_context ctx = {0};
mbedtls_aes_init(&ctx);
if (mbedtls_aes_setkey_enc(&ctx, key, 128) != 0) {
mbedtls_aes_free(&ctx);
return -EINVAL;
}
if (mbedtls_aes_crypt_ecb(&ctx, MBEDTLS_AES_ENCRYPT,
plaintext, enc_data) != 0) {
mbedtls_aes_free(&ctx);
return -EINVAL;
}
mbedtls_aes_free(&ctx);
#else /* CONFIG_MBEDTLS_HARDWARE_AES */
struct tc_aes_key_sched_struct s = {0};
if (tc_aes128_set_encrypt_key(&s, key) == TC_CRYPTO_FAIL) {
return -EINVAL;
}
if (tc_aes_encrypt(enc_data, plaintext, &s) == TC_CRYPTO_FAIL) {
return -EINVAL;
}
#endif /* CONFIG_MBEDTLS_HARDWARE_AES */
BT_DBG("enc_data %s", bt_hex(enc_data, 16));
return 0;
}
#if CONFIG_BLE_MESH_USE_DUPLICATE_SCAN
+18 -19
View File
@@ -2,7 +2,7 @@
/*
* SPDX-FileCopyrightText: 2017 Intel Corporation
* SPDX-FileContributor: 2018-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileContributor: 2018-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -616,7 +616,7 @@ int bt_mesh_input_string(const char *str)
static void send_pub_key(void)
{
const uint8_t *key = NULL;
uint8_t pub_key[64] = {0};
uint8_t dhkey[32] = {0};
PROV_BUF(buf, 65);
@@ -625,8 +625,8 @@ static void send_pub_key(void)
* buffer as a temporary storage location. The validating
* of the remote public key is finished when it is received.
*/
sys_memcpy_swap(buf.data, &prov_link.conf_inputs[17], 32);
sys_memcpy_swap(&buf.data[32], &prov_link.conf_inputs[49], 32);
memcpy(buf.data, &prov_link.conf_inputs[17], 32);
memcpy(&buf.data[32], &prov_link.conf_inputs[49], 32);
if (bt_mesh_dh_key_gen(buf.data, dhkey)) {
BT_ERR("Unable to generate DHKey");
@@ -634,26 +634,25 @@ static void send_pub_key(void)
return;
}
sys_memcpy_swap(prov_link.dhkey, dhkey, 32);
memcpy(prov_link.dhkey, dhkey, 32);
BT_DBG("DHkey: %s", bt_hex(prov_link.dhkey, 32));
bt_mesh_atomic_set_bit(prov_link.flags, HAVE_DHKEY);
key = bt_mesh_pub_key_get();
if (!key) {
if (bt_mesh_pub_key_copy(pub_key)) {
BT_ERR("No public key available");
close_link(PROV_ERR_UNEXP_ERR);
return;
}
BT_DBG("Local Public Key: %s", bt_hex(key, 64));
BT_DBG("Local Public Key: %s", bt_hex(pub_key, 64));
bt_mesh_prov_buf_init(&buf, PROV_PUB_KEY);
/* Swap X and Y halves independently to big-endian */
sys_memcpy_swap(net_buf_simple_add(&buf, 32), key, 32);
sys_memcpy_swap(net_buf_simple_add(&buf, 32), &key[32], 32);
/* Public key is already in big-endian format from bt_mesh_pub_key_copy() */
memcpy(net_buf_simple_add(&buf, 32), pub_key, 32);
memcpy(net_buf_simple_add(&buf, 32), &pub_key[32], 32);
memcpy(&prov_link.conf_inputs[81], &buf.data[1], 64);
@@ -673,8 +672,8 @@ static int bt_mesh_calc_dh_key(void)
/* Copy remote key in little-endian for generating DHKey.
* X and Y halves are swapped independently.
*/
sys_memcpy_swap(&pub_key[0], &prov_link.conf_inputs[17], 32);
sys_memcpy_swap(&pub_key[32], &prov_link.conf_inputs[49], 32);
memcpy(&pub_key[0], &prov_link.conf_inputs[17], 32);
memcpy(&pub_key[32], &prov_link.conf_inputs[49], 32);
if (bt_mesh_dh_key_gen(pub_key, dhkey)) {
BT_ERR("Unable to generate DHKey");
@@ -682,7 +681,7 @@ static int bt_mesh_calc_dh_key(void)
return -EIO;
}
sys_memcpy_swap(prov_link.dhkey, dhkey, 32);
memcpy(prov_link.dhkey, dhkey, 32);
BT_DBG("DHkey: %s", bt_hex(prov_link.dhkey, 32));
@@ -704,6 +703,8 @@ int bt_mesh_set_oob_pub_key(const uint8_t pub_key_x[32],
const uint8_t pub_key_y[32],
const uint8_t pri_key[32])
{
uint8_t privkey[32] = {0};
if (!pub_key_x || !pub_key_y || !pri_key) {
BT_ERR("%s, Invalid parameter", __func__);
return -EINVAL;
@@ -715,7 +716,8 @@ int bt_mesh_set_oob_pub_key(const uint8_t pub_key_x[32],
*/
sys_memcpy_swap(&prov_link.conf_inputs[81], pub_key_x, 32);
sys_memcpy_swap(&prov_link.conf_inputs[81] + 32, pub_key_y, 32);
bt_mesh_set_private_key(pri_key);
sys_memcpy_swap(privkey, pri_key, 32);
bt_mesh_set_private_key(privkey);
bt_mesh_atomic_set_bit(prov_link.flags, OOB_PUB_KEY);
@@ -1558,8 +1560,6 @@ static void protocol_timeout(struct k_work *work)
int bt_mesh_prov_init(void)
{
const uint8_t *key = NULL;
if (bt_mesh_prov_get() == NULL) {
BT_ERR("No provisioning context provided");
return -EINVAL;
@@ -1574,8 +1574,7 @@ int bt_mesh_prov_init(void)
__ASSERT(bt_mesh_prov_get()->uuid, "Device UUID not initialized");
key = bt_mesh_pub_key_get();
if (!key) {
if (bt_mesh_pub_key_gen()) {
BT_ERR("Failed to generate public key");
return -EIO;
}
+11 -14
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2017-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -1764,8 +1764,8 @@ static void prov_gen_dh_key(struct bt_mesh_prov_link *link)
/* Copy public key in little-endian for generating DHKey.
* X and Y halves are swapped independently.
*/
sys_memcpy_swap(&pub_key[0], &link->conf_inputs[81], 32);
sys_memcpy_swap(&pub_key[32], &link->conf_inputs[113], 32);
memcpy(&pub_key[0], &link->conf_inputs[81], 32);
memcpy(&pub_key[32], &link->conf_inputs[113], 32);
if (bt_mesh_dh_key_gen(pub_key, dhkey)) {
BT_ERR("Failed to generate DHKey");
@@ -1773,7 +1773,7 @@ static void prov_gen_dh_key(struct bt_mesh_prov_link *link)
return;
}
sys_memcpy_swap(link->dhkey, dhkey, 32);
memcpy(link->dhkey, dhkey, 32);
BT_DBG("DHKey: %s", bt_hex(link->dhkey, 32));
@@ -1847,23 +1847,22 @@ static void prov_gen_dh_key(struct bt_mesh_prov_link *link)
static void send_pub_key(struct bt_mesh_prov_link *link)
{
const uint8_t *key = NULL;
uint8_t pub_key[64] = {0};
PROV_BUF(buf, 65);
key = bt_mesh_pub_key_get();
if (!key) {
if (bt_mesh_pub_key_copy(pub_key)) {
BT_ERR("No public key available");
close_link(link, CLOSE_REASON_FAILED);
return;
}
BT_DBG("Local Public Key: %s", bt_hex(key, 64));
BT_DBG("Local Public Key: %s", bt_hex(pub_key, 64));
bt_mesh_prov_buf_init(&buf, PROV_PUB_KEY);
/* Swap X and Y halves independently to big-endian */
sys_memcpy_swap(net_buf_simple_add(&buf, 32), key, 32);
sys_memcpy_swap(net_buf_simple_add(&buf, 32), &key[32], 32);
/* Public key is already in big-endian format from bt_mesh_pub_key_copy() */
memcpy(net_buf_simple_add(&buf, 32), pub_key, 32);
memcpy(net_buf_simple_add(&buf, 32), &pub_key[32], 32);
/* Store provisioner public key value in conf_inputs */
memcpy(&link->conf_inputs[17], &buf.data[1], 64);
@@ -2819,7 +2818,6 @@ static void protocol_timeout(struct k_work *work)
int bt_mesh_provisioner_prov_init(void)
{
const uint8_t *key = NULL;
int i;
if (bt_mesh_prov_get() == NULL) {
@@ -2827,8 +2825,7 @@ int bt_mesh_provisioner_prov_init(void)
return -EINVAL;
}
key = bt_mesh_pub_key_get();
if (!key) {
if (bt_mesh_pub_key_gen()) {
BT_ERR("Failed to generate Public Key");
return -EIO;
}
+32 -26
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -14,6 +14,10 @@
#include "bta/bta_api.h"
#endif
#if CONFIG_BLE_MESH_COMPRESSED_LOG_ENABLE
#include "log_compression/utils.h"
#endif
#include "btc_ble_mesh_agg_model.h"
#include "btc_ble_mesh_brc_model.h"
#include "btc_ble_mesh_df_model.h"
@@ -35,8 +39,6 @@
#include "lpn.h"
#include "rpl.h"
#include "foundation.h"
#include <tinycrypt/hmac.h>
#include <tinycrypt/sha256.h>
#include "mesh/buf.h"
#include "mesh/slist.h"
#include "mesh/config.h"
@@ -562,24 +564,9 @@ int bt_mesh_ext_net_decrypt(const uint8_t key[16], struct net_buf_simple *buf,
return bt_mesh_net_decrypt(key, buf, iv_index, proxy, proxy_solic);
}
int bt_mesh_ext_tc_hmac_set_key(void *ctx, const uint8_t *key, unsigned int key_size)
int bt_mesh_ext_hmac_sha_256(const uint8_t key[32], struct bt_mesh_sg *sg, size_t sg_len, uint8_t mac[32])
{
return tc_hmac_set_key(ctx, key, key_size);
}
int bt_mesh_ext_tc_hmac_init(void *ctx)
{
return tc_hmac_init(ctx);
}
int bt_mesh_ext_tc_hmac_update(void *ctx, const void *data, unsigned int data_length)
{
return tc_hmac_update(ctx, data, data_length);
}
int bt_mesh_ext_tc_hmac_final(uint8_t *tag, unsigned int taglen, void *ctx)
{
return tc_hmac_final(tag, taglen, ctx);
return bt_mesh_sha256_hmac_raw_key(key, sg, sg_len, mac);
}
/* Mutex */
@@ -4274,12 +4261,6 @@ static const bt_mesh_ext_config_t bt_mesh_ext_cfg = {
.struct_addr_off_val = offsetof(bt_mesh_addr_t, val),
.struct_sg_size = sizeof(struct bt_mesh_sg),
.struct_sg_off_len = offsetof(struct bt_mesh_sg, len),
.struct_tc_sha256_state = sizeof(struct tc_sha256_state_struct),
.struct_tc_sha256_off_bits_hashed = offsetof(struct tc_sha256_state_struct, bits_hashed),
.struct_tc_sha256_off_leftover = offsetof(struct tc_sha256_state_struct, leftover),
.struct_tc_sha256_off_leftover_offset = offsetof(struct tc_sha256_state_struct, leftover_offset),
.struct_tc_hmac_state_size = sizeof(struct tc_hmac_state_struct),
.struct_tc_hmac_state_off_key = offsetof(struct tc_hmac_state_struct, key),
.btc_ble_mesh_evt_agg_client_send_timeout = BTC_BLE_MESH_EVT_AGG_CLIENT_SEND_TIMEOUT,
.btc_ble_mesh_evt_agg_client_recv_rsp = BTC_BLE_MESH_EVT_AGG_CLIENT_RECV_RSP,
@@ -5042,6 +5023,31 @@ void bt_mesh_lib_log_debug(const char *format, ...)
#endif
}
void ble_mesh_lib_compressed_out(uint8_t log_level, uint32_t log_index, size_t arg_cnt, ...)
{
#if CONFIG_BLE_MESH_COMPRESSED_LOG_ENABLE
if (BLE_MESH_LOG_LEVEL >= log_level) {
va_list args = {0};
va_start(args, arg_cnt);
extern int ble_log_compressed_hex_printv(uint8_t source, uint32_t log_index, size_t args_cnt, va_list args);
ble_log_compressed_hex_printv(BLE_COMPRESSED_LOG_OUT_SOURCE_MESH_LIB, log_index, arg_cnt, args);
va_end(args);
}
#endif
return;
}
void ble_mesh_lib_compressed_buf_out(uint8_t log_level, uint32_t log_index, uint8_t buf_idx, const uint8_t *buf, uint8_t len)
{
#if CONFIG_BLE_MESH_COMPRESSED_LOG_ENABLE
if (BLE_MESH_LOG_LEVEL >= log_level) {
extern int ble_log_compressed_hex_print_buf(uint8_t source, uint32_t log_index, uint8_t buf_idx, const uint8_t *buf, size_t len);
ble_log_compressed_hex_print_buf(BLE_COMPRESSED_LOG_OUT_SOURCE_MESH_LIB, log_index, buf_idx, buf, len);
}
#endif
return;
}
/**
* @brief Keep symbols alive.
* @note Dummy function to stop the linker from
@@ -1277,19 +1277,19 @@ void bta_av_setconfig_rsp (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
bta_av_adjust_seps_idx(p_scb, avdt_handle);
APPL_TRACE_DEBUG("bta_av_setconfig_rsp: sep_idx: %d cur_psc_mask:0x%x", p_scb->sep_idx, p_scb->cur_psc_mask);
if (AVDT_TSEP_SNK == local_sep) {
if ((p_data->ci_setconfig.err_code == AVDT_SUCCESS) &&
(p_scb->seps[p_scb->sep_idx].p_app_data_cback != NULL)) {
p_scb->seps[p_scb->sep_idx].p_app_data_cback(BTA_AV_MEDIA_CFG_EVT,
(tBTA_AV_MEDIA *)p_scb->cfg.codec_info);
}
if (AVDT_TSEP_SNK == local_sep) {
if (p_scb->cur_psc_mask & AVDT_PSC_DELAY_RPT) {
psc_cfg.psc_mask |= BTA_AV_PSC_DEALY_RPT;
}
(*bta_av_cb.p_cback)(BTA_AV_SNK_PSC_CFG_EVT, (tBTA_AV *)&psc_cfg);
}
AVDT_ConfigRsp(p_scb->avdt_handle, p_scb->avdt_label, p_data->ci_setconfig.err_code,
p_data->ci_setconfig.category);
@@ -1908,24 +1908,18 @@ void bta_av_getcap_results (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
cfg.psc_mask &= p_scb->p_cap->psc_mask;
p_scb->cur_psc_mask = cfg.psc_mask;
if (uuid_int == UUID_SERVCLASS_AUDIO_SINK) {
if (p_scb->seps[p_scb->sep_idx].p_app_data_cback != NULL) {
APPL_TRACE_DEBUG(" Configure Deoder for Sink Connection ");
APPL_TRACE_DEBUG(" Configure Deoder for A2DP Connection ");
p_scb->seps[p_scb->sep_idx].p_app_data_cback(BTA_AV_MEDIA_CFG_EVT,
(tBTA_AV_MEDIA *)p_scb->cfg.codec_info);
}
if (uuid_int == UUID_SERVCLASS_AUDIO_SINK) {
if (p_scb->cur_psc_mask & AVDT_PSC_DELAY_RPT) {
psc_cfg.psc_mask |= BTA_AV_PSC_DEALY_RPT;
}
(*bta_av_cb.p_cback)(BTA_AV_SNK_PSC_CFG_EVT, (tBTA_AV *)&psc_cfg);
}
else {
/* UUID_SERVCLASS_AUDIO_SOURCE */
if (p_scb->seps[p_scb->sep_idx].p_app_data_cback != NULL) {
p_scb->seps[p_scb->sep_idx].p_app_data_cback(BTA_AV_MEDIA_CFG_EVT,
(tBTA_AV_MEDIA *)p_scb->cfg.codec_info);
}
}
/* open the stream */
AVDT_OpenReq(p_scb->seps[p_scb->sep_idx].av_handle, p_scb->peer_addr,
@@ -283,6 +283,11 @@ tBTA_JV_STATUS BTA_JvStartDiscovery(BD_ADDR bd_addr, UINT16 num_uuid,
tBTA_JV_API_START_DISCOVERY *p_msg;
APPL_TRACE_API( "BTA_JvStartDiscovery");
if ((num_uuid > BTA_JV_MAX_UUIDS) || ((num_uuid > 0) && (p_uuid_list == NULL))) {
APPL_TRACE_ERROR("invalid uuid list: num_uuid=%u", num_uuid);
return BTA_JV_FAILURE;
}
if ((p_msg = (tBTA_JV_API_START_DISCOVERY *)osi_malloc(sizeof(tBTA_JV_API_START_DISCOVERY))) != NULL) {
p_msg->hdr.event = BTA_JV_API_START_DISCOVERY_EVT;
bdcpy(p_msg->bd_addr, bd_addr);
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -652,7 +652,11 @@ static void btc_spp_start_discovery(btc_spp_args_t *arg)
ret = ESP_SPP_NEED_INIT;
break;
}
BTA_JvStartDiscovery(arg->start_discovery.bd_addr, arg->start_discovery.num_uuid, arg->start_discovery.p_uuid_list, NULL);
tBTA_JV_STATUS status = BTA_JvStartDiscovery(arg->start_discovery.bd_addr, arg->start_discovery.num_uuid, arg->start_discovery.p_uuid_list, NULL);
if (status != BTA_JV_SUCCESS) {
BTC_TRACE_ERROR("%s SPP failed to start discovery\n", __func__);
ret = ESP_SPP_NO_RESOURCE;
}
} while (0);
if (ret != ESP_SPP_SUCCESS) {
@@ -481,6 +481,10 @@ static void hci_hal_h4_hdl_rx_packet(BT_HDR *packet)
packet->len--;
if (type == HCI_BLE_EVENT) {
#if (!CONFIG_BT_STACK_NO_LOG)
if (packet->len < 1) {
osi_free(packet);
return;
}
uint8_t len = 0;
STREAM_TO_UINT8(len, stream);
#endif
@@ -447,12 +447,26 @@ static bool filter_incoming_event(BT_HDR *packet)
uint8_t event_code;
command_opcode_t opcode;
if (packet == NULL) {
return true;
}
if (packet->len < HCI_EVENT_PREAMBLE_SIZE) {
HCI_TRACE_WARNING("dropping too short HCI event (len=%u)", packet->len);
osi_free(packet);
return true;
}
STREAM_TO_UINT8(event_code, stream);
STREAM_SKIP_UINT8(stream); // Skip the parameter total length field
HCI_TRACE_DEBUG("Receive packet event_code=0x%x\n", event_code);
if (event_code == HCI_COMMAND_COMPLETE_EVT) {
if (packet->len < HCI_EVENT_PREAMBLE_SIZE + HCI_CC_EVENT_MIN_PARAM_LEN) {
HCI_TRACE_WARNING("dropping too short Command Complete (len=%u)", packet->len);
osi_free(packet);
return true;
}
STREAM_TO_UINT8(hci_host_env.command_credits, stream);
STREAM_TO_UINT16(opcode, stream);
wait_entry = get_waiting_command(opcode);
@@ -481,6 +495,11 @@ static bool filter_incoming_event(BT_HDR *packet)
goto intercepted;
} else if (event_code == HCI_COMMAND_STATUS_EVT) {
uint8_t status;
if (packet->len < HCI_EVENT_PREAMBLE_SIZE + HCI_CS_EVENT_MIN_PARAM_LEN) {
HCI_TRACE_WARNING("dropping too short Command Status (len=%u)", packet->len);
osi_free(packet);
return true;
}
STREAM_TO_UINT8(status, stream);
STREAM_TO_UINT8(hci_host_env.command_credits, stream);
STREAM_TO_UINT16(opcode, stream);
@@ -27,5 +27,9 @@
#define HCI_SCO_PREAMBLE_SIZE 3
// 1 byte for event code, 1 byte for parameter length (Volume 2, Part E, 5.4.4)
#define HCI_EVENT_PREAMBLE_SIZE 2
// 1 byte for Num_HCI_Command_Packets, 2 bytes for Commnad_Opcode (Volume 4, Part E, 7.7.14)
#define HCI_CC_EVENT_MIN_PARAM_LEN 3
// 1 byte for status, 1 byte for Num_HCI_Command_Packets, 2 bytes for Commnad_Opcode (Volume 4, Part E, 7.7.15)
#define HCI_CS_EVENT_MIN_PARAM_LEN 4
#endif /* _HCI_INTERNALS_H_ */
@@ -37,6 +37,7 @@
#define START_PACKET_BOUNDARY 2
#define CONTINUATION_PACKET_BOUNDARY 1
#define L2CAP_HEADER_SIZE 4
#define L2CAP_LENGTH_SIZE 2
// TODO(zachoverflow): find good value for this
#define NUMBER_OF_BUCKETS 42
@@ -81,6 +82,11 @@ static void fragment_and_dispatch(BT_HDR *packet)
callbacks->fragmented(packet, true);
return;
}
if (packet->len < HCI_ACL_PREAMBLE_SIZE) {
HCI_TRACE_ERROR("ACL packet too short for preamble (len=%u)", packet->len);
callbacks->fragmented(packet, true);
return;
}
max_data_size =
SUB_EVENT(packet->event) == LOCAL_BR_EDR_CONTROLLER_ID ?
@@ -143,6 +149,11 @@ static void reassemble_and_dispatch(BT_HDR *packet)
uint16_t l2cap_length;
uint16_t acl_length __attribute__((unused));
if (packet->len < HCI_ACL_PREAMBLE_SIZE + L2CAP_LENGTH_SIZE) {
HCI_TRACE_ERROR("ACL packet too short (len=%u)\n", packet->len);
osi_free(packet);
return;
}
STREAM_TO_UINT16(handle, stream);
STREAM_TO_UINT16(acl_length, stream);
STREAM_TO_UINT16(l2cap_length, stream);
@@ -106,6 +106,9 @@ static tAVRC_STS avrc_pars_vendor_cmd(tAVRC_MSG_VENDOR *p_msg, tAVRC_COMMAND *p_
case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE: /* 0x13 */
case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT: /* 0x15 */
if (len < 1) {
status = AVRC_STS_INTERNAL_ERR;
} else {
BE_STREAM_TO_UINT8 (p_result->get_cur_app_val.num_attr, p);
if (len != (p_result->get_cur_app_val.num_attr + 1)) {
status = AVRC_STS_INTERNAL_ERR;
@@ -123,9 +126,13 @@ static tAVRC_STS avrc_pars_vendor_cmd(tAVRC_MSG_VENDOR *p_msg, tAVRC_COMMAND *p_
if (yy == 0) {
status = AVRC_STS_BAD_PARAM;
}
}
break;
case AVRC_PDU_SET_PLAYER_APP_VALUE: /* 0x14 */
if (len < 1) {
status = AVRC_STS_INTERNAL_ERR;
} else {
BE_STREAM_TO_UINT8 (p_result->set_app_val.num_val, p);
size_needed = sizeof(tAVRC_APP_SETTING);
if (p_buf && (len == ((p_result->set_app_val.num_val << 1) + 1))) {
@@ -147,6 +154,7 @@ static tAVRC_STS avrc_pars_vendor_cmd(tAVRC_MSG_VENDOR *p_msg, tAVRC_COMMAND *p_
AVRC_TRACE_ERROR("AVRC_PDU_SET_PLAYER_APP_VALUE NULL decode buffer or bad len");
status = AVRC_STS_INTERNAL_ERR;
}
}
break;
case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT:/* 0x16 */
@@ -118,6 +118,10 @@ void sdp_server_handle_client_req (tCONN_CB *p_ccb, BT_HDR *p_msg)
UINT8 pdu_id;
UINT16 trans_num, param_len;
if (p_msg->len < 5) {
SDP_TRACE_WARNING("SDP - short request received: len=%u\n", p_msg->len);
return;
}
/* Start inactivity timer */
btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_SDP, SDP_INACT_TIMEOUT);
@@ -187,6 +191,11 @@ static void process_service_search (tCONN_CB *p_ccb, UINT16 trans_num,
return;
}
if (p_req + 2 > p_req_end) {
sdpu_build_n_send_error (p_ccb, trans_num, SDP_INVALID_REQ_SYNTAX, SDP_TEXT_BAD_MAX_RECORDS_LIST);
return;
}
/* Get the max replies we can send. Cap it at our max anyways. */
BE_STREAM_TO_UINT16 (max_replies, p_req);
@@ -194,7 +203,6 @@ static void process_service_search (tCONN_CB *p_ccb, UINT16 trans_num,
max_replies = SDP_MAX_RECORDS;
}
if ((!p_req) || (p_req > p_req_end)) {
sdpu_build_n_send_error (p_ccb, trans_num, SDP_INVALID_REQ_SYNTAX, SDP_TEXT_BAD_MAX_RECORDS_LIST);
return;
@@ -322,14 +330,13 @@ static void process_service_attr_req (tCONN_CB *p_ccb, UINT16 trans_num,
BOOLEAN is_cont = FALSE;
UINT16 attr_len;
/* Extract the record handle */
BE_STREAM_TO_UINT32 (rec_handle, p_req);
if (p_req > p_req_end) {
if (p_req + 4 + 2 > p_req_end) {
sdpu_build_n_send_error (p_ccb, trans_num, SDP_INVALID_SERV_REC_HDL, SDP_TEXT_BAD_HANDLE);
return;
}
/* Extract the record handle */
BE_STREAM_TO_UINT32 (rec_handle, p_req);
/* Get the max list length we can send. Cap it at MTU size minus overhead */
BE_STREAM_TO_UINT16 (max_list_len, p_req);
@@ -371,7 +378,7 @@ static void process_service_attr_req (tCONN_CB *p_ccb, UINT16 trans_num,
return;
}
if (*p_req++ != SDP_CONTINUATION_LEN) {
if ((*p_req++ != SDP_CONTINUATION_LEN) || (p_req + 2 > p_req_end)) {
sdpu_build_n_send_error (p_ccb, trans_num, SDP_INVALID_CONT_STATE, SDP_TEXT_BAD_CONT_LEN);
return;
}
+28 -1
View File
@@ -290,7 +290,7 @@ menu "GAP"
config BT_NIMBLE_MAX_CCCDS
int "Maximum number of CCC descriptors to save across reboots"
default 8
depends on BT_NIMBLE_ENABLED && BT_NIMBLE_NVS_PERSIST
depends on BT_NIMBLE_ENABLED
help
Defines maximum number of CCC descriptors to save
@@ -1216,6 +1216,15 @@ menu "Extra Features"
help
This option is used to enable encrypted advertising data.
config BT_NIMBLE_ADV_UUID_CONCAT
bool "concatenate uuids while parsing advertising data"
default n
depends on BT_NIMBLE_ENABLED
help
Enables concatenation of multiple UUIDs of the same type while parsing
advertising data on the central device. When disabled, only the last
parsed UUID of a given type is retained.
config BT_NIMBLE_MAX_EADS
int "Maximum number of EAD devices to save across reboots"
default 10
@@ -1619,6 +1628,24 @@ menu "Vendor / Optimization"
depends on BT_NIMBLE_ENABLED
help
This enable BLE high duty advertising interval feature
config BT_NIMBLE_ADV_SEND_CONSTANT_DID
bool "Enable BLE Ext Adv to Send with Specific DID"
depends on SOC_ESP_NIMBLE_CONTROLLER && BT_NIMBLE_50_FEATURE_SUPPORT && !(IDF_TARGET_ESP32C2)
select BT_NIMBLE_VS_SUPPORT
help
This enable vendor-specific APIs to send specific DID for different advertising data in extended
advertising.
config BT_NIMBLE_SCAN_ALLOW_ENH_ADI_FILTER
bool "Enable BLE Ext Scan to Receive Packet with Specific ADI"
depends on SOC_ESP_NIMBLE_CONTROLLER && BT_NIMBLE_50_FEATURE_SUPPORT && !(IDF_TARGET_ESP32C2)
select BT_NIMBLE_VS_SUPPORT
help
This enables vendor-specific APIs to only receive specific groups of ADIs, and implements DIDs
duplicate filtering for extended scanning. Enabling this can reduce the unnecessary reception of
secondary channel PDUs carrying non-targeted ADIs.
endmenu #Vendor
menu "Helper Utils"
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -118,6 +118,12 @@
#define MYNEWT_VAL_ENC_ADV_DATA (CONFIG_BT_NIMBLE_ENC_ADV_DATA)
#endif
#ifndef CONFIG_BT_NIMBLE_ADV_UUID_CONCAT
#define MYNEWT_VAL_BLE_ADV_UUID_CONCAT (0)
#else
#define MYNEWT_VAL_BLE_ADV_UUID_CONCAT (CONFIG_BT_NIMBLE_ADV_UUID_CONCAT)
#endif
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
#define BLE_SCAN_RSP_DATA_MAX_LEN_N (1650)
#else
@@ -2356,4 +2362,20 @@
#endif
#endif
#ifndef MYNEWT_VAL_BLE_ADV_SEND_CONSTANT_DID
#ifdef CONFIG_BT_NIMBLE_ADV_SEND_CONSTANT_DID
#define MYNEWT_VAL_BLE_ADV_SEND_CONSTANT_DID (CONFIG_BT_NIMBLE_ADV_SEND_CONSTANT_DID)
#else
#define MYNEWT_VAL_BLE_ADV_SEND_CONSTANT_DID (0)
#endif
#endif
#ifndef MYNEWT_VAL_BLE_SCAN_ALLOW_ENH_ADI_FILTER
#ifdef CONFIG_BT_NIMBLE_SCAN_ALLOW_ENH_ADI_FILTER
#define MYNEWT_VAL_BLE_SCAN_ALLOW_ENH_ADI_FILTER (CONFIG_BT_NIMBLE_SCAN_ALLOW_ENH_ADI_FILTER)
#else
#define MYNEWT_VAL_BLE_SCAN_ALLOW_ENH_ADI_FILTER (0)
#endif
#endif
#endif
+3 -2
View File
@@ -13,6 +13,7 @@
#include "sdkconfig.h"
#include "esp_task.h"
#include "esp_assert.h"
#include "../../../../controller/esp32/esp_bredr_cfg.h"
#ifdef __cplusplus
extern "C" {
@@ -46,7 +47,7 @@ extern "C" {
#define SOC_MEM_BT_EM_PER_SYNC_SIZE 0x870
#define SOC_MEM_BT_EM_BREDR_REAL_END (SOC_MEM_BT_EM_BREDR_NO_SYNC_END + CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN_EFF * SOC_MEM_BT_EM_PER_SYNC_SIZE)
#define SOC_MEM_BT_EM_BREDR_REAL_END (SOC_MEM_BT_EM_BREDR_NO_SYNC_END + UT_BR_EDR_CTRL_MAX_SYNC_CONN_EFF * SOC_MEM_BT_EM_PER_SYNC_SIZE)
#endif //CONFIG_BT_ENABLED
@@ -241,7 +242,7 @@ the advertising packet will be discarded until the memory is restored. */
.bt_sco_datapath = CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF, \
.auto_latency = BTDM_CTRL_AUTO_LATENCY_EFF, \
.bt_legacy_auth_vs_evt = BTDM_CTRL_LEGACY_AUTH_VENDOR_EVT_EFF, \
.bt_max_sync_conn = CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN_EFF, \
.bt_max_sync_conn = UT_BR_EDR_CTRL_MAX_SYNC_CONN_EFF, \
.ble_sca = CONFIG_BTDM_BLE_SLEEP_CLOCK_ACCURACY_INDEX_EFF, \
.pcm_role = CONFIG_BTDM_CTRL_PCM_ROLE_EFF, \
.pcm_polar = CONFIG_BTDM_CTRL_PCM_POLAR_EFF, \
@@ -159,7 +159,7 @@ esp_err_t esp_ble_tx_power_set_enhanced(esp_ble_enhanced_power_type_t power_type
*/
esp_power_level_t esp_ble_tx_power_get_enhanced(esp_ble_enhanced_power_type_t power_type, uint16_t handle);
#define CONFIG_VERSION 0x20251125
#define CONFIG_VERSION 0x20251211
#define CONFIG_MAGIC 0x5A5AA5A5
/**
@@ -237,6 +237,7 @@ typedef struct {
uint8_t priority_level_cfg; /*!< The option for priority level configuration */
uint8_t slv_fst_rx_lat_en; /*!< The option for enabling slave fast PDU reception during latency. */
uint8_t dl_itvl_phy_sync_en; /*!< The option for automatically initiate the data length update when phy update or connect interval update. */
uint8_t scan_allow_adi_filter; /*!< The option for ext scan to allow PDU with specific adi. */
uint32_t config_magic; /*!< Magic number for configuration validation */
} esp_bt_controller_config_t;
@@ -301,6 +302,7 @@ typedef struct {
.priority_level_cfg = BT_LL_CTRL_PRIO_LVL_CFG, \
.slv_fst_rx_lat_en = DEFAULT_BT_LE_CTRL_SLV_FAST_RX_CONN_DATA_EN, \
.dl_itvl_phy_sync_en = DEFAULT_BT_LE_CTRL_DL_ITVL_PHY_SYNC_EN, \
.scan_allow_adi_filter = DEFAULT_BT_SCAN_ALLOW_ENH_ADI_FILTER, \
.config_magic = CONFIG_MAGIC, \
}
@@ -156,7 +156,7 @@ esp_err_t esp_ble_tx_power_set_enhanced(esp_ble_enhanced_power_type_t power_type
*/
esp_power_level_t esp_ble_tx_power_get_enhanced(esp_ble_enhanced_power_type_t power_type, uint16_t handle);
#define CONFIG_VERSION 0x20251125
#define CONFIG_VERSION 0x20251211
#define CONFIG_MAGIC 0x5A5AA5A5
/**
@@ -237,6 +237,7 @@ typedef struct {
uint8_t priority_level_cfg; /*!< The option for priority level configuration */
uint8_t slv_fst_rx_lat_en; /*!< The option for enabling slave fast PDU reception during latency. */
uint8_t dl_itvl_phy_sync_en; /*!< The option for automatically initiate the data length update when phy update or connect interval update. */
uint8_t scan_allow_adi_filter; /*!< The option for ext scan to allow PDU with specific adi. */
uint32_t config_magic; /*!< Magic number for configuration validation */
} esp_bt_controller_config_t;
@@ -304,6 +305,7 @@ typedef struct {
.priority_level_cfg = BT_LL_CTRL_PRIO_LVL_CFG, \
.slv_fst_rx_lat_en = DEFAULT_BT_LE_CTRL_SLV_FAST_RX_CONN_DATA_EN, \
.dl_itvl_phy_sync_en = DEFAULT_BT_LE_CTRL_DL_ITVL_PHY_SYNC_EN, \
.scan_allow_adi_filter = DEFAULT_BT_SCAN_ALLOW_ENH_ADI_FILTER, \
.config_magic = CONFIG_MAGIC, \
}
#elif CONFIG_IDF_TARGET_ESP32C61
@@ -161,7 +161,7 @@ esp_err_t esp_ble_tx_power_set_enhanced(esp_ble_enhanced_power_type_t power_type
*/
esp_power_level_t esp_ble_tx_power_get_enhanced(esp_ble_enhanced_power_type_t power_type, uint16_t handle);
#define CONFIG_VERSION 0x20251125
#define CONFIG_VERSION 0x20251211
#define CONFIG_MAGIC 0x5A5AA5A5
/**
@@ -239,6 +239,7 @@ typedef struct {
uint8_t priority_level_cfg; /*!< The option for priority level configuration */
uint8_t slv_fst_rx_lat_en; /*!< The option for enabling slave fast PDU reception during latency. */
uint8_t dl_itvl_phy_sync_en; /*!< The option for automatically initiate the data length update when phy update or connect interval update. */
uint8_t scan_allow_adi_filter; /*!< The option for ext scan to allow PDU with specific adi. */
uint32_t config_magic; /*!< Configuration magic value */
} esp_bt_controller_config_t;
@@ -304,6 +305,7 @@ typedef struct {
.priority_level_cfg = BT_LL_CTRL_PRIO_LVL_CFG, \
.slv_fst_rx_lat_en = DEFAULT_BT_LE_CTRL_SLV_FAST_RX_CONN_DATA_EN, \
.dl_itvl_phy_sync_en = DEFAULT_BT_LE_CTRL_DL_ITVL_PHY_SYNC_EN, \
.scan_allow_adi_filter = DEFAULT_BT_SCAN_ALLOW_ENH_ADI_FILTER, \
.config_magic = CONFIG_MAGIC, \
}
@@ -590,7 +590,7 @@ hci_driver_uart_dma_deinit(void)
ESP_ERROR_CHECK(uart_driver_delete(s_hci_driver_uart_dma_env.hci_uart_params->hci_uart_port));
hci_driver_uart_dma_memory_deinit();
if (!s_hci_driver_uart_dma_env.process_sem) {
if (s_hci_driver_uart_dma_env.process_sem) {
vSemaphoreDelete(s_hci_driver_uart_dma_env.process_sem);
}
-1
View File
@@ -10,7 +10,6 @@ CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_ACL_CONN CONFIG_BTDM_CTRL_BR_
CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_SYNC_CONN CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN
CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN_EFF CONFIG_BTDM_CTRL_BLE_MAX_CONN_EFF
CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_ACL_CONN_EFF CONFIG_BTDM_CTRL_BR_EDR_MAX_ACL_CONN_EFF
CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_SYNC_CONN_EFF CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN_EFF
CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE_CHOICE CONFIG_BTDM_CTRL_PINNED_TO_CORE_CHOICE
CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE CONFIG_BTDM_CTRL_PINNED_TO_CORE
CONFIG_BTDM_CONTROLLER_HCI_MODE_CHOICE CONFIG_BTDM_CTRL_HCI_MODE_CHOICE
@@ -4,3 +4,10 @@ idf_component_register(SRCS "test_bt_main.c"
INCLUDE_DIRS "."
PRIV_REQUIRES unity bt
WHOLE_ARCHIVE)
# Add private include directories from bt component to access internal headers
idf_component_get_property(bt_dir bt COMPONENT_DIR)
target_include_directories(${COMPONENT_LIB} PRIVATE ${bt_dir}/host/bluedroid/stack/smp/include)
target_include_directories(${COMPONENT_LIB} PRIVATE ${bt_dir}/host/bluedroid/common/include)
target_include_directories(${COMPONENT_LIB} PRIVATE ${bt_dir}/host/bluedroid/stack/include)
target_include_directories(${COMPONENT_LIB} PRIVATE ${bt_dir}/common/include)
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
@@ -18,42 +18,14 @@
#include "esp_bt_main.h"
#include "esp_bt_device.h"
#include "esp_gap_ble_api.h"
#include "sdkconfig.h"
#if defined(CONFIG_BT_SMP_CRYPTO_STACK_NATIVE) && CONFIG_BT_SMP_CRYPTO_STACK_NATIVE
/* Native Bluedroid crypto implementation tests */
#include "p_256_ecc_pp.h"
#define KEY_LENGTH_DWORDS_P256 8
typedef unsigned long DWORD;
typedef uint32_t UINT32;
typedef struct {
DWORD x[KEY_LENGTH_DWORDS_P256];
DWORD y[KEY_LENGTH_DWORDS_P256];
DWORD z[KEY_LENGTH_DWORDS_P256];
} Point;
typedef struct {
// curve's coefficients
DWORD a[KEY_LENGTH_DWORDS_P256];
DWORD b[KEY_LENGTH_DWORDS_P256];
//whether a is -3
int a_minus3;
// prime modulus
DWORD p[KEY_LENGTH_DWORDS_P256];
// Omega, p = 2^m -omega
DWORD omega[KEY_LENGTH_DWORDS_P256];
// base point, a point on E of order r
Point G;
} elliptic_curve_t;
extern void ECC_PointMult_Bin_NAF(Point *q, Point *p, DWORD *n, uint32_t keyLength);
extern bool ECC_CheckPointIsInElliCur_P256(Point *p);
extern void p_256_init_curve(UINT32 keyLength);
extern elliptic_curve_t curve_p256;
static void bt_rand(void *buf, size_t len)
{
if (!len) {
@@ -70,7 +42,17 @@ static void bt_rand(void *buf, size_t len)
return;
}
TEST_CASE("ble_smp_public_key_check", "[ble_smp]")
/**
* @brief Test ECC public key validation for native Bluedroid crypto implementation
*
* This test is only compiled when SMP_CRYPTO_STACK_NATIVE is enabled.
* It tests the native Bluedroid ECC implementation including:
* - Public key generation from private key
* - Public key validation on elliptic curve
* - Attack simulation (invalid public key detection)
* - Random key generation and validation
*/
TEST_CASE("ble_smp_public_key_check", "[ble_smp][native_crypto]")
{
/* We wait init finish 200ms here */
vTaskDelay(200 / portTICK_PERIOD_MS);
@@ -96,7 +78,14 @@ TEST_CASE("ble_smp_public_key_check", "[ble_smp]")
TEST_ASSERT(ECC_CheckPointIsInElliCur_P256(&public_key));
}
}
#endif /* CONFIG_BT_SMP_CRYPTO_STACK_NATIVE */
/**
* @brief Test static passkey set/clear functionality
*
* This test is applicable to all crypto stack implementations (Native, TinyCrypt, mbedTLS).
* It tests the SMP security parameter API for setting and clearing static passkeys.
*/
TEST_CASE("ble_smp_set_clear_static_passkey", "[ble_smp]")
{
/* We wait init finish 200ms here */
@@ -66,7 +66,7 @@ typedef enum {
ESP_EFUSE_KEY_PURPOSE_USER = 0, /**< User purposes (software-only use) */
ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY = 1, /**< ECDSA private key (Expected in little endian order)*/
#if CONFIG_ESP32P4_REV_MIN_FULL >= 300
#if !CONFIG_ESP32P4_SELECTS_REV_LESS_V3
ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY_P256 = ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY, /**< ECDSA private key (P256) (Expected in little endian order)*/
#endif
@@ -82,7 +82,7 @@ typedef enum {
ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST2 = 11, /**< SECURE_BOOT_DIGEST2 (Secure Boot key digest) */
ESP_EFUSE_KEY_PURPOSE_KM_INIT_KEY = 12, /**< KM_INIT_KEY */
#if CONFIG_ESP32P4_REV_MIN_FULL >= 300
#if !CONFIG_ESP32P4_SELECTS_REV_LESS_V3
ESP_EFUSE_KEY_PURPOSE_XTS_AES_256_PSRAM_KEY_1 = 13, /**< PSRAM encryption key (XTS_AES_256_KEY_1) */
ESP_EFUSE_KEY_PURPOSE_XTS_AES_256_PSRAM_KEY_2 = 14, /**< PSRAM encryption key (XTS_AES_256_KEY_2) */
ESP_EFUSE_KEY_PURPOSE_XTS_AES_128_PSRAM_KEY = 15, /**< PSRAM encryption key (XTS_AES_128_KEY) */
@@ -10,7 +10,7 @@ extern "C" {
#include "sdkconfig.h"
#if CONFIG_ESP32P4_REV_MIN_FULL >= 300
#if !CONFIG_ESP32P4_SELECTS_REV_LESS_V3
#include "esp_efuse_table_v3.0.h"
#else
#include "esp_efuse_table_v0.0_v2.0.h"
+1 -1
View File
@@ -4,7 +4,7 @@ set(EFUSE_SOC_SRCS
"esp_efuse_rtc_calib.c"
)
if(CONFIG_ESP32P4_REV_MIN_FULL GREATER_EQUAL 300)
if(NOT CONFIG_ESP32P4_SELECTS_REV_LESS_V3)
list(APPEND EFUSE_SOC_SRCS
"esp_efuse_table_v3.0.c"
)
+1 -1
View File
@@ -25,7 +25,7 @@ menu "ESP-TLS"
config ESP_TLS_USE_DS_PERIPHERAL
bool "Use Digital Signature (DS) Peripheral with ESP-TLS"
depends on ESP_TLS_USING_MBEDTLS && SOC_DIG_SIGN_SUPPORTED && MBEDTLS_PK_RSA_ALT_SUPPORT
depends on ESP_TLS_USING_MBEDTLS && SOC_DIG_SIGN_SUPPORTED
default y
help
Enable use of the Digital Signature Peripheral for ESP-TLS.The DS peripheral
+9 -2
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2019-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -17,6 +17,7 @@
#include "hal/adc_hal_common.h"
#include "esp_private/regi2c_ctrl.h"
#include "soc/adc_periph.h"
#include "hal/adc_ll.h"
static const char *TAG = "adc_common";
@@ -57,10 +58,13 @@ esp_err_t adc_channel_to_io(adc_unit_t unit_id, adc_channel_t channel, int * con
---------------------------------------------------------------*/
static __attribute__((constructor)) void adc_hw_calibration(void)
{
adc_apb_periph_claim();
ANALOG_CLOCK_ENABLE();
//Calculate all ICode
for (int i = 0; i < SOC_ADC_PERIPH_NUM; i++) {
if (ADC_LL_NEED_APB_PERIPH_CLAIM(i)) {
adc_apb_periph_claim();
}
adc_hal_calibration_init(i);
for (int j = 0; j < SOC_ADC_ATTEN_NUM; j++) {
/**
@@ -75,6 +79,9 @@ static __attribute__((constructor)) void adc_hw_calibration(void)
}
#endif
}
if (ADC_LL_NEED_APB_PERIPH_CLAIM(i)) {
adc_apb_periph_free();
}
}
ANALOG_CLOCK_DISABLE();
}
+7 -5
View File
@@ -144,7 +144,7 @@ esp_err_t adc_oneshot_new_unit(const adc_oneshot_unit_init_cfg_t *init_config, a
adc_oneshot_hal_init(&(unit->hal), &config);
#if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED
if (ADC_LL_NEED_APB_PERIPH_CLAIM(unit->unit_id)) {
//To enable the APB_SARADC periph if needed
_lock_acquire(&s_ctx.mutex);
s_ctx.apb_periph_ref_cnts++;
@@ -152,7 +152,7 @@ esp_err_t adc_oneshot_new_unit(const adc_oneshot_unit_init_cfg_t *init_config, a
adc_apb_periph_claim();
}
_lock_release(&s_ctx.mutex);
#endif
}
if (init_config->ulp_mode == ADC_ULP_MODE_DISABLE) {
sar_periph_ctrl_adc_oneshot_power_acquire();
@@ -297,9 +297,8 @@ esp_err_t adc_oneshot_del_unit(adc_oneshot_unit_handle_t handle)
#endif
ESP_ERROR_CHECK(esp_clk_tree_enable_src((soc_module_clk_t)(handle->hal.clk_src), false));
}
free(handle);
#if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED
if (ADC_LL_NEED_APB_PERIPH_CLAIM(handle->unit_id)) {
//To free the APB_SARADC periph if needed
_lock_acquire(&s_ctx.mutex);
s_ctx.apb_periph_ref_cnts--;
@@ -308,7 +307,10 @@ esp_err_t adc_oneshot_del_unit(adc_oneshot_unit_handle_t handle)
adc_apb_periph_free();
}
_lock_release(&s_ctx.mutex);
#endif
}
ESP_LOGD(TAG, "adc unit%"PRId32" is deleted", handle->unit_id);
free(handle);
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
//TODO: IDF-8475: Depends to SLEEP_RETENTION_MODULE_CLOCK_MODEM retention module after ADC retention supported.
@@ -106,6 +106,10 @@ typedef struct isp_processor_t {
uint32_t hist_isr_added: 1;
} isr_users;
struct {
uint32_t wbg_update_once_configured: 1;
} sub_module_flags;
} isp_processor_t;
#endif
+5
View File
@@ -40,6 +40,8 @@ esp_err_t esp_isp_wbg_configure(isp_proc_handle_t isp_proc, const esp_isp_wbg_co
bool valid = isp_ll_shadow_update_wbg(isp_proc->hal.hw, config->flags.update_once_configured);
ESP_RETURN_ON_FALSE_ISR(valid, ESP_ERR_INVALID_STATE, TAG, "failed to update wbg shadow register");
isp_proc->sub_module_flags.wbg_update_once_configured = config->flags.update_once_configured;
return ESP_OK;
}
@@ -64,6 +66,9 @@ esp_err_t esp_isp_wbg_set_wb_gain(isp_proc_handle_t isp_proc, isp_wbg_gain_t gai
// Set WBG gain
isp_ll_awb_set_wb_gain(isp_proc->hal.hw, gain);
bool valid = isp_ll_shadow_update_wbg(isp_proc->hal.hw, isp_proc->sub_module_flags.wbg_update_once_configured);
ESP_RETURN_ON_FALSE_ISR(valid, ESP_ERR_INVALID_STATE, TAG, "failed to update wbg shadow register");
return ESP_OK;
}
@@ -1210,11 +1210,11 @@ static SPI_MASTER_ISR_ATTR esp_err_t setup_dma_priv_buffer(spi_host_t *host, uin
}
buffer = temp;
}
if (use_psram) {
*ret_buffer = buffer;
if (use_psram || (host->bus_attr->cache_align_int > 1)) {
esp_err_t ret = esp_cache_msync((void *)buffer, len, is_tx ? (ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED) : ESP_CACHE_MSYNC_FLAG_DIR_M2C);
ESP_RETURN_ON_FALSE_ISR(ret == ESP_OK, ESP_ERR_INVALID_ARG, SPI_TAG, "sync failed for %s buffer", is_tx ? "TX" : "RX");
}
*ret_buffer = buffer;
return ESP_OK;
}
@@ -0,0 +1,15 @@
idf_build_get_property(target IDF_TARGET)
set(includes "include")
set(srcs "")
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/${target}/include")
list(APPEND includes "${target}/include")
endif()
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/${target}/ieee802154_periph.c")
list(APPEND srcs "${target}/ieee802154_periph.c")
endif()
idf_component_register(SRCS ${srcs}
INCLUDE_DIRS ${includes})
@@ -1,10 +1,10 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/ieee802154_periph.h"
#include "hal/ieee802154_periph.h"
const ieee802154_conn_t ieee802154_periph = {
.module = PERIPH_IEEE802154_MODULE,
@@ -1,12 +1,11 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdbool.h>
#include "hal/ieee802154_common_ll.h"
#define IEEE802154_TXPOWER_VALUE_MAX 20
@@ -1,10 +1,10 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/ieee802154_periph.h"
#include "hal/ieee802154_periph.h"
const ieee802154_conn_t ieee802154_periph = {
.module = PERIPH_IEEE802154_MODULE,
@@ -1,12 +1,11 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdbool.h>
#include "hal/ieee802154_common_ll.h"
#define IEEE802154_TXPOWER_VALUE_MAX 20
@@ -1,10 +1,10 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/ieee802154_periph.h"
#include "hal/ieee802154_periph.h"
const ieee802154_conn_t ieee802154_periph = {
.module = PERIPH_IEEE802154_MODULE,
@@ -1,12 +1,11 @@
/*
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdbool.h>
#include "hal/ieee802154_common_ll.h"
#ifdef __cplusplus
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -414,6 +414,11 @@ static inline void ieee802154_ll_set_pending_mode(bool enable)
IEEE802154.conf.pending_enhance = enable;
}
static inline bool ieee802154_ll_get_pending_mode(void)
{
return IEEE802154.conf.pending_enhance;
}
FORCE_INLINE_ATTR void ieee802154_ll_set_pending_bit(bool pending)
{
IEEE802154.pending_cfg.pending = pending;
@@ -470,8 +475,8 @@ static inline void ieee802154_ll_set_security_key(uint8_t *security_key)
static inline void ieee802154_ll_disable_coex(void)
{
IEEE802154.pti.pti = 1;
IEEE802154.pti.hw_ack_pti = 1;
IEEE802154.pti.pti = 3;
IEEE802154.pti.hw_ack_pti = 3;
}
static inline void ieee802154_ll_clear_debug_cnt(uint32_t clear_bits)
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
+15 -5
View File
@@ -35,6 +35,11 @@ static const char *TAG = "NIMBLE_HIDD";
typedef struct esp_ble_hidd_dev_s esp_ble_hidd_dev_t;
// there can be only one BLE HID device
static esp_ble_hidd_dev_t *s_dev = NULL;
/** service index is used to identify the hid service instance
of the registered characteristic.
Assuming the first instance of the hid service is registered first.
Increment service index as the hid services get registered */
static int service_index = -1;
typedef hidd_report_item_t hidd_le_report_item_t;
@@ -183,6 +188,15 @@ static int nimble_hid_stop_gatts(esp_ble_hidd_dev_t *dev)
/* stop gatt database */
ble_gatts_stop();
ble_svc_hid_deinit();
ble_svc_hid_reset();
ble_svc_dis_deinit();
ble_svc_bas_deinit();
ble_svc_sps_deinit();
ble_svc_gatt_deinit();
ble_svc_gap_deinit();
return rc;
}
@@ -283,6 +297,7 @@ static int nimble_hidd_dev_deinit(void *devp)
return ESP_FAIL;
}
s_dev = NULL;
service_index = -1; // resetting the value
nimble_hid_stop_gatts(dev);
esp_event_post_to(dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_STOP_EVENT, NULL, 0, portMAX_DELAY);
@@ -521,11 +536,6 @@ static int nimble_hid_gap_event(struct ble_gap_event *event, void *arg)
return 0;
}
/** service index is used to identify the hid service instance
of the registered characteristic.
Assuming the first instance of the hid service is registered first.
Increment service index as the hid services get registered */
static int service_index = -1;
static void nimble_gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg)
{
char buf[BLE_UUID_STR_LEN];
+3 -2
View File
@@ -289,7 +289,7 @@ desc_disced(uint16_t conn_handle, const struct ble_gatt_error *error,
}
/* this api does the following things :
** does service, characteristic and discriptor discovery and
** does service, characteristic and descriptor discovery and
** fills the hid device information accordingly in dev */
static void read_device_services(esp_hidh_dev_t *dev)
{
@@ -466,7 +466,7 @@ static void read_device_services(esp_hidh_dev_t *dev)
chr_end_handle, desc_disced, descr_result);
WAIT_CB();
if (status != 0) {
ESP_LOGE(TAG, "failed to find discriptors for characteristic : %d", c);
ESP_LOGE(TAG, "failed to find descriptors for characteristic : %d", c);
assert(status == 0);
}
dcount = dscs_discovered;
@@ -949,6 +949,7 @@ esp_hidh_dev_t *esp_ble_hidh_dev_open(uint8_t *bda, uint8_t address_type)
dev->report_write = esp_ble_hidh_dev_report_write;
dev->report_read = esp_ble_hidh_dev_report_read;
dev->dump = esp_ble_hidh_dev_dump;
dev->connected = true;
/* perform service discovery and fill the report maps */
read_device_services(dev);
+10 -1
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -2034,3 +2034,12 @@ bool esp_http_client_is_persistent_connection(esp_http_client_handle_t client)
}
return false;
}
int esp_http_client_get_socket(esp_http_client_handle_t client)
{
if (client == NULL || client->transport == NULL) {
return -1;
}
return esp_transport_get_socket(client->transport);
}
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -857,6 +857,17 @@ esp_err_t esp_http_client_get_chunk_length(esp_http_client_handle_t client, int
*/
bool esp_http_client_is_persistent_connection(esp_http_client_handle_t client);
/**
* @brief Get the socket from the underlying transport
*
* @param client The HTTP client handle
*
* @return
* - -1 if the client is NULL or the transport is not initialized
* - The socket file descriptor if successful
*/
int esp_http_client_get_socket(esp_http_client_handle_t client);
#ifdef __cplusplus
}
#endif
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2018-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2018-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -576,6 +576,16 @@ esp_err_t httpd_ws_get_frame_type(httpd_req_t *req);
*/
esp_err_t httpd_sess_trigger_close_(httpd_handle_t handle, struct sock_db *session);
/**
* @brief Directly closes the least recently used session
*
* @param[in] hd Server instance data
*
* @return
* - ESP_OK : if session closed successfully
*/
esp_err_t httpd_sess_close_lru_direct(struct httpd_data *hd);
/** End of WebSocket related functions
* @}
*/
+6 -1
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2018-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2018-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -54,7 +54,12 @@ static esp_err_t httpd_accept_conn(struct httpd_data *hd, int listen_fd)
if (hd->config.lru_purge_enable == true) {
if (!httpd_is_sess_available(hd)) {
/* Queue asynchronous closure of the least recently used session */
#if CONFIG_HTTPD_QUEUE_WORK_BLOCKING
/* In case of blocking mode, close the least recently used session directly */
return httpd_sess_close_lru_direct(hd);
#else
return httpd_sess_close_lru(hd);
#endif /* CONFIG_HTTPD_QUEUE_WORK_BLOCKING */
/* Returning from this allows the main server thread to process
* the queued asynchronous control message for closing LRU session.
* Since connection request hasn't been addressed yet using accept()
+19 -1
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2018-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2018-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -498,3 +498,21 @@ void httpd_sess_close_all(struct httpd_data *hd)
};
httpd_sess_enum(hd, enum_function, &context);
}
esp_err_t httpd_sess_close_lru_direct(struct httpd_data *hd)
{
enum_context_t context = {
.task = HTTPD_TASK_FIND_LOWEST_LRU,
.lru_counter = UINT64_MAX,
.fd = -1
};
httpd_sess_enum(hd, enum_function, &context);
if (!context.session) {
return ESP_OK;
}
ESP_LOGD(TAG, LOG_FMT("Directly closing session with fd %d"), context.session->fd);
// Call httpd_sess_delete directly instead of going through work queue
httpd_sess_delete(hd, context.session);
return ESP_OK;
}
+1 -1
View File
@@ -122,7 +122,7 @@ int httpd_recv_with_opt(httpd_req_t *r, char *buf, size_t buf_len, httpd_recv_op
size_t recv_len = pending_len;
do {
int ret = ra->sd->recv_fn(ra->sd->handle, ra->sd->fd, buf, buf_len, 0);
if (ret < 0) {
if (ret <= 0) {
ESP_LOGD(TAG, LOG_FMT("error in recv_fn"));
if ((ret == HTTPD_SOCK_ERR_TIMEOUT) && (pending_len != 0)) {
/* If recv() timeout occurred, but pending data is
+3 -1
View File
@@ -383,7 +383,9 @@ esp_err_t gdma_config_transfer(gdma_channel_handle_t dma_chan, const gdma_transf
bool en_desc_burst = true;
bool en_data_burst = max_data_burst_size > 0;
#if SOC_PSRAM_DMA_CAPABLE || SOC_DMA_CAN_ACCESS_FLASH
// There's auto alignment for AHB GDMA version 1, so we don't need to do anything here
// While, for AHB GDMA version 2 and AXI GDMA, we need to ensure the alignment by software
#if (SOC_PSRAM_DMA_CAPABLE || SOC_DMA_CAN_ACCESS_FLASH) && SOC_AHB_GDMA_VERSION != 1
// if MSPI encryption is enabled, and DMA wants to read/write external memory
if (efuse_hal_flash_encryption_enabled() && config->access_ext_mem) {
uint32_t enc_mem_alignment = GDMA_LL_ACCESS_ENCRYPTION_MEM_ALIGNMENT;
@@ -62,6 +62,27 @@ void modem_clock_module_enable(periph_module_t module);
*/
void modem_clock_module_disable(periph_module_t module);
/**
* @brief Gets the clock bitmask associated with the specified modem module.
*
* This function returns the complete set of clock-enable bits that correspond
* to @p module.
*
* @param module Target shared peripheral clock module.
*
* @return Bitmask of clock-enable bits for the given module.
*/
uint32_t modem_clock_module_bits_get(periph_module_t module);
#if SOC_WIFI_SUPPORTED
/**
* @brief Set Wi-Fi initialization status.
*
* @param inited Wi-Fi initialization status.
*/
void modem_clock_configure_wifi_status(bool inited);
#endif
/**
* @brief Reset the mac of modem module
*
@@ -6,6 +6,7 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "sdkconfig.h"
#include "soc/periph_defs.h"
@@ -153,6 +154,27 @@ void wifi_module_enable(void);
*/
void wifi_module_disable(void);
/**
* @brief Enable phy module by un-gating related clock and de-asserting the reset signal.
*
* @note This function acquires clocks required during the PHY enable sequence.
*/
void phy_module_enable(void);
/**
* @brief Disable phy module by gating related clock and asserting the reset signal.
*
* @note This function releases clocks required during the PHY enable sequence.
*/
void phy_module_disable(void);
/**
* @brief Checks whether phy module has all bits in @p mask set.
*
* @return true if all bits in @p mask are set; false otherwise.
*/
bool phy_module_has_clock_bits(uint32_t mask);
#undef __PERIPH_CTRL_DEPRECATE_ATTR
#ifdef __cplusplus
-1
View File
@@ -18,7 +18,6 @@ entries:
rtc_clk (noflash)
if IDF_TARGET_ESP32 = y:
rtc_clk:rtc_clk_cpu_freq_to_pll_mhz (noflash)
rtc_clk:rtc_clk_cpu_freq_to_xtal (noflash)
if RTC_TIME_FUNC_IN_IRAM = y:
rtc_time (noflash_text)
if SOC_CONFIGURABLE_VDDSDIO_SUPPORTED = y:
@@ -1,7 +1,7 @@
config P4_REV3_MSPI_CRASH_AFTER_POWER_UP_WORKAROUND
bool
depends on IDF_TARGET_ESP32P4
default y if ESP32P4_REV_MIN_300
default y if ESP32P4_REV_MIN_300 # Fixed since REV3.1
config P4_REV3_MSPI_WORKAROUND_SIZE
hex
+62 -7
View File
@@ -53,6 +53,8 @@ typedef enum {
MODEM_CLOCK_DEVICE_MAX
} modem_clock_device_t;
#define MODEM_STATUS_IDLE (0)
#define MODEM_STATUS_WIFI_INITED (0x1UL)
typedef struct modem_clock_context {
modem_clock_hal_context_t *hal;
@@ -64,13 +66,16 @@ typedef struct modem_clock_context {
} dev[MODEM_CLOCK_DEVICE_MAX];
/* the low-power clock source for each module */
modem_clock_lpclk_src_t lpclk_src[PERIPH_MODEM_MODULE_NUM];
#if SOC_WIFI_SUPPORTED
uint32_t modem_status;
#endif
} modem_clock_context_t;
#if SOC_WIFI_SUPPORTED
static void IRAM_ATTR modem_clock_wifi_mac_configure(modem_clock_context_t *ctx, bool enable)
{
if (enable) {
if (enable || !(ctx->modem_status & MODEM_STATUS_WIFI_INITED)) {
#if !SOC_PHY_CALIBRATION_CLOCK_IS_INDEPENDENT
modem_syscon_ll_enable_wifi_apb_clock(ctx->hal->syscon_dev, enable);
#endif
@@ -80,7 +85,7 @@ static void IRAM_ATTR modem_clock_wifi_mac_configure(modem_clock_context_t *ctx,
static void IRAM_ATTR modem_clock_wifi_bb_configure(modem_clock_context_t *ctx, bool enable)
{
if (enable) {
if (enable || !(ctx->modem_status & MODEM_STATUS_WIFI_INITED)) {
modem_syscon_ll_clk_wifibb_configure(ctx->hal->syscon_dev, enable);
}
}
@@ -98,14 +103,14 @@ static void IRAM_ATTR modem_clock_ble_mac_configure(modem_clock_context_t *ctx,
#if SOC_PHY_CALIBRATION_CLOCK_IS_INDEPENDENT
static void IRAM_ATTR modem_clock_wifi_apb_configure(modem_clock_context_t *ctx, bool enable)
{
if (enable) {
if (enable || !(ctx->modem_status & MODEM_STATUS_WIFI_INITED)) {
modem_syscon_ll_enable_wifi_apb_clock(ctx->hal->syscon_dev, enable);
}
}
static void IRAM_ATTR modem_clock_wifi_bb_44m_configure(modem_clock_context_t *ctx, bool enable)
{
if (enable) {
if (enable || !(ctx->modem_status & MODEM_STATUS_WIFI_INITED)) {
modem_syscon_ll_enable_wifibb_44m_clock(ctx->hal->syscon_dev, enable);
}
}
@@ -195,6 +200,10 @@ modem_clock_context_t * __attribute__((weak)) IRAM_ATTR MODEM_CLOCK_instance(voi
[MODEM_CLOCK_DATADUMP] = { .refs = 0, .configure = modem_clock_data_dump_configure }
},
.lpclk_src = { [0 ... PERIPH_MODEM_MODULE_NUM - 1] = MODEM_CLOCK_LPCLK_SRC_INVALID }
#if SOC_WIFI_SUPPORTED
,
.modem_status = MODEM_STATUS_IDLE
#endif
};
if (modem_clock_hal.syscon_dev == NULL || modem_clock_hal.lpcon_dev == NULL) {
modem_clock_hal.syscon_dev = &MODEM_SYSCON;
@@ -311,8 +320,21 @@ void IRAM_ATTR modem_clock_module_mac_reset(periph_module_t module)
#define MODEM_ETM_CLOCK_DEPS (BIT(MODEM_CLOCK_ETM))
#define MODEM_ADC_COMMON_FE_CLOCK_DEPS (BIT(MODEM_CLOCK_MODEM_ADC_COMMON_FE))
#if SOC_PHY_CALIBRATION_CLOCK_IS_INDEPENDENT
#define PHY_CALIBRATION_CLOCK_DEPS (BIT(MODEM_CLOCK_WIFI_APB) | BIT(MODEM_CLOCK_WIFI_BB_44M))
#define PHY_CALIBRATION_WIFI_CLOCK_DEPS (BIT(MODEM_CLOCK_WIFI_APB) | BIT(MODEM_CLOCK_WIFI_BB) | BIT(MODEM_CLOCK_WIFI_BB_44M))
#define PHY_CALIBRATION_BT_I154_CLOCK_DEPS (BIT(MODEM_CLOCK_WIFI_APB) | BIT(MODEM_CLOCK_WIFI_BB_44M) | BIT(MODEM_CLOCK_BT_I154_COMMON_BB))
#else
#define PHY_CALIBRATION_WIFI_CLOCK_DEPS (BIT(MODEM_CLOCK_WIFI_BB))
#define PHY_CALIBRATION_BT_I154_CLOCK_DEPS (BIT(MODEM_CLOCK_BT_I154_COMMON_BB))
#endif
#ifndef SOC_WIFI_SUPPORTED
#undef PHY_CALIBRATION_WIFI_CLOCK_DEPS
#define PHY_CALIBRATION_WIFI_CLOCK_DEPS 0
#endif
#if !defined(SOC_BT_SUPPORTED) && !defined(SOC_IEEE802154_SUPPORTED)
#undef PHY_CALIBRATION_BT_I154_CLOCK_DEPS
#define PHY_CALIBRATION_BT_I154_CLOCK_DEPS 0
#endif
#define PHY_CALIBRATION_CLOCK_DEPS (PHY_CALIBRATION_WIFI_CLOCK_DEPS | PHY_CALIBRATION_BT_I154_CLOCK_DEPS)
static IRAM_ATTR uint32_t modem_clock_get_module_deps(periph_module_t module)
{
@@ -330,9 +352,7 @@ static IRAM_ATTR uint32_t modem_clock_get_module_deps(periph_module_t module)
#if SOC_BT_SUPPORTED
case PERIPH_BT_MODULE: deps = BLE_CLOCK_DEPS; break;
#endif
#if SOC_PHY_CALIBRATION_CLOCK_IS_INDEPENDENT
case PERIPH_PHY_CALIBRATION_MODULE: deps = PHY_CALIBRATION_CLOCK_DEPS; break;
#endif
#if SOC_IEEE802154_SUPPORTED
case PERIPH_IEEE802154_MODULE: deps = IEEE802154_CLOCK_DEPS; break;
#endif
@@ -395,6 +415,41 @@ void IRAM_ATTR modem_clock_module_disable(periph_module_t module)
modem_clock_device_disable(MODEM_CLOCK_instance(), deps);
}
uint32_t IRAM_ATTR modem_clock_module_bits_get(periph_module_t module)
{
assert(IS_MODEM_MODULE(module));
uint32_t val = 0;
switch (module)
{
#if SOC_WIFI_SUPPORTED
case PERIPH_WIFI_MODULE:
#endif
#if SOC_BT_SUPPORTED
case PERIPH_BT_MODULE:
#endif
#if SOC_IEEE802154_SUPPORTED
case PERIPH_IEEE802154_MODULE:
#endif
case PERIPH_PHY_MODULE:
val = modem_syscon_ll_clk_conf1_get(MODEM_CLOCK_instance()->hal->syscon_dev);
default:
break;
}
return val;
}
#if SOC_WIFI_SUPPORTED
void modem_clock_configure_wifi_status(bool inited)
{
portENTER_CRITICAL_SAFE(&MODEM_CLOCK_instance()->lock);
if (inited)
MODEM_CLOCK_instance()->modem_status |= MODEM_STATUS_WIFI_INITED;
else
MODEM_CLOCK_instance()->modem_status &= ~MODEM_STATUS_WIFI_INITED;
portEXIT_CRITICAL_SAFE(&MODEM_CLOCK_instance()->lock);
}
#endif
void modem_clock_deselect_all_module_lp_clock_source(void)
{
#if SOC_WIFI_SUPPORTED
+85
View File
@@ -10,6 +10,7 @@
#ifdef __PERIPH_CTRL_ALLOW_LEGACY_API
#include "hal/clk_gate_ll.h"
#endif
#include "esp_log.h"
#if SOC_MODEM_CLOCK_IS_INDEPENDENT && SOC_MODEM_CLOCK_SUPPORTED
#include "esp_private/esp_modem_clock.h"
@@ -130,7 +131,10 @@ void wifi_module_enable(void)
modem_clock_module_enable(PERIPH_WIFI_MODULE);
#else
portENTER_CRITICAL_SAFE(&periph_spinlock);
if (ref_counts[PERIPH_WIFI_MODULE] == 0) {
periph_ll_wifi_module_enable_clk_clear_rst();
}
ref_counts[PERIPH_WIFI_MODULE]++;
portEXIT_CRITICAL_SAFE(&periph_spinlock);
#endif
}
@@ -141,8 +145,89 @@ void wifi_module_disable(void)
modem_clock_module_disable(PERIPH_WIFI_MODULE);
#else
portENTER_CRITICAL_SAFE(&periph_spinlock);
ref_counts[PERIPH_WIFI_MODULE]--;
if (ref_counts[PERIPH_WIFI_MODULE] == 0) {
periph_ll_wifi_module_disable_clk_set_rst();
}
portEXIT_CRITICAL_SAFE(&periph_spinlock);
#endif
}
#endif // CONFIG_ESP_WIFI_ENABLED
#if SOC_BT_SUPPORTED || SOC_WIFI_SUPPORTED || SOC_IEEE802154_SUPPORTED
// PERIPH_WIFI_BT_COMMON_MODULE is enabled outside
IRAM_ATTR void phy_module_enable(void)
{
#if SOC_MODEM_CLOCK_IS_INDEPENDENT
modem_clock_module_enable(PERIPH_PHY_CALIBRATION_MODULE);
#else
portENTER_CRITICAL_SAFE(&periph_spinlock);
#if SOC_WIFI_SUPPORTED || SOC_BT_SUPPORTED
periph_ll_phy_calibration_module_enable_clk_clear_rst();
if (ref_counts[PERIPH_RNG_MODULE] == 0) {
periph_ll_enable_clk_clear_rst(PERIPH_RNG_MODULE);
}
ref_counts[PERIPH_RNG_MODULE]++;
#endif
#if SOC_WIFI_SUPPORTED
if (ref_counts[PERIPH_WIFI_MODULE] == 0) {
periph_ll_wifi_module_enable_clk_clear_rst();
}
ref_counts[PERIPH_WIFI_MODULE]++;
#endif
#if SOC_BT_SUPPORTED
if (ref_counts[PERIPH_BT_MODULE] == 0) {
periph_ll_enable_clk_clear_rst(PERIPH_BT_MODULE);
}
ref_counts[PERIPH_BT_MODULE]++;
#endif
portEXIT_CRITICAL_SAFE(&periph_spinlock);
#endif
}
// PERIPH_WIFI_BT_COMMON_MODULE is disabled outside
IRAM_ATTR void phy_module_disable(void)
{
#if SOC_MODEM_CLOCK_IS_INDEPENDENT
modem_clock_module_disable(PERIPH_PHY_CALIBRATION_MODULE);
#else
portENTER_CRITICAL_SAFE(&periph_spinlock);
#if SOC_BT_SUPPORTED
ref_counts[PERIPH_BT_MODULE]--;
if (ref_counts[PERIPH_BT_MODULE] == 0) {
periph_ll_disable_clk_set_rst(PERIPH_BT_MODULE);
}
#endif
#if SOC_WIFI_SUPPORTED
ref_counts[PERIPH_WIFI_MODULE]--;
if (ref_counts[PERIPH_WIFI_MODULE] == 0) {
periph_ll_wifi_module_disable_clk_set_rst();
}
#endif
#if SOC_WIFI_SUPPORTED || SOC_BT_SUPPORTED
// Do not disable PHY clock and RNG clock
ref_counts[PERIPH_RNG_MODULE]--;
#endif
portEXIT_CRITICAL_SAFE(&periph_spinlock);
#endif
}
IRAM_ATTR bool phy_module_has_clock_bits(uint32_t mask)
{
uint32_t val = 0;
#if SOC_MODEM_CLOCK_IS_INDEPENDENT
val = modem_clock_module_bits_get(PERIPH_PHY_MODULE);
#else
#if SOC_WIFI_SUPPORTED || SOC_BT_SUPPORTED
val = DPORT_REG_READ(periph_ll_get_clk_en_reg(PERIPH_WIFI_BT_COMMON_MODULE));
#else
return true;
#endif
#endif
if ((val & mask) != mask) {
ESP_LOGW("periph_ctrl", "phy module clock bits 0x%x, required 0x%x", val, mask);
return false;
}
return true;
}
#endif //#if SOC_BT_SUPPORTED || SOC_WIFI_SUPPORTED || SOC_IEEE802154_SUPPORTED
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -31,6 +31,7 @@
#include "esp_private/systimer.h"
#include "hal/timer_ll.h"
#endif
#include "esp_attr.h"
#define XTAL_32K_BOOTSTRAP_TIME_US 7
@@ -369,7 +370,7 @@ static void rtc_clk_bbpll_configure(soc_xtal_freq_t xtal_freq, int pll_freq)
* Must satisfy: cpu_freq = XTAL_FREQ / div.
* Does not disable the PLL.
*/
void rtc_clk_cpu_freq_to_xtal(int cpu_freq, int div)
FORCE_IRAM_ATTR void rtc_clk_cpu_freq_to_xtal(int cpu_freq, int div)
{
esp_rom_set_cpu_ticks_per_us(cpu_freq);
/* set divider from XTAL to APB clock */
@@ -461,7 +462,7 @@ void rtc_clk_cpu_freq_set_xtal(void)
rtc_clk_bbpll_disable();
}
void rtc_clk_cpu_set_to_default_config(void)
FORCE_IRAM_ATTR void rtc_clk_cpu_set_to_default_config(void)
{
int freq_mhz = (int)rtc_clk_xtal_freq_get();
@@ -607,7 +608,7 @@ void rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t* config)
}
}
soc_xtal_freq_t rtc_clk_xtal_freq_get(void)
FORCE_IRAM_ATTR soc_xtal_freq_t rtc_clk_xtal_freq_get(void)
{
uint32_t xtal_freq_mhz = clk_ll_xtal_load_freq_mhz();
if (xtal_freq_mhz == 0) {
@@ -621,7 +622,7 @@ void rtc_clk_xtal_freq_update(soc_xtal_freq_t xtal_freq)
clk_ll_xtal_store_freq_mhz((uint32_t)xtal_freq);
}
void rtc_clk_apb_freq_update(uint32_t apb_freq)
FORCE_IRAM_ATTR void rtc_clk_apb_freq_update(uint32_t apb_freq)
{
clk_ll_apb_store_freq_hz(apb_freq);
}
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -21,6 +21,7 @@
#include "esp_rom_sys.h"
#include "hal/clk_tree_ll.h"
#include "hal/regi2c_ctrl_ll.h"
#include "esp_attr.h"
static const char *TAG = "rtc_clk";
@@ -289,7 +290,7 @@ void rtc_clk_cpu_freq_set_xtal(void)
rtc_clk_bbpll_disable();
}
void rtc_clk_cpu_set_to_default_config(void)
FORCE_IRAM_ATTR void rtc_clk_cpu_set_to_default_config(void)
{
int freq_mhz = (int)rtc_clk_xtal_freq_get();
@@ -306,7 +307,7 @@ void rtc_clk_cpu_freq_set_xtal_for_sleep(void)
* Must satisfy: cpu_freq = XTAL_FREQ / div.
* Does not disable the PLL.
*/
void rtc_clk_cpu_freq_to_xtal(int cpu_freq, int div)
FORCE_IRAM_ATTR void rtc_clk_cpu_freq_to_xtal(int cpu_freq, int div)
{
esp_rom_set_cpu_ticks_per_us(cpu_freq);
/* Set divider from XTAL to APB clock. Need to set divider to 1 (reg. value 0) first. */
@@ -325,7 +326,7 @@ static void rtc_clk_cpu_freq_to_8m(void)
rtc_clk_apb_freq_update(SOC_CLK_RC_FAST_FREQ_APPROX);
}
soc_xtal_freq_t rtc_clk_xtal_freq_get(void)
FORCE_IRAM_ATTR soc_xtal_freq_t rtc_clk_xtal_freq_get(void)
{
uint32_t xtal_freq_mhz = clk_ll_xtal_load_freq_mhz();
if (xtal_freq_mhz == 0) {
@@ -340,7 +341,7 @@ void rtc_clk_xtal_freq_update(soc_xtal_freq_t xtal_freq)
clk_ll_xtal_store_freq_mhz(xtal_freq);
}
void rtc_clk_apb_freq_update(uint32_t apb_freq)
FORCE_IRAM_ATTR void rtc_clk_apb_freq_update(uint32_t apb_freq)
{
clk_ll_apb_store_freq_hz(apb_freq);
}
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -19,6 +19,7 @@
#include "esp_rom_sys.h"
#include "hal/clk_tree_ll.h"
#include "hal/regi2c_ctrl_ll.h"
#include "esp_attr.h"
static const char *TAG = "rtc_clk";
@@ -318,7 +319,7 @@ void rtc_clk_cpu_freq_set_xtal(void)
rtc_clk_bbpll_disable();
}
void rtc_clk_cpu_set_to_default_config(void)
FORCE_IRAM_ATTR void rtc_clk_cpu_set_to_default_config(void)
{
int freq_mhz = (int)rtc_clk_xtal_freq_get();
@@ -335,7 +336,7 @@ void rtc_clk_cpu_freq_set_xtal_for_sleep(void)
* Must satisfy: cpu_freq = XTAL_FREQ / div.
* Does not disable the PLL.
*/
static void rtc_clk_cpu_freq_to_xtal(int cpu_freq, int div)
static FORCE_IRAM_ATTR void rtc_clk_cpu_freq_to_xtal(int cpu_freq, int div)
{
esp_rom_set_cpu_ticks_per_us(cpu_freq);
/* Set divider from XTAL to APB clock. Need to set divider to 1 (reg. value 0) first. */
@@ -354,7 +355,7 @@ static void rtc_clk_cpu_freq_to_8m(void)
rtc_clk_apb_freq_update(SOC_CLK_RC_FAST_FREQ_APPROX);
}
soc_xtal_freq_t rtc_clk_xtal_freq_get(void)
FORCE_IRAM_ATTR soc_xtal_freq_t rtc_clk_xtal_freq_get(void)
{
uint32_t xtal_freq_mhz = clk_ll_xtal_load_freq_mhz();
if (xtal_freq_mhz == 0) {
@@ -369,7 +370,7 @@ void rtc_clk_xtal_freq_update(soc_xtal_freq_t xtal_freq)
clk_ll_xtal_store_freq_mhz(xtal_freq);
}
void rtc_clk_apb_freq_update(uint32_t apb_freq)
FORCE_IRAM_ATTR void rtc_clk_apb_freq_update(uint32_t apb_freq)
{
clk_ll_apb_store_freq_hz(apb_freq);
}
@@ -14,6 +14,10 @@ if(NOT non_os_build)
list(APPEND srcs "sar_periph_ctrl.c")
endif()
if(NOT BOOTLOADER_BUILD AND CONFIG_ESP_ENABLE_PVT)
list(APPEND srcs "pmu_pvt.c")
endif()
add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" "${srcs}")
target_sources(${COMPONENT_LIB} PRIVATE "${srcs}")
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -99,6 +99,53 @@ storing in efuse (based on ATE 5k ECO3 chips)
#define V_RTC_MID_MUL10000 10800
#define V_DIG_MID_MUL10000 10860
#if CONFIG_ESP_ENABLE_PVT
/*
set pvt default param
*/
#define PVT_CHANNEL0_SEL 33
#define PVT_CHANNEL1_SEL 37
#define PVT_CHANNEL0_CFG 0x13e80
#define PVT_CHANNEL1_CFG 0x13e80
#define PVT_CHANNEL2_CFG 0x10000
#define PVT_CMD0 0x24
#define PVT_CMD1 0x5
#define PVT_CMD2 0x427
#define PVT_TARGET 0xffff
#define PVT_CLK_DIV 1
#define PVT_DELAY_NUM_HIGH 150
#define PVT_DELAY_NUM_LOW 143
#define PVT_PUMP_CHANNEL_CODE 1
#define PVT_PUMP_BITMAP 22
#define PVT_PUMP_DRV 0
#define PVT_DELAY_NUM_PUMP 139
/**
* @brief Initialize PVT related parameters
*/
void pvt_auto_dbias_init(void);
/**
* @brief Enable or disable PVT functions
*
* @param enable true to enable, false to disable
*/
void pvt_func_enable(bool enable);
/**
* @brief Initialize charge pump related parameters
*/
void charge_pump_init(void);
/**
* @brief Enable or disable charge pump functions
*
* @param enable true to enable, false to disable
*/
void charge_pump_enable(bool enable);
#endif //#if CONFIG_ESP_ENABLE_PVT
/**
* @brief CPU clock configuration structure
*/
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -18,6 +18,10 @@
#include "regi2c_ctrl.h"
#include "esp_private/ocode_init.h"
#include "esp_rom_sys.h"
#include "esp_hw_log.h"
#include "soc/rtc.h"
#include "hal/efuse_ll.h"
#include "hal/efuse_hal.h"
static __attribute__((unused)) const char *TAG = "pmu_init";
@@ -220,4 +224,20 @@ void pmu_init(void)
esp_ocode_calib_init();
}
#endif
#if CONFIG_ESP_ENABLE_PVT
/*setup pvt function*/
uint32_t blk_version = efuse_hal_blk_version();
if (blk_version >= 2) {
pvt_auto_dbias_init();
charge_pump_init();
pvt_func_enable(true);
charge_pump_enable(true);
esp_rom_delay_us(1000);
}
else {
ESP_HW_LOGW(TAG, "blk_version is less than 2, pvt function not supported in efuse.");
}
#endif
}
@@ -0,0 +1,161 @@
/*
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <stdlib.h>
#include <esp_types.h>
#include "sdkconfig.h"
#include "esp_attr.h"
#include "soc/soc.h"
#include "soc/pmu_struct.h"
#include "soc/pvt_reg.h"
#include "soc/pcr_reg.h"
#include "soc/pmu_reg.h"
#include "hal/pmu_hal.h"
#include "pmu_param.h"
#include "esp_rom_sys.h"
#include "esp_private/esp_pmu.h"
#include "soc/regi2c_dig_reg.h"
#include "regi2c_ctrl.h"
#include "soc/rtc.h"
#include "hal/efuse_ll.h"
#include "hal/efuse_hal.h"
#include "esp_hw_log.h"
static __attribute__((unused)) const char *TAG = "pmu_pvt";
#if CONFIG_ESP_ENABLE_PVT
static uint8_t get_lp_hp_gap(void)
{
int8_t lp_hp_gap = 0;
uint32_t blk_version = efuse_hal_blk_version();
uint8_t lp_hp_gap_efuse = 0;
if (blk_version >= 2) {
lp_hp_gap_efuse = efuse_ll_get_dbias_vol_gap();
bool gap_flag = lp_hp_gap_efuse >> 4;
uint8_t gap_abs_value = lp_hp_gap_efuse & 0xf;
if (gap_flag) {
lp_hp_gap = -1 * gap_abs_value;
} else {
lp_hp_gap = gap_abs_value;
}
lp_hp_gap = lp_hp_gap - 8;
assert((lp_hp_gap >= -15) && (lp_hp_gap <= 7));
if (lp_hp_gap < 0 ) {
lp_hp_gap = 16 - lp_hp_gap;
}
}
return lp_hp_gap;
}
static void set_pvt_hp_lp_gap(uint8_t value)
{
bool flag = value >> 4;
uint8_t abs_value = value & 0xf;
SET_PERI_REG_BITS(PVT_DBIAS_CMD0_REG, PVT_DBIAS_CMD0_OFFSET_FLAG, flag, PVT_DBIAS_CMD0_OFFSET_FLAG_S);
SET_PERI_REG_BITS(PVT_DBIAS_CMD0_REG, PVT_DBIAS_CMD0_OFFSET_VALUE, abs_value, PVT_DBIAS_CMD0_OFFSET_VALUE_S);
SET_PERI_REG_BITS(PVT_DBIAS_CMD1_REG, PVT_DBIAS_CMD1_OFFSET_FLAG, flag, PVT_DBIAS_CMD1_OFFSET_FLAG_S);
SET_PERI_REG_BITS(PVT_DBIAS_CMD1_REG, PVT_DBIAS_CMD1_OFFSET_VALUE, abs_value, PVT_DBIAS_CMD1_OFFSET_VALUE_S);
SET_PERI_REG_BITS(PVT_DBIAS_CMD2_REG, PVT_DBIAS_CMD2_OFFSET_FLAG, flag, PVT_DBIAS_CMD2_OFFSET_FLAG_S);
SET_PERI_REG_BITS(PVT_DBIAS_CMD2_REG, PVT_DBIAS_CMD2_OFFSET_VALUE, abs_value, PVT_DBIAS_CMD2_OFFSET_VALUE_S);
}
FORCE_INLINE_ATTR uint32_t get_pvt_hp_dbias(void)
{
return GET_PERI_REG_BITS2(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_DBIAS_VOL_V, PMU_HP_DBIAS_VOL_S);
}
FORCE_INLINE_ATTR uint32_t get_pvt_lp_dbias(void)
{
return GET_PERI_REG_BITS2(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_LP_DBIAS_VOL_V, PMU_LP_DBIAS_VOL_S);
}
void pvt_auto_dbias_init(void)
{
uint32_t blk_version = efuse_hal_blk_version();
if (blk_version >= 2) {
SET_PERI_REG_MASK(PCR_PVT_MONITOR_CONF_REG, PCR_PVT_MONITOR_CLK_EN);
SET_PERI_REG_MASK(PCR_PVT_MONITOR_FUNC_CLK_CONF_REG, PCR_PVT_MONITOR_FUNC_CLK_EN);
/*config for dbias func*/
CLEAR_PERI_REG_MASK(PVT_DBIAS_TIMER_REG, PVT_TIMER_EN);
esp_rom_delay_us(1);
SET_PERI_REG_BITS(PVT_DBIAS_CHANNEL_SEL0_REG, PVT_DBIAS_CHANNEL0_SEL, PVT_CHANNEL0_SEL, PVT_DBIAS_CHANNEL0_SEL_S);
SET_PERI_REG_BITS(PVT_DBIAS_CHANNEL_SEL0_REG, PVT_DBIAS_CHANNEL1_SEL, PVT_CHANNEL1_SEL, PVT_DBIAS_CHANNEL1_SEL_S); // Select monitor cell ,which used to monitor PVT situation
SET_PERI_REG_BITS(PVT_DBIAS_CHANNEL0_SEL_REG, PVT_DBIAS_CHANNEL0_CFG, PVT_CHANNEL0_CFG, PVT_DBIAS_CHANNEL0_CFG_S);
SET_PERI_REG_BITS(PVT_DBIAS_CHANNEL1_SEL_REG, PVT_DBIAS_CHANNEL1_CFG, PVT_CHANNEL1_CFG, PVT_DBIAS_CHANNEL1_CFG_S);
SET_PERI_REG_BITS(PVT_DBIAS_CHANNEL2_SEL_REG, PVT_DBIAS_CHANNEL2_CFG, PVT_CHANNEL2_CFG, PVT_DBIAS_CHANNEL2_CFG_S); // Configure filter threshold for avoiding auto-dbias overly sensitive regulation
SET_PERI_REG_BITS(PVT_DBIAS_CMD0_REG, PVT_DBIAS_CMD0_PVT, PVT_CMD0, PVT_DBIAS_CMD0_PVT_S);
SET_PERI_REG_BITS(PVT_DBIAS_CMD1_REG, PVT_DBIAS_CMD1_PVT, PVT_CMD1, PVT_DBIAS_CMD1_PVT_S);
SET_PERI_REG_BITS(PVT_DBIAS_CMD2_REG, PVT_DBIAS_CMD2_PVT, PVT_CMD2, PVT_DBIAS_CMD2_PVT_S); // Configure auto-dbias adjust property, such as adjusting step
SET_PERI_REG_BITS(PVT_DBIAS_TIMER_REG, PVT_TIMER_TARGET, PVT_TARGET, PVT_TIMER_TARGET_S); // Configure auto-dbias voltage regulation cycle
SET_PERI_REG_BITS(PCR_PVT_MONITOR_FUNC_CLK_CONF_REG, PCR_PVT_MONITOR_FUNC_CLK_DIV_NUM, PVT_CLK_DIV, PCR_PVT_MONITOR_FUNC_CLK_DIV_NUM_S);//pvt function clock divider number
/*config for pvt cell: unit0; site2; vt1*/
SET_PERI_REG_MASK(PCR_PVT_MONITOR_FUNC_CLK_CONF_REG, PCR_PVT_MONITOR_FUNC_CLK_SEL); // choose pvt clk
SET_PERI_REG_BITS(PVT_COMB_PD_SITE2_UNIT0_VT1_CONF1_REG, PVT_DELAY_LIMIT_VT1_PD_SITE2_UNIT0, PVT_DELAY_NUM_HIGH, PVT_DELAY_LIMIT_VT1_PD_SITE2_UNIT0_S); // The threshold for determining whether the voltage is too high
SET_PERI_REG_BITS(PVT_COMB_PD_SITE2_UNIT1_VT1_CONF1_REG, PVT_DELAY_LIMIT_VT1_PD_SITE2_UNIT1, PVT_DELAY_NUM_LOW, PVT_DELAY_LIMIT_VT1_PD_SITE2_UNIT1_S); // The threshold for determining whether the voltage is too low
SET_PERI_REG_BITS(PVT_COMB_PD_SITE2_UNIT2_VT1_CONF1_REG, PVT_DELAY_LIMIT_VT1_PD_SITE2_UNIT2, PVT_DELAY_NUM_PUMP, PVT_DELAY_LIMIT_VT1_PD_SITE2_UNIT2_S); // The threshold for chargepump
/*config lp offset for pvt func*/
uint8_t lp_hp_gap = get_lp_hp_gap();
set_pvt_hp_lp_gap(lp_hp_gap);
}
}
void IRAM_ATTR pvt_func_enable(bool enable)
{
uint32_t blk_version = efuse_hal_blk_version();
if (blk_version >= 2) {
if (enable) {
SET_PERI_REG_MASK(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_DIG_DBIAS_INIT); // start calibration @HP_CALI_DBIAS_DEFAULT
SET_PERI_REG_MASK(PCR_PVT_MONITOR_FUNC_CLK_CONF_REG, PCR_PVT_MONITOR_FUNC_CLK_EN);
SET_PERI_REG_MASK(PCR_PVT_MONITOR_CONF_REG, PCR_PVT_MONITOR_CLK_EN);
SET_PERI_REG_MASK(PVT_CLK_CFG_REG, PVT_MONITOR_CLK_PVT_EN); // once enable cannot be closed
SET_PERI_REG_MASK(PVT_COMB_PD_SITE2_UNIT0_VT1_CONF1_REG, PVT_MONITOR_EN_VT1_PD_SITE2_UNIT0); // enable pvt clk
esp_rom_delay_us(10);
CLEAR_PERI_REG_MASK(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_DIG_REGULATOR0_DBIAS_SEL); // hand over control of dbias to pvt
CLEAR_PERI_REG_MASK(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_DIG_DBIAS_INIT); // must clear @HP_CALI_DBIAS_DEFAULT
SET_PERI_REG_MASK(PVT_DBIAS_TIMER_REG, PVT_TIMER_EN); // enable auto dbias
} else {
uint32_t pvt_hp_dbias = get_pvt_hp_dbias();
uint32_t pvt_lp_dbias = get_pvt_lp_dbias(); // update pvt_cali_dbias
SET_PERI_REG_BITS(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_ACTIVE_HP_REGULATOR_DBIAS, pvt_hp_dbias, PMU_HP_ACTIVE_HP_REGULATOR_DBIAS_S);
SET_PERI_REG_BITS(PMU_HP_SLEEP_LP_REGULATOR0_REG, PMU_HP_SLEEP_LP_REGULATOR_DBIAS, pvt_lp_dbias, PMU_HP_SLEEP_LP_REGULATOR_DBIAS_S);
CLEAR_PERI_REG_MASK(PVT_DBIAS_TIMER_REG, PVT_TIMER_EN); //disable auto dbias
SET_PERI_REG_MASK(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_DIG_REGULATOR0_DBIAS_SEL); // hand over control of dbias to pmu
CLEAR_PERI_REG_MASK(PCR_PVT_MONITOR_CONF_REG, PCR_PVT_MONITOR_CLK_EN);
CLEAR_PERI_REG_MASK(PCR_PVT_MONITOR_FUNC_CLK_CONF_REG, PCR_PVT_MONITOR_FUNC_CLK_EN);
}
}
}
void charge_pump_init(void)
{
uint32_t blk_version = efuse_hal_blk_version();
if (blk_version >= 2) {
/*config for charge pump*/
SET_PERI_REG_BITS(PVT_PMUP_CHANNEL_CFG_REG, PVT_PUMP_CHANNEL_CODE0, PVT_PUMP_CHANNEL_CODE, PVT_PUMP_CHANNEL_CODE0_S); //Set channel code
WRITE_PERI_REG(PVT_PMUP_BITMAP_LOW0_REG, (1 << PVT_PUMP_BITMAP)); // Select monitor cell for charge pump
SET_PERI_REG_BITS(PVT_PMUP_DRV_CFG_REG, PVT_PUMP_DRV0, PVT_PUMP_DRV, PVT_PUMP_DRV0_S); //Configure the charging intensity
}
}
void IRAM_ATTR charge_pump_enable(bool enable)
{
uint32_t blk_version = efuse_hal_blk_version();
if (blk_version >= 2) {
if (enable) {
SET_PERI_REG_MASK(PVT_PMUP_DRV_CFG_REG, PVT_PUMP_EN); // enable charge pump
} else {
CLEAR_PERI_REG_MASK(PVT_PMUP_DRV_CFG_REG, PVT_PUMP_EN); //disable charge pump
}
}
}
#endif
@@ -324,6 +324,10 @@ static void pmu_sleep_analog_init(pmu_context_t *ctx, const pmu_sleep_analog_con
pmu_ll_hp_set_regulator_xpd (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.xpd);
pmu_ll_hp_set_regulator_dbias (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.dbias);
pmu_ll_hp_set_regulator_driver_bar (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.drv_b);
#if CONFIG_ESP_ENABLE_PVT
uint32_t pvt_hp_dbias = GET_PERI_REG_BITS2(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_DBIAS_VOL_V, PMU_HP_DBIAS_VOL_S);
pmu_ll_hp_set_regulator_dbias (ctx->hal->dev, HP(MODEM), pvt_hp_dbias);
#endif
pmu_ll_lp_set_dbg_atten (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.dbg_atten);
pmu_ll_lp_set_current_power_off (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.pd_cur);
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -24,6 +24,8 @@
#include "hal/efuse_hal.h"
#include "soc/chip_revision.h"
#include "esp_private/regi2c_ctrl.h"
#include "esp_attr.h"
#include "esp_private/esp_pmu.h"
static const char *TAG = "rtc_clk";
@@ -170,7 +172,7 @@ static void rtc_clk_bbpll_configure(soc_xtal_freq_t xtal_freq, int pll_freq)
* Must satisfy: cpu_freq = XTAL_FREQ / div.
* Does not disable the PLL.
*/
static void rtc_clk_cpu_freq_to_xtal(int cpu_freq, int div)
static FORCE_IRAM_ATTR void rtc_clk_cpu_freq_to_xtal(int cpu_freq, int div)
{
// let f_cpu = f_ahb
clk_ll_cpu_set_divider(div);
@@ -178,6 +180,10 @@ static void rtc_clk_cpu_freq_to_xtal(int cpu_freq, int div)
clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_XTAL);
clk_ll_bus_update();
esp_rom_set_cpu_ticks_per_us(cpu_freq);
#if CONFIG_ESP_ENABLE_PVT && !defined(BOOTLOADER_BUILD)
charge_pump_enable(false);
pvt_func_enable(false);
#endif
}
static void rtc_clk_cpu_freq_to_8m(void)
@@ -187,6 +193,10 @@ static void rtc_clk_cpu_freq_to_8m(void)
clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_RC_FAST);
clk_ll_bus_update();
esp_rom_set_cpu_ticks_per_us(20);
#if CONFIG_ESP_ENABLE_PVT && !defined(BOOTLOADER_BUILD)
charge_pump_enable(false);
pvt_func_enable(false);
#endif
}
/**
@@ -196,6 +206,12 @@ static void rtc_clk_cpu_freq_to_8m(void)
*/
static void rtc_clk_cpu_freq_to_pll_240_mhz(int cpu_freq_mhz)
{
#if CONFIG_ESP_ENABLE_PVT && !defined(BOOTLOADER_BUILD)
pvt_auto_dbias_init();
charge_pump_init();
pvt_func_enable(true);
charge_pump_enable(true);
#endif
// f_hp_root = 240MHz
uint32_t cpu_divider = CLK_LL_PLL_240M_FREQ_MHZ / cpu_freq_mhz;
clk_ll_cpu_set_divider(cpu_divider);
@@ -216,6 +232,12 @@ static void rtc_clk_cpu_freq_to_pll_240_mhz(int cpu_freq_mhz)
*/
static void rtc_clk_cpu_freq_to_pll_160_mhz(int cpu_freq_mhz)
{
#if CONFIG_ESP_ENABLE_PVT && !defined(BOOTLOADER_BUILD)
pvt_auto_dbias_init();
charge_pump_init();
pvt_func_enable(true);
charge_pump_enable(true);
#endif
// f_hp_root = 160MHz
uint32_t cpu_divider = CLK_LL_PLL_160M_FREQ_MHZ / cpu_freq_mhz;
clk_ll_cpu_set_divider(cpu_divider);
@@ -429,7 +451,7 @@ void rtc_clk_cpu_freq_set_xtal(void)
rtc_clk_bbpll_disable();
}
void rtc_clk_cpu_set_to_default_config(void)
FORCE_IRAM_ATTR void rtc_clk_cpu_set_to_default_config(void)
{
int freq_mhz = (int)rtc_clk_xtal_freq_get();
#ifndef BOOTLOADER_BUILD
@@ -475,7 +497,7 @@ void rtc_clk_cpu_freq_to_pll_and_pll_lock_release(int cpu_freq_mhz)
}
#endif
soc_xtal_freq_t rtc_clk_xtal_freq_get(void)
FORCE_IRAM_ATTR soc_xtal_freq_t rtc_clk_xtal_freq_get(void)
{
uint32_t xtal_freq_mhz = clk_ll_xtal_get_freq_mhz();
assert(xtal_freq_mhz == SOC_XTAL_FREQ_48M || xtal_freq_mhz == SOC_XTAL_FREQ_40M);
@@ -83,6 +83,8 @@ void rtc_clk_init(rtc_clk_config_t cfg)
uint32_t hp_cali_dbias = get_act_hp_dbias();
uint32_t lp_cali_dbias = get_act_lp_dbias();
SET_PERI_REG_MASK(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_DIG_REGULATOR0_DBIAS_SEL); // Hand over control of dbias to pmu
SET_PERI_REG_BITS(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_ACTIVE_HP_REGULATOR_DBIAS, hp_cali_dbias, PMU_HP_ACTIVE_HP_REGULATOR_DBIAS_S);
SET_PERI_REG_BITS(PMU_HP_MODEM_HP_REGULATOR0_REG, PMU_HP_MODEM_HP_REGULATOR_DBIAS, hp_cali_dbias, PMU_HP_MODEM_HP_REGULATOR_DBIAS_S);
SET_PERI_REG_BITS(PMU_HP_SLEEP_LP_REGULATOR0_REG, PMU_HP_SLEEP_LP_REGULATOR_DBIAS, lp_cali_dbias, PMU_HP_SLEEP_LP_REGULATOR_DBIAS_S);
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -106,8 +106,6 @@ void pvt_auto_dbias_init(void)
/*config lp offset for pvt func*/
uint8_t lp_hp_gap = get_lp_hp_gap();
set_pvt_hp_lp_gap(lp_hp_gap);
} else {
ESP_HW_LOGD(TAG, "blk_version is less than 3, pvt auto dbias init not supported in efuse.");
}
}
@@ -135,8 +133,6 @@ void IRAM_ATTR pvt_func_enable(bool enable)
CLEAR_PERI_REG_MASK(PCR_PVT_MONITOR_CONF_REG, PCR_PVT_MONITOR_CLK_EN);
CLEAR_PERI_REG_MASK(PCR_PVT_MONITOR_FUNC_CLK_CONF_REG, PCR_PVT_MONITOR_FUNC_CLK_EN);
}
} else {
ESP_HW_LOGD(TAG, "blk_version is less than 3, pvt enable not supported in efuse.");
}
}
@@ -148,8 +144,6 @@ void charge_pump_init(void)
SET_PERI_REG_BITS(PVT_PMUP_CHANNEL_CFG_REG, PVT_PUMP_CHANNEL_CODE0, PVT_PUMP_CHANNEL_CODE, PVT_PUMP_CHANNEL_CODE0_S); //Set channel code
WRITE_PERI_REG(PVT_PMUP_BITMAP_LOW0_REG, (1 << PVT_PUMP_BITMAP)); // Select monitor cell for charge pump
SET_PERI_REG_BITS(PVT_PMUP_DRV_CFG_REG, PVT_PUMP_DRV0, PVT_PUMP_DRV, PVT_PUMP_DRV0_S); //Configure the charging intensity
} else {
ESP_HW_LOGD(TAG, "blk_version is less than 3, pvt charge_pump init not supported in efuse.");
}
}
@@ -162,8 +156,6 @@ void IRAM_ATTR charge_pump_enable(bool enable)
} else {
CLEAR_PERI_REG_MASK(PVT_PMUP_DRV_CFG_REG, PVT_PUMP_EN); //disable charge pump
}
} else {
ESP_HW_LOGD(TAG, "blk_version is less than 3, pvt charge_pump enable not supported in efuse.");
}
}
@@ -22,6 +22,7 @@
#include "soc/lp_aon_reg.h"
#include "esp_private/sleep_event.h"
#include "esp_private/regi2c_ctrl.h"
#include "esp_attr.h"
static const char *TAG = "rtc_clk";
@@ -184,7 +185,7 @@ static void rtc_clk_bbpll_configure(soc_xtal_freq_t xtal_freq, int pll_freq)
* Must satisfy: cpu_freq = XTAL_FREQ / div.
* Does not disable the PLL.
*/
static void rtc_clk_cpu_freq_to_xtal(int cpu_freq, int div)
static FORCE_IRAM_ATTR void rtc_clk_cpu_freq_to_xtal(int cpu_freq, int div)
{
clk_ll_ahb_set_ls_divider(div);
clk_ll_cpu_set_ls_divider(div);
@@ -359,7 +360,7 @@ void rtc_clk_cpu_freq_set_xtal(void)
rtc_clk_bbpll_disable();
}
void rtc_clk_cpu_set_to_default_config(void)
FORCE_IRAM_ATTR void rtc_clk_cpu_set_to_default_config(void)
{
int freq_mhz = (int)rtc_clk_xtal_freq_get();
@@ -378,7 +379,7 @@ void rtc_clk_cpu_freq_to_pll_and_pll_lock_release(int cpu_freq_mhz)
clk_ll_cpu_clk_src_lock_release();
}
soc_xtal_freq_t rtc_clk_xtal_freq_get(void)
FORCE_IRAM_ATTR soc_xtal_freq_t rtc_clk_xtal_freq_get(void)
{
uint32_t xtal_freq_mhz = clk_ll_xtal_load_freq_mhz();
if (xtal_freq_mhz == 0) {

Some files were not shown because too many files have changed in this diff Show More