mirror of
https://github.com/espressif/esp-idf.git
synced 2026-09-22 13:01:16 +03:00
Merge branch 'fix/ble_mesh_fixed_issues_v5.5' into 'release/v5.5'
Resolve reported BLE mesh stack issues (5.5) See merge request espressif/esp-idf!50406
This commit is contained in:
@@ -1875,6 +1875,15 @@ if BLE_MESH
|
||||
help
|
||||
Enable the Device Distribution Client model
|
||||
|
||||
if BLE_MESH_DFD_CLI
|
||||
config BLE_MESH_DFD_CLI_SRV_TARGETS_MAX
|
||||
int "Number of DFD SRVs can be accepted"
|
||||
default 3
|
||||
range 1 100
|
||||
help
|
||||
The maximum number of DFD SRVs that can be accepted.
|
||||
endif
|
||||
|
||||
config BLE_MESH_DFD_SRV
|
||||
bool "Support for Firmware Distribution Server model"
|
||||
depends on BLE_MESH_BLOB_SRV
|
||||
|
||||
@@ -347,8 +347,8 @@ void bt_mesh_set_private_key_raw(const uint8_t pri_key[32])
|
||||
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));
|
||||
// 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:
|
||||
|
||||
@@ -380,7 +380,7 @@ void bt_mesh_set_private_key_raw(const uint8_t pri_key[32])
|
||||
psa_status_t status;
|
||||
size_t key_len;
|
||||
|
||||
BT_DBG("Privkey:%s", bt_hex(pri_key, PRIV_KEY_SIZE));
|
||||
// BT_DBG("Privkey:%s", bt_hex(pri_key, PRIV_KEY_SIZE));
|
||||
|
||||
/* Destroy any existing key */
|
||||
if (dh_pair.priv_key_id != PSA_KEY_ID_NULL) {
|
||||
@@ -414,7 +414,7 @@ void bt_mesh_set_private_key_raw(const uint8_t pri_key[32])
|
||||
return;
|
||||
}
|
||||
|
||||
BT_DBG("Pubkey:%s", bt_hex(&dh_pair.public_key[1], PUB_KEY_SIZE));
|
||||
// BT_DBG("Pubkey:%s", bt_hex(&dh_pair.public_key[1], PUB_KEY_SIZE));
|
||||
dh_pair.is_ready = true;
|
||||
psa_reset_key_attributes(&attributes);
|
||||
}
|
||||
|
||||
@@ -236,8 +236,8 @@ void bt_mesh_set_private_key_raw(const uint8_t pri_key[32])
|
||||
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));
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -640,7 +640,7 @@ static void bt_mesh_scan_result_callback(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARC
|
||||
if (bt_mesh_scan_dev_found_cb) {
|
||||
bt_mesh_scan_dev_found_cb(&adv_rpt);
|
||||
|
||||
if (p_data->inq_res.scan_rsp_len) {
|
||||
if (p_data->inq_res.scan_rsp_len && bt_mesh_scan_dev_found_cb) {
|
||||
adv_rpt.adv_type = BLE_MESH_ADV_SCAN_RSP;
|
||||
net_buf_simple_init_with_data(&adv_rpt.adv_data, p_data->inq_res.p_eir + p_data->inq_res.adv_data_len, p_data->inq_res.scan_rsp_len);
|
||||
bt_mesh_scan_dev_found_cb(&adv_rpt);
|
||||
@@ -1165,7 +1165,7 @@ static void bt_mesh_bta_gatts_cb(tBTA_GATTS_EVT event, tBTA_GATTS *p_data)
|
||||
uint8_t index = BLE_MESH_GATT_GET_CONN_ID(p_data->req_data.conn_id);
|
||||
tBTA_GATTS_RSP rsp = {0};
|
||||
uint8_t buf[100] = {0};
|
||||
uint16_t len = 0;
|
||||
ssize_t len = 0;
|
||||
|
||||
BT_DBG("gatts read, handle %d", p_data->req_data.p_data->read_req.handle);
|
||||
|
||||
@@ -1187,7 +1187,7 @@ static void bt_mesh_bta_gatts_cb(tBTA_GATTS_EVT event, tBTA_GATTS *p_data)
|
||||
case BTA_GATTS_WRITE_EVT: {
|
||||
struct bt_mesh_gatt_attr *attr = bt_mesh_gatts_find_attr_by_handle(p_data->req_data.p_data->write_req.handle);
|
||||
uint8_t index = BLE_MESH_GATT_GET_CONN_ID(p_data->req_data.conn_id);
|
||||
uint16_t len = 0;
|
||||
ssize_t len = 0;
|
||||
|
||||
BT_DBG("gatts write, handle %d, len %d, data %s", p_data->req_data.p_data->write_req.handle,
|
||||
p_data->req_data.p_data->write_req.len,
|
||||
|
||||
@@ -538,6 +538,10 @@ int disc_cb(struct ble_gap_event *event, void *arg)
|
||||
switch (desc->data_status) {
|
||||
case BLE_GAP_EXT_ADV_DATA_STATUS_COMPLETE:
|
||||
if (adv_report_cache.adv_data_len) {
|
||||
if (adv_report_cache.adv_data_len + desc->length_data > BLE_MESH_GAP_ADV_MAX_LEN) {
|
||||
memset(&adv_report_cache, 0, sizeof(adv_report_cache));
|
||||
return false;
|
||||
}
|
||||
memcpy(adv_report_cache.adv_data + adv_report_cache.adv_data_len,
|
||||
desc->data, desc->length_data);
|
||||
adv_report_cache.adv_data_len += desc->length_data;
|
||||
@@ -952,10 +956,10 @@ static int gap_event_cb(struct ble_gap_event *event, void *arg)
|
||||
if (index != -ENODEV) {
|
||||
bt_mesh_gatts_conn[index].handle = BLE_MESH_GATT_GET_CONN_ID(event->disconnect.conn.conn_handle);
|
||||
(bt_mesh_gatts_conn_cb->disconnected)(&bt_mesh_gatts_conn[index], event->disconnect.reason);
|
||||
bt_mesh_gatts_conn[index].handle = BT_MESH_GATTS_CONN_UNUSED;
|
||||
} else {
|
||||
BT_ERR("No device");
|
||||
}
|
||||
bt_mesh_gatts_conn[index].handle = BT_MESH_GATTS_CONN_UNUSED;
|
||||
memset(bt_mesh_gatts_addr, 0x0, BLE_MESH_ADDR_LEN);
|
||||
}
|
||||
|
||||
|
||||
@@ -188,6 +188,8 @@ bool bt_mesh_gen_prov_start(struct bt_mesh_prov_link *link,
|
||||
struct net_buf_simple *buf,
|
||||
struct prov_rx *rx, bool *close)
|
||||
{
|
||||
uint8_t last_seg = START_LAST_SEG(rx->gpc);
|
||||
|
||||
if (link->rx.seg) {
|
||||
BT_INFO("Get Start while there are unreceived segments");
|
||||
return false;
|
||||
@@ -199,12 +201,23 @@ bool bt_mesh_gen_prov_start(struct bt_mesh_prov_link *link,
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Reset the reassembly buffer so every transaction starts from the
|
||||
* buffer origin. prov_msg_recv() pulls the PDU type byte (advancing
|
||||
* buf->data by one) and nothing restores it between transactions, so
|
||||
* without this reset buf->data would drift forward by one byte per
|
||||
* received PDU: the segment-0 memcpy below would then write past the
|
||||
* end of the statically allocated rx buffer (PROV_RX_BUF_SIZE), and
|
||||
* the XACT_SEG_DATA() offsets used for continuation segments would
|
||||
* be skewed by the accumulated drift.
|
||||
*/
|
||||
net_buf_simple_reset(link->rx.buf);
|
||||
|
||||
link->rx.buf->len = net_buf_simple_pull_be16(buf);
|
||||
link->rx.id = rx->xact_id;
|
||||
link->rx.fcs = net_buf_simple_pull_u8(buf);
|
||||
|
||||
BT_DBG("LinkId:%08x,len %u last_seg %u total_len %u fcs 0x%02x", link->link_id, buf->len,
|
||||
START_LAST_SEG(rx->gpc), link->rx.buf->len, link->rx.fcs);
|
||||
last_seg, link->rx.buf->len, link->rx.fcs);
|
||||
|
||||
/* At least one-octet pdu type is needed */
|
||||
if (link->rx.buf->len < 1) {
|
||||
@@ -215,8 +228,8 @@ bool bt_mesh_gen_prov_start(struct bt_mesh_prov_link *link,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (START_LAST_SEG(rx->gpc) > START_LAST_SEG_MAX) {
|
||||
BT_ERR("Invalid SegN 0x%02x", START_LAST_SEG(rx->gpc));
|
||||
if (last_seg > START_LAST_SEG_MAX) {
|
||||
BT_ERR("Invalid SegN 0x%02x", last_seg);
|
||||
if (close) {
|
||||
*close = true;
|
||||
}
|
||||
@@ -232,16 +245,19 @@ bool bt_mesh_gen_prov_start(struct bt_mesh_prov_link *link,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (START_LAST_SEG(rx->gpc) > 0) {
|
||||
/* For multi-segment PDUs, validate that total length is consistent
|
||||
* with the claimed segment count to prevent underflow in
|
||||
* bt_mesh_gen_prov_cont() when computing expect_len.
|
||||
* Minimum length = first segment (20) + (last_seg - 1) * full continuation (23) + 1
|
||||
/* Validate that the declared total length and the actual start-segment
|
||||
* payload length match the claimed segment count before copying segment 0.
|
||||
* This keeps malformed extended advertising reports from writing past the
|
||||
* fixed provisioning rx buffer.
|
||||
*/
|
||||
if (last_seg > 0) {
|
||||
/* Minimum length = first segment (20) + (last_seg - 1) *
|
||||
* full continuation (23) + one byte in the last segment.
|
||||
*/
|
||||
uint16_t min_len = 20 + 23 * (START_LAST_SEG(rx->gpc) - 1) + 1;
|
||||
uint16_t min_len = START_PAYLOAD_MAX + CONT_PAYLOAD_MAX * (last_seg - 1) + 1;
|
||||
if (link->rx.buf->len < min_len) {
|
||||
BT_ERR("Total length %u too small for %u segments (min %u)",
|
||||
link->rx.buf->len, START_LAST_SEG(rx->gpc) + 1, min_len);
|
||||
link->rx.buf->len, last_seg + 1, min_len);
|
||||
if (close) {
|
||||
*close = true;
|
||||
}
|
||||
@@ -249,8 +265,30 @@ bool bt_mesh_gen_prov_start(struct bt_mesh_prov_link *link,
|
||||
}
|
||||
}
|
||||
|
||||
link->rx.seg = (1 << (START_LAST_SEG(rx->gpc) + 1)) - 1;
|
||||
link->rx.last_seg = START_LAST_SEG(rx->gpc);
|
||||
{
|
||||
uint16_t max_len = START_PAYLOAD_MAX + CONT_PAYLOAD_MAX * last_seg;
|
||||
uint16_t seg_0_len = last_seg ? START_PAYLOAD_MAX : link->rx.buf->len;
|
||||
|
||||
if (link->rx.buf->len > max_len) {
|
||||
BT_ERR("Total length %u too large for %u segments (max %u)",
|
||||
link->rx.buf->len, last_seg + 1, max_len);
|
||||
if (close) {
|
||||
*close = true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (buf->len != seg_0_len) {
|
||||
BT_ERR("Invalid start segment len %u != %u", buf->len, seg_0_len);
|
||||
if (close) {
|
||||
*close = true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
link->rx.seg = (1 << (last_seg + 1)) - 1;
|
||||
link->rx.last_seg = last_seg;
|
||||
memcpy(link->rx.buf->data, buf->data, buf->len);
|
||||
XACT_SEG_RECV(link, 0);
|
||||
BT_DBG("Seg: %04x, lastSeg: %04x, Data: %s", link->rx.seg, link->rx.last_seg, bt_hex(buf->data, buf->len));
|
||||
|
||||
@@ -86,7 +86,6 @@ static void dfd_client_recv_status(struct bt_mesh_model *model,
|
||||
} else {
|
||||
switch (ctx->recv_op) {
|
||||
case BLE_MESH_DFD_OP_RECEIVERS_STATUS:
|
||||
case BLE_MESH_DFD_OP_CAPABILITIES_GET:
|
||||
case BLE_MESH_DFD_OP_RECEIVERS_LIST:
|
||||
case BLE_MESH_DFD_OP_CAPABILITIES_STATUS:
|
||||
case BLE_MESH_DFD_OP_STATUS:
|
||||
@@ -122,7 +121,7 @@ static void handle_receiver_status(struct bt_mesh_model *model,
|
||||
}
|
||||
|
||||
if (status.receiver_status.status != BLE_MESH_DFD_SUCCESS) {
|
||||
BT_ERR("StusErr:%d", status);
|
||||
BT_ERR("StusErr:%d", status.receiver_status.status);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -142,8 +141,30 @@ static void handle_receiver_list(struct bt_mesh_model *model,
|
||||
|
||||
dfd_status_t status = {0};
|
||||
status.receiver_list.entries_cnt = net_buf_simple_pull_le16(buf);
|
||||
|
||||
if (status.receiver_list.entries_cnt > CONFIG_BLE_MESH_DFD_CLI_SRV_TARGETS_MAX) {
|
||||
BT_ERR("InvalidDfdSrvEntries:%d",status.receiver_list.entries_cnt);
|
||||
return;
|
||||
}
|
||||
|
||||
status.receiver_list.first_index = net_buf_simple_pull_le16(buf);
|
||||
status.receiver_list.entries = bt_mesh_calloc(status.receiver_list.entries_cnt * sizeof(target_node_entry_t));
|
||||
|
||||
/* Each entry is 4 bytes (packed target info) + 1 byte (fwidx) = 5 bytes. */
|
||||
if (buf->len < (uint32_t)status.receiver_list.entries_cnt * 5u) {
|
||||
BT_ERR("InvRcvListLen:cnt=%d,buf=%d", status.receiver_list.entries_cnt, buf->len);
|
||||
return;
|
||||
}
|
||||
|
||||
if (status.receiver_list.entries_cnt == 0) {
|
||||
status.receiver_list.entries = NULL;
|
||||
} else {
|
||||
status.receiver_list.entries = bt_mesh_calloc(status.receiver_list.entries_cnt * sizeof(target_node_entry_t));
|
||||
if (status.receiver_list.entries == NULL) {
|
||||
BT_ERR("MemAllocFailedForSz:%zu",status.receiver_list.entries_cnt * sizeof(target_node_entry_t));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < status.receiver_list.entries_cnt; i++) {
|
||||
target_info = net_buf_simple_pull_le32(buf);
|
||||
status.receiver_list.entries[i].addr = TARGET_ADDR(target_info);
|
||||
@@ -170,7 +191,7 @@ static void handle_capabilities(struct bt_mesh_model *model,
|
||||
status.dist_caps.max_fw_sz = net_buf_simple_pull_le32(buf);
|
||||
status.dist_caps.max_upload_space = net_buf_simple_pull_le32(buf);
|
||||
status.dist_caps.remaining_upload_space = net_buf_simple_pull_le32(buf);
|
||||
status.dist_caps.oob_retrieval_supported = net_buf_simple_pull_le32(buf);
|
||||
status.dist_caps.oob_retrieval_supported = net_buf_simple_pull_u8(buf);
|
||||
if (buf->len) {
|
||||
status.dist_caps.supported_url_scheme_names = &url_scheme_names;
|
||||
net_buf_simple_init_with_data(status.dist_caps.supported_url_scheme_names, buf->data, buf->len);
|
||||
@@ -189,7 +210,13 @@ static void handle_dfd_status(struct bt_mesh_model *model,
|
||||
|
||||
status.dist_status.status = net_buf_simple_pull_u8(buf);
|
||||
status.dist_status.dist_phase = net_buf_simple_pull_u8(buf);
|
||||
if (buf->len != 0 && buf->len != 10) {
|
||||
if (buf->len == 0) {
|
||||
/* Only Status and Distribution Phase are present (e.g. IDLE phase);
|
||||
* the optional fields are not part of the message. */
|
||||
dfd_client_recv_status(model, ctx, &status, sizeof(status.dist_status));
|
||||
return;
|
||||
}
|
||||
if (buf->len != 10) {
|
||||
BT_ERR("Invalid data");
|
||||
return;
|
||||
}
|
||||
@@ -199,13 +226,14 @@ static void handle_dfd_status(struct bt_mesh_model *model,
|
||||
status.dist_status.timeout_base = net_buf_simple_pull_le16(buf);
|
||||
|
||||
trans_mode_policy = net_buf_simple_pull_u8(buf);
|
||||
if ((trans_mode_policy & ~(BIT6 - 1)) != 0) {
|
||||
if ((trans_mode_policy & 0xF8) != 0) {
|
||||
BT_ERR("RFU should be zero");
|
||||
return;
|
||||
}
|
||||
status.dist_status.trans_mode = trans_mode_policy >> 6;
|
||||
status.dist_status.update_policy = (trans_mode_policy >> 5) & 0x01;
|
||||
status.dist_status.RFU = trans_mode_policy & 0x1f;
|
||||
/* trans_mode: bits 0-1, update_policy: bit 2, RFU: bits 3-7 */
|
||||
status.dist_status.trans_mode = trans_mode_policy & 0x03;
|
||||
status.dist_status.update_policy = (trans_mode_policy >> 2) & 0x01;
|
||||
status.dist_status.RFU = (trans_mode_policy >> 3) & 0x1f;
|
||||
status.dist_status.fw_idx = net_buf_simple_pull_le16(buf);
|
||||
dfd_client_recv_status(model, ctx, &status, sizeof(status.dist_status));
|
||||
return;
|
||||
@@ -228,7 +256,7 @@ static void handle_upload_status(struct bt_mesh_model *model,
|
||||
}
|
||||
|
||||
progress_type = net_buf_simple_pull_u8(buf);
|
||||
status.upload_status.upload_progress = progress_type>>1;
|
||||
status.upload_status.upload_progress = progress_type & 0x7F;
|
||||
|
||||
if (status.upload_status.upload_progress >= UPLOAD_PROGRESS_UNSET) {
|
||||
BT_ERR("Invalid upload progress");
|
||||
@@ -240,7 +268,7 @@ static void handle_upload_status(struct bt_mesh_model *model,
|
||||
return;
|
||||
}
|
||||
|
||||
status.upload_status.upload_type = progress_type & 0x01;
|
||||
status.upload_status.upload_type = (progress_type >> 7) & 0x01;
|
||||
if (status.upload_status.upload_type == UPLOAD_IN_BAND) {
|
||||
status.upload_status.fwid = &buf_cache;
|
||||
net_buf_simple_init_with_data(status.upload_status.fwid, buf->data, buf->len);
|
||||
@@ -288,7 +316,7 @@ const struct bt_mesh_model_op _bt_mesh_dfd_cli_op[] = {
|
||||
|
||||
int bt_mesh_dfd_cli_receivers_add(bt_mesh_client_common_param_t *param, dfd_cli_receiver_entry_t *receivers, uint16_t receivers_cnt)
|
||||
{
|
||||
uint16_t msg_length = 2;
|
||||
uint32_t msg_length = 2;
|
||||
struct net_buf_simple *msg = NULL;
|
||||
dfd_cli_receiver_entry_t *entry = NULL;
|
||||
int err = 0;
|
||||
@@ -298,8 +326,13 @@ int bt_mesh_dfd_cli_receivers_add(bt_mesh_client_common_param_t *param, dfd_cli_
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (receivers == NULL && receivers_cnt) {
|
||||
BT_ERR("Invalid receivers");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
BT_INFO("AddedValidCnt:%d", receivers_cnt);
|
||||
msg_length += (receivers_cnt * 3);
|
||||
msg_length += (uint32_t)receivers_cnt * 3;
|
||||
|
||||
/* needs to confirm long or short mic */
|
||||
if (msg_length > BLE_MESH_MAX_PDU_LEN_WITH_SMIC) {
|
||||
@@ -392,7 +425,7 @@ int bt_mesh_dfd_cli_distribution_start(bt_mesh_client_common_param_t *param,
|
||||
net_buf_simple_add_le16(&msg, start->app_idx);
|
||||
net_buf_simple_add_u8(&msg, start->ttl);
|
||||
net_buf_simple_add_le16(&msg, start->timeout_base);
|
||||
net_buf_simple_add_u8(&msg, ((start->trans_mode) << 6) | ((start->update_policy) << 5));
|
||||
net_buf_simple_add_u8(&msg, ((start->trans_mode) & 0x03) | (((start->update_policy) & 0x01) << 2));
|
||||
net_buf_simple_add_le16(&msg, start->fw_idx);
|
||||
|
||||
if (start->is_va) {
|
||||
@@ -503,17 +536,17 @@ int bt_mesh_dfd_cli_distribution_upload_oob_start(bt_mesh_client_common_param_t
|
||||
|
||||
if (!param || !start) {
|
||||
BT_ERR("Invalid param");
|
||||
return -1;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!start->url) {
|
||||
BT_ERR("Null url info");
|
||||
return -1;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!start->fwid) {
|
||||
BT_ERR("Invalid firmware id");
|
||||
return -1;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
msg_length += (1 + start->url->len + start->fwid->len);
|
||||
|
||||
@@ -1398,6 +1398,10 @@ static int handle_block_status(const struct bt_mesh_model *mod, struct bt_mesh_m
|
||||
size_t len;
|
||||
int idx;
|
||||
|
||||
if (!cli->xfer) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
target = target_get(cli, ctx->addr);
|
||||
if (!target) {
|
||||
return -ENOENT;
|
||||
@@ -1408,8 +1412,8 @@ static int handle_block_status(const struct bt_mesh_model *mod, struct bt_mesh_m
|
||||
status.missing = status_and_format >> 6;
|
||||
status.block.number = net_buf_simple_pull_le16(buf);
|
||||
chunk_size = net_buf_simple_pull_le16(buf);
|
||||
if (chunk_size == 0) {
|
||||
BT_ERR("Invalid chunk_size: 0");
|
||||
if (chunk_size == 0 || chunk_size != cli->xfer->chunk_size) {
|
||||
BT_ERR("Invalid chunk_size: %d,%d", chunk_size, cli->xfer->chunk_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
status.block.chunk_count =
|
||||
|
||||
Reference in New Issue
Block a user