1 /* Bluetooth Mesh */
2
3 /*
4 * Copyright (c) 2017 Intel Corporation
5 * Additional Copyright (c) 2020 Espressif Systems (Shanghai) PTE LTD
6 *
7 * SPDX-License-Identifier: Apache-2.0
8 */
9 #include <string.h>
10 #include <errno.h>
11
12 #include "mesh.h"
13 #include "lpn.h"
14 #include "crypto.h"
15 #include "access.h"
16 #include "foundation.h"
17 #include "transport.h"
18 #include "mesh_main.h"
19 #include "settings.h"
20
find_model(uint16_t elem_addr,uint16_t cid,uint16_t mod_id)21 static struct bt_mesh_model *find_model(uint16_t elem_addr, uint16_t cid, uint16_t mod_id)
22 {
23 struct bt_mesh_elem *elem = NULL;
24
25 if (!BLE_MESH_ADDR_IS_UNICAST(elem_addr)) {
26 BT_ERR("Invalid unicast address 0x%04x", elem_addr);
27 return NULL;
28 }
29
30 elem = bt_mesh_elem_find(elem_addr);
31 if (elem == NULL) {
32 BT_ERR("No element found, addr 0x%04x", elem_addr);
33 return NULL;
34 }
35
36 if (cid == BLE_MESH_CID_NVAL) {
37 return bt_mesh_model_find(elem, mod_id);
38 } else {
39 return bt_mesh_model_find_vnd(elem, cid, mod_id);
40 }
41 }
42
bt_mesh_model_subscribe_group_addr(uint16_t elem_addr,uint16_t cid,uint16_t mod_id,uint16_t group_addr)43 int bt_mesh_model_subscribe_group_addr(uint16_t elem_addr, uint16_t cid,
44 uint16_t mod_id, uint16_t group_addr)
45 {
46 struct bt_mesh_model *model = NULL;
47 int i;
48
49 model = find_model(elem_addr, cid, mod_id);
50 if (model == NULL) {
51 BT_ERR("Subscribe, model not found, cid 0x%04x, mod_id 0x%04x", cid, mod_id);
52 return -ENODEV;
53 }
54
55 if (!BLE_MESH_ADDR_IS_GROUP(group_addr)) {
56 BT_ERR("Subscribe, not a group address 0x%04x", group_addr);
57 return -EINVAL;
58 }
59
60 if (bt_mesh_model_find_group(model, group_addr)) {
61 BT_INFO("Group address 0x%04x already exists", group_addr);
62 return 0;
63 }
64
65 for (i = 0; i < ARRAY_SIZE(model->groups); i++) {
66 if (model->groups[i] == BLE_MESH_ADDR_UNASSIGNED) {
67 model->groups[i] = group_addr;
68
69 if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) {
70 bt_mesh_store_mod_sub(model);
71 }
72
73 if (IS_ENABLED(CONFIG_BLE_MESH_LOW_POWER)) {
74 bt_mesh_lpn_group_add(group_addr);
75 }
76
77 BT_INFO("Subscribe group address 0x%04x", group_addr);
78 return 0;
79 }
80 }
81
82 BT_ERR("Subscribe, model sub is full!");
83 return -ENOMEM;
84 }
85
bt_mesh_model_unsubscribe_group_addr(uint16_t elem_addr,uint16_t cid,uint16_t mod_id,uint16_t group_addr)86 int bt_mesh_model_unsubscribe_group_addr(uint16_t elem_addr, uint16_t cid,
87 uint16_t mod_id, uint16_t group_addr)
88 {
89 struct bt_mesh_model *model = NULL;
90 uint16_t *match = NULL;
91
92 model = find_model(elem_addr, cid, mod_id);
93 if (model == NULL) {
94 BT_ERR("Unsubscribe, model not found, cid 0x%04x, mod_id 0x%04x", cid, mod_id);
95 return -ENODEV;
96 }
97
98 if (!BLE_MESH_ADDR_IS_GROUP(group_addr)) {
99 BT_ERR("Unsubscribe, not a group address 0x%04x", group_addr);
100 return -EINVAL;
101 }
102
103 match = bt_mesh_model_find_group(model, group_addr);
104 if (match == NULL) {
105 BT_WARN("Group address 0x%04x not exists", group_addr);
106 return -EEXIST;
107 }
108
109 *match = BLE_MESH_ADDR_UNASSIGNED;
110
111 if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) {
112 bt_mesh_store_mod_sub(model);
113 }
114
115 if (IS_ENABLED(CONFIG_BLE_MESH_LOW_POWER)) {
116 bt_mesh_lpn_group_del(&group_addr, 1);
117 }
118
119 BT_INFO("Unsubscribe group address 0x%04x", group_addr);
120 return 0;
121 }
122
123 #if CONFIG_BLE_MESH_NODE
124
bt_mesh_node_get_local_net_key(uint16_t net_idx)125 const uint8_t *bt_mesh_node_get_local_net_key(uint16_t net_idx)
126 {
127 struct bt_mesh_subnet *sub = NULL;
128
129 if (net_idx > 0xFFF) {
130 BT_ERR("Invalid NetKeyIndex 0x%04x", net_idx);
131 return NULL;
132 }
133
134 sub = bt_mesh_subnet_get(net_idx);
135 if (!sub) {
136 BT_ERR("NetKey 0x%04x not exists", net_idx);
137 return NULL;
138 }
139
140 return sub->kr_flag ? sub->keys[1].net : sub->keys[0].net;
141 }
142
bt_mesh_node_get_local_app_key(uint16_t app_idx)143 const uint8_t *bt_mesh_node_get_local_app_key(uint16_t app_idx)
144 {
145 struct bt_mesh_app_key *key = NULL;
146
147 if (app_idx > 0xFFF) {
148 BT_ERR("Invalid AppKeyIndex 0x%04x", app_idx);
149 return NULL;
150 }
151
152 key = bt_mesh_app_key_find(app_idx);
153 if (!key) {
154 BT_ERR("AppKey 0x%04x not exists", app_idx);
155 return NULL;
156 }
157
158 return key->updated ? key->keys[1].val : key->keys[0].val;
159 }
160
bt_mesh_node_local_net_key_add(uint16_t net_idx,const uint8_t net_key[16])161 int bt_mesh_node_local_net_key_add(uint16_t net_idx, const uint8_t net_key[16])
162 {
163 struct bt_mesh_subnet *sub = NULL;
164 int err = 0;
165 int i;
166
167 if (net_idx > 0xFFF || net_key == NULL) {
168 BT_ERR("%s, Invalid parameter", __func__);
169 return -EINVAL;
170 }
171
172 if (!bt_mesh_is_provisioned()) {
173 BT_ERR("Not provisioned, failed to add NetKey");
174 return -EIO;
175 }
176
177 sub = bt_mesh_subnet_get(net_idx);
178 if (sub) {
179 BT_WARN("NetKey 0x%04x already exists", net_idx);
180 return -EEXIST;
181 }
182
183 for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
184 if (bt_mesh.sub[i].net_idx != BLE_MESH_KEY_UNUSED) {
185 if ((bt_mesh.sub[i].kr_flag == false &&
186 memcmp(bt_mesh.sub[i].keys[0].net, net_key, 16) == 0) ||
187 (bt_mesh.sub[i].kr_flag == true &&
188 memcmp(bt_mesh.sub[i].keys[1].net, net_key, 16) == 0)) {
189 BT_WARN("Key value %s already exists", bt_hex(net_key, 16));
190 return -EEXIST;
191 }
192 }
193 }
194
195 for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
196 if (bt_mesh.sub[i].net_idx == BLE_MESH_KEY_UNUSED) {
197 sub = &bt_mesh.sub[i];
198 break;
199 }
200 }
201
202 if (sub == NULL) {
203 BT_ERR("NetKey is full!");
204 return -ENOMEM;
205 }
206
207 err = bt_mesh_net_keys_create(&sub->keys[0], net_key);
208 if (err) {
209 BT_ERR("Failed to create keys for NetKey 0x%04x", net_idx);
210 return -EIO;
211 }
212
213 sub->net_idx = net_idx;
214 sub->kr_flag = false;
215 sub->kr_phase = BLE_MESH_KR_NORMAL;
216 if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER)) {
217 sub->node_id = BLE_MESH_NODE_IDENTITY_STOPPED;
218 } else {
219 sub->node_id = BLE_MESH_NODE_IDENTITY_NOT_SUPPORTED;
220 }
221
222 if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) {
223 BT_DBG("Storing NetKey persistently");
224 bt_mesh_store_subnet(sub);
225 }
226
227 /* Make sure we have valid beacon data to be sent */
228 bt_mesh_net_beacon_update(sub);
229
230 return 0;
231 }
232
bt_mesh_node_local_app_key_add(uint16_t net_idx,uint16_t app_idx,const uint8_t app_key[16])233 int bt_mesh_node_local_app_key_add(uint16_t net_idx, uint16_t app_idx,
234 const uint8_t app_key[16])
235 {
236 struct bt_mesh_app_key *key = NULL;
237
238 if (net_idx > 0xFFF || app_idx > 0xFFF || app_key == NULL) {
239 BT_ERR("%s, Invalid parameter", __func__);
240 return -EINVAL;
241 }
242
243 if (!bt_mesh_is_provisioned()) {
244 BT_ERR("Not provisioned, failed to add AppKey");
245 return -EIO;
246 }
247
248 if (bt_mesh_subnet_get(net_idx) == NULL) {
249 BT_ERR("Subnet 0x%04x not exists", net_idx);
250 return -EIO;
251 }
252
253 key = bt_mesh_app_key_find(app_idx);
254 if (key) {
255 BT_WARN("AppKey 0x%04x already exists", app_idx);
256 return -EEXIST;
257 }
258
259 for (int i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) {
260 if (bt_mesh.app_keys[i].net_idx != BLE_MESH_KEY_UNUSED) {
261 if ((bt_mesh.app_keys[i].updated == false &&
262 memcmp(bt_mesh.app_keys[i].keys[0].val, app_key, 16) == 0) ||
263 (bt_mesh.app_keys[i].updated == true &&
264 memcmp(bt_mesh.app_keys[i].keys[1].val, app_key, 16) == 0)) {
265 BT_WARN("Key value %s already exists", bt_hex(app_key, 16));
266 return -EEXIST;
267 }
268 }
269 }
270
271 key = bt_mesh_app_key_alloc(app_idx);
272 if (key) {
273 struct bt_mesh_app_keys *keys = &key->keys[0];
274
275 if (bt_mesh_app_id(app_key, &keys->id)) {
276 BT_ERR("Failed to generate AID");
277 return -EIO;
278 }
279
280 key->net_idx = net_idx;
281 key->app_idx = app_idx;
282 key->updated = false;
283 memcpy(keys->val, app_key, 16);
284
285 if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) {
286 BT_DBG("Storing AppKey persistently");
287 bt_mesh_store_app_key(key);
288 }
289
290 BT_INFO("Add AppKey 0x%04x, NetKeyIndex 0x%04x", app_idx, net_idx);
291 return 0;
292 }
293
294 BT_ERR("AppKey is full!");
295 return -ENOMEM;
296 }
297
bt_mesh_node_bind_app_key_to_model(uint16_t elem_addr,uint16_t mod_id,uint16_t cid,uint16_t app_idx)298 int bt_mesh_node_bind_app_key_to_model(uint16_t elem_addr, uint16_t mod_id,
299 uint16_t cid, uint16_t app_idx)
300 {
301 struct bt_mesh_model *model = NULL;
302 int i;
303
304 if (!bt_mesh_is_provisioned()) {
305 BT_ERR("Not provisioned, failed to bind AppKey");
306 return -EIO;
307 }
308
309 model = find_model(elem_addr, cid, mod_id);
310 if (model == NULL) {
311 BT_ERR("Bind, model(id 0x%04x, cid 0x%04x) not found", mod_id, cid);
312 return -ENODEV;
313 }
314
315 if (bt_mesh_app_key_find(app_idx) == NULL) {
316 BT_ERR("Bind, AppKey 0x%03x not exists", app_idx);
317 return -ENODEV;
318 }
319
320 for (i = 0; i < ARRAY_SIZE(model->keys); i++) {
321 if (model->keys[i] == app_idx) {
322 BT_WARN("Already bound to AppKey 0x%04x", app_idx);
323 return -EALREADY;
324 }
325 }
326
327 for (i = 0; i < ARRAY_SIZE(model->keys); i++) {
328 if (model->keys[i] == BLE_MESH_KEY_UNUSED) {
329 model->keys[i] = app_idx;
330 if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) {
331 bt_mesh_store_mod_bind(model);
332 }
333
334 BT_INFO("Model(id 0x%04x, cid 0x%04x) bound to AppKey 0x%04x", mod_id, cid, app_idx);
335 return 0;
336 }
337 }
338
339 BT_ERR("Model bound is full!");
340 return -ENOMEM;
341 }
342
343 #endif /* CONFIG_BLE_MESH_NODE */
344