Bluetooth: Mesh: Move Replay Protect to seperate module

Move RPL to seperate module, and remove it in `bt_mesh`
structure.

Signed-off-by: Lingao Meng <mengabc1086@gmail.com>
This commit is contained in:
Lingao Meng 2020-09-09 16:59:43 +08:00 committed by Johan Hedberg
commit f16c653be9
16 changed files with 249 additions and 186 deletions

View file

@ -12,6 +12,7 @@
#if defined(CONFIG_BT_MESH) #if defined(CONFIG_BT_MESH)
#include "mesh/net.h" #include "mesh/net.h"
#include "mesh/lpn.h" #include "mesh/lpn.h"
#include "mesh/rpl.h"
#include "mesh/transport.h" #include "mesh/transport.h"
#endif /* CONFIG_BT_MESH */ #endif /* CONFIG_BT_MESH */

View file

@ -9,6 +9,7 @@ zephyr_library_sources_ifdef(CONFIG_BT_MESH
beacon.c beacon.c
net.c net.c
transport.c transport.c
rpl.c
crypto.c crypto.c
access.c access.c
cfg_srv.c cfg_srv.c

View file

@ -589,6 +589,12 @@ config BT_MESH_DEBUG_NET
Use this option to enable Network layer debug logs for the Use this option to enable Network layer debug logs for the
Bluetooth Mesh functionality. Bluetooth Mesh functionality.
config BT_MESH_DEBUG_RPL
bool "Replay protection list debug"
help
Use this option to enable Replay protection list debug logs
for the Bluetooth Mesh functionality.
config BT_MESH_DEBUG_TRANS config BT_MESH_DEBUG_TRANS
bool "Transport layer debug" bool "Transport layer debug"
help help

View file

@ -15,6 +15,7 @@
#include "mesh.h" #include "mesh.h"
#include "net.h" #include "net.h"
#include "rpl.h"
#include "settings.h" #include "settings.h"
struct bt_mesh_cdb bt_mesh_cdb = { struct bt_mesh_cdb bt_mesh_cdb = {

View file

@ -27,6 +27,7 @@
#include "mesh.h" #include "mesh.h"
#include "adv.h" #include "adv.h"
#include "net.h" #include "net.h"
#include "rpl.h"
#include "lpn.h" #include "lpn.h"
#include "transport.h" #include "transport.h"
#include "crypto.h" #include "crypto.h"

View file

@ -24,6 +24,7 @@
#include "adv.h" #include "adv.h"
#include "prov.h" #include "prov.h"
#include "net.h" #include "net.h"
#include "rpl.h"
#include "beacon.h" #include "beacon.h"
#include "lpn.h" #include "lpn.h"
#include "friend.h" #include "friend.h"

View file

@ -27,6 +27,7 @@
#include "adv.h" #include "adv.h"
#include "mesh.h" #include "mesh.h"
#include "net.h" #include "net.h"
#include "rpl.h"
#include "lpn.h" #include "lpn.h"
#include "friend.h" #include "friend.h"
#include "proxy.h" #include "proxy.h"
@ -559,30 +560,6 @@ bool bt_mesh_kr_update(struct bt_mesh_subnet *sub, uint8_t new_kr, bool new_key)
return false; return false;
} }
void bt_mesh_rpl_reset(void)
{
int i;
/* Discard "old old" IV Index entries from RPL and flag
* any other ones (which are valid) as old.
*/
for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) {
struct bt_mesh_rpl *rpl = &bt_mesh.rpl[i];
if (rpl->src) {
if (rpl->old_iv) {
(void)memset(rpl, 0, sizeof(*rpl));
} else {
rpl->old_iv = true;
}
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
bt_mesh_store_rpl(rpl);
}
}
}
}
#if defined(CONFIG_BT_MESH_IV_UPDATE_TEST) #if defined(CONFIG_BT_MESH_IV_UPDATE_TEST)
void bt_mesh_iv_update_test(bool enable) void bt_mesh_iv_update_test(bool enable)
{ {
@ -658,7 +635,7 @@ bool bt_mesh_net_iv_update(uint32_t iv_index, bool iv_update)
if (iv_index > bt_mesh.iv_index + 1) { if (iv_index > bt_mesh.iv_index + 1) {
BT_WARN("Performing IV Index Recovery"); BT_WARN("Performing IV Index Recovery");
(void)memset(bt_mesh.rpl, 0, sizeof(bt_mesh.rpl)); bt_mesh_rpl_clear();
bt_mesh.iv_index = iv_index; bt_mesh.iv_index = iv_index;
bt_mesh.seq = 0U; bt_mesh.seq = 0U;
goto do_update; goto do_update;

View file

@ -74,15 +74,6 @@ struct bt_mesh_subnet {
} keys[2]; } keys[2];
}; };
struct bt_mesh_rpl {
uint16_t src;
bool old_iv;
#if defined(CONFIG_BT_SETTINGS)
bool store;
#endif
uint32_t seq;
};
#if defined(CONFIG_BT_MESH_FRIEND) #if defined(CONFIG_BT_MESH_FRIEND)
#define FRIEND_SEG_RX CONFIG_BT_MESH_FRIEND_SEG_RX #define FRIEND_SEG_RX CONFIG_BT_MESH_FRIEND_SEG_RX
#define FRIEND_SUB_LIST_SIZE CONFIG_BT_MESH_FRIEND_SUB_LIST_SIZE #define FRIEND_SUB_LIST_SIZE CONFIG_BT_MESH_FRIEND_SUB_LIST_SIZE
@ -257,8 +248,6 @@ struct bt_mesh_net {
struct bt_mesh_app_key app_keys[CONFIG_BT_MESH_APP_KEY_COUNT]; struct bt_mesh_app_key app_keys[CONFIG_BT_MESH_APP_KEY_COUNT];
struct bt_mesh_subnet sub[CONFIG_BT_MESH_SUBNET_COUNT]; struct bt_mesh_subnet sub[CONFIG_BT_MESH_SUBNET_COUNT];
struct bt_mesh_rpl rpl[CONFIG_BT_MESH_CRPL];
}; };
/* Network interface */ /* Network interface */
@ -318,8 +307,6 @@ void bt_mesh_net_revoke_keys(struct bt_mesh_subnet *sub);
int bt_mesh_net_beacon_update(struct bt_mesh_subnet *sub); int bt_mesh_net_beacon_update(struct bt_mesh_subnet *sub);
void bt_mesh_rpl_reset(void);
bool bt_mesh_net_iv_update(uint32_t iv_index, bool iv_update); bool bt_mesh_net_iv_update(uint32_t iv_index, bool iv_update);
void bt_mesh_net_sec_update(struct bt_mesh_subnet *sub); void bt_mesh_net_sec_update(struct bt_mesh_subnet *sub);

