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:
parent
e04c963d9c
commit
a5d15ec017
3 changed files with 444 additions and 123 deletions
|
@ -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);
|
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,
|
int bt_mesh_pb_remote_open_node(struct bt_mesh_rpr_cli *cli,
|
||||||
struct bt_mesh_rpr_node *srv, uint16_t addr,
|
struct bt_mesh_rpr_node *srv, uint16_t addr,
|
||||||
bool composition_change)
|
bool composition_change)
|
||||||
|
@ -877,6 +943,11 @@ int bt_mesh_pb_remote_open_node(struct bt_mesh_rpr_cli *cli,
|
||||||
return -ENOENT;
|
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,
|
return link_open(NULL, &pb_remote_cli, prov_device.node->net_idx, addr,
|
||||||
0, &ctx, 0);
|
0, &ctx, 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,6 +139,19 @@ static const struct bt_mesh_comp rpr_srv_comp = {
|
||||||
.elem_count = 1,
|
.elem_count = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct bt_mesh_comp rpr_cli_srv_comp = {
|
||||||
|
.elem =
|
||||||
|
(struct bt_mesh_elem[]){
|
||||||
|
BT_MESH_ELEM(1,
|
||||||
|
MODEL_LIST(BT_MESH_MODEL_CFG_SRV,
|
||||||
|
BT_MESH_MODEL_CFG_CLI(&(struct bt_mesh_cfg_cli){}),
|
||||||
|
BT_MESH_MODEL_RPR_CLI(&rpr_cli),
|
||||||
|
BT_MESH_MODEL_RPR_SRV),
|
||||||
|
BT_MESH_MODEL_NONE),
|
||||||
|
},
|
||||||
|
.elem_count = 1,
|
||||||
|
};
|
||||||
|
|
||||||
static int mock_pdu_send(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
|
static int mock_pdu_send(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
|
||||||
struct net_buf_simple *buf)
|
struct net_buf_simple *buf)
|
||||||
{
|
{
|
||||||
|
@ -1072,18 +1085,127 @@ static void test_provisioner_pb_remote_client_provision_timeout(void)
|
||||||
PASS();
|
PASS();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void reprovision_remote_devkey_client(struct bt_mesh_rpr_node *srv,
|
||||||
|
struct bt_mesh_cdb_node *node)
|
||||||
|
{
|
||||||
|
uint8_t status;
|
||||||
|
uint8_t prev_node_dev_key[16];
|
||||||
|
|
||||||
|
ASSERT_OK_MSG(bt_mesh_cdb_node_key_export(node, prev_node_dev_key),
|
||||||
|
"Can't export device key from cdb");
|
||||||
|
|
||||||
|
bt_mesh_reprovision_remote(&rpr_cli, srv, current_dev_addr, false);
|
||||||
|
|
||||||
|
ASSERT_OK(k_sem_take(&reprov_sem, K_SECONDS(20)));
|
||||||
|
|
||||||
|
/* Check that CDB has updated Device Key for the node. */
|
||||||
|
ASSERT_TRUE(bt_mesh_key_compare(prev_node_dev_key, &node->dev_key));
|
||||||
|
ASSERT_OK_MSG(bt_mesh_cdb_node_key_export(node, prev_node_dev_key),
|
||||||
|
"Can't export device key from cdb");
|
||||||
|
|
||||||
|
/* Check device key by adding appkey. */
|
||||||
|
ASSERT_OK(bt_mesh_cfg_cli_app_key_add(0, current_dev_addr, 0, 0, test_app_key,
|
||||||
|
&status));
|
||||||
|
ASSERT_OK(status);
|
||||||
|
|
||||||
|
/* Let RPR Server verify Device Key. */
|
||||||
|
k_sleep(K_SECONDS(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void reprovision_remote_comp_data_client(struct bt_mesh_rpr_node *srv,
|
||||||
|
struct bt_mesh_cdb_node *node,
|
||||||
|
struct net_buf_simple *dev_comp)
|
||||||
|
{
|
||||||
|
NET_BUF_SIMPLE_DEFINE(new_dev_comp, BT_MESH_RX_SDU_MAX);
|
||||||
|
uint8_t prev_node_dev_key[16];
|
||||||
|
uint8_t page;
|
||||||
|
|
||||||
|
ASSERT_OK_MSG(bt_mesh_cdb_node_key_export(node, prev_node_dev_key),
|
||||||
|
"Can't export device key from cdb");
|
||||||
|
|
||||||
|
bt_mesh_reprovision_remote(&rpr_cli, srv, current_dev_addr, true);
|
||||||
|
|
||||||
|
ASSERT_OK(k_sem_take(&reprov_sem, K_SECONDS(20)));
|
||||||
|
|
||||||
|
/* Check that CDB has updated Device Key for the node. */
|
||||||
|
ASSERT_TRUE(bt_mesh_key_compare(prev_node_dev_key, &node->dev_key));
|
||||||
|
ASSERT_OK_MSG(bt_mesh_cdb_node_key_export(node, prev_node_dev_key),
|
||||||
|
"Can't export device key from cdb");
|
||||||
|
|
||||||
|
/* Check that Composition Data Page 128 is now Page 0. */
|
||||||
|
net_buf_simple_reset(&new_dev_comp);
|
||||||
|
ASSERT_OK(bt_mesh_cfg_cli_comp_data_get(0, current_dev_addr, 0, &page,
|
||||||
|
&new_dev_comp));
|
||||||
|
|
||||||
|
ASSERT_EQUAL(0, page);
|
||||||
|
ASSERT_EQUAL(dev_comp->len, new_dev_comp.len);
|
||||||
|
if (memcmp(dev_comp->data, new_dev_comp.data, dev_comp->len)) {
|
||||||
|
FAIL("Wrong composition data page 0");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Let RPR Server verify Device Key. */
|
||||||
|
k_sleep(K_SECONDS(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void reprovision_remote_address_client(struct bt_mesh_rpr_node *srv,
|
||||||
|
struct bt_mesh_cdb_node *node)
|
||||||
|
{
|
||||||
|
uint8_t status;
|
||||||
|
uint8_t prev_node_dev_key[16];
|
||||||
|
|
||||||
|
ASSERT_OK_MSG(bt_mesh_cdb_node_key_export(node, prev_node_dev_key),
|
||||||
|
"Can't export device key from cdb");
|
||||||
|
|
||||||
|
bt_mesh_reprovision_remote(&rpr_cli, srv, current_dev_addr + 1, false);
|
||||||
|
|
||||||
|
ASSERT_OK(k_sem_take(&reprov_sem, K_SECONDS(20)));
|
||||||
|
|
||||||
|
current_dev_addr++;
|
||||||
|
srv->addr++;
|
||||||
|
|
||||||
|
/* Check that device doesn't respond to old address with old and new device key. */
|
||||||
|
struct bt_mesh_cdb_node *prev_node;
|
||||||
|
uint8_t tmp[16];
|
||||||
|
|
||||||
|
prev_node = bt_mesh_cdb_node_alloc((uint8_t[16]) {}, current_dev_addr - 1, 1, 0);
|
||||||
|
ASSERT_TRUE(node);
|
||||||
|
ASSERT_OK_MSG(bt_mesh_cdb_node_key_import(prev_node, prev_node_dev_key),
|
||||||
|
"Can't import device key into cdb");
|
||||||
|
ASSERT_EQUAL(-ETIMEDOUT, bt_mesh_cfg_cli_app_key_add(0, current_dev_addr - 1, 0, 0,
|
||||||
|
test_app_key, &status));
|
||||||
|
ASSERT_OK_MSG(bt_mesh_cdb_node_key_export(node, tmp),
|
||||||
|
"Can't export device key from cdb");
|
||||||
|
ASSERT_OK_MSG(bt_mesh_cdb_node_key_import(prev_node, tmp),
|
||||||
|
"Can't import device key into cdb");
|
||||||
|
ASSERT_EQUAL(-ETIMEDOUT, bt_mesh_cfg_cli_app_key_add(0, current_dev_addr - 1, 0, 0,
|
||||||
|
test_app_key, &status));
|
||||||
|
bt_mesh_cdb_node_del(prev_node, false);
|
||||||
|
|
||||||
|
/* Check that CDB has updated Device Key for the node. */
|
||||||
|
ASSERT_TRUE(bt_mesh_key_compare(prev_node_dev_key, &node->dev_key));
|
||||||
|
ASSERT_OK_MSG(bt_mesh_cdb_node_key_export(node, prev_node_dev_key),
|
||||||
|
"Can't export device key from cdb");
|
||||||
|
|
||||||
|
/* Check new device address by adding appkey. */
|
||||||
|
ASSERT_OK(bt_mesh_cfg_cli_app_key_add(0, current_dev_addr, 0, 0, test_app_key,
|
||||||
|
&status));
|
||||||
|
ASSERT_OK(status);
|
||||||
|
|
||||||
|
/* Let RPR Server verify Device Key. */
|
||||||
|
k_sleep(K_SECONDS(2));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/** @brief Verify robustness of NPPI procedures on a RPR Client by running Device Key Refresh,
|
/** @brief Verify robustness of NPPI procedures on a RPR Client by running Device Key Refresh,
|
||||||
* Node Composition Refresh and Node Address Refresh procedures.
|
* Node Composition Refresh and Node Address Refresh procedures.
|
||||||
*/
|
*/
|
||||||
static void test_provisioner_pb_remote_client_nppi_robustness(void)
|
static void test_provisioner_pb_remote_client_nppi_robustness(void)
|
||||||
{
|
{
|
||||||
NET_BUF_SIMPLE_DEFINE(dev_comp, BT_MESH_RX_SDU_MAX);
|
NET_BUF_SIMPLE_DEFINE(dev_comp, BT_MESH_RX_SDU_MAX);
|
||||||
NET_BUF_SIMPLE_DEFINE(new_dev_comp, BT_MESH_RX_SDU_MAX);
|
|
||||||
uint8_t page;
|
uint8_t page;
|
||||||
uint16_t pb_remote_server_addr;
|
uint16_t pb_remote_server_addr;
|
||||||
uint8_t status;
|
uint8_t status;
|
||||||
struct bt_mesh_cdb_node *node;
|
struct bt_mesh_cdb_node *node;
|
||||||
uint8_t prev_node_dev_key[16];
|
|
||||||
|
|
||||||
provisioner_pb_remote_client_setup();
|
provisioner_pb_remote_client_setup();
|
||||||
|
|
||||||
|
@ -1111,96 +1233,23 @@ static void test_provisioner_pb_remote_client_nppi_robustness(void)
|
||||||
|
|
||||||
node = bt_mesh_cdb_node_get(current_dev_addr);
|
node = bt_mesh_cdb_node_get(current_dev_addr);
|
||||||
ASSERT_TRUE(node);
|
ASSERT_TRUE(node);
|
||||||
ASSERT_OK_MSG(bt_mesh_cdb_node_key_export(node, prev_node_dev_key),
|
|
||||||
"Can't export device key from cdb");
|
|
||||||
|
|
||||||
LOG_INF("Testing DevKey refresh...");
|
LOG_INF("Testing DevKey refresh...");
|
||||||
for (int i = 0; i < PROV_REPROV_COUNT; i++) {
|
for (int i = 0; i < PROV_REPROV_COUNT; i++) {
|
||||||
LOG_INF("Refreshing device key #%d...\n", i);
|
LOG_INF("Refreshing device key #%d...\n", i);
|
||||||
bt_mesh_reprovision_remote(&rpr_cli, &srv, current_dev_addr, false);
|
reprovision_remote_devkey_client(&srv, node);
|
||||||
|
|
||||||
ASSERT_OK(k_sem_take(&reprov_sem, K_SECONDS(20)));
|
|
||||||
|
|
||||||
/* Check that CDB has updated Device Key for the node. */
|
|
||||||
ASSERT_TRUE(bt_mesh_key_compare(prev_node_dev_key, &node->dev_key));
|
|
||||||
ASSERT_OK_MSG(bt_mesh_cdb_node_key_export(node, prev_node_dev_key),
|
|
||||||
"Can't export device key from cdb");
|
|
||||||
|
|
||||||
/* Check device key by adding appkey. */
|
|
||||||
ASSERT_OK(bt_mesh_cfg_cli_app_key_add(0, current_dev_addr, 0, 0, test_app_key,
|
|
||||||
&status));
|
|
||||||
ASSERT_OK(status);
|
|
||||||
|
|
||||||
/* Let RPR Server verify Device Key. */
|
|
||||||
k_sleep(K_SECONDS(2));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_INF("Testing Composition Data refresh...");
|
LOG_INF("Testing Composition Data refresh...");
|
||||||
for (int i = 0; i < PROV_REPROV_COUNT; i++) {
|
for (int i = 0; i < PROV_REPROV_COUNT; i++) {
|
||||||
LOG_INF("Changing Composition Data #%d...\n", i);
|
LOG_INF("Changing Composition Data #%d...\n", i);
|
||||||
bt_mesh_reprovision_remote(&rpr_cli, &srv, current_dev_addr, true);
|
reprovision_remote_comp_data_client(&srv, node, &dev_comp);
|
||||||
|
|
||||||
ASSERT_OK(k_sem_take(&reprov_sem, K_SECONDS(20)));
|
|
||||||
|
|
||||||
/* Check that CDB has updated Device Key for the node. */
|
|
||||||
ASSERT_TRUE(bt_mesh_key_compare(prev_node_dev_key, &node->dev_key));
|
|
||||||
ASSERT_OK_MSG(bt_mesh_cdb_node_key_export(node, prev_node_dev_key),
|
|
||||||
"Can't export device key from cdb");
|
|
||||||
|
|
||||||
/* Check that Composition Data Page 128 is now Page 0. */
|
|
||||||
net_buf_simple_reset(&new_dev_comp);
|
|
||||||
ASSERT_OK(bt_mesh_cfg_cli_comp_data_get(0, current_dev_addr, 0, &page,
|
|
||||||
&new_dev_comp));
|
|
||||||
ASSERT_EQUAL(0, page);
|
|
||||||
ASSERT_EQUAL(dev_comp.len, new_dev_comp.len);
|
|
||||||
if (memcmp(dev_comp.data, new_dev_comp.data, dev_comp.len)) {
|
|
||||||
FAIL("Wrong composition data page 0");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Let RPR Server verify Device Key. */
|
|
||||||
k_sleep(K_SECONDS(2));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_INF("Testing address refresh...");
|
LOG_INF("Testing address refresh...");
|
||||||
for (int i = 0; i < PROV_REPROV_COUNT; i++) {
|
for (int i = 0; i < PROV_REPROV_COUNT; i++) {
|
||||||
LOG_INF("Changing address #%d...\n", i);
|
LOG_INF("Changing address #%d...\n", i);
|
||||||
bt_mesh_reprovision_remote(&rpr_cli, &srv, current_dev_addr + 1, false);
|
reprovision_remote_address_client(&srv, node);
|
||||||
|
|
||||||
ASSERT_OK(k_sem_take(&reprov_sem, K_SECONDS(20)));
|
|
||||||
|
|
||||||
current_dev_addr++;
|
|
||||||
srv.addr++;
|
|
||||||
|
|
||||||
/* Check that device doesn't respond to old address with old and new device key. */
|
|
||||||
struct bt_mesh_cdb_node *prev_node;
|
|
||||||
uint8_t tmp[16];
|
|
||||||
|
|
||||||
prev_node = bt_mesh_cdb_node_alloc((uint8_t[16]) {}, current_dev_addr - 1, 1, 0);
|
|
||||||
ASSERT_TRUE(node);
|
|
||||||
ASSERT_OK_MSG(bt_mesh_cdb_node_key_import(prev_node, prev_node_dev_key),
|
|
||||||
"Can't import device key into cdb");
|
|
||||||
ASSERT_EQUAL(-ETIMEDOUT, bt_mesh_cfg_cli_app_key_add(0, current_dev_addr - 1, 0, 0,
|
|
||||||
test_app_key, &status));
|
|
||||||
ASSERT_OK_MSG(bt_mesh_cdb_node_key_export(node, tmp),
|
|
||||||
"Can't export device key from cdb");
|
|
||||||
ASSERT_OK_MSG(bt_mesh_cdb_node_key_import(prev_node, tmp),
|
|
||||||
"Can't import device key into cdb");
|
|
||||||
ASSERT_EQUAL(-ETIMEDOUT, bt_mesh_cfg_cli_app_key_add(0, current_dev_addr - 1, 0, 0,
|
|
||||||
test_app_key, &status));
|
|
||||||
bt_mesh_cdb_node_del(prev_node, false);
|
|
||||||
|
|
||||||
/* Check that CDB has updated Device Key for the node. */
|
|
||||||
ASSERT_TRUE(bt_mesh_key_compare(prev_node_dev_key, &node->dev_key));
|
|
||||||
ASSERT_OK_MSG(bt_mesh_cdb_node_key_export(node, prev_node_dev_key),
|
|
||||||
"Can't export device key from cdb");
|
|
||||||
|
|
||||||
/* Check new device address by adding appkey. */
|
|
||||||
ASSERT_OK(bt_mesh_cfg_cli_app_key_add(0, current_dev_addr, 0, 0, test_app_key,
|
|
||||||
&status));
|
|
||||||
ASSERT_OK(status);
|
|
||||||
|
|
||||||
/* Let RPR Server verify Device Key. */
|
|
||||||
k_sleep(K_SECONDS(2));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PASS();
|
PASS();
|
||||||
|
@ -1240,13 +1289,78 @@ static void test_device_pb_remote_server_proved(void)
|
||||||
PASS();
|
PASS();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void reprovision_remote_devkey_server(const uint16_t initial_addr)
|
||||||
|
{
|
||||||
|
uint8_t prev_dev_key[16];
|
||||||
|
uint8_t dev_key[16];
|
||||||
|
|
||||||
|
ASSERT_OK(bt_mesh_key_export(prev_dev_key, &bt_mesh.dev_key));
|
||||||
|
|
||||||
|
ASSERT_OK(k_sem_take(&reprov_sem, K_SECONDS(30)));
|
||||||
|
ASSERT_EQUAL(initial_addr, bt_mesh_primary_addr());
|
||||||
|
|
||||||
|
/* Let Configuration Client activate the new Device Key and verify that it has
|
||||||
|
* been changed.
|
||||||
|
*/
|
||||||
|
k_sleep(K_SECONDS(2));
|
||||||
|
ASSERT_OK(bt_mesh_key_export(dev_key, &bt_mesh.dev_key));
|
||||||
|
ASSERT_TRUE(memcmp(&prev_dev_key, dev_key, sizeof(dev_key)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void reprovision_remote_comp_data_server(const uint16_t initial_addr)
|
||||||
|
{
|
||||||
|
u_int8_t prev_dev_key[16];
|
||||||
|
u_int8_t dev_key[16];
|
||||||
|
|
||||||
|
/* The RPR Server won't let to run Node Composition Refresh procedure without first
|
||||||
|
* setting the BT_MESH_COMP_DIRTY flag. The flag is set on a boot if there is a
|
||||||
|
* "bt/mesh/cmp" entry in settings. The entry is added by the
|
||||||
|
* `bt_mesh_comp_change_prepare() call. The test suite is not compiled
|
||||||
|
* with CONFIG_BT_SETTINGS, so the flag will never be set. Since the purpose of the
|
||||||
|
* test is to check RPR Server behavior, but not the actual swap of the Composition
|
||||||
|
* Data, the flag is toggled directly from the test.
|
||||||
|
*/
|
||||||
|
atomic_set_bit(bt_mesh.flags, BT_MESH_COMP_DIRTY);
|
||||||
|
ASSERT_OK(bt_mesh_key_export(prev_dev_key, &bt_mesh.dev_key));
|
||||||
|
|
||||||
|
ASSERT_OK(k_sem_take(&reprov_sem, K_SECONDS(30)));
|
||||||
|
|
||||||
|
/* Drop the flag manually as CONFIG_BT_SETTINGS is not enabled. */
|
||||||
|
atomic_clear_bit(bt_mesh.flags, BT_MESH_COMP_DIRTY);
|
||||||
|
|
||||||
|
ASSERT_EQUAL(initial_addr, bt_mesh_primary_addr());
|
||||||
|
|
||||||
|
/* Let Configuration Client activate the new Device Key and verify that it has
|
||||||
|
* been changed.
|
||||||
|
*/
|
||||||
|
k_sleep(K_SECONDS(2));
|
||||||
|
ASSERT_OK(bt_mesh_key_export(dev_key, &bt_mesh.dev_key));
|
||||||
|
ASSERT_TRUE(memcmp(prev_dev_key, dev_key, sizeof(dev_key)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void reprovision_remote_address_server(const uint16_t initial_addr)
|
||||||
|
{
|
||||||
|
uint8_t prev_dev_key[16];
|
||||||
|
uint8_t dev_key[16];
|
||||||
|
|
||||||
|
ASSERT_OK(bt_mesh_key_export(prev_dev_key, &bt_mesh.dev_key));
|
||||||
|
|
||||||
|
ASSERT_OK(k_sem_take(&reprov_sem, K_SECONDS(30)));
|
||||||
|
ASSERT_EQUAL(initial_addr + 1, bt_mesh_primary_addr());
|
||||||
|
|
||||||
|
/* Let Configuration Client activate the new Device Key and verify that it has
|
||||||
|
* been changed.
|
||||||
|
*/
|
||||||
|
k_sleep(K_SECONDS(2));
|
||||||
|
ASSERT_OK(bt_mesh_key_export(dev_key, &bt_mesh.dev_key));
|
||||||
|
ASSERT_TRUE(memcmp(prev_dev_key, dev_key, sizeof(dev_key)));
|
||||||
|
}
|
||||||
|
|
||||||
/** @brief Verify robustness of NPPI procedures on a RPR Server by running Device Key Refresh,
|
/** @brief Verify robustness of NPPI procedures on a RPR Server by running Device Key Refresh,
|
||||||
* Node Composition Refresh and Node Address Refresh procedures multiple times each.
|
* Node Composition Refresh and Node Address Refresh procedures multiple times each.
|
||||||
*/
|
*/
|
||||||
static void test_device_pb_remote_server_nppi_robustness(void)
|
static void test_device_pb_remote_server_nppi_robustness(void)
|
||||||
{
|
{
|
||||||
struct bt_mesh_key prev_dev_key;
|
|
||||||
|
|
||||||
k_sem_init(&prov_sem, 0, 1);
|
k_sem_init(&prov_sem, 0, 1);
|
||||||
k_sem_init(&reprov_sem, 0, 1);
|
k_sem_init(&reprov_sem, 0, 1);
|
||||||
|
|
||||||
|
@ -1259,65 +1373,25 @@ static void test_device_pb_remote_server_nppi_robustness(void)
|
||||||
ASSERT_OK(k_sem_take(&prov_sem, K_SECONDS(20)));
|
ASSERT_OK(k_sem_take(&prov_sem, K_SECONDS(20)));
|
||||||
const uint16_t initial_addr = bt_mesh_primary_addr();
|
const uint16_t initial_addr = bt_mesh_primary_addr();
|
||||||
|
|
||||||
memcpy(&prev_dev_key, &bt_mesh.dev_key, sizeof(struct bt_mesh_key));
|
|
||||||
|
|
||||||
LOG_INF("Enabling PB-Remote server");
|
LOG_INF("Enabling PB-Remote server");
|
||||||
ASSERT_OK(bt_mesh_prov_enable(BT_MESH_PROV_REMOTE));
|
ASSERT_OK(bt_mesh_prov_enable(BT_MESH_PROV_REMOTE));
|
||||||
|
|
||||||
/* Test Device Key Refresh procedure robustness. */
|
/* Test Device Key Refresh procedure robustness. */
|
||||||
for (int i = 0; i < PROV_REPROV_COUNT; i++) {
|
for (int i = 0; i < PROV_REPROV_COUNT; i++) {
|
||||||
LOG_INF("Devkey refresh loop #%d, waiting for being reprov ...\n", i);
|
LOG_INF("Devkey refresh loop #%d, waiting for being reprov ...\n", i);
|
||||||
ASSERT_OK(k_sem_take(&reprov_sem, K_SECONDS(30)));
|
reprovision_remote_devkey_server(initial_addr);
|
||||||
ASSERT_EQUAL(initial_addr, bt_mesh_primary_addr());
|
|
||||||
|
|
||||||
/* Let Configuration Client activate the new Device Key and verify that it has
|
|
||||||
* been changed.
|
|
||||||
*/
|
|
||||||
k_sleep(K_SECONDS(2));
|
|
||||||
ASSERT_TRUE(memcmp(&prev_dev_key, &bt_mesh.dev_key, sizeof(struct bt_mesh_key)));
|
|
||||||
memcpy(&prev_dev_key, &bt_mesh.dev_key, sizeof(struct bt_mesh_key));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test Node Composition Refresh procedure robustness. */
|
/* Test Node Composition Refresh procedure robustness. */
|
||||||
for (int i = 0; i < PROV_REPROV_COUNT; i++) {
|
for (int i = 0; i < PROV_REPROV_COUNT; i++) {
|
||||||
/* The RPR Server won't let to run Node Composition Refresh procedure without first
|
|
||||||
* setting the BT_MESH_COMP_DIRTY flag. The flag is set on a boot if there is a
|
|
||||||
* "bt/mesh/cmp" entry in settings. The entry is added by the
|
|
||||||
* `bt_mesh_comp_change_prepare() call. The test suite is not compiled
|
|
||||||
* with CONFIG_BT_SETTINGS, so the flag will never be set. Since the purpose of the
|
|
||||||
* test is to check RPR Server behavior, but not the actual swap of the Composition
|
|
||||||
* Data, the flag is toggled directly from the test.
|
|
||||||
*/
|
|
||||||
atomic_set_bit(bt_mesh.flags, BT_MESH_COMP_DIRTY);
|
|
||||||
|
|
||||||
LOG_INF("Composition data refresh loop #%d, waiting for being reprov ...\n", i);
|
LOG_INF("Composition data refresh loop #%d, waiting for being reprov ...\n", i);
|
||||||
ASSERT_OK(k_sem_take(&reprov_sem, K_SECONDS(30)));
|
reprovision_remote_comp_data_server(initial_addr);
|
||||||
|
|
||||||
/* Drop the flag manually as CONFIG_BT_SETTINGS is not enabled. */
|
|
||||||
atomic_clear_bit(bt_mesh.flags, BT_MESH_COMP_DIRTY);
|
|
||||||
|
|
||||||
ASSERT_EQUAL(initial_addr, bt_mesh_primary_addr());
|
|
||||||
|
|
||||||
/* Let Configuration Client activate the new Device Key and verify that it has
|
|
||||||
* been changed.
|
|
||||||
*/
|
|
||||||
k_sleep(K_SECONDS(2));
|
|
||||||
ASSERT_TRUE(memcmp(&prev_dev_key, &bt_mesh.dev_key, sizeof(struct bt_mesh_key)));
|
|
||||||
memcpy(&prev_dev_key, &bt_mesh.dev_key, sizeof(struct bt_mesh_key));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Node Address Refresh robustness. */
|
/* Node Address Refresh robustness. */
|
||||||
for (int i = 0; i < PROV_REPROV_COUNT; i++) {
|
for (int i = 0; i < PROV_REPROV_COUNT; i++) {
|
||||||
LOG_INF("Address refresh loop #%d, waiting for being reprov ...\n", i);
|
LOG_INF("Address refresh loop #%d, waiting for being reprov ...\n", i);
|
||||||
ASSERT_OK(k_sem_take(&reprov_sem, K_SECONDS(30)));
|
reprovision_remote_address_server(initial_addr+i);
|
||||||
ASSERT_EQUAL(initial_addr + 1 + i, bt_mesh_primary_addr());
|
|
||||||
|
|
||||||
/* Let Configuration Client activate the new Device Key and verify that it has
|
|
||||||
* been changed.
|
|
||||||
*/
|
|
||||||
k_sleep(K_SECONDS(2));
|
|
||||||
ASSERT_TRUE(memcmp(&prev_dev_key, &bt_mesh.dev_key, sizeof(struct bt_mesh_key)));
|
|
||||||
memcpy(&prev_dev_key, &bt_mesh.dev_key, sizeof(struct bt_mesh_key));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PASS();
|
PASS();
|
||||||
|
@ -1354,6 +1428,146 @@ static void test_provisioner_pb_remote_client_ncrp_provision(void)
|
||||||
PASS();
|
PASS();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @brief A device running a Remote Provisioning client and server that is used to reprovision
|
||||||
|
* another device and it self with the client.
|
||||||
|
*/
|
||||||
|
static void test_device_pb_remote_client_server_same_dev(void)
|
||||||
|
{
|
||||||
|
NET_BUF_SIMPLE_DEFINE(dev_comp, BT_MESH_RX_SDU_MAX);
|
||||||
|
uint8_t status;
|
||||||
|
struct bt_mesh_cdb_node *node;
|
||||||
|
uint8_t page;
|
||||||
|
uint8_t prev_dev_key[16];
|
||||||
|
uint16_t test_vector[] = { 0x0002, 0x0001 };
|
||||||
|
|
||||||
|
k_sem_init(&prov_sem, 0, 1);
|
||||||
|
k_sem_init(&reprov_sem, 0, 1);
|
||||||
|
|
||||||
|
bt_mesh_device_setup(&prov, &rpr_cli_srv_comp);
|
||||||
|
|
||||||
|
ASSERT_OK(bt_mesh_cdb_create(test_net_key));
|
||||||
|
ASSERT_OK(bt_mesh_provision(test_net_key, 0, 0, 0, 0x0001, dev_key));
|
||||||
|
|
||||||
|
LOG_INF("Enabling PB-Remote server");
|
||||||
|
ASSERT_OK(bt_mesh_prov_enable(BT_MESH_PROV_REMOTE));
|
||||||
|
|
||||||
|
/* Provision a remote device with RPR Client and Server with local RPR Server. */
|
||||||
|
current_dev_addr = 0x0001;
|
||||||
|
struct bt_mesh_rpr_node srv = {
|
||||||
|
.addr = current_dev_addr,
|
||||||
|
.net_idx = 0,
|
||||||
|
.ttl = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
LOG_INF("Provisioner prov, waiting for prov ...\n");
|
||||||
|
ASSERT_OK(provision_remote(&srv, 1, &srv.addr));
|
||||||
|
|
||||||
|
ASSERT_OK(k_sem_take(&prov_sem, K_SECONDS(20)));
|
||||||
|
|
||||||
|
/* Check device key by adding bt_mesh_reprovision_remote appkey. */
|
||||||
|
ASSERT_OK(bt_mesh_cfg_cli_app_key_add(0, current_dev_addr, 0, 0, test_app_key, &status));
|
||||||
|
ASSERT_OK(status);
|
||||||
|
|
||||||
|
/* Swap callback to catch when device reprovisioned. */
|
||||||
|
prov.node_added = prov_node_added_rpr;
|
||||||
|
|
||||||
|
/* Reprovision a device with both RPR Client and Server. */
|
||||||
|
for (int i = 0; i < ARRAY_SIZE(test_vector); i++) {
|
||||||
|
current_dev_addr = test_vector[i];
|
||||||
|
srv.addr = current_dev_addr;
|
||||||
|
bool self_reprov = (bool)(current_dev_addr == bt_mesh_primary_addr());
|
||||||
|
|
||||||
|
/* Store initial Composition Data Page 0. */
|
||||||
|
net_buf_simple_reset(&dev_comp);
|
||||||
|
ASSERT_OK(bt_mesh_cfg_cli_comp_data_get(0, current_dev_addr, 0, &page, &dev_comp));
|
||||||
|
|
||||||
|
node = bt_mesh_cdb_node_get(current_dev_addr);
|
||||||
|
ASSERT_TRUE(node);
|
||||||
|
|
||||||
|
LOG_INF("Refreshing 0x%04x device key ...\n", srv.addr);
|
||||||
|
ASSERT_OK(bt_mesh_key_export(prev_dev_key, &bt_mesh.dev_key));
|
||||||
|
reprovision_remote_devkey_client(&srv, node);
|
||||||
|
if (self_reprov) {
|
||||||
|
uint8_t dev_key[16];
|
||||||
|
|
||||||
|
ASSERT_EQUAL(current_dev_addr, bt_mesh_primary_addr());
|
||||||
|
|
||||||
|
/* Let Configuration Client activate the new Device Key
|
||||||
|
* and verify that it has been changed.
|
||||||
|
*/
|
||||||
|
ASSERT_OK(bt_mesh_key_export(dev_key, &bt_mesh.dev_key));
|
||||||
|
ASSERT_TRUE(memcmp(prev_dev_key, dev_key, sizeof(dev_key)));
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_INF("Changing 0x%04x Composition Data ...\n", srv.addr);
|
||||||
|
ASSERT_OK(bt_mesh_key_export(prev_dev_key, &bt_mesh.dev_key));
|
||||||
|
reprovision_remote_comp_data_client(&srv, node, &dev_comp);
|
||||||
|
if (self_reprov) {
|
||||||
|
uint8_t dev_key[16];
|
||||||
|
|
||||||
|
ASSERT_EQUAL(current_dev_addr, bt_mesh_primary_addr());
|
||||||
|
|
||||||
|
/* Let Configuration Client activate the new Device Key
|
||||||
|
* and verify that it has been changed.
|
||||||
|
*/
|
||||||
|
ASSERT_OK(bt_mesh_key_export(dev_key, &bt_mesh.dev_key));
|
||||||
|
ASSERT_TRUE(memcmp(prev_dev_key, dev_key, sizeof(struct bt_mesh_key)));
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_INF("Changing 0x%04x address ...\n", srv.addr);
|
||||||
|
ASSERT_OK(bt_mesh_key_export(prev_dev_key, &bt_mesh.dev_key));
|
||||||
|
reprovision_remote_address_client(&srv, node);
|
||||||
|
if (self_reprov) {
|
||||||
|
uint8_t dev_key[16];
|
||||||
|
|
||||||
|
ASSERT_EQUAL(current_dev_addr, bt_mesh_primary_addr());
|
||||||
|
|
||||||
|
/* Let Configuration Client activate the new Device Key
|
||||||
|
* and verify that it has been changed.
|
||||||
|
*/
|
||||||
|
ASSERT_OK(bt_mesh_key_export(dev_key, &bt_mesh.dev_key));
|
||||||
|
ASSERT_TRUE(memcmp(prev_dev_key, dev_key, sizeof(dev_key)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PASS();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @brief Verify that the Remote Provisioning client and server is able to be reprovision
|
||||||
|
* by another device with a Remote Provisioning client and server.
|
||||||
|
*/
|
||||||
|
static void test_device_pb_remote_server_same_dev(void)
|
||||||
|
{
|
||||||
|
k_sem_init(&prov_sem, 0, 1);
|
||||||
|
k_sem_init(&reprov_sem, 0, 1);
|
||||||
|
|
||||||
|
bt_mesh_device_setup(&prov, &rpr_cli_srv_comp);
|
||||||
|
|
||||||
|
ASSERT_OK(bt_mesh_prov_enable(BT_MESH_PROV_ADV));
|
||||||
|
|
||||||
|
LOG_INF("Waiting for being provisioned...");
|
||||||
|
ASSERT_OK(k_sem_take(&prov_sem, K_SECONDS(20)));
|
||||||
|
|
||||||
|
LOG_INF("Enabling PB-Remote server");
|
||||||
|
ASSERT_OK(bt_mesh_prov_enable(BT_MESH_PROV_REMOTE));
|
||||||
|
|
||||||
|
/* Swap callback to catch when device reprovisioned. */
|
||||||
|
prov.node_added = prov_node_added_rpr;
|
||||||
|
|
||||||
|
const uint16_t initial_addr = bt_mesh_primary_addr();
|
||||||
|
|
||||||
|
LOG_INF("Devkey refresh, waiting for being reprov ...\n");
|
||||||
|
reprovision_remote_devkey_server(initial_addr);
|
||||||
|
|
||||||
|
LOG_INF("Composition data refresh, waiting for being reprov ...\n");
|
||||||
|
reprovision_remote_comp_data_server(initial_addr);
|
||||||
|
|
||||||
|
LOG_INF("Address refresh, waiting for being reprov ...\n");
|
||||||
|
reprovision_remote_address_server(initial_addr);
|
||||||
|
|
||||||
|
PASS();
|
||||||
|
}
|
||||||
|
|
||||||
static void comp_data_get(uint16_t server_addr, uint8_t page, struct net_buf_simple *comp)
|
static void comp_data_get(uint16_t server_addr, uint8_t page, struct net_buf_simple *comp)
|
||||||
{
|
{
|
||||||
uint8_t page_rsp;
|
uint8_t page_rsp;
|
||||||
|
@ -1573,6 +1787,10 @@ static const struct bst_test_instance test_connect[] = {
|
||||||
"Device: pb-remote reprovisioning, NPPI robustness"),
|
"Device: pb-remote reprovisioning, NPPI robustness"),
|
||||||
TEST_CASE(device, pb_remote_server_unproved_unresponsive,
|
TEST_CASE(device, pb_remote_server_unproved_unresponsive,
|
||||||
"Device: used for remote provisioning, starts unprovisioned, stops responding"),
|
"Device: used for remote provisioning, starts unprovisioned, stops responding"),
|
||||||
|
TEST_CASE(device, pb_remote_client_server_same_dev,
|
||||||
|
"Device: used for remote provisioning, with both client and server"),
|
||||||
|
TEST_CASE(device, pb_remote_server_same_dev,
|
||||||
|
"Device: used for remote reprovisioning, with both client and server"),
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TEST_CASE(provisioner, pb_adv_no_oob,
|
TEST_CASE(provisioner, pb_adv_no_oob,
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Copyright 2023 Nordic Semiconductor
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh
|
||||||
|
|
||||||
|
# Test a node re-provisioning through Remote Provisioning models. Procedure:
|
||||||
|
# 1. Device (prov_device_pb_remote_client_server_same_dev) provisions it self
|
||||||
|
# and start scanning for an upprovisioned device, and provisions the the
|
||||||
|
# second device (prov_device_pb_remote_server_same_dev) with local RPR server.
|
||||||
|
# 2. The first device (prov_device_pb_remote_client_server_same_dev) execute
|
||||||
|
# device key refresh procedure the second device (prov_device_pb_remote_server_same_dev).
|
||||||
|
# 3. The first device (prov_device_pb_remote_client_server_same_dev) execute
|
||||||
|
# composition refresh procedure the second device (prov_device_pb_remote_server_same_dev).
|
||||||
|
# 4. The first device (prov_device_pb_remote_client_server_same_dev) execute
|
||||||
|
# address refresh procedure the second device (prov_device_pb_remote_server_same_dev).
|
||||||
|
# 5. The first device (prov_device_pb_remote_client_server_same_dev) execute
|
||||||
|
# device key refresh procedure on it self with local RPR client and server.
|
||||||
|
# 6. The first device (prov_device_pb_remote_client_server_same_dev) execute
|
||||||
|
# composition refresh procedure on it self with local RPR client and server.
|
||||||
|
# 7. The first device (prov_device_pb_remote_client_server_same_dev) execute
|
||||||
|
# address refresh procedure on it self with local RPR client and server.
|
||||||
|
conf=prj_mesh1d1_conf
|
||||||
|
RunTest mesh_prov_pb_remote_client_server_same_dev \
|
||||||
|
prov_device_pb_remote_client_server_same_dev \
|
||||||
|
prov_device_pb_remote_server_same_dev
|
||||||
|
|
||||||
|
conf=prj_mesh1d1_conf
|
||||||
|
overlay=overlay_psa_conf
|
||||||
|
RunTest mesh_prov_pb_remote_client_server_same_dev \
|
||||||
|
prov_device_pb_remote_client_server_same_dev \
|
||||||
|
prov_device_pb_remote_server_same_dev
|
Loading…
Add table
Add a link
Reference in a new issue