Bluetooth: Mesh: Fix sending beacons to Friend Queue & GATT clients

Whenever there's a security change (Key Refresh or IV Update) we
should immediately send beacons to any Friend Queues or connected GATT
clients. Introduce a helper function to do this, and make sure it's
called from all places that change the Key Refresh or IV Update
states.

This fixes test case MESH/SR/PROX/PB-12-C.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
This commit is contained in:
Johan Hedberg 2017-11-30 13:27:49 +02:00 committed by Johan Hedberg
commit 77ca943fd5
5 changed files with 38 additions and 12 deletions

View file

@ -25,7 +25,6 @@
#include "crypto.h"
#include "beacon.h"
#include "foundation.h"
#include "friend.h"
#define UNPROVISIONED_INTERVAL K_SECONDS(5)
#define PROVISIONED_INTERVAL K_SECONDS(10)
@ -302,12 +301,12 @@ static void secure_beacon_recv(struct net_buf_simple *buf)
bt_mesh_net_beacon_update(sub);
}
if (IS_ENABLED(CONFIG_BT_MESH_FRIEND) && (iv_change || kr_change)) {
if (iv_change) {
bt_mesh_friend_sec_update(BT_MESH_KEY_ANY);
} else {
bt_mesh_friend_sec_update(sub->net_idx);
}
if (iv_change) {
/* Update all subnets */
bt_mesh_net_sec_update(NULL);
} else if (kr_change) {
/* Key Refresh without IV Update only impacts one subnet */
bt_mesh_net_sec_update(sub);
}
update_stats:

View file

@ -602,10 +602,25 @@ bool bt_mesh_iv_update(void)
bt_mesh_net_iv_update(bt_mesh.iv_index + 1, true);
}
bt_mesh_net_sec_update(NULL);
return bt_mesh.iv_update;
}
#endif /* CONFIG_BT_MESH_IV_UPDATE_TEST */
/* Used for sending immediate beacons to Friend queues and GATT clients */
void bt_mesh_net_sec_update(struct bt_mesh_subnet *sub)
{
if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
bt_mesh_friend_sec_update(sub ? sub->net_idx : BT_MESH_KEY_ANY);
}
if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) &&
bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED) {
bt_mesh_proxy_beacon_send(sub);
}
}
bool bt_mesh_net_iv_update(u32_t iv_index, bool iv_update)
{
int i;
@ -758,10 +773,7 @@ int bt_mesh_net_resend(struct bt_mesh_subnet *sub, struct net_buf *buf,
if (!bt_mesh.iv_update && bt_mesh.seq > IV_UPDATE_SEQ_LIMIT) {
bt_mesh_beacon_ivu_initiator(true);
bt_mesh_net_iv_update(bt_mesh.iv_index + 1, true);
if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
bt_mesh_friend_sec_update(BT_MESH_KEY_ANY);
}
bt_mesh_net_sec_update(NULL);
}
return 0;

View file

@ -275,6 +275,8 @@ void bt_mesh_rpl_reset(void);
bool bt_mesh_net_iv_update(u32_t iv_index, bool iv_update);
void bt_mesh_net_sec_update(struct bt_mesh_subnet *sub);
struct bt_mesh_subnet *bt_mesh_subnet_get(u16_t net_idx);
struct bt_mesh_subnet *bt_mesh_subnet_find(const u8_t net_id[8], u8_t flags,

View file

@ -319,6 +319,17 @@ void bt_mesh_proxy_beacon_send(struct bt_mesh_subnet *sub)
{
int i;
if (!sub) {
/* NULL means we send on all subnets */
for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
if (bt_mesh.sub[i].net_idx != BT_MESH_KEY_UNUSED) {
bt_mesh_proxy_beacon_send(&bt_mesh.sub[i]);
}
}
return;
}
for (i = 0; i < ARRAY_SIZE(clients); i++) {
if (clients[i].conn) {
beacon_send(clients[i].conn, sub);

View file

@ -185,7 +185,9 @@ static void seg_tx_reset(struct seg_tx *tx)
/* bt_mesh_net_iv_update() will re-enable the flag if this
* wasn't the only transfer.
*/
bt_mesh_net_iv_update(bt_mesh.iv_index, false);
if (bt_mesh_net_iv_update(bt_mesh.iv_index, false)) {
bt_mesh_net_sec_update(NULL);
}
}
}