1 /*
2  * Copyright (c) 2017 Intel Corporation
3  * Copyright (c) 2020 Lingao Meng
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <zephyr.h>
9 #include <string.h>
10 #include <errno.h>
11 #include <stdbool.h>
12 #include <stdlib.h>
13 #include <sys/atomic.h>
14 #include <sys/util.h>
15 #include <sys/byteorder.h>
16 
17 #include <net/buf.h>
18 #include <bluetooth/bluetooth.h>
19 #include <bluetooth/conn.h>
20 #include <bluetooth/mesh.h>
21 
22 #define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_RPL)
23 #define LOG_MODULE_NAME bt_mesh_rpl
24 #include "common/log.h"
25 
26 #include "mesh.h"
27 #include "adv.h"
28 #include "net.h"
29 #include "rpl.h"
30 #include "settings.h"
31 
32 /* Replay Protection List information for persistent storage. */
33 struct rpl_val {
34 	uint32_t seq:24,
35 	      old_iv:1;
36 };
37 
38 static struct bt_mesh_rpl replay_list[CONFIG_BT_MESH_CRPL];
39 static ATOMIC_DEFINE(store, CONFIG_BT_MESH_CRPL);
40 
rpl_idx(const struct bt_mesh_rpl * rpl)41 static inline int rpl_idx(const struct bt_mesh_rpl *rpl)
42 {
43 	return rpl - &replay_list[0];
44 }
45 
clear_rpl(struct bt_mesh_rpl * rpl)46 static void clear_rpl(struct bt_mesh_rpl *rpl)
47 {
48 	int err;
49 	char path[18];
50 
51 	if (!rpl->src) {
52 		return;
53 	}
54 
55 	snprintk(path, sizeof(path), "bt/mesh/RPL/%x", rpl->src);
56 	err = settings_delete(path);
57 	if (err) {
58 		BT_ERR("Failed to clear RPL");
59 	} else {
60 		BT_DBG("Cleared RPL");
61 	}
62 
63 	(void)memset(rpl, 0, sizeof(*rpl));
64 	atomic_clear_bit(store, rpl_idx(rpl));
65 }
66 
schedule_rpl_store(struct bt_mesh_rpl * entry,bool force)67 static void schedule_rpl_store(struct bt_mesh_rpl *entry, bool force)
68 {
69 	atomic_set_bit(store, rpl_idx(entry));
70 
71 	if (force
72 #ifdef CONFIG_BT_MESH_RPL_STORE_TIMEOUT
73 	    || CONFIG_BT_MESH_RPL_STORE_TIMEOUT >= 0
74 #endif
75 	    ) {
76 		bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_RPL_PENDING);
77 	}
78 }
79 
schedule_rpl_clear(void)80 static void schedule_rpl_clear(void)
81 {
82 	bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_RPL_PENDING);
83 }
84 
bt_mesh_rpl_update(struct bt_mesh_rpl * rpl,struct bt_mesh_net_rx * rx)85 void bt_mesh_rpl_update(struct bt_mesh_rpl *rpl,
86 		struct bt_mesh_net_rx *rx)
87 {
88 	/* If this is the first message on the new IV index, we should reset it
89 	 * to zero to avoid invalid combinations of IV index and seg.
90 	 */
91 	if (rpl->old_iv && !rx->old_iv) {
92 		rpl->seg = 0;
93 	}
94 
95 	rpl->src = rx->ctx.addr;
96 	rpl->seq = rx->seq;
97 	rpl->old_iv = rx->old_iv;
98 
99 	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
100 		schedule_rpl_store(rpl, false);
101 	}
102 }
103 
104 /* Check the Replay Protection List for a replay attempt. If non-NULL match
105  * parameter is given the RPL slot is returned but it is not immediately
106  * updated (needed for segmented messages), whereas if a NULL match is given
107  * the RPL is immediately updated (used for unsegmented messages).
108  */
bt_mesh_rpl_check(struct bt_mesh_net_rx * rx,struct bt_mesh_rpl ** match)109 bool bt_mesh_rpl_check(struct bt_mesh_net_rx *rx,
110 		struct bt_mesh_rpl **match)
111 {
112 	int i;
113 
114 	/* Don't bother checking messages from ourselves */
115 	if (rx->net_if == BT_MESH_NET_IF_LOCAL) {
116 		return false;
117 	}
118 
119 	/* The RPL is used only for the local node */
120 	if (!rx->local_match) {
121 		return false;
122 	}
123 
124 	for (i = 0; i < ARRAY_SIZE(replay_list); i++) {
125 		struct bt_mesh_rpl *rpl = &replay_list[i];
126 
127 		/* Empty slot */
128 		if (!rpl->src) {
129 			if (match) {
130 				*match = rpl;
131 			} else {
132 				bt_mesh_rpl_update(rpl, rx);
133 			}
134 
135 			return false;
136 		}
137 
138 		/* Existing slot for given address */
139 		if (rpl->src == rx->ctx.addr) {
140 			if (rx->old_iv && !rpl->old_iv) {
141 				return true;
142 			}
143 
144 			if ((!rx->old_iv && rpl->old_iv) ||
145 			    rpl->seq < rx->seq) {
146 				if (match) {
147 					*match = rpl;
148 				} else {
149 					bt_mesh_rpl_update(rpl, rx);
150 				}
151 
152 				return false;
153 			} else {
154 				return true;
155 			}
156 		}
157 	}
158 
159 	BT_ERR("RPL is full!");
160 	return true;
161 }
162 
bt_mesh_rpl_clear(void)163 void bt_mesh_rpl_clear(void)
164 {
165 	BT_DBG("");
166 
167 	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
168 		schedule_rpl_clear();
169 	} else {
170 		(void)memset(replay_list, 0, sizeof(replay_list));
171 	}
172 }
173 
bt_mesh_rpl_find(uint16_t src)174 static struct bt_mesh_rpl *bt_mesh_rpl_find(uint16_t src)
175 {
176 	int i;
177 
178 	for (i = 0; i < ARRAY_SIZE(replay_list); i++) {
179 		if (replay_list[i].src == src) {
180 			return &replay_list[i];
181 		}
182 	}
183 
184 	return NULL;
185 }
186 
bt_mesh_rpl_alloc(uint16_t src)187 static struct bt_mesh_rpl *bt_mesh_rpl_alloc(uint16_t src)
188 {
189 	int i;
190 
191 	for (i = 0; i < ARRAY_SIZE(replay_list); i++) {
192 		if (!replay_list[i].src) {
193 			replay_list[i].src = src;
194 			return &replay_list[i];
195 		}
196 	}
197 
198 	return NULL;
199 }
200 
bt_mesh_rpl_reset(void)201 void bt_mesh_rpl_reset(void)
202 {
203 	int i;
204 
205 	/* Discard "old old" IV Index entries from RPL and flag
206 	 * any other ones (which are valid) as old.
207 	 */
208 	for (i = 0; i < ARRAY_SIZE(replay_list); i++) {
209 		struct bt_mesh_rpl *rpl = &replay_list[i];
210 
211 		if (rpl->src) {
212 			if (rpl->old_iv) {
213 				if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
214 					clear_rpl(rpl);
215 				} else {
216 					(void)memset(rpl, 0, sizeof(*rpl));
217 				}
218 			} else {
219 				rpl->old_iv = true;
220 
221 				if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
222 					schedule_rpl_store(rpl, true);
223 				}
224 			}
225 		}
226 	}
227 }
228 
rpl_set(const char * name,size_t len_rd,settings_read_cb read_cb,void * cb_arg)229 static int rpl_set(const char *name, size_t len_rd,
230 		   settings_read_cb read_cb, void *cb_arg)
231 {
232 	struct bt_mesh_rpl *entry;
233 	struct rpl_val rpl;
234 	int err;
235 	uint16_t src;
236 
237 	if (!name) {
238 		BT_ERR("Insufficient number of arguments");
239 		return -ENOENT;
240 	}
241 
242 	src = strtol(name, NULL, 16);
243 	entry = bt_mesh_rpl_find(src);
244 
245 	if (len_rd == 0) {
246 		BT_DBG("val (null)");
247 		if (entry) {
248 			(void)memset(entry, 0, sizeof(*entry));
249 		} else {
250 			BT_WARN("Unable to find RPL entry for 0x%04x", src);
251 		}
252 
253 		return 0;
254 	}
255 
256 	if (!entry) {
257 		entry = bt_mesh_rpl_alloc(src);
258 		if (!entry) {
259 			BT_ERR("Unable to allocate RPL entry for 0x%04x", src);
260 			return -ENOMEM;
261 		}
262 	}
263 
264 	err = bt_mesh_settings_set(read_cb, cb_arg, &rpl, sizeof(rpl));
265 	if (err) {
266 		BT_ERR("Failed to set `net`");
267 		return err;
268 	}
269 
270 	entry->seq = rpl.seq;
271 	entry->old_iv = rpl.old_iv;
272 
273 	BT_DBG("RPL entry for 0x%04x: Seq 0x%06x old_iv %u", entry->src,
274 	       entry->seq, entry->old_iv);
275 
276 	return 0;
277 }
278 
279 BT_MESH_SETTINGS_DEFINE(rpl, "RPL", rpl_set);
280 
store_rpl(struct bt_mesh_rpl * entry)281 static void store_rpl(struct bt_mesh_rpl *entry)
282 {
283 	struct rpl_val rpl;
284 	char path[18];
285 	int err;
286 
287 	if (!entry->src) {
288 		return;
289 	}
290 
291 	BT_DBG("src 0x%04x seq 0x%06x old_iv %u", entry->src, entry->seq,
292 	       entry->old_iv);
293 
294 	rpl.seq = entry->seq;
295 	rpl.old_iv = entry->old_iv;
296 
297 	snprintk(path, sizeof(path), "bt/mesh/RPL/%x", entry->src);
298 
299 	err = settings_save_one(path, &rpl, sizeof(rpl));
300 	if (err) {
301 		BT_ERR("Failed to store RPL %s value", log_strdup(path));
302 	} else {
303 		BT_DBG("Stored RPL %s value", log_strdup(path));
304 	}
305 }
306 
store_pending_rpl(struct bt_mesh_rpl * rpl)307 static void store_pending_rpl(struct bt_mesh_rpl *rpl)
308 {
309 	BT_DBG("");
310 
311 	if (atomic_test_and_clear_bit(store, rpl_idx(rpl))) {
312 		store_rpl(rpl);
313 	}
314 }
315 
bt_mesh_rpl_pending_store(uint16_t addr)316 void bt_mesh_rpl_pending_store(uint16_t addr)
317 {
318 	int i;
319 
320 	if (!IS_ENABLED(CONFIG_BT_SETTINGS) ||
321 	    (!BT_MESH_ADDR_IS_UNICAST(addr) &&
322 	     addr != BT_MESH_ADDR_ALL_NODES)) {
323 		return;
324 	}
325 
326 	if (addr == BT_MESH_ADDR_ALL_NODES) {
327 		bt_mesh_settings_store_cancel(BT_MESH_SETTINGS_RPL_PENDING);
328 	}
329 
330 	for (i = 0; i < ARRAY_SIZE(replay_list); i++) {
331 		if (addr != BT_MESH_ADDR_ALL_NODES &&
332 		    addr != replay_list[i].src) {
333 			continue;
334 		}
335 
336 		if (atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
337 			store_pending_rpl(&replay_list[i]);
338 		} else {
339 			clear_rpl(&replay_list[i]);
340 		}
341 
342 		if (addr != BT_MESH_ADDR_ALL_NODES) {
343 			break;
344 		}
345 	}
346 }
347