linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH BlueZ v2 0/5] mesh: Add NVM storage of Replay Protection List
@ 2020-01-25  0:43 Brian Gix
  2020-01-25  0:43 ` [PATCH BlueZ v2 1/5] mesh: Relocate tree deletion to util.c/h Brian Gix
                   ` (5 more replies)
  0 siblings, 6 replies; 8+ messages in thread
From: Brian Gix @ 2020-01-25  0:43 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: brian.gix, inga.stotland

Version 2: Fix path construction code when first reading RPL from NVM


An oversight led to losing our Replay Protection List with every
re-boot. This patch-set makes a number of Replay Protect List
modifications that culminate in adding rpl.c/h, which stores the latest
iv_index/sequence values for each node that handles an incoming packet.

The first 4 patches, does some maintenance required to handle RPL
according the the Mesh Specification.


Brian Gix (5):
  mesh: Relocate tree deletion to util.c/h
  mesh: Move Replay Protection to mesh/net.c
  mesh: Remove unneeded Sequence Number increment
  mesh: Apply Replay Protection to all incoming packets
  mesh: Add NVM storage of Replay Protection

 Makefile.mesh           |   1 +
 mesh/appkey.c           | 102 ---------------
 mesh/appkey.h           |   3 -
 mesh/mesh-config-json.c |  20 +--
 mesh/model.c            |  16 +--
 mesh/net.c              | 112 ++++++++++++++--
 mesh/net.h              |   3 +
 mesh/rpl.c              | 277 ++++++++++++++++++++++++++++++++++++++++
 mesh/rpl.h              |  30 +++++
 mesh/util.c             |  25 ++++
 mesh/util.h             |   1 +
 11 files changed, 447 insertions(+), 143 deletions(-)
 create mode 100644 mesh/rpl.c
 create mode 100644 mesh/rpl.h

-- 
2.21.1


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH BlueZ v2 1/5] mesh: Relocate tree deletion to util.c/h
  2020-01-25  0:43 [PATCH BlueZ v2 0/5] mesh: Add NVM storage of Replay Protection List Brian Gix
@ 2020-01-25  0:43 ` Brian Gix
  2020-01-25  0:43 ` [PATCH BlueZ v2 2/5] mesh: Move Replay Protection to mesh/net.c Brian Gix
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Brian Gix @ 2020-01-25  0:43 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: brian.gix, inga.stotland

---
 mesh/mesh-config-json.c | 20 +-------------------
 mesh/util.c             | 25 +++++++++++++++++++++++++
 mesh/util.h             |  1 +
 3 files changed, 27 insertions(+), 19 deletions(-)

diff --git a/mesh/mesh-config-json.c b/mesh/mesh-config-json.c
index 5855149e3..ad2d4d0f8 100644
--- a/mesh/mesh-config-json.c
+++ b/mesh/mesh-config-json.c
@@ -2253,24 +2253,6 @@ bool mesh_config_load_nodes(const char *cfgdir_name, mesh_config_node_func_t cb,
 	return true;
 }
 
-static int del_fobject(const char *fpath, const struct stat *sb, int typeflag,
-						struct FTW *ftwbuf)
-{
-	switch (typeflag) {
-	case FTW_DP:
-		rmdir(fpath);
-		l_debug("RMDIR %s", fpath);
-		break;
-
-	case FTW_SL:
-	default:
-		remove(fpath);
-		l_debug("RM %s", fpath);
-		break;
-	}
-	return 0;
-}
-
 void mesh_config_destroy(struct mesh_config *cfg)
 {
 	char *node_dir, *node_name;
@@ -2291,7 +2273,7 @@ void mesh_config_destroy(struct mesh_config *cfg)
 	if (strcmp(node_name, uuid))
 		return;
 
-	nftw(node_dir, del_fobject, 5, FTW_DEPTH | FTW_PHYS);
+	del_path(node_dir);
 
 	/* Release node config object */
 	mesh_config_release(cfg);
diff --git a/mesh/util.c b/mesh/util.c
index 986ba4b28..43340f159 100644
--- a/mesh/util.c
+++ b/mesh/util.c
@@ -24,6 +24,7 @@
 #define _GNU_SOURCE
 #include <dirent.h>
 #include <ftw.h>
+#include <unistd.h>
 #include <stdio.h>
 #include <limits.h>
 #include <time.h>
@@ -129,3 +130,27 @@ int create_dir(const char *dir_name)
 
 	return 0;
 }
