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