View file

@ -29,6 +29,7 @@
#include "adv.h" #include "adv.h"
#include "mesh.h" #include "mesh.h"
#include "net.h" #include "net.h"
#include "rpl.h"
#include "beacon.h" #include "beacon.h"
#include "access.h" #include "access.h"
#include "foundation.h" #include "foundation.h"

View file

@ -22,6 +22,7 @@
#include "mesh.h" #include "mesh.h"
#include "adv.h" #include "adv.h"
#include "net.h" #include "net.h"
#include "rpl.h"
#include "transport.h" #include "transport.h"
#include "prov.h" #include "prov.h"
#include "beacon.h" #include "beacon.h"

175
subsys/bluetooth/mesh/rpl.c Normal file
View file

@ -0,0 +1,175 @@
/* Bluetooth Mesh */
/*
* Copyright (c) 2017 Intel Corporation
* Copyright (c) 2020 Lingao Meng
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr.h>
#include <string.h>
#include <errno.h>
#include <stdbool.h>
#include <sys/atomic.h>
#include <sys/util.h>
#include <sys/byteorder.h>
#include <net/buf.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/conn.h>
#include <bluetooth/mesh.h>
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_RPL)
#define LOG_MODULE_NAME bt_mesh_rpl
#include "common/log.h"
#include "mesh.h"
#include "adv.h"
#include "net.h"
#include "rpl.h"
#include "settings.h"
static struct bt_mesh_rpl replay_list[CONFIG_BT_MESH_CRPL];
void bt_mesh_rpl_update(struct bt_mesh_rpl *rpl,
struct bt_mesh_net_rx *rx)
{
rpl->src = rx->ctx.addr;
rpl->seq = rx->seq;
rpl->old_iv = rx->old_iv;
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
bt_mesh_store_rpl(rpl);
}
}
/* Check the Replay Protection List for a replay attempt. If non-NULL match
* parameter is given the RPL slot is returned but it is not immediately
* updated (needed for segmented messages), whereas if a NULL match is given
* the RPL is immediately updated (used for unsegmented messages).
*/
bool bt_mesh_rpl_check(struct bt_mesh_net_rx *rx,
struct bt_mesh_rpl **match)
{
int i;
/* Don't bother checking messages from ourselves */
if (rx->net_if == BT_MESH_NET_IF_LOCAL) {
return false;
}
/* The RPL is used only for the local node */
if (!rx->local_match) {
return false;
}
for (i = 0; i < ARRAY_SIZE(replay_list); i++) {
struct bt_mesh_rpl *rpl = &replay_list[i];
/* Empty slot */
if (!rpl->src) {
if (match) {
*match = rpl;
} else {
bt_mesh_rpl_update(rpl, rx);
}
return false;
}
/* Existing slot for given address */
if (rpl->src == rx->ctx.addr) {
if (rx->old_iv && !rpl->old_iv) {
return true;
}
if ((!rx->old_iv && rpl->old_iv) ||
rpl->seq < rx->seq) {
if (match) {
*match = rpl;
} else {
bt_mesh_rpl_update(rpl, rx);
}
return false;
} else {
return true;
}
}
}
BT_ERR("RPL is full!");
return true;
}
void bt_mesh_rpl_clear(void)
{
BT_DBG("");
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
bt_mesh_clear_rpl();
} else {
(void)memset(replay_list, 0, sizeof(replay_list));
}
}
struct bt_mesh_rpl *bt_mesh_rpl_find(uint16_t src)
{
int i;
for (i = 0; i < ARRAY_SIZE(replay_list); i++) {
if (replay_list[i].src == src) {
return &replay_list[i];
}
}
return NULL;
}
struct bt_mesh_rpl *bt_mesh_rpl_alloc(uint16_t src)
{
int i;
for (i = 0; i < ARRAY_SIZE(replay_list); i++) {
if (!replay_list[i].src) {
replay_list[i].src = src;
return &replay_list[i];
}
}
return NULL;
}
void bt_mesh_rpl_foreach(bt_mesh_rpl_func_t func, void *user_data)
{
int i;
for (i = 0; i < ARRAY_SIZE(replay_list); i++) {
func(&replay_list[i], user_data);
}
}
void bt_mesh_rpl_reset(void)
{
int i;
/* Discard "old old" IV Index entries from RPL and flag
* any other ones (which are valid) as old.
*/
for (i = 0; i < ARRAY_SIZE(replay_list); i++) {
struct bt_mesh_rpl *rpl = &replay_list[i];
if (rpl->src) {
if (rpl->old_iv) {
(void)memset(rpl, 0, sizeof(*rpl));
} else {
rpl->old_iv = true;
}
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
bt_mesh_store_rpl(rpl);
}
}
}
}

