From b4650fcc16963bce40fca330f62643d39b48947c Mon Sep 17 00:00:00 2001 From: wangjialiang Date: Thu, 4 Mar 2021 16:06:24 +0800 Subject: [PATCH 1/8] ble_mesh: stack: Fix invalid provisioning pdu type check For case MESH/NODE/PROV/BI-15-C --- components/bt/esp_ble_mesh/mesh_core/prov.c | 31 +++++++++++++-------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/components/bt/esp_ble_mesh/mesh_core/prov.c b/components/bt/esp_ble_mesh/mesh_core/prov.c index 4e9813f7c6..cb3ddae2e2 100644 --- a/components/bt/esp_ble_mesh/mesh_core/prov.c +++ b/components/bt/esp_ble_mesh/mesh_core/prov.c @@ -1450,18 +1450,22 @@ static void prov_msg_recv(void) return; } - if (type != PROV_FAILED && type != link.expect) { - BT_WARN("Unexpected msg 0x%02x != 0x%02x", type, link.expect); - prov_send_fail_msg(PROV_ERR_UNEXP_PDU); - return; - } - + /* For case MESH/NODE/PROV/BI-15-C, when the node receive a Provisioning PDU + * with the Type field set to the lowest unsupported or RFU value, it sends a + * Provisioning Failed PDU with the Error Code field set to Invalid PDU(0x01). + */ if (type >= ARRAY_SIZE(prov_handlers)) { BT_ERR("Unknown provisioning PDU type 0x%02x", type); prov_send_fail_msg(PROV_ERR_NVAL_PDU); return; } + if (type != PROV_FAILED && type != link.expect) { + BT_WARN("Unexpected msg 0x%02x != 0x%02x", type, link.expect); + prov_send_fail_msg(PROV_ERR_UNEXP_PDU); + return; + } + if (1 + prov_handlers[type].len != link.rx.buf->len) { BT_ERR("Invalid length %u for type 0x%02x", link.rx.buf->len, type); @@ -1666,15 +1670,20 @@ int bt_mesh_pb_gatt_recv(struct bt_mesh_conn *conn, struct net_buf_simple *buf) return -EINVAL; } + /* For case MESH/NODE/PROV/BI-15-C, when the node receive a Provisioning PDU + * with the Type field set to the lowest unsupported or RFU value, it sends a + * Provisioning Failed PDU with the Error Code field set to Invalid PDU(0x01). + */ type = net_buf_simple_pull_u8(buf); - if (type != PROV_FAILED && type != link.expect) { - BT_WARN("Unexpected msg 0x%02x != 0x%02x", type, link.expect); - prov_send_fail_msg(PROV_ERR_UNEXP_PDU); + if (type >= ARRAY_SIZE(prov_handlers)) { + BT_ERR("Unknown provisioning PDU type 0x%02x", type); + prov_send_fail_msg(PROV_ERR_NVAL_PDU); return -EINVAL; } - if (type >= ARRAY_SIZE(prov_handlers)) { - BT_ERR("Unknown provisioning PDU type 0x%02x", type); + if (type != PROV_FAILED && type != link.expect) { + BT_WARN("Unexpected msg 0x%02x != 0x%02x", type, link.expect); + prov_send_fail_msg(PROV_ERR_UNEXP_PDU); return -EINVAL; } From 0a33ec0d1c112458e7a198bb8f6754c02899bcdc Mon Sep 17 00:00:00 2001 From: wangjialiang Date: Thu, 4 Mar 2021 15:27:21 +0800 Subject: [PATCH 2/8] ble_mesh: stack: Fix PB-GATT not check invalid link flag For case MESH/NODE/PROV/BI-03-C --- components/bt/esp_ble_mesh/mesh_core/prov.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/components/bt/esp_ble_mesh/mesh_core/prov.c b/components/bt/esp_ble_mesh/mesh_core/prov.c index cb3ddae2e2..f9de1e271c 100644 --- a/components/bt/esp_ble_mesh/mesh_core/prov.c +++ b/components/bt/esp_ble_mesh/mesh_core/prov.c @@ -1670,6 +1670,16 @@ int bt_mesh_pb_gatt_recv(struct bt_mesh_conn *conn, struct net_buf_simple *buf) return -EINVAL; } + /* For case MESH/NODE/PROV/BI-03-C, if the link is closed, when the node receive + * a Provisioning PDU , it will send a Provisioning Failed PDU with the Error Code + * field set to Unexpected PDU(0x03). + */ + if (bt_mesh_atomic_test_bit(link.flags, LINK_INVALID)) { + BT_WARN("Unexpected msg 0x%02x on invalid link", type); + prov_send_fail_msg(PROV_ERR_UNEXP_PDU); + return -EINVAL; + } + /* For case MESH/NODE/PROV/BI-15-C, when the node receive a Provisioning PDU * with the Type field set to the lowest unsupported or RFU value, it sends a * Provisioning Failed PDU with the Error Code field set to Invalid PDU(0x01). From 7a8023e54c54b3eceef51578a361a1ce057f5471 Mon Sep 17 00:00:00 2001 From: wangjialiang Date: Sat, 20 Mar 2021 13:49:36 +0800 Subject: [PATCH 3/8] ble_mesh: stack: Fix ignore connectable PB-ADV PDU containing a Link Open message. For case MESH/NODE/PBADV/BI-04-C --- components/bt/esp_ble_mesh/mesh_core/scan.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/components/bt/esp_ble_mesh/mesh_core/scan.c b/components/bt/esp_ble_mesh/mesh_core/scan.c index 753f19bb9c..b840eff9d0 100644 --- a/components/bt/esp_ble_mesh/mesh_core/scan.c +++ b/components/bt/esp_ble_mesh/mesh_core/scan.c @@ -233,14 +233,11 @@ static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr, buf->len = len - 1; -#if 0 - /* TODO: Check with BLE Mesh BQB test cases */ if ((type == BLE_MESH_DATA_MESH_PROV || type == BLE_MESH_DATA_MESH_MESSAGE || type == BLE_MESH_DATA_MESH_BEACON) && (adv_type != BLE_MESH_ADV_NONCONN_IND)) { BT_DBG("Ignore mesh packet (type 0x%02x) with adv_type 0x%02x", type, adv_type); return; } -#endif switch (type) { case BLE_MESH_DATA_MESH_MESSAGE: From 7a8ebdc40922ddf567a17df85704e475b31b9603 Mon Sep 17 00:00:00 2001 From: wangjialiang Date: Thu, 21 Jul 2022 20:25:19 +0800 Subject: [PATCH 4/8] ble_mesh: stack: The value of expect_ack_for will be rewrited after send_pub_key(). For case MESH/PVNR/PROV/BV-04-C --- components/bt/esp_ble_mesh/mesh_core/provisioner_prov.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/components/bt/esp_ble_mesh/mesh_core/provisioner_prov.c b/components/bt/esp_ble_mesh/mesh_core/provisioner_prov.c index 4945e1faee..60ac6c2f03 100644 --- a/components/bt/esp_ble_mesh/mesh_core/provisioner_prov.c +++ b/components/bt/esp_ble_mesh/mesh_core/provisioner_prov.c @@ -2943,6 +2943,12 @@ static void gen_prov_ack(const uint8_t idx, struct prov_rx *rx, struct net_buf_s case PROV_START: pub_key_oob = link[idx].conf_inputs[13]; send_pub_key(idx, pub_key_oob); + /* For case MESH/PVNR/PROV/BV-04-C, if using OOB public key, + * the value of expect_ack_for shall be PROV_PUB_KEY. + */ + if (pub_key_oob) { + return; + } break; case PROV_PUB_KEY: prov_gen_dh_key(idx); From e260a04f222bb42d0af4cd29bd6fd94df20ae24b Mon Sep 17 00:00:00 2001 From: wangjialiang Date: Wed, 7 Apr 2021 17:10:54 +0800 Subject: [PATCH 5/8] ble_mesh: stack: The Heartbeat Publication Period Log value can set to 0x11, range: [0, 0x11] --- components/bt/esp_ble_mesh/mesh_core/cfg_srv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/bt/esp_ble_mesh/mesh_core/cfg_srv.c b/components/bt/esp_ble_mesh/mesh_core/cfg_srv.c index 12f910986d..c6606efba8 100644 --- a/components/bt/esp_ble_mesh/mesh_core/cfg_srv.c +++ b/components/bt/esp_ble_mesh/mesh_core/cfg_srv.c @@ -3049,7 +3049,7 @@ static void heartbeat_pub_set(struct bt_mesh_model *model, goto failed; } - if (param->period_log > 0x10) { + if (param->period_log > 0x11) { status = STATUS_CANNOT_SET; goto failed; } From 52af572bd5fa67f1d6eb2a7fd6c19f1e0ac5ca3b Mon Sep 17 00:00:00 2001 From: wangjialiang Date: Wed, 7 Apr 2021 17:09:58 +0800 Subject: [PATCH 6/8] ble_mesh: stack: the count_log field should be set to 0 when HBS is sent. For MESH/NODE/CFG/HBS/BV-02-C --- components/bt/esp_ble_mesh/mesh_core/cfg_srv.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/components/bt/esp_ble_mesh/mesh_core/cfg_srv.c b/components/bt/esp_ble_mesh/mesh_core/cfg_srv.c index c6606efba8..c49cea5309 100644 --- a/components/bt/esp_ble_mesh/mesh_core/cfg_srv.c +++ b/components/bt/esp_ble_mesh/mesh_core/cfg_srv.c @@ -3202,19 +3202,18 @@ static void heartbeat_sub_set(struct bt_mesh_model *model, } if (sub_src == BLE_MESH_ADDR_UNASSIGNED || - sub_dst == BLE_MESH_ADDR_UNASSIGNED || - sub_period == 0x00) { + sub_dst == BLE_MESH_ADDR_UNASSIGNED || + sub_period == 0x00) { /* Only an explicit address change to unassigned should * trigger clearing of the values according to * MESH/NODE/CFG/HBS/BV-02-C. */ if (sub_src == BLE_MESH_ADDR_UNASSIGNED || - sub_dst == BLE_MESH_ADDR_UNASSIGNED) { + sub_dst == BLE_MESH_ADDR_UNASSIGNED) { cfg->hb_sub.src = BLE_MESH_ADDR_UNASSIGNED; cfg->hb_sub.dst = BLE_MESH_ADDR_UNASSIGNED; cfg->hb_sub.min_hops = BLE_MESH_TTL_MAX; cfg->hb_sub.max_hops = 0U; - cfg->hb_sub.count = 0U; } period_ms = 0; @@ -3240,6 +3239,11 @@ static void heartbeat_sub_set(struct bt_mesh_model *model, hb_sub_send_status(model, ctx, STATUS_SUCCESS); + /* For case MESH/NODE/CFG/HBS/BV-02-C, set count_log to 0 + * when Heartbeat Subscription Status message is sent. + */ + cfg->hb_sub.count = 0U; + /* MESH/NODE/CFG/HBS/BV-01-C expects the MinHops to be 0x7f after * disabling subscription, but 0x00 for subsequent Get requests. */ From b42b8b007af1d74ca1fff68feefe8d3e5503c4ad Mon Sep 17 00:00:00 2001 From: wangjialiang Date: Wed, 3 Aug 2022 21:16:01 +0800 Subject: [PATCH 7/8] ble_mesh: stack: Add a check if the appkey is bound to the model. For case MESH/NODE/CFG/MP/BI-03-C --- .../bt/esp_ble_mesh/mesh_core/cfg_srv.c | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/components/bt/esp_ble_mesh/mesh_core/cfg_srv.c b/components/bt/esp_ble_mesh/mesh_core/cfg_srv.c index c49cea5309..7a0c52a8e7 100644 --- a/components/bt/esp_ble_mesh/mesh_core/cfg_srv.c +++ b/components/bt/esp_ble_mesh/mesh_core/cfg_srv.c @@ -197,6 +197,21 @@ static bool app_key_is_valid(uint16_t app_idx) return false; } +static bool mod_pub_app_key_bound(struct bt_mesh_model *model, + uint16_t app_idx) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(model->keys); i++) { + if (model->keys[i] == app_idx) { + return true; + } + } + + BT_ERR("Appkey(0x%02x) not bound to this model.", app_idx); + return false; +} + static uint8_t _mod_pub_set(struct bt_mesh_model *model, uint16_t pub_addr, uint16_t app_idx, uint8_t cred_flag, uint8_t ttl, uint8_t period, uint8_t retransmit, bool store) @@ -237,7 +252,11 @@ static uint8_t _mod_pub_set(struct bt_mesh_model *model, uint16_t pub_addr, return STATUS_SUCCESS; } - if (!bt_mesh_app_key_find(app_idx)) { + /* For case MESH/NODE/CFG/MP/BI-03-C, need to check if appkey + * is bound to model identified by the ModelIdentifier. + */ + if (!bt_mesh_app_key_find(app_idx) || + !mod_pub_app_key_bound(model, app_idx)) { return STATUS_INVALID_APPKEY; } From e15b3b8b9d4d8e9f0ad699ed6f7f13112f23da0e Mon Sep 17 00:00:00 2001 From: wangjialiang Date: Thu, 18 Mar 2021 17:27:19 +0800 Subject: [PATCH 8/8] ble_mesh: stack: Fix kr from non-primary subnet shouldn't ignore For case MESH/NODE/KR/BV-02-C --- components/bt/esp_ble_mesh/mesh_core/beacon.c | 24 ++++++++++++++++--- .../bt/esp_ble_mesh/mesh_core/cfg_srv.c | 2 +- components/bt/esp_ble_mesh/mesh_core/prov.c | 2 +- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/components/bt/esp_ble_mesh/mesh_core/beacon.c b/components/bt/esp_ble_mesh/mesh_core/beacon.c index 31d09aa05a..981f88edcd 100644 --- a/components/bt/esp_ble_mesh/mesh_core/beacon.c +++ b/components/bt/esp_ble_mesh/mesh_core/beacon.c @@ -374,9 +374,19 @@ static void secure_beacon_recv(struct net_buf_simple *buf) cache_add(data, sub); - /* If we have NetKey0 accept initiation only from it */ + /* Spec v1.0.1, Section 3.8.4: + * If a node on a primary subnet receives an update on + * the primary subnet, it shall propagate the IV update + * to all other subnets. If a node on a primary subnet + * receives an IV update on any other subnet, the update + * shall be ignored. + * If a node on a primary subnet receives an key update + * on any other subnet, the update shall not be ignored. + */ if (bt_mesh_primary_subnet_exist() && - sub->net_idx != BLE_MESH_KEY_PRIMARY) { + sub->net_idx != BLE_MESH_KEY_PRIMARY && + BLE_MESH_IV_UPDATE(flags) && + !BLE_MESH_KEY_REFRESH(flags)) { BT_WARN("Ignoring secure beacon on non-primary subnet"); goto update_stats; } @@ -390,7 +400,15 @@ static void secure_beacon_recv(struct net_buf_simple *buf) bt_mesh_beacon_ivu_initiator(false); } - iv_change = bt_mesh_net_iv_update(iv_index, BLE_MESH_IV_UPDATE(flags)); + /* If a node on a primary subnet receives an IV update on any other subnet, + * the IV update shall be ignored. And if a node on a non-primary subnet + * receives an IV update on primary subnet, the IV update shall be ignored, + * because it doesn't have a primary network key. + */ + if ((bt_mesh_primary_subnet_exist() && sub->net_idx == BLE_MESH_KEY_PRIMARY) || + (!bt_mesh_primary_subnet_exist() && sub->net_idx != BLE_MESH_KEY_PRIMARY)) { + iv_change = bt_mesh_net_iv_update(iv_index, BLE_MESH_IV_UPDATE(flags)); + } kr_change = bt_mesh_kr_update(sub, BLE_MESH_KEY_REFRESH(flags), new_key); if (kr_change) { diff --git a/components/bt/esp_ble_mesh/mesh_core/cfg_srv.c b/components/bt/esp_ble_mesh/mesh_core/cfg_srv.c index 7a0c52a8e7..2818936d91 100644 --- a/components/bt/esp_ble_mesh/mesh_core/cfg_srv.c +++ b/components/bt/esp_ble_mesh/mesh_core/cfg_srv.c @@ -252,7 +252,7 @@ static uint8_t _mod_pub_set(struct bt_mesh_model *model, uint16_t pub_addr, return STATUS_SUCCESS; } - /* For case MESH/NODE/CFG/MP/BI-03-C, need to check if appkey + /* For case MESH/NODE/CFG/MP/BI-03-C, need to check if appkey * is bound to model identified by the ModelIdentifier. */ if (!bt_mesh_app_key_find(app_idx) || diff --git a/components/bt/esp_ble_mesh/mesh_core/prov.c b/components/bt/esp_ble_mesh/mesh_core/prov.c index f9de1e271c..c18c6949cf 100644 --- a/components/bt/esp_ble_mesh/mesh_core/prov.c +++ b/components/bt/esp_ble_mesh/mesh_core/prov.c @@ -1672,7 +1672,7 @@ int bt_mesh_pb_gatt_recv(struct bt_mesh_conn *conn, struct net_buf_simple *buf) /* For case MESH/NODE/PROV/BI-03-C, if the link is closed, when the node receive * a Provisioning PDU , it will send a Provisioning Failed PDU with the Error Code - * field set to Unexpected PDU(0x03). + * field set to Unexpected PDU(0x03). */ if (bt_mesh_atomic_test_bit(link.flags, LINK_INVALID)) { BT_WARN("Unexpected msg 0x%02x on invalid link", type);