Bluetooth: Mesh: Isolate cryptographic material

This is a major refactoring of the handling of the cryptographic
material of both the network and transport layers. The aim is to
encapsulate the key object manipulation, and improve overall modularity.

Pulls Applications and Subnets out of the bt_mesh and into separate
modules, with static storage types on the data. This has several
side-effects:
- The Config Server no longer operates directly on the bt_mesh.subs and
  bt_mesh.apps lists, but goes through a public configuration interface,
  following the pattern set in #27908.
- All iteration through the keys is done through iteration APIs
- Key resolution on RX and TX is centralized.
- Changes to the keys triggers events the other modules can register
  handlers for.
- Friendship credentials are stored in the lpn and friend structures.

Part of #27842.

Signed-off-by: Trond Einar Snekvik <Trond.Einar.Snekvik@nordicsemi.no>
This commit is contained in:
Trond Einar Snekvik 2020-08-25 11:03:42 +02:00 committed by Johan Hedberg
commit eca0141152
30 changed files with 2611 additions and 2100 deletions

View file

@ -179,22 +179,6 @@ static struct bt_mesh_model *get_model(struct bt_mesh_elem *elem,
}
}
static bool app_key_is_valid(uint16_t app_idx)
{
int i;
for (i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) {
struct bt_mesh_app_key *key = &bt_mesh.app_keys[i];
if (key->net_idx != BT_MESH_KEY_UNUSED &&
key->app_idx == app_idx) {
return true;
}
}
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)
@ -235,7 +219,7 @@ 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)) {
if (!bt_mesh_app_key_exists(app_idx)) {
return STATUS_INVALID_APPKEY;
}
@ -283,7 +267,7 @@ static uint8_t mod_bind(struct bt_mesh_model *model, uint16_t key_idx)
BT_DBG("model %p key_idx 0x%03x", model, key_idx);
if (!app_key_is_valid(key_idx)) {
if (!bt_mesh_app_key_exists(key_idx)) {
return STATUS_INVALID_APPKEY;
}
@ -315,7 +299,7 @@ static uint8_t mod_unbind(struct bt_mesh_model *model, uint16_t key_idx, bool st
BT_DBG("model %p key_idx 0x%03x store %u", model, key_idx, store);
if (!app_key_is_valid(key_idx)) {
if (!bt_mesh_app_key_exists(key_idx)) {
return STATUS_INVALID_APPKEY;
}
@ -339,115 +323,26 @@ static uint8_t mod_unbind(struct bt_mesh_model *model, uint16_t key_idx, bool st
return STATUS_SUCCESS;
}
struct bt_mesh_app_key *bt_mesh_app_key_alloc(uint16_t app_idx)
static void send_app_key_status(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
uint8_t status,
uint16_t app_idx, uint16_t net_idx)
{
int i;
BT_MESH_MODEL_BUF_DEFINE(msg, OP_APP_KEY_STATUS, 4);
for (i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) {
struct bt_mesh_app_key *key = &bt_mesh.app_keys[i];
bt_mesh_model_msg_init(&msg, OP_APP_KEY_STATUS);
net_buf_simple_add_u8(&msg, status);
key_idx_pack(&msg, net_idx, app_idx);
if (key->net_idx == BT_MESH_KEY_UNUSED) {
return key;
}
if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
BT_ERR("Unable to send App Key Status response");
}
return NULL;
}
static uint8_t app_key_set(uint16_t net_idx, uint16_t app_idx, const uint8_t val[16],
bool update)
{
struct bt_mesh_app_keys *keys;
struct bt_mesh_app_key *key;
struct bt_mesh_subnet *sub;
BT_DBG("net_idx 0x%04x app_idx %04x update %u val %s",
net_idx, app_idx, update, bt_hex(val, 16));
sub = bt_mesh_subnet_get(net_idx);
if (!sub) {
return STATUS_INVALID_NETKEY;
}
key = bt_mesh_app_key_find(app_idx);
if (update) {
if (!key) {
return STATUS_INVALID_APPKEY;
}
if (key->net_idx != net_idx) {
return STATUS_INVALID_BINDING;
}
keys = &key->keys[1];
/* The AppKey Update message shall generate an error when node
* is in normal operation, Phase 2, or Phase 3 or in Phase 1
* when the AppKey Update message on a valid AppKeyIndex when
* the AppKey value is different.
*/
if (sub->kr_phase != BT_MESH_KR_PHASE_1) {
return STATUS_CANNOT_UPDATE;
}
if (key->updated) {
if (memcmp(keys->val, val, 16)) {
return STATUS_CANNOT_UPDATE;
} else {
return STATUS_SUCCESS;
}
}
key->updated = true;
} else {
if (key) {
if (key->net_idx == net_idx &&
!memcmp(key->keys[0].val, val, 16)) {
return STATUS_SUCCESS;
}
if (key->net_idx == net_idx) {
return STATUS_IDX_ALREADY_STORED;
} else {
return STATUS_INVALID_NETKEY;
}
}
key = bt_mesh_app_key_alloc(app_idx);
if (!key) {
return STATUS_INSUFF_RESOURCES;
}
keys = &key->keys[0];
}
if (bt_mesh_app_id(val, &keys->id)) {
if (update) {
key->updated = false;
}
return STATUS_STORAGE_FAIL;
}
BT_DBG("app_idx 0x%04x AID 0x%02x", app_idx, keys->id);
key->net_idx = net_idx;
key->app_idx = app_idx;
memcpy(keys->val, val, 16);
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
BT_DBG("Storing AppKey persistently");
bt_mesh_store_app_key(key);
}
return STATUS_SUCCESS;
}
static void app_key_add(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
BT_MESH_MODEL_BUF_DEFINE(msg, OP_APP_KEY_STATUS, 4);
uint16_t key_net_idx, key_app_idx;
uint8_t status;
@ -455,24 +350,15 @@ static void app_key_add(struct bt_mesh_model *model,
BT_DBG("AppIdx 0x%04x NetIdx 0x%04x", key_app_idx, key_net_idx);
bt_mesh_model_msg_init(&msg, OP_APP_KEY_STATUS);
status = bt_mesh_app_key_add(key_app_idx, key_net_idx, buf->data);
status = app_key_set(key_net_idx, key_app_idx, buf->data, false);
BT_DBG("status 0x%02x", status);
net_buf_simple_add_u8(&msg, status);
key_idx_pack(&msg, key_net_idx, key_app_idx);
if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
BT_ERR("Unable to send App Key Status response");
}
send_app_key_status(model, ctx, status, key_app_idx, key_net_idx);
}
static void app_key_update(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
BT_MESH_MODEL_BUF_DEFINE(msg, OP_APP_KEY_STATUS, 4);
uint16_t key_net_idx, key_app_idx;
uint8_t status;
@ -480,93 +366,45 @@ static void app_key_update(struct bt_mesh_model *model,
BT_DBG("AppIdx 0x%04x NetIdx 0x%04x", key_app_idx, key_net_idx);
bt_mesh_model_msg_init(&msg, OP_APP_KEY_STATUS);
status = app_key_set(key_net_idx, key_app_idx, buf->data, true);
status = bt_mesh_app_key_update(key_app_idx, key_net_idx, buf->data);
BT_DBG("status 0x%02x", status);
net_buf_simple_add_u8(&msg, status);
key_idx_pack(&msg, key_net_idx, key_app_idx);
send_app_key_status(model, ctx, status, key_app_idx, key_net_idx);
}
if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
BT_ERR("Unable to send App Key Status response");
static void mod_app_key_del(struct bt_mesh_model *mod,
struct bt_mesh_elem *elem, bool vnd, bool primary,
void *user_data)
{
uint16_t *app_idx = user_data;
mod_unbind(mod, *app_idx, true);
}
static void app_key_evt(uint16_t app_idx, uint16_t net_idx,
enum bt_mesh_key_evt evt)
{
if (evt == BT_MESH_KEY_DELETED) {
bt_mesh_model_foreach(&mod_app_key_del, &app_idx);
}
}
struct unbind_data {
uint16_t app_idx;
bool store;
};
static void _mod_unbind(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
bool vnd, bool primary, void *user_data)
{
struct unbind_data *data = user_data;
mod_unbind(mod, data->app_idx, data->store);
}
void bt_mesh_app_key_del(struct bt_mesh_app_key *key, bool store)
{
struct unbind_data data = { .app_idx = key->app_idx, .store = store };
BT_DBG("AppIdx 0x%03x store %u", key->app_idx, store);
bt_mesh_model_foreach(_mod_unbind, &data);
if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
bt_mesh_clear_app_key(key);
}
key->net_idx = BT_MESH_KEY_UNUSED;
(void)memset(key->keys, 0, sizeof(key->keys));
}
BT_MESH_APP_KEY_CB_DEFINE(app_key_evt);
static void app_key_del(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
BT_MESH_MODEL_BUF_DEFINE(msg, OP_APP_KEY_STATUS, 4);
uint16_t key_net_idx, key_app_idx;
struct bt_mesh_app_key *key;
uint8_t status;
key_idx_unpack(buf, &key_net_idx, &key_app_idx);
BT_DBG("AppIdx 0x%04x NetIdx 0x%04x", key_app_idx, key_net_idx);
if (!bt_mesh_subnet_get(key_net_idx)) {
status = STATUS_INVALID_NETKEY;
goto send_status;
}
status = bt_mesh_app_key_del(key_net_idx, key_net_idx);
key = bt_mesh_app_key_find(key_app_idx);
if (!key) {
/* Treat as success since the client might have missed a
* previous response and is resending the request.
*/
status = STATUS_SUCCESS;
goto send_status;
}
if (key->net_idx != key_net_idx) {
status = STATUS_INVALID_BINDING;
goto send_status;
}
bt_mesh_app_key_del(key, true);
status = STATUS_SUCCESS;
send_status:
bt_mesh_model_msg_init(&msg, OP_APP_KEY_STATUS);
net_buf_simple_add_u8(&msg, status);
key_idx_pack(&msg, key_net_idx, key_app_idx);
if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
BT_ERR("Unable to send App Key Status response");
}
send_app_key_status(model, ctx, status, key_app_idx, key_net_idx);
}
/* Index list length: 3 bytes for every pair and 2 bytes for an odd idx */
@ -578,8 +416,11 @@ static void app_key_get(struct bt_mesh_model *model,
{
BT_MESH_MODEL_BUF_DEFINE(msg, OP_APP_KEY_LIST,
3 + IDX_LEN(CONFIG_BT_MESH_APP_KEY_COUNT));
uint16_t get_idx, i, prev;
uint16_t app_idx[CONFIG_BT_MESH_APP_KEY_COUNT];
uint16_t get_idx;
uint8_t status;
ssize_t count;
int i;
get_idx = net_buf_simple_pull_le16(buf);
if (get_idx > 0xfff) {
@ -591,7 +432,7 @@ static void app_key_get(struct bt_mesh_model *model,
bt_mesh_model_msg_init(&msg, OP_APP_KEY_LIST);
if (!bt_mesh_subnet_get(get_idx)) {
if (!bt_mesh_subnet_exists(get_idx)) {
status = STATUS_INVALID_NETKEY;
} else {
status = STATUS_SUCCESS;
@ -604,25 +445,17 @@ static void app_key_get(struct bt_mesh_model *model,
goto send_status;
}
prev = BT_MESH_KEY_UNUSED;
for (i = 0U; i < ARRAY_SIZE(bt_mesh.app_keys); i++) {
struct bt_mesh_app_key *key = &bt_mesh.app_keys[i];
if (key->net_idx != get_idx) {
continue;
}
if (prev == BT_MESH_KEY_UNUSED) {
prev = key->app_idx;
continue;
}
key_idx_pack(&msg, prev, key->app_idx);
prev = BT_MESH_KEY_UNUSED;
count = bt_mesh_app_keys_get(get_idx, app_idx, ARRAY_SIZE(app_idx), 0);
if (count < 0 || count > ARRAY_SIZE(app_idx)) {
count = ARRAY_SIZE(app_idx);
}
if (prev != BT_MESH_KEY_UNUSED) {
net_buf_simple_add_le16(&msg, prev);
for (i = 0; i < count - 1; i += 2) {
key_idx_pack(&msg, app_idx[i], app_idx[i + 1]);
}
if (i < count) {
net_buf_simple_add_le16(&msg, app_idx[i]);
}
send_status:
@ -2122,9 +1955,8 @@ static void net_key_add(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
struct bt_mesh_subnet *sub;
uint8_t status;
uint16_t idx;
int err;
idx = net_buf_simple_pull_le16(buf);
if (idx > 0xfff) {
@ -2134,72 +1966,17 @@ static void net_key_add(struct bt_mesh_model *model,
BT_DBG("idx 0x%04x", idx);
sub = bt_mesh_subnet_get(idx);
if (!sub) {
int i;
status = bt_mesh_subnet_add(idx, buf->data);
for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
if (bt_mesh.sub[i].net_idx == BT_MESH_KEY_UNUSED) {
sub = &bt_mesh.sub[i];
break;
}
}
if (!sub) {
send_net_key_status(model, ctx, idx,
STATUS_INSUFF_RESOURCES);
return;
}
}
/* Check for already existing subnet */
if (sub->net_idx == idx) {
uint8_t status;
if (memcmp(buf->data, sub->keys[0].net, 16)) {
status = STATUS_IDX_ALREADY_STORED;
} else {
status = STATUS_SUCCESS;
}
send_net_key_status(model, ctx, idx, status);
return;
}
err = bt_mesh_net_keys_create(&sub->keys[0], buf->data);
if (err) {
send_net_key_status(model, ctx, idx, STATUS_UNSPECIFIED);
return;
}
sub->net_idx = idx;
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
BT_DBG("Storing NetKey persistently");
bt_mesh_store_subnet(sub);
}
/* Make sure we have valid beacon data to be sent */
bt_mesh_net_beacon_update(sub);
if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
sub->node_id = BT_MESH_NODE_IDENTITY_STOPPED;
bt_mesh_proxy_beacon_send(sub);
bt_mesh_adv_update();
} else {
sub->node_id = BT_MESH_NODE_IDENTITY_NOT_SUPPORTED;
}
send_net_key_status(model, ctx, idx, STATUS_SUCCESS);
send_net_key_status(model, ctx, idx, status);
}
static void net_key_update(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
struct bt_mesh_subnet *sub;
uint8_t status;
uint16_t idx;
int err;
idx = net_buf_simple_pull_le16(buf);
if (idx > 0xfff) {
@ -2207,59 +1984,9 @@ static void net_key_update(struct bt_mesh_model *model,
return;
}
BT_DBG("idx 0x%04x", idx);
status = bt_mesh_subnet_update(idx, buf->data);
sub = bt_mesh_subnet_get(idx);
if (!sub) {
send_net_key_status(model, ctx, idx, STATUS_INVALID_NETKEY);
return;
}
/* The node shall successfully process a NetKey Update message on a
* valid NetKeyIndex when the NetKey value is different and the Key
* Refresh procedure has not been started, or when the NetKey value is
* the same in Phase 1. The NetKey Update message shall generate an
* error when the node is in Phase 2, or Phase 3.
*/
switch (sub->kr_phase) {
case BT_MESH_KR_NORMAL:
if (!memcmp(buf->data, sub->keys[0].net, 16)) {
return;
}
break;
case BT_MESH_KR_PHASE_1:
if (!memcmp(buf->data, sub->keys[1].net, 16)) {
send_net_key_status(model, ctx, idx, STATUS_SUCCESS);
return;
}
__fallthrough;
case BT_MESH_KR_PHASE_2:
case BT_MESH_KR_PHASE_3:
send_net_key_status(model, ctx, idx, STATUS_CANNOT_UPDATE);
return;
}
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 = friend_cred_update(sub);
}
if (err) {
send_net_key_status(model, ctx, idx, STATUS_UNSPECIFIED);
return;
}
sub->kr_phase = BT_MESH_KR_PHASE_1;
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
BT_DBG("Storing NetKey persistently");
bt_mesh_store_subnet(sub);
}
bt_mesh_net_beacon_update(sub);
send_net_key_status(model, ctx, idx, STATUS_SUCCESS);
send_net_key_status(model, ctx, idx, status);
}
static void hb_pub_disable(struct bt_mesh_cfg_srv *cfg)
@ -2278,9 +2005,7 @@ static void net_key_del(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
struct bt_mesh_subnet *sub;
uint16_t del_idx;
uint8_t status;
del_idx = net_buf_simple_pull_le16(buf);
if (del_idx > 0xfff) {
@ -2290,28 +2015,18 @@ static void net_key_del(struct bt_mesh_model *model,
BT_DBG("idx 0x%04x", del_idx);
sub = bt_mesh_subnet_get(del_idx);
if (!sub) {
/* This could be a retry of a previous attempt that had its
* response lost, so pretend that it was a success.
*/
status = STATUS_SUCCESS;
goto send_status;
}
/* The key that the message was encrypted with cannot be removed.
* The NetKey List must contain a minimum of one NetKey.
*/
if (ctx->net_idx == del_idx) {
status = STATUS_CANNOT_REMOVE;
goto send_status;
send_net_key_status(model, ctx, del_idx,
STATUS_CANNOT_REMOVE);
return;
}
bt_mesh_subnet_del(sub, true);
status = STATUS_SUCCESS;
bt_mesh_subnet_del(del_idx);
send_status:
send_net_key_status(model, ctx, del_idx, status);
send_net_key_status(model, ctx, del_idx, STATUS_SUCCESS);
}
static void net_key_get(struct bt_mesh_model *model,
@ -2320,29 +2035,23 @@ static void net_key_get(struct bt_mesh_model *model,
{
BT_MESH_MODEL_BUF_DEFINE(msg, OP_NET_KEY_LIST,
IDX_LEN(CONFIG_BT_MESH_SUBNET_COUNT));
uint16_t prev, i;
uint16_t net_idx[CONFIG_BT_MESH_SUBNET_COUNT];
ssize_t count;
int i;
bt_mesh_model_msg_init(&msg, OP_NET_KEY_LIST);
prev = BT_MESH_KEY_UNUSED;
for (i = 0U; i < ARRAY_SIZE(bt_mesh.sub); i++) {
struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
if (sub->net_idx == BT_MESH_KEY_UNUSED) {
continue;
}
if (prev == BT_MESH_KEY_UNUSED) {
prev = sub->net_idx;
continue;
}
key_idx_pack(&msg, prev, sub->net_idx);
prev = BT_MESH_KEY_UNUSED;
count = bt_mesh_subnets_get(net_idx, ARRAY_SIZE(net_idx), 0);
if (count < 0 || count > ARRAY_SIZE(net_idx)) {
count = ARRAY_SIZE(net_idx);
}
if (prev != BT_MESH_KEY_UNUSED) {
net_buf_simple_add_le16(&msg, prev);
for (i = 0; i < count - 1; i += 2) {
key_idx_pack(&msg, net_idx[i], net_idx[i + 1]);
}
if (i < count) {
net_buf_simple_add_le16(&msg, net_idx[i]);
}
if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
@ -2350,13 +2059,29 @@ static void net_key_get(struct bt_mesh_model *model,
}
}
static void send_node_id_status(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
uint8_t status,
uint16_t net_idx, uint8_t node_id)
{
BT_MESH_MODEL_BUF_DEFINE(msg, OP_NODE_IDENTITY_STATUS, 4);
bt_mesh_model_msg_init(&msg, OP_NODE_IDENTITY_STATUS);
net_buf_simple_add_u8(&msg, status);
net_buf_simple_add_le16(&msg, net_idx);
net_buf_simple_add_u8(&msg, node_id);
if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
BT_ERR("Unable to send Node Identity Status");
}
}
static void node_identity_get(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
BT_MESH_MODEL_BUF_DEFINE(msg, OP_NODE_IDENTITY_STATUS, 4);
struct bt_mesh_subnet *sub;
uint8_t node_id;
enum bt_mesh_feat_state node_id;
uint8_t status;
uint16_t idx;
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
@ -2369,32 +2094,16 @@ static void node_identity_get(struct bt_mesh_model *model,
return;
}
bt_mesh_model_msg_init(&msg, OP_NODE_IDENTITY_STATUS);
status = bt_mesh_subnet_node_id_get(idx, &node_id);
sub = bt_mesh_subnet_get(idx);
if (!sub) {
net_buf_simple_add_u8(&msg, STATUS_INVALID_NETKEY);
node_id = 0x00;
} else {
net_buf_simple_add_u8(&msg, STATUS_SUCCESS);
node_id = sub->node_id;
}
net_buf_simple_add_le16(&msg, idx);
net_buf_simple_add_u8(&msg, node_id);
if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
BT_ERR("Unable to send Node Identity Status");
}
send_node_id_status(model, ctx, status, idx, node_id);
}
static void node_identity_set(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
BT_MESH_MODEL_BUF_DEFINE(msg, OP_NODE_IDENTITY_STATUS, 4);
struct bt_mesh_subnet *sub;
uint8_t node_id;
uint8_t node_id, status;
uint16_t idx;
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
@ -2413,32 +2122,21 @@ static void node_identity_set(struct bt_mesh_model *model,
return;
}
bt_mesh_model_msg_init(&msg, OP_NODE_IDENTITY_STATUS);
sub = bt_mesh_subnet_get(idx);
if (!sub) {
net_buf_simple_add_u8(&msg, STATUS_INVALID_NETKEY);
net_buf_simple_add_le16(&msg, idx);
net_buf_simple_add_u8(&msg, node_id);
} else {
net_buf_simple_add_u8(&msg, STATUS_SUCCESS);
net_buf_simple_add_le16(&msg, idx);
if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
if (node_id) {
bt_mesh_proxy_identity_start(sub);
} else {
bt_mesh_proxy_identity_stop(sub);
}
bt_mesh_adv_update();
}
net_buf_simple_add_u8(&msg, sub->node_id);
status = bt_mesh_subnet_node_id_set(idx, node_id);
if (status == STATUS_INVALID_NETKEY) {
send_node_id_status(model, ctx, status, idx,
BT_MESH_NODE_IDENTITY_STOPPED);
return;
}
if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
BT_ERR("Unable to send Node Identity Status");
if (status == STATUS_FEAT_NOT_SUPP) {
/* Should return success, even if feature isn't supported: */
send_node_id_status(model, ctx, STATUS_SUCCESS, idx,
BT_MESH_NODE_IDENTITY_NOT_SUPPORTED);
return;
}
send_node_id_status(model, ctx, status, idx, node_id);
}
static void create_mod_app_status(struct net_buf_simple *msg,
@ -2727,7 +2425,7 @@ static void friend_set(struct bt_mesh_model *model,
}
if (cfg->frnd == BT_MESH_FRIEND_DISABLED) {
bt_mesh_friend_clear_net_idx(BT_MESH_KEY_ANY);
bt_mesh_friends_clear();
}
}
@ -2802,7 +2500,7 @@ static void send_krp_status(struct bt_mesh_model *model,
static void krp_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
struct bt_mesh_subnet *sub;
uint8_t kr_phase, status;
uint16_t idx;
idx = net_buf_simple_pull_le16(buf);
@ -2813,20 +2511,15 @@ static void krp_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
BT_DBG("idx 0x%04x", idx);
sub = bt_mesh_subnet_get(idx);
if (!sub) {
send_krp_status(model, ctx, idx, 0x00, STATUS_INVALID_NETKEY);
} else {
send_krp_status(model, ctx, idx, sub->kr_phase,
STATUS_SUCCESS);
}
status = bt_mesh_subnet_kr_phase_get(idx, &kr_phase);
send_krp_status(model, ctx, idx, kr_phase, status);
}
static void krp_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
struct bt_mesh_subnet *sub;
uint8_t phase;
uint8_t phase, status;
uint16_t idx;
idx = net_buf_simple_pull_le16(buf);
@ -2837,48 +2530,13 @@ static void krp_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
return;
}
BT_DBG("idx 0x%04x transition 0x%02x", idx, phase);
sub = bt_mesh_subnet_get(idx);
if (!sub) {
send_krp_status(model, ctx, idx, 0x00, STATUS_INVALID_NETKEY);
status = bt_mesh_subnet_kr_phase_set(idx, &phase);
if (status == STATUS_CANNOT_UPDATE) {
BT_ERR("Invalid kr phase transition 0x%02x", phase);
return;
}
BT_DBG("%u -> %u", sub->kr_phase, phase);
if (phase < BT_MESH_KR_PHASE_2 || phase > BT_MESH_KR_PHASE_3 ||
(sub->kr_phase == BT_MESH_KR_NORMAL &&
phase == BT_MESH_KR_PHASE_2)) {
BT_WARN("Prohibited transition %u -> %u", sub->kr_phase, phase);
return;
}
if (sub->kr_phase == BT_MESH_KR_PHASE_1 &&
phase == BT_MESH_KR_PHASE_2) {
sub->kr_phase = BT_MESH_KR_PHASE_2;
sub->kr_flag = 1;
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
BT_DBG("Storing krp phase persistently");
bt_mesh_store_subnet(sub);
}
bt_mesh_net_beacon_update(sub);
} else if ((sub->kr_phase == BT_MESH_KR_PHASE_1 ||
sub->kr_phase == BT_MESH_KR_PHASE_2) &&
phase == BT_MESH_KR_PHASE_3) {
bt_mesh_net_revoke_keys(sub);
if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) ||
IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
friend_cred_refresh(ctx->net_idx);
}
sub->kr_phase = BT_MESH_KR_NORMAL;
sub->kr_flag = 0;
bt_mesh_net_beacon_update(sub);
}
send_krp_status(model, ctx, idx, sub->kr_phase, STATUS_SUCCESS);
send_krp_status(model, ctx, idx, phase, status);
}
static uint8_t hb_log(uint16_t val)
@ -3382,7 +3040,6 @@ static void mod_reset(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
void bt_mesh_cfg_reset(void)
{
struct bt_mesh_cfg_srv *cfg = conf;
int i;
BT_DBG("");
@ -3392,17 +3049,6 @@ void bt_mesh_cfg_reset(void)
cfg->hb_sub.dst = BT_MESH_ADDR_UNASSIGNED;
cfg->hb_sub.expiry = 0;
/* Delete all net keys, which also takes care of all app keys which
* are associated with each net key.
*/
for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
if (sub->net_idx != BT_MESH_KEY_UNUSED) {
bt_mesh_subnet_del(sub, true);
}
}
bt_mesh_model_foreach(mod_reset, NULL);
(void)memset(labels, 0, sizeof(labels));
@ -3535,40 +3181,3 @@ struct bt_mesh_cfg_srv *bt_mesh_cfg_get(void)
{
return conf;
}
void bt_mesh_subnet_del(struct bt_mesh_subnet *sub, bool store)
{
int i;
BT_DBG("NetIdx 0x%03x store %u", sub->net_idx, store);
if (conf->hb_pub.net_idx == sub->net_idx) {
hb_pub_disable(conf);
if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
bt_mesh_store_hb_pub();
}
}
/* Delete any app keys bound to this NetKey index */
for (i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) {
struct bt_mesh_app_key *key = &bt_mesh.app_keys[i];
if (key->net_idx == sub->net_idx) {
bt_mesh_app_key_del(key, store);
}
}
if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
bt_mesh_friend_clear_net_idx(sub->net_idx);
}
bt_mesh_net_loopback_clear(sub->net_idx);
if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
bt_mesh_clear_subnet(sub);
}
(void)memset(sub, 0, sizeof(*sub));
sub->net_idx = BT_MESH_KEY_UNUSED;
}