Bluetooth: Mesh: Fixed issue with RPR server and client.

Fixed issue when reprovisioning is done on a device with
both RPR client and server on the same device.

Signed-off-by: Ingar Kulbrandstad <ingar.kulbrandstad@nordicsemi.no>
This commit is contained in:
Ingar Kulbrandstad 2023-10-02 17:41:31 +02:00 committed by Johan Hedberg
commit a5d15ec017
3 changed files with 444 additions and 123 deletions

View file

@ -857,6 +857,72 @@ int bt_mesh_pb_remote_open(struct bt_mesh_rpr_cli *cli,
return link_open(uuid, &pb_remote_cli, net_idx, addr, 0, &ctx, 0);
}
/* Remote Provision done where client and server is on same node, skip open link
* and sending of reprovision message, just execute reprovisioning on it self.
*/
static int reprovision_local_client_server(uint16_t addr)
{
int err;
const uint8_t *pub_key;
const uint8_t *priv_key = NULL;
if (atomic_test_and_set_bit(bt_mesh_prov_link.flags, LINK_ACTIVE)) {
return -EBUSY;
}
LOG_DBG("net_idx %u iv_index 0x%08x, addr 0x%04x",
prov_device.node->net_idx, bt_mesh_cdb.iv_index, addr);
atomic_set_bit(bt_mesh_prov_link.flags, REPROVISION);
atomic_set_bit(bt_mesh_prov_link.flags, PROVISIONER);
bt_mesh_prov_link.addr = addr;
bt_mesh_prov_link.bearer = &pb_remote_cli;
bt_mesh_prov_link.role = &role_provisioner;
prov_device.net_idx = prov_device.node->net_idx;
prov_device.attention_duration = 0;
if (IS_ENABLED(CONFIG_BT_MESH_PROV_OOB_PUBLIC_KEY) &&
bt_mesh_prov->public_key_be && bt_mesh_prov->private_key_be) {
LOG_DBG("Use OOB Public and Private key");
pub_key = bt_mesh_prov->public_key_be;
priv_key = bt_mesh_prov->private_key_be;
} else {
pub_key = bt_mesh_pub_key_get();
}
if (!pub_key) {
LOG_ERR("No public key available");
return -ENOEXEC;
}
if (bt_mesh_dhkey_gen(pub_key, priv_key, bt_mesh_prov_link.dhkey)) {
LOG_ERR("Failed to generate DHKey");
return -ENOEXEC;
}
LOG_DBG("DHkey: %s", bt_hex(bt_mesh_prov_link.dhkey, DH_KEY_SIZE));
err = bt_mesh_dev_key(bt_mesh_prov_link.dhkey,
bt_mesh_prov_link.prov_salt, prov_device.new_dev_key);
if (err) {
LOG_ERR("Unable to generate device key");
return err;
}
bt_mesh_dev_key_cand(prov_device.new_dev_key);
/* Mark the link that was never opened as closed. */
atomic_set_bit(bt_mesh_prov_link.flags, COMPLETE);
bt_mesh_reprovision(addr);
bt_mesh_dev_key_cand_activate();
if (bt_mesh_prov->reprovisioned) {
LOG_DBG("Application reprovisioned callback 0x%04x", bt_mesh_primary_addr());
bt_mesh_prov->reprovisioned(bt_mesh_primary_addr());
}
prov_link_closed(PROV_BEARER_LINK_STATUS_SUCCESS);
return 0;
}
int bt_mesh_pb_remote_open_node(struct bt_mesh_rpr_cli *cli,
struct bt_mesh_rpr_node *srv, uint16_t addr,
bool composition_change)
@ -877,6 +943,11 @@ int bt_mesh_pb_remote_open_node(struct bt_mesh_rpr_cli *cli,
return -ENOENT;
}
/* Check if server is on same device as client */
if (IS_ENABLED(CONFIG_BT_MESH_RPR_SRV) && bt_mesh_has_addr(srv->addr)) {
return reprovision_local_client_server(addr);
}
return link_open(NULL, &pb_remote_cli, prov_device.node->net_idx, addr,
0, &ctx, 0);
}