From patchwork Sun Mar 29 20:56:14 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Stotland, Inga" X-Patchwork-Id: 11464223 X-Patchwork-Delegate: brian.gix@gmail.com Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 345B817EA for ; Sun, 29 Mar 2020 20:56:19 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 1D39620774 for ; Sun, 29 Mar 2020 20:56:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728667AbgC2U4S (ORCPT ); Sun, 29 Mar 2020 16:56:18 -0400 Received: from mga04.intel.com ([192.55.52.120]:20803 "EHLO mga04.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727101AbgC2U4S (ORCPT ); Sun, 29 Mar 2020 16:56:18 -0400 IronPort-SDR: iwqgAhfL0E4A4pVInbZUtBr8ZJZxi0hJRy//Iq3/DAYvhIwCK78KT0VgeO9OFBJM9jN+yDeQdY MElYZL/ol8fA== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Mar 2020 13:56:16 -0700 IronPort-SDR: IP614L/0zDUrxy03oEf14y2K6FCdq2sQ4WF8hGCx1XATfs8wUmMNFiVhAM7w55QZR+XWUqcftm TelJsyI6siuA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.72,321,1580803200"; d="scan'208";a="294412308" Received: from ingas-nuc1.sea.intel.com ([10.252.139.119]) by FMSMGA003.fm.intel.com with ESMTP; 29 Mar 2020 13:56:16 -0700 From: Inga Stotland To: linux-bluetooth@vger.kernel.org Cc: brian.gix@intel.com, Inga Stotland Subject: [PATCH BlueZ 1/2] tools/mesh-cfgclient: Save subnet key refresh phase Date: Sun, 29 Mar 2020 13:56:14 -0700 Message-Id: <20200329205615.22090-1-inga.stotland@intel.com> X-Mailer: git-send-email 2.21.1 MIME-Version: 1.0 Sender: linux-bluetooth-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org This records Key Refresh phase of a subnet either as a consequence of successful execution of subnet-update or subnet-set-phase commands. --- tools/mesh-cfgclient.c | 16 ++++++++++- tools/mesh/keys.c | 24 ++++++++++++++-- tools/mesh/keys.h | 1 + tools/mesh/mesh-db.c | 64 +++++++++++++++++++++++++++++++++--------- tools/mesh/mesh-db.h | 1 + 5 files changed, 90 insertions(+), 16 deletions(-) diff --git a/tools/mesh-cfgclient.c b/tools/mesh-cfgclient.c index d1c673182..a1dbf3fa7 100644 --- a/tools/mesh-cfgclient.c +++ b/tools/mesh-cfgclient.c @@ -950,14 +950,25 @@ fail: static void subnet_set_phase_reply(struct l_dbus_proxy *proxy, struct l_dbus_message *msg, void *user_data) { + struct generic_request *req = user_data; + uint16_t net_idx; + uint8_t phase; + if (l_dbus_message_is_error(msg)) { const char *name; l_dbus_message_get_error(msg, &name, NULL); l_error("Failed to set subnet phase: %s", name); + return; } - /* TODO: Set key phase in configuration */ + net_idx = (uint16_t) req->arg1; + phase = (uint8_t) req->arg2; + + if (phase == KEY_REFRESH_PHASE_THREE) + phase = KEY_REFRESH_PHASE_NONE; + + keys_set_net_key_phase(net_idx, phase); } static void subnet_set_phase_setup(struct l_dbus_message *msg, void *user_data) @@ -1016,6 +1027,7 @@ static void mgr_key_reply(struct l_dbus_proxy *proxy, l_dbus_message_get_error(msg, &name, NULL); l_error("Method %s returned error: %s", method, name); + bt_shell_printf("Method %s returned error: %s\n", method, name); return; } @@ -1025,6 +1037,8 @@ static void mgr_key_reply(struct l_dbus_proxy *proxy, } else if (!strcmp("DeleteSubnet", method)) { keys_del_net_key(idx); mesh_db_net_key_del(idx); + } else if (!strcmp("UpdateSubnet", method)) { + keys_set_net_key_phase(idx, KEY_REFRESH_PHASE_ONE); } else if (!strcmp("DeleteAppKey", method)) { keys_del_app_key(idx); mesh_db_app_key_del(idx); diff --git a/tools/mesh/keys.c b/tools/mesh/keys.c index 77b32da63..e7b065beb 100644 --- a/tools/mesh/keys.c +++ b/tools/mesh/keys.c @@ -31,8 +31,9 @@ #include "tools/mesh/keys.h" struct net_key { - uint16_t idx; struct l_queue *app_keys; + uint16_t idx; + uint8_t phase; }; static struct l_queue *net_keys; @@ -78,6 +79,7 @@ void keys_add_net_key(uint16_t net_idx) key = l_new(struct net_key, 1); key->idx = net_idx; + key->phase = KEY_REFRESH_PHASE_NONE; l_queue_push_tail(net_keys, key); } @@ -97,6 +99,23 @@ void keys_del_net_key(uint16_t idx) l_free(key); } +void keys_set_net_key_phase(uint16_t net_idx, uint8_t phase) +{ + struct net_key *key; + + if (!net_keys) + return; + + key = l_queue_find(net_keys, net_idx_match, L_UINT_TO_PTR(net_idx)); + if (!key) + return; + + key->phase = phase; + + if (!mesh_db_net_key_phase_set(net_idx, phase)) + bt_shell_printf("Failed to save updated KR phase\n"); +} + void keys_add_app_key(uint16_t net_idx, uint16_t app_idx) { struct net_key *key; @@ -166,7 +185,8 @@ static void print_netkey(void *net_key, void *user_data) { struct net_key *key = net_key; - bt_shell_printf(COLOR_YELLOW "NetKey: 0x%3.3x\n" COLOR_OFF, key->idx); + bt_shell_printf(COLOR_YELLOW "NetKey: 0x%3.3x, phase: %u\n" COLOR_OFF, + key->idx, key->phase); if (!key->app_keys || l_queue_isempty(key->app_keys)) return; diff --git a/tools/mesh/keys.h b/tools/mesh/keys.h index 71c3bb390..e05e57997 100644 --- a/tools/mesh/keys.h +++ b/tools/mesh/keys.h @@ -20,6 +20,7 @@ void keys_add_net_key(uint16_t net_idx); void keys_del_net_key(uint16_t net_idx); +void keys_set_net_key_phase(uint16_t net_idx, uint8_t phase); void keys_add_app_key(uint16_t net_idx, uint16_t app_idx); void keys_del_app_key(uint16_t app_idx); uint16_t keys_get_bound_key(uint16_t app_idx); diff --git a/tools/mesh/mesh-db.c b/tools/mesh/mesh-db.c index e938ee733..05e96e554 100644 --- a/tools/mesh/mesh-db.c +++ b/tools/mesh/mesh-db.c @@ -114,6 +114,20 @@ static json_object *get_key_object(json_object *jarray, uint16_t idx) return NULL; } +static bool get_int(json_object *jobj, const char *keyword, int *value) +{ + json_object *jvalue; + + if (!json_object_object_get_ex(jobj, keyword, &jvalue)) + return false; + + *value = json_object_get_int(jvalue); + if (errno == EINVAL) + return false; + + return true; +} + static bool write_int(json_object *jobj, const char *keyword, int val) { json_object *jval; @@ -416,8 +430,7 @@ static bool add_node_key(json_object *jobj, const char *desc, uint16_t idx) json_object_object_add(jkey, "index", jval); json_object_array_add(jarray, jkey); - return mesh_config_save((struct mesh_config *) cfg, true, - NULL, NULL); + return mesh_config_save((struct mesh_config *) cfg, true, NULL, NULL); } bool mesh_db_node_net_key_add(uint16_t unicast, uint16_t idx) @@ -448,8 +461,7 @@ bool mesh_db_node_ttl_set(uint16_t unicast, uint8_t ttl) if (!write_int(jnode, "defaultTTL", ttl)) return false; - return mesh_config_save((struct mesh_config *) cfg, true, - NULL, NULL); + return mesh_config_save((struct mesh_config *) cfg, true, NULL, NULL); } static void jarray_key_del(json_object *jarray, int16_t idx) @@ -488,8 +500,7 @@ static bool delete_key(json_object *jobj, const char *desc, uint16_t idx) jarray_key_del(jarray, idx); - return mesh_config_save((struct mesh_config *) cfg, true, - NULL, NULL); + return mesh_config_save((struct mesh_config *) cfg, true, NULL, NULL); } bool mesh_db_node_net_key_del(uint16_t unicast, uint16_t net_idx) @@ -550,6 +561,7 @@ static bool load_keys(json_object *jobj) for (i = 0; i < key_cnt; ++i) { const char *str; + int phase; jentry = json_object_array_get_idx(jarray, i); @@ -562,6 +574,11 @@ static bool load_keys(json_object *jobj) return false; keys_add_net_key(net_idx); + + if (!get_int(jentry, "phase", &phase)) + return false; + + keys_set_net_key_phase(net_idx, (uint8_t) phase); } json_object_object_get_ex(jobj, "appKeys", &jarray); @@ -623,15 +640,13 @@ bool mesh_db_net_key_add(uint16_t net_idx) json_object_object_add(jkey, "index", jval); - jval = json_object_new_int(KEY_REFRESH_PHASE_NONE); - if (!jval) + if (!write_int(jkey, "phase", KEY_REFRESH_PHASE_NONE)) goto fail; - json_object_object_add(jkey, "phase", jval); json_object_array_add(jarray, jkey); - return mesh_config_save((struct mesh_config *) cfg, true, - NULL, NULL); + return mesh_config_save((struct mesh_config *) cfg, true, NULL, NULL); + fail: json_object_put(jkey); return false; @@ -645,6 +660,30 @@ bool mesh_db_net_key_del(uint16_t net_idx) return delete_key(cfg->jcfg, "netKeys", net_idx); } +bool mesh_db_net_key_phase_set(uint16_t net_idx, uint8_t phase) +{ + json_object *jval, *jarray, *jkey; + + if (!cfg || !cfg->jcfg) + return false; + + json_object_object_get_ex(cfg->jcfg, "netKeys", &jarray); + if (!jarray || json_object_get_type(jarray) != json_type_array) + return false; + + jkey = get_key_object(jarray, net_idx); + if (!jkey) + return false; + + jval = json_object_new_int(phase); + if (!jval) + return false; + + json_object_object_add(jkey, "phase", jval); + + return mesh_config_save((struct mesh_config *) cfg, true, NULL, NULL); +} + bool mesh_db_app_key_add(uint16_t net_idx, uint16_t app_idx) { if (!cfg || !cfg->jcfg) @@ -653,8 +692,7 @@ bool mesh_db_app_key_add(uint16_t net_idx, uint16_t app_idx) if (!add_app_key(cfg->jcfg, net_idx, app_idx)) return false; - return mesh_config_save((struct mesh_config *) cfg, true, - NULL, NULL); + return mesh_config_save((struct mesh_config *) cfg, true, NULL, NULL); } bool mesh_db_app_key_del(uint16_t app_idx) diff --git a/tools/mesh/mesh-db.h b/tools/mesh/mesh-db.h index 80dc4ed53..1f9e4e3d3 100644 --- a/tools/mesh/mesh-db.h +++ b/tools/mesh/mesh-db.h @@ -29,6 +29,7 @@ bool mesh_db_get_token(uint8_t token[8]); bool mesh_db_net_key_add(uint16_t idx); bool mesh_db_net_key_del(uint16_t idx); +bool mesh_db_net_key_phase_set(uint16_t net_idx, uint8_t phase); bool mesh_db_app_key_add(uint16_t net_idx, uint16_t app_idx); bool mesh_db_app_key_del(uint16_t app_idx); bool mesh_db_set_addr_range(uint16_t low, uint16_t high); From patchwork Sun Mar 29 20:56:15 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Stotland, Inga" X-Patchwork-Id: 11464221 X-Patchwork-Delegate: brian.gix@gmail.com Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id DE455159A for ; Sun, 29 Mar 2020 20:56:18 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id C677B2074A for ; Sun, 29 Mar 2020 20:56:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728619AbgC2U4S (ORCPT ); Sun, 29 Mar 2020 16:56:18 -0400 Received: from mga04.intel.com ([192.55.52.120]:20805 "EHLO mga04.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728475AbgC2U4R (ORCPT ); Sun, 29 Mar 2020 16:56:17 -0400 IronPort-SDR: gVL2dAVWRoK5rqqhlz55PyL2Nqi9ZNiU77ybFa+g5IW8c2TfpmhBCbwMP6woeETwoe+cO7or39 YIy9uO5GJvwQ== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Mar 2020 13:56:17 -0700 IronPort-SDR: 2yZ91HX/YcbQX8CHwLDatVZf/ZmGn8xWJOFTNJUn8uF8wunRcrYu7MEXcNFGA698+AK8UQjJ84 w5jPpFHDf8Hw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.72,321,1580803200"; d="scan'208";a="294412312" Received: from ingas-nuc1.sea.intel.com ([10.252.139.119]) by FMSMGA003.fm.intel.com with ESMTP; 29 Mar 2020 13:56:17 -0700 From: Inga Stotland To: linux-bluetooth@vger.kernel.org Cc: brian.gix@intel.com, Inga Stotland Subject: [PATCH BlueZ 2/2] tools/mesh-cfgclient: Add commands for Key Refresh Phase Date: Sun, 29 Mar 2020 13:56:15 -0700 Message-Id: <20200329205615.22090-2-inga.stotland@intel.com> X-Mailer: git-send-email 2.21.1 In-Reply-To: <20200329205615.22090-1-inga.stotland@intel.com> References: <20200329205615.22090-1-inga.stotland@intel.com> MIME-Version: 1.0 Sender: linux-bluetooth-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org This adds two new menu commands: "kr-phase-get" - sends Config Key Refresh Phase Get message "kr-phase-set" - sends Config Key Refresh Phase Set message --- tools/mesh/cfgcli.c | 84 +++++++++++++++++++++++++++++++++++++++++++++ tools/mesh/keys.c | 15 ++++++++ tools/mesh/keys.h | 1 + 3 files changed, 100 insertions(+) diff --git a/tools/mesh/cfgcli.c b/tools/mesh/cfgcli.c index 0c82d9f82..d9f1c9b72 100644 --- a/tools/mesh/cfgcli.c +++ b/tools/mesh/cfgcli.c @@ -516,6 +516,18 @@ static bool msg_recvd(uint16_t src, uint16_t idx, uint8_t *data, break; + case OP_CONFIG_KEY_REFRESH_PHASE_STATUS: + if (len != 4) + break; + + bt_shell_printf("Node %4.4x Key Refresh Phase status %s\n", src, + mesh_status_str(data[0])); + net_idx = get_le16(data + 1) & 0xfff; + + bt_shell_printf("\tNetKey %3.3x\n", net_idx); + bt_shell_printf("\tKR Phase %2.2x\n", data[3]); + break; + case OP_MODEL_APP_STATUS: if (len != 7 && len != 9) break; @@ -950,6 +962,74 @@ static void cmd_netkey_del(int argc, char *argv[]) return bt_shell_noninteractive_quit(EXIT_SUCCESS); } +static void cmd_kr_phase_get(int argc, char *argv[]) +{ + uint16_t n; + uint8_t msg[32]; + + if (IS_UNASSIGNED(target)) { + bt_shell_printf("Destination not set\n"); + return bt_shell_noninteractive_quit(EXIT_FAILURE); + } + + n = mesh_opcode_set(OP_CONFIG_KEY_REFRESH_PHASE_GET, msg); + + if (read_input_parameters(argc, argv) != 1) + return bt_shell_noninteractive_quit(EXIT_FAILURE); + + put_le16(parms[0], msg + n); + n += 2; + + if (!config_send(msg, n, OP_CONFIG_KEY_REFRESH_PHASE_GET)) + return bt_shell_noninteractive_quit(EXIT_FAILURE); + + return bt_shell_noninteractive_quit(EXIT_SUCCESS); +} + +static void cmd_kr_phase_set(int argc, char *argv[]) +{ + uint16_t n; + uint8_t msg[32]; + uint8_t phase; + + if (IS_UNASSIGNED(target)) { + bt_shell_printf("Destination not set\n"); + return bt_shell_noninteractive_quit(EXIT_FAILURE); + } + + n = mesh_opcode_set(OP_CONFIG_KEY_REFRESH_PHASE_SET, msg); + + if (read_input_parameters(argc, argv) != 2) + return bt_shell_noninteractive_quit(EXIT_FAILURE); + + if (parms[1] != KEY_REFRESH_PHASE_TWO && + parms[1] != KEY_REFRESH_PHASE_THREE) { + bt_shell_printf("Invalid KR transition value %u\n", parms[1]); + bt_shell_printf("Allowed values: 2 or 3\n"); + return bt_shell_noninteractive_quit(EXIT_FAILURE); + } + + if (!keys_get_net_key_phase((uint16_t) parms[0], &phase)) { + bt_shell_printf("Subnet KR state not found\n"); + return bt_shell_noninteractive_quit(EXIT_FAILURE); + } + + if (phase != (parms[1] % KEY_REFRESH_PHASE_THREE)) { + bt_shell_printf("Subnet's phase must be updated first!\n"); + return bt_shell_noninteractive_quit(EXIT_FAILURE); + } + + put_le16(parms[0], msg + n); + n += 2; + + msg[n++] = parms[1]; + + if (!config_send(msg, n, OP_CONFIG_KEY_REFRESH_PHASE_SET)) + return bt_shell_noninteractive_quit(EXIT_FAILURE); + + return bt_shell_noninteractive_quit(EXIT_SUCCESS); +} + static void cmd_appkey_del(int argc, char *argv[]) { uint16_t n; @@ -1788,6 +1868,10 @@ static const struct bt_shell_menu cfg_menu = { "Delete NetKey"}, {"netkey-get", NULL, cmd_netkey_get, "List NetKeys known to the node"}, + {"kr-phase-get", "", cmd_kr_phase_get, + "Get Key Refresh phase of a NetKey"}, + {"kr-phase-set", " ", cmd_kr_phase_set, + "Set Key Refresh phase transition of a NetKey"}, {"appkey-add", "", cmd_appkey_add, "Add AppKey"}, {"appkey-update", "", cmd_appkey_update, diff --git a/tools/mesh/keys.c b/tools/mesh/keys.c index e7b065beb..b7d36599a 100644 --- a/tools/mesh/keys.c +++ b/tools/mesh/keys.c @@ -116,6 +116,21 @@ void keys_set_net_key_phase(uint16_t net_idx, uint8_t phase) bt_shell_printf("Failed to save updated KR phase\n"); } +bool keys_get_net_key_phase(uint16_t net_idx, uint8_t *phase) +{ + struct net_key *key; + + if (!phase || !net_keys) + return false; + + key = l_queue_find(net_keys, net_idx_match, L_UINT_TO_PTR(net_idx)); + if (!key) + return false; + + *phase = key->phase; + return true; +} + void keys_add_app_key(uint16_t net_idx, uint16_t app_idx) { struct net_key *key; diff --git a/tools/mesh/keys.h b/tools/mesh/keys.h index e05e57997..3a90fa14b 100644 --- a/tools/mesh/keys.h +++ b/tools/mesh/keys.h @@ -21,6 +21,7 @@ void keys_add_net_key(uint16_t net_idx); void keys_del_net_key(uint16_t net_idx); void keys_set_net_key_phase(uint16_t net_idx, uint8_t phase); +bool keys_get_net_key_phase(uint16_t net_idx, uint8_t *phase); void keys_add_app_key(uint16_t net_idx, uint16_t app_idx); void keys_del_app_key(uint16_t app_idx); uint16_t keys_get_bound_key(uint16_t app_idx);