* [PATCH BlueZ 0/2] Central Net Key storage cache for multiple Nodes
@ 2018-09-19 20:40 Brian Gix
2018-09-19 20:40 ` [PATCH BlueZ 1/2] mesh: Add centralized caching Net Key management Brian Gix
2018-09-19 20:40 ` [PATCH BlueZ 2/2] mesh: Refactor friend.c and net.c for central key DB Brian Gix
0 siblings, 2 replies; 3+ messages in thread
From: Brian Gix @ 2018-09-19 20:40 UTC (permalink / raw)
To: linux-bluetooth; +Cc: marcel, johan.hedberg, inga.stotland, Brian Gix
The strategy for Bluetooth Mesh is to allow each application that want to use
mesh services to operate as an independant Node on one or more Mesh networks.
To enable this, at the lowest network layer, we are creating a cache of Network
Keys and associated credentials (NIDs, Privacy Keys, Encryption Keys, etc).
This will allow Network decryption to be done once per incoming packets,
without requiring each "Node" on the local device to handle them redundantly.
Brian Gix (2):
mesh: Add centralized caching Net Key management
mesh: Refactor friend.c and net.c for central key DB
Makefile.mesh | 1 +
mesh/friend.c | 188 +++++++++-------------
mesh/friend.h | 2 +-
mesh/net.c | 476 +++++++++++++++----------------------------------------
mesh/net.h | 14 +-
mesh/net_keys.c | 326 +++++++++++++++++++++++++++++++++++++
mesh/net_keys.h | 33 ++++
mesh/provision.c | 5 +-
8 files changed, 572 insertions(+), 473 deletions(-)
create mode 100644 mesh/net_keys.c
create mode 100644 mesh/net_keys.h
--
2.14.4
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH BlueZ 1/2] mesh: Add centralized caching Net Key management
2018-09-19 20:40 [PATCH BlueZ 0/2] Central Net Key storage cache for multiple Nodes Brian Gix
@ 2018-09-19 20:40 ` Brian Gix
2018-09-19 20:40 ` [PATCH BlueZ 2/2] mesh: Refactor friend.c and net.c for central key DB Brian Gix
1 sibling, 0 replies; 3+ messages in thread
From: Brian Gix @ 2018-09-19 20:40 UTC (permalink / raw)
To: linux-bluetooth; +Cc: marcel, johan.hedberg, inga.stotland, Brian Gix
---
Makefile.mesh | 1 +
mesh/net_keys.c | 326 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
mesh/net_keys.h | 33 ++++++
3 files changed, 360 insertions(+)
create mode 100644 mesh/net_keys.c
create mode 100644 mesh/net_keys.h
diff --git a/Makefile.mesh b/Makefile.mesh
index e93e68e38..0df7db2be 100644
--- a/Makefile.mesh
+++ b/Makefile.mesh
@@ -1,5 +1,6 @@
if MESH
mesh_sources = mesh/mesh.h mesh/mesh.c \
+ mesh/net_keys.h mesh/net_keys.c \
mesh/mesh-io.h mesh/mesh-io.c \
mesh/mesh-io-api.h \
mesh/mesh-io-generic.h \
diff --git a/mesh/net_keys.c b/mesh/net_keys.c
new file mode 100644
index 000000000..43c8a938b
--- /dev/null
+++ b/mesh/net_keys.c
@@ -0,0 +1,326 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2018 Intel Corporation. All rights reserved.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <ell/ell.h>
+
+#include "mesh/crypto.h"
+#include "mesh/net_keys.h"
+
+#define BEACON_TYPE_SNB 0x01
+#define KEY_REFRESH 0x01
+#define IV_INDEX_UPDATE 0x02
+
+struct net_key {
+ uint32_t id;
+ uint16_t ref_cnt;
+ uint8_t friend_key;
+ uint8_t nid;
+ uint8_t master[16];
+ uint8_t encrypt[16];
+ uint8_t privacy[16];
+ uint8_t beacon[16];
+ uint8_t network[8];
+};
+
+static struct l_queue *keys = NULL;
+static uint32_t last_master_id = 0;
+
+/* To avoid re-decrypting same packet for multiple nodes, cache and check */
+static uint8_t cache_pkt[29];
+static uint8_t cache_plain[29];
+static size_t cache_len;
+static size_t cache_plainlen;
+static uint32_t cache_id;
+static uint32_t cache_iv_index;
+
+static bool match_master(const void *a, const void *b)
+{
+ const struct net_key *key = a;
+
+ return (memcmp(key->master, b, sizeof(key->master)) == 0);
+}
+
+static bool match_id(const void *a, const void *b)
+{
+ const struct net_key *key = a;
+ uint32_t id = L_PTR_TO_UINT(b);
+
+ return id == key->id;
+}
+
+static bool match_network(const void *a, const void *b)
+{
+ const struct net_key *key = a;
+ const uint8_t *network = b;
+
+ return memcmp(key->network, network, sizeof(key->network)) == 0;
+}
+
+/* Key added from Provisioning, NetKey Add or NetKey update */
+uint32_t net_key_add(const uint8_t master[16])
+{
+ struct net_key *key = l_queue_find(keys, match_master, master);
+ uint8_t p[] = {0};
+ bool result;
+
+ if (key) {
+ key->ref_cnt++;
+ return key->id;
+ }
+
+ if (!keys)
+ keys = l_queue_new();
+
+ key = l_new(struct net_key, 1);
+ memcpy(key->master, master, 16);
+ key->ref_cnt++;
+ result = mesh_crypto_k2(master, p, sizeof(p), &key->nid, key->encrypt,
+ key->privacy);
+ if (!result)
+ goto fail;
+
+ result = mesh_crypto_k3(master, key->network);
+ if (!result)
+ goto fail;
+
+ result = mesh_crypto_nkbk(master, key->beacon);
+ if (!result)
+ goto fail;
+
+ key->id = ++last_master_id;
+ l_queue_push_tail(keys, key);
+ return key->id;
+
+fail:
+ l_free(key);
+ return 0;
+}
+
+uint32_t net_key_frnd_add(uint32_t master_id, uint16_t lpn, uint16_t frnd,
+ uint16_t lp_cnt, uint16_t fn_cnt)
+{
+ const struct net_key *key = l_queue_find(keys, match_id,
+ L_UINT_TO_PTR(master_id));
+ struct net_key *frnd_key;
+ uint8_t p[9] = {0x01};
+ bool result;
+
+ if (!key || key->friend_key)
+ return 0;
+
+ frnd_key = l_new(struct net_key, 1);
+
+ l_put_be16(lpn, p + 1);
+ l_put_be16(frnd, p + 3);
+ l_put_be16(lp_cnt, p + 5);
+ l_put_be16(fn_cnt, p + 7);
+
+ result = mesh_crypto_k2(key->master, p, sizeof(p), &frnd_key->nid,
+ frnd_key->encrypt, frnd_key->privacy);
+
+ if (!result) {
+ l_free(frnd_key);
+ return 0;
+ }
+
+ frnd_key->friend_key = true;
+ frnd_key->ref_cnt++;
+ frnd_key->id = ++last_master_id;
+ l_queue_push_head(keys, frnd_key);
+
+ return frnd_key->id;
+}
+
+void net_key_unref(uint32_t id)
+{
+ struct net_key *key = l_queue_find(keys, match_id, L_UINT_TO_PTR(id));
+
+ if (key && key->ref_cnt) {
+ if (--key->ref_cnt == 0) {
+ l_queue_remove(keys, key);
+ l_free(key);
+ }
+ }
+}
+
+bool net_key_confirm(uint32_t id, const uint8_t *master)
+{
+ struct net_key *key = l_queue_find(keys, match_id, L_UINT_TO_PTR(id));
+
+ if (key)
+ return memcmp(key->master, master, sizeof(key->master)) == 0;
+
+ return false;
+}
+
+bool net_key_retrieve(uint32_t id, uint8_t *master)
+{
+ struct net_key *key = l_queue_find(keys, match_id, L_UINT_TO_PTR(id));
+
+ if (key) {
+ memcpy(master, key->master, sizeof(key->master));
+ return true;
+ }
+
+ return false;
+}
+
+static void decrypt_net_pkt(void *a, void *b)
+{
+ const struct net_key *key = a;
+ bool result;
+
+ if (cache_id || !key->ref_cnt || (cache_pkt[0] & 0x7f) != key->nid)
+ return;
+
+ result = mesh_crypto_packet_decode(cache_pkt, cache_len, false,
+ cache_plain, cache_iv_index,
+ key->encrypt, key->privacy);
+
+ if (result) {
+ cache_id = key->id;
+ if (cache_plain[1] & 0x80)
+ cache_plainlen = cache_len - 8;
+ else
+ cache_plainlen = cache_len - 4;
+ }
+}
+
+uint32_t net_key_decrypt(uint32_t iv_index, const uint8_t *pkt, size_t len,
+ uint8_t **plain, size_t *plain_len)
+{
+ bool iv_flag = !!(iv_index & 1);
+ bool iv_pkt = !!(pkt[0] & 0x80);
+
+ if (iv_pkt != iv_flag)
+ iv_index--;
+
+ if (cache_len == len && memcmp(pkt, cache_pkt, len) == 0)
+ goto done;
+
+ cache_id = 0;
+ memcpy(cache_pkt, pkt, len);
+ cache_len = len;
+ cache_iv_index = iv_index;
+
+ /* Try all network keys known to us */
+ l_queue_foreach(keys, decrypt_net_pkt, NULL);
+
+done:
+ if (cache_iv_index != iv_index)
+ return 0;
+
+ if (cache_id) {
+ *plain = cache_plain;
+ *plain_len = cache_plainlen;
+ }
+
+ return cache_id;
+}
+
+bool net_key_encrypt(uint32_t id, uint32_t iv_index, uint8_t *pkt, size_t len)
+{
+ struct net_key *key = l_queue_find(keys, match_id, L_UINT_TO_PTR(id));
+ bool result;
+
+ if (!key)
+ return false;
+
+ result = mesh_crypto_packet_encode(pkt, len, key->encrypt, iv_index,
+ key->privacy);
+
+ if (!result)
+ return false;
+
+ result = mesh_crypto_packet_label(pkt, len, iv_index, key->nid);
+
+ return result;
+}
+
+uint32_t net_key_network_id(const uint8_t network[8])
+{
+ struct net_key *key = l_queue_find(keys, match_network, network);
+
+ if (!key)
+ return 0;
+
+ return key->id;
+}
+
+bool net_key_snb_check(uint32_t id, uint32_t iv_index, bool kr, bool ivu,
+ uint64_t cmac)
+{
+ struct net_key *key = l_queue_find(keys, match_id, L_UINT_TO_PTR(id));
+ uint64_t cmac_check;
+
+ if (!key)
+ return false;
+
+ /* Any behavioral changes must pass CMAC test */
+ if (!mesh_crypto_beacon_cmac(key->beacon, key->network, iv_index, kr,
+ ivu, &cmac_check)) {
+ l_error("mesh_crypto_beacon_cmac failed");
+ return false;
+ }
+
+ if (cmac != cmac_check) {
+ l_error("cmac compare failed %16.16lx != %16.16lx",
+ cmac, cmac_check);
+ return false;
+ }
+
+ return true;
+}
+
+bool net_key_snb_compose(uint32_t id, uint32_t iv_index, bool kr, bool ivu,
+ uint8_t *snb)
+{
+ struct net_key *key = l_queue_find(keys, match_id, L_UINT_TO_PTR(id));
+ uint64_t cmac;
+
+ if (!key)
+ return false;
+
+ /* Any behavioral changes must pass CMAC test */
+ if (!mesh_crypto_beacon_cmac(key->beacon, key->network, iv_index, kr,
+ ivu, &cmac)) {
+ l_error("mesh_crypto_beacon_cmac failed");
+ return false;
+ }
+
+ snb[0] = BEACON_TYPE_SNB;
+ snb[1] = 0;
+
+ if (kr)
+ snb[1] |= KEY_REFRESH;
+
+ if (ivu)
+ snb[1] |= IV_INDEX_UPDATE;
+
+ memcpy(snb + 2, key->network, 8);
+ l_put_be32(iv_index, snb + 10);
+ l_put_be64(cmac, snb + 14);
+
+ return true;
+}
diff --git a/mesh/net_keys.h b/mesh/net_keys.h
new file mode 100644
index 000000000..c752d3991
--- /dev/null
+++ b/mesh/net_keys.h
@@ -0,0 +1,33 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2018 Intel Corporation. All rights reserved.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ */
+
+bool net_key_confirm(uint32_t id, const uint8_t master[16]);
+bool net_key_retrieve(uint32_t id, uint8_t *master);
+uint32_t net_key_add(const uint8_t master[16]);
+uint32_t net_key_frnd_add(uint32_t master_id, uint16_t lpn, uint16_t frnd,
+ uint16_t lp_cnt, uint16_t fn_cnt);
+void net_key_unref(uint32_t id);
+uint32_t net_key_decrypt(uint32_t iv_index, const uint8_t *pkt, size_t len,
+ uint8_t **plain, size_t *plain_len);
+bool net_key_encrypt(uint32_t id, uint32_t iv_index, uint8_t *pkt, size_t len);
+uint32_t net_key_network_id(const uint8_t network[8]);
+bool net_key_snb_check(uint32_t id, uint32_t iv_index, bool kr, bool ivu,
+ uint64_t cmac);
+bool net_key_snb_compose(uint32_t id, uint32_t iv_index, bool kr, bool ivu,
+ uint8_t *snb);
--
2.14.4
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH BlueZ 2/2] mesh: Refactor friend.c and net.c for central key DB
2018-09-19 20:40 [PATCH BlueZ 0/2] Central Net Key storage cache for multiple Nodes Brian Gix
2018-09-19 20:40 ` [PATCH BlueZ 1/2] mesh: Add centralized caching Net Key management Brian Gix
@ 2018-09-19 20:40 ` Brian Gix
1 sibling, 0 replies; 3+ messages in thread
From: Brian Gix @ 2018-09-19 20:40 UTC (permalink / raw)
To: linux-bluetooth; +Cc: marcel, johan.hedberg, inga.stotland, Brian Gix
To enable multiple local nodes and friendships to
coexist, and minimize redundant encryption processing
---
mesh/friend.c | 188 +++++++++-------------
mesh/friend.h | 2 +-
mesh/net.c | 476 +++++++++++++++----------------------------------------
mesh/net.h | 14 +-
mesh/provision.c | 5 +-
5 files changed, 212 insertions(+), 473 deletions(-)
diff --git a/mesh/friend.c b/mesh/friend.c
index 5a4088ef1..9ce499463 100644
--- a/mesh/friend.c
+++ b/mesh/friend.c
@@ -29,6 +29,7 @@
#include "mesh/mesh-defs.h"
#include "mesh/mesh.h"
+#include "mesh/net_keys.h"
#include "mesh/node.h"
#include "mesh/net.h"
#include "mesh/crypto.h"
@@ -56,7 +57,7 @@ static uint8_t frnd_sublist_size = FRND_SUB_LIST_SIZE;
struct frnd_negotiation {
struct l_timeout *timeout;
struct mesh_net *net;
- struct mesh_key_set key_set;
+ uint32_t key_id;
uint32_t poll_timeout;
uint16_t low_power_node;
uint16_t old_relay;
@@ -79,7 +80,7 @@ static void response_timeout(struct l_timeout *timeout, void *user_data)
/* LPN did not choose us */
l_info("Did not win negotiation for %4.4x", neg->low_power_node);
- mesh_net_remove_keyset(neg->net, &neg->key_set);
+ net_key_unref(neg->key_id);
l_queue_remove(frnd_negotiations, neg);
l_timeout_remove(timeout);
l_free(neg);
@@ -89,8 +90,7 @@ static void response_delay(struct l_timeout *timeout, void *user_data)
{
struct frnd_negotiation *neg = user_data;
uint16_t net_idx = mesh_net_get_primary_idx(neg->net);
- uint8_t key[16];
- uint8_t p[9] = { 1 };
+ uint32_t key_id;
uint8_t msg[8];
uint16_t n = 0;
bool res;
@@ -98,27 +98,17 @@ static void response_delay(struct l_timeout *timeout, void *user_data)
l_timeout_remove(timeout);
/* Create key Set for this offer */
- l_put_be16(neg->low_power_node, p + 1);
- l_put_be16(mesh_net_get_address(neg->net), p + 3);
- l_put_be16(neg->lp_cnt, p + 5);
- l_put_be16(counter, p + 7);
- res = mesh_net_get_key(neg->net, false, net_idx, key);
+ res = mesh_net_get_key(neg->net, false, net_idx, &key_id);
if (!res)
goto cleanup;
- print_packet("Friend Key P =", p, 9);
- res = mesh_crypto_k2(key, p, sizeof(p), &neg->key_set.nid,
- neg->key_set.enc_key, neg->key_set.privacy_key);
- if (!res)
+ neg->key_id = net_key_frnd_add(key_id, neg->low_power_node,
+ mesh_net_get_address(neg->net),
+ neg->lp_cnt, counter);
+ if (!neg->key_id)
goto cleanup;
- print_packet("NID =", &neg->key_set.nid, 1);
- print_packet("ENC_KEY =", neg->key_set.enc_key, 16);
- print_packet("PRIV_KEY =", neg->key_set.privacy_key, 16);
-
neg->fn_cnt = counter++;
- neg->key_set.frnd = true;
- mesh_net_add_keyset(neg->net, &neg->key_set);
msg[n++] = NET_OP_FRND_OFFER;
msg[n++] = frnd_relay_window;
@@ -128,7 +118,7 @@ static void response_delay(struct l_timeout *timeout, void *user_data)
l_put_be16(neg->fn_cnt, msg + n);
n += 2;
print_packet("Tx-NET_OP_FRND_OFFER", msg, n);
- mesh_net_transport_send(neg->net, NULL, true,
+ mesh_net_transport_send(neg->net, 0, true,
mesh_net_get_iv_index(neg->net), 0,
0, 0, neg->low_power_node,
msg, n);
@@ -142,7 +132,7 @@ static void response_delay(struct l_timeout *timeout, void *user_data)
return;
cleanup:
- mesh_net_remove_keyset(neg->net, &neg->key_set);
+ net_key_unref(neg->key_id);
l_queue_remove(frnd_negotiations, neg);
l_free(neg);
}
@@ -357,7 +347,7 @@ void friend_clear(struct mesh_net *net, uint16_t src, uint16_t lpn,
l_put_be16(lpn, msg + 1);
l_put_be16(lpnCounter, msg + 3);
- mesh_net_transport_send(net, NULL, false,
+ mesh_net_transport_send(net, 0, false,
mesh_net_get_iv_index(net), DEFAULT_TTL,
0, 0, src,
msg, sizeof(msg));
@@ -372,7 +362,7 @@ static void clear_retry(struct l_timeout *timeout, void *user_data)
l_put_be16(neg->low_power_node, msg + 1);
l_put_be16(neg->lp_cnt, msg + 3);
- mesh_net_transport_send(neg->net, NULL, false,
+ mesh_net_transport_send(neg->net, 0, false,
mesh_net_get_iv_index(neg->net), DEFAULT_TTL,
0, 0, neg->old_relay,
msg, sizeof(msg));
@@ -422,7 +412,7 @@ static void friend_delay_rsp(struct l_timeout *timeout, void *user_data)
pkt->iv_index);
pkt->u.one[0].sent = true;
- mesh_net_ack_send(net, &frnd->key_set,
+ mesh_net_ack_send(net, frnd->net_key_cur,
pkt->iv_index, pkt->ttl,
pkt->u.one[0].seq, pkt->src, pkt->dst,
rly, seqZero,
@@ -438,7 +428,7 @@ static void friend_delay_rsp(struct l_timeout *timeout, void *user_data)
pkt->u.one[0].data, pkt->last_len);
pkt->u.one[0].sent = true;
- mesh_net_transport_send(net, &frnd->key_set, false,
+ mesh_net_transport_send(net, frnd->net_key_cur, false,
pkt->iv_index, pkt->ttl,
pkt->u.one[0].seq, pkt->src, pkt->dst,
pkt->u.one[0].data, pkt->last_len);
@@ -458,7 +448,7 @@ static void friend_delay_rsp(struct l_timeout *timeout, void *user_data)
print_packet("Frnd-Msg", pkt->u.s12[pkt->cnt_out].data, len);
pkt->u.s12[pkt->cnt_out].sent = true;
- mesh_net_send_seg(net, &frnd->key_set,
+ mesh_net_send_seg(net, frnd->net_key_cur,
pkt->iv_index,
pkt->ttl,
pkt->u.s12[pkt->cnt_out].seq,
@@ -470,16 +460,16 @@ static void friend_delay_rsp(struct l_timeout *timeout, void *user_data)
return;
update:
- // No More Data -- send Update message with md = false
+ /* No More Data -- send Update message with md = false */
net_seq = mesh_net_get_seq_num(net);
l_info("Fwd FRND UPDATE %6.6x with MD == 0", net_seq);
frnd->last = frnd->seq;
mesh_net_get_snb_state(net, upd + 1, &iv_index);
l_put_be32(iv_index, upd + 2);
- upd[6] = false; // Queue is Empty
+ upd[6] = false; /* Queue is Empty */
print_packet("Update", upd, sizeof(upd));
- mesh_net_transport_send(net, &frnd->key_set, false,
+ mesh_net_transport_send(net, frnd->net_key_cur, false,
mesh_net_get_iv_index(net), 0,
net_seq, 0, frnd->dst,
upd, sizeof(upd));
@@ -512,7 +502,8 @@ void friend_poll(struct mesh_net *net, uint16_t src, bool seq,
friend_poll_timeout, frnd, NULL);
l_timeout_remove(neg->timeout);
- mesh_net_remove_keyset(neg->net, &neg->key_set);
+ net_key_unref(neg->key_id);
+ neg->key_id = 0;
if (neg->old_relay == 0 ||
neg->old_relay == mesh_net_get_address(net)) {
@@ -522,7 +513,7 @@ void friend_poll(struct mesh_net *net, uint16_t src, bool seq,
neg->clearing = true;
l_put_be16(neg->low_power_node, msg + 1);
l_put_be16(neg->lp_cnt, msg + 3);
- mesh_net_transport_send(net, NULL, false,
+ mesh_net_transport_send(net, 0, false,
mesh_net_get_iv_index(net), DEFAULT_TTL,
0, 0, neg->old_relay,
msg, sizeof(msg));
@@ -630,7 +621,7 @@ void friend_sub_add(struct mesh_net *net, struct mesh_friend *frnd,
print_packet("Tx-NET_OP_PROXY_SUB_CONFIRM", msg, sizeof(msg));
net_seq = mesh_net_get_seq_num(net);
- mesh_net_transport_send(net, &frnd->key_set, false,
+ mesh_net_transport_send(net, frnd->net_key_cur, false,
mesh_net_get_iv_index(net), 0,
net_seq, 0, frnd->dst,
msg, sizeof(msg));
@@ -668,7 +659,7 @@ void friend_sub_del(struct mesh_net *net, struct mesh_friend *frnd,
print_packet("Tx-NET_OP_PROXY_SUB_CONFIRM", msg, sizeof(msg));
net_seq = mesh_net_get_seq_num(net);
- mesh_net_transport_send(net, &frnd->key_set, false,
+ mesh_net_transport_send(net, frnd->net_key_cur, false,
mesh_net_get_iv_index(net), 0,
net_seq, 0, frnd->dst,
msg, sizeof(msg));
@@ -695,8 +686,8 @@ static uint16_t fn_cnt, cnt = 0xffff;
static uint32_t poll_period_ms;
static struct l_timeout *poll_retry_to;
static struct l_timeout *poll_period_to;
-static struct mesh_key_set lpn_set;
-static struct mesh_key_set new_lpn_set;
+static uint32_t lpn_key_id;
+static uint32_t new_lpn_id;
void frnd_offer(struct mesh_net *net, uint16_t src, uint8_t window,
uint8_t cache, uint8_t sub_list_size,
@@ -763,13 +754,13 @@ void frnd_poll_cancel(struct mesh_net *net)
void frnd_poll(struct mesh_net *net, bool retry)
{
- struct mesh_key_set *key_set = &lpn_set;
+ uint32_t key_id = lpn_key_id;
uint32_t net_seq;
uint8_t msg[2] = { NET_OP_FRND_POLL };
bool seq = mesh_net_get_frnd_seq(net);
/* Check if we are in Phase 2 of Key Refresh */
- if (new_lpn_set.nid != 0xff) {
+ if (new_lpn_id) {
uint8_t phase;
uint16_t net_idx = mesh_net_get_primary_idx(net);
uint8_t status =
@@ -777,7 +768,7 @@ void frnd_poll(struct mesh_net *net, bool retry)
if (status == MESH_STATUS_SUCCESS &&
phase == KEY_REFRESH_PHASE_TWO)
- key_set = &new_lpn_set;
+ key_id = new_lpn_id;
}
if (!retry) {
@@ -789,8 +780,9 @@ void frnd_poll(struct mesh_net *net, bool retry)
l_timeout_remove(poll_period_to);
poll_period_to = NULL;
frnd_poll_cancel(net);
- mesh_net_remove_keyset(net, &lpn_set);
- mesh_net_remove_keyset(net, &new_lpn_set);
+ net_key_unref(lpn_key_id);
+ net_key_unref(new_lpn_id);
+ new_lpn_id = lpn_key_id = 0;
mesh_net_set_friend(net, 0);
return;
}
@@ -801,7 +793,7 @@ void frnd_poll(struct mesh_net *net, bool retry)
l_info("TX-FRIEND POLL %d", seq);
msg[1] = seq;
net_seq = mesh_net_get_seq_num(net);
- mesh_net_transport_send(net, key_set, true,
+ mesh_net_transport_send(net, key_id, true,
mesh_net_get_iv_index(net), 0,
net_seq, 0, mesh_net_get_friend(net),
msg, sizeof(msg));
@@ -828,8 +820,7 @@ static void req_timeout(struct l_timeout *timeout, void *user_data)
struct mesh_net *net = user_data;
struct frnd_offers *best;
struct frnd_offers *offer = l_queue_pop_head(offers);
- uint8_t p[9] = { 1 };
- uint8_t key[16];
+ uint32_t key_id = 0;
bool res;
l_timeout_remove(timeout);
@@ -860,8 +851,9 @@ static void req_timeout(struct l_timeout *timeout, void *user_data)
offer = l_queue_pop_head(offers);
}
- mesh_net_remove_keyset(net, &lpn_set);
- mesh_net_remove_keyset(net, &new_lpn_set);
+ net_key_unref(lpn_key_id);
+ net_key_unref(new_lpn_id);
+ new_lpn_id = lpn_key_id = 0;
if (mesh_net_get_friend(net)) {
l_free(best);
return;
@@ -871,41 +863,24 @@ static void req_timeout(struct l_timeout *timeout, void *user_data)
}
fn_cnt = best->fn_cnt;
- l_put_be16(mesh_net_get_address(net), p + 1);
- l_put_be16(best->src, p + 3);
- l_put_be16(cnt, p + 5);
- l_put_be16(best->fn_cnt, p + 7);
- print_packet("Friend Key P =", p, 9);
- res = mesh_net_get_key(net, false, mesh_net_get_primary_idx(net), key);
+ res = mesh_net_get_key(net, false, mesh_net_get_primary_idx(net),
+ &key_id);
if (!res)
return;
- res = mesh_crypto_k2(key, p, sizeof(p), &lpn_set.nid,
- lpn_set.enc_key, lpn_set.privacy_key);
- if (!res)
+ lpn_key_id = net_key_frnd_add(key_id, mesh_net_get_address(net),
+ best->src, cnt, best->fn_cnt);
+ if (!lpn_key_id)
return;
- print_packet("Cur-NID", &lpn_set.nid, 1);
- print_packet("Cur-ENC_KEY", lpn_set.enc_key, 16);
- print_packet("Cur-PRIV_KEY", lpn_set.privacy_key, 16);
-
- mesh_net_add_keyset(net, &lpn_set);
+ res = mesh_net_get_key(net, true, mesh_net_get_primary_idx(net),
+ &key_id);
- res = mesh_net_get_key(net, true, mesh_net_get_primary_idx(net), key);
-
- if (res)
- res = mesh_crypto_k2(key, p, sizeof(p), &new_lpn_set.nid,
- new_lpn_set.enc_key, new_lpn_set.privacy_key);
- if (!res) {
- new_lpn_set.nid = 0xff;
+ if (!res)
goto old_keys_only;
- }
- print_packet("New-NID", &new_lpn_set.nid, 1);
- print_packet("New-ENC_KEY", new_lpn_set.enc_key, 16);
- print_packet("New-PRIV_KEY", new_lpn_set.privacy_key, 16);
-
- mesh_net_add_keyset(net, &new_lpn_set);
+ new_lpn_id = net_key_frnd_add(key_id, mesh_net_get_address(net),
+ best->src, cnt, best->fn_cnt);
old_keys_only:
@@ -935,11 +910,11 @@ void frnd_clear(struct mesh_net *net)
l_put_be16(cnt, msg + n);
n += 2;
- mesh_net_remove_keyset(net, &lpn_set);
- mesh_net_remove_keyset(net, &new_lpn_set);
+ net_key_unref(lpn_key_id);
+ net_key_unref(new_lpn_id);
mesh_net_set_friend(net, 0);
- mesh_net_transport_send(net, NULL, false,
+ mesh_net_transport_send(net, 0, false,
mesh_net_get_iv_index(net), 0,
0, 0, frnd_addr,
msg, n);
@@ -967,7 +942,7 @@ void frnd_request_friend(struct mesh_net *net, uint8_t cache,
l_put_be16(cnt + 1, msg + n); // Next counter
n += 2;
print_packet("Tx-NET_OP_FRND_REQUEST", msg, n);
- mesh_net_transport_send(net, NULL, false,
+ mesh_net_transport_send(net, 0, false,
mesh_net_get_iv_index(net), 0,
0, 0, FRIENDS_ADDRESS,
msg, n);
@@ -979,13 +954,13 @@ void frnd_request_friend(struct mesh_net *net, uint8_t cache,
static uint8_t trans_id;
void frnd_sub_add(struct mesh_net *net, uint32_t parms[7])
{
- struct mesh_key_set *key_set = &lpn_set;
+ uint32_t key_id = lpn_key_id;
uint32_t net_seq;
uint8_t msg[15] = { NET_OP_PROXY_SUB_ADD };
uint8_t i, n = 1;
/* Check if we are in Phase 2 of Key Refresh */
- if (new_lpn_set.nid != 0xff) {
+ if (new_lpn_id) {
uint8_t phase;
uint16_t net_idx = mesh_net_get_primary_idx(net);
uint8_t status = mesh_net_key_refresh_phase_get(net,
@@ -993,7 +968,7 @@ void frnd_sub_add(struct mesh_net *net, uint32_t parms[7])
if (status == MESH_STATUS_SUCCESS &&
phase == KEY_REFRESH_PHASE_TWO)
- key_set = &new_lpn_set;
+ key_id = new_lpn_id;
}
msg[n++] = ++trans_id;
@@ -1007,7 +982,7 @@ void frnd_sub_add(struct mesh_net *net, uint32_t parms[7])
net_seq = mesh_net_get_seq_num(net);
print_packet("Friend Sub Add", msg, n);
- mesh_net_transport_send(net, key_set, false,
+ mesh_net_transport_send(net, key_id, false,
mesh_net_get_iv_index(net), 0,
net_seq, 0, mesh_net_get_friend(net),
msg, n);
@@ -1016,13 +991,13 @@ void frnd_sub_add(struct mesh_net *net, uint32_t parms[7])
void frnd_sub_del(struct mesh_net *net, uint32_t parms[7])
{
- struct mesh_key_set *key_set = &lpn_set;
+ uint32_t key_id = lpn_key_id;
uint32_t net_seq;
uint8_t msg[15] = { NET_OP_PROXY_SUB_REMOVE };
uint8_t i, n = 1;
/* Check if we are in Phase 2 of Key Refresh */
- if (new_lpn_set.nid != 0xff) {
+ if (new_lpn_id) {
uint8_t phase;
uint16_t net_idx = mesh_net_get_primary_idx(net);
uint8_t status = mesh_net_key_refresh_phase_get(net,
@@ -1030,7 +1005,7 @@ void frnd_sub_del(struct mesh_net *net, uint32_t parms[7])
if (status == MESH_STATUS_SUCCESS &&
phase == KEY_REFRESH_PHASE_TWO)
- key_set = &new_lpn_set;
+ key_id = new_lpn_id;
}
msg[n++] = ++trans_id;
@@ -1044,7 +1019,7 @@ void frnd_sub_del(struct mesh_net *net, uint32_t parms[7])
net_seq = mesh_net_get_seq_num(net);
print_packet("Friend Sub Del", msg, n);
- mesh_net_transport_send(net, key_set, false,
+ mesh_net_transport_send(net, key_id, false,
mesh_net_get_iv_index(net), 0,
net_seq, 0, mesh_net_get_friend(net),
msg, n);
@@ -1054,46 +1029,29 @@ void frnd_sub_del(struct mesh_net *net, uint32_t parms[7])
void frnd_key_refresh(struct mesh_net *net, uint8_t phase)
{
uint16_t net_idx = mesh_net_get_primary_idx(net);
- uint8_t p[9] = { 1 };
- uint8_t key[16];
+ uint32_t key_id;
switch (phase) {
default:
case 0:
case 3:
- if (new_lpn_set.nid != 0xff) {
- l_info("LPN Retiring KeySet %2.2x", lpn_set.nid);
- lpn_set = new_lpn_set;
- new_lpn_set.nid = 0xff;
- mesh_net_remove_keyset(net, &new_lpn_set);
+ if (new_lpn_id) {
+ l_info("LPN Retiring KeySet %d", lpn_key_id);
+ net_key_unref(lpn_key_id);
+ lpn_key_id = new_lpn_id;
}
return;
case 1:
- mesh_net_remove_keyset(net, &new_lpn_set);
- if (!mesh_net_get_key(net, true, net_idx, key)) {
- new_lpn_set.nid = 0xff;
- return;
- }
-
- l_put_be16(mesh_net_get_address(net), p + 1);
- l_put_be16(mesh_net_get_friend(net), p + 3);
- l_put_be16(cnt, p + 5);
- l_put_be16(fn_cnt, p + 7);
- print_packet("Friend Key P =", p, 9);
-
- if (!mesh_crypto_k2(key, p, sizeof(p), &new_lpn_set.nid,
- new_lpn_set.enc_key,
- new_lpn_set.privacy_key)) {
- new_lpn_set.nid = 0xff;
+ net_key_unref(new_lpn_id);
+ if (!mesh_net_get_key(net, true, net_idx, &key_id)) {
+ new_lpn_id = 0;
return;
}
- print_packet("New-NID", &new_lpn_set.nid, 1);
- print_packet("New-ENC_KEY", new_lpn_set.enc_key, 16);
- print_packet("New-PRIV_KEY", new_lpn_set.privacy_key, 16);
-
- mesh_net_add_keyset(net, &new_lpn_set);
+ new_lpn_id = net_key_frnd_add(key_id, mesh_net_get_address(net),
+ mesh_net_get_friend(net),
+ cnt, fn_cnt);
return;
case 2:
@@ -1102,7 +1060,7 @@ void frnd_key_refresh(struct mesh_net *net, uint8_t phase)
}
}
-struct mesh_key_set *frnd_get_key(struct mesh_net *net)
+uint32_t frnd_get_key(struct mesh_net *net)
{
uint8_t idx = mesh_net_get_primary_idx(net);
uint8_t phase = 0;
@@ -1110,7 +1068,7 @@ struct mesh_key_set *frnd_get_key(struct mesh_net *net)
mesh_net_key_refresh_phase_get(net, idx, &phase);
if (phase == 2)
- return &new_lpn_set;
+ return new_lpn_id;
else
- return &lpn_set;
+ return lpn_key_id;
}
diff --git a/mesh/friend.h b/mesh/friend.h
index 1fa6ec92a..7ab5dea2e 100644
--- a/mesh/friend.h
+++ b/mesh/friend.h
@@ -54,4 +54,4 @@ void frnd_offer(struct mesh_net *net, uint16_t src, uint8_t window,
uint8_t cache, uint8_t sub_list_size,
int8_t r_rssi, int8_t l_rssi, uint16_t fn_cnt);
void frnd_key_refresh(struct mesh_net *net, uint8_t phase);
-struct mesh_key_set *frnd_get_key(struct mesh_net *net);
+uint32_t frnd_get_key(struct mesh_net *net);
diff --git a/mesh/net.c b/mesh/net.c
index fb17e639d..444d383e4 100644
--- a/mesh/net.c
+++ b/mesh/net.c
@@ -31,6 +31,7 @@
#include "mesh/display.h"
#include "mesh/crypto.h"
+#include "mesh/net_keys.h"
#include "mesh/mesh.h"
#include "mesh/node.h"
#include "mesh/net.h"
@@ -64,8 +65,6 @@
#define DEFAULT_TRANSMIT_COUNT 1
#define DEFAULT_TRANSMIT_INTERVAL 100
-#define BEACON_TYPE_SNB 0x01
-
#define BEACON_INTERVAL_MIN 10
#define BEACON_INTERVAL_MAX 600
@@ -103,9 +102,9 @@ struct mesh_beacon {
struct mesh_subnet {
struct mesh_net *net;
uint16_t idx;
- struct net_key *tx;
- struct net_key current;
- struct net_key updated;
+ uint32_t net_key_tx;
+ uint32_t net_key_cur;
+ uint32_t net_key_upd;
struct mesh_beacon snb;
uint8_t key_refresh;
uint8_t kr_phase;
@@ -166,7 +165,6 @@ struct mesh_net {
struct l_queue *friends;
struct l_queue *destinations;
struct l_queue *fast_cache;
- struct l_queue *key_sets;
uint8_t prov_priv_key[32];
@@ -267,22 +265,13 @@ static bool match_key_index(const void *a, const void *b)
return subnet->idx == idx;
}
-static bool match_key_set(const void *a, const void *b)
+static bool match_key_id(const void *a, const void *b)
{
const struct mesh_subnet *subnet = a;
- const struct mesh_key_set *key_set = b;
+ uint32_t key_id = L_PTR_TO_UINT(b);
- return (key_set == &subnet->current.key_set) ||
- (key_set == &subnet->updated.key_set);
-}
-
-static bool match_network_id(const void *a, const void *b)
-{
- const struct mesh_subnet *subnet = a;
- const uint8_t *network_id = b;
-
- return ((memcmp(subnet->current.network_id, network_id, 8) == 0) ||
- (memcmp(subnet->updated.network_id, network_id, 8) == 0));
+ return (key_id == subnet->net_key_cur) ||
+ (key_id == subnet->net_key_upd);
}
static void idle_mesh_heartbeat_send(void *net)
@@ -333,29 +322,17 @@ static void free_friend_internals(struct mesh_friend *frnd)
frnd->pkt_cache = NULL;
frnd->grp_list = NULL;
- mesh_net_remove_keyset(frnd->net, &frnd->key_set);
- mesh_net_remove_keyset(frnd->net, &frnd->new_key_set);
+ net_key_unref(frnd->net_key_cur);
+ net_key_unref(frnd->net_key_upd);
}
static void frnd_kr_phase1(void *a, void *b)
{
struct mesh_friend *frnd = a;
- const uint8_t *key = b;
- uint8_t p[9] = {0x01};
-
- l_put_be16(frnd->dst, p + 1);
- l_put_be16(frnd->net->src_addr, p + 3);
- l_put_be16(frnd->lp_cnt, p + 5);
- l_put_be16(frnd->fn_cnt, p + 7);
+ uint32_t key_id = L_PTR_TO_UINT(b);
- mesh_crypto_k2(key, p, sizeof(p), &frnd->new_key_set.nid,
- frnd->new_key_set.enc_key,
- frnd->new_key_set.privacy_key);
-
- mesh_net_add_keyset(frnd->net, &frnd->new_key_set);
- l_info("Add New KeySet %2.2x for %4.4x",
- frnd->new_key_set.nid, frnd->dst);
- l_info("Outgoing with %2.2x", frnd->key_set.nid);
+ frnd->net_key_upd = net_key_frnd_add(key_id, frnd->dst,
+ frnd->net->src_addr, frnd->lp_cnt, frnd->fn_cnt);
}
static void frnd_kr_phase2(void *a, void *b)
@@ -369,20 +346,19 @@ static void frnd_kr_phase2(void *a, void *b)
* receives it's first Poll using the new keys (?)
*/
- l_info("Use Both KeySet %2.2x && %2.2x for %4.4x",
- frnd->key_set.nid, frnd->new_key_set.nid, frnd->dst);
+ l_info("Use Both KeySet %d && %d for %4.4x",
+ frnd->net_key_cur, frnd->net_key_upd, frnd->dst);
}
static void frnd_kr_phase3(void *a, void *b)
{
struct mesh_friend *frnd = a;
- struct mesh_net *net = b;
- l_info("Replace KeySet %2.2x with %2.2x for %4.4x",
- frnd->key_set.nid, frnd->new_key_set.nid, frnd->dst);
- frnd->key_set = frnd->new_key_set;
- mesh_net_remove_keyset(net, &frnd->new_key_set);
- frnd->new_key_set.nid = 0xff;
+ l_info("Replace KeySet %d with %d for %4.4x",
+ frnd->net_key_cur, frnd->net_key_upd, frnd->dst);
+ net_key_unref(frnd->net_key_cur);
+ frnd->net_key_cur = frnd->net_key_upd;
+ frnd->net_key_upd = 0;
}
/* TODO: add net key idx? For now, use primary net key */
@@ -392,7 +368,6 @@ struct mesh_friend *mesh_friend_new(struct mesh_net *net, uint16_t dst,
uint16_t fn_cnt, uint16_t lp_cnt)
{
struct mesh_subnet *subnet;
- uint8_t p[9] = {0x01};
struct mesh_friend *frnd = l_queue_find(net->friends,
match_by_friend, L_UINT_TO_PTR(dst));
@@ -416,33 +391,21 @@ struct mesh_friend *mesh_friend_new(struct mesh_net *net, uint16_t dst,
frnd->poll_timeout = fpt;
frnd->ele_cnt = ele_cnt;
frnd->pkt_cache = l_queue_new();
- frnd->new_key_set.nid = NET_NID_INVALID;
-
- l_put_be16(dst, p + 1);
- l_put_be16(net->src_addr, p + 3);
- l_put_be16(lp_cnt, p + 5);
- l_put_be16(fn_cnt, p + 7);
+ frnd->net_key_upd = 0;
subnet = get_primary_subnet(net);
/* TODO: the primary key must be present, do we need to add check?. */
- mesh_crypto_k2(subnet->current.key, p, sizeof(p),
- &frnd->key_set.nid,
- frnd->key_set.enc_key,
- frnd->key_set.privacy_key);
-
- frnd->key_set.frnd = true;
- mesh_net_add_keyset(net, &frnd->key_set);
+ frnd->net_key_cur = net_key_frnd_add(subnet->net_key_cur,
+ dst, net->src_addr,
+ lp_cnt, fn_cnt);
- if (subnet->updated.key_set.nid == NET_NID_INVALID)
+ if (!subnet->net_key_upd)
return frnd;
- mesh_crypto_k2(subnet->updated.key, p, sizeof(p),
- &frnd->new_key_set.nid,
- frnd->new_key_set.enc_key,
- frnd->new_key_set.privacy_key);
- frnd->new_key_set.frnd = true;
- mesh_net_add_keyset(net, &frnd->new_key_set);
+ frnd->net_key_upd = net_key_frnd_add(subnet->net_key_upd,
+ dst, net->src_addr,
+ lp_cnt, fn_cnt);
return frnd;
}
@@ -465,26 +428,6 @@ bool mesh_friend_clear(struct mesh_net *net, struct mesh_friend *frnd)
return removed;
}
-bool mesh_net_add_keyset(struct mesh_net *net, struct mesh_key_set *key_set)
-{
- if (!net)
- return false;
-
- l_info("Add KEY_SET %2.2x (%d) %p",
- key_set->nid, key_set->frnd, key_set);
- return l_queue_push_tail(net->key_sets, key_set);
-}
-
-bool mesh_net_remove_keyset(struct mesh_net *net, struct mesh_key_set *key_set)
-{
- if (!net || !net->key_sets)
- return false;
-
- l_info("DEL KEY_SET %2.2x (%d) %p",
- key_set->nid, key_set->frnd, key_set);
- return l_queue_remove(net->key_sets, key_set);
-}
-
void mesh_friend_sub_add(struct mesh_net *net, uint16_t lpn, uint8_t ele_cnt,
uint8_t grp_cnt,
const uint8_t *list)
@@ -593,6 +536,15 @@ static void mesh_msg_free(void *data)
l_free(msg);
}
+static void subnet_free(void *data)
+{
+ struct mesh_subnet *subnet = data;
+
+ net_key_unref(subnet->net_key_cur);
+ net_key_unref(subnet->net_key_upd);
+ l_free(subnet);
+}
+
static void lpn_process_beacon(void *user_data, const void *data, uint8_t size,
int8_t rssi);
@@ -606,70 +558,17 @@ static struct mesh_subnet *subnet_new(struct mesh_net *net, uint16_t idx)
subnet->net = net;
subnet->idx = idx;
- subnet->tx = &subnet->current;
- subnet->updated.key_set.nid = NET_NID_INVALID;
subnet->snb.beacon[0] = MESH_AD_TYPE_BEACON;
return subnet;
}
-static bool create_keys(struct mesh_net *net, struct net_key *keys,
- const uint8_t *net_key)
-{
- uint8_t nid[1];
- uint8_t enc_key[16];
- uint8_t privacy_key[16];
- uint8_t network_id[8];
- uint8_t p[] = {0};
-
- if (!mesh_crypto_k2(net_key, p, sizeof(p),
- nid, enc_key, privacy_key))
- return false;
-
- if (!mesh_crypto_k3(net_key, network_id))
- return false;
-
- if (!mesh_crypto_nkbk(net_key, keys->beacon_key))
- return false;
-
- keys->key_set.frnd = false;
- keys->key_set.nid = nid[0];
- memcpy(keys->key_set.enc_key, enc_key, 16);
- memcpy(keys->key_set.privacy_key, privacy_key, 16);
- memcpy(keys->network_id, network_id, 8);
- memcpy(keys->key, net_key, 16);
- return true;
-}
-
static bool create_secure_beacon(struct mesh_net *net,
struct mesh_subnet *subnet,
- uint8_t *beacon_data, uint8_t size)
+ uint8_t *beacon_data)
{
- uint64_t cmac;
-
- if (size < 22)
- return false;
-
- beacon_data[0] = BEACON_TYPE_SNB;
- beacon_data[1] = 0;
-
- if (subnet->key_refresh)
- beacon_data[1] |= 0x01;
-
- if (iv_is_updating(net))
- beacon_data[1] |= 0x02;
-
- memcpy(beacon_data + 2, subnet->tx->network_id, 8);
- l_put_be32(net->iv_index, beacon_data + 10);
-
- if (!mesh_crypto_beacon_cmac(subnet->tx->beacon_key,
- subnet->tx->network_id,
- net->iv_index, subnet->key_refresh,
- iv_is_updating(net), &cmac))
- return false;
-
- l_put_be64(cmac, beacon_data + 14);
-
- return true;
+ return net_key_snb_compose(subnet->net_key_tx, net->iv_index,
+ !!subnet->key_refresh, iv_is_updating(net),
+ beacon_data);
}
static void send_network_beacon(struct mesh_subnet *subnet,
@@ -778,7 +677,6 @@ struct mesh_net *mesh_net_new(uint16_t index)
net->tx_interval = DEFAULT_TRANSMIT_INTERVAL;
net->subnets = l_queue_new();
- net->key_sets = l_queue_new();
net->fast_cache = l_queue_new();
net->msg_cache = l_queue_new();
net->sar_in = l_queue_new();
@@ -811,11 +709,7 @@ void mesh_net_unref(struct mesh_net *net)
if (__sync_sub_and_fetch(&net->ref_count, 1))
return;
- /* key_sets are not allocated to this queue. Only Borrowed */
- l_queue_destroy(net->key_sets, NULL);
- net->key_sets = NULL;
-
- l_queue_destroy(net->subnets, l_free);
+ l_queue_destroy(net->subnets, subnet_free);
l_queue_destroy(net->fast_cache, mesh_msg_free);
l_queue_destroy(net->msg_cache, mesh_msg_free);
l_queue_destroy(net->sar_in, mesh_sar_free);
@@ -1071,12 +965,11 @@ int mesh_net_del_key(struct mesh_net *net, uint16_t idx)
if (idx == net->heartbeat.pub_net_idx)
net->heartbeat.pub_dst = UNASSIGNED_ADDRESS;
- mesh_net_remove_keyset(net, &subnet->current.key_set);
- mesh_net_remove_keyset(net, &subnet->updated.key_set);
-
/* TODO: cancel beacon_enable on this subnet */
l_queue_remove(net->subnets, subnet);
+ subnet_free(subnet);
+
if (!storage_local_net_key_del(net, idx))
return MESH_STATUS_STORAGE_FAIL;
@@ -1104,32 +997,33 @@ int mesh_net_add_key(struct mesh_net *net, bool update, uint16_t idx,
return MESH_STATUS_CANNOT_UPDATE;
}
- if (subnet)
- return memcmp(subnet->current.key, value, 16) ?
- MESH_STATUS_IDX_ALREADY_STORED : MESH_STATUS_SUCCESS;
+ 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;
- if (!create_keys(net, &subnet->current, value) ||
- !mesh_net_add_keyset(net, &subnet->current.key_set)) {
+ subnet->net_key_tx = subnet->net_key_cur = net_key_add(value);
+ if (!subnet->net_key_cur) {
l_free(subnet);
return MESH_STATUS_INSUFF_RESOURCES;
}
- if (!create_secure_beacon(net, subnet, &subnet->snb.beacon[1], 22) ||
+ if (!create_secure_beacon(net, subnet, subnet->snb.beacon + 1) ||
!l_queue_push_tail(net->subnets, subnet)) {
- mesh_net_remove_keyset(net, &subnet->current.key_set);
- l_free(subnet);
+ subnet_free(subnet);
return MESH_STATUS_INSUFF_RESOURCES;
}
if (!storage_local_net_key_add(net, idx, value,
KEY_REFRESH_PHASE_NONE)) {
l_queue_remove(net->subnets, subnet);
- mesh_net_remove_keyset(net, &subnet->current.key_set);
- l_free(subnet);
+ subnet_free(subnet);
return MESH_STATUS_STORAGE_FAIL;
}
@@ -1171,7 +1065,7 @@ void mesh_net_get_snb_state(struct mesh_net *net, uint8_t *flags,
}
bool mesh_net_get_key(struct mesh_net *net, bool new_key, uint16_t idx,
- uint8_t key_buf[16])
+ uint32_t *key_id)
{
struct mesh_subnet *subnet;
@@ -1184,14 +1078,14 @@ bool mesh_net_get_key(struct mesh_net *net, bool new_key, uint16_t idx,
return false;
if (!new_key) {
- memcpy(key_buf, subnet->current.key, 16);
+ *key_id = subnet->net_key_cur;
return true;
}
- if (subnet->updated.key_set.nid == NET_NID_INVALID)
+ if (!subnet->net_key_upd)
return false;
- memcpy(key_buf, subnet->updated.key, 16);
+ *key_id = subnet->net_key_upd;
return true;
}
@@ -1673,7 +1567,7 @@ static void send_frnd_ack(struct mesh_net *net, uint16_t src, uint16_t dst,
friend_ack_rxed(net, mesh_net_get_iv_index(net),
mesh_net_next_seq_num(net), 0, dst, msg);
} else {
- mesh_net_transport_send(net, NULL, false,
+ mesh_net_transport_send(net, 0, false,
mesh_net_get_iv_index(net), DEFAULT_TTL,
0, 0, dst, msg, sizeof(msg));
}
@@ -1712,7 +1606,7 @@ static void send_net_ack(struct mesh_net *net, struct mesh_sar *sar,
return;
}
- mesh_net_transport_send(net, NULL, false,
+ mesh_net_transport_send(net, 0, false,
mesh_net_get_iv_index(net), DEFAULT_TTL,
0, src, dst, msg, sizeof(msg));
}
@@ -2319,7 +2213,7 @@ static bool ctl_received(struct mesh_net *net, bool frnd, uint32_t iv_index,
}
if (n) {
- mesh_net_transport_send(net, NULL, false,
+ mesh_net_transport_send(net, 0, false,
mesh_net_get_iv_index(net), rsp_ttl,
0, dst & 0x8000 ? 0 : dst, src,
msg, n);
@@ -2355,73 +2249,6 @@ static void *check_fast_cache(struct mesh_net *net, uint64_t hash)
return new_hash;
}
-static bool match_keyset(const void *a, const void *b)
-{
- const struct mesh_friend *frnd = a;
- const struct mesh_key_set *key_set = b;
-
- return (key_set == &frnd->key_set) || (key_set == &frnd->new_key_set);
-}
-
-static void try_decode(void *a, void *b)
-{
- struct mesh_key_set *key_set = a;
- struct net_decode *decode = b;
- uint8_t tmp[29];
- bool status;
-
- if (decode->key_set || key_set->nid != decode->nid)
- return;
-
- status = mesh_crypto_packet_decode(decode->packet, decode->size,
- decode->proxy, tmp, decode->iv_index,
- key_set->enc_key, key_set->privacy_key);
-
- if (!status)
- return;
-
- memcpy(decode->packet, tmp, decode->size);
- decode->key_set = key_set;
- if (key_set->frnd)
- decode->frnd = l_queue_find(decode->net->friends,
- match_keyset, key_set);
- else
- decode->frnd = NULL;
-}
-
-static struct mesh_key_set *net_packet_decode(struct mesh_net *net,
- uint32_t iv_index, uint8_t nid,
- struct mesh_friend **frnd,
- bool proxy,
- uint8_t *packet, uint8_t size)
-{
- struct net_decode decode = {
- .net = net,
- .key_set = NULL,
- .nid = nid,
- .iv_index = iv_index,
- .packet = packet,
- .size = size,
- .proxy = proxy,
- };
-
- l_queue_foreach(net->key_sets, try_decode, &decode);
-
- if (decode.key_set != NULL) {
- *frnd = decode.frnd;
- return decode.key_set;
- }
- return NULL;
-}
-
-static bool match_key_nid(const void *a, const void *b)
-{
- const struct mesh_key_set *key_set = a;
- uint8_t nid = L_PTR_TO_UINT(b);
-
- return key_set->nid == nid;
-}
-
static bool match_by_dst(const void *a, const void *b)
{
const struct mesh_destination *dest = a;
@@ -2469,30 +2296,23 @@ static void packet_received(void *user_data, const void *data, uint8_t size,
struct mesh_net *net = user_data;
uint32_t iv_index;
uint8_t iv_flag;
- uint8_t nid;
const uint8_t *msg = data;
+ uint8_t *out;
+ size_t out_size;
uint8_t app_msg_len;
uint8_t net_ttl, net_key_id, net_segO, net_segN, net_opcode;
uint32_t net_seq, cache_cookie;
uint16_t net_src, net_dst, net_seqZero;
uint8_t packet[31];
bool net_ctl, net_segmented, net_szmic, net_relay;
- struct mesh_friend *net_frnd;
+ struct mesh_friend *net_frnd = NULL;
bool drop = false;
uint64_t hash, *isNew = NULL;
- struct mesh_key_set *keys;
-
- nid = msg[0] & 0x7f;
-
- /* Ignore unrecognized NIDs */
- if (!(l_queue_find(net->key_sets, match_key_nid, L_UINT_TO_PTR(nid)))) {
- /* print_packet("Nope", data, size); */
- return;
- }
+ uint32_t key_id;
iv_flag = msg[0] >> 7;
iv_index = net->iv_index;
- l_debug("%s iv_index %d NID: %2.2x", __func__, iv_index, nid);
+ l_debug("%s iv_index %d NID: %2.2x", __func__, iv_index, msg[0] & 0x7f);
if (sizeof(uint16_t) <= sizeof(void *)) {
/* Add in additional cache to allow us to
@@ -2520,9 +2340,9 @@ static void packet_received(void *user_data, const void *data, uint8_t size,
if (!drop)
print_packet("RX: Network [enc] :", data, size);
- keys = net_packet_decode(net, iv_index, nid, &net_frnd, false,
- packet + 2, size);
- if (keys == NULL) {
+ key_id = net_key_decrypt(iv_index, packet + 2, size, &out, &out_size);
+
+ if (!key_id) {
l_debug("Failed to decode packet");
/* Remove fast-cache-hash */
l_queue_remove(net->fast_cache, isNew);
@@ -2530,6 +2350,8 @@ static void packet_received(void *user_data, const void *data, uint8_t size,
return;
}
+ memcpy(packet + 2, out, out_size);
+
if (!drop)
print_packet("RX: Network [clr] :", packet + 2, size);
@@ -2552,7 +2374,8 @@ static void packet_received(void *user_data, const void *data, uint8_t size,
if (net->friend_addr) {
struct mesh_subnet *subnet;
- subnet = l_queue_find(net->subnets, match_key_set, keys);
+ subnet = l_queue_find(net->subnets, match_key_id,
+ L_UINT_TO_PTR(key_id));
if (subnet)
return;
@@ -2675,8 +2498,7 @@ static void packet_received(void *user_data, const void *data, uint8_t size,
packet[2 + 1] = (packet[2 + 1] & ~TTL_MASK) | (net_ttl - 1);
- if (!mesh_crypto_packet_encode(packet + 2, size, keys->enc_key,
- iv_index, keys->privacy_key)) {
+ if (!net_key_encrypt(key_id, iv_index, packet + 2, size)) {
l_error("Failed to encode relay packet");
return;
}
@@ -2709,8 +2531,7 @@ static void set_network_beacon(void *a, void *b)
struct mesh_net *net = b;
uint8_t beacon_data[22];
- if (!create_secure_beacon(net, subnet, beacon_data,
- sizeof(beacon_data)))
+ if (!create_secure_beacon(net, subnet, beacon_data))
return;
if (memcmp(&subnet->snb.beacon[1], beacon_data,
@@ -2889,10 +2710,9 @@ static void process_beacon(void *user_data, const void *data,
struct mesh_net *net = user_data;
const uint8_t *buf = data;
uint32_t iv_index;
- uint64_t cmac;
bool iv_update, rxed_iv_update, rxed_key_refresh;
struct mesh_subnet *subnet;
- struct net_key *keys;
+ uint32_t key_id;
bool kr_transition = false;
if (size != 22 || buf[0] != 0x01)
@@ -2914,8 +2734,10 @@ static void process_beacon(void *user_data, const void *data,
iv_update = true;
}
- subnet = l_queue_find(net->subnets, match_network_id, buf + 2);
- if (!subnet)
+ key_id = net_key_network_id(buf + 2);
+ subnet = l_queue_find(net->subnets, match_key_id,
+ L_UINT_TO_PTR(key_id));
+ if (!subnet || !key_id)
return;
/* Check if Key Refresh flag value is different from
@@ -2929,14 +2751,13 @@ static void process_beacon(void *user_data, const void *data,
*/
if (net->provisioner)
kr_transition = false;
- else if (subnet->updated.key_set.nid == NET_NID_INVALID)
+ else if (!subnet->net_key_upd)
kr_transition = false;
/* If beacon's key refresh bit is not set and the beacon is encoded
* with the "new" network key, this signals transition from
* key refresh procedure to normal operation
*/
- else if (!rxed_key_refresh &&
- !memcmp(subnet->updated.network_id, buf + 2, 8))
+ else if (!rxed_key_refresh && subnet->net_key_upd == key_id)
kr_transition = true;
if ((net->iv_index + IV_IDX_DIFF_RANGE < iv_index) ||
@@ -2952,26 +2773,16 @@ static void process_beacon(void *user_data, const void *data,
}
if (!rxed_key_refresh && !subnet->key_refresh && !kr_transition)
- keys = &subnet->current;
- else if (subnet->updated.key_set.nid != NET_NID_INVALID)
- keys = &subnet->updated;
+ key_id = subnet->net_key_cur;
+ else if (subnet->net_key_upd)
+ key_id = subnet->net_key_upd;
else
return;
- if (memcmp(keys->network_id, buf + 2, 8))
- return;
-
- /* Any behavioral changes must pass CMAC test */
- if (!mesh_crypto_beacon_cmac(keys->beacon_key, keys->network_id,
- iv_index, rxed_key_refresh,
- rxed_iv_update, &cmac)) {
- l_error("mesh_crypto_beacon_cmac failed");
- return;
- }
-
- if (cmac != l_get_be64(buf + 14)) {
- l_error("cmac compare failed %16.16lx != %16.16lx",
- cmac, l_get_be64(buf + 14));
+ if (!net_key_snb_check(key_id, iv_index, rxed_key_refresh,
+ rxed_iv_update,
+ l_get_be64(buf + 14))) {
+ l_error("mesh_crypto_beacon verify failed");
return;
}
@@ -3033,7 +2844,7 @@ static void lpn_process_beacon(void *user_data, const void *data,
/* If the local node is a provisioner or there are no new keys,
* ignore KR beacon setting
*/
- if (subnet->updated.key_set.nid == NET_NID_INVALID)
+ if (!subnet->net_key_upd)
kr_transition = false;
if ((net->iv_index + IV_IDX_DIFF_RANGE < iv_index) ||
@@ -3181,7 +2992,7 @@ void mesh_net_sub_list_add(struct mesh_net *net, uint16_t addr)
l_put_be16(addr, msg + n);
n += 2;
- mesh_net_transport_send(net, NULL, false,
+ mesh_net_transport_send(net, 0, false,
mesh_net_get_iv_index(net), 0,
0, 0, 0, msg, n);
}
@@ -3194,7 +3005,7 @@ void mesh_net_sub_list_del(struct mesh_net *net, uint16_t addr)
l_put_be16(addr, msg + n);
n += 2;
- mesh_net_transport_send(net, NULL, false,
+ mesh_net_transport_send(net, 0, false,
mesh_net_get_iv_index(net), 0,
0, 0, 0, msg, n);
}
@@ -3304,7 +3115,7 @@ static bool send_seg(struct mesh_net *net, struct mesh_sar *msg, uint8_t segO)
uint8_t packet_len;
uint8_t segN = SEG_MAX(msg->len);
uint16_t seg_off = SEG_OFF(segO);
- struct mesh_key_set *key_set = NULL;
+ uint32_t key_id = 0;
uint32_t seq_num = mesh_net_next_seq_num(net);
if (segN) {
@@ -3341,26 +3152,19 @@ static bool send_seg(struct mesh_net *net, struct mesh_sar *msg, uint8_t segO)
print_packet("Clr-Net Tx", packet + 1, packet_len);
if (msg->frnd_cred && net->friend_addr)
- key_set = frnd_get_key(net);
+ key_id = frnd_get_key(net);
- if (key_set == NULL) {
+ if (!key_id) {
struct mesh_subnet *subnet = get_primary_subnet(net);
- key_set = &subnet->tx->key_set;
+ key_id = subnet->net_key_tx;
}
- if (!mesh_crypto_packet_encode(packet + 1, packet_len, key_set->enc_key,
- msg->iv_index, key_set->privacy_key)) {
+ if (!net_key_encrypt(key_id, msg->iv_index, packet + 1, packet_len)) {
l_error("Failed to encode packet");
return false;
}
- print_packet("Step 3", packet + 1, packet_len);
- if (!mesh_crypto_packet_label(packet + 1, packet_len,
- msg->iv_index, key_set->nid)) {
- l_error("Failed to label packet");
- return false;
- }
/* print_packet("Step 4", packet + 1, packet_len); */
{
@@ -3381,7 +3185,7 @@ static bool send_seg(struct mesh_net *net, struct mesh_sar *msg, uint8_t segO)
return true;
}
-void mesh_net_send_seg(struct mesh_net *net, struct mesh_key_set *key_set,
+void mesh_net_send_seg(struct mesh_net *net, uint32_t net_key_id,
uint32_t iv_index,
uint8_t ttl,
uint32_t seq,
@@ -3393,7 +3197,7 @@ void mesh_net_send_seg(struct mesh_net *net, struct mesh_key_set *key_set,
uint8_t packet[30];
uint8_t packet_len;
bool segmented = !!((hdr >> SEG_HDR_SHIFT) & true);
- uint8_t key_id = (hdr >> KEY_HDR_SHIFT) & KEY_ID_MASK;
+ uint8_t app_key_id = (hdr >> KEY_HDR_SHIFT) & KEY_ID_MASK;
bool szmic = !!((hdr >> SZMIC_HDR_SHIFT) & true);
uint16_t seqZero = (hdr >> SEQ_ZERO_HDR_SHIFT) & SEQ_ZERO_MASK;
uint8_t segO = (hdr >> SEGO_HDR_SHIFT) & SEG_MASK;
@@ -3409,7 +3213,7 @@ void mesh_net_send_seg(struct mesh_net *net, struct mesh_key_set *key_set,
seq,
src, dst,
0,
- segmented, key_id,
+ segmented, app_key_id,
szmic, false, seqZero,
segO, segN,
seg, seg_len,
@@ -3418,18 +3222,11 @@ void mesh_net_send_seg(struct mesh_net *net, struct mesh_key_set *key_set,
return;
}
- if (!mesh_crypto_packet_encode(packet + 1, packet_len, key_set->enc_key,
- iv_index, key_set->privacy_key)) {
+ if (!net_key_encrypt(net_key_id, iv_index, packet + 1, packet_len)) {
l_error("Failed to encode packet");
return;
}
- /* print_packet("Step 3", packet + 0, packet_len); */
- if (!mesh_crypto_packet_label(packet + 1, packet_len, iv_index,
- key_set->nid)) {
- l_error("Failed to label packet");
- return;
- }
/* print_packet("Step 4", packet + 1, packet_len); */
send_msg_pkt(net, packet, packet_len + 1);
@@ -3557,7 +3354,7 @@ void mesh_net_app_send_cancel(struct mesh_net *net, unsigned int id)
}
/* TODO: add net key index */
-void mesh_net_ack_send(struct mesh_net *net, struct mesh_key_set *key_set,
+void mesh_net_ack_send(struct mesh_net *net, uint32_t key_id,
uint32_t iv_index,
uint8_t ttl,
uint32_t seq,
@@ -3589,25 +3386,17 @@ void mesh_net_ack_send(struct mesh_net *net, struct mesh_key_set *key_set,
return;
}
- if (key_set == NULL) {
+ if (!key_id) {
struct mesh_subnet *subnet = get_primary_subnet(net);
- key_set = &subnet->tx->key_set;
+ key_id = subnet->net_key_tx;
}
- if (!mesh_crypto_packet_encode(pkt + 1, pkt_len, key_set->enc_key,
- iv_index, key_set->privacy_key)) {
+ if (!net_key_encrypt(key_id, iv_index, pkt + 1, pkt_len)) {
l_error("Failed to encode packet");
return;
}
- /* print_packet("Step 3", pkt, pkt_len); */
- if (!mesh_crypto_packet_label(pkt + 1, pkt_len,
- iv_index, key_set->nid)) {
- l_error("Failed to label packet");
- return;
- }
-
/* print_packet("Step 4", pkt, pkt_len); */
send_msg_pkt(net, pkt, pkt_len + 1);
@@ -3619,7 +3408,7 @@ void mesh_net_ack_send(struct mesh_net *net, struct mesh_key_set *key_set,
}
/* TODO: add net key index */
-void mesh_net_transport_send(struct mesh_net *net, struct mesh_key_set *key_set,
+void mesh_net_transport_send(struct mesh_net *net, uint32_t key_id,
bool fast, uint32_t iv_index, uint8_t ttl,
uint32_t seq, uint16_t src, uint16_t dst,
const uint8_t *msg, uint16_t msg_len)
@@ -3646,7 +3435,7 @@ void mesh_net_transport_send(struct mesh_net *net, struct mesh_key_set *key_set,
return;
/* Enqueue for Friend if forwardable and from us */
- if (!(key_set) && src >= net->src_addr && src <= net->last_addr) {
+ if (!key_id && src >= net->src_addr && src <= net->last_addr) {
uint32_t hdr = msg[0] << OPCODE_HDR_SHIFT;
uint8_t frnd_ttl = ttl;
@@ -3662,17 +3451,17 @@ void mesh_net_transport_send(struct mesh_net *net, struct mesh_key_set *key_set,
/* Deliver to Local entities if applicable */
if (!(dst & 0x8000) && src >= net->src_addr && src <= net->last_addr) {
- result = ctl_received(net, !!(key_set),
+ result = ctl_received(net, !!(key_id),
iv_index, ttl,
mesh_net_next_seq_num(net),
src, dst,
msg[0], 0, msg + 1, msg_len - 1);
}
- if (key_set == NULL) {
+ if (!key_id) {
struct mesh_subnet *subnet = get_primary_subnet(net);
- key_set = &subnet->tx->key_set;
+ key_id = subnet->net_key_tx;
use_seq = mesh_net_next_seq_num(net);
if (result || (dst >= net->src_addr && dst <= net->last_addr))
@@ -3692,16 +3481,8 @@ void mesh_net_transport_send(struct mesh_net *net, struct mesh_key_set *key_set,
/* print_packet("Step 2", pkt + 1, pkt_len); */
- if (!mesh_crypto_packet_encode(pkt + 1, pkt_len, key_set->enc_key,
- iv_index, key_set->privacy_key)) {
- l_error("Failed to encode pkt");
- return;
- }
-
- /* print_packet("Step 3", pkt + 1, pkt_len); */
- if (!mesh_crypto_packet_label(pkt, pkt_len, iv_index,
- key_set->nid)) {
- l_error("Failed to label pkt");
+ if (!net_key_encrypt(key_id, iv_index, pkt + 1, pkt_len)) {
+ l_error("Failed to encode packet");
return;
}
@@ -3787,15 +3568,15 @@ int mesh_net_kr_phase_one(struct mesh_net *net, uint16_t idx,
if (!subnet)
return MESH_STATUS_CANNOT_UPDATE;
- if (subnet->updated.key_set.nid != NET_NID_INVALID)
+ if (subnet->net_key_upd) {
+ net_key_unref(subnet->net_key_upd);
l_info("Warning: overwriting new keys");
+ }
/* Preserve starting data */
- subnet->updated = subnet->current;
+ subnet->net_key_upd = net_key_add(value);
- /* Generate new keys */
- if (!create_keys(net, &subnet->updated, value)) {
- subnet->updated.key_set.nid = NET_NID_INVALID;
+ if (!subnet->net_key_upd) {
l_error("Failed to start key refresh phase one");
return MESH_STATUS_CANNOT_UPDATE;
}
@@ -3805,11 +3586,11 @@ int mesh_net_kr_phase_one(struct mesh_net *net, uint16_t idx,
frnd_key_refresh(net, 1);
else
/* If we are a Friend-Node, generate all our new keys */
- l_queue_foreach(net->friends, frnd_kr_phase1, (void *)value);
+ l_queue_foreach(net->friends, frnd_kr_phase1,
+ L_UINT_TO_PTR(subnet->net_key_upd));
- l_info("key refresh phase 1: NID 0x%2x", subnet->updated.key_set.nid);
+ l_info("key refresh phase 1: Key ID %d", subnet->net_key_upd);
- mesh_net_add_keyset(net, &subnet->updated.key_set);
subnet->kr_phase = KEY_REFRESH_PHASE_ONE;
return MESH_STATUS_SUCCESS;
@@ -3825,12 +3606,12 @@ int mesh_net_key_refresh_phase_two(struct mesh_net *net, uint16_t idx)
subnet = l_queue_find(net->subnets, match_key_index,
L_UINT_TO_PTR(idx));
- if (!subnet || subnet->updated.key_set.nid == NET_NID_INVALID)
+ if (!subnet || !subnet->net_key_upd)
return MESH_STATUS_INVALID_NETKEY;
l_info("Key refresh procedure phase 2: start using new net TX keys");
subnet->key_refresh = 1;
- subnet->tx = &subnet->updated;
+ subnet->net_key_tx = subnet->net_key_upd;
/* TODO: Provisioner may need to stay in phase three until
* it hears beacons from all the nodes
*/
@@ -3855,7 +3636,7 @@ int mesh_net_key_refresh_finish(struct mesh_net *net, uint16_t idx)
subnet = l_queue_find(net->subnets, match_key_index,
L_UINT_TO_PTR(idx));
- if (!subnet || subnet->updated.key_set.nid == NET_NID_INVALID)
+ if (!subnet || !subnet->net_key_upd)
return MESH_STATUS_INVALID_NETKEY;
if (subnet->kr_phase == KEY_REFRESH_PHASE_NONE)
@@ -3864,10 +3645,9 @@ int mesh_net_key_refresh_finish(struct mesh_net *net, uint16_t idx)
l_info("Key refresh phase 3: use new keys only, discard old ones");
/* Switch to using new keys, discard old ones */
- subnet->current = subnet->updated;
- subnet->tx = &subnet->current;
- subnet->updated.key_set.nid = NET_NID_INVALID;
- mesh_net_remove_keyset(net, &subnet->updated.key_set);
+ net_key_unref(subnet->net_key_cur);
+ subnet->net_key_tx = subnet->net_key_cur = subnet->net_key_upd;
+ subnet->net_key_upd = 0;
subnet->key_refresh = 0;
subnet->kr_phase = KEY_REFRESH_PHASE_NONE;
set_network_beacon(subnet, net);
@@ -3915,7 +3695,7 @@ void mesh_net_heartbeat_send(struct mesh_net *net)
l_put_be16(hb->features, msg + n);
n += 2;
- mesh_net_transport_send(net, NULL, false, mesh_net_get_iv_index(net),
+ mesh_net_transport_send(net, 0, false, mesh_net_get_iv_index(net),
hb->pub_ttl, 0, 0, hb->pub_dst, msg, n);
}
diff --git a/mesh/net.h b/mesh/net.h
index e48380314..b8eb0699d 100644
--- a/mesh/net.h
+++ b/mesh/net.h
@@ -183,12 +183,12 @@ struct mesh_friend {
uint16_t *grp_list;
uint32_t poll_timeout;
uint32_t last_hdr;
+ uint32_t net_key_cur;
+ uint32_t net_key_upd;
uint16_t dst; /* Primary Element unicast addr */
uint16_t fn_cnt;
uint16_t lp_cnt;
int16_t grp_cnt;
- struct mesh_key_set key_set;
- struct mesh_key_set new_key_set;
uint8_t ele_cnt;
uint8_t frd;
uint8_t frw;
@@ -283,8 +283,6 @@ bool mesh_net_set_proxy_mode(struct mesh_net *net, bool enable);
bool mesh_net_set_relay_mode(struct mesh_net *net, bool enable, uint8_t cnt,
uint8_t interval);
bool mesh_net_set_friend_mode(struct mesh_net *net, bool enable);
-bool mesh_net_add_keyset(struct mesh_net *net, struct mesh_key_set *key_set);
-bool mesh_net_remove_keyset(struct mesh_net *net, struct mesh_key_set *key_set);
int mesh_net_del_key(struct mesh_net *net, uint16_t net_idx);
int mesh_net_add_key(struct mesh_net *net, bool update,
uint16_t net_idx, const void *key);
@@ -292,13 +290,13 @@ 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);
bool mesh_net_get_key(struct mesh_net *net, bool new_key, uint16_t idx,
- uint8_t key[16]);
+ uint32_t *key_id);
bool mesh_net_attach(struct mesh_net *net, struct mesh_io *io);
struct mesh_io *mesh_net_detach(struct mesh_net *net);
struct l_queue *mesh_net_get_app_keys(struct mesh_net *net);
bool mesh_net_flush(struct mesh_net *net);
-void mesh_net_transport_send(struct mesh_net *net, struct mesh_key_set *key_set,
+void mesh_net_transport_send(struct mesh_net *net, uint32_t key_id,
bool fast, uint32_t iv_index, uint8_t ttl,
uint32_t seq, uint16_t src, uint16_t dst,
const uint8_t *msg, uint16_t msg_len);
@@ -310,7 +308,7 @@ unsigned int mesh_net_app_send(struct mesh_net *net, bool frnd_cred,
mesh_net_status_func_t status_func,
void *user_data);
void mesh_net_app_send_cancel(struct mesh_net *net, unsigned int id);
-void mesh_net_ack_send(struct mesh_net *net, struct mesh_key_set *key_set,
+void mesh_net_ack_send(struct mesh_net *net, uint32_t key_id,
uint32_t iv_index, uint8_t ttl, uint32_t seq,
uint16_t src, uint16_t dst, bool rly,
uint16_t seqZero, uint32_t ack_flags);
@@ -346,7 +344,7 @@ int mesh_net_kr_phase_one(struct mesh_net *net, uint16_t net_idx,
const uint8_t *key);
int mesh_net_key_refresh_phase_two(struct mesh_net *net, uint16_t net_idx);
int mesh_net_key_refresh_finish(struct mesh_net *net, uint16_t net_idx);
-void mesh_net_send_seg(struct mesh_net *net, struct mesh_key_set *key_set,
+void mesh_net_send_seg(struct mesh_net *net, uint32_t key_id,
uint32_t iv_index, uint8_t ttl, uint32_t seq,
uint16_t src, uint16_t dst, uint32_t hdr,
const void *seg, uint16_t seg_len);
diff --git a/mesh/provision.c b/mesh/provision.c
index c7cb5f160..17422ce0a 100644
--- a/mesh/provision.c
+++ b/mesh/provision.c
@@ -39,6 +39,7 @@
#include "src/shared/ecc.h"
#include "mesh/display.h"
+#include "mesh/net_keys.h"
#include "mesh/crypto.h"
#include "mesh/net.h"
#include "mesh/prov.h"
@@ -286,6 +287,7 @@ static void send_prov_data(struct mesh_prov *prov)
struct mesh_net_prov_caps *caps = mesh_net_prov_caps_get(net);
uint64_t mic;
uint32_t iv_index;
+ uint32_t net_key_id;
uint8_t snb_flags;
uint16_t net_idx = mesh_prov_get_idx(prov);
uint8_t prov_data[1 + 16 + 2 + 1 + 4 + 2 + sizeof(mic)] = { PROV_DATA };
@@ -296,7 +298,8 @@ static void send_prov_data(struct mesh_prov *prov)
prov_expected = PROV_COMPLETE;
mesh_net_get_snb_state(net, &snb_flags, &iv_index);
- mesh_net_get_key(net, !!(snb_flags & 0x01), net_idx, prov_data + 1);
+ mesh_net_get_key(net, !!(snb_flags & 0x01), net_idx, &net_key_id);
+ net_key_retrieve(net_key_id, prov_data + 1);
l_put_be16(net_idx, prov_data + 1 + 16);
l_put_u8(snb_flags, prov_data + 1 + 16 + 2);
l_put_be32(iv_index, prov_data + 1 + 16 + 2 + 1);
--
2.14.4
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2018-09-19 20:40 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-09-19 20:40 [PATCH BlueZ 0/2] Central Net Key storage cache for multiple Nodes Brian Gix
2018-09-19 20:40 ` [PATCH BlueZ 1/2] mesh: Add centralized caching Net Key management Brian Gix
2018-09-19 20:40 ` [PATCH BlueZ 2/2] mesh: Refactor friend.c and net.c for central key DB Brian Gix
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).