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