Merge branch 'espressif:release/v5.5' into release/v5.5
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
Submodule components/bt/controller/lib_esp32c5/esp32c5-bt-lib updated: 95899f11a3...bbff15b4d8
Submodule components/bt/controller/lib_esp32c6/esp32c6-bt-lib updated: d40be82077...d8b5341796
Submodule components/bt/controller/lib_esp32h2/esp32h2-bt-lib updated: 1034b3c595...27ca7c0a07
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Submodule components/bt/esp_ble_mesh/lib/lib updated: 85e64e61f8...e44762384e
@@ -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 ((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_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 (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 (p_scb->seps[p_scb->sep_idx].p_app_data_cback != NULL) {
|
||||
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->seps[p_scb->sep_idx].p_app_data_cback != NULL) {
|
||||
APPL_TRACE_DEBUG(" Configure Deoder for Sink 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 (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,46 +106,54 @@ 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 */
|
||||
BE_STREAM_TO_UINT8 (p_result->get_cur_app_val.num_attr, p);
|
||||
if (len != (p_result->get_cur_app_val.num_attr + 1)) {
|
||||
if (len < 1) {
|
||||
status = AVRC_STS_INTERNAL_ERR;
|
||||
break;
|
||||
}
|
||||
p_u8 = p_result->get_cur_app_val.attrs;
|
||||
for (xx = 0, yy = 0; xx < p_result->get_cur_app_val.num_attr; xx++) {
|
||||
/* only report the valid player app attributes */
|
||||
if (AVRC_IsValidPlayerAttr(*p)) {
|
||||
p_u8[yy++] = *p;
|
||||
} 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;
|
||||
break;
|
||||
}
|
||||
p_u8 = p_result->get_cur_app_val.attrs;
|
||||
for (xx = 0, yy = 0; xx < p_result->get_cur_app_val.num_attr; xx++) {
|
||||
/* only report the valid player app attributes */
|
||||
if (AVRC_IsValidPlayerAttr(*p)) {
|
||||
p_u8[yy++] = *p;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
p_result->get_cur_app_val.num_attr = yy;
|
||||
if (yy == 0) {
|
||||
status = AVRC_STS_BAD_PARAM;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
p_result->get_cur_app_val.num_attr = yy;
|
||||
if (yy == 0) {
|
||||
status = AVRC_STS_BAD_PARAM;
|
||||
}
|
||||
break;
|
||||
|
||||
case AVRC_PDU_SET_PLAYER_APP_VALUE: /* 0x14 */
|
||||
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))) {
|
||||
p_result->set_app_val.p_vals = (tAVRC_APP_SETTING *)p_buf;
|
||||
p_app_set = p_result->set_app_val.p_vals;
|
||||
for (xx = 0; ((xx < p_result->set_app_val.num_val) && (buf_len > size_needed)); xx++) {
|
||||
p_app_set[xx].attr_id = *p++;
|
||||
p_app_set[xx].attr_val = *p++;
|
||||
if (!avrc_is_valid_player_attrib_value(p_app_set[xx].attr_id, p_app_set[xx].attr_val)) {
|
||||
status = AVRC_STS_BAD_PARAM;
|
||||
}
|
||||
}
|
||||
if (xx != p_result->set_app_val.num_val) {
|
||||
AVRC_TRACE_ERROR("AVRC_PDU_SET_PLAYER_APP_VALUE not enough room:%d orig num_val:%d",
|
||||
xx, p_result->set_app_val.num_val);
|
||||
p_result->set_app_val.num_val = xx;
|
||||
}
|
||||
} else {
|
||||
AVRC_TRACE_ERROR("AVRC_PDU_SET_PLAYER_APP_VALUE NULL decode buffer or bad len");
|
||||
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))) {
|
||||
p_result->set_app_val.p_vals = (tAVRC_APP_SETTING *)p_buf;
|
||||
p_app_set = p_result->set_app_val.p_vals;
|
||||
for (xx = 0; ((xx < p_result->set_app_val.num_val) && (buf_len > size_needed)); xx++) {
|
||||
p_app_set[xx].attr_id = *p++;
|
||||
p_app_set[xx].attr_val = *p++;
|
||||
if (!avrc_is_valid_player_attrib_value(p_app_set[xx].attr_id, p_app_set[xx].attr_val)) {
|
||||
status = AVRC_STS_BAD_PARAM;
|
||||
}
|
||||
}
|
||||
if (xx != p_result->set_app_val.num_val) {
|
||||
AVRC_TRACE_ERROR("AVRC_PDU_SET_PLAYER_APP_VALUE not enough room:%d orig num_val:%d",
|
||||
xx, p_result->set_app_val.num_val);
|
||||
p_result->set_app_val.num_val = xx;
|
||||
}
|
||||
} else {
|
||||
AVRC_TRACE_ERROR("AVRC_PDU_SET_PLAYER_APP_VALUE NULL decode buffer or bad len");
|
||||
status = AVRC_STS_INTERNAL_ERR;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
Submodule components/bt/host/nimble/nimble updated: d9a6fa8630...039d2d62ed
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -144,15 +144,15 @@ 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
|
||||
//To enable the APB_SARADC periph if needed
|
||||
_lock_acquire(&s_ctx.mutex);
|
||||
s_ctx.apb_periph_ref_cnts++;
|
||||
if (s_ctx.apb_periph_ref_cnts == 1) {
|
||||
adc_apb_periph_claim();
|
||||
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++;
|
||||
if (s_ctx.apb_periph_ref_cnts == 1) {
|
||||
adc_apb_periph_claim();
|
||||
}
|
||||
_lock_release(&s_ctx.mutex);
|
||||
}
|
||||
_lock_release(&s_ctx.mutex);
|
||||
#endif
|
||||
|
||||
if (init_config->ulp_mode == ADC_ULP_MODE_DISABLE) {
|
||||
sar_periph_ctrl_adc_oneshot_power_acquire();
|
||||
@@ -297,18 +297,20 @@ 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
|
||||
//To free the APB_SARADC periph if needed
|
||||
_lock_acquire(&s_ctx.mutex);
|
||||
s_ctx.apb_periph_ref_cnts--;
|
||||
assert(s_ctx.apb_periph_ref_cnts >= 0);
|
||||
if (s_ctx.apb_periph_ref_cnts == 0) {
|
||||
adc_apb_periph_free();
|
||||
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--;
|
||||
assert(s_ctx.apb_periph_ref_cnts >= 0);
|
||||
if (s_ctx.apb_periph_ref_cnts == 0) {
|
||||
adc_apb_periph_free();
|
||||
}
|
||||
_lock_release(&s_ctx.mutex);
|
||||
}
|
||||
_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
|
||||
|
||||
|
||||
@@ -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})
|
||||
+2
-2
@@ -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
-2
@@ -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
|
||||
+2
-2
@@ -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
-2
@@ -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
|
||||
+2
-2
@@ -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
-2
@@ -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
|
||||
+8
-3
@@ -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
-1
@@ -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
|
||||
*/
|
||||
@@ -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];
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
* @}
|
||||
*/
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
periph_ll_wifi_module_enable_clk_clear_rst();
|
||||
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);
|
||||
periph_ll_wifi_module_disable_clk_set_rst();
|
||||
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
Reference in New Issue
Block a user