From 5fb368188599b2b0f9b28193a72df72526ab4894 Mon Sep 17 00:00:00 2001 From: Tuong Lien Date: Fri, 16 Oct 2020 23:02:00 +0700 Subject: [PATCH 1/2] tipc: add option to set master key for encryption In addition to the support of master key in kernel, we add the 'master' option to the 'tipc node set key' command for user to be able to specify a key as master key during the key setting. This is carried out by turning on the new netlink flag - 'TIPC_NLA_NODE_KEY_MASTER'. For example: $ tipc node set key "this_is_a_master_key" master The command's help menu is also updated to give a better description of all the available options. Acked-by: Jon Maloy Signed-off-by: Tuong Lien Signed-off-by: David Ahern --- tipc/node.c | 46 +++++++++++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/tipc/node.c b/tipc/node.c index ffdaeaea..1ff0baa4 100644 --- a/tipc/node.c +++ b/tipc/node.c @@ -160,19 +160,21 @@ static int cmd_node_set_nodeid(struct nlmsghdr *nlh, const struct cmd *cmd, static void cmd_node_set_key_help(struct cmdl *cmdl) { fprintf(stderr, - "Usage: %s node set key KEY [algname ALGNAME] [nodeid NODEID]\n\n" + "Usage: %s node set key KEY [algname ALGNAME] [PROPERTIES]\n\n" + "KEY\n" + " Symmetric KEY & SALT as a composite ASCII or hex string (0x...) in form:\n" + " [KEY: 16, 24 or 32 octets][SALT: 4 octets]\n\n" + "ALGNAME\n" + " Cipher algorithm [default: \"gcm(aes)\"]\n\n" "PROPERTIES\n" - " KEY - Symmetric KEY & SALT as a normal or hex string\n" - " that consists of two parts:\n" - " [KEY: 16, 24 or 32 octets][SALT: 4 octets]\n\n" - " algname ALGNAME - Default: \"gcm(aes)\"\n\n" - " nodeid NODEID - Own or peer node identity to which the key will\n" - " be attached. If not present, the key is a cluster\n" - " key!\n\n" + " master - Set KEY as a cluster master key\n" + " - Set KEY as a cluster key\n" + " nodeid NODEID - Set KEY as a per-node key for own or peer\n\n" "EXAMPLES\n" - " %s node set key this_is_a_key16_salt algname \"gcm(aes)\" nodeid node1\n" - " %s node set key 0x746869735F69735F615F6B657931365F73616C74 nodeid node2\n\n", - cmdl->argv[0], cmdl->argv[0], cmdl->argv[0]); + " %s node set key this_is_a_master_key master\n" + " %s node set key 0x746869735F69735F615F6B657931365F73616C74\n" + " %s node set key this_is_a_key16_salt algname \"gcm(aes)\" nodeid 1001002\n\n", + cmdl->argv[0], cmdl->argv[0], cmdl->argv[0], cmdl->argv[0]); } static int cmd_node_set_key(struct nlmsghdr *nlh, const struct cmd *cmd, @@ -187,24 +189,21 @@ static int cmd_node_set_key(struct nlmsghdr *nlh, const struct cmd *cmd, struct opt opts[] = { { "algname", OPT_KEYVAL, NULL }, { "nodeid", OPT_KEYVAL, NULL }, + { "master", OPT_KEY, NULL }, { NULL } }; struct nlattr *nest; - struct opt *opt_algname, *opt_nodeid; + struct opt *opt_algname, *opt_nodeid, *opt_master; char buf[MNL_SOCKET_BUFFER_SIZE]; uint8_t id[TIPC_NODEID_LEN] = {0,}; int keysize; char *str; - if (help_flag) { + if (help_flag || cmdl->optind >= cmdl->argc) { (cmd->help)(cmdl); return -EINVAL; } - if (cmdl->optind >= cmdl->argc) { - fprintf(stderr, "error, missing key\n"); - return -EINVAL; - } /* Get user key */ str = shift_cmdl(cmdl); @@ -230,17 +229,30 @@ static int cmd_node_set_key(struct nlmsghdr *nlh, const struct cmd *cmd, return -EINVAL; } + /* Get master key indication */ + opt_master = get_opt(opts, "master"); + + /* Sanity check if wrong option */ + if (opt_nodeid && opt_master) { + fprintf(stderr, "error, per-node key cannot be master\n"); + return -EINVAL; + } + /* Init & do the command */ nlh = msg_init(buf, TIPC_NL_KEY_SET); if (!nlh) { fprintf(stderr, "error, message initialisation failed\n"); return -1; } + nest = mnl_attr_nest_start(nlh, TIPC_NLA_NODE); keysize = tipc_aead_key_size(&input.key); mnl_attr_put(nlh, TIPC_NLA_NODE_KEY, keysize, &input.key); if (opt_nodeid) mnl_attr_put(nlh, TIPC_NLA_NODE_ID, TIPC_NODEID_LEN, id); + if (opt_master) + mnl_attr_put(nlh, TIPC_NLA_NODE_KEY_MASTER, 0, NULL); + mnl_attr_nest_end(nlh, nest); return msg_doit(nlh, NULL, NULL); } From 2bf1ba5a5cf4ceb125be8813b2134605a28206a8 Mon Sep 17 00:00:00 2001 From: Tuong Lien Date: Fri, 16 Oct 2020 23:02:01 +0700 Subject: [PATCH 2/2] tipc: add option to set rekeying for encryption As supported in kernel, the TIPC encryption rekeying can be tuned using the netlink attribute - 'TIPC_NLA_NODE_REKEYING'. Now we add the 'rekeying' option correspondingly to the 'tipc node set key' command so that user will be able to perform that tuning: tipc node set key rekeying REKEYING where the 'REKEYING' value can be: INTERVAL - Set rekeying interval (in minutes) [0: disable] now - Trigger one (first) rekeying immediately For example: $ tipc node set key rekeying 60 $ tipc node set key rekeying now The command's help menu is also updated with these descriptions for the new command option. Acked-by: Jon Maloy Signed-off-by: Tuong Lien Signed-off-by: David Ahern --- tipc/cmdl.c | 2 +- tipc/cmdl.h | 1 + tipc/node.c | 47 +++++++++++++++++++++++++++++++++++++---------- 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/tipc/cmdl.c b/tipc/cmdl.c index f2f259cc..981e268e 100644 --- a/tipc/cmdl.c +++ b/tipc/cmdl.c @@ -33,7 +33,7 @@ static const struct cmd *find_cmd(const struct cmd *cmds, char *str) return match; } -static struct opt *find_opt(struct opt *opts, char *str) +struct opt *find_opt(struct opt *opts, char *str) { struct opt *o; struct opt *match = NULL; diff --git a/tipc/cmdl.h b/tipc/cmdl.h index 03db3599..dcade362 100644 --- a/tipc/cmdl.h +++ b/tipc/cmdl.h @@ -46,6 +46,7 @@ struct opt { char *val; }; +struct opt *find_opt(struct opt *opts, char *str); struct opt *get_opt(struct opt *opts, char *key); bool has_opt(struct opt *opts, char *key); int parse_opts(struct opt *opts, struct cmdl *cmdl); diff --git a/tipc/node.c b/tipc/node.c index 1ff0baa4..05246013 100644 --- a/tipc/node.c +++ b/tipc/node.c @@ -160,7 +160,8 @@ static int cmd_node_set_nodeid(struct nlmsghdr *nlh, const struct cmd *cmd, static void cmd_node_set_key_help(struct cmdl *cmdl) { fprintf(stderr, - "Usage: %s node set key KEY [algname ALGNAME] [PROPERTIES]\n\n" + "Usage: %s node set key KEY [algname ALGNAME] [PROPERTIES]\n" + " %s node set key rekeying REKEYING\n\n" "KEY\n" " Symmetric KEY & SALT as a composite ASCII or hex string (0x...) in form:\n" " [KEY: 16, 24 or 32 octets][SALT: 4 octets]\n\n" @@ -170,11 +171,16 @@ static void cmd_node_set_key_help(struct cmdl *cmdl) " master - Set KEY as a cluster master key\n" " - Set KEY as a cluster key\n" " nodeid NODEID - Set KEY as a per-node key for own or peer\n\n" + "REKEYING\n" + " INTERVAL - Set rekeying interval (in minutes) [0: disable]\n" + " now - Trigger one (first) rekeying immediately\n\n" "EXAMPLES\n" " %s node set key this_is_a_master_key master\n" " %s node set key 0x746869735F69735F615F6B657931365F73616C74\n" - " %s node set key this_is_a_key16_salt algname \"gcm(aes)\" nodeid 1001002\n\n", - cmdl->argv[0], cmdl->argv[0], cmdl->argv[0], cmdl->argv[0]); + " %s node set key this_is_a_key16_salt algname \"gcm(aes)\" nodeid 1001002\n" + " %s node set key rekeying 600\n\n", + cmdl->argv[0], cmdl->argv[0], cmdl->argv[0], cmdl->argv[0], + cmdl->argv[0], cmdl->argv[0]); } static int cmd_node_set_key(struct nlmsghdr *nlh, const struct cmd *cmd, @@ -190,12 +196,15 @@ static int cmd_node_set_key(struct nlmsghdr *nlh, const struct cmd *cmd, { "algname", OPT_KEYVAL, NULL }, { "nodeid", OPT_KEYVAL, NULL }, { "master", OPT_KEY, NULL }, + { "rekeying", OPT_KEYVAL, NULL }, { NULL } }; struct nlattr *nest; - struct opt *opt_algname, *opt_nodeid, *opt_master; + struct opt *opt_algname, *opt_nodeid, *opt_master, *opt_rekeying; char buf[MNL_SOCKET_BUFFER_SIZE]; uint8_t id[TIPC_NODEID_LEN] = {0,}; + uint32_t rekeying = 0; + bool has_key = false; int keysize; char *str; @@ -204,17 +213,31 @@ static int cmd_node_set_key(struct nlmsghdr *nlh, const struct cmd *cmd, return -EINVAL; } + /* Check if command starts with opts i.e. "rekeying" opt without key */ + if (find_opt(opts, cmdl->argv[cmdl->optind])) + goto get_ops; /* Get user key */ + has_key = true; str = shift_cmdl(cmdl); if (str2key(str, &input.key)) { fprintf(stderr, "error, invalid key input\n"); return -EINVAL; } +get_ops: if (parse_opts(opts, cmdl) < 0) return -EINVAL; + /* Get rekeying time */ + opt_rekeying = get_opt(opts, "rekeying"); + if (opt_rekeying) { + if (!strcmp(opt_rekeying->val, "now")) + rekeying = TIPC_REKEYING_NOW; + else + rekeying = atoi(opt_rekeying->val); + } + /* Get algorithm name, default: "gcm(aes)" */ opt_algname = get_opt(opts, "algname"); if (!opt_algname) @@ -246,12 +269,16 @@ static int cmd_node_set_key(struct nlmsghdr *nlh, const struct cmd *cmd, } nest = mnl_attr_nest_start(nlh, TIPC_NLA_NODE); - keysize = tipc_aead_key_size(&input.key); - mnl_attr_put(nlh, TIPC_NLA_NODE_KEY, keysize, &input.key); - if (opt_nodeid) - mnl_attr_put(nlh, TIPC_NLA_NODE_ID, TIPC_NODEID_LEN, id); - if (opt_master) - mnl_attr_put(nlh, TIPC_NLA_NODE_KEY_MASTER, 0, NULL); + if (has_key) { + keysize = tipc_aead_key_size(&input.key); + mnl_attr_put(nlh, TIPC_NLA_NODE_KEY, keysize, &input.key); + if (opt_nodeid) + mnl_attr_put(nlh, TIPC_NLA_NODE_ID, TIPC_NODEID_LEN, id); + if (opt_master) + mnl_attr_put(nlh, TIPC_NLA_NODE_KEY_MASTER, 0, NULL); + } + if (opt_rekeying) + mnl_attr_put_u32(nlh, TIPC_NLA_NODE_REKEYING, rekeying); mnl_attr_nest_end(nlh, nest); return msg_doit(nlh, NULL, NULL);