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