1 /*
2 * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <string.h>
8 #include <errno.h>
9
10 #include "mesh.h"
11 #include "mesh_common.h"
12 #include "access.h"
13 #include "beacon.h"
14 #include "foundation.h"
15 #include "proxy_client.h"
16 #include "provisioner_prov.h"
17 #include "provisioner_main.h"
18
19 #if CONFIG_BLE_MESH_FAST_PROV
20
21 #define ACTION_ENTER 0x01
22 #define ACTION_SUSPEND 0x02
23 #define ACTION_EXIT 0x03
24
bt_mesh_fast_prov_dev_key_get(uint16_t dst)25 const uint8_t *bt_mesh_fast_prov_dev_key_get(uint16_t dst)
26 {
27 if (!BLE_MESH_ADDR_IS_UNICAST(dst)) {
28 BT_ERR("Invalid unicast address 0x%04x", dst);
29 return NULL;
30 }
31
32 if (dst == bt_mesh_primary_addr()) {
33 return bt_mesh.dev_key;
34 }
35
36 return bt_mesh_provisioner_dev_key_get(dst);
37 }
38
bt_mesh_fast_prov_subnet_get(uint16_t net_idx)39 struct bt_mesh_subnet *bt_mesh_fast_prov_subnet_get(uint16_t net_idx)
40 {
41 struct bt_mesh_subnet *sub = NULL;
42 int i;
43
44 for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
45 sub = &bt_mesh.sub[i];
46 if (sub->net_idx == net_idx) {
47 return sub;
48 }
49 }
50
51 for (i = 0; i < ARRAY_SIZE(bt_mesh.p_sub); i++) {
52 sub = bt_mesh.p_sub[i];
53 if (sub && sub->net_idx == net_idx) {
54 return sub;
55 }
56 }
57
58 return NULL;
59 }
60
bt_mesh_fast_prov_app_key_find(uint16_t app_idx)61 struct bt_mesh_app_key *bt_mesh_fast_prov_app_key_find(uint16_t app_idx)
62 {
63 struct bt_mesh_app_key *key = NULL;
64 int i;
65
66 for (i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) {
67 key = &bt_mesh.app_keys[i];
68 if (key->net_idx != BLE_MESH_KEY_UNUSED &&
69 key->app_idx == app_idx) {
70 return key;
71 }
72 }
73
74 for (i = 0; i < ARRAY_SIZE(bt_mesh.p_app_keys); i++) {
75 key = bt_mesh.p_app_keys[i];
76 if (key && key->net_idx != BLE_MESH_KEY_UNUSED &&
77 key->app_idx == app_idx) {
78 return key;
79 }
80 }
81
82 return NULL;
83 }
84
bt_mesh_set_fast_prov_net_idx(uint16_t net_idx)85 uint8_t bt_mesh_set_fast_prov_net_idx(uint16_t net_idx)
86 {
87 /* Set net_idx for fast provisioning */
88 bt_mesh_provisioner_set_fast_prov_net_idx(net_idx);
89
90 if (bt_mesh_fast_prov_subnet_get(net_idx) == NULL) {
91 /* If NetKey is not found, wait for NetKey to be added. */
92 BT_WARN("Wait for NetKey for fast provisioning");
93 return 0x01; /*status: Wait for NetKey */
94 }
95
96 return 0x0; /* status: Succeed */
97 }
98
bt_mesh_fast_prov_net_key_add(const uint8_t net_key[16])99 uint8_t bt_mesh_fast_prov_net_key_add(const uint8_t net_key[16])
100 {
101 uint16_t net_idx = 0U;
102 int err = 0;
103
104 net_idx = bt_mesh_provisioner_get_fast_prov_net_idx();
105 bt_mesh.p_net_idx_next = net_idx;
106
107 err = bt_mesh_provisioner_local_net_key_add(net_key, &net_idx);
108 if (err) {
109 BT_ERR("Invalid NetKeyIndex 0x%04x", net_idx);
110 return 0x01; /* status: Add NetKey failed */
111 };
112
113 bt_mesh_provisioner_set_fast_prov_net_idx(net_idx);
114 return 0x0; /* status: Succeed */
115 }
116
bt_mesh_fast_prov_net_key_get(uint16_t net_idx)117 const uint8_t *bt_mesh_fast_prov_net_key_get(uint16_t net_idx)
118 {
119 struct bt_mesh_subnet *sub = NULL;
120
121 sub = bt_mesh_fast_prov_subnet_get(net_idx);
122 if (!sub) {
123 BT_ERR("Invalid NetKeyIndex 0x%04x", net_idx);
124 return NULL;
125 }
126
127 return (sub->kr_flag ? sub->keys[1].net : sub->keys[0].net);
128 }
129
bt_mesh_get_fast_prov_app_key(uint16_t net_idx,uint16_t app_idx)130 const uint8_t *bt_mesh_get_fast_prov_app_key(uint16_t net_idx, uint16_t app_idx)
131 {
132 struct bt_mesh_app_key *key = NULL;
133
134 key = bt_mesh_fast_prov_app_key_find(app_idx);
135 if (!key) {
136 BT_ERR("Invalid AppKeyIndex 0x%04x", app_idx);
137 return NULL;
138 }
139
140 return (key->updated ? key->keys[1].val : key->keys[0].val);
141 }
142
bt_mesh_set_fast_prov_action(uint8_t action)143 uint8_t bt_mesh_set_fast_prov_action(uint8_t action)
144 {
145 if (!action || action > ACTION_EXIT) {
146 return 0x01;
147 }
148
149 if ((!bt_mesh_is_provisioner_en() && (action == ACTION_SUSPEND || action == ACTION_EXIT)) ||
150 (bt_mesh_is_provisioner_en() && (action == ACTION_ENTER))) {
151 BT_WARN("%s, Already", __func__);
152 return 0x0;
153 }
154
155 if (action == ACTION_ENTER) {
156 if (bt_mesh_beacon_get() == BLE_MESH_BEACON_ENABLED) {
157 bt_mesh_beacon_disable();
158 }
159 if (IS_ENABLED(CONFIG_BLE_MESH_PB_GATT)) {
160 bt_mesh_proxy_client_prov_enable();
161 }
162 bt_mesh_provisioner_set_primary_elem_addr(bt_mesh_primary_addr());
163 bt_mesh_provisioner_set_prov_bearer(BLE_MESH_PROV_ADV, false);
164 bt_mesh_provisioner_fast_prov_enable(true);
165 bt_mesh_atomic_or(bt_mesh.flags, BIT(BLE_MESH_PROVISIONER) | BIT(BLE_MESH_VALID_PROV));
166 } else {
167 if (IS_ENABLED(CONFIG_BLE_MESH_PB_GATT)) {
168 bt_mesh_proxy_client_prov_disable();
169 }
170 if (bt_mesh_beacon_get() == BLE_MESH_BEACON_ENABLED) {
171 bt_mesh_beacon_enable();
172 }
173 bt_mesh_atomic_and(bt_mesh.flags, ~(BIT(BLE_MESH_PROVISIONER) | BIT(BLE_MESH_VALID_PROV)));
174 bt_mesh_provisioner_fast_prov_enable(false);
175 if (action == ACTION_EXIT) {
176 bt_mesh_provisioner_remove_node(NULL);
177 }
178 }
179
180 return 0x0;
181 }
182 #endif /* CONFIG_BLE_MESH_FAST_PROV */
183