Mesh: Handle Key management operations
[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         l_free(a);
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(_bt_mesh_cdb_t *cfg)
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, cfg->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: Unloadeded [%d] Keys from the network",
124                         numkeys);
125         l_free(network);
126 }
127
128 void _bt_mesh_keys_load_net(uint8_t net_uuid[])
129 {
130         struct mesh_network_t *network;
131         BT_INFO("Mesh:Keys: Create new network");
132
133         if (l_queue_find(networks, __mesh_net_uuid_match, net_uuid))
134                 return;
135
136         if (!networks)
137                 networks = l_queue_new();
138
139         network = l_new(struct mesh_network_t, 1);
140         memcpy(network->net_uuid, net_uuid, 16);
141         network->net_keys =  l_queue_new();
142         l_queue_push_tail(networks, network);
143 }
144
145 void _bt_mesh_keys_add_net_key(uint8_t net_uuid[],
146                  uint16_t net_idx)
147 {
148         struct mesh_net_key_t  *key;
149         struct mesh_network_t *network;
150         BT_INFO("Mesh:Keys: Create new netkey for Network KeyIDx [%u]",
151                         net_idx);
152
153         network = l_queue_find(networks,
154                 __mesh_net_uuid_match, net_uuid);
155         if (!network)
156                 return;
157
158         if (l_queue_find(network->net_keys, __mesh_net_idx_match,
159                                 L_UINT_TO_PTR(net_idx)))
160                 return;
161
162         key = l_new(struct mesh_net_key_t , 1);
163         key->idx = net_idx;
164         key->phase = MESH_KEY_REFRESH_PHASE_NONE;
165
166         l_queue_push_tail(network->net_keys, key);
167 }
168
169 bool _bt_mesh_keys_is_netkey_present(uint8_t net_uuid[], uint16_t net_idx)
170 {
171         struct mesh_network_t *network;
172
173         network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
174         if (!network)
175                 return false;
176         if (!l_queue_find(network->net_keys, __mesh_net_idx_match,
177                 L_UINT_TO_PTR(net_idx)))
178                 return false;
179         return true;
180 }
181
182 bool _bt_mesh_keys_get_netkey_list(uint8_t net_uuid[], GArray **out)
183 {
184         struct mesh_network_t *network;
185         const struct l_queue_entry *l;
186
187         network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
188         if (!network)
189                 return false;
190
191         for (l = l_queue_get_entries(network->net_keys); l; l = l->next) {
192                 const struct mesh_net_key_t  *key = l->data;
193
194                 g_array_append_vals(*out, &key->idx, sizeof(uint16_t));
195         }
196
197         return true;
198 }
199
200 bool _bt_mesh_keys_get_appkey_list(uint8_t net_uuid[],
201                 uint16_t net_idx, GArray **out)
202 {
203         struct mesh_network_t *network;
204         struct mesh_net_key_t  *netkey;
205         const struct l_queue_entry *l;
206
207         network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
208         if (!network)
209                 return false;
210
211         netkey = l_queue_find(network->net_keys,
212                         __mesh_net_idx_match, L_UINT_TO_PTR(net_idx));
213         if (!netkey)
214                 return false;
215
216         for (l = l_queue_get_entries(netkey->app_keys); l; l = l->next) {
217                 uint16_t app_idx = L_PTR_TO_UINT(l->data);
218
219                 g_array_append_vals(*out, &app_idx, sizeof(uint16_t));
220         }
221
222         return true;
223 }
224
225 bool _bt_mesh_keys_get_new_netkey_index(uint8_t net_uuid[],
226                 uint16_t *net_idx)
227 {
228         struct mesh_net_key_t  *key;
229         struct mesh_network_t *network;
230
231         network = l_queue_find(networks,
232                         __mesh_net_uuid_match, net_uuid);
233         if (!network)
234                 return false;
235
236         if (l_queue_length(network->net_keys)) {
237                 key = l_queue_peek_tail(network->net_keys);
238                 if (!key)
239                         return false;
240                 *net_idx = key->idx + 1;
241         } else
242                 return false;
243
244         return true;
245 }
246
247 bool _bt_mesh_keys_get_new_appkey_index(uint8_t net_uuid[],
248                 uint16_t *app_idx)
249 {
250         const struct l_queue_entry *l;
251         struct mesh_network_t *network;
252         int maxkey = -1;
253
254         network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
255         if (!network)
256                 return false;
257
258         if (!network->net_keys)
259                 return false;
260
261         for (l = l_queue_get_entries(network->net_keys); l; l = l->next) {
262                 struct mesh_net_key_t  *key = l->data;
263
264                 if (!key->app_keys)
265                         continue;
266
267                 for (l = l_queue_get_entries(key->app_keys); l; l = l->next) {
268                         uint16_t app_idx = L_PTR_TO_UINT(l->data);
269                         if (app_idx > maxkey)
270                                 maxkey = app_idx;
271                 }
272         }
273         *app_idx = maxkey + 1;
274
275         return true;
276 }
277
278 bool _bt_mesh_keys_get_net_key_phase(uint8_t net_uuid[],
279                 uint16_t net_idx, uint8_t *phase)
280 {
281         struct mesh_net_key_t  *key;
282         struct mesh_network_t *network;
283
284         network = l_queue_find(networks,
285                         __mesh_net_uuid_match, net_uuid);
286         if (!network)
287                 return false;
288
289         if (!phase || !network->net_keys)
290                 return false;
291
292         key = l_queue_find(network->net_keys, __mesh_net_idx_match,
293                         L_UINT_TO_PTR(net_idx));
294         if (!key)
295                 return false;
296
297         *phase = key->phase;
298         return true;
299 }
300
301 void _bt_mesh_keys_set_net_key_phase(_bt_mesh_cdb_t *cfg,
302                 uint16_t net_idx, uint8_t phase, bool save)
303 {
304         struct mesh_net_key_t *key;
305         struct mesh_network_t *network;
306
307         network = l_queue_find(networks, __mesh_net_uuid_match, cfg->uuid);
308         if (!network)
309                 return;
310
311         if (!network->net_keys)
312                 return;
313
314         key = l_queue_find(network->net_keys,
315                         __mesh_net_idx_match, L_UINT_TO_PTR(net_idx));
316         if (!key)
317                 return;
318
319         key->phase = phase;
320
321         if (save && !_bt_mesh_conf_set_phase_network_key(cfg,
322                         net_idx, phase))
323                 BT_INFO("Failed to save updated KR phase\n");
324 }
325
326 void _bt_mesh_keys_del_net_key(uint8_t net_uuid[],
327                 uint16_t idx, _bt_mesh_cdb_t *cfg)
328 {
329         struct mesh_net_key_t *key;
330         struct mesh_network_t *network;
331         BT_INFO("Mesh:Keys: Delete new netkey for Network KeyIDx [%u]",
332                         idx);
333
334         network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
335         if (!network)
336                 return;
337
338         if (!network->net_keys)
339                 return;
340
341         key = l_queue_remove_if(network->net_keys,
342                         __mesh_net_idx_match, L_UINT_TO_PTR(idx));
343         if (!key)
344                 return;
345
346         l_queue_foreach_remove(key->app_keys,
347                         __mesh_delete_bound_appkey, cfg);
348         l_free(key);
349 }
350
351 void _bt_mesh_keys_add_app_key(uint8_t net_uuid[],
352                 uint16_t net_idx, uint16_t app_idx)
353 {
354         struct mesh_net_key_t  *key;
355         struct mesh_network_t *network;
356
357         network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
358         if (!network)
359                 return;
360
361         if (!network->net_keys)
362                 return;
363
364         key = l_queue_find(network->net_keys, __mesh_net_idx_match,
365                         L_UINT_TO_PTR(net_idx));
366         if (!key)
367                 return;
368
369         if (!key->app_keys)
370                 key->app_keys = l_queue_new();
371
372         if (__mesh_app_key_present(key, app_idx))
373                 return;
374
375         l_queue_push_tail(key->app_keys, L_UINT_TO_PTR(app_idx));
376 }
377
378 void _bt_mesh_keys_del_app_key(uint8_t net_uuid[], uint16_t app_idx)
379 {
380         const struct l_queue_entry *l;
381         struct mesh_network_t *network;
382
383         network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
384         if (!network)
385                 return;
386
387         if (!network->net_keys)
388                 return;
389
390         for (l = l_queue_get_entries(network->net_keys); l; l = l->next) {
391                 struct mesh_net_key_t  *key = l->data;
392
393                 if (!key->app_keys)
394                         continue;
395
396                 if (l_queue_remove(key->app_keys, L_UINT_TO_PTR(app_idx)))
397                         return;
398         }
399 }
400
401 uint16_t _bt_mesh_keys_get_bound_key(uint8_t net_uuid[], uint16_t app_idx)
402 {
403         const struct l_queue_entry *l;
404         struct mesh_network_t *network;
405
406         network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
407         if (!network)
408                 return MESH_NET_IDX_INVALID;
409
410         if (!network->net_keys)
411                 return MESH_NET_IDX_INVALID;
412
413         for (l = l_queue_get_entries(network->net_keys); l; l = l->next) {
414                 struct mesh_net_key_t  *key = l->data;
415
416                 if (!key->app_keys)
417                         continue;
418
419                 if (__mesh_app_key_present(key, app_idx))
420                         return key->idx;
421         }
422
423         return MESH_NET_IDX_INVALID;
424 }
425
426 bool _bt_mesh_keys_subnet_exists(uint8_t net_uuid[], uint16_t idx)
427 {
428         struct mesh_network_t *network;
429
430         network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
431         if (!network)
432                 return false;
433
434         if (!l_queue_find(network->net_keys, __mesh_net_idx_match,
435                                 L_UINT_TO_PTR(idx)))
436                 return false;
437
438         return true;
439 }