diff --git a/components/bt/esp_ble_mesh/mesh_core/beacon.c b/components/bt/esp_ble_mesh/mesh_core/beacon.c index 31d09aa05a74..981f88edcde1 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 12f910986d71..2818936d91f1 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; } @@ -3049,7 +3068,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; } @@ -3202,19 +3221,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 +3258,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. */ diff --git a/components/bt/esp_ble_mesh/mesh_core/prov.c b/components/bt/esp_ble_mesh/mesh_core/prov.c index 4e9813f7c60f..c18c6949cf1b 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,30 @@ int bt_mesh_pb_gatt_recv(struct bt_mesh_conn *conn, struct net_buf_simple *buf) return -EINVAL; } - 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); + /* 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). + */ + type = net_buf_simple_pull_u8(buf); 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 != 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; } 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 4945e1faee0e..60ac6c2f03b6 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); diff --git a/components/bt/esp_ble_mesh/mesh_core/scan.c b/components/bt/esp_ble_mesh/mesh_core/scan.c index 753f19bb9c91..b840eff9d0dc 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: