1 /*
2  * Copyright (c) 2017 Intel Corporation
3  * Copyright (c) 2020 Nordic Semiconductor ASA
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <string.h>
9 #include <stdlib.h>
10 #include <zephyr/bluetooth/mesh.h>
11 #include <zephyr/bluetooth/conn.h>
12 #include <zephyr/sys/iterable_sections.h>
13 
14 #include "mesh.h"
15 #include "net.h"
16 #include "app_keys.h"
17 #include "rpl.h"
18 #include "settings.h"
19 #include "crypto.h"
20 #include "proxy.h"
21 #include "friend.h"
22 #include "foundation.h"
23 #include "access.h"
24 
25 #include "common/bt_str.h"
26 
27 #define LOG_LEVEL CONFIG_BT_MESH_KEYS_LOG_LEVEL
28 #include <zephyr/logging/log.h>
29 LOG_MODULE_REGISTER(bt_mesh_app_keys);
30 
31 /* Tracking of what storage changes are pending for App Keys. We track this in
32  * a separate array here instead of within the respective bt_mesh_app_key
33  * struct itself, since once a key gets deleted its struct becomes invalid
34  * and may be reused for other keys.
35  */
36 struct app_key_update {
37 	uint16_t key_idx:12,    /* AppKey Index */
38 		 valid:1,       /* 1 if this entry is valid, 0 if not */
39 		 clear:1;       /* 1 if key needs clearing, 0 if storing */
40 };
41 
42 /* AppKey information for persistent storage. */
43 struct app_key_val {
44 	uint16_t net_idx;
45 	bool updated;
46 	struct bt_mesh_key val[2];
47 } __packed;
48 
49 /** Mesh Application Key. */
50 struct app_key {
51 	uint16_t net_idx;
52 	uint16_t app_idx;
53 	bool updated;
54 	struct bt_mesh_app_cred {
55 		uint8_t id;
56 		struct bt_mesh_key val;
57 	} keys[2];
58 };
59 
60 static struct app_key_update app_key_updates[CONFIG_BT_MESH_APP_KEY_COUNT];
61 
62 static struct app_key apps[CONFIG_BT_MESH_APP_KEY_COUNT] = {
63 	[0 ... (CONFIG_BT_MESH_APP_KEY_COUNT - 1)] = {
64 		.app_idx = BT_MESH_KEY_UNUSED,
65 		.net_idx = BT_MESH_KEY_UNUSED,
66 	}
67 };
68 
app_get(uint16_t app_idx)69 static struct app_key *app_get(uint16_t app_idx)
70 {
71 	for (int i = 0; i < ARRAY_SIZE(apps); i++) {
72 		if (apps[i].app_idx == app_idx) {
73 			return &apps[i];
74 		}
75 	}
76 
77 	return NULL;
78 }
79 
clear_app_key(uint16_t app_idx)80 static void clear_app_key(uint16_t app_idx)
81 {
82 	char path[20];
83 	int err;
84 
85 	snprintk(path, sizeof(path), "bt/mesh/AppKey/%x", app_idx);
86 	err = settings_delete(path);
87 	if (err) {
88 		LOG_ERR("Failed to clear AppKeyIndex 0x%03x", app_idx);
89 	} else {
90 		LOG_DBG("Cleared AppKeyIndex 0x%03x", app_idx);
91 	}
92 }
93 
store_app_key(uint16_t app_idx)94 static void store_app_key(uint16_t app_idx)
95 {
96 	const struct app_key *app;
97 	struct app_key_val key;
98 	char path[20];
99 	int err;
100 
101 	snprintk(path, sizeof(path), "bt/mesh/AppKey/%x", app_idx);
102 
103 	app = app_get(app_idx);
104 	if (!app) {
105 		LOG_WRN("ApKeyIndex 0x%03x not found", app_idx);
106 		return;
107 	}
108 
109 	key.net_idx = app->net_idx,
110 	key.updated = app->updated,
111 
112 	memcpy(&key.val[0], &app->keys[0].val, sizeof(struct bt_mesh_key));
113 	memcpy(&key.val[1], &app->keys[1].val, sizeof(struct bt_mesh_key));
114 
115 	err = settings_save_one(path, &key, sizeof(key));
116 	if (err) {
117 		LOG_ERR("Failed to store AppKey %s value", path);
118 	} else {
119 		LOG_DBG("Stored AppKey %s value", path);
120 	}
121 }
122 
app_key_update_find(uint16_t key_idx,struct app_key_update ** free_slot)123 static struct app_key_update *app_key_update_find(uint16_t key_idx,
124 					struct app_key_update **free_slot)
125 {
126 	struct app_key_update *match;
127 	int i;
128 
129 	match = NULL;
130 	*free_slot = NULL;
131 
132 	for (i = 0; i < ARRAY_SIZE(app_key_updates); i++) {
133 		struct app_key_update *update = &app_key_updates[i];
134 
135 		if (!update->valid) {
136 			*free_slot = update;
137 			continue;
138 		}
139 
140 		if (update->key_idx == key_idx) {
141 			match = update;
142 		}
143 	}
144 
145 	return match;
146 }
147 
update_app_key_settings(uint16_t app_idx,bool store)148 static void update_app_key_settings(uint16_t app_idx, bool store)
149 {
150 	struct app_key_update *update, *free_slot;
151 	uint8_t clear = store ? 0U : 1U;
152 
153 	LOG_DBG("AppKeyIndex 0x%03x", app_idx);
154 
155 	update = app_key_update_find(app_idx, &free_slot);
156 	if (update) {
157 		update->clear = clear;
158 		bt_mesh_settings_store_schedule(
159 					BT_MESH_SETTINGS_APP_KEYS_PENDING);
160 		return;
161 	}
162 
163 	if (!free_slot) {
164 		if (store) {
165 			store_app_key(app_idx);
166 		} else {
167 			clear_app_key(app_idx);
168 		}
169 		return;
170 	}
171 
172 	free_slot->valid = 1U;
173 	free_slot->key_idx = app_idx;
174 	free_slot->clear = clear;
175 
176 	bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_APP_KEYS_PENDING);
177 }
178 
app_key_evt(struct app_key * app,enum bt_mesh_key_evt evt)179 static void app_key_evt(struct app_key *app, enum bt_mesh_key_evt evt)
180 {
181 	STRUCT_SECTION_FOREACH(bt_mesh_app_key_cb, cb) {
182 		cb->evt_handler(app->app_idx, app->net_idx, evt);
183 	}
184 }
185 
app_key_alloc(uint16_t app_idx)186 static struct app_key *app_key_alloc(uint16_t app_idx)
187 {
188 	struct app_key *app = NULL;
189 
190 	for (int i = 0; i < ARRAY_SIZE(apps); i++) {
191 		/* Check for already existing app_key */
192 		if (apps[i].app_idx == app_idx) {
193 			return &apps[i];
194 		}
195 
196 		if (!app && apps[i].app_idx == BT_MESH_KEY_UNUSED) {
197 			app = &apps[i];
198 		}
199 	}
200 
201 	return app;
202 }
203 
app_key_del(struct app_key * app)204 static void app_key_del(struct app_key *app)
205 {
206 	LOG_DBG("AppIdx 0x%03x", app->app_idx);
207 
208 	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
209 		update_app_key_settings(app->app_idx, false);
210 	}
211 
212 	app_key_evt(app, BT_MESH_KEY_DELETED);
213 
214 	app->net_idx = BT_MESH_KEY_UNUSED;
215 	app->app_idx = BT_MESH_KEY_UNUSED;
216 	bt_mesh_key_destroy(&app->keys[0].val);
217 	bt_mesh_key_destroy(&app->keys[1].val);
218 	memset(app->keys, 0, sizeof(app->keys));
219 }
220 
app_key_revoke(struct app_key * app)221 static void app_key_revoke(struct app_key *app)
222 {
223 	if (!app->updated) {
224 		return;
225 	}
226 
227 	bt_mesh_key_destroy(&app->keys[0].val);
228 	memcpy(&app->keys[0], &app->keys[1], sizeof(app->keys[0]));
229 	memset(&app->keys[1], 0, sizeof(app->keys[1]));
230 	app->updated = false;
231 
232 	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
233 		update_app_key_settings(app->app_idx, true);
234 	}
235 
236 	app_key_evt(app, BT_MESH_KEY_REVOKED);
237 }
238 
bt_mesh_app_key_add(uint16_t app_idx,uint16_t net_idx,const uint8_t key[16])239 uint8_t bt_mesh_app_key_add(uint16_t app_idx, uint16_t net_idx,
240 			const uint8_t key[16])
241 {
242 	struct app_key *app;
243 
244 	LOG_DBG("net_idx 0x%04x app_idx %04x val %s", net_idx, app_idx, bt_hex(key, 16));
245 
246 	if (!bt_mesh_subnet_get(net_idx)) {
247 		return STATUS_INVALID_NETKEY;
248 	}
249 
250 	app = app_key_alloc(app_idx);
251 	if (!app) {
252 		return STATUS_INSUFF_RESOURCES;
253 	}
254 
255 	if (app->app_idx == app_idx) {
256 		if (app->net_idx != net_idx) {
257 			return STATUS_INVALID_NETKEY;
258 		}
259 
260 		if (bt_mesh_key_compare(key, &app->keys[0].val)) {
261 			return STATUS_IDX_ALREADY_STORED;
262 		}
263 
264 		return STATUS_SUCCESS;
265 	}
266 
267 	if (bt_mesh_app_id(key, &app->keys[0].id)) {
268 		return STATUS_CANNOT_SET;
269 	}
270 
271 	LOG_DBG("AppIdx 0x%04x AID 0x%02x", app_idx, app->keys[0].id);
272 
273 	app->net_idx = net_idx;
274 	app->app_idx = app_idx;
275 	app->updated = false;
276 	if (bt_mesh_key_import(BT_MESH_KEY_TYPE_APP, key, &app->keys[0].val)) {
277 		LOG_ERR("Unable to import application key");
278 		return STATUS_CANNOT_SET;
279 	}
280 
281 	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
282 		LOG_DBG("Storing AppKey persistently");
283 		update_app_key_settings(app->app_idx, true);
284 	}
285 
286 	app_key_evt(app, BT_MESH_KEY_ADDED);
287 
288 	return STATUS_SUCCESS;
289 }
290 
bt_mesh_app_key_update(uint16_t app_idx,uint16_t net_idx,const uint8_t key[16])291 uint8_t bt_mesh_app_key_update(uint16_t app_idx, uint16_t net_idx,
292 			       const uint8_t key[16])
293 {
294 	struct app_key *app;
295 	struct bt_mesh_subnet *sub;
296 
297 	LOG_DBG("net_idx 0x%04x app_idx %04x val %s", net_idx, app_idx, bt_hex(key, 16));
298 
299 	app = app_get(app_idx);
300 	if (!app) {
301 		return STATUS_INVALID_APPKEY;
302 	}
303 
304 	if (net_idx != BT_MESH_KEY_UNUSED && app->net_idx != net_idx) {
305 		return STATUS_INVALID_BINDING;
306 	}
307 
308 	sub = bt_mesh_subnet_get(app->net_idx);
309 	if (!sub) {
310 		return STATUS_INVALID_NETKEY;
311 	}
312 
313 	/* The AppKey Update message shall generate an error when node
314 	 * is in normal operation, Phase 2, or Phase 3 or in Phase 1
315 	 * when the AppKey Update message on a valid AppKeyIndex when
316 	 * the AppKey value is different.
317 	 */
318 	if (sub->kr_phase != BT_MESH_KR_PHASE_1) {
319 		return STATUS_CANNOT_UPDATE;
320 	}
321 
322 	if (app->updated) {
323 		if (bt_mesh_key_compare(key, &app->keys[1].val)) {
324 			return STATUS_IDX_ALREADY_STORED;
325 		}
326 
327 		return STATUS_SUCCESS;
328 	}
329 
330 	if (bt_mesh_app_id(key, &app->keys[1].id)) {
331 		return STATUS_CANNOT_UPDATE;
332 	}
333 
334 	LOG_DBG("app_idx 0x%04x AID 0x%02x", app_idx, app->keys[1].id);
335 
336 	app->updated = true;
337 	if (bt_mesh_key_import(BT_MESH_KEY_TYPE_APP, key, &app->keys[1].val)) {
338 		LOG_ERR("Unable to import application key");
339 		return STATUS_CANNOT_UPDATE;
340 	}
341 
342 	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
343 		LOG_DBG("Storing AppKey persistently");
344 		update_app_key_settings(app->app_idx, true);
345 	}
346 
347 	app_key_evt(app, BT_MESH_KEY_UPDATED);
348 
349 	return STATUS_SUCCESS;
350 }
351 
bt_mesh_app_key_del(uint16_t app_idx,uint16_t net_idx)352 uint8_t bt_mesh_app_key_del(uint16_t app_idx, uint16_t net_idx)
353 {
354 	struct app_key *app;
355 
356 	LOG_DBG("AppIdx 0x%03x", app_idx);
357 
358 	if (net_idx != BT_MESH_KEY_UNUSED && !bt_mesh_subnet_get(net_idx)) {
359 		return STATUS_INVALID_NETKEY;
360 	}
361 
362 	app = app_get(app_idx);
363 	if (!app) {
364 		/* This could be a retry of a previous attempt that had its
365 		 * response lost, so pretend that it was a success.
366 		 */
367 		return STATUS_SUCCESS;
368 	}
369 
370 	if (net_idx != BT_MESH_KEY_UNUSED && net_idx != app->net_idx) {
371 		return STATUS_INVALID_BINDING;
372 	}
373 
374 	app_key_del(app);
375 
376 	return STATUS_SUCCESS;
377 }
378 
app_id_set(struct app_key * app,int key_idx,const struct bt_mesh_key * key)379 static int app_id_set(struct app_key *app, int key_idx, const struct bt_mesh_key *key)
380 {
381 	uint8_t raw_key[16];
382 	int err;
383 
384 	err = bt_mesh_key_export(raw_key, key);
385 	if (err) {
386 		return err;
387 	}
388 
389 	err = bt_mesh_app_id(raw_key, &app->keys[key_idx].id);
390 	if (err) {
391 		return err;
392 	}
393 
394 	bt_mesh_key_assign(&app->keys[key_idx].val, key);
395 
396 	return 0;
397 }
398 
bt_mesh_app_key_set(uint16_t app_idx,uint16_t net_idx,const struct bt_mesh_key * old_key,const struct bt_mesh_key * new_key)399 int bt_mesh_app_key_set(uint16_t app_idx, uint16_t net_idx,
400 			const struct bt_mesh_key *old_key, const struct bt_mesh_key *new_key)
401 {
402 	struct app_key *app;
403 
404 	app = app_key_alloc(app_idx);
405 	if (!app) {
406 		return -ENOMEM;
407 	}
408 
409 	if (app->app_idx == app_idx) {
410 		return 0;
411 	}
412 
413 	LOG_DBG("AppIdx 0x%04x AID 0x%02x", app_idx, app->keys[0].id);
414 
415 	if (app_id_set(app, 0, old_key)) {
416 		return -EIO;
417 	}
418 
419 	if (new_key != NULL && app_id_set(app, 1, new_key)) {
420 		return -EIO;
421 	}
422 
423 	app->net_idx = net_idx;
424 	app->app_idx = app_idx;
425 	app->updated = !!new_key;
426 
427 	return 0;
428 }
429 
bt_mesh_app_key_exists(uint16_t app_idx)430 bool bt_mesh_app_key_exists(uint16_t app_idx)
431 {
432 	for (int i = 0; i < ARRAY_SIZE(apps); i++) {
433 		if (apps[i].app_idx == app_idx) {
434 			return true;
435 		}
436 	}
437 
438 	return false;
439 }
440 
bt_mesh_app_keys_get(uint16_t net_idx,uint16_t app_idxs[],size_t max,off_t skip)441 ssize_t bt_mesh_app_keys_get(uint16_t net_idx, uint16_t app_idxs[], size_t max,
442 			     off_t skip)
443 {
444 	size_t count = 0;
445 
446 	for (int i = 0; i < ARRAY_SIZE(apps); i++) {
447 		struct app_key *app = &apps[i];
448 
449 		if (app->app_idx == BT_MESH_KEY_UNUSED) {
450 			continue;
451 		}
452 
453 		if (net_idx != BT_MESH_KEY_ANY && app->net_idx != net_idx) {
454 			continue;
455 		}
456 
457 		if (skip) {
458 			skip--;
459 			continue;
460 		}
461 
462 		if (count >= max) {
463 			return -ENOMEM;
464 		}
465 
466 		app_idxs[count++] = app->app_idx;
467 	}
468 
469 	return count;
470 }
471 
bt_mesh_keys_resolve(struct bt_mesh_msg_ctx * ctx,struct bt_mesh_subnet ** sub,const struct bt_mesh_key ** app_key,uint8_t * aid)472 int bt_mesh_keys_resolve(struct bt_mesh_msg_ctx *ctx,
473 			 struct bt_mesh_subnet **sub,
474 			 const struct bt_mesh_key **app_key, uint8_t *aid)
475 {
476 	struct app_key *app = NULL;
477 
478 	if (BT_MESH_IS_DEV_KEY(ctx->app_idx)) {
479 		/* With device keys, the application has to decide which subnet
480 		 * to send on.
481 		 */
482 		*sub = bt_mesh_subnet_get(ctx->net_idx);
483 		if (!*sub) {
484 			LOG_WRN("Unknown NetKey 0x%03x", ctx->net_idx);
485 			return -EINVAL;
486 		}
487 
488 		if (ctx->app_idx == BT_MESH_KEY_DEV_REMOTE &&
489 		    !bt_mesh_has_addr(ctx->addr)) {
490 			struct bt_mesh_cdb_node *node;
491 
492 			if (!IS_ENABLED(CONFIG_BT_MESH_CDB)) {
493 				LOG_WRN("No DevKey for 0x%04x", ctx->addr);
494 				return -EINVAL;
495 			}
496 
497 			node = bt_mesh_cdb_node_get(ctx->addr);
498 			if (!node) {
499 				LOG_WRN("No DevKey for 0x%04x", ctx->addr);
500 				return -EINVAL;
501 			}
502 
503 			*app_key = &node->dev_key;
504 		} else {
505 			*app_key = &bt_mesh.dev_key;
506 		}
507 
508 		*aid = 0;
509 		return 0;
510 	}
511 
512 	app = app_get(ctx->app_idx);
513 	if (!app) {
514 		LOG_WRN("Unknown AppKey 0x%03x", ctx->app_idx);
515 		return -EINVAL;
516 	}
517 
518 	*sub = bt_mesh_subnet_get(app->net_idx);
519 	if (!*sub) {
520 		LOG_WRN("Unknown NetKey 0x%03x", app->net_idx);
521 		return -EINVAL;
522 	}
523 
524 	if ((*sub)->kr_phase == BT_MESH_KR_PHASE_2 && app->updated) {
525 		*aid = app->keys[1].id;
526 		*app_key = &app->keys[1].val;
527 	} else {
528 		*aid = app->keys[0].id;
529 		*app_key = &app->keys[0].val;
530 	}
531 
532 	return 0;
533 }
534 
bt_mesh_app_key_find(bool dev_key,uint8_t aid,struct bt_mesh_net_rx * rx,int (* cb)(struct bt_mesh_net_rx * rx,const struct bt_mesh_key * key,void * cb_data),void * cb_data)535 uint16_t bt_mesh_app_key_find(bool dev_key, uint8_t aid,
536 			      struct bt_mesh_net_rx *rx,
537 			      int (*cb)(struct bt_mesh_net_rx *rx,
538 					const struct bt_mesh_key *key, void *cb_data),
539 			      void *cb_data)
540 {
541 	int err, i;
542 
543 	if (dev_key) {
544 		/* Attempt remote dev key first, as that is only available for
545 		 * provisioner devices, which normally don't interact with nodes
546 		 * that know their local dev key.
547 		 */
548 		if (IS_ENABLED(CONFIG_BT_MESH_CDB) &&
549 		    rx->net_if != BT_MESH_NET_IF_LOCAL) {
550 			struct bt_mesh_cdb_node *node;
551 
552 			node = bt_mesh_cdb_node_get(rx->ctx.addr);
553 			if (node && !cb(rx, &node->dev_key, cb_data)) {
554 				return BT_MESH_KEY_DEV_REMOTE;
555 			}
556 		}
557 
558 		/** MshPRTv1.1: 3.4.3:
559 		 *  The Device key is only valid for unicast addresses.
560 		 */
561 		if (BT_MESH_ADDR_IS_UNICAST(rx->ctx.recv_dst)) {
562 			err = cb(rx, &bt_mesh.dev_key, cb_data);
563 			if (!err) {
564 				return BT_MESH_KEY_DEV_LOCAL;
565 			}
566 
567 #if defined(CONFIG_BT_MESH_RPR_SRV)
568 			if (atomic_test_bit(bt_mesh.flags, BT_MESH_DEVKEY_CAND)) {
569 				err = cb(rx, &bt_mesh.dev_key_cand, cb_data);
570 				if (!err) {
571 					/* MshPRTv1.1: 3.6.4.2:
572 					 * If a message is successfully decrypted using the device
573 					 * key candidate, the device key candidate should
574 					 * permanently replace the original devkey.
575 					 */
576 					bt_mesh_dev_key_cand_activate();
577 					return BT_MESH_KEY_DEV_LOCAL;
578 				}
579 			}
580 #endif
581 		}
582 
583 		return BT_MESH_KEY_UNUSED;
584 	}
585 
586 	for (i = 0; i < ARRAY_SIZE(apps); i++) {
587 		const struct app_key *app = &apps[i];
588 		const struct bt_mesh_app_cred *cred;
589 
590 		if (app->app_idx == BT_MESH_KEY_UNUSED) {
591 			continue;
592 		}
593 
594 		if (app->net_idx != rx->sub->net_idx) {
595 			continue;
596 		}
597 
598 		if (rx->new_key && app->updated) {
599 			cred = &app->keys[1];
600 		} else {
601 			cred = &app->keys[0];
602 		}
603 
604 		if (cred->id != aid) {
605 			continue;
606 		}
607 
608 		err = cb(rx, &cred->val, cb_data);
609 		if (err) {
610 			continue;
611 		}
612 
613 		return app->app_idx;
614 	}
615 
616 	return BT_MESH_KEY_UNUSED;
617 }
618 
subnet_evt(struct bt_mesh_subnet * sub,enum bt_mesh_key_evt evt)619 static void subnet_evt(struct bt_mesh_subnet *sub, enum bt_mesh_key_evt evt)
620 {
621 	if (evt == BT_MESH_KEY_UPDATED || evt == BT_MESH_KEY_ADDED) {
622 		return;
623 	}
624 
625 	for (int i = 0; i < ARRAY_SIZE(apps); i++) {
626 		struct app_key *app = &apps[i];
627 
628 		if (app->app_idx == BT_MESH_KEY_UNUSED) {
629 			continue;
630 		}
631 
632 		if (app->net_idx != sub->net_idx) {
633 			continue;
634 		}
635 
636 		if (evt == BT_MESH_KEY_DELETED) {
637 			app_key_del(app);
638 		} else if (evt == BT_MESH_KEY_REVOKED) {
639 			app_key_revoke(app);
640 		} else if (evt == BT_MESH_KEY_SWAPPED && app->updated) {
641 			app_key_evt(app, BT_MESH_KEY_SWAPPED);
642 		}
643 	}
644 }
645 
646 BT_MESH_SUBNET_CB_DEFINE(app_keys) = {
647 	.evt_handler = subnet_evt,
648 };
649 
bt_mesh_app_keys_reset(void)650 void bt_mesh_app_keys_reset(void)
651 {
652 	for (int i = 0; i < ARRAY_SIZE(apps); i++) {
653 		struct app_key *app = &apps[i];
654 
655 		if (app->app_idx != BT_MESH_KEY_UNUSED) {
656 			app_key_del(app);
657 		}
658 	}
659 }
660 
app_key_set(const char * name,size_t len_rd,settings_read_cb read_cb,void * cb_arg)661 static int app_key_set(const char *name, size_t len_rd,
662 		       settings_read_cb read_cb, void *cb_arg)
663 {
664 	struct app_key_val key;
665 	struct bt_mesh_key val[2];
666 	uint16_t app_idx;
667 	int err;
668 
669 	if (!name) {
670 		LOG_ERR("Insufficient number of arguments");
671 		return -ENOENT;
672 	}
673 
674 	app_idx = strtol(name, NULL, 16);
675 
676 	if (!len_rd) {
677 		return 0;
678 	}
679 
680 	err = bt_mesh_settings_set(read_cb, cb_arg, &key, sizeof(key));
681 	if (err < 0) {
682 		return -EINVAL;
683 	}
684 
685 	/* One extra copying since key.val array is from packed structure
686 	 * and might be unaligned.
687 	 */
688 	memcpy(val, key.val, sizeof(key.val));
689 
690 	err = bt_mesh_app_key_set(app_idx, key.net_idx, &val[0],
691 			      key.updated ? &val[1] : NULL);
692 	if (err) {
693 		LOG_ERR("Failed to set \'app-key\'");
694 		return err;
695 	}
696 
697 	LOG_DBG("AppKeyIndex 0x%03x recovered from storage", app_idx);
698 
699 	return 0;
700 }
701 
702 BT_MESH_SETTINGS_DEFINE(app, "AppKey", app_key_set);
703 
bt_mesh_app_key_pending_store(void)704 void bt_mesh_app_key_pending_store(void)
705 {
706 	int i;
707 
708 	for (i = 0; i < ARRAY_SIZE(app_key_updates); i++) {
709 		struct app_key_update *update = &app_key_updates[i];
710 
711 		if (!update->valid) {
712 			continue;
713 		}
714 
715 		update->valid = 0U;
716 
717 		if (update->clear) {
718 			clear_app_key(update->key_idx);
719 		} else {
720 			store_app_key(update->key_idx);
721 		}
722 	}
723 }
724