diff --git a/components/bt/esp_ble_mesh/Kconfig.in b/components/bt/esp_ble_mesh/Kconfig.in index 27989394c52..95b428b3ef3 100644 --- a/components/bt/esp_ble_mesh/Kconfig.in +++ b/components/bt/esp_ble_mesh/Kconfig.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 diff --git a/components/bt/esp_ble_mesh/common/crypto_mbedtls.c b/components/bt/esp_ble_mesh/common/crypto_mbedtls.c index 1f340cff405..f444c85aff6 100644 --- a/components/bt/esp_ble_mesh/common/crypto_mbedtls.c +++ b/components/bt/esp_ble_mesh/common/crypto_mbedtls.c @@ -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: diff --git a/components/bt/esp_ble_mesh/common/crypto_psa.c b/components/bt/esp_ble_mesh/common/crypto_psa.c index 09e40e057d5..a44e49a7b4a 100644 --- a/components/bt/esp_ble_mesh/common/crypto_psa.c +++ b/components/bt/esp_ble_mesh/common/crypto_psa.c @@ -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); } diff --git a/components/bt/esp_ble_mesh/common/crypto_tc.c b/components/bt/esp_ble_mesh/common/crypto_tc.c index 66c5a7c1748..d3b019ba67d 100644 --- a/components/bt/esp_ble_mesh/common/crypto_tc.c +++ b/components/bt/esp_ble_mesh/common/crypto_tc.c @@ -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; } diff --git a/components/bt/esp_ble_mesh/core/bluedroid_host/adapter.c b/components/bt/esp_ble_mesh/core/bluedroid_host/adapter.c index f815bcd0209..80bb83316a3 100644 --- a/components/bt/esp_ble_mesh/core/bluedroid_host/adapter.c +++ b/components/bt/esp_ble_mesh/core/bluedroid_host/adapter.c @@ -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, diff --git a/components/bt/esp_ble_mesh/core/nimble_host/adapter.c b/components/bt/esp_ble_mesh/core/nimble_host/adapter.c index 9608762a417..6e1cda17b56 100644 --- a/components/bt/esp_ble_mesh/core/nimble_host/adapter.c +++ b/components/bt/esp_ble_mesh/core/nimble_host/adapter.c @@ -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); } diff --git a/components/bt/esp_ble_mesh/core/prov_common.c b/components/bt/esp_ble_mesh/core/prov_common.c index 58bbf7bce5c..e72d82fa815 100644 --- a/components/bt/esp_ble_mesh/core/prov_common.c +++ b/components/bt/esp_ble_mesh/core/prov_common.c @@ -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)); diff --git a/components/bt/esp_ble_mesh/v1.1/dfu/dfd_cli.c b/components/bt/esp_ble_mesh/v1.1/dfu/dfd_cli.c index 19fce3b9a8c..a29827b5e6e 100644 --- a/components/bt/esp_ble_mesh/v1.1/dfu/dfd_cli.c +++ b/components/bt/esp_ble_mesh/v1.1/dfu/dfd_cli.c @@ -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); diff --git a/components/bt/esp_ble_mesh/v1.1/mbt/blob_cli.c b/components/bt/esp_ble_mesh/v1.1/mbt/blob_cli.c index a5d36d8fa83..b1fc64492b9 100644 --- a/components/bt/esp_ble_mesh/v1.1/mbt/blob_cli.c +++ b/components/bt/esp_ble_mesh/v1.1/mbt/blob_cli.c @@ -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 =