0b54fb455bc08734b8a5c2e79349d6830dc408eb
[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 void _bt_mesh_keys_load_net(uint8_t net_uuid[])
90 {
91         struct mesh_network_t *network;
92         BT_INFO("Mesh:Keys: Create new network");
93
94         if (l_queue_find(networks, __mesh_net_uuid_match, net_uuid))
95                 return;
96
97         if (!networks)
98                 networks = l_queue_new();
99
100         network = l_new(struct mesh_network_t, 1);
101         memcpy(network->net_uuid, net_uuid, 16);
102         network->net_keys =  l_queue_new();
103         l_queue_push_tail(networks, network);
104 }
105
106 void _bt_mesh_keys_add_net_key(uint8_t net_uuid[], uint16_t net_idx)
107 {
108         struct mesh_net_key_t  *key;
109         struct mesh_network_t *network;
110         BT_INFO("Mesh:Keys: Create new netkey for Network KeyIDx [%u]",
111                         net_idx);
112
113         network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
114         if (!network)
115                 return;
116
117         if (l_queue_find(network->net_keys, __mesh_net_idx_match,
118                                 L_UINT_TO_PTR(net_idx)))
119                 return;
120
121         key = l_new(struct mesh_net_key_t , 1);
122         key->idx = net_idx;
123         key->phase = MESH_KEY_REFRESH_PHASE_NONE;
124
125         l_queue_push_tail(network->net_keys, key);
126 }
127
128 bool _bt_mesh_keys_is_netkey_present(uint8_t net_uuid[], uint16_t net_idx)
129 {
130         struct mesh_network_t *network;
131
132         network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
133         if (!network)
134                 return false;
135         if (!l_queue_find(network->net_keys, __mesh_net_idx_match,
136                 L_UINT_TO_PTR(net_idx)))
137                 return false;
138         return true;
139 }
140
141 bool _bt_mesh_keys_get_netkey_list(uint8_t net_uuid[], GArray **out)
142 {
143         struct mesh_network_t *network;
144         const struct l_queue_entry *l;
145
146         network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
147         if (!network)
148                 return false;
149
150         for (l = l_queue_get_entries(network->net_keys); l; l = l->next) {
151                 const struct mesh_net_key_t  *key = l->data;
152
153                 g_array_append_vals(*out, &key->idx, sizeof(uint16_t));
154         }
155
156         return true;
157 }
158
159 bool _bt_mesh_keys_get_appkey_list(uint8_t net_uuid[],
160                 uint16_t net_idx, GArray **out)
161 {
162         struct mesh_network_t *network;
163         struct mesh_net_key_t  *netkey;
164         const struct l_queue_entry *l;
165
166         network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
167         if (!network)
168                 return false;
169
170         netkey = l_queue_find(network->net_keys,
171                         __mesh_net_idx_match, L_UINT_TO_PTR(net_idx));
172         if (!netkey)
173                 return false;
174
175         for (l = l_queue_get_entries(netkey->app_keys); l; l = l->next) {
176                 uint16_t app_idx = L_PTR_TO_UINT(l->data);
177
178                 g_array_append_vals(*out, &app_idx, sizeof(uint16_t));
179         }
180
181         return true;
182 }
183
184 bool _bt_mesh_keys_get_new_netkey_index(uint8_t net_uuid[],
185                 uint16_t *net_idx)
186 {
187         struct mesh_net_key_t  *key;
188         struct mesh_network_t *network;
189
190         network = l_queue_find(networks,
191                         __mesh_net_uuid_match, net_uuid);
192         if (!network)
193                 return false;
194
195         if (l_queue_length(network->net_keys)) {
196                 key = l_queue_peek_tail(network->net_keys);
197                 if (!key)
198                         return false;
199                 *net_idx = key->idx + 1;
200         } else
201                 return false;
202
203         return true;
204 }
205
206 bool _bt_mesh_keys_get_new_appkey_index(uint8_t net_uuid[],
207                 uint16_t *app_idx)
208 {
209         const struct l_queue_entry *l;
210         struct mesh_network_t *network;
211         int maxkey = -1;
212
213         network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
214         if (!network)
215                 return false;
216
217         if (!network->net_keys)
218                 return false;
219
220         for (l = l_queue_get_entries(network->net_keys); l; l = l->next) {
221                 struct mesh_net_key_t  *key = l->data;
222
223                 if (!key->app_keys)
224                         continue;
225
226                 for (l = l_queue_get_entries(key->app_keys); l; l = l->next) {
227                         uint16_t app_idx = L_PTR_TO_UINT(l->data);
228                         if (app_idx > maxkey)
229                                 maxkey = app_idx;
230                 }
231         }
232         *app_idx = maxkey + 1;
233
234         return true;
235 }
236
237 bool _bt_mesh_keys_get_net_key_phase(uint8_t net_uuid[],
238                 uint16_t net_idx, uint8_t *phase)
239 {
240         struct mesh_net_key_t  *key;
241         struct mesh_network_t *network;
242
243         network = l_queue_find(networks,
244                         __mesh_net_uuid_match, net_uuid);
245         if (!network)
246                 return false;
247
248         if (!phase || !network->net_keys)
249                 return false;
250
251         key = l_queue_find(network->net_keys, __mesh_net_idx_match,
252                         L_UINT_TO_PTR(net_idx));
253         if (!key)
254                 return false;
255
256         *phase = key->phase;
257         return true;
258 }
259
260 void _bt_mesh_keys_add_app_key(uint8_t net_uuid[],
261                 uint16_t net_idx, uint16_t app_idx)
262 {
263         struct mesh_net_key_t  *key;
264         struct mesh_network_t *network;
265
266         network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
267         if (!network)
268                 return;
269
270         if (!network->net_keys)
271                 return;
272
273         key = l_queue_find(network->net_keys, __mesh_net_idx_match,
274                         L_UINT_TO_PTR(net_idx));
275         if (!key)
276                 return;
277
278         if (!key->app_keys)
279                 key->app_keys = l_queue_new();
280
281         if (__mesh_app_key_present(key, app_idx))
282                 return;
283
284         l_queue_push_tail(key->app_keys, L_UINT_TO_PTR(app_idx));
285 }
286
287 void _bt_mesh_keys_del_app_key(uint8_t net_uuid[], uint16_t app_idx)
288 {
289         const struct l_queue_entry *l;
290         struct mesh_network_t *network;
291
292         network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
293         if (!network)
294                 return;
295
296         if (!network->net_keys)
297                 return;
298
299         for (l = l_queue_get_entries(network->net_keys); l; l = l->next) {
300                 struct mesh_net_key_t  *key = l->data;
301
302                 if (!key->app_keys)
303                         continue;
304
305                 if (l_queue_remove(key->app_keys, L_UINT_TO_PTR(app_idx)))
306                         return;
307         }
308 }
309
310 uint16_t _bt_mesh_keys_get_bound_key(uint8_t net_uuid[], uint16_t app_idx)
311 {
312         const struct l_queue_entry *l;
313         struct mesh_network_t *network;
314
315         network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
316         if (!network)
317                 return MESH_NET_IDX_INVALID;
318
319         if (!network->net_keys)
320                 return MESH_NET_IDX_INVALID;
321
322         for (l = l_queue_get_entries(network->net_keys); l; l = l->next) {
323                 struct mesh_net_key_t  *key = l->data;
324
325                 if (!key->app_keys)
326                         continue;
327
328                 if (__mesh_app_key_present(key, app_idx))
329                         return key->idx;
330         }
331
332         return MESH_NET_IDX_INVALID;
333 }
334
335 bool _bt_mesh_keys_subnet_exists(uint8_t net_uuid[], uint16_t idx)
336 {
337         struct mesh_network_t *network;
338
339         network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
340         if (!network)
341                 return false;
342
343         if (!l_queue_find(network->net_keys, __mesh_net_idx_match,
344                                 L_UINT_TO_PTR(idx)))
345                 return false;
346
347         return true;
348 }