From: Brian Gix <brian.gix@intel.com>
To: linux-bluetooth@vger.kernel.org
Cc: brian.gix@intel.com, inga.stotland@intel.com, rafal.gajda@silvair.com
Subject: [PATCH BlueZ v4 2/5] mesh: Move Replay Protection to mesh/net.c
Date: Tue, 28 Jan 2020 18:32:55 -0800 [thread overview]
Message-ID: <20200129023258.10004-3-brian.gix@intel.com> (raw)
In-Reply-To: <20200129023258.10004-1-brian.gix@intel.com>
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
next prev parent reply other threads:[~2020-01-29 2:33 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-01-29 2:32 [PATCH BlueZ v4 0/5] mesh: Add NVM storage of Replay Protection List Brian Gix
2020-01-29 2:32 ` [PATCH BlueZ v4 1/5] mesh: Relocate tree deletion to util.c/h Brian Gix
2020-01-29 2:32 ` Brian Gix [this message]
2020-01-29 2:32 ` [PATCH BlueZ v4 3/5] mesh: Clean-up unneeded Sequence Number increments Brian Gix
2020-01-29 2:32 ` [PATCH BlueZ v4 4/5] mesh: Apply Replay Protection to all incoming packets Brian Gix
2020-01-29 2:32 ` [PATCH BlueZ v4 5/5] mesh: Add NVM storage of Replay Protection Brian Gix
2020-01-29 12:17 ` Rafal Gajda
2020-01-29 15:06 ` Gix, Brian
2020-01-30 8:55 ` Rafal Gajda
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200129023258.10004-3-brian.gix@intel.com \
--to=brian.gix@intel.com \
--cc=inga.stotland@intel.com \
--cc=linux-bluetooth@vger.kernel.org \
--cc=rafal.gajda@silvair.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).