fix(ble/bluedroid): fix BLE bonding key storage validation

(cherry picked from commit 62cdd4ac38)

Co-authored-by: zhiweijian <zhiweijian@espressif.com>
This commit is contained in:
Zhi Wei Jian
2026-06-10 19:53:46 +08:00
parent ed8e4b6a37
commit 665b52b20f
3 changed files with 114 additions and 34 deletions
@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -90,6 +90,17 @@ void btc_storage_save(void)
} }
#if (BLE_INCLUDED == TRUE) #if (BLE_INCLUDED == TRUE)
static bool btc_storage_is_all_zeros(const void *buf, size_t len)
{
const uint8_t *p = (const uint8_t *)buf;
for (size_t i = 0; i < len; i++) {
if (p[i] != 0) {
return false;
}
}
return true;
}
static bt_status_t _btc_storage_add_ble_bonding_key(bt_bdaddr_t *remote_bd_addr, static bt_status_t _btc_storage_add_ble_bonding_key(bt_bdaddr_t *remote_bd_addr,
char *key, char *key,
uint8_t key_type, uint8_t key_type,
@@ -158,33 +169,48 @@ static bt_status_t _btc_storage_get_ble_bonding_key(bt_bdaddr_t *remote_bd_addr,
{ {
bdstr_t bdstr; bdstr_t bdstr;
bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr)); bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
const char* name; const char *name;
size_t expected_len;
switch (key_type) { switch (key_type) {
case BTM_LE_KEY_PENC: case BTM_LE_KEY_PENC:
name = BTC_BLE_STORAGE_LE_KEY_PENC_STR; name = BTC_BLE_STORAGE_LE_KEY_PENC_STR;
expected_len = sizeof(tBTM_LE_PENC_KEYS);
break; break;
case BTM_LE_KEY_PID: case BTM_LE_KEY_PID:
name = BTC_BLE_STORAGE_LE_KEY_PID_STR; name = BTC_BLE_STORAGE_LE_KEY_PID_STR;
expected_len = sizeof(tBTM_LE_PID_KEYS);
break; break;
case BTM_LE_KEY_PCSRK: case BTM_LE_KEY_PCSRK:
name = BTC_BLE_STORAGE_LE_KEY_PCSRK_STR; name = BTC_BLE_STORAGE_LE_KEY_PCSRK_STR;
expected_len = sizeof(tBTM_LE_PCSRK_KEYS);
break; break;
case BTM_LE_KEY_LENC: case BTM_LE_KEY_LENC:
name = BTC_BLE_STORAGE_LE_KEY_LENC_STR; name = BTC_BLE_STORAGE_LE_KEY_LENC_STR;
expected_len = sizeof(tBTM_LE_LENC_KEYS);
break; break;
case BTM_LE_KEY_LCSRK: case BTM_LE_KEY_LCSRK:
name = BTC_BLE_STORAGE_LE_KEY_LCSRK_STR; name = BTC_BLE_STORAGE_LE_KEY_LCSRK_STR;
expected_len = sizeof(tBTM_LE_LCSRK_KEYS);
break; break;
case BTM_LE_KEY_LID: case BTM_LE_KEY_LID:
name = BTC_BLE_STORAGE_LE_KEY_LID_STR; /* LID is a flag-only key; no payload is persisted. */
name = BTC_BLE_STORAGE_LE_KEY_LID_STR;
expected_len = 0;
break; break;
default: default:
return BT_STATUS_FAIL; return BT_STATUS_FAIL;
} }
size_t length = key_length;
int ret = btc_config_get_bin(bdstr, name, (uint8_t *)key_value, &length);
return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
if (key_length < 0 || (size_t)key_length < expected_len) {
return BT_STATUS_FAIL;
}
size_t length = (size_t)key_length;
bool ret = btc_config_get_bin(bdstr, name, (uint8_t *)key_value, &length);
if (!ret || length != expected_len) {
return BT_STATUS_FAIL;
}
return BT_STATUS_SUCCESS;
} }
bt_status_t btc_storage_get_ble_bonding_key(bt_bdaddr_t *remote_bd_addr, bt_status_t btc_storage_get_ble_bonding_key(bt_bdaddr_t *remote_bd_addr,
@@ -237,17 +263,22 @@ static bt_status_t _btc_storage_remove_all_ble_keys(const char *name)
void btc_storage_remove_unused_sections(uint8_t *cur_addr, tBTM_LE_PID_KEYS *del_pid_key) void btc_storage_remove_unused_sections(uint8_t *cur_addr, tBTM_LE_PID_KEYS *del_pid_key)
{ {
bt_bdaddr_t bd_addr; bt_bdaddr_t bd_addr;
uint32_t device_type = 0;
if (del_pid_key == NULL) { if (del_pid_key == NULL) {
return; return;
} }
// Only use valid static address for de-duplication.
if (btc_storage_is_all_zeros(del_pid_key->static_addr, sizeof(del_pid_key->static_addr))) {
return;
}
btc_config_lock(); btc_config_lock();
const btc_config_section_iter_t *iter = btc_config_section_begin(); const btc_config_section_iter_t *iter = btc_config_section_begin();
while (iter != btc_config_section_end()) { while (iter != btc_config_section_end()) {
uint32_t device_type = 0;
//store the next iter, if remove section, then will not loss the point //store the next iter, if remove section, then will not loss the point
const char *section = btc_config_section_name(iter); const char *section = btc_config_section_name(iter);
@@ -276,13 +307,19 @@ void btc_storage_remove_unused_sections(uint8_t *cur_addr, tBTM_LE_PID_KEYS *del
char buffer[sizeof(tBTM_LE_KEY_VALUE)] = {0}; char buffer[sizeof(tBTM_LE_KEY_VALUE)] = {0};
if (_btc_storage_get_ble_bonding_key(&bd_addr, BTM_LE_KEY_PID, buffer, sizeof(tBTM_LE_PID_KEYS)) == BT_STATUS_SUCCESS) { size_t pid_len = sizeof(tBTM_LE_PID_KEYS);
bool pid_ok = btc_config_get_bin(section, BTC_BLE_STORAGE_LE_KEY_PID_STR, (uint8_t *)buffer, &pid_len);
if (pid_ok && pid_len >= sizeof(tBTM_LE_PID_KEYS)) {
tBTM_LE_PID_KEYS *pid_key = (tBTM_LE_PID_KEYS *) buffer; tBTM_LE_PID_KEYS *pid_key = (tBTM_LE_PID_KEYS *) buffer;
iter = btc_config_section_next(iter); iter = btc_config_section_next(iter);
if (memcmp(del_pid_key->static_addr, pid_key->static_addr, 6) == 0 && memcmp(cur_addr, bd_addr.address, 6) != 0 && del_pid_key->addr_type == pid_key->addr_type) { if (del_pid_key->addr_type == pid_key->addr_type &&
!btc_storage_is_all_zeros(pid_key->static_addr, sizeof(pid_key->static_addr)) &&
memcmp(del_pid_key->static_addr, pid_key->static_addr, sizeof(pid_key->static_addr)) == 0 &&
memcmp(cur_addr, bd_addr.address, sizeof(bd_addr.address)) != 0) {
if (device_type == BT_DEVICE_TYPE_DUMO) { if (device_type == BT_DEVICE_TYPE_DUMO) {
btc_config_set_int(section, BTC_BLE_STORAGE_DEV_TYPE_STR, BT_DEVICE_TYPE_BREDR); btc_config_set_int(section, BTC_BLE_STORAGE_DEV_TYPE_STR, BT_DEVICE_TYPE_BREDR);
_btc_storage_remove_all_ble_keys(section); _btc_storage_remove_all_ble_keys(section);
@@ -308,13 +345,13 @@ void btc_storage_delete_duplicate_ble_devices(void)
char temp_buffer[sizeof(tBTM_LE_KEY_VALUE)] = {0}; char temp_buffer[sizeof(tBTM_LE_KEY_VALUE)] = {0};
tBTM_LE_PID_KEYS *pid_key; tBTM_LE_PID_KEYS *pid_key;
tBTM_LE_PID_KEYS *temp_pid_key; tBTM_LE_PID_KEYS *temp_pid_key;
uint32_t device_type = 0;
bt_bdaddr_t temp_bd_addr; bt_bdaddr_t temp_bd_addr;
btc_config_lock(); btc_config_lock();
for (const btc_config_section_iter_t *iter = btc_config_section_begin(); iter != btc_config_section_end(); for (const btc_config_section_iter_t *iter = btc_config_section_begin(); iter != btc_config_section_end();
iter = btc_config_section_next(iter)) { iter = btc_config_section_next(iter)) {
uint32_t device_type = 0;
const char *name = btc_config_section_name(iter); const char *name = btc_config_section_name(iter);
if (!string_is_bdaddr(name) || if (!string_is_bdaddr(name) ||
@@ -324,27 +361,36 @@ void btc_storage_delete_duplicate_ble_devices(void)
} }
string_to_bdaddr(name, &bd_addr); string_to_bdaddr(name, &bd_addr);
if (_btc_storage_get_ble_bonding_key(&bd_addr, BTM_LE_KEY_PID, buffer, sizeof(tBTM_LE_PID_KEYS)) == BT_STATUS_SUCCESS) size_t pid_len = sizeof(tBTM_LE_PID_KEYS);
bool pid_ok = btc_config_get_bin(name, BTC_BLE_STORAGE_LE_KEY_PID_STR, (uint8_t *)buffer, &pid_len);
if (pid_ok && pid_len >= sizeof(tBTM_LE_PID_KEYS))
{ {
pid_key = (tBTM_LE_PID_KEYS *) buffer; pid_key = (tBTM_LE_PID_KEYS *) buffer;
if (btc_storage_is_all_zeros(pid_key->static_addr, sizeof(pid_key->static_addr))) {
continue;
}
const btc_config_section_iter_t *temp_iter = btc_config_section_next(iter); const btc_config_section_iter_t *temp_iter = btc_config_section_next(iter);
while (temp_iter != NULL) while (temp_iter != NULL)
{ {
uint32_t temp_device_type = 0;
const char *temp_name = btc_config_section_name(temp_iter); const char *temp_name = btc_config_section_name(temp_iter);
if (!string_is_bdaddr(temp_name) || !btc_config_get_int(temp_name, BTC_BLE_STORAGE_DEV_TYPE_STR, (int *)&device_type) || if (!string_is_bdaddr(temp_name) || !btc_config_get_int(temp_name, BTC_BLE_STORAGE_DEV_TYPE_STR, (int *)&temp_device_type) ||
((device_type & BT_DEVICE_TYPE_BLE) != BT_DEVICE_TYPE_BLE)) { ((temp_device_type & BT_DEVICE_TYPE_BLE) != BT_DEVICE_TYPE_BLE)) {
temp_iter = btc_config_section_next(temp_iter); temp_iter = btc_config_section_next(temp_iter);
continue; continue;
} }
string_to_bdaddr(temp_name, &temp_bd_addr); string_to_bdaddr(temp_name, &temp_bd_addr);
if (_btc_storage_get_ble_bonding_key(&temp_bd_addr, BTM_LE_KEY_PID, temp_buffer, sizeof(tBTM_LE_PID_KEYS)) == BT_STATUS_SUCCESS) size_t temp_pid_len = sizeof(tBTM_LE_PID_KEYS);
bool temp_pid_ok = btc_config_get_bin(temp_name, BTC_BLE_STORAGE_LE_KEY_PID_STR, (uint8_t *)temp_buffer, &temp_pid_len);
if (temp_pid_ok && temp_pid_len >= sizeof(tBTM_LE_PID_KEYS))
{ {
temp_pid_key = (tBTM_LE_PID_KEYS *) temp_buffer; temp_pid_key = (tBTM_LE_PID_KEYS *) temp_buffer;
if (memcmp(pid_key->static_addr, temp_pid_key->static_addr, 6) == 0 && pid_key->addr_type == temp_pid_key->addr_type) { if (pid_key->addr_type == temp_pid_key->addr_type &&
const char *temp_name = btc_config_section_name(temp_iter); !btc_storage_is_all_zeros(temp_pid_key->static_addr, sizeof(temp_pid_key->static_addr)) &&
memcmp(pid_key->static_addr, temp_pid_key->static_addr, sizeof(pid_key->static_addr)) == 0) {
temp_iter = btc_config_section_next(temp_iter); temp_iter = btc_config_section_next(temp_iter);
if (device_type == BT_DEVICE_TYPE_DUMO) { if (temp_device_type == BT_DEVICE_TYPE_DUMO) {
btc_config_set_int(temp_name, BTC_BLE_STORAGE_DEV_TYPE_STR, BT_DEVICE_TYPE_BREDR); btc_config_set_int(temp_name, BTC_BLE_STORAGE_DEV_TYPE_STR, BT_DEVICE_TYPE_BREDR);
_btc_storage_remove_all_ble_keys(temp_name); _btc_storage_remove_all_ble_keys(temp_name);
} else { } else {
@@ -484,9 +530,11 @@ static bt_status_t _btc_storage_get_ble_local_key(uint8_t key_type,
} }
size_t length = key_length; size_t length = key_length;
int ret = btc_config_get_bin(BTC_BLE_STORAGE_LOCAL_ADAPTER_STR, name, (uint8_t *)key_value, &length); bool ret = btc_config_get_bin(BTC_BLE_STORAGE_LOCAL_ADAPTER_STR, name, (uint8_t *)key_value, &length);
if (!ret || length != (size_t)key_length) {
return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL; return BT_STATUS_FAIL;
}
return BT_STATUS_SUCCESS;
} }
bt_status_t btc_storage_get_ble_local_key(uint8_t key_type, bt_status_t btc_storage_get_ble_local_key(uint8_t key_type,
@@ -905,8 +953,8 @@ static void _btc_read_le_key(const uint8_t key_type, const size_t key_len, bt_bd
} }
bt_status_t _btc_storage_in_fetch_bonded_ble_device(const char *remote_bd_addr, int add) bt_status_t _btc_storage_in_fetch_bonded_ble_device(const char *remote_bd_addr, int add)
{ {
uint32_t device_type; uint32_t device_type = 0;
int addr_type; int addr_type = BLE_ADDR_PUBLIC;
bt_bdaddr_t bd_addr; bt_bdaddr_t bd_addr;
BD_ADDR bta_bd_addr; BD_ADDR bta_bd_addr;
bool device_added = false; bool device_added = false;
@@ -1015,11 +1063,11 @@ bt_status_t btc_storage_get_bonded_ble_devices_list(esp_ble_bond_dev_t *bond_dev
int btc_storage_get_num_ble_bond_devices(void) int btc_storage_get_num_ble_bond_devices(void)
{ {
int num_dev = 0; int num_dev = 0;
uint32_t device_type = 0;
btc_config_lock(); btc_config_lock();
for (const btc_config_section_iter_t *iter = btc_config_section_begin(); iter != btc_config_section_end(); for (const btc_config_section_iter_t *iter = btc_config_section_begin(); iter != btc_config_section_end();
iter = btc_config_section_next(iter)) { iter = btc_config_section_next(iter)) {
uint32_t device_type = 0;
const char *name = btc_config_section_name(iter); const char *name = btc_config_section_name(iter);
if (!string_is_bdaddr(name) || if (!string_is_bdaddr(name) ||
!btc_config_get_int(name, BTC_BLE_STORAGE_DEV_TYPE_STR, (int *)&device_type) || !btc_config_get_int(name, BTC_BLE_STORAGE_DEV_TYPE_STR, (int *)&device_type) ||
@@ -1037,18 +1085,30 @@ int btc_storage_get_num_ble_bond_devices(void)
bt_status_t btc_storage_get_gatt_cl_supp_feat(bt_bdaddr_t *remote_bd_addr, uint8_t *value, int len) bt_status_t btc_storage_get_gatt_cl_supp_feat(bt_bdaddr_t *remote_bd_addr, uint8_t *value, int len)
{ {
bdstr_t bdstr; bdstr_t bdstr;
bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr)); bool ret;
int ret = btc_config_get_bin(bdstr, BTC_BLE_STORAGE_GATT_CL_SUPP_FEAT_STR, value, (size_t *)&len); size_t length = len;
return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
btc_config_lock();
bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr_t));
ret = btc_config_get_bin(bdstr, BTC_BLE_STORAGE_GATT_CL_SUPP_FEAT_STR, value, &length);
btc_config_unlock();
if (!ret || length != (size_t)len) {
return BT_STATUS_FAIL;
}
return BT_STATUS_SUCCESS;
} }
bt_status_t btc_storage_set_gatt_cl_supp_feat(bt_bdaddr_t *remote_bd_addr, uint8_t *value, int len) bt_status_t btc_storage_set_gatt_cl_supp_feat(bt_bdaddr_t *remote_bd_addr, uint8_t *value, int len)
{ {
int ret; bool ret;
bdstr_t bdstr; bdstr_t bdstr;
btc_config_lock(); btc_config_lock();
bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr_t)); bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr_t));
ret = btc_config_set_bin(bdstr, BTC_BLE_STORAGE_GATT_CL_SUPP_FEAT_STR, value, (size_t)len); ret = btc_config_set_bin(bdstr, BTC_BLE_STORAGE_GATT_CL_SUPP_FEAT_STR, value, (size_t)len);
if (ret) {
_btc_storage_save();
}
btc_config_unlock(); btc_config_unlock();
if (ret == false) { if (ret == false) {
return BT_STATUS_FAIL; return BT_STATUS_FAIL;
@@ -1060,18 +1120,33 @@ bt_status_t btc_storage_set_gatt_cl_supp_feat(bt_bdaddr_t *remote_bd_addr, uint8
bt_status_t btc_storage_get_gatt_db_hash(bt_bdaddr_t *remote_bd_addr, uint8_t *value, int len) bt_status_t btc_storage_get_gatt_db_hash(bt_bdaddr_t *remote_bd_addr, uint8_t *value, int len)
{ {
bdstr_t bdstr; bdstr_t bdstr;
bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr)); bool ret;
int ret = btc_config_get_bin(bdstr, BTC_BLE_STORAGE_GATT_DB_HASH_STR, value, (size_t *)&len); size_t length = len;
return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
btc_config_lock();
bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr_t));
ret = btc_config_get_bin(bdstr, BTC_BLE_STORAGE_GATT_DB_HASH_STR, value, &length);
btc_config_unlock();
if (!ret || length != (size_t)len) {
return BT_STATUS_FAIL;
}
return BT_STATUS_SUCCESS;
} }
bt_status_t btc_storage_set_gatt_db_hash(bt_bdaddr_t *remote_bd_addr, uint8_t *value, int len) bt_status_t btc_storage_set_gatt_db_hash(bt_bdaddr_t *remote_bd_addr, uint8_t *value, int len)
{ {
int ret; bool ret;
bdstr_t bdstr; bdstr_t bdstr;
btc_config_lock();
bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr_t)); bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr_t));
ret = btc_config_set_bin(bdstr, BTC_BLE_STORAGE_GATT_DB_HASH_STR, value, (size_t)len); ret = btc_config_set_bin(bdstr, BTC_BLE_STORAGE_GATT_DB_HASH_STR, value, (size_t)len);
if (ret) {
_btc_storage_save();
}
btc_config_unlock();
if (ret == false) { if (ret == false) {
return BT_STATUS_FAIL; return BT_STATUS_FAIL;
} }
@@ -1084,9 +1159,11 @@ bt_status_t btc_storage_remove_gatt_cl_supp_feat(bt_bdaddr_t *remote_bd_addr)
bool ret = true; bool ret = true;
bdstr_t bdstr; bdstr_t bdstr;
btc_config_lock();
bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr)); bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
ret = btc_config_remove(bdstr, BTC_BLE_STORAGE_GATT_CL_SUPP_FEAT_STR); ret = btc_config_remove(bdstr, BTC_BLE_STORAGE_GATT_CL_SUPP_FEAT_STR);
btc_config_unlock();
if (ret == false) { if (ret == false) {
return BT_STATUS_FAIL; return BT_STATUS_FAIL;
} }
@@ -1099,9 +1176,11 @@ bt_status_t btc_storage_remove_gatt_db_hash(bt_bdaddr_t *remote_bd_addr)
bool ret = true; bool ret = true;
bdstr_t bdstr; bdstr_t bdstr;
btc_config_lock();
bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr)); bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
ret = btc_config_remove(bdstr, BTC_BLE_STORAGE_GATT_DB_HASH_STR); ret = btc_config_remove(bdstr, BTC_BLE_STORAGE_GATT_DB_HASH_STR);
btc_config_unlock();
if (ret == false) { if (ret == false) {
return BT_STATUS_FAIL; return BT_STATUS_FAIL;
} }
@@ -277,6 +277,7 @@ bool btc_config_set_bin(const char *section, const char *key, const uint8_t *val
config_set_string(config, section, key, str, false); config_set_string(config, section, key, str, false);
memset(str, 0, length * 2 + 1);
osi_free(str); osi_free(str);
return true; return true;
} }
@@ -269,7 +269,7 @@ static void btc_dm_ble_auth_cmpl_evt (tBTA_DM_AUTH_CMPL *p_auth_cmpl)
} }
#if BLE_SMP_BOND_NVS_FLASH #if BLE_SMP_BOND_NVS_FLASH
int addr_type; int addr_type = BLE_ADDR_PUBLIC;
if (btc_dm_cb.pairing_cb.ble.is_pid_key_rcvd) { if (btc_dm_cb.pairing_cb.ble.is_pid_key_rcvd) {
// delete unused section in NVS // delete unused section in NVS