From: Jakub Witowski <jakub.witowski@silvair.com>
To: linux-bluetooth@vger.kernel.org
Cc: Inga Stotland <inga.stotland@intel.com>, Brian Gix <brian.gix@intel.com>
Subject: [PATCH 3/3] mesh: Allow to import multiple network keys
Date: Fri, 14 Jun 2019 14:45:11 +0200 [thread overview]
Message-ID: <20190614124512.19062-4-jakub.witowski@silvair.com> (raw)
In-Reply-To: <20190614124512.19062-1-jakub.witowski@silvair.com>
This implements allows to import local node with
multiple network keys
---
mesh/keyring.h | 1 +
mesh/net.c | 2 +-
mesh/node.c | 264 ++++++++++++++++++++++++++-----------------------
3 files changed, 144 insertions(+), 123 deletions(-)
diff --git a/mesh/keyring.h b/mesh/keyring.h
index 167191013..8607f6497 100644
--- a/mesh/keyring.h
+++ b/mesh/keyring.h
@@ -22,6 +22,7 @@ struct keyring_net_key {
uint8_t phase;
uint8_t old_key[16];
uint8_t new_key[16];
+ bool key_refresh;
};
struct keyring_app_key {
diff --git a/mesh/net.c b/mesh/net.c
index 1cb29e1e8..a597b8794 100644
--- a/mesh/net.c
+++ b/mesh/net.c
@@ -56,7 +56,7 @@
#define DEFAULT_MIN_DELAY 0
#define DEFAULT_MAX_DELAY 25
-#define DEFAULT_TRANSMIT_COUNT 3
+#define DEFAULT_TRANSMIT_COUNT 1
#define DEFAULT_TRANSMIT_INTERVAL 100
#define BEACON_INTERVAL_MIN 10
diff --git a/mesh/node.c b/mesh/node.c
index fab5780cb..40def0fba 100644
--- a/mesh/node.c
+++ b/mesh/node.c
@@ -1457,77 +1457,92 @@ static bool parse_imported_device_key(json_object *jobj, uint8_t key_buf[16])
return true;
}
-static bool parse_imported_net_key(json_object *jobj, uint8_t key_buf[16],
- bool *kr, uint16_t *net_idx, uint8_t *ph)
+static struct l_queue *parse_imported_net_key(json_object *jobj)
{
json_object *jobject;
struct json_object_iterator iter, iend;
const char *jidx;
json_object *jtemp, *jvalue;
+ struct l_queue *keys;
+ struct keyring_net_key *net_keyring;
if (!json_object_object_get_ex(jobj, "netKeys", &jobject))
- return false;
+ return NULL;
if (json_object_get_type(jobject) != json_type_object)
- return false;
+ return NULL;
+
+ keys = l_queue_new();
iter = json_object_iter_begin(jobject);
iend = json_object_iter_end(jobject);
while (!json_object_iter_equal(&iter, &iend)) {
+
uint16_t idx;
char *str, *end;
- bool key_refresh = false;
- uint8_t phase;
- uint8_t key[16];
uint8_t new_key[16];
+ uint8_t old_key[16];
+
+ net_keyring = l_new(struct keyring_net_key, 1);
+ net_keyring->key_refresh = false;
jidx = json_object_iter_peek_name(&iter);
jtemp = json_object_iter_peek_value(&iter);
if (!*jidx)
- return false;
+ goto fail;
idx = (uint16_t)strtol(jidx, &end, 10);
if (*end || (idx > 4095))
- return false;
+ goto fail;
- *net_idx = idx;
+ net_keyring->net_idx = idx;
if (json_object_get_type(jtemp) != json_type_object)
- return false;
+ goto fail;
json_object_object_get_ex(jtemp, "oldKey", &jvalue);
if (jvalue) {
str = (char *)json_object_get_string(jvalue);
- if (!str2hex(str, strlen(str), key, 16))
- return false;
- key_refresh = true;
+ if (!str2hex(str, strlen(str), old_key, 16))
+ goto fail;
+
+ net_keyring->key_refresh = true;
}
if (!json_object_object_get_ex(jtemp, "key", &jvalue))
- return false;
+ goto fail;
str = (char *)json_object_get_string(jvalue);
- if (!str2hex(str, strlen(str), key_refresh ? new_key : key, 16))
- return false;
- memcpy(&key_buf[0], key_refresh ? new_key : key, 16);
+ if (!str2hex(str, strlen(str), net_keyring->key_refresh ?
+ new_key : old_key, 16))
+ goto fail;
+
+ memcpy(net_keyring->old_key, old_key, 16);
+
+ if (net_keyring->key_refresh)
+ memcpy(net_keyring->new_key, new_key, 16);
if (!json_object_object_get_ex(jtemp, "keyRefresh", &jvalue))
- return false;
+ goto fail;
if (!jvalue)
- phase = KEY_REFRESH_PHASE_NONE;
+ net_keyring->phase = KEY_REFRESH_PHASE_NONE;
else
- phase = (uint8_t)json_object_get_int(jvalue);
+ net_keyring->phase =
+ (uint8_t)json_object_get_int(jvalue);
- *ph = phase;
- *kr = key_refresh;
+ l_queue_push_tail(keys, net_keyring);
json_object_iter_next(&iter);
}
- return true;
+ return keys;
+fail:
+ l_queue_destroy(keys, l_free);
+ l_free(net_keyring);
+ return NULL;
}
static bool parse_imported_models(json_object *jmodels,
@@ -1548,7 +1563,7 @@ static bool parse_imported_models(json_object *jmodels,
mod = l_new(struct mesh_db_model, 1);
if (!mod)
- goto fail;
+ return false;
jidx = json_object_iter_peek_name(&iter);
@@ -1557,35 +1572,30 @@ static bool parse_imported_models(json_object *jmodels,
switch (strlen(jidx)) {
- case 4: {
+ case 4:
if (sscanf(jidx, "%04x", &id) != 1)
- goto fail;
+ return false;
id |= VENDOR_ID_MASK;
break;
- }
- case 8: {
+ case 8:
if (sscanf(jidx, "%08x", &id) != 1)
- goto fail;
+ return false;
mod->vendor = true;
break;
- }
default:
- goto fail;
+ return false;
}
mod->id = id;
l_queue_push_tail(ele->models, mod);
json_object_iter_next(&iter);
}
- return true;
-fail:
- l_queue_destroy(ele->models, l_free);
- return false;
+ return true;
}
static bool parse_imported_elements(json_object *jelements,
@@ -1638,54 +1648,54 @@ static bool parse_imported_elements(json_object *jelements,
ele = l_new(struct mesh_db_element, 1);
if (!ele)
- goto fail;
+ return false;
ele->index = idx;
ele->models = l_queue_new();
if (!ele->models)
- goto fail;
+ return false;
if (!json_object_object_get_ex(jtemp, "location", &jlocation))
- goto fail;
+ return false;
str = (char *)json_object_get_string(jlocation);
if (sscanf(str, "%04hx", &(ele->location)) != 1)
- goto fail;
+ return false;
if (json_object_object_get_ex(jtemp, "models", &jmodels)) {
if (json_object_get_type(jmodels) != json_type_object)
- goto fail;
+ return false;
if (!parse_imported_models(jmodels, ele))
- goto fail;
+ return false;
}
l_queue_push_tail(db_node->elements, ele);
json_object_iter_next(&iter);
}
+
return true;
+}
-fail:
- l_queue_destroy(db_node->elements, l_free);
- db_node->elements = NULL;
+static void put_net_keyrings(void *net_keys, void *_node)
+{
+ struct mesh_node *node = _node;
+ struct keyring_net_key *net_key = net_keys;
- if (ele->models) {
- l_queue_destroy(ele->models, l_free);
- ele->models = NULL;
- }
+ if (!node || !net_key)
+ return;
- return false;
+ if (!keyring_put_net_key(node, net_key->net_idx, net_key))
+ return;
}
static bool parse_imported_finalize(struct mesh_db_node *db_node,
struct mesh_node *node)
{
struct mesh_net *net;
- uint8_t mode, cnt;
- uint16_t interval;
if (!node_init_from_storage(node, db_node)) {
node_remove(node);
@@ -1693,42 +1703,48 @@ static bool parse_imported_finalize(struct mesh_db_node *db_node,
}
net = node_get_net(node);
- mesh_net_set_seq_num(net, node_get_sequence_number(node));
- mesh_net_set_default_ttl(net, node_default_ttl_get(node));
-
- mode = node_proxy_mode_get(node);
- if (mode == MESH_MODE_ENABLED || mode == MESH_MODE_DISABLED)
- mesh_net_set_proxy_mode(net, mode == MESH_MODE_ENABLED);
-
- mode = node_friend_mode_get(node);
- if (mode == MESH_MODE_ENABLED || mode == MESH_MODE_DISABLED)
- mesh_net_set_friend_mode(net, mode == MESH_MODE_ENABLED);
-
- mode = node_relay_mode_get(node, &cnt, &interval);
- if (mode == MESH_MODE_ENABLED || mode == MESH_MODE_DISABLED)
- mesh_net_set_relay_mode(net, mode == MESH_MODE_ENABLED, cnt,
- interval);
-
- mode = node_beacon_mode_get(node);
- if (mode == MESH_MODE_ENABLED || mode == MESH_MODE_DISABLED)
- mesh_net_set_beacon_mode(net, mode == MESH_MODE_ENABLED);
if (!IS_UNASSIGNED(db_node->unicast) &&
!mesh_net_register_unicast(net, db_node->unicast,
node_get_num_elements(node))) {
+
node_remove(node);
return false;
}
- if (node_uuid_get(node))
- mesh_net_id_uuid_set(net, node_uuid_get(node));
-
+ mesh_net_id_uuid_set(net, node_uuid_get(node));
return true;
}
-static bool add_local_node(struct mesh_node *node, uint16_t unicast, bool kr,
- bool ivu, uint32_t iv_idx, uint8_t dev_key[16],
- uint16_t net_key_idx, uint8_t net_key[16])
+static void add_keys(void *net_keys, void *_node)
+{
+ struct mesh_node *node = _node;
+ struct keyring_net_key *net_key = net_keys;
+
+ if (!node || !net_key) {
+ l_info("Add network key error");
+ return;
+ }
+
+ if (mesh_net_add_key(node->net, net_key->net_idx, net_key->old_key) !=
+ MESH_STATUS_SUCCESS)
+ return;
+
+ if (net_key->key_refresh) {
+ /* Duplicate net key, if the key refresh is on */
+ if (mesh_net_update_key(node->net, net_key->net_idx,
+ net_key->old_key) != MESH_STATUS_SUCCESS)
+ return;
+
+ if (!mesh_db_net_key_set_phase(node->jconfig, net_key->net_idx,
+ KEY_REFRESH_PHASE_TWO))
+ return;
+ }
+}
+
+static bool add_local_node(struct mesh_node *node, uint16_t unicast, bool ivu,
+ uint32_t iv_idx, uint8_t dev_key[16],
+ struct l_queue *net_keys)
{
if (!storage_set_iv_index(node->net, iv_idx, ivu))
return false;
@@ -1750,21 +1766,7 @@ static bool add_local_node(struct mesh_node *node, uint16_t unicast, bool kr,
node->primary = unicast;
mesh_net_register_unicast(node->net, unicast, node->num_ele);
- if (mesh_net_add_key(node->net, net_key_idx, net_key) !=
- MESH_STATUS_SUCCESS)
- return false;
-
- if (kr) {
- /* Duplicate net key, if the key refresh is on */
- if (mesh_net_update_key(node->net, net_key_idx, net_key) !=
- MESH_STATUS_SUCCESS)
- return false;
-
- if (!mesh_db_net_key_set_phase(node->jconfig, net_key_idx,
- KEY_REFRESH_PHASE_TWO))
- return false;
- }
-
+ l_queue_foreach(net_keys, add_keys, node);
storage_save_config(node, true, NULL, NULL);
/* Initialize configuration server model */
@@ -1779,6 +1781,8 @@ static void get_managed_objects_cb(struct l_dbus_message *msg, void *user_data)
struct managed_obj_request *req = user_data;
const char *path;
struct mesh_node *node = NULL;
+ struct l_queue *net_keys = NULL;
+ struct keyring_net_key *net_key = NULL;
void *agent = NULL;
bool have_app = false;
bool is_new;
@@ -1902,9 +1906,10 @@ static void get_managed_objects_cb(struct l_dbus_message *msg, void *user_data)
} else {
/* Callback for create node request */
- node_ready_func_t cb = req->cb;
- struct keyring_net_key net_key;
uint8_t dev_key[16];
+ node_ready_func_t cb = req->cb;
+
+ net_key = l_new(struct keyring_net_key, 1);
node->num_ele = num_ele;
set_defaults(node);
@@ -1915,21 +1920,22 @@ static void get_managed_objects_cb(struct l_dbus_message *msg, void *user_data)
/* Generate device and primary network keys */
l_getrandom(dev_key, sizeof(dev_key));
- l_getrandom(net_key.old_key, sizeof(net_key.old_key));
- net_key.net_idx = PRIMARY_NET_IDX;
- net_key.phase = KEY_REFRESH_PHASE_NONE;
-
- if (!add_local_node(node, DEFAULT_NEW_UNICAST, false, false,
- DEFAULT_IV_INDEX, dev_key,
- PRIMARY_NET_IDX,
- net_key.old_key))
+ l_getrandom(net_key->old_key, sizeof(net_key->old_key));
+ net_key->net_idx = PRIMARY_NET_IDX;
+ net_key->phase = KEY_REFRESH_PHASE_NONE;
+
+ net_keys = l_queue_new();
+ l_queue_push_tail(net_keys, net_key);
+
+ if (!add_local_node(node, DEFAULT_NEW_UNICAST, false,
+ DEFAULT_IV_INDEX, dev_key, net_keys))
goto fail;
if (!keyring_put_remote_dev_key(node, DEFAULT_NEW_UNICAST,
num_ele, dev_key))
goto fail;
- if (!keyring_put_net_key(node, PRIMARY_NET_IDX, &net_key))
+ if (!keyring_put_net_key(node, PRIMARY_NET_IDX, net_key))
goto fail;
cb(req->user_data, MESH_ERROR_NONE, node);
@@ -1937,6 +1943,12 @@ static void get_managed_objects_cb(struct l_dbus_message *msg, void *user_data)
return;
fail:
+ if (net_keys)
+ l_queue_destroy(net_keys, l_free);
+
+ if (net_key)
+ l_free(net_key);
+
if (agent)
mesh_agent_remove(agent);
@@ -2031,15 +2043,12 @@ void node_import(const char *sender, void *json_data, const uint8_t *uuid,
struct mesh_node *node;
struct mesh_net *net;
struct mesh_db_node db_node;
- struct keyring_net_key network_key;
+ struct l_queue *net_keys = NULL;
json_object *jnode = json_data;
+
uint16_t unicast;
uint8_t dev_key[16];
- uint8_t net_key[16];
- bool key_refresh;
- uint16_t net_idx;
- uint8_t phase;
uint32_t iv_idx;
bool iv_update;
@@ -2073,8 +2082,9 @@ void node_import(const char *sender, void *json_data, const uint8_t *uuid,
goto fail;
}
- if (!parse_imported_net_key(jnode, &net_key[0], &key_refresh,
- &net_idx, &phase)) {
+ net_keys = parse_imported_net_key(jnode);
+
+ if (!net_keys) {
l_error("Failed to parse imported network key");
goto fail;
}
@@ -2094,22 +2104,17 @@ void node_import(const char *sender, void *json_data, const uint8_t *uuid,
goto fail;
}
- if (!add_local_node(node, unicast, key_refresh, iv_update, iv_idx,
- dev_key, net_idx, &net_key[0])) {
+ if (!add_local_node(node, unicast, iv_update, iv_idx, dev_key,
+ net_keys)) {
l_error("Failed to add local node");
goto fail;
}
- memcpy(network_key.old_key, net_key, 16);
- network_key.net_idx = net_idx;
- network_key.phase = phase;
+ l_queue_foreach(net_keys, put_net_keyrings, node);
if (!keyring_put_remote_dev_key(node, unicast, node->num_ele, dev_key))
goto fail;
- if (!keyring_put_net_key(node, net_idx, &network_key))
- goto fail;
-
cb(user_data, MESH_ERROR_NONE, node);
return;
@@ -2117,6 +2122,9 @@ fail:
cb(user_data, MESH_ERROR_FAILED, NULL);
json_object_put(jnode);
+ if (net_keys)
+ l_queue_destroy(net_keys, l_free);
+
if (node)
node_remove(node);
}
@@ -2125,11 +2133,9 @@ void node_create(const char *app_path, const char *sender, const uint8_t *uuid,
node_ready_func_t cb, void *user_data)
{
struct managed_obj_request *req;
- struct mesh_node *node;
l_debug("");
- node = node_new(uuid);
req = l_new(struct managed_obj_request, 1);
req->data = (void *) uuid;
req->cb = cb;
@@ -2377,11 +2383,25 @@ const char *node_get_element_path(struct mesh_node *node, uint8_t ele_idx)
bool node_add_pending_local(struct mesh_node *node, void *prov_node_info)
{
struct mesh_prov_node_info *info = prov_node_info;
+ struct l_queue *net_keys = l_queue_new();
+ struct keyring_net_key *net_keyring = l_new(struct keyring_net_key, 1);
+
bool kr = !!(info->flags & PROV_FLAG_KR);
bool ivu = !!(info->flags & PROV_FLAG_IVU);
- return add_local_node(node, info->unicast, kr, ivu, info->iv_index,
- info->device_key, info->net_index, info->net_key);
+ net_keyring->net_idx = info->net_index;
+ net_keyring->key_refresh = kr;
+ memcpy(net_keyring->old_key, info->net_key, 16);
+
+ l_queue_push_tail(net_keys, net_keyring);
+
+ if (add_local_node(node, info->unicast, ivu, info->iv_index,
+ info->device_key, net_keys))
+ return true;
+
+ l_free(net_keyring);
+ l_queue_destroy(net_keys, l_free);
+ return false;
}
void node_jconfig_set(struct mesh_node *node, void *jconfig)
--
2.20.1
prev parent reply other threads:[~2019-06-14 12:45 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-06-14 12:45 [RFC 0/3] Import local node Jakub Witowski
2019-06-14 12:45 ` [PATCH 1/3] mesh: Added ImportLocalNode call Jakub Witowski
2019-06-14 12:45 ` [PATCH 2/3] mesh: Added functionality of import local node Jakub Witowski
2019-06-14 12:45 ` Jakub Witowski [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190614124512.19062-4-jakub.witowski@silvair.com \
--to=jakub.witowski@silvair.com \
--cc=brian.gix@intel.com \
--cc=inga.stotland@intel.com \
--cc=linux-bluetooth@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).