1 /*
2  * Copyright (c) 2019 Tobias Svehagen
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <string.h>
9 #include <stdlib.h>
10 
11 #include <zephyr/settings/settings.h>
12 
13 #include <zephyr/bluetooth/mesh.h>
14 
15 #include "common/bt_str.h"
16 
17 #include "cdb.h"
18 #include "mesh.h"
19 #include "net.h"
20 #include "rpl.h"
21 #include "settings.h"
22 #include "keys.h"
23 
24 #define LOG_LEVEL CONFIG_BT_MESH_CDB_LOG_LEVEL
25 #include <zephyr/logging/log.h>
26 LOG_MODULE_REGISTER(bt_mesh_cdb);
27 
28 /* Tracking of what storage changes are pending for App and Net Keys. We
29  * track this in a separate array here instead of within the respective
30  * bt_mesh_app_key and bt_mesh_subnet structs themselves, since once a key
31  * gets deleted its struct becomes invalid and may be reused for other keys.
32  */
33 struct key_update {
34 	uint16_t key_idx:12,    /* AppKey or NetKey Index */
35 		 valid:1,       /* 1 if this entry is valid, 0 if not */
36 		 app_key:1,     /* 1 if this is an AppKey, 0 if a NetKey */
37 		 clear:1;       /* 1 if key needs clearing, 0 if storing */
38 };
39 
40 /* Tracking of what storage changes are pending for node settings. */
41 struct node_update {
42 	uint16_t addr;
43 	bool clear;
44 };
45 
46 /* Node information for persistent storage. */
47 struct node_val {
48 	uint16_t net_idx;
49 	uint8_t num_elem;
50 	uint8_t flags;
51 #define F_NODE_CONFIGURED 0x01
52 	uint8_t uuid[16];
53 	struct bt_mesh_key dev_key;
54 } __packed;
55 
56 /* NetKey storage information */
57 struct net_key_val {
58 	uint8_t kr_flag:1,
59 		kr_phase:7;
60 	struct bt_mesh_key val[2];
61 } __packed;
62 
63 /* AppKey information for persistent storage. */
64 struct app_key_val {
65 	uint16_t net_idx;
66 	bool updated;
67 	struct bt_mesh_key val[2];
68 } __packed;
69 
70 /* Network information for persistent storage. */
71 struct net_val {
72 	struct __packed {
73 		uint32_t index;
74 		bool     update;
75 	} iv;
76 	uint16_t lowest_avail_addr;
77 } __packed;
78 
79 /* One more entry for the node's address update. */
80 static struct node_update cdb_node_updates[CONFIG_BT_MESH_CDB_NODE_COUNT + 1];
81 static struct key_update cdb_key_updates[CONFIG_BT_MESH_CDB_SUBNET_COUNT +
82 					 CONFIG_BT_MESH_CDB_APP_KEY_COUNT];
83 
84 struct bt_mesh_cdb bt_mesh_cdb = {
85 	.nodes = {
86 		[0 ... (CONFIG_BT_MESH_CDB_NODE_COUNT - 1)] = {
87 			.addr = BT_MESH_ADDR_UNASSIGNED,
88 		}
89 	},
90 	.subnets = {
91 		[0 ... (CONFIG_BT_MESH_CDB_SUBNET_COUNT - 1)] = {
92 			.net_idx = BT_MESH_KEY_UNUSED,
93 		}
94 	},
95 	.app_keys = {
96 		[0 ... (CONFIG_BT_MESH_CDB_APP_KEY_COUNT - 1)] = {
97 			.app_idx = BT_MESH_KEY_UNUSED,
98 			.net_idx = BT_MESH_KEY_UNUSED,
99 		}
100 	},
101 };
102 
103 /*
104  * Check if an address range from addr_start for addr_start + num_elem - 1 is
105  * free for use. When a conflict is found, next will be set to the next address
106  * available after the conflicting range and -EAGAIN will be returned.
107  */
addr_is_free(uint16_t addr_start,uint8_t num_elem,uint16_t * next)108 static int addr_is_free(uint16_t addr_start, uint8_t num_elem, uint16_t *next)
109 {
110 	uint16_t addr_end = addr_start + num_elem - 1;
111 	uint16_t other_start, other_end;
112 	int i;
113 
114 	if (!BT_MESH_ADDR_IS_UNICAST(addr_start) ||
115 	    !BT_MESH_ADDR_IS_UNICAST(addr_end) ||
116 	    num_elem == 0) {
117 		return -EINVAL;
118 	}
119 
120 	for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); i++) {
121 		struct bt_mesh_cdb_node *node = &bt_mesh_cdb.nodes[i];
122 
123 		if (node->addr == BT_MESH_ADDR_UNASSIGNED) {
124 			continue;
125 		}
126 
127 		other_start = node->addr;
128 		other_end = other_start + node->num_elem - 1;
129 
130 		if (!(addr_end < other_start || addr_start > other_end)) {
131 			if (next) {
132 				*next = other_end + 1;
133 			}
134 
135 			return -EAGAIN;
136 		}
137 	}
138 
139 	return 0;
140 }
141 
142 /*
143  * Find the lowest possible starting address that can fit num_elem elements. If
144  * a free address range cannot be found, BT_MESH_ADDR_UNASSIGNED will be
145  * returned. Otherwise the first address in the range is returned.
146  *
147  * NOTE: This is quite an ineffective algorithm as it might need to look
148  *       through the array of nodes N+2 times. A more effective algorithm
149  *       could be used if the nodes were stored in a sorted list.
150  */
find_lowest_free_addr(uint8_t num_elem)151 static uint16_t find_lowest_free_addr(uint8_t num_elem)
152 {
153 	uint16_t addr = bt_mesh_cdb.lowest_avail_addr;
154 	uint16_t next;
155 	int err, i;
156 
157 	/*
158 	 * It takes a maximum of node count + 2 to find a free address if there
159 	 * is any. +1 for our own address and +1 for making sure that the
160 	 * address range is valid.
161 	 */
162 	for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes) + 2; ++i) {
163 		err = addr_is_free(addr, num_elem, &next);
164 		if (err == 0) {
165 			break;
166 		} else if (err != -EAGAIN) {
167 			addr = BT_MESH_ADDR_UNASSIGNED;
168 			break;
169 		}
170 
171 		addr = next;
172 	}
173 
174 	return addr;
175 }
176 
cdb_net_set(const char * name,size_t len_rd,settings_read_cb read_cb,void * cb_arg)177 static int cdb_net_set(const char *name, size_t len_rd,
178 		       settings_read_cb read_cb, void *cb_arg)
179 {
180 	struct net_val net;
181 	int err;
182 
183 	if (len_rd == 0) {
184 		LOG_DBG("val (null)");
185 		return 0;
186 	}
187 
188 	err = bt_mesh_settings_set(read_cb, cb_arg, &net, sizeof(net));
189 	if (err) {
190 		/* Try to recover previous version of the network settings without address. */
191 		err = bt_mesh_settings_set(read_cb, cb_arg, &net, sizeof(net.iv));
192 		if (err) {
193 			LOG_ERR("Failed to set \'cdb_net\'");
194 			return err;
195 		}
196 
197 		net.lowest_avail_addr = 1;
198 	}
199 
200 	bt_mesh_cdb.iv_index = net.iv.index;
201 
202 	if (net.iv.update) {
203 		atomic_set_bit(bt_mesh_cdb.flags, BT_MESH_CDB_IVU_IN_PROGRESS);
204 	}
205 
206 	bt_mesh_cdb.lowest_avail_addr = net.lowest_avail_addr;
207 
208 	atomic_set_bit(bt_mesh_cdb.flags, BT_MESH_CDB_VALID);
209 
210 	return 0;
211 }
212 
cdb_node_set(const char * name,size_t len_rd,settings_read_cb read_cb,void * cb_arg)213 static int cdb_node_set(const char *name, size_t len_rd,
214 			settings_read_cb read_cb, void *cb_arg)
215 {
216 	struct bt_mesh_cdb_node *node;
217 	struct node_val val;
218 	struct bt_mesh_key tmp;
219 	uint16_t addr;
220 	int err;
221 
222 	if (!name) {
223 		LOG_ERR("Insufficient number of arguments");
224 		return -ENOENT;
225 	}
226 
227 	addr = strtol(name, NULL, 16);
228 
229 	if (len_rd == 0) {
230 		LOG_DBG("val (null)");
231 		LOG_DBG("Deleting node 0x%04x", addr);
232 
233 		node = bt_mesh_cdb_node_get(addr);
234 		if (node) {
235 			bt_mesh_cdb_node_del(node, false);
236 		}
237 
238 		return 0;
239 	}
240 
241 	err = bt_mesh_settings_set(read_cb, cb_arg, &val, sizeof(val));
242 	if (err) {
243 		LOG_ERR("Failed to set \'node\'");
244 		return err;
245 	}
246 
247 	node = bt_mesh_cdb_node_get(addr);
248 	if (!node) {
249 		node = bt_mesh_cdb_node_alloc(val.uuid, addr, val.num_elem,
250 					      val.net_idx);
251 	}
252 
253 	if (!node) {
254 		LOG_ERR("No space for a new node");
255 		return -ENOMEM;
256 	}
257 
258 	if (val.flags & F_NODE_CONFIGURED) {
259 		atomic_set_bit(node->flags, BT_MESH_CDB_NODE_CONFIGURED);
260 	}
261 
262 	memcpy(node->uuid, val.uuid, 16);
263 
264 	/* One extra copying since val.dev_key is from packed structure
265 	 * and might be unaligned.
266 	 */
267 	memcpy(&tmp, &val.dev_key, sizeof(struct bt_mesh_key));
268 	bt_mesh_key_assign(&node->dev_key, &tmp);
269 
270 	LOG_DBG("Node 0x%04x recovered from storage", addr);
271 
272 	return 0;
273 }
274 
cdb_subnet_set(const char * name,size_t len_rd,settings_read_cb read_cb,void * cb_arg)275 static int cdb_subnet_set(const char *name, size_t len_rd,
276 			  settings_read_cb read_cb, void *cb_arg)
277 {
278 	struct bt_mesh_cdb_subnet *sub;
279 	struct net_key_val key;
280 	struct bt_mesh_key tmp[2];
281 	uint16_t net_idx;
282 	int err;
283 
284 	if (!name) {
285 		LOG_ERR("Insufficient number of arguments");
286 		return -ENOENT;
287 	}
288 
289 	net_idx = strtol(name, NULL, 16);
290 	sub = bt_mesh_cdb_subnet_get(net_idx);
291 
292 	if (len_rd == 0) {
293 		LOG_DBG("val (null)");
294 		if (!sub) {
295 			LOG_ERR("No subnet with NetKeyIndex 0x%03x", net_idx);
296 			return -ENOENT;
297 		}
298 
299 		LOG_DBG("Deleting NetKeyIndex 0x%03x", net_idx);
300 		bt_mesh_cdb_subnet_del(sub, false);
301 		return 0;
302 	}
303 
304 	err = bt_mesh_settings_set(read_cb, cb_arg, &key, sizeof(key));
305 	if (err) {
306 		LOG_ERR("Failed to set \'net-key\'");
307 		return err;
308 	}
309 
310 	/* One extra copying since key.val[] is from packed structure
311 	 * and might be unaligned.
312 	 */
313 	memcpy(&tmp[0], &key.val[0], sizeof(struct bt_mesh_key));
314 	memcpy(&tmp[1], &key.val[1], sizeof(struct bt_mesh_key));
315 
316 	if (sub) {
317 		LOG_DBG("Updating existing NetKeyIndex 0x%03x", net_idx);
318 
319 		sub->kr_phase = key.kr_phase;
320 		bt_mesh_key_assign(&sub->keys[0].net_key, &tmp[0]);
321 		bt_mesh_key_assign(&sub->keys[1].net_key, &tmp[1]);
322 
323 		return 0;
324 	}
325 
326 	sub = bt_mesh_cdb_subnet_alloc(net_idx);
327 	if (!sub) {
328 		LOG_ERR("No space to allocate a new subnet");
329 		return -ENOMEM;
330 	}
331 
332 	sub->kr_phase = key.kr_phase;
333 	bt_mesh_key_assign(&sub->keys[0].net_key, &tmp[0]);
334 	bt_mesh_key_assign(&sub->keys[1].net_key, &tmp[1]);
335 
336 	LOG_DBG("NetKeyIndex 0x%03x recovered from storage", net_idx);
337 
338 	return 0;
339 }
340 
cdb_app_key_set(const char * name,size_t len_rd,settings_read_cb read_cb,void * cb_arg)341 static int cdb_app_key_set(const char *name, size_t len_rd,
342 			   settings_read_cb read_cb, void *cb_arg)
343 {
344 	struct bt_mesh_cdb_app_key *app;
345 	struct app_key_val key;
346 	struct bt_mesh_key tmp[2];
347 	uint16_t app_idx;
348 	int err;
349 
350 	if (!name) {
351 		LOG_ERR("Insufficient number of arguments");
352 		return -ENOENT;
353 	}
354 
355 	app_idx = strtol(name, NULL, 16);
356 
357 	if (len_rd == 0) {
358 		LOG_DBG("val (null)");
359 		LOG_DBG("Deleting AppKeyIndex 0x%03x", app_idx);
360 
361 		app = bt_mesh_cdb_app_key_get(app_idx);
362 		if (app) {
363 			bt_mesh_cdb_app_key_del(app, false);
364 		}
365 
366 		return 0;
367 	}
368 
369 	err = bt_mesh_settings_set(read_cb, cb_arg, &key, sizeof(key));
370 	if (err) {
371 		LOG_ERR("Failed to set \'app-key\'");
372 		return err;
373 	}
374 
375 	/* One extra copying since key.val[] is from packed structure
376 	 * and might be unaligned.
377 	 */
378 	memcpy(&tmp[0], &key.val[0], sizeof(struct bt_mesh_key));
379 	memcpy(&tmp[1], &key.val[1], sizeof(struct bt_mesh_key));
380 
381 	app = bt_mesh_cdb_app_key_get(app_idx);
382 	if (!app) {
383 		app = bt_mesh_cdb_app_key_alloc(key.net_idx, app_idx);
384 	}
385 
386 	if (!app) {
387 		LOG_ERR("No space for a new app key");
388 		return -ENOMEM;
389 	}
390 
391 	bt_mesh_key_assign(&app->keys[0].app_key, &tmp[0]);
392 	bt_mesh_key_assign(&app->keys[1].app_key, &tmp[1]);
393 
394 	LOG_DBG("AppKeyIndex 0x%03x recovered from storage", app_idx);
395 
396 	return 0;
397 }
398 
cdb_set(const char * name,size_t len_rd,settings_read_cb read_cb,void * cb_arg)399 static int cdb_set(const char *name, size_t len_rd,
400 		   settings_read_cb read_cb, void *cb_arg)
401 {
402 	int len;
403 	const char *next;
404 
405 	if (!name) {
406 		LOG_ERR("Insufficient number of arguments");
407 		return -ENOENT;
408 	}
409 
410 	if (!strcmp(name, "Net")) {
411 		return cdb_net_set(name, len_rd, read_cb, cb_arg);
412 	}
413 
414 
415 	len = settings_name_next(name, &next);
416 
417 	if (!next) {
418 		LOG_ERR("Insufficient number of arguments");
419 		return -ENOENT;
420 	}
421 
422 	if (!strncmp(name, "Node", len)) {
423 		return cdb_node_set(next, len_rd, read_cb, cb_arg);
424 	}
425 
426 	if (!strncmp(name, "Subnet", len)) {
427 		return cdb_subnet_set(next, len_rd, read_cb, cb_arg);
428 	}
429 
430 	if (!strncmp(name, "AppKey", len)) {
431 		return cdb_app_key_set(next, len_rd, read_cb, cb_arg);
432 	}
433 
434 	LOG_WRN("Unknown module key %s", name);
435 	return -ENOENT;
436 }
437 
438 BT_MESH_SETTINGS_DEFINE(cdb, "cdb", cdb_set);
439 
store_cdb_node(const struct bt_mesh_cdb_node * node)440 static void store_cdb_node(const struct bt_mesh_cdb_node *node)
441 {
442 	struct node_val val;
443 	char path[30];
444 	int err;
445 
446 	val.net_idx = node->net_idx;
447 	val.num_elem = node->num_elem;
448 	val.flags = 0;
449 
450 	if (atomic_test_bit(node->flags, BT_MESH_CDB_NODE_CONFIGURED)) {
451 		val.flags |= F_NODE_CONFIGURED;
452 	}
453 
454 	memcpy(val.uuid, node->uuid, 16);
455 	memcpy(&val.dev_key, &node->dev_key, sizeof(struct bt_mesh_key));
456 
457 	snprintk(path, sizeof(path), "bt/mesh/cdb/Node/%x", node->addr);
458 
459 	err = settings_save_one(path, &val, sizeof(val));
460 	if (err) {
461 		LOG_ERR("Failed to store Node %s value", path);
462 	} else {
463 		LOG_DBG("Stored Node %s value", path);
464 	}
465 }
466 
clear_cdb_node(uint16_t addr)467 static void clear_cdb_node(uint16_t addr)
468 {
469 	char path[30];
470 	int err;
471 
472 	LOG_DBG("Node 0x%04x", addr);
473 
474 	snprintk(path, sizeof(path), "bt/mesh/cdb/Node/%x", addr);
475 	err = settings_delete(path);
476 	if (err) {
477 		LOG_ERR("Failed to clear Node 0x%04x", addr);
478 	} else {
479 		LOG_DBG("Cleared Node 0x%04x", addr);
480 	}
481 }
482 
store_cdb_subnet(const struct bt_mesh_cdb_subnet * sub)483 static void store_cdb_subnet(const struct bt_mesh_cdb_subnet *sub)
484 {
485 	struct net_key_val key;
486 	char path[30];
487 	int err;
488 
489 	LOG_DBG("NetKeyIndex 0x%03x NetKey %s", sub->net_idx,
490 	       bt_hex(&sub->keys[0].net_key, sizeof(struct bt_mesh_key)));
491 
492 	memcpy(&key.val[0], &sub->keys[0].net_key, sizeof(struct bt_mesh_key));
493 	memcpy(&key.val[1], &sub->keys[1].net_key, sizeof(struct bt_mesh_key));
494 	key.kr_flag = 0U; /* Deprecated */
495 	key.kr_phase = sub->kr_phase;
496 
497 	snprintk(path, sizeof(path), "bt/mesh/cdb/Subnet/%x", sub->net_idx);
498 
499 	err = settings_save_one(path, &key, sizeof(key));
500 	if (err) {
501 		LOG_ERR("Failed to store Subnet value");
502 	} else {
503 		LOG_DBG("Stored Subnet value");
504 	}
505 }
506 
clear_cdb_subnet(uint16_t net_idx)507 static void clear_cdb_subnet(uint16_t net_idx)
508 {
509 	char path[30];
510 	int err;
511 
512 	LOG_DBG("NetKeyIndex 0x%03x", net_idx);
513 
514 	snprintk(path, sizeof(path), "bt/mesh/cdb/Subnet/%x", net_idx);
515 	err = settings_delete(path);
516 	if (err) {
517 		LOG_ERR("Failed to clear NetKeyIndex 0x%03x", net_idx);
518 	} else {
519 		LOG_DBG("Cleared NetKeyIndex 0x%03x", net_idx);
520 	}
521 }
522 
store_cdb_app_key(const struct bt_mesh_cdb_app_key * app)523 static void store_cdb_app_key(const struct bt_mesh_cdb_app_key *app)
524 {
525 	struct app_key_val key;
526 	char path[30];
527 	int err;
528 
529 	key.net_idx = app->net_idx;
530 	key.updated = false;
531 	memcpy(&key.val[0], &app->keys[0].app_key, sizeof(struct bt_mesh_key));
532 	memcpy(&key.val[1], &app->keys[1].app_key, sizeof(struct bt_mesh_key));
533 
534 	snprintk(path, sizeof(path), "bt/mesh/cdb/AppKey/%x", app->app_idx);
535 
536 	err = settings_save_one(path, &key, sizeof(key));
537 	if (err) {
538 		LOG_ERR("Failed to store AppKey %s value", path);
539 	} else {
540 		LOG_DBG("Stored AppKey %s value", path);
541 	}
542 }
543 
clear_cdb_app_key(uint16_t app_idx)544 static void clear_cdb_app_key(uint16_t app_idx)
545 {
546 	char path[30];
547 	int err;
548 
549 	snprintk(path, sizeof(path), "bt/mesh/cdb/AppKey/%x", app_idx);
550 	err = settings_delete(path);
551 	if (err) {
552 		LOG_ERR("Failed to clear AppKeyIndex 0x%03x", app_idx);
553 	} else {
554 		LOG_DBG("Cleared AppKeyIndex 0x%03x", app_idx);
555 	}
556 }
557 
schedule_cdb_store(int flag)558 static void schedule_cdb_store(int flag)
559 {
560 	atomic_set_bit(bt_mesh_cdb.flags, flag);
561 	bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_CDB_PENDING);
562 }
563 
update_cdb_net_settings(void)564 static void update_cdb_net_settings(void)
565 {
566 	schedule_cdb_store(BT_MESH_CDB_SUBNET_PENDING);
567 }
568 
cdb_node_update_find(uint16_t addr,struct node_update ** free_slot)569 static struct node_update *cdb_node_update_find(uint16_t addr,
570 						struct node_update **free_slot)
571 {
572 	struct node_update *match;
573 	int i;
574 
575 	match = NULL;
576 	*free_slot = NULL;
577 
578 	for (i = 0; i < ARRAY_SIZE(cdb_node_updates); i++) {
579 		struct node_update *update = &cdb_node_updates[i];
580 
581 		if (update->addr == BT_MESH_ADDR_UNASSIGNED) {
582 			*free_slot = update;
583 			continue;
584 		}
585 
586 		if (update->addr == addr) {
587 			match = update;
588 		}
589 	}
590 
591 	return match;
592 }
593 
update_cdb_node_settings(const struct bt_mesh_cdb_node * node,bool store)594 static void update_cdb_node_settings(const struct bt_mesh_cdb_node *node,
595 				     bool store)
596 {
597 	struct node_update *update, *free_slot;
598 
599 	LOG_DBG("Node 0x%04x", node->addr);
600 
601 	update = cdb_node_update_find(node->addr, &free_slot);
602 	if (update) {
603 		update->clear = !store;
604 		schedule_cdb_store(BT_MESH_CDB_NODES_PENDING);
605 		return;
606 	}
607 
608 	if (!free_slot) {
609 		if (store) {
610 			store_cdb_node(node);
611 		} else {
612 			clear_cdb_node(node->addr);
613 		}
614 		return;
615 	}
616 
617 	free_slot->addr = node->addr;
618 	free_slot->clear = !store;
619 
620 	schedule_cdb_store(BT_MESH_CDB_NODES_PENDING);
621 }
622 
cdb_key_update_find(bool app_key,uint16_t key_idx,struct key_update ** free_slot)623 static struct key_update *cdb_key_update_find(bool app_key, uint16_t key_idx,
624 					      struct key_update **free_slot)
625 {
626 	struct key_update *match;
627 	int i;
628 
629 	match = NULL;
630 	*free_slot = NULL;
631 
632 	for (i = 0; i < ARRAY_SIZE(cdb_key_updates); i++) {
633 		struct key_update *update = &cdb_key_updates[i];
634 
635 		if (!update->valid) {
636 			*free_slot = update;
637 			continue;
638 		}
639 
640 		if (update->app_key != app_key) {
641 			continue;
642 		}
643 
644 		if (update->key_idx == key_idx) {
645 			match = update;
646 		}
647 	}
648 
649 	return match;
650 }
651 
update_cdb_subnet_settings(const struct bt_mesh_cdb_subnet * sub,bool store)652 static void update_cdb_subnet_settings(const struct bt_mesh_cdb_subnet *sub,
653 				       bool store)
654 {
655 	struct key_update *update, *free_slot;
656 	uint8_t clear = store ? 0U : 1U;
657 
658 	LOG_DBG("NetKeyIndex 0x%03x", sub->net_idx);
659 
660 	update = cdb_key_update_find(false, sub->net_idx, &free_slot);
661 	if (update) {
662 		update->clear = clear;
663 		schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING);
664 		return;
665 	}
666 
667 	if (!free_slot) {
668 		if (store) {
669 			store_cdb_subnet(sub);
670 		} else {
671 			clear_cdb_subnet(sub->net_idx);
672 		}
673 		return;
674 	}
675 
676 	free_slot->valid = 1U;
677 	free_slot->key_idx = sub->net_idx;
678 	free_slot->app_key = 0U;
679 	free_slot->clear = clear;
680 
681 	schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING);
682 }
683 
update_cdb_app_key_settings(const struct bt_mesh_cdb_app_key * key,bool store)684 static void update_cdb_app_key_settings(const struct bt_mesh_cdb_app_key *key,
685 					bool store)
686 {
687 	struct key_update *update, *free_slot;
688 	uint8_t clear = store ? 0U : 1U;
689 
690 	LOG_DBG("AppKeyIndex 0x%03x", key->app_idx);
691 
692 	update = cdb_key_update_find(true, key->app_idx, &free_slot);
693 	if (update) {
694 		update->clear = clear;
695 		schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING);
696 		return;
697 	}
698 
699 	if (!free_slot) {
700 		if (store) {
701 			store_cdb_app_key(key);
702 		} else {
703 			clear_cdb_app_key(key->app_idx);
704 		}
705 
706 		return;
707 	}
708 
709 	free_slot->valid = 1U;
710 	free_slot->key_idx = key->app_idx;
711 	free_slot->app_key = 1U;
712 	free_slot->clear = clear;
713 
714 	schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING);
715 }
716 
addr_assign(uint16_t addr,uint8_t num_elem)717 static uint16_t addr_assign(uint16_t addr, uint8_t num_elem)
718 {
719 	if (addr == BT_MESH_ADDR_UNASSIGNED) {
720 		addr = find_lowest_free_addr(num_elem);
721 	} else if (addr < bt_mesh_cdb.lowest_avail_addr) {
722 		return BT_MESH_ADDR_UNASSIGNED;
723 	} else if (addr_is_free(addr, num_elem, NULL) < 0) {
724 		LOG_DBG("Address range 0x%04x-0x%04x is not free", addr,
725 			addr + num_elem - 1);
726 		return BT_MESH_ADDR_UNASSIGNED;
727 	}
728 
729 	return addr;
730 }
731 
bt_mesh_cdb_create(const uint8_t key[16])732 int bt_mesh_cdb_create(const uint8_t key[16])
733 {
734 	struct bt_mesh_cdb_subnet *sub;
735 	int err;
736 
737 	if (atomic_test_and_set_bit(bt_mesh_cdb.flags,
738 				    BT_MESH_CDB_VALID)) {
739 		return -EALREADY;
740 	}
741 
742 	sub = bt_mesh_cdb_subnet_alloc(BT_MESH_KEY_PRIMARY);
743 	if (sub == NULL) {
744 		return -ENOMEM;
745 	}
746 
747 	err = bt_mesh_key_import(BT_MESH_KEY_TYPE_NET, key, &sub->keys[0].net_key);
748 	if (err) {
749 		return err;
750 	}
751 
752 	bt_mesh_cdb.iv_index = 0;
753 	bt_mesh_cdb.lowest_avail_addr = 1;
754 
755 	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
756 		update_cdb_net_settings();
757 		update_cdb_subnet_settings(sub, true);
758 	}
759 
760 	return 0;
761 }
762 
bt_mesh_cdb_clear(void)763 void bt_mesh_cdb_clear(void)
764 {
765 	int i;
766 
767 	atomic_clear_bit(bt_mesh_cdb.flags, BT_MESH_CDB_VALID);
768 
769 	for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); ++i) {
770 		if (bt_mesh_cdb.nodes[i].addr != BT_MESH_ADDR_UNASSIGNED) {
771 			bt_mesh_cdb_node_del(&bt_mesh_cdb.nodes[i], true);
772 		}
773 	}
774 
775 	for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.subnets); ++i) {
776 		if (bt_mesh_cdb.subnets[i].net_idx != BT_MESH_KEY_UNUSED) {
777 			bt_mesh_cdb_subnet_del(&bt_mesh_cdb.subnets[i], true);
778 		}
779 	}
780 
781 	for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.app_keys); ++i) {
782 		if (bt_mesh_cdb.app_keys[i].net_idx != BT_MESH_KEY_UNUSED) {
783 			bt_mesh_cdb_app_key_del(&bt_mesh_cdb.app_keys[i], true);
784 		}
785 	}
786 
787 	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
788 		update_cdb_net_settings();
789 		bt_mesh_settings_store_pending();
790 	}
791 }
792 
bt_mesh_cdb_iv_update(uint32_t iv_index,bool iv_update)793 void bt_mesh_cdb_iv_update(uint32_t iv_index, bool iv_update)
794 {
795 	LOG_DBG("Updating IV index to %d\n", iv_index);
796 
797 	/* Reset the last deleted addr when IV Index is updated or recovered. */
798 	if (!iv_update || iv_index > bt_mesh_cdb.iv_index + 1) {
799 		bt_mesh_cdb.lowest_avail_addr = 1;
800 	}
801 
802 	bt_mesh_cdb.iv_index = iv_index;
803 
804 	atomic_set_bit_to(bt_mesh_cdb.flags, BT_MESH_CDB_IVU_IN_PROGRESS,
805 			  iv_update);
806 
807 	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
808 		update_cdb_net_settings();
809 	}
810 }
811 
bt_mesh_cdb_subnet_alloc(uint16_t net_idx)812 struct bt_mesh_cdb_subnet *bt_mesh_cdb_subnet_alloc(uint16_t net_idx)
813 {
814 	struct bt_mesh_cdb_subnet *sub;
815 	int i;
816 
817 	if (bt_mesh_cdb_subnet_get(net_idx) != NULL) {
818 		return NULL;
819 	}
820 
821 	for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.subnets); ++i) {
822 		sub = &bt_mesh_cdb.subnets[i];
823 
824 		if (sub->net_idx != BT_MESH_KEY_UNUSED) {
825 			continue;
826 		}
827 
828 		sub->net_idx = net_idx;
829 
830 		return sub;
831 	}
832 
833 	return NULL;
834 }
835 
bt_mesh_cdb_subnet_del(struct bt_mesh_cdb_subnet * sub,bool store)836 void bt_mesh_cdb_subnet_del(struct bt_mesh_cdb_subnet *sub, bool store)
837 {
838 	LOG_DBG("NetIdx 0x%03x store %u", sub->net_idx, store);
839 
840 	if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
841 		update_cdb_subnet_settings(sub, false);
842 	}
843 
844 	sub->net_idx = BT_MESH_KEY_UNUSED;
845 	bt_mesh_key_destroy(&sub->keys[0].net_key);
846 	bt_mesh_key_destroy(&sub->keys[1].net_key);
847 	memset(sub->keys, 0, sizeof(sub->keys));
848 }
849 
bt_mesh_cdb_subnet_get(uint16_t net_idx)850 struct bt_mesh_cdb_subnet *bt_mesh_cdb_subnet_get(uint16_t net_idx)
851 {
852 	int i;
853 
854 	for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.subnets); ++i) {
855 		if (bt_mesh_cdb.subnets[i].net_idx == net_idx) {
856 			return &bt_mesh_cdb.subnets[i];
857 		}
858 	}
859 
860 	return NULL;
861 }
862 
bt_mesh_cdb_subnet_store(const struct bt_mesh_cdb_subnet * sub)863 void bt_mesh_cdb_subnet_store(const struct bt_mesh_cdb_subnet *sub)
864 {
865 	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
866 		update_cdb_subnet_settings(sub, true);
867 	}
868 }
869 
bt_mesh_cdb_subnet_flags(const struct bt_mesh_cdb_subnet * sub)870 uint8_t bt_mesh_cdb_subnet_flags(const struct bt_mesh_cdb_subnet *sub)
871 {
872 	uint8_t flags = 0x00;
873 
874 	if (sub && SUBNET_KEY_TX_IDX(sub)) {
875 		flags |= BT_MESH_NET_FLAG_KR;
876 	}
877 
878 	if (atomic_test_bit(bt_mesh_cdb.flags, BT_MESH_CDB_IVU_IN_PROGRESS)) {
879 		flags |= BT_MESH_NET_FLAG_IVU;
880 	}
881 
882 	return flags;
883 }
884 
bt_mesh_cdb_subnet_key_import(struct bt_mesh_cdb_subnet * sub,int key_idx,const uint8_t in[16])885 int bt_mesh_cdb_subnet_key_import(struct bt_mesh_cdb_subnet *sub, int key_idx,
886 				  const uint8_t in[16])
887 {
888 	if (!bt_mesh_key_compare(in, &sub->keys[key_idx].net_key)) {
889 		return 0;
890 	}
891 
892 	bt_mesh_key_destroy(&sub->keys[key_idx].net_key);
893 
894 	return bt_mesh_key_import(BT_MESH_KEY_TYPE_NET, in, &sub->keys[key_idx].net_key);
895 }
896 
bt_mesh_cdb_subnet_key_export(const struct bt_mesh_cdb_subnet * sub,int key_idx,uint8_t out[16])897 int bt_mesh_cdb_subnet_key_export(const struct bt_mesh_cdb_subnet *sub, int key_idx,
898 				  uint8_t out[16])
899 {
900 	return bt_mesh_key_export(out, &sub->keys[key_idx].net_key);
901 }
902 
bt_mesh_cdb_node_alloc(const uint8_t uuid[16],uint16_t addr,uint8_t num_elem,uint16_t net_idx)903 struct bt_mesh_cdb_node *bt_mesh_cdb_node_alloc(const uint8_t uuid[16], uint16_t addr,
904 						uint8_t num_elem, uint16_t net_idx)
905 {
906 	int i;
907 
908 	addr = addr_assign(addr, num_elem);
909 	if (addr == BT_MESH_ADDR_UNASSIGNED) {
910 		return NULL;
911 	}
912 
913 	for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); i++) {
914 		struct bt_mesh_cdb_node *node = &bt_mesh_cdb.nodes[i];
915 
916 		if (node->addr == BT_MESH_ADDR_UNASSIGNED) {
917 			memcpy(node->uuid, uuid, 16);
918 			node->addr = addr;
919 			node->num_elem = num_elem;
920 			node->net_idx = net_idx;
921 			atomic_set(node->flags, 0);
922 			return node;
923 		}
924 	}
925 
926 	return NULL;
927 }
928 
bt_mesh_cdb_free_addr_get(uint8_t num_elem)929 uint16_t bt_mesh_cdb_free_addr_get(uint8_t num_elem)
930 {
931 	return find_lowest_free_addr(num_elem);
932 }
933 
bt_mesh_cdb_node_del(struct bt_mesh_cdb_node * node,bool store)934 void bt_mesh_cdb_node_del(struct bt_mesh_cdb_node *node, bool store)
935 {
936 	LOG_DBG("Node addr 0x%04x store %u", node->addr, store);
937 
938 	if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
939 		update_cdb_node_settings(node, false);
940 	}
941 
942 	if (store && node->addr + node->num_elem > bt_mesh_cdb.lowest_avail_addr) {
943 		bt_mesh_cdb.lowest_avail_addr = node->addr + node->num_elem;
944 
945 		if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
946 			update_cdb_net_settings();
947 		}
948 	}
949 
950 	node->addr = BT_MESH_ADDR_UNASSIGNED;
951 	bt_mesh_key_destroy(&node->dev_key);
952 	memset(&node->dev_key, 0, sizeof(node->dev_key));
953 }
954 
bt_mesh_cdb_node_update(struct bt_mesh_cdb_node * node,uint16_t addr,uint8_t num_elem)955 void bt_mesh_cdb_node_update(struct bt_mesh_cdb_node *node, uint16_t addr,
956 			     uint8_t num_elem)
957 {
958 	/* Address is used as a key to the nodes array. Remove the current entry first, then store
959 	 * new address.
960 	 */
961 	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
962 		update_cdb_node_settings(node, false);
963 	}
964 
965 	node->addr = addr;
966 	node->num_elem = num_elem;
967 
968 	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
969 		update_cdb_node_settings(node, true);
970 	}
971 }
972 
bt_mesh_cdb_node_get(uint16_t addr)973 struct bt_mesh_cdb_node *bt_mesh_cdb_node_get(uint16_t addr)
974 {
975 	int i;
976 
977 	for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); i++) {
978 		struct bt_mesh_cdb_node *node = &bt_mesh_cdb.nodes[i];
979 
980 		if (addr >= node->addr &&
981 		    addr <= node->addr + node->num_elem - 1) {
982 			return node;
983 		}
984 	}
985 
986 	return NULL;
987 }
988 
bt_mesh_cdb_node_store(const struct bt_mesh_cdb_node * node)989 void bt_mesh_cdb_node_store(const struct bt_mesh_cdb_node *node)
990 {
991 	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
992 		update_cdb_node_settings(node, true);
993 	}
994 }
995 
bt_mesh_cdb_node_foreach(bt_mesh_cdb_node_func_t func,void * user_data)996 void bt_mesh_cdb_node_foreach(bt_mesh_cdb_node_func_t func, void *user_data)
997 {
998 	int i;
999 
1000 	for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); ++i) {
1001 		if (bt_mesh_cdb.nodes[i].addr == BT_MESH_ADDR_UNASSIGNED) {
1002 			continue;
1003 		}
1004 
1005 		if (func(&bt_mesh_cdb.nodes[i], user_data) ==
1006 		    BT_MESH_CDB_ITER_STOP) {
1007 			break;
1008 		}
1009 	}
1010 }
1011 
bt_mesh_cdb_node_key_import(struct bt_mesh_cdb_node * node,const uint8_t in[16])1012 int bt_mesh_cdb_node_key_import(struct bt_mesh_cdb_node *node, const uint8_t in[16])
1013 {
1014 	if (!bt_mesh_key_compare(in, &node->dev_key)) {
1015 		return 0;
1016 	}
1017 
1018 	bt_mesh_key_destroy(&node->dev_key);
1019 
1020 	return bt_mesh_key_import(BT_MESH_KEY_TYPE_DEV, in, &node->dev_key);
1021 }
1022 
bt_mesh_cdb_node_key_export(const struct bt_mesh_cdb_node * node,uint8_t out[16])1023 int bt_mesh_cdb_node_key_export(const struct bt_mesh_cdb_node *node, uint8_t out[16])
1024 {
1025 	return bt_mesh_key_export(out, &node->dev_key);
1026 }
1027 
bt_mesh_cdb_app_key_alloc(uint16_t net_idx,uint16_t app_idx)1028 struct bt_mesh_cdb_app_key *bt_mesh_cdb_app_key_alloc(uint16_t net_idx, uint16_t app_idx)
1029 {
1030 	struct bt_mesh_cdb_app_key *key;
1031 	struct bt_mesh_cdb_app_key *vacant_key = NULL;
1032 	int i;
1033 
1034 	for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.app_keys); ++i) {
1035 		key = &bt_mesh_cdb.app_keys[i];
1036 
1037 		if (key->app_idx == app_idx) {
1038 			return NULL;
1039 		}
1040 
1041 		if (key->net_idx != BT_MESH_KEY_UNUSED || vacant_key) {
1042 			continue;
1043 		}
1044 
1045 		vacant_key = key;
1046 	}
1047 
1048 	if (vacant_key) {
1049 		vacant_key->net_idx = net_idx;
1050 		vacant_key->app_idx = app_idx;
1051 	}
1052 
1053 	return vacant_key;
1054 }
1055 
bt_mesh_cdb_app_key_del(struct bt_mesh_cdb_app_key * key,bool store)1056 void bt_mesh_cdb_app_key_del(struct bt_mesh_cdb_app_key *key, bool store)
1057 {
1058 	LOG_DBG("AppIdx 0x%03x store %u", key->app_idx, store);
1059 
1060 	if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
1061 		update_cdb_app_key_settings(key, false);
1062 	}
1063 
1064 	key->net_idx = BT_MESH_KEY_UNUSED;
1065 	key->app_idx = BT_MESH_KEY_UNUSED;
1066 	bt_mesh_key_destroy(&key->keys[0].app_key);
1067 	bt_mesh_key_destroy(&key->keys[1].app_key);
1068 	memset(key->keys, 0, sizeof(key->keys));
1069 }
1070 
bt_mesh_cdb_app_key_get(uint16_t app_idx)1071 struct bt_mesh_cdb_app_key *bt_mesh_cdb_app_key_get(uint16_t app_idx)
1072 {
1073 	int i;
1074 
1075 	for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.app_keys); i++) {
1076 		struct bt_mesh_cdb_app_key *key = &bt_mesh_cdb.app_keys[i];
1077 
1078 		if (key->net_idx != BT_MESH_KEY_UNUSED &&
1079 		    key->app_idx == app_idx) {
1080 			return key;
1081 		}
1082 	}
1083 
1084 	return NULL;
1085 }
1086 
bt_mesh_cdb_app_key_store(const struct bt_mesh_cdb_app_key * key)1087 void bt_mesh_cdb_app_key_store(const struct bt_mesh_cdb_app_key *key)
1088 {
1089 	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
1090 		update_cdb_app_key_settings(key, true);
1091 	}
1092 }
1093 
bt_mesh_cdb_app_key_import(struct bt_mesh_cdb_app_key * key,int key_idx,const uint8_t in[16])1094 int bt_mesh_cdb_app_key_import(struct bt_mesh_cdb_app_key *key, int key_idx, const uint8_t in[16])
1095 {
1096 	if (!bt_mesh_key_compare(in, &key->keys[key_idx].app_key)) {
1097 		return 0;
1098 	}
1099 
1100 	bt_mesh_key_destroy(&key->keys[key_idx].app_key);
1101 
1102 	return bt_mesh_key_import(BT_MESH_KEY_TYPE_APP, in, &key->keys[key_idx].app_key);
1103 }
1104 
bt_mesh_cdb_app_key_export(const struct bt_mesh_cdb_app_key * key,int key_idx,uint8_t out[16])1105 int bt_mesh_cdb_app_key_export(const struct bt_mesh_cdb_app_key *key, int key_idx, uint8_t out[16])
1106 {
1107 	return bt_mesh_key_export(out, &key->keys[key_idx].app_key);
1108 }
1109 
clear_cdb_net(void)1110 static void clear_cdb_net(void)
1111 {
1112 	int err;
1113 
1114 	err = settings_delete("bt/mesh/cdb/Net");
1115 	if (err) {
1116 		LOG_ERR("Failed to clear Network");
1117 	} else {
1118 		LOG_DBG("Cleared Network");
1119 	}
1120 }
1121 
store_cdb_pending_net(void)1122 static void store_cdb_pending_net(void)
1123 {
1124 	struct net_val net;
1125 	int err;
1126 
1127 	LOG_DBG("");
1128 
1129 	net.iv.index = bt_mesh_cdb.iv_index;
1130 	net.iv.update = atomic_test_bit(bt_mesh_cdb.flags,
1131 					BT_MESH_CDB_IVU_IN_PROGRESS);
1132 	net.lowest_avail_addr = bt_mesh_cdb.lowest_avail_addr;
1133 
1134 	err = settings_save_one("bt/mesh/cdb/Net", &net, sizeof(net));
1135 	if (err) {
1136 		LOG_ERR("Failed to store Network value");
1137 	} else {
1138 		LOG_DBG("Stored Network value");
1139 	}
1140 }
1141 
store_cdb_pending_nodes(void)1142 static void store_cdb_pending_nodes(void)
1143 {
1144 	int i;
1145 
1146 	for (i = 0; i < ARRAY_SIZE(cdb_node_updates); ++i) {
1147 		struct node_update *update = &cdb_node_updates[i];
1148 		uint16_t addr;
1149 
1150 		if (update->addr == BT_MESH_ADDR_UNASSIGNED) {
1151 			continue;
1152 		}
1153 
1154 		addr = update->addr;
1155 		update->addr = BT_MESH_ADDR_UNASSIGNED;
1156 
1157 		LOG_DBG("addr: 0x%04x, clear: %d", addr, update->clear);
1158 
1159 		if (update->clear) {
1160 			clear_cdb_node(addr);
1161 		} else {
1162 			struct bt_mesh_cdb_node *node;
1163 
1164 			node = bt_mesh_cdb_node_get(addr);
1165 			if (node) {
1166 				store_cdb_node(node);
1167 			} else {
1168 				LOG_WRN("Node 0x%04x not found", addr);
1169 			}
1170 		}
1171 	}
1172 }
1173 
store_cdb_pending_keys(void)1174 static void store_cdb_pending_keys(void)
1175 {
1176 	int i;
1177 
1178 	for (i = 0; i < ARRAY_SIZE(cdb_key_updates); i++) {
1179 		struct key_update *update = &cdb_key_updates[i];
1180 
1181 		if (!update->valid) {
1182 			continue;
1183 		}
1184 
1185 		update->valid = 0U;
1186 
1187 		if (update->clear) {
1188 			if (update->app_key) {
1189 				clear_cdb_app_key(update->key_idx);
1190 			} else {
1191 				clear_cdb_subnet(update->key_idx);
1192 			}
1193 		} else {
1194 			if (update->app_key) {
1195 				struct bt_mesh_cdb_app_key *key;
1196 
1197 				key = bt_mesh_cdb_app_key_get(update->key_idx);
1198 				if (key) {
1199 					store_cdb_app_key(key);
1200 				} else {
1201 					LOG_WRN("AppKeyIndex 0x%03x not found", update->key_idx);
1202 				}
1203 			} else {
1204 				struct bt_mesh_cdb_subnet *sub;
1205 
1206 				sub = bt_mesh_cdb_subnet_get(update->key_idx);
1207 				if (sub) {
1208 					store_cdb_subnet(sub);
1209 				} else {
1210 					LOG_WRN("NetKeyIndex 0x%03x not found", update->key_idx);
1211 				}
1212 			}
1213 		}
1214 	}
1215 }
1216 
bt_mesh_cdb_pending_store(void)1217 void bt_mesh_cdb_pending_store(void)
1218 {
1219 	if (atomic_test_and_clear_bit(bt_mesh_cdb.flags,
1220 				      BT_MESH_CDB_SUBNET_PENDING)) {
1221 		if (atomic_test_bit(bt_mesh_cdb.flags,
1222 				    BT_MESH_CDB_VALID)) {
1223 			store_cdb_pending_net();
1224 		} else {
1225 			clear_cdb_net();
1226 		}
1227 	}
1228 
1229 	if (atomic_test_and_clear_bit(bt_mesh_cdb.flags,
1230 				      BT_MESH_CDB_NODES_PENDING)) {
1231 		store_cdb_pending_nodes();
1232 	}
1233 
1234 	if (atomic_test_and_clear_bit(bt_mesh_cdb.flags,
1235 				      BT_MESH_CDB_KEYS_PENDING)) {
1236 		store_cdb_pending_keys();
1237 	}
1238 }
1239