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