View file

@ -0,0 +1,30 @@
/* Bluetooth Mesh */
/*
* Copyright (c) 2017 Intel Corporation
* Copyright (c) 2020 Lingao Meng
*
* SPDX-License-Identifier: Apache-2.0
*/
struct bt_mesh_rpl {
uint16_t src;
bool old_iv;
#if defined(CONFIG_BT_SETTINGS)
bool store;
#endif
uint32_t seq;
};
typedef void (*bt_mesh_rpl_func_t)(struct bt_mesh_rpl *rpl,
void *user_data);
void bt_mesh_rpl_reset(void);
bool bt_mesh_rpl_check(struct bt_mesh_net_rx *rx,
struct bt_mesh_rpl **match);
void bt_mesh_rpl_clear(void);
struct bt_mesh_rpl *bt_mesh_rpl_find(uint16_t src);
struct bt_mesh_rpl *bt_mesh_rpl_alloc(uint16_t src);
void bt_mesh_rpl_foreach(bt_mesh_rpl_func_t func, void *user_data);
void bt_mesh_rpl_update(struct bt_mesh_rpl *rpl,
struct bt_mesh_net_rx *rx);

View file

@ -27,6 +27,7 @@
#include "mesh.h" #include "mesh.h"
#include "net.h" #include "net.h"
#include "crypto.h" #include "crypto.h"
#include "rpl.h"
#include "transport.h" #include "transport.h"
#include "access.h" #include "access.h"
#include "foundation.h" #include "foundation.h"
@ -280,33 +281,6 @@ static int seq_set(const char *name, size_t len_rd, settings_read_cb read_cb,
return 0; return 0;
} }
static struct bt_mesh_rpl *rpl_find(uint16_t src)
{
int i;
for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) {
if (bt_mesh.rpl[i].src == src) {
return &bt_mesh.rpl[i];
}
}
return NULL;
}
static struct bt_mesh_rpl *rpl_alloc(uint16_t src)
{
int i;
for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) {
if (!bt_mesh.rpl[i].src) {
bt_mesh.rpl[i].src = src;
return &bt_mesh.rpl[i];
}
}
return NULL;
}
static int rpl_set(const char *name, size_t len_rd, static int rpl_set(const char *name, size_t len_rd,
settings_read_cb read_cb, void *cb_arg) settings_read_cb read_cb, void *cb_arg)
{ {
@ -321,7 +295,7 @@ static int rpl_set(const char *name, size_t len_rd,
} }
src = strtol(name, NULL, 16); src = strtol(name, NULL, 16);
entry = rpl_find(src); entry = bt_mesh_rpl_find(src);
if (len_rd == 0) { if (len_rd == 0) {
BT_DBG("val (null)"); BT_DBG("val (null)");
@ -335,7 +309,7 @@ static int rpl_set(const char *name, size_t len_rd,
} }
if (!entry) { if (!entry) {
entry = rpl_alloc(src); entry = bt_mesh_rpl_alloc(src);
if (!entry) { if (!entry) {
BT_ERR("Unable to allocate RPL entry for 0x%04x", src); BT_ERR("Unable to allocate RPL entry for 0x%04x", src);
return -ENOMEM; return -ENOMEM;
@ -1349,45 +1323,33 @@ static void store_rpl(struct bt_mesh_rpl *entry)
} }
} }
static void clear_rpl(void) static void clear_rpl(struct bt_mesh_rpl *rpl, void *user_data)
{ {
int i, err; int err;
char path[18];
BT_DBG(""); if (!rpl->src) {
return;
for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) {
struct bt_mesh_rpl *rpl = &bt_mesh.rpl[i];
char path[18];
if (!rpl->src) {
continue;
}
snprintk(path, sizeof(path), "bt/mesh/RPL/%x", rpl->src);
err = settings_delete(path);
if (err) {
BT_ERR("Failed to clear RPL");
} else {
BT_DBG("Cleared RPL");
}
(void)memset(rpl, 0, sizeof(*rpl));
} }
snprintk(path, sizeof(path), "bt/mesh/RPL/%x", rpl->src);
err = settings_delete(path);
if (err) {
BT_ERR("Failed to clear RPL");
} else {
BT_DBG("Cleared RPL");
}
(void)memset(rpl, 0, sizeof(*rpl));
} }
static void store_pending_rpl(void) static void store_pending_rpl(struct bt_mesh_rpl *rpl, void *user_data)
{ {
int i;
BT_DBG(""); BT_DBG("");
for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) { if (rpl->store) {
struct bt_mesh_rpl *rpl = &bt_mesh.rpl[i]; rpl->store = false;
store_rpl(rpl);
if (rpl->store) {
rpl->store = false;
store_rpl(rpl);
}
} }
} }
@ -1996,9 +1958,9 @@ static void store_pending(struct k_work *work)
if (atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_RPL_PENDING)) { if (atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_RPL_PENDING)) {
if (atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) { if (atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
store_pending_rpl(); bt_mesh_rpl_foreach(store_pending_rpl, NULL);
} else { } else {
clear_rpl(); bt_mesh_rpl_foreach(clear_rpl, NULL);
} }
} }

