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