--- /dev/null
+/*
+ * Bluetooth-frwk
+ *
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * @author: Anupam Roy <anupam.r@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef BT_SERVICE_MESH_KEYS_H_
+#define BT_SERVICE_MESH_KEYS_H_
+
+#include <glib.h>
+#include <sys/types.h>
+#include "bluetooth-api.h"
+#include "bluetooth-mesh-api.h"
+#include <json-c/json.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void _bt_mesh_keys_load_net(uint8_t net_uuid[]);
+void _bt_mesh_keys_add_net_key(uint8_t net_uuid[],
+ uint16_t net_idx);
+void _bt_mesh_keys_add_app_key(uint8_t net_uuid[],
+ uint16_t net_idx, uint16_t app_idx);
+void _bt_mesh_keys_del_app_key(uint8_t net_uuid[],
+ uint16_t app_idx);
+uint16_t _bt_mesh_keys_get_bound_key(uint8_t net_uuid[],
+ uint16_t app_idx);
+bool _bt_mesh_keys_subnet_exists(uint8_t net_uuid[],
+ uint16_t idx);
+void _bt_mesh_keys_print_keys(uint8_t net_uuid[]);
+bool _bt_mesh_keys_get_new_netkey_index(uint8_t net_uuid[],
+ uint16_t *net_idx);
+bool _bt_mesh_keys_get_new_appkey_index(uint8_t net_uuid[],
+ uint16_t *app_idx);
+bool _bt_mesh_keys_is_netkey_present(uint8_t net_uuid[],
+ uint16_t net_idx);
+bool _bt_mesh_keys_get_netkey_list(uint8_t net_uuid[],
+ GArray **out);
+bool _bt_mesh_keys_get_appkey_list(uint8_t net_uuid[],
+ uint16_t net_idx, GArray **out);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* BT_SERVICE_MESH_KEYS_H_ */
--- /dev/null
+/*
+ * Bluetooth-frwk
+ *
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * @author: Anupam Roy <anupam.r@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#include <glib.h>
+#include <dlog.h>
+#include "bt-service-common.h"
+#include "bluetooth-api.h"
+
+#include "bluetooth-mesh-api.h"
+#include "bt-internal-types.h"
+#include "bt-service-util.h"
+#include "bt-service-common.h"
+#include "bt-service-event.h"
+#include "bt-service-mesh-keys.h"
+#include "bt-service-mesh-util.h"
+
+#include "bt-internal-types.h"
+
+#include <ell/ell.h>
+
+/* An instance of a Mesh Network Key */
+struct mesh_net_key_t {
+ struct l_queue *app_keys;
+ uint16_t idx;
+ uint8_t phase;
+};
+
+/* An instance of a Mesh network */
+struct mesh_network_t {
+ uint8_t net_uuid[16];
+ struct l_queue *net_keys;
+};
+
+static struct l_queue *networks;
+
+static bool __mesh_net_uuid_match(const void *a, const void *b)
+{
+ const struct mesh_network_t *net = a;
+ uint8_t* uuid = (uint8_t*)b;
+
+ if (memcmp(net->net_uuid, uuid, 16) == 0) {
+ BT_INFO("Mesh: Found network with given Net UUID");
+ return true;
+ }
+
+ return false;
+}
+
+static bool __mesh_app_key_present(const struct mesh_net_key_t *key,
+ uint16_t app_idx)
+{
+ const struct l_queue_entry *l;
+
+ for (l = l_queue_get_entries(key->app_keys); l; l = l->next) {
+ uint16_t idx = L_PTR_TO_UINT(l->data);
+
+ if (idx == app_idx)
+ return true;
+ }
+
+ return false;
+}
+
+static bool __mesh_net_idx_match(const void *a, const void *b)
+{
+ const struct mesh_net_key_t *key = a;
+ uint32_t idx = L_PTR_TO_UINT(b);
+
+ return key->idx == idx;
+}
+
+void _bt_mesh_keys_load_net(uint8_t net_uuid[])
+{
+ struct mesh_network_t *network;
+ BT_INFO("Mesh:Keys: Create new network");
+
+ if (l_queue_find(networks, __mesh_net_uuid_match, net_uuid))
+ return;
+
+ if (!networks)
+ networks = l_queue_new();
+
+ network = l_new(struct mesh_network_t, 1);
+ memcpy(network->net_uuid, net_uuid, 16);
+ network->net_keys = l_queue_new();
+ l_queue_push_tail(networks, network);
+}
+
+void _bt_mesh_keys_add_net_key(uint8_t net_uuid[], uint16_t net_idx)
+{
+ struct mesh_net_key_t *key;
+ struct mesh_network_t *network;
+ BT_INFO("Mesh:Keys: Create new netkey for Network KeyIDx [%u]",
+ net_idx);
+
+ network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
+ if (!network)
+ return;
+
+ if (l_queue_find(network->net_keys, __mesh_net_idx_match,
+ L_UINT_TO_PTR(net_idx)))
+ return;
+
+ key = l_new(struct mesh_net_key_t , 1);
+ key->idx = net_idx;
+ key->phase = MESH_KEY_REFRESH_PHASE_NONE;
+
+ l_queue_push_tail(network->net_keys, key);
+}
+
+bool _bt_mesh_keys_is_netkey_present(uint8_t net_uuid[], uint16_t net_idx)
+{
+ struct mesh_network_t *network;
+
+ network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
+ if (!network)
+ return false;
+ if (!l_queue_find(network->net_keys, __mesh_net_idx_match,
+ L_UINT_TO_PTR(net_idx)))
+ return false;
+ return true;
+}
+
+bool _bt_mesh_keys_get_netkey_list(uint8_t net_uuid[], GArray **out)
+{
+ struct mesh_network_t *network;
+ const struct l_queue_entry *l;
+
+ network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
+ if (!network)
+ return false;
+
+ for (l = l_queue_get_entries(network->net_keys); l; l = l->next) {
+ const struct mesh_net_key_t *key = l->data;
+
+ g_array_append_vals(*out, &key->idx, sizeof(uint16_t));
+ }
+
+ return true;
+}
+
+bool _bt_mesh_keys_get_appkey_list(uint8_t net_uuid[],
+ uint16_t net_idx, GArray **out)
+{
+ struct mesh_network_t *network;
+ struct mesh_net_key_t *netkey;
+ const struct l_queue_entry *l;
+
+ network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
+ if (!network)
+ return false;
+
+ netkey = l_queue_find(network->net_keys,
+ __mesh_net_idx_match, L_UINT_TO_PTR(net_idx));
+ if (!netkey)
+ return false;
+
+ for (l = l_queue_get_entries(netkey->app_keys); l; l = l->next) {
+ uint16_t app_idx = L_PTR_TO_UINT(l->data);
+
+ g_array_append_vals(*out, &app_idx, sizeof(uint16_t));
+ }
+
+ return true;
+}
+
+bool _bt_mesh_keys_get_new_netkey_index(uint8_t net_uuid[],
+ uint16_t *net_idx)
+{
+ struct mesh_net_key_t *key;
+ struct mesh_network_t *network;
+
+ network = l_queue_find(networks,
+ __mesh_net_uuid_match, net_uuid);
+ if (!network)
+ return false;
+
+ if (l_queue_length(network->net_keys)) {
+ key = l_queue_peek_tail(network->net_keys);
+ if (!key)
+ return false;
+ *net_idx = key->idx + 1;
+ } else
+ return false;
+
+ return true;
+}
+
+bool _bt_mesh_keys_get_new_appkey_index(uint8_t net_uuid[],
+ uint16_t *app_idx)
+{
+ const struct l_queue_entry *l;
+ struct mesh_network_t *network;
+ int maxkey = -1;
+
+ network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
+ if (!network)
+ return false;
+
+ if (!network->net_keys)
+ return false;
+
+ for (l = l_queue_get_entries(network->net_keys); l; l = l->next) {
+ struct mesh_net_key_t *key = l->data;
+
+ if (!key->app_keys)
+ continue;
+
+ for (l = l_queue_get_entries(key->app_keys); l; l = l->next) {
+ uint16_t app_idx = L_PTR_TO_UINT(l->data);
+ if (app_idx > maxkey)
+ maxkey = app_idx;
+ }
+ }
+ *app_idx = maxkey + 1;
+
+ return true;
+}
+
+bool _bt_mesh_keys_get_net_key_phase(uint8_t net_uuid[],
+ uint16_t net_idx, uint8_t *phase)
+{
+ struct mesh_net_key_t *key;
+ struct mesh_network_t *network;
+
+ network = l_queue_find(networks,
+ __mesh_net_uuid_match, net_uuid);
+ if (!network)
+ return false;
+
+ if (!phase || !network->net_keys)
+ return false;
+
+ key = l_queue_find(network->net_keys, __mesh_net_idx_match,
+ L_UINT_TO_PTR(net_idx));
+ if (!key)
+ return false;
+
+ *phase = key->phase;
+ return true;
+}
+
+void _bt_mesh_keys_add_app_key(uint8_t net_uuid[],
+ uint16_t net_idx, uint16_t app_idx)
+{
+ struct mesh_net_key_t *key;
+ struct mesh_network_t *network;
+
+ network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
+ if (!network)
+ return;
+
+ if (!network->net_keys)
+ return;
+
+ key = l_queue_find(network->net_keys, __mesh_net_idx_match,
+ L_UINT_TO_PTR(net_idx));
+ if (!key)
+ return;
+
+ if (!key->app_keys)
+ key->app_keys = l_queue_new();
+
+ if (__mesh_app_key_present(key, app_idx))
+ return;
+
+ l_queue_push_tail(key->app_keys, L_UINT_TO_PTR(app_idx));
+}
+
+void _bt_mesh_keys_del_app_key(uint8_t net_uuid[], uint16_t app_idx)
+{
+ const struct l_queue_entry *l;
+ struct mesh_network_t *network;
+
+ network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
+ if (!network)
+ return;
+
+ if (!network->net_keys)
+ return;
+
+ for (l = l_queue_get_entries(network->net_keys); l; l = l->next) {
+ struct mesh_net_key_t *key = l->data;
+
+ if (!key->app_keys)
+ continue;
+
+ if (l_queue_remove(key->app_keys, L_UINT_TO_PTR(app_idx)))
+ return;
+ }
+}
+
+uint16_t _bt_mesh_keys_get_bound_key(uint8_t net_uuid[], uint16_t app_idx)
+{
+ const struct l_queue_entry *l;
+ struct mesh_network_t *network;
+
+ network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
+ if (!network)
+ return MESH_NET_IDX_INVALID;
+
+ if (!network->net_keys)
+ return MESH_NET_IDX_INVALID;
+
+ for (l = l_queue_get_entries(network->net_keys); l; l = l->next) {
+ struct mesh_net_key_t *key = l->data;
+
+ if (!key->app_keys)
+ continue;
+
+ if (__mesh_app_key_present(key, app_idx))
+ return key->idx;
+ }
+
+ return MESH_NET_IDX_INVALID;
+}
+
+bool _bt_mesh_keys_subnet_exists(uint8_t net_uuid[], uint16_t idx)
+{
+ struct mesh_network_t *network;
+
+ network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
+ if (!network)
+ return false;
+
+ if (!l_queue_find(network->net_keys, __mesh_net_idx_match,
+ L_UINT_TO_PTR(idx)))
+ return false;
+
+ return true;
+}