2019-02-06 07:38:51

by Stotland, Inga

[permalink] [raw]
Subject: [PATCH BlueZ 2/5] mesh: Add function to restore net key state from storage

This creates subnet state based on saved network key state:
current keys and, if present, updated keys.
Secure network beacon is generated according to key refresh phase.
---
mesh/net.c | 90 ++++++++++++++++++++++++++++++++++++++++++++------
mesh/net.h | 2 ++
mesh/storage.c | 6 +---
3 files changed, 82 insertions(+), 16 deletions(-)

diff --git a/mesh/net.c b/mesh/net.c
index bfc1a01bb..cf7603053 100644
--- a/mesh/net.c
+++ b/mesh/net.c
@@ -970,20 +970,10 @@ int mesh_net_del_key(struct mesh_net *net, uint16_t idx)
return MESH_STATUS_SUCCESS;
}

-int mesh_net_add_key(struct mesh_net *net, uint16_t idx, const uint8_t *value)
+static int add_key(struct mesh_net *net, uint16_t idx, const uint8_t *value)
{
struct mesh_subnet *subnet;

- subnet = l_queue_find(net->subnets, match_key_index,
- L_UINT_TO_PTR(idx));
-
- if (subnet) {
- if (net_key_confirm(subnet->net_key_cur, value))
- return MESH_STATUS_SUCCESS;
- else
- return MESH_STATUS_IDX_ALREADY_STORED;
- }
-
subnet = subnet_new(net, idx);
if (!subnet)
return MESH_STATUS_INSUFF_RESOURCES;
@@ -1000,6 +990,32 @@ int mesh_net_add_key(struct mesh_net *net, uint16_t idx, const uint8_t *value)
return MESH_STATUS_INSUFF_RESOURCES;
}

+ return MESH_STATUS_SUCCESS;
+}
+
+/*
+ * This function is called when Configuration Server Model receives
+ * a NETKEY_ADD command
+ */
+int mesh_net_add_key(struct mesh_net *net, uint16_t idx, const uint8_t *value)
+{
+ struct mesh_subnet *subnet;
+ int status;
+
+ subnet = l_queue_find(net->subnets, match_key_index,
+ L_UINT_TO_PTR(idx));
+
+ if (subnet) {
+ if (net_key_confirm(subnet->net_key_cur, value))
+ return MESH_STATUS_SUCCESS;
+ else
+ return MESH_STATUS_IDX_ALREADY_STORED;
+ }
+
+ status = add_key(net, idx, value);
+ if (status != MESH_STATUS_SUCCESS)
+ return status;
+
if (!storage_net_key_add(net, idx, value,
KEY_REFRESH_PHASE_NONE)) {
l_queue_remove(net->subnets, subnet);
@@ -2923,6 +2939,54 @@ bool mesh_net_set_beacon_mode(struct mesh_net *net, bool enable)
return true;
}

+/* This function is called when network keys are restored from storage. */
+bool mesh_net_set_key(struct mesh_net *net, uint16_t idx, const uint8_t *key,
+ const uint8_t *new_key, uint8_t phase)
+{
+ struct mesh_subnet *subnet;
+ int status;
+
+ subnet = l_queue_find(net->subnets, match_key_index,
+ L_UINT_TO_PTR(idx));
+ if (subnet)
+ return false;
+
+ /* Current key must be always present */
+ if (!key)
+ return false;
+
+ /* If key refresh is in progress, a new key must be present */
+ if (phase != KEY_REFRESH_PHASE_NONE && !new_key)
+ return false;
+
+ status = add_key(net, idx, key);
+ if (status != MESH_STATUS_SUCCESS)
+ return false;
+
+ subnet = l_queue_find(net->subnets, match_key_index,
+ L_UINT_TO_PTR(idx));
+ if (!subnet)
+ return false;
+
+ if (new_key)
+ subnet->net_key_upd = net_key_add(new_key);
+
+ /* Preserve key refresh state to generate secure beacon flags*/
+ if (phase == KEY_REFRESH_PHASE_TWO) {
+ subnet->key_refresh = 1;
+ subnet->net_key_tx = subnet->net_key_upd;
+ }
+
+ subnet->kr_phase = phase;
+
+ set_network_beacon(subnet, net);
+
+ if (net->io)
+ start_network_beacon(subnet, net);
+
+ return true;
+}
+
static bool is_this_net(const void *a, const void *b)
{
return a == b;
@@ -3556,6 +3620,10 @@ uint8_t mesh_net_key_refresh_phase_get(struct mesh_net *net, uint16_t idx,
return MESH_STATUS_SUCCESS;
}

+/*
+ * This function is called when Configuration Server Model receives
+ * a NETKEY_UPDATE command
+ */
int mesh_net_update_key(struct mesh_net *net, uint16_t idx,
const uint8_t *value)
{
diff --git a/mesh/net.h b/mesh/net.h
index b27a4e614..591a6898e 100644
--- a/mesh/net.h
+++ b/mesh/net.h
@@ -284,6 +284,8 @@ int mesh_net_add_key(struct mesh_net *net, uint16_t net_idx,
const uint8_t *key);
int mesh_net_update_key(struct mesh_net *net, uint16_t net_idx,
const uint8_t *key);
+bool mesh_net_set_key(struct mesh_net *net, uint16_t idx, const uint8_t *key,
+ const uint8_t *new_key, uint8_t phase);
uint32_t mesh_net_get_iv_index(struct mesh_net *net);
void mesh_net_get_snb_state(struct mesh_net *net,
uint8_t *flags, uint32_t *iv_index);
diff --git a/mesh/storage.c b/mesh/storage.c
index 1b52000b0..84f7c6161 100644
--- a/mesh/storage.c
+++ b/mesh/storage.c
@@ -120,11 +120,7 @@ static bool read_net_keys_cb(uint16_t idx, uint8_t *key, uint8_t *new_key,
if (!net)
return false;

- if (mesh_net_add_key(net, idx, key) != MESH_STATUS_SUCCESS)
- return false;
- /* TODO: handle restoring key refresh phase and new keys */
-
- return true;
+ return mesh_net_set_key(net, idx, key, new_key, phase);
}

static bool read_app_keys_cb(uint16_t net_idx, uint16_t app_idx, uint8_t *key,
--
2.17.2