View file

@ -24,6 +24,7 @@
/* Private includes for raw Network & Transport layer access */ /* Private includes for raw Network & Transport layer access */
#include "mesh.h" #include "mesh.h"
#include "net.h" #include "net.h"
#include "rpl.h"
#include "transport.h" #include "transport.h"
#include "foundation.h" #include "foundation.h"
#include "settings.h" #include "settings.h"

View file

@ -29,6 +29,7 @@
#include "mesh.h" #include "mesh.h"
#include "net.h" #include "net.h"
#include "lpn.h" #include "lpn.h"
#include "rpl.h"
#include "friend.h" #include "friend.h"
#include "access.h" #include "access.h"
#include "foundation.h" #include "foundation.h"
@ -676,75 +677,6 @@ int bt_mesh_trans_send(struct bt_mesh_net_tx *tx, struct net_buf_simple *msg,
return err; return err;
} }
static void update_rpl(struct bt_mesh_rpl *rpl, struct bt_mesh_net_rx *rx)
{
rpl->src = rx->ctx.addr;
rpl->seq = rx->seq;
rpl->old_iv = rx->old_iv;
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
bt_mesh_store_rpl(rpl);
}
}
/* Check the Replay Protection List for a replay attempt. If non-NULL match
* parameter is given the RPL slot is returned but it is not immediately
* updated (needed for segmented messages), whereas if a NULL match is given
* the RPL is immediately updated (used for unsegmented messages).
*/
bool bt_mesh_rpl_check(struct bt_mesh_net_rx *rx, struct bt_mesh_rpl **match)
{
int i;
/* Don't bother checking messages from ourselves */
if (rx->net_if == BT_MESH_NET_IF_LOCAL) {
return false;
}
/* The RPL is used only for the local node */
if (!rx->local_match) {
return false;
}
for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) {
struct bt_mesh_rpl *rpl = &bt_mesh.rpl[i];
/* Empty slot */
if (!rpl->src) {
if (match) {
*match = rpl;
} else {
update_rpl(rpl, rx);
}
return false;
}
/* Existing slot for given address */
if (rpl->src == rx->ctx.addr) {
if (rx->old_iv && !rpl->old_iv) {
return true;
}
if ((!rx->old_iv && rpl->old_iv) ||
rpl->seq < rx->seq) {
if (match) {
*match = rpl;
} else {
update_rpl(rpl, rx);
}
return false;
} else {
return true;
}
}
}
BT_ERR("RPL is full!");
return true;
}
static void seg_rx_assemble(struct seg_rx *rx, struct net_buf_simple *buf, static void seg_rx_assemble(struct seg_rx *rx, struct net_buf_simple *buf,
uint8_t aszmic) uint8_t aszmic)
{ {
@ -1587,7 +1519,7 @@ static int trans_seg(struct net_buf_simple *buf, struct bt_mesh_net_rx *net_rx,
seq_auth, rx->block, rx->obo); seq_auth, rx->block, rx->obo);
if (rpl) { if (rpl) {
update_rpl(rpl, net_rx); bt_mesh_rpl_update(rpl, net_rx);
} }
return -EALREADY; return -EALREADY;
@ -1700,7 +1632,7 @@ found_rx:
BT_DBG("Complete SDU"); BT_DBG("Complete SDU");
if (rpl) { if (rpl) {
update_rpl(rpl, net_rx); bt_mesh_rpl_update(rpl, net_rx);
} }
*pdu_type = BT_MESH_FRIEND_PDU_COMPLETE; *pdu_type = BT_MESH_FRIEND_PDU_COMPLETE;
@ -1822,11 +1754,7 @@ void bt_mesh_rx_reset(void)
seg_rx_reset(&seg_rx[i], true); seg_rx_reset(&seg_rx[i], true);
} }
if (IS_ENABLED(CONFIG_BT_SETTINGS)) { bt_mesh_rpl_clear();
bt_mesh_clear_rpl();
} else {
(void)memset(bt_mesh.rpl, 0, sizeof(bt_mesh.rpl));
}
} }
void bt_mesh_tx_reset(void) void bt_mesh_tx_reset(void)
@ -1853,12 +1781,6 @@ void bt_mesh_trans_init(void)
} }
} }
void bt_mesh_rpl_clear(void)
{
BT_DBG("");
(void)memset(bt_mesh.rpl, 0, sizeof(bt_mesh.rpl));
}
int bt_mesh_heartbeat_send(const struct bt_mesh_send_cb *cb, void *cb_data) int bt_mesh_heartbeat_send(const struct bt_mesh_send_cb *cb, void *cb_data)
{ {
struct bt_mesh_cfg_srv *cfg = bt_mesh_cfg_get(); struct bt_mesh_cfg_srv *cfg = bt_mesh_cfg_get();

View file

@ -99,10 +99,6 @@ int bt_mesh_trans_recv(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx);
void bt_mesh_trans_init(void); void bt_mesh_trans_init(void);
void bt_mesh_rpl_clear(void);
bool bt_mesh_rpl_check(struct bt_mesh_net_rx *rx, struct bt_mesh_rpl **match);
int bt_mesh_heartbeat_send(const struct bt_mesh_send_cb *cb, void *cb_data); int bt_mesh_heartbeat_send(const struct bt_mesh_send_cb *cb, void *cb_data);
int bt_mesh_app_key_get(const struct bt_mesh_subnet *subnet, uint16_t app_idx, int bt_mesh_app_key_get(const struct bt_mesh_subnet *subnet, uint16_t app_idx,