+
+static int del_fobject(const char *fpath, const struct stat *sb, int typeflag,
+						struct FTW *ftwbuf)
+{
+	switch (typeflag) {
+	case FTW_DP:
+		rmdir(fpath);
+		l_debug("RMDIR %s", fpath);
+		break;
+
+	case FTW_SL:
+	default:
+		remove(fpath);
+		l_debug("RM %s", fpath);
+		break;
+	}
+	return 0;
+}
+
+
+void del_path(const char *path)
+{
+	nftw(path, del_fobject, 5, FTW_DEPTH | FTW_PHYS);
+}
diff --git a/mesh/util.h b/mesh/util.h
index d1e83b573..092d33041 100644
--- a/mesh/util.h
+++ b/mesh/util.h
@@ -23,3 +23,4 @@ bool str2hex(const char *str, uint16_t in_len, uint8_t *out,
 size_t hex2str(uint8_t *in, size_t in_len, char *out, size_t out_len);
 void print_packet(const char *label, const void *data, uint16_t size);
 int create_dir(const char *dir_name);
+void del_path(const char *path);
-- 
2.21.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH BlueZ v2 2/5] mesh: Move Replay Protection to mesh/net.c
  2020-01-25  0:43 [PATCH BlueZ v2 0/5] mesh: Add NVM storage of Replay Protection List Brian Gix
  2020-01-25  0:43 ` [PATCH BlueZ v2 1/5] mesh: Relocate tree deletion to util.c/h Brian Gix
@ 2020-01-25  0:43 ` Brian Gix
  2020-01-25  0:43 ` [PATCH BlueZ v2 3/5] mesh: Remove unneeded Sequence Number increment Brian Gix
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Brian Gix @ 2020-01-25  0:43 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: brian.gix, inga.stotland

The specification calls for a flatter Replay Protection List that
applies to all processed messages, regardless of which credentials
were used to secure them. So storage and checking is now centralized
in mesh/net.c
---
 mesh/appkey.c | 102 -------------------------------------------------
 mesh/appkey.h |   3 --
 mesh/model.c  |   2 +-
 mesh/net.c    | 104 +++++++++++++++++++++++++++++++++++++++++++++-----
 mesh/net.h    |   3 ++
 5 files changed, 99 insertions(+), 115 deletions(-)

diff --git a/mesh/appkey.c b/mesh/appkey.c
index 0eb268782..45d604007 100644
--- a/mesh/appkey.c
+++ b/mesh/appkey.c
@@ -35,7 +35,6 @@
 #include "mesh/appkey.h"
 
 struct mesh_app_key {
-	struct l_queue *replay_cache;
 	uint16_t net_idx;
 	uint16_t app_idx;
 	uint8_t key[16];
@@ -44,12 +43,6 @@ struct mesh_app_key {
 	uint8_t new_key_aid;
 };
 
-struct mesh_msg {
-	uint32_t iv_index;
-	uint32_t seq;
-	uint16_t src;
-};
-
 static bool match_key_index(const void *a, const void *b)
 {
 	const struct mesh_app_key *key = a;
@@ -66,103 +59,11 @@ static bool match_bound_key(const void *a, const void *b)
 	return key->net_idx == idx;
 }
 
-static bool match_replay_cache(const void *a, const void *b)
-{
-	const struct mesh_msg *msg = a;
-	uint16_t src = L_PTR_TO_UINT(b);
-
-	return src == msg->src;
-}
-
-static bool clean_old_iv_index(void *a, void *b)
-{
-	struct mesh_msg *msg = a;
-	uint32_t iv_index = L_PTR_TO_UINT(b);
-
-	if (iv_index < 2)
-		return false;
-
-	if (msg->iv_index < iv_index - 1) {
-		l_free(msg);
-		return true;
-	}
-
-	return false;
-}
-
-bool appkey_msg_in_replay_cache(struct mesh_net *net, uint16_t idx,
-				uint16_t src, uint16_t crpl, uint32_t seq,
-				uint32_t iv_index)
-{
-	struct mesh_app_key *key;
-	struct mesh_msg *msg;
-	struct l_queue *app_keys;
-
-	app_keys = mesh_net_get_app_keys(net);
-	if (!app_keys)
-		return false;
-
-	l_debug("Test Replay src: %4.4x seq: %6.6x iv: %8.8x",
-						src, seq, iv_index);
-
-	key = l_queue_find(app_keys, match_key_index, L_UINT_TO_PTR(idx));
-
-	if (!key)
-		return false;
-
-	msg = l_queue_find(key->replay_cache, match_replay_cache,
-						L_UINT_TO_PTR(src));
-
-	if (msg) {
-		if (iv_index > msg->iv_index) {
-			msg->seq = seq;
-			msg->iv_index = iv_index;
-			return false;
-		}
-
-		if (seq < msg->seq) {
-			l_debug("Ignoring packet with lower sequence number");
-			return true;
-		}
-
-		if (seq == msg->seq) {
-			l_debug("Message already processed (duplicate)");
-			return true;
-		}
-
-		msg->seq = seq;
-
-		return false;
-	}
-
-	l_debug("New Entry for %4.4x", src);
-	if (key->replay_cache == NULL)
-		key->replay_cache = l_queue_new();
-
-	/* Replay Cache is fixed sized */
-	if (l_queue_length(key->replay_cache) >= crpl) {
-		int ret = l_queue_foreach_remove(key->replay_cache,
-				clean_old_iv_index, L_UINT_TO_PTR(iv_index));
-
-		if (!ret)
-			return true;
-	}
-
-	msg = l_new(struct mesh_msg, 1);
-	msg->src = src;
-	msg->seq = seq;
-	msg->iv_index = iv_index;
-	l_queue_push_head(key->replay_cache, msg);
-
-	return false;
-}
-
 static struct mesh_app_key *app_key_new(void)
 {
 	struct mesh_app_key *key = l_new(struct mesh_app_key, 1);
 
 	key->new_key_aid = 0xFF;
-	key->replay_cache = l_queue_new();
 	return key;
 }
 
@@ -192,7 +93,6 @@ void appkey_key_free(void *data)
 	if (!key)
 		return;
 
-	l_queue_destroy(key->replay_cache, l_free);
 	l_free(key);
 }
 
@@ -403,8 +303,6 @@ int appkey_key_add(struct mesh_net *net, uint16_t net_idx, uint16_t app_idx,
 	key->app_idx = app_idx;
 	l_queue_push_tail(app_keys, key);
 
-	l_queue_clear(key->replay_cache, l_free);
-
 	return MESH_STATUS_SUCCESS;
 }
 
diff --git a/mesh/appkey.h b/mesh/appkey.h
index b3e548071..23b474a0a 100644
--- a/mesh/appkey.h
+++ b/mesh/appkey.h
@@ -25,9 +25,6 @@ struct mesh_app_key;
 bool appkey_key_init(struct mesh_net *net, uint16_t net_idx, uint16_t app_idx,
 				uint8_t *key_value, uint8_t *new_key_value);
 void appkey_key_free(void *data);
-bool appkey_msg_in_replay_cache(struct mesh_net *net, uint16_t idx,
-				uint16_t src, uint16_t crpl, uint32_t seq,
-				uint32_t iv_index);
 const uint8_t *appkey_get_key(struct mesh_net *net, uint16_t app_idx,
 							uint8_t *key_id);
 int appkey_get_key_idx(struct mesh_app_key *app_key,
diff --git a/mesh/model.c b/mesh/model.c
index 6d7674ee5..0018c7cff 100644
--- a/mesh/model.c
+++ b/mesh/model.c
@@ -1000,7 +1000,7 @@ bool mesh_model_rx(struct mesh_node *node, bool szmict, uint32_t seq0,
 	if (key_aid != APP_AID_DEV) {
 		uint16_t crpl = node_get_crpl(node);
 
-		if (appkey_msg_in_replay_cache(net, (uint16_t) decrypt_idx, src,
+		if (net_msg_in_replay_cache(net, (uint16_t) decrypt_idx, src,
 							crpl, seq, iv_index)) {
 			result = true;
 			goto done;
diff --git a/mesh/net.c b/mesh/net.c
index 219217793..71ff2cea0 100644
--- a/mesh/net.c
+++ b/mesh/net.c
@@ -135,6 +135,7 @@ struct mesh_net {
 
 	struct l_queue *subnets;
 	struct l_queue *msg_cache;
+	struct l_queue *replay_cache;
 	struct l_queue *sar_in;
 	struct l_queue *sar_out;
 	struct l_queue *frnd_msgs;
@@ -255,6 +256,12 @@ struct net_beacon_data {
 	bool processed;
 };
 
+struct mesh_rpl {
+	uint32_t iv_index;
+	uint32_t seq;
+	uint16_t src;
+};
+
 #define FAST_CACHE_SIZE 8
 static struct l_queue *fast_cache;
 static struct l_queue *nets;
@@ -554,13 +561,6 @@ static void mesh_sar_free(void *data)
 	l_free(sar);
 }
 
-static void mesh_msg_free(void *data)
-{
-	struct mesh_msg *msg = data;
-
-	l_free(msg);
-}
-
 static void subnet_free(void *data)
 {
 	struct mesh_subnet *subnet = data;
@@ -688,7 +688,8 @@ void mesh_net_free(struct mesh_net *net)
 		return;
 
 	l_queue_destroy(net->subnets, subnet_free);
-	l_queue_destroy(net->msg_cache, mesh_msg_free);
+	l_queue_destroy(net->msg_cache, l_free);
+	l_queue_destroy(net->replay_cache, l_free);
 	l_queue_destroy(net->sar_in, mesh_sar_free);
 	l_queue_destroy(net->sar_out, mesh_sar_free);
 	l_queue_destroy(net->frnd_msgs, l_free);
@@ -1024,7 +1025,7 @@ int mesh_net_add_key(struct mesh_net *net, uint16_t idx, const uint8_t *value)
 
 void mesh_net_flush_msg_queues(struct mesh_net *net)
 {
-	l_queue_clear(net->msg_cache, mesh_msg_free);
+	l_queue_clear(net->msg_cache, l_free);
 }
 
 uint32_t mesh_net_get_iv_index(struct mesh_net *net)
@@ -3734,3 +3735,88 @@ uint32_t mesh_net_get_instant(struct mesh_net *net)
 
 	return net->instant;
 }
+
+static bool match_replay_cache(const void *a, const void *b)
+{
+	const struct mesh_rpl *rpe = a;
+	uint16_t src = L_PTR_TO_UINT(b);
+
+	return src == rpe->src;
+}
+
+static bool clean_old_iv_index(void *a, void *b)
+{
+	struct mesh_rpl *rpe = a;
+	uint32_t iv_index = L_PTR_TO_UINT(b);
+
+	if (iv_index < 2)
+		return false;
+
+	if (rpe->iv_index < iv_index - 1) {
+		l_free(rpe);
+		return true;
+	}
+
+	return false;
+}
+
+bool net_msg_in_replay_cache(struct mesh_net *net, uint16_t idx,
+				uint16_t src, uint16_t crpl, uint32_t seq,
+				uint32_t iv_index)
+{
+	struct mesh_rpl *rpe;
+
+	/* If anything missing reject this message by returning true */
+	if (!net || !net->node)
+		return true;
+
+	if (!net->replay_cache)
+		net->replay_cache = l_queue_new();
+
+	l_debug("Test Replay src: %4.4x seq: %6.6x iv: %8.8x",
+						src, seq, iv_index);
+
+	rpe = l_queue_find(net->replay_cache, match_replay_cache,
+						L_UINT_TO_PTR(src));
+
+	if (rpe) {
+		if (iv_index > rpe->iv_index) {
+			rpe->seq = seq;
+			rpe->iv_index = iv_index;
+			return false;
+		}
+
+		if (seq < rpe->seq) {
+			l_debug("Ignoring packet with lower sequence number");
+			return true;
+		}
+
+		if (seq == rpe->seq) {
+			l_debug("Message already processed (duplicate)");
+			return true;
+		}
+
+		rpe->seq = seq;
+
+		return false;
+	}
+
+	l_debug("New Entry for %4.4x", src);
+
+	/* Replay Cache is fixed sized */
+	if (l_queue_length(net->replay_cache) >= crpl) {
+		int ret = l_queue_foreach_remove(net->replay_cache,
+				clean_old_iv_index, L_UINT_TO_PTR(iv_index));
+
+		if (!ret)
+			return true;
+	}
+
+	rpe = l_new(struct mesh_rpl, 1);
+	rpe->src = src;
+	rpe->seq = seq;
+	rpe->iv_index = iv_index;
+	l_queue_push_head(net->replay_cache, rpe);
+
+	return false;
+}
diff --git a/mesh/net.h b/mesh/net.h
index 023b61e71..ff0a9bb2b 100644
--- a/mesh/net.h
+++ b/mesh/net.h
@@ -379,3 +379,6 @@ void mesh_net_set_prov(struct mesh_net *net, struct mesh_prov *prov);
 uint32_t mesh_net_get_instant(struct mesh_net *net);
 struct l_queue *mesh_net_get_friends(struct mesh_net *net);
 struct l_queue *mesh_net_get_negotiations(struct mesh_net *net);
+bool net_msg_in_replay_cache(struct mesh_net *net, uint16_t idx,
+				uint16_t src, uint16_t crpl, uint32_t seq,
+				uint32_t iv_index);
-- 
2.21.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH BlueZ v2 3/5] mesh: Remove unneeded Sequence Number increment
  2020-01-25  0:43 [PATCH BlueZ v2 0/5] mesh: Add NVM storage of Replay Protection List Brian Gix
  2020-01-25  0:43 ` [PATCH BlueZ v2 1/5] mesh: Relocate tree deletion to util.c/h Brian Gix
  2020-01-25  0:43 ` [PATCH BlueZ v2 2/5] mesh: Move Replay Protection to mesh/net.c Brian Gix
@ 2020-01-25  0:43 ` Brian Gix
  2020-01-25  0:43 ` [PATCH BlueZ v2 4/5] mesh: Apply Replay Protection to all incoming packets Brian Gix
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Brian Gix @ 2020-01-25  0:43 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: brian.gix, inga.stotland

---
 mesh/net.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/mesh/net.c b/mesh/net.c
index 71ff2cea0..ff43176a3 100644
--- a/mesh/net.c
+++ b/mesh/net.c
@@ -3199,7 +3199,6 @@ bool mesh_net_app_send(struct mesh_net *net, bool frnd_cred, uint16_t src,
 			(dst >= net->src_addr && dst <= net->last_addr)) {
 		/* Adjust our seq_num for "virtual" delivery */
 		net->seq_num += seg_max;
-		mesh_net_next_seq_num(net);
 		return true;
 	}
 
-- 
2.21.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH BlueZ v2 4/5] mesh: Apply Replay Protection to all incoming packets
  2020-01-25  0:43 [PATCH BlueZ v2 0/5] mesh: Add NVM storage of Replay Protection List Brian Gix
                   ` (2 preceding siblings ...)
  2020-01-25  0:43 ` [PATCH BlueZ v2 3/5] mesh: Remove unneeded Sequence Number increment Brian Gix
@ 2020-01-25  0:43 ` Brian Gix
  2020-01-25  0:43 ` [PATCH BlueZ v2 5/5] mesh: Add NVM storage of Replay Protection Brian Gix
  2020-01-27 21:27 ` [PATCH BlueZ v2 0/5] mesh: Add NVM storage of Replay Protection List Rafał Gajda
  5 siblings, 0 replies; 8+ messages in thread
From: Brian Gix @ 2020-01-25  0:43 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: brian.gix, inga.stotland

Replay Protection was only being applied against Application Keys,
but messages with Device Keys are just as vulnerable, and need to be
checked as well.
---
 mesh/model.c | 16 +++++++---------
 1 file changed, 7 insertions(+), 9 deletions(-)

diff --git a/mesh/model.c b/mesh/model.c
index 0018c7cff..92a00496c 100644
--- a/mesh/model.c
+++ b/mesh/model.c
@@ -608,7 +608,7 @@ static bool msg_send(struct mesh_node *node, bool credential, uint16_t src,
 
 	iv_index = mesh_net_get_iv_index(net);
 
-	seq_num = mesh_net_get_seq_num(net);
+	seq_num = mesh_net_next_seq_num(net);
 	if (!mesh_crypto_payload_encrypt(label, msg, out, msg_len, src, dst,
 				key_aid, seq_num, iv_index, szmic, key)) {
 		l_error("Failed to Encrypt Payload");
@@ -949,7 +949,7 @@ bool mesh_model_rx(struct mesh_node *node, bool szmict, uint32_t seq0,
 	struct mesh_net *net = node_get_net(node);
 	uint8_t num_ele;
 	int decrypt_idx, i, ele_idx;
-	uint16_t addr;
+	uint16_t addr, crpl;
 	struct mesh_virtual *decrypt_virt = NULL;
 	bool result = false;
 	bool is_subscription;
@@ -997,14 +997,12 @@ bool mesh_model_rx(struct mesh_node *node, bool szmict, uint32_t seq0,
 
 	/* print_packet("Clr Rx (pre-cache-check)", clear_text, size - 4); */
 
-	if (key_aid != APP_AID_DEV) {
-		uint16_t crpl = node_get_crpl(node);
+	crpl = node_get_crpl(node);
 
-		if (net_msg_in_replay_cache(net, (uint16_t) decrypt_idx, src,
-							crpl, seq, iv_index)) {
-			result = true;
-			goto done;
-		}
+	if (net_msg_in_replay_cache(net, (uint16_t) decrypt_idx, src,
+				crpl, seq, iv_index)) {
+		result = true;
+		goto done;
 	}
 
 	print_packet("Clr Rx", clear_text, size - (szmict ? 8 : 4));
-- 
2.21.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH BlueZ v2 5/5] mesh: Add NVM storage of Replay Protection
  2020-01-25  0:43 [PATCH BlueZ v2 0/5] mesh: Add NVM storage of Replay Protection List Brian Gix
                   ` (3 preceding siblings ...)
  2020-01-25  0:43 ` [PATCH BlueZ v2 4/5] mesh: Apply Replay Protection to all incoming packets Brian Gix
@ 2020-01-25  0:43 ` Brian Gix
  2020-01-27 21:27 ` [PATCH BlueZ v2 0/5] mesh: Add NVM storage of Replay Protection List Rafał Gajda
  5 siblings, 0 replies; 8+ messages in thread
From: Brian Gix @ 2020-01-25  0:43 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: brian.gix, inga.stotland

Mesh specification requires that Replay Protection be preserved
across node restarts.  This adds that storage in
<node_uuid>/rpl/<iv_index>/<src>

Realtime access remains in an l_queue structure, and stored as
messages are processed.
---
 Makefile.mesh |   1 +
 mesh/net.c    |  21 ++--
 mesh/rpl.c    | 277 ++++++++++++++++++++++++++++++++++++++++++++++++++
 mesh/rpl.h    |  30 ++++++
 4 files changed, 322 insertions(+), 7 deletions(-)
 create mode 100644 mesh/rpl.c
 create mode 100644 mesh/rpl.h

diff --git a/Makefile.mesh b/Makefile.mesh
index 401122029..10573b304 100644
--- a/Makefile.mesh
+++ b/Makefile.mesh
@@ -32,6 +32,7 @@ mesh_sources = mesh/mesh.h mesh/mesh.c \
 				mesh/manager.h mesh/manager.c \
 				mesh/pb-adv.h mesh/pb-adv.c \
 				mesh/keyring.h mesh/keyring.c \
+				mesh/rpl.h mesh/rpl.c \
 				mesh/mesh-defs.h
 pkglibexec_PROGRAMS += mesh/bluetooth-meshd
 
diff --git a/mesh/net.c b/mesh/net.c
index ff43176a3..09a4c6834 100644
--- a/mesh/net.c
+++ b/mesh/net.c
@@ -36,6 +36,7 @@
 #include "mesh/mesh-config.h"
 #include "mesh/model.h"
 #include "mesh/appkey.h"
+#include "mesh/rpl.h"
 
 #define abs_diff(a, b) ((a) > (b) ? (a) - (b) : (b) - (a))
 
@@ -256,12 +257,6 @@ struct net_beacon_data {
 	bool processed;
 };
 
-struct mesh_rpl {
-	uint32_t iv_index;
-	uint32_t seq;
-	uint16_t src;
-};
-
 #define FAST_CACHE_SIZE 8
 static struct l_queue *fast_cache;
 static struct l_queue *nets;
@@ -2714,6 +2709,9 @@ static void update_iv_ivu_state(struct mesh_net *net, uint32_t iv_index,
 		struct mesh_config *cfg = node_config_get(net->node);
 
 		mesh_config_write_iv_index(cfg, iv_index, ivu);
+
+		/* Cleanup Replay Protection List NVM */
+		rpl_init(net->node, iv_index);
 	}
 
 	net->iv_index = iv_index;
@@ -3769,8 +3767,11 @@ bool net_msg_in_replay_cache(struct mesh_net *net, uint16_t idx,
 	if (!net || !net->node)
 		return true;
 
-	if (!net->replay_cache)
+	if (!net->replay_cache) {
 		net->replay_cache = l_queue_new();
+		rpl_init(net->node, net->iv_index);
+		rpl_get_list(net->node, net->replay_cache);
+	}
 
 	l_debug("Test Replay src: %4.4x seq: %6.6x iv: %8.8x",
 						src, seq, iv_index);
@@ -3782,6 +3783,7 @@ bool net_msg_in_replay_cache(struct mesh_net *net, uint16_t idx,
 		if (iv_index > rpe->iv_index) {
 			rpe->seq = seq;
 			rpe->iv_index = iv_index;
+			rpl_put_entry(net->node, src, iv_index, seq);
 			return false;
 		}
 
@@ -3797,6 +3799,8 @@ bool net_msg_in_replay_cache(struct mesh_net *net, uint16_t idx,
 
 		rpe->seq = seq;
 
+		rpl_put_entry(net->node, src, iv_index, seq);
+
 		return false;
 	}
 
@@ -3811,6 +3815,9 @@ bool net_msg_in_replay_cache(struct mesh_net *net, uint16_t idx,
 			return true;
 	}
 
+	if (!rpl_put_entry(net->node, src, iv_index, seq))
+		return true;
+
 	rpe = l_new(struct mesh_rpl, 1);
 	rpe->src = src;
 	rpe->seq = seq;
diff --git a/mesh/rpl.c b/mesh/rpl.c
new file mode 100644
index 000000000..27cce4e53
--- /dev/null
+++ b/mesh/rpl.c
@@ -0,0 +1,277 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2020  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
+
+#define _GNU_SOURCE
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <dirent.h>
+
+#include <sys/stat.h>
+
+#include <ell/ell.h>
+
+#include "mesh/mesh-defs.h"
+
+#include "mesh/node.h"
+#include "mesh/net.h"
+#include "mesh/util.h"
+#include "mesh/rpl.h"
+
+const char *rpl_dir = "/rpl";
+
+bool rpl_put_entry(struct mesh_node *node, uint16_t src, uint32_t iv_index,
+								uint32_t seq)
+{
+	const char *node_path;
+	char src_file[PATH_MAX];
+	char seq_txt[7];
+	bool result = false;
+	int fd;
+
+	if (!node || !IS_UNICAST(src))
+		return false;
+
+	node_path = node_get_storage_dir(node);
+
+	if (strlen(node_path) + strlen(rpl_dir) + 15 >= PATH_MAX)
+		return false;
+
+	snprintf(src_file, PATH_MAX, "%s%s/%8.8x/%4.4x", node_path, rpl_dir,
+								iv_index, src);
+
+	fd = open(src_file, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
+	if (fd >= 0) {
+		snprintf(seq_txt, 7, "%6.6x", seq);
+		if (write(fd, seq_txt, 6) == 6)
+			result = true;
+
+		close(fd);
+	}
+
+	if (!result)
+		return false;
+
+	/* Delete RPL entry from old iv_index (if it exists) */
+	iv_index--;
+	snprintf(src_file, PATH_MAX, "%s%s/%8.8x/%4.4x", node_path, rpl_dir,
+								iv_index, src);
+	remove(src_file);
+
+
+	return result;
+}
+
+void rpl_del_entry(struct mesh_node *node, uint16_t src)
+{
+	const char *node_path;
+	char rpl_path[PATH_MAX];
+	struct dirent *entry;
+	DIR *dir;
+
+	if (!node || !IS_UNICAST(src))
+		return;
+
+	node_path = node_get_storage_dir(node);
+
+	if (strlen(node_path) + strlen(rpl_dir) + 15 >= PATH_MAX)
+		return;
+
+	snprintf(rpl_path, PATH_MAX, "%s%s", node_path, rpl_dir);
+	dir = opendir(rpl_path);
+
+	if (!dir)
+		return;
+
+	/* Remove all instances of src address */
+	while ((entry = readdir(dir)) != NULL) {
+		if (entry->d_type == DT_DIR) {
+			snprintf(rpl_path, PATH_MAX, "%s/%4.4x",
+							entry->d_name, src);
+			remove(rpl_path);
+		}
+	}
+
+	closedir(dir);
+}
+
+static bool match_src(const void *a, const void *b)
+{
+	const struct mesh_rpl *rpl = a;
+	uint16_t src = L_PTR_TO_UINT(b);
+
+	return rpl->src == src;
+}
+
+static void get_entries(const char *iv_path, struct l_queue *rpl_list)
+{
+	struct mesh_rpl *rpl;
+	struct dirent *entry;
+	DIR *dir;
+	int fd;
+	const char *iv_txt;
+	char src_path[PATH_MAX];
+	char seq_txt[7];
+	uint32_t iv_index, seq;
+	uint16_t src;
+
+	dir = opendir(iv_path);
+
+	if (!dir)
+		return;
+
+	iv_txt = basename(iv_path);
+	sscanf(iv_txt, "%08x", &iv_index);
+
+	memset(seq_txt, 0, sizeof(seq_txt));
+
+	while ((entry = readdir(dir)) != NULL) {
+		/* RPL sequences are stored in src files under iv_index */
+		if (entry->d_type == DT_REG) {
+			snprintf(src_path, PATH_MAX, "%s/%s", iv_path,
+								entry->d_name);
+			fd = open(src_path, O_RDONLY);
+
+			if (fd < 0)
+				continue;
+
+			if(read(fd, seq_txt, 6) == 6) {
+				sscanf(entry->d_name, "%04hx", &src);
+				sscanf(seq_txt, "%06x", &seq);
+
+				rpl = l_queue_find(rpl_list, match_src,
+							L_UINT_TO_PTR(src));
+
+				if (rpl) {
+					/* Replace older entries */
+					if (rpl->iv_index < iv_index) {
+						rpl->iv_index = iv_index;
+						rpl->seq = seq;
+					}
+				} else if (seq <= SEQ_MASK && IS_UNICAST(src)) {
+					rpl = l_new(struct mesh_rpl, 1);
+					rpl->src = src;
+					rpl->iv_index = iv_index;
+					rpl->seq = seq;
+
+					l_queue_push_head(rpl_list, rpl);
+				}
+			}
+
+			close(fd);
+		}
+	}
+
+	closedir(dir);
+}
+
+bool rpl_get_list(struct mesh_node *node, struct l_queue *rpl_list)
+{
+	const char *node_path;
+	struct dirent *entry;
+	char *rpl_path;
+	size_t len;
+	DIR *dir;
+
+	if (!node || !rpl_list)
+		return false;
+
+	node_path = node_get_storage_dir(node);
+
+	len = strlen(node_path) + strlen(rpl_dir) + 1;
+
+	if (len + 14 > PATH_MAX)
+		return false;
+
+	rpl_path = l_malloc(len);
+	snprintf(rpl_path, PATH_MAX, "%s%s", node_path, rpl_dir);
+
+	dir = opendir(rpl_path);
+
+	if (!dir) {
+		l_error("Failed to read RPL dir: %s", rpl_path);
+		l_free(rpl_path);
+		return false;
+	}
+
+	while ((entry = readdir(dir)) != NULL) {
+		/* RPL sequences are stored in files under iv_indexs */
+		if (entry->d_type == DT_DIR && entry->d_name[0] != '.') {
+			snprintf(rpl_path, PATH_MAX, "%s%s/%s",
+					node_path, rpl_dir, entry->d_name);
+			get_entries(rpl_path, rpl_list);
+		}
+	}
+
+	l_free(rpl_path);
+	closedir(dir);
+
+	return true;
+}
+
+void rpl_init(struct mesh_node *node, uint32_t cur)
+{
+	uint32_t old = cur - 1;
+	const char *node_path;
+	struct dirent *entry;
+	char rpl_path[PATH_MAX];
+	DIR *dir;
+
+	if (!node)
+		return;
+
+	node_path = node_get_storage_dir(node);
+
+	if (strlen(node_path) + strlen(rpl_dir) + 10 >= PATH_MAX)
+		return;
+
+	/* Make sure rpl_path exists */
+	snprintf(rpl_path, PATH_MAX, "%s%s", node_path, rpl_dir);
+	mkdir(rpl_path, 0755);
+
+	/* Cleanup any stale trees */
+	dir = opendir(rpl_path);
+	if (!dir)
+		return;
+
+	while ((entry = readdir(dir)) != NULL) {
+		if (entry->d_type == DT_DIR) {
+			const char *iv_txt = basename(entry->d_name);
+			uint32_t iv_index = 0;
+
+			/* Delete all invalid iv_index trees */
+			sscanf(iv_txt, "%08x", &iv_index);
+			if (iv_index != cur && iv_index != old)
+				del_path(entry->d_name);
+		}
+	}
+
+	closedir(dir);
+
+	/* Make sure all currently considered iv_index directories exist */
+	snprintf(rpl_path, PATH_MAX, "%s%s/%8.8x", node_path, rpl_dir, old);
+	mkdir(rpl_path, 0755);
+	snprintf(rpl_path, PATH_MAX, "%s%s/%8.8x", node_path, rpl_dir, cur);
+	mkdir(rpl_path, 0755);
+}
diff --git a/mesh/rpl.h b/mesh/rpl.h
new file mode 100644
index 000000000..17d2e3f05
--- /dev/null
+++ b/mesh/rpl.h
@@ -0,0 +1,30 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2020  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.
+ *
+ */
+
+struct mesh_rpl {
+	uint32_t iv_index;
+	uint32_t seq;
+	uint16_t src;
+};
+
+bool rpl_put_entry(struct mesh_node *node, uint16_t src, uint32_t iv_index,
+								uint32_t seq);
+void rpl_del_entry(struct mesh_node *node, uint16_t src);
+bool rpl_get_list(struct mesh_node *node, struct l_queue *rpl_list);
+void rpl_init(struct mesh_node *node, uint32_t iv_index);
-- 
2.21.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH BlueZ v2 0/5] mesh: Add NVM storage of Replay Protection List
  2020-01-25  0:43 [PATCH BlueZ v2 0/5] mesh: Add NVM storage of Replay Protection List Brian Gix
                   ` (4 preceding siblings ...)
  2020-01-25  0:43 ` [PATCH BlueZ v2 5/5] mesh: Add NVM storage of Replay Protection Brian Gix
@ 2020-01-27 21:27 ` Rafał Gajda
  2020-01-28 11:26   ` Rafał Gajda
  5 siblings, 1 reply; 8+ messages in thread
From: Rafał Gajda @ 2020-01-27 21:27 UTC (permalink / raw)
  To: Brian Gix; +Cc: linux-bluetooth, inga.stotland

Hi,

sob., 25 sty 2020 o 01:44 Brian Gix <brian.gix@intel.com> napisał(a):
>
> Version 2: Fix path construction code when first reading RPL from NVM
>
>
> An oversight led to losing our Replay Protection List with every
> re-boot. This patch-set makes a number of Replay Protect List
> modifications that culminate in adding rpl.c/h, which stores the latest
> iv_index/sequence values for each node that handles an incoming packet.
>
> The first 4 patches, does some maintenance required to handle RPL
> according the the Mesh Specification.

While testing this patch set I've come across the following problem:

After importing and attaching new node to the daemon I tried to
configure new application key by sending dev key message
ConfigOpcode.APPKEY_ADD to self.
This previously resulted in DevKeyMessageReceived reply.

16:40:24.045 MESHD.stderr          INFO 2020-01-27 16:40:24.045
mesh.c:622  attach_call                mesh/mesh.c:attach_call()
Attach
16:40:24.045 DBUS.in              DEBUG /
org.freedesktop.DBus.ObjectManager::GetManagedObjects()
16:40:24.046 MESHD.stderr          INFO 2020-01-27 16:40:24.046
node.c:1311 get_app_properties
mesh/node.c:get_app_properties() path /com/silvair/application
16:40:24.046 MESHD.stderr          INFO 2020-01-27 16:40:24.046
node.c:1158 get_element_properties
mesh/node.c:get_element_properties() path
/com/silvair/application/element0
16:40:24.048 MESHD.stderr          INFO 2020-01-27 16:40:24.046
node.c:1797 build_element_config
mesh/node.c:build_element_config() Element 0
16:40:24.048 DBUS.out             DEBUG /org/bluez/mesh
org.bluez.mesh.Network1::Attach('/', 1141961045074800157) =
('/org/bluez/mesh/node83bf3b46810345a28bcce70d8d0b46d3', [[0, []]])
16:40:24.054 DBUS.out             DEBUG
/org/bluez/mesh/node83bf3b46810345a28bcce70d8d0b46d3
org.freedesktop.DBus.Properties::Get('org.bluez.mesh.Node1',
'Addresses') = (<dbus_next.signature.Variant object at
0x7f11eaece150>,)
16:40:24.054 APPLICATION           INFO Attached to node
/org/bluez/mesh/node83bf3b46810345a28bcce70d8d0b46d3, address: 05f2,
configuration: {0: {}}
16:40:24.056 MESHD.stderr          INFO 2020-01-27 16:40:24.055
keyring.c:209  keyring_put_remote_dev_key
mesh/keyring.c:keyring_put_remote_dev_key() Put Dev Key
/tmp/pytest-of-ragajda/pytest-74/test_rpl_persistence_after_res0/config/83bf3b46810345a28bcce70d8d0b46d3/dev_keys/05f2
16:40:24.057 DBUS.out             DEBUG
/org/bluez/mesh/node83bf3b46810345a28bcce70d8d0b46d3
org.bluez.mesh.Management1::ImportRemoteNode(1522, 1,
b'\x9dm\xd0\xe9n\xb2]\xc1\x9a@\xed\x99\x14\xf8\xf0?') = ()
16:40:24.060 APPLICATION.Element0.ConfigClient DEBUG Sending:
/com/silvair/application/element0 -> 05f2 [remote True, net_index 0]
ConfigOpcode.APPKEY_ADD Container(app_key_index=0, net_key_index=0,
app_key=b'c\x96GqsO\xbdv\xe3\xb4\x05\x19\xd1\xd9JH')
16:40:24.060 APPLICATION.Element0.ConfigClient DEBUG Sending:
/com/silvair/application/element0 - > 0001 [remote 1522, net_index 0]
0000000063964771734fbd76e3b40519d1d94a48
16:40:24.063 MESHD.stderr          INFO 2020-01-27 16:40:24.062
node.c:1891 dev_key_send_call          mesh/node.c:dev_key_send_call()
DevKeySend
16:40:24.064 MESHD.stderr          INFO 2020-01-27 16:40:24.063
model.c:604  msg_send                   mesh/model.c:msg_send() (6fff)
0x7ffffffa9fa0
16:40:24.064 MESHD.stderr          INFO 2020-01-27 16:40:24.063
model.c:605  msg_send                   mesh/model.c:msg_send()
net_idx 0
16:40:24.064 MESHD.stderr          INFO 2020-01-27 16:40:24.063
model.c:957  mesh_model_rx              mesh/model.c:mesh_model_rx()
iv_index 00000000 key_aid = 00
16:40:24.064 MESHD.stderr          INFO 2020-01-27 16:40:24.063
util.c:46   print_packet               mesh/util.c:print_packet()
39624.063 Clr Rx: 0000000063964771734fbd76e3b40519d1d94a48
16:40:24.065 MESHD.stderr          INFO 2020-01-27 16:40:24.063
model.c:370  forward_model              mesh/model.c:forward_model()
model ffff0000 with idx 7fff
16:40:24.065 MESHD.stderr          INFO 2020-01-27 16:40:24.063
cfgmod-server.c:783  cfg_srv_pkt
mesh/cfgmod-server.c:cfg_srv_pkt() CONFIG-SRV-opcode 0x0 size 19 idx
000
16:40:24.065 MESHD.stderr          INFO 2020-01-27 16:40:24.065
cfgmod-server.c:1036 cfg_srv_pkt
mesh/cfgmod-server.c:cfg_srv_pkt() Add/Update AppKey success: Net_Idx
000, App_Idx 000
16:40:24.065 MESHD.stderr          INFO 2020-01-27 16:40:24.065
model.c:604  msg_send                   mesh/model.c:msg_send() (7fff)
0x5564327d323c
16:40:24.066 MESHD.stderr          INFO 2020-01-27 16:40:24.065
model.c:605  msg_send                   mesh/model.c:msg_send()
net_idx 0
16:40:24.066 MESHD.stderr          INFO 2020-01-27 16:40:24.065
model.c:957  mesh_model_rx              mesh/model.c:mesh_model_rx()
iv_index 00000000 key_aid = 00
16:40:24.066 MESHD.stderr          INFO 2020-01-27 16:40:24.065
util.c:46   print_packet               mesh/util.c:print_packet()
39624.065 Clr Rx: 800300000000
16:40:24.066 MESHD.stderr          INFO 2020-01-27 16:40:24.065
cfgmod-server.c:783  cfg_srv_pkt
mesh/cfgmod-server.c:cfg_srv_pkt() CONFIG-SRV-opcode 0x8003 size 4 idx
000
16:40:24.067 MESHD.stderr          INFO 2020-01-27 16:40:24.065
model.c:871  send_dev_key_msg_rcvd
mesh/model.c:send_dev_key_msg_rcvd() Send "DevKeyMessageReceived"
16:40:24.067 MESHD.stderr          INFO 2020-01-27 16:40:24.065
mesh-config-json.c:2111 mesh_config_write_seq_number
mesh/mesh-config-json.c:mesh_config_write_seq_number() Seq Cache: 1 ->
14286

After applying the patch set the same procedure results in:

16:41:04.102 MESHD.stderr          INFO mesh/mesh.c:attach_call() Attach
16:41:04.103 DBUS.in              DEBUG /
org.freedesktop.DBus.ObjectManager::GetManagedObjects()
16:41:04.103 MESHD.stderr          INFO
mesh/node.c:get_app_properties() path /com/silvair/application
16:41:04.104 MESHD.stderr          INFO
mesh/node.c:get_element_properties() path
/com/silvair/application/element0
16:41:04.105 MESHD.stderr          INFO
mesh/node.c:build_element_config() Element 0
16:41:04.105 DBUS.out             DEBUG /org/bluez/mesh
org.bluez.mesh.Network1::Attach('/', 11095264700132944744) =
('/org/bluez/mesh/node83bf3b46810345a28bcce70d8d0b46d3', [[0, []]])
16:41:04.110 DBUS.out             DEBUG
/org/bluez/mesh/node83bf3b46810345a28bcce70d8d0b46d3
org.freedesktop.DBus.Properties::Get('org.bluez.mesh.Node1',
'Addresses') = (<dbus_next.signature.Variant object at
0x7f27613a2990>,)
16:41:04.110 APPLICATION           INFO Attached to node
/org/bluez/mesh/node83bf3b46810345a28bcce70d8d0b46d3, address: 05f2,
configuration: {0: {}}
16:41:04.111 MESHD.stderr          INFO
mesh/keyring.c:keyring_put_remote_dev_key() Put Dev Key
/tmp/pytest-of-ragajda/pytest-75/test_rpl_persistence_after_res0/config/83bf3b46810345a28bcce70d8d0b46d3/dev_keys/05f2
16:41:04.112 DBUS.out             DEBUG
/org/bluez/mesh/node83bf3b46810345a28bcce70d8d0b46d3
org.bluez.mesh.Management1::ImportRemoteNode(1522, 1,
b'\x9dm\xd0\xe9n\xb2]\xc1\x9a@\xed\x99\x14\xf8\xf0?') = ()
16:41:04.113 APPLICATION.Element0.ConfigClient DEBUG Sending:
/com/silvair/application/element0 -> 05f2 [remote True, net_index 0]
ConfigOpcode.APPKEY_ADD Container(app_key_index=0, net_key_index=0,
app_key=b'c\x96GqsO\xbdv\xe3\xb4\x05\x19\xd1\xd9JH')
16:41:04.113 APPLICATION.Element0.ConfigClient DEBUG Sending:
/com/silvair/application/element0 - > 0001 [remote 1522, net_index 0]
0000000063964771734fbd76e3b40519d1d94a48
16:41:04.113 MESHD.stderr          INFO
mesh/node.c:dev_key_send_call() DevKeySend
16:41:04.114 MESHD.stderr          INFO mesh/model.c:msg_send() (6fff)
0x7ffffce69290
16:41:04.114 MESHD.stderr          INFO mesh/model.c:msg_send() net_idx 0
16:41:04.114 MESHD.stderr          INFO
mesh/mesh-config-json.c:mesh_config_write_seq_number() Seq Cache: 1 ->
25001
16:41:04.114 MESHD.stderr          INFO mesh/model.c:mesh_model_rx()
iv_index 00000000 key_aid = 00
16:41:04.115 MESHD.stderr          INFO
mesh/net.c:net_msg_in_replay_cache() Test Replay src: 05f2 seq: 000001
iv: 00000000
16:41:04.115 MESHD.stderr          INFO
mesh/net.c:net_msg_in_replay_cache() New Entry for 05f2
16:41:04.115 MESHD.stderr          INFO mesh/util.c:print_packet()
39664.115 Clr Rx: 0000000063964771734fbd76e3b40519d1d94a48
16:41:04.115 MESHD.stderr          INFO mesh/model.c:forward_model()
model ffff0000 with idx 7fff
16:41:04.115 MESHD.stderr          INFO
mesh/cfgmod-server.c:cfg_srv_pkt() CONFIG-SRV-opcode 0x0 size 19 idx
000
16:41:04.115 MESHD.stderr          INFO
mesh/cfgmod-server.c:cfg_srv_pkt() Add/Update AppKey success: Net_Idx
000, App_Idx 000
16:41:04.115 MESHD.stderr          INFO mesh/model.c:msg_send() (7fff)
0x55639ab9c8ec
16:41:04.115 MESHD.stderr          INFO mesh/model.c:msg_send() net_idx 0
16:41:04.116 MESHD.stderr          INFO mesh/model.c:mesh_model_rx()
iv_index 00000000 key_aid = 00
16:41:04.116 MESHD.stderr          INFO
mesh/net.c:net_msg_in_replay_cache() Test Replay src: 05f2 seq: 000001
iv: 00000000
16:41:04.116 MESHD.stderr          INFO
mesh/net.c:net_msg_in_replay_cache() Message already processed
(duplicate)

It looks like sequence number is correctly incremented when calling
DevKeySend but it isn't incremented at all when ConfigModel sends the
reply back.

-- 

Rafał Gajda
Silvair Sp. z o.o.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH BlueZ v2 0/5] mesh: Add NVM storage of Replay Protection List
  2020-01-27 21:27 ` [PATCH BlueZ v2 0/5] mesh: Add NVM storage of Replay Protection List Rafał Gajda
@ 2020-01-28 11:26   ` Rafał Gajda
  0 siblings, 0 replies; 8+ messages in thread
From: Rafał Gajda @ 2020-01-28 11:26 UTC (permalink / raw)
  To: Brian Gix; +Cc: linux-bluetooth, inga.stotland

Hi,

pon., 27 sty 2020 o 22:27 Rafał Gajda <rafal.gajda@silvair.com> napisał(a):
>
> It looks like sequence number is correctly incremented when calling
> DevKeySend but it isn't incremented at all when ConfigModel sends the
> reply back.

I think the culprit is in mesh/net.c in mesh_net_app_send() line 3160:

> /* First enqueue to any Friends and internal models */
>     result = msg_rxed(net, false, iv_index, ttl,
>     seq + seg_max,
>     net_idx,
>     src, dst,
>     key_aid,szmic, seq & SEQ_ZERO_MASK,
>     msg, msg_len);
>
> /* If addressed to a unicast address and successfully enqueued,
> * or delivered to one of our Unicast addresses we are done
> */
> if ((result && IS_UNICAST(dst)) || src == dst ||
>     (dst >= net->src_addr && dst <= net->last_addr)) {
>     /* Adjust our seq_num for "virtual" delivery */
>     net->seq_num += seg_max;
>     return true;
> }

When sending the message we first deliver it to internal models and
only after that we increment the msg sequence number.
If we do "net->seq_num += seg_max" before calling msg_rxed() then
messages are delivered correctly.

-- 

Rafał Gajda
Silvair Sp. z o.o.

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2020-01-28 11:26 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-01-25  0:43 [PATCH BlueZ v2 0/5] mesh: Add NVM storage of Replay Protection List Brian Gix
2020-01-25  0:43 ` [PATCH BlueZ v2 1/5] mesh: Relocate tree deletion to util.c/h Brian Gix
2020-01-25  0:43 ` [PATCH BlueZ v2 2/5] mesh: Move Replay Protection to mesh/net.c Brian Gix
2020-01-25  0:43 ` [PATCH BlueZ v2 3/5] mesh: Remove unneeded Sequence Number increment Brian Gix
2020-01-25  0:43 ` [PATCH BlueZ v2 4/5] mesh: Apply Replay Protection to all incoming packets Brian Gix
2020-01-25  0:43 ` [PATCH BlueZ v2 5/5] mesh: Add NVM storage of Replay Protection Brian Gix
2020-01-27 21:27 ` [PATCH BlueZ v2 0/5] mesh: Add NVM storage of Replay Protection List Rafał Gajda
2020-01-28 11:26   ` Rafał Gajda

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).