Mesh: Implement Network Destroy Request
[platform/core/connectivity/bluetooth-frwk.git] / bt-service / services / mesh / bt-service-mesh-keys.c
1 /*
2  * Bluetooth-frwk
3  *
4  * Copyright (c) 2020 Samsung Electronics Co., Ltd.
5  *
6  * @author: Anupam Roy <anupam.r@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *              http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21 #include <glib.h>
22 #include <dlog.h>
23 #include "bt-service-common.h"
24 #include "bluetooth-api.h"
25
26 #include "bluetooth-mesh-api.h"
27 #include "bt-internal-types.h"
28 #include "bt-service-util.h"
29 #include "bt-service-common.h"
30 #include "bt-service-event.h"
31 #include "bt-service-mesh-keys.h"
32 #include "bt-service-mesh-util.h"
33
34 #include "bt-internal-types.h"
35
36 #include <ell/ell.h>
37
38 /* An instance of a Mesh Network Key */
39 struct mesh_net_key_t  {
40         struct l_queue *app_keys;
41         uint16_t idx;
42         uint8_t phase;
43 };
44
45 /* An instance of a Mesh network */
46 struct mesh_network_t {
47         uint8_t net_uuid[16];
48         struct l_queue *net_keys;
49 };
50
51 static struct l_queue *networks;
52
53 static bool __mesh_net_uuid_match(const void *a, const void *b)
54 {
55         const struct mesh_network_t *net = a;
56         uint8_t* uuid = (uint8_t*)b;
57
58         if (memcmp(net->net_uuid, uuid, 16) == 0) {
59                 BT_INFO("Mesh: Found network with given Net UUID");
60                 return true;
61         }
62
63         return false;
64 }
65
66 static bool __mesh_app_key_present(const struct mesh_net_key_t  *key,
67                 uint16_t app_idx)
68 {
69         const struct l_queue_entry *l;
70
71         for (l = l_queue_get_entries(key->app_keys); l; l = l->next) {
72                 uint16_t idx = L_PTR_TO_UINT(l->data);
73
74                 if (idx == app_idx)
75                         return true;
76         }
77
78         return false;
79 }
80
81 static bool __mesh_net_idx_match(const void *a, const void *b)
82 {
83         const struct mesh_net_key_t  *key = a;
84         uint32_t idx = L_PTR_TO_UINT(b);
85
86         return key->idx == idx;
87 }
88
89 static bool __mesh_delete_bound_appkey(void *a, void *b)
90 {
91         uint32_t idx = L_PTR_TO_UINT(a);
92         _bt_mesh_cdb_t *cfg = (_bt_mesh_cdb_t*) b;
93
94         if (!_bt_mesh_conf_delete_application_key(cfg, idx))
95                 return false;
96
97         BT_INFO("Mesh: freed Appkey index [%u]", idx);
98         return true;
99 }
100 static bool __mesh_remove_netkey_entry(void *a, void *b)
101 {
102         struct mesh_net_key_t *key = (struct mesh_net_key_t*) a;
103
104         /* Only cleanup local keys from the network object:
105         DONT touch configuration file */
106         l_queue_destroy(key->app_keys, l_free);
107         l_free(key);
108         return true;
109 }
110
111 void _bt_mesh_keys_unload_net(uint8_t net_uuid[])
112 {
113         struct mesh_network_t *network;
114         int numkeys;
115         BT_INFO("Mesh:Keys: Unload network with all Keys");
116
117         network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
118         if (!network || !network->net_keys)
119                 return;
120
121         numkeys = l_queue_foreach_remove(network->net_keys,
122                         __mesh_remove_netkey_entry, network);
123         BT_INFO("Mesh:Nodes: Unloaded [%d] Keys from the network",
124                         numkeys);
125         l_queue_remove(networks, network);
126         l_free(network);
127         BT_INFO("Mesh: Current Number of networks [%d]",
128                         l_queue_length(networks));
129 }
130
131 void _bt_mesh_keys_load_net(uint8_t net_uuid[])
132 {
133         struct mesh_network_t *network;
134         BT_INFO("Mesh:Keys: Create new network");
135
136         if (l_queue_find(networks, __mesh_net_uuid_match, net_uuid))
137                 return;
138
139         if (!networks)
140                 networks = l_queue_new();
141
142         network = l_new(struct mesh_network_t, 1);
143         memcpy(network->net_uuid, net_uuid, 16);
144         network->net_keys =  l_queue_new();
145         l_queue_push_tail(networks, network);
146 }
147
148 void _bt_mesh_keys_add_net_key(uint8_t net_uuid[],
149                  uint16_t net_idx)
150 {
151         struct mesh_net_key_t  *key;
152         struct mesh_network_t *network;
153         BT_INFO("Mesh:Keys: Create new netkey for Network KeyIDx [%u]",
154                         net_idx);
155
156         network = l_queue_find(networks,
157                 __mesh_net_uuid_match, net_uuid);
158         if (!network)
159                 return;
160
161         if (l_queue_find(network->net_keys, __mesh_net_idx_match,
162                                 L_UINT_TO_PTR(net_idx)))
163                 return;
164
165         key = l_new(struct mesh_net_key_t , 1);
166         key->idx = net_idx;
167         key->phase = MESH_KEY_REFRESH_PHASE_NONE;
168
169         l_queue_push_tail(network->net_keys, key);
170 }
171
172 bool _bt_mesh_keys_is_netkey_present(uint8_t net_uuid[], uint16_t net_idx)
173 {
174         struct mesh_network_t *network;
175
176         network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
177         if (!network)
178                 return false;
179         if (!l_queue_find(network->net_keys, __mesh_net_idx_match,
180                 L_UINT_TO_PTR(net_idx)))
181                 return false;
182         return true;
183 }
184
185 bool _bt_mesh_keys_get_netkey_list(uint8_t net_uuid[], GArray **out)
186 {
187         struct mesh_network_t *network;
188         const struct l_queue_entry *l;
189
190         network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
191         if (!network)
192                 return false;
193
194         for (l = l_queue_get_entries(network->net_keys); l; l = l->next) {
195                 const struct mesh_net_key_t  *key = l->data;
196
197                 g_array_append_vals(*out, &key->idx, sizeof(uint16_t));
198         }
199
200         return true;
201 }
202
203 bool _bt_mesh_keys_get_appkey_list(uint8_t net_uuid[],
204                 uint16_t net_idx, GArray **out)
205 {
206         struct mesh_network_t *network;
207         struct mesh_net_key_t  *netkey;
208         const struct l_queue_entry *l;
209
210         network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
211         if (!network)
212                 return false;
213
214         netkey = l_queue_find(network->net_keys,
215                         __mesh_net_idx_match, L_UINT_TO_PTR(net_idx));
216         if (!netkey)
217                 return false;
218
219         for (l = l_queue_get_entries(netkey->app_keys); l; l = l->next) {
220                 uint16_t app_idx = L_PTR_TO_UINT(l->data);
221
222                 g_array_append_vals(*out, &app_idx, sizeof(uint16_t));
223         }
224
225         return true;
226 }
227
228 bool _bt_mesh_keys_get_new_netkey_index(uint8_t net_uuid[],
229                 uint16_t *net_idx)
230 {
231         struct mesh_net_key_t  *key;
232         struct mesh_network_t *network;
233
234         network = l_queue_find(networks,
235                         __mesh_net_uuid_match, net_uuid);
236         if (!network)
237                 return false;
238
239         if (l_queue_length(network->net_keys)) {
240                 key = l_queue_peek_tail(network->net_keys);
241                 if (!key)
242                         return false;
243                 *net_idx = key->idx + 1;
244         } else
245                 return false;
246
247         return true;
248 }
249
250 bool _bt_mesh_keys_get_new_appkey_index(uint8_t net_uuid[],
251                 uint16_t *app_idx)
252 {
253         const struct l_queue_entry *l, *l1;
254         struct mesh_network_t *network;
255         int maxkey = -1;
256         BT_INFO("Mesh: Find New appkey index");
257         network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
258         if (!network)
259                 return false;
260
261         BT_INFO("Mesh: Found network, number of netkeys present [%d]",
262                         l_queue_length(network->net_keys));
263
264         if (!network->net_keys)
265                 return false;
266
267         /* TODO: Save max appkey index in Network to avoid looping */
268         for (l = l_queue_get_entries(network->net_keys); l; l = l->next) {
269                 struct mesh_net_key_t  *key = l->data;
270
271                 BT_INFO("Mesh: Number of Appkeys in current netkey is [%d]",
272                         l_queue_length(key->app_keys));
273
274                 if (!key->app_keys)
275                         continue;
276
277                 for (l1 = l_queue_get_entries(key->app_keys); l1; l1 = l1->next) {
278                         uint16_t app_idx = L_PTR_TO_UINT(l1->data);
279                         BT_INFO("Mesh: Current AppKey Index [0x%2.2x]", app_idx);
280                         if (app_idx > maxkey)
281                                 maxkey = app_idx;
282                 }
283         }
284         *app_idx = maxkey + 1;
285
286         return true;
287 }
288
289 bool _bt_mesh_keys_get_net_key_phase(uint8_t net_uuid[],
290                 uint16_t net_idx, uint8_t *phase)
291 {
292         struct mesh_net_key_t  *key;
293         struct mesh_network_t *network;
294
295         network = l_queue_find(networks,
296                         __mesh_net_uuid_match, net_uuid);
297         if (!network)
298                 return false;
299
300         if (!phase || !network->net_keys)
301                 return false;
302
303         key = l_queue_find(network->net_keys, __mesh_net_idx_match,
304                         L_UINT_TO_PTR(net_idx));
305         if (!key)
306                 return false;
307
308         *phase = key->phase;
309         return true;
310 }
311
312 void _bt_mesh_keys_set_net_key_phase(_bt_mesh_cdb_t *cfg,
313                 uint16_t net_idx, uint8_t phase, bool save)
314 {
315         struct mesh_net_key_t *key;
316         struct mesh_network_t *network;
317
318         network = l_queue_find(networks, __mesh_net_uuid_match, cfg->uuid);
319         if (!network)
320                 return;
321
322         if (!network->net_keys)
323                 return;
324
325         key = l_queue_find(network->net_keys,
326                         __mesh_net_idx_match, L_UINT_TO_PTR(net_idx));
327         if (!key)
328                 return;
329
330         key->phase = phase;
331
332         if (save && !_bt_mesh_conf_set_phase_network_key(cfg,
333                         net_idx, phase))
334                 BT_INFO("Failed to save updated KR phase\n");
335 }
336
337 void _bt_mesh_keys_del_net_key(uint8_t net_uuid[],
338                 uint16_t idx, _bt_mesh_cdb_t *cfg)
339 {
340         struct mesh_net_key_t *key;
341         struct mesh_network_t *network;
342         BT_INFO("Mesh:Keys: Delete new netkey for Network KeyIDx [%u]",
343                         idx);
344
345         network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
346         if (!network)
347                 return;
348
349         if (!network->net_keys)
350                 return;
351
352         key = l_queue_remove_if(network->net_keys,
353                         __mesh_net_idx_match, L_UINT_TO_PTR(idx));
354         if (!key)
355                 return;
356
357         l_queue_foreach_remove(key->app_keys,
358                         __mesh_delete_bound_appkey, cfg);
359         l_free(key);
360         BT_INFO("Mesh: NetKey deleted");
361 }
362
363 void _bt_mesh_keys_add_app_key(uint8_t net_uuid[],
364                 uint16_t net_idx, uint16_t app_idx)
365 {
366         struct mesh_net_key_t  *key;
367         struct mesh_network_t *network;
368
369         BT_INFO("Mesh: Add Appkey in Netkey");
370         network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
371         if (!network)
372                 return;
373
374         if (!network->net_keys)
375                 return;
376
377         key = l_queue_find(network->net_keys, __mesh_net_idx_match,
378                         L_UINT_TO_PTR(net_idx));
379         if (!key)
380                 return;
381
382         if (!key->app_keys)
383                 key->app_keys = l_queue_new();
384
385         if (__mesh_app_key_present(key, app_idx))
386                 return;
387
388         l_queue_push_tail(key->app_keys, L_UINT_TO_PTR(app_idx));
389         BT_INFO("Mesh: Appkey with index [0x%2.2x] added to Netkey [0x%2.2x]",
390                 app_idx, key->idx);
391 }
392
393 void _bt_mesh_keys_del_app_key(uint8_t net_uuid[], uint16_t app_idx)
394 {
395         const struct l_queue_entry *l;
396         struct mesh_network_t *network;
397
398         network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
399         if (!network)
400                 return;
401
402         if (!network->net_keys)
403                 return;
404
405         for (l = l_queue_get_entries(network->net_keys); l; l = l->next) {
406                 struct mesh_net_key_t  *key = l->data;
407
408                 if (!key->app_keys)
409                         continue;
410                 BT_INFO("Mesh: Delete AppKey index [%u]", app_idx);
411                 if (l_queue_remove(key->app_keys, L_UINT_TO_PTR(app_idx)))
412                         return;
413         }
414 }
415
416 uint16_t _bt_mesh_keys_get_bound_key(uint8_t net_uuid[], uint16_t app_idx)
417 {
418         const struct l_queue_entry *l;
419         struct mesh_network_t *network;
420
421         network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
422         if (!network)
423                 return MESH_NET_IDX_INVALID;
424
425         if (!network->net_keys)
426                 return MESH_NET_IDX_INVALID;
427
428         for (l = l_queue_get_entries(network->net_keys); l; l = l->next) {
429                 struct mesh_net_key_t  *key = l->data;
430
431                 if (!key->app_keys)
432                         continue;
433
434                 if (__mesh_app_key_present(key, app_idx))
435                         return key->idx;
436         }
437
438         return MESH_NET_IDX_INVALID;
439 }
440
441 bool _bt_mesh_keys_subnet_exists(uint8_t net_uuid[], uint16_t idx)
442 {
443         struct mesh_network_t *network;
444
445         network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
446         if (!network)
447                 return false;
448
449         if (!l_queue_find(network->net_keys, __mesh_net_idx_match,
450                                 L_UINT_TO_PTR(idx)))
451                 return false;
452
453         return true;
454 }