From 2d63f5e4807d2bd8955f9b35c3449c2d36d59982 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 27 Nov 2017 17:14:01 +0200 Subject: [PATCH] Bluetooth: Mesh: Fix & clean up Friendship Credential handling Pass the subnet to some friend_cred_* APIs since it contains all necessary information for choosing the right keys to generate them from. Also shorten the API names to avoid awkward line splitting - these are internal APIs so it's an acceptable compromise. One bug that this fixes as part of the cleanup is using the right NetKey Index when clearing Friendship: previously the code was always using the index of the first subnet, regardless of which subnet the Friendship was based on. Signed-off-by: Johan Hedberg --- subsys/bluetooth/host/mesh/cfg_srv.c | 4 +- subsys/bluetooth/host/mesh/friend.c | 10 ++-- subsys/bluetooth/host/mesh/lpn.c | 18 ++----- subsys/bluetooth/host/mesh/net.c | 72 +++++++++++++++------------- subsys/bluetooth/host/mesh/net.h | 55 ++++++++++----------- 5 files changed, 73 insertions(+), 86 deletions(-) diff --git a/subsys/bluetooth/host/mesh/cfg_srv.c b/subsys/bluetooth/host/mesh/cfg_srv.c index d3c13901c0f..cb2a57dcce0 100644 --- a/subsys/bluetooth/host/mesh/cfg_srv.c +++ b/subsys/bluetooth/host/mesh/cfg_srv.c @@ -1999,7 +1999,7 @@ static void net_key_update(struct bt_mesh_model *model, err = bt_mesh_net_keys_create(&sub->keys[1], buf->data); if (!err && (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) || IS_ENABLED(CONFIG_BT_MESH_FRIEND))) { - err = bt_mesh_friend_cred_update(ctx->net_idx, 1, buf->data); + err = friend_cred_update(sub); } if (err) { @@ -2608,7 +2608,7 @@ static void krp_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, bt_mesh_net_revoke_keys(sub); if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) || IS_ENABLED(CONFIG_BT_MESH_FRIEND)) { - bt_mesh_friend_cred_refresh(ctx->net_idx); + friend_cred_refresh(ctx->net_idx); } sub->kr_phase = BT_MESH_KR_NORMAL; sub->kr_flag = 0; diff --git a/subsys/bluetooth/host/mesh/friend.c b/subsys/bluetooth/host/mesh/friend.c index b9b0d4424ed..ef53cbd134e 100644 --- a/subsys/bluetooth/host/mesh/friend.c +++ b/subsys/bluetooth/host/mesh/friend.c @@ -160,7 +160,7 @@ static void friend_clear(struct bt_mesh_friend *frnd) k_delayed_work_cancel(&frnd->timer); - bt_mesh_friend_cred_del(bt_mesh.sub[0].net_idx, frnd->lpn); + friend_cred_del(frnd->net_idx, frnd->lpn); if (frnd->last) { net_buf_unref(frnd->last); @@ -325,9 +325,8 @@ static struct net_buf *create_friend_pdu(struct bt_mesh_friend *frnd, priv = sub->keys[sub->kr_flag].privacy; nid = sub->keys[sub->kr_flag].nid; } else { - if (bt_mesh_friend_cred_get(sub, frnd->lpn, &nid, &enc, - &priv)) { - BT_ERR("bt_mesh_friend_cred_get failed"); + if (friend_cred_get(sub, frnd->lpn, &nid, &enc, &priv)) { + BT_ERR("friend_cred_get failed"); goto failed; } } @@ -861,8 +860,7 @@ init_friend: k_delayed_work_submit(&frnd->timer, offer_delay(frnd, rx->rssi, msg->criteria)); - bt_mesh_friend_cred_add(sub->net_idx, sub->keys[0].net, 0, - frnd->lpn, frnd->lpn_counter, frnd->counter); + friend_cred_create(sub, frnd->lpn, frnd->lpn_counter, frnd->counter); enqueue_offer(frnd, rx->rssi); diff --git a/subsys/bluetooth/host/mesh/lpn.c b/subsys/bluetooth/host/mesh/lpn.c index ff56e59f70d..d010340a8c3 100644 --- a/subsys/bluetooth/host/mesh/lpn.c +++ b/subsys/bluetooth/host/mesh/lpn.c @@ -213,7 +213,7 @@ static void clear_friendship(bool force, bool disable) k_delayed_work_cancel(&lpn->timer); - bt_mesh_friend_cred_del(bt_mesh.sub[0].net_idx, lpn->frnd); + friend_cred_del(bt_mesh.sub[0].net_idx, lpn->frnd); if (lpn->clear_success) { lpn->old_friend = BT_MESH_ADDR_UNASSIGNED; @@ -482,7 +482,7 @@ int bt_mesh_lpn_friend_offer(struct bt_mesh_net_rx *rx, struct bt_mesh_ctl_friend_offer *msg = (void *)buf->data; struct bt_mesh_lpn *lpn = &bt_mesh.lpn; struct bt_mesh_subnet *sub = rx->sub; - struct bt_mesh_friend_cred *cred; + struct friend_cred *cred; u16_t frnd_counter; int err; @@ -509,22 +509,12 @@ int bt_mesh_lpn_friend_offer(struct bt_mesh_net_rx *rx, lpn->frnd = rx->ctx.addr; - cred = bt_mesh_friend_cred_add(sub->net_idx, sub->keys[0].net, 0, - lpn->frnd, lpn->counter, frnd_counter); + cred = friend_cred_create(sub, lpn->frnd, lpn->counter, frnd_counter); if (!cred) { lpn->frnd = BT_MESH_ADDR_UNASSIGNED; return -ENOMEM; } - if (sub->kr_flag) { - err = bt_mesh_friend_cred_set(cred, 1, sub->keys[1].net); - if (err) { - bt_mesh_friend_cred_clear(cred); - lpn->frnd = BT_MESH_ADDR_UNASSIGNED; - return err; - } - } - /* TODO: Add offer acceptance criteria check */ k_delayed_work_cancel(&lpn->timer); @@ -534,7 +524,7 @@ int bt_mesh_lpn_friend_offer(struct bt_mesh_net_rx *rx, err = send_friend_poll(); if (err) { - bt_mesh_friend_cred_clear(cred); + friend_cred_clear(cred); lpn->frnd = BT_MESH_ADDR_UNASSIGNED; lpn->recv_win = 0; lpn->queue_size = 0; diff --git a/subsys/bluetooth/host/mesh/net.c b/subsys/bluetooth/host/mesh/net.c index 8848811faea..9382dbbe58b 100644 --- a/subsys/bluetooth/host/mesh/net.c +++ b/subsys/bluetooth/host/mesh/net.c @@ -64,7 +64,7 @@ #endif #if FRIEND_CRED_COUNT > 0 -static struct bt_mesh_friend_cred friend_cred[FRIEND_CRED_COUNT]; +static struct friend_cred friend_cred[FRIEND_CRED_COUNT]; #endif static u64_t msg_cache[CONFIG_BT_MESH_MSG_CACHE_SIZE]; @@ -208,8 +208,7 @@ int bt_mesh_net_keys_create(struct bt_mesh_subnet_keys *keys, #if (defined(CONFIG_BT_MESH_LOW_POWER) || \ defined(CONFIG_BT_MESH_FRIEND)) -int bt_mesh_friend_cred_set(struct bt_mesh_friend_cred *cred, u8_t idx, - const u8_t net_key[16]) +int friend_cred_set(struct friend_cred *cred, u8_t idx, const u8_t net_key[16]) { u16_t lpn_addr, frnd_addr; int err; @@ -252,12 +251,12 @@ int bt_mesh_friend_cred_set(struct bt_mesh_friend_cred *cred, u8_t idx, return 0; } -void bt_mesh_friend_cred_refresh(u16_t net_idx) +void friend_cred_refresh(u16_t net_idx) { int i; for (i = 0; i < ARRAY_SIZE(friend_cred); i++) { - struct bt_mesh_friend_cred *cred = &friend_cred[i]; + struct friend_cred *cred = &friend_cred[i]; if (cred->addr != BT_MESH_ADDR_UNASSIGNED && cred->net_idx == net_idx) { @@ -267,21 +266,21 @@ void bt_mesh_friend_cred_refresh(u16_t net_idx) } } -int bt_mesh_friend_cred_update(u16_t net_idx, u8_t idx, const u8_t net_key[16]) +int friend_cred_update(struct bt_mesh_subnet *sub) { int err, i; - BT_DBG("net_idx 0x%04x idx %u", net_idx, idx); + BT_DBG("net_idx 0x%04x", sub->net_idx); for (i = 0; i < ARRAY_SIZE(friend_cred); i++) { - struct bt_mesh_friend_cred *cred = &friend_cred[i]; + struct friend_cred *cred = &friend_cred[i]; if (cred->addr == BT_MESH_ADDR_UNASSIGNED || - cred->net_idx != net_idx) { + cred->net_idx != sub->net_idx) { continue; } - err = bt_mesh_friend_cred_set(cred, idx, net_key); + err = friend_cred_set(cred, 1, sub->keys[1].net); if (err) { return err; } @@ -290,21 +289,18 @@ int bt_mesh_friend_cred_update(u16_t net_idx, u8_t idx, const u8_t net_key[16]) return 0; } -struct bt_mesh_friend_cred *bt_mesh_friend_cred_add(u16_t net_idx, - const u8_t net_key[16], - u8_t idx, u16_t addr, - u16_t lpn_counter, - u16_t frnd_counter) +struct friend_cred *friend_cred_create(struct bt_mesh_subnet *sub, u16_t addr, + u16_t lpn_counter, u16_t frnd_counter) { - struct bt_mesh_friend_cred *cred; + struct friend_cred *cred; int i, err; - BT_DBG("net_idx 0x%04x addr 0x%04x idx %u", net_idx, addr, idx); + BT_DBG("net_idx 0x%04x addr 0x%04x", sub->net_idx, addr); for (cred = NULL, i = 0; i < ARRAY_SIZE(friend_cred); i++) { if ((friend_cred[i].addr == BT_MESH_ADDR_UNASSIGNED) || (friend_cred[i].addr == addr && - friend_cred[i].net_idx == net_idx)) { + friend_cred[i].net_idx == sub->net_idx)) { cred = &friend_cred[i]; break; } @@ -315,21 +311,29 @@ struct bt_mesh_friend_cred *bt_mesh_friend_cred_add(u16_t net_idx, return NULL; } - cred->net_idx = net_idx; + cred->net_idx = sub->net_idx; cred->addr = addr; cred->lpn_counter = lpn_counter; cred->frnd_counter = frnd_counter; - err = bt_mesh_friend_cred_set(cred, idx, net_key); + err = friend_cred_set(cred, 0, sub->keys[0].net); if (err) { - bt_mesh_friend_cred_clear(cred); + friend_cred_clear(cred); return NULL; } + if (sub->kr_flag) { + err = friend_cred_set(cred, 1, sub->keys[1].net); + if (err) { + friend_cred_clear(cred); + return NULL; + } + } + return cred; } -void bt_mesh_friend_cred_clear(struct bt_mesh_friend_cred *cred) +void friend_cred_clear(struct friend_cred *cred) { cred->net_idx = BT_MESH_KEY_UNUSED; cred->addr = BT_MESH_ADDR_UNASSIGNED; @@ -338,15 +342,15 @@ void bt_mesh_friend_cred_clear(struct bt_mesh_friend_cred *cred) memset(cred->cred, 0, sizeof(cred->cred)); } -int bt_mesh_friend_cred_del(u16_t net_idx, u16_t addr) +int friend_cred_del(u16_t net_idx, u16_t addr) { int i; for (i = 0; i < ARRAY_SIZE(friend_cred); i++) { - struct bt_mesh_friend_cred *cred = &friend_cred[i]; + struct friend_cred *cred = &friend_cred[i]; if (cred->addr == addr && cred->net_idx == net_idx) { - bt_mesh_friend_cred_clear(cred); + friend_cred_clear(cred); return 0; } } @@ -354,15 +358,15 @@ int bt_mesh_friend_cred_del(u16_t net_idx, u16_t addr) return -ENOENT; } -int bt_mesh_friend_cred_get(struct bt_mesh_subnet *sub, u16_t addr, u8_t *nid, - const u8_t **enc, const u8_t **priv) +int friend_cred_get(struct bt_mesh_subnet *sub, u16_t addr, u8_t *nid, + const u8_t **enc, const u8_t **priv) { int i; BT_DBG("net_idx 0x%04x addr 0x%04x", sub->net_idx, addr); for (i = 0; i < ARRAY_SIZE(friend_cred); i++) { - struct bt_mesh_friend_cred *cred = &friend_cred[i]; + struct friend_cred *cred = &friend_cred[i]; if (cred->net_idx != sub->net_idx) { continue; @@ -390,8 +394,8 @@ int bt_mesh_friend_cred_get(struct bt_mesh_subnet *sub, u16_t addr, u8_t *nid, return -ENOENT; } #else -int bt_mesh_friend_cred_get(struct bt_mesh_subnet *sub, u16_t addr, u8_t *nid, - const u8_t **enc, const u8_t **priv) +int friend_cred_get(struct bt_mesh_subnet *sub, u16_t addr, u8_t *nid, + const u8_t **enc, const u8_t **priv) { return -ENOENT; } @@ -541,7 +545,7 @@ bool bt_mesh_kr_update(struct bt_mesh_subnet *sub, u8_t new_kr, bool new_key) bt_mesh_net_revoke_keys(sub); if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) || IS_ENABLED(CONFIG_BT_MESH_FRIEND)) { - bt_mesh_friend_cred_refresh(sub->net_idx); + friend_cred_refresh(sub->net_idx); } sub->kr_phase = BT_MESH_KR_NORMAL; return true; @@ -801,8 +805,8 @@ int bt_mesh_net_encode(struct bt_mesh_net_tx *tx, struct net_buf_simple *buf, } if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) && tx->friend_cred) { - if (bt_mesh_friend_cred_get(tx->sub, BT_MESH_ADDR_UNASSIGNED, - &nid, &enc, &priv)) { + if (friend_cred_get(tx->sub, BT_MESH_ADDR_UNASSIGNED, + &nid, &enc, &priv)) { BT_WARN("Falling back to master credentials"); tx->friend_cred = 0; @@ -993,7 +997,7 @@ static int friend_decrypt(struct bt_mesh_subnet *sub, const u8_t *data, BT_DBG("NID 0x%02x net_idx 0x%04x", NID(data), sub->net_idx); for (i = 0; i < ARRAY_SIZE(friend_cred); i++) { - struct bt_mesh_friend_cred *cred = &friend_cred[i]; + struct friend_cred *cred = &friend_cred[i]; if (cred->net_idx != sub->net_idx) { continue; diff --git a/subsys/bluetooth/host/mesh/net.h b/subsys/bluetooth/host/mesh/net.h index be1e12e19a5..31670c540ee 100644 --- a/subsys/bluetooth/host/mesh/net.h +++ b/subsys/bluetooth/host/mesh/net.h @@ -27,21 +27,6 @@ struct bt_mesh_app_key { } keys[2]; }; -/* Friendship Credentials */ -struct bt_mesh_friend_cred { - u16_t net_idx; - u16_t addr; - - u16_t lpn_counter; - u16_t frnd_counter; - - struct { - u8_t nid; /* NID */ - u8_t enc[16]; /* EncKey */ - u8_t privacy[16]; /* PrivacyKey */ - } cred[2]; -}; - struct bt_mesh_subnet { u32_t beacon_sent; /* Timestamp of last sent beacon */ u8_t beacons_last; /* Number of beacons during last @@ -279,21 +264,6 @@ int bt_mesh_net_create(u16_t idx, u8_t flags, const u8_t key[16], u8_t bt_mesh_net_flags(struct bt_mesh_subnet *sub); -int bt_mesh_friend_cred_get(struct bt_mesh_subnet *sub, u16_t addr, u8_t *nid, - const u8_t **enc, const u8_t **priv); -int bt_mesh_friend_cred_set(struct bt_mesh_friend_cred *cred, u8_t idx, - const u8_t net_key[16]); -void bt_mesh_friend_cred_refresh(u16_t net_idx); -int bt_mesh_friend_cred_update(u16_t net_idx, u8_t idx, - const u8_t net_key[16]); -struct bt_mesh_friend_cred *bt_mesh_friend_cred_add(u16_t net_idx, - const u8_t net_key[16], - u8_t idx, u16_t addr, - u16_t lpn_counter, - u16_t frnd_counter); -void bt_mesh_friend_cred_clear(struct bt_mesh_friend_cred *cred); -int bt_mesh_friend_cred_del(u16_t net_idx, u16_t addr); - bool bt_mesh_kr_update(struct bt_mesh_subnet *sub, u8_t new_kr, bool new_key); void bt_mesh_net_revoke_keys(struct bt_mesh_subnet *sub); @@ -327,3 +297,28 @@ void bt_mesh_net_recv(struct net_buf_simple *data, s8_t rssi, enum bt_mesh_net_if net_if); void bt_mesh_net_init(void); + +/* Friendship Credential Management */ +struct friend_cred { + u16_t net_idx; + u16_t addr; + + u16_t lpn_counter; + u16_t frnd_counter; + + struct { + u8_t nid; /* NID */ + u8_t enc[16]; /* EncKey */ + u8_t privacy[16]; /* PrivacyKey */ + } cred[2]; +}; + +int friend_cred_get(struct bt_mesh_subnet *sub, u16_t addr, u8_t *nid, + const u8_t **enc, const u8_t **priv); +int friend_cred_set(struct friend_cred *cred, u8_t idx, const u8_t net_key[16]); +void friend_cred_refresh(u16_t net_idx); +int friend_cred_update(struct bt_mesh_subnet *sub); +struct friend_cred *friend_cred_create(struct bt_mesh_subnet *sub, u16_t addr, + u16_t lpn_counter, u16_t frnd_counter); +void friend_cred_clear(struct friend_cred *cred); +int friend_cred_del(u16_t net_idx, u16_t addr);