Acked-by: Jon Maloy <jon.ma...@ericsson.com>
> -----Original Message----- > From: Tuong Lien Tong <tuong.t.l...@dektech.com.au> > Sent: 19-Nov-19 22:37 > To: Jon Maloy <jon.ma...@ericsson.com>; 'Ying Xue' <ying....@windriver.com>; > tipc- > discuss...@lists.sourceforge.net; ma...@donjonn.com > Subject: RE: [iproute2] tipc: add new commands to set TIPC AEAD key > > Hi Jon/Ying, > > We still have this patch (i.e. for the 'tipc node set/flush key...' > commands), may I put your ACK on it before > sending to iproute2-next? > Many thanks! > > BR/Tuong > > -----Original Message----- > From: Jon Maloy <jon.ma...@ericsson.com> > Sent: Wednesday, October 16, 2019 9:51 PM > To: Ying Xue <ying....@windriver.com>; Tuong Tong Lien > <tuong.t.l...@dektech.com.au>; tipc- > discuss...@lists.sourceforge.net; ma...@donjonn.com > Subject: RE: [iproute2] tipc: add new commands to set TIPC AEAD key > > > > > -----Original Message----- > > From: Ying Xue <ying....@windriver.com> > > Sent: 16-Oct-19 08:30 > > To: Tuong Tong Lien <tuong.t.l...@dektech.com.au>; tipc- > > discuss...@lists.sourceforge.net; Jon Maloy <jon.ma...@ericsson.com>; > > ma...@donjonn.com > > Subject: Re: [iproute2] tipc: add new commands to set TIPC AEAD key > > > > Tt looks like we will use "tipc node" command to configure static key to > > TIPC > > module, right? > > The key is static in the sense that TIPC itself cannot change the key. But > the protocol ensures that keys can > be replaced without any traffic disturbances. > > > > > Do we plan to support dynamic key setting? If yes, what kinds of key > > exchange > > protocol would we use? For example, in IPSEC, it uses IKEv2 as its key > > exchange protocol. > > At the moment we assume there is an external user land framework where node > authentication is done > and where keys are generated and distributed (via TLS) to the nodes. > When we want to replace a key (probably at fix pre-defined intervals), the > framework has to generate new > keys and distribute/inject those to TIPC. > > > > > Will key be expired after a specific lifetime? For instance, in > > IPSEC/Raccoon2 or strongswan, they use rekey feature to provide this > > function to make security association safer. > > We are considering this, so that the external framework can be kept simpler > or even be eliminated. That > would be the next step, once this series is applied. > > Regards > ///jon > > > > > > On 10/14/19 7:36 PM, Tuong Lien wrote: > > > Two new commands are added as part of 'tipc node' command: > > > > > > $tipc node set key KEY [algname ALGNAME] [nodeid NODEID] $tipc node > > > flush key > > > > > > which enable user to set and remove AEAD keys in kernel TIPC. > > > > > > For the 'set key' command, the given 'nodeid' parameter decides the > > > mode to be applied to the key, particularly: > > > > > > - If NODEID is empty, the key is a 'cluster' key which will be used > > > for all message encryption/decryption from/to the node (i.e. both TX & > > > RX). > > > The same key needs to be set in the other nodes i.e. the 'cluster key' > > > mode. > > > > > > - If NODEID is own node, the key is used for message encryption (TX) > > > from the node. Whereas, if NODEID is a peer node, the key is for > > > message decryption (RX) from that peer node. > > > This is the 'per-node-key' mode that each nodes in the cluster has its > > > specific (TX) key. > > > > > > Signed-off-by: Tuong Lien <tuong.t.l...@dektech.com.au> > > > --- > > > include/uapi/linux/tipc.h | 21 ++++++ > > > include/uapi/linux/tipc_netlink.h | 4 ++ > > > tipc/misc.c | 38 +++++++++++ > > > tipc/misc.h | 1 + > > > tipc/node.c | 133 > > +++++++++++++++++++++++++++++++++++++- > > > 5 files changed, 195 insertions(+), 2 deletions(-) > > > > > > diff --git a/include/uapi/linux/tipc.h b/include/uapi/linux/tipc.h > > > index e16cb4e2..b118ce9b 100644 > > > --- a/include/uapi/linux/tipc.h > > > +++ b/include/uapi/linux/tipc.h > > > @@ -232,6 +232,27 @@ struct tipc_sioc_nodeid_req { > > > char node_id[TIPC_NODEID_LEN]; > > > }; > > > > > > +/* > > > + * TIPC Crypto, AEAD mode > > > + */ > > > +#define TIPC_AEAD_MAX_ALG_NAME (32) > > > +#define TIPC_AEAD_MIN_KEYLEN (16 + 4) > > > +#define TIPC_AEAD_MAX_KEYLEN (32 + 4) > > > + > > > +struct tipc_aead_key { > > > + char alg_name[TIPC_AEAD_MAX_ALG_NAME]; > > > + unsigned int keylen; /* in bytes */ > > > + char key[]; > > > +}; > > > + > > > +#define TIPC_AEAD_KEY_MAX_SIZE (sizeof(struct tipc_aead_key) + \ > > > + TIPC_AEAD_MAX_KEYLEN) > > > + > > > +static inline int tipc_aead_key_size(struct tipc_aead_key *key) { > > > + return sizeof(*key) + key->keylen; > > > +} > > > + > > > /* The macros and functions below are deprecated: > > > */ > > > > > > diff --git a/include/uapi/linux/tipc_netlink.h > > > b/include/uapi/linux/tipc_netlink.h > > > index efb958fd..6c2194ab 100644 > > > --- a/include/uapi/linux/tipc_netlink.h > > > +++ b/include/uapi/linux/tipc_netlink.h > > > @@ -63,6 +63,8 @@ enum { > > > TIPC_NL_PEER_REMOVE, > > > TIPC_NL_BEARER_ADD, > > > TIPC_NL_UDP_GET_REMOTEIP, > > > + TIPC_NL_KEY_SET, > > > + TIPC_NL_KEY_FLUSH, > > > > > > __TIPC_NL_CMD_MAX, > > > TIPC_NL_CMD_MAX = __TIPC_NL_CMD_MAX - 1 @@ -160,6 +162,8 > > @@ enum { > > > TIPC_NLA_NODE_UNSPEC, > > > TIPC_NLA_NODE_ADDR, /* u32 */ > > > TIPC_NLA_NODE_UP, /* flag */ > > > + TIPC_NLA_NODE_ID, /* data */ > > > + TIPC_NLA_NODE_KEY, /* data */ > > > > > > __TIPC_NLA_NODE_MAX, > > > TIPC_NLA_NODE_MAX = __TIPC_NLA_NODE_MAX - 1 diff --git > > a/tipc/misc.c > > > b/tipc/misc.c index e4b1cd0c..1daf3072 100644 > > > --- a/tipc/misc.c > > > +++ b/tipc/misc.c > > > @@ -98,6 +98,44 @@ int str2nodeid(char *str, uint8_t *id) > > > return 0; > > > } > > > > > > +int str2key(char *str, struct tipc_aead_key *key) { > > > + int len = strlen(str); > > > + int ishex = 0; > > > + int i; > > > + > > > + /* Check if the input is a hex string (i.e. 0x...) */ > > > + if (len > 2 && strncmp(str, "0x", 2) == 0) { > > > + ishex = is_hex(str + 2, len - 2 - 1); > > > + if (ishex) { > > > + len -= 2; > > > + str += 2; > > > + } > > > + } > > > + > > > + /* Obtain key: */ > > > + if (!ishex) { > > > + key->keylen = len; > > > + memcpy(key->key, str, len); > > > + } else { > > > + /* Convert hex string to key */ > > > + key->keylen = (len + 1) / 2; > > > + for (i = 0; i < key->keylen; i++) { > > > + if (i == 0 && len % 2 != 0) { > > > + if (sscanf(str, "%1hhx", &key->key[0]) != 1) > > > + return -1; > > > + str += 1; > > > + continue; > > > + } > > > + if (sscanf(str, "%2hhx", &key->key[i]) != 1) > > > + return -1; > > > + str += 2; > > > + } > > > + } > > > + > > > + return 0; > > > +} > > > + > > > void nodeid2str(uint8_t *id, char *str) { > > > int i; > > > diff --git a/tipc/misc.h b/tipc/misc.h index ff2f31f1..59309f68 100644 > > > --- a/tipc/misc.h > > > +++ b/tipc/misc.h > > > @@ -18,5 +18,6 @@ uint32_t str2addr(char *str); int str2nodeid(char > > > *str, uint8_t *id); void nodeid2str(uint8_t *id, char *str); void > > > hash2nodestr(uint32_t hash, char *str); > > > +int str2key(char *str, struct tipc_aead_key *key); > > > > > > #endif > > > diff --git a/tipc/node.c b/tipc/node.c index 2fec6753..fc81bd30 100644 > > > --- a/tipc/node.c > > > +++ b/tipc/node.c > > > @@ -157,6 +157,111 @@ static int cmd_node_set_nodeid(struct nlmsghdr > > *nlh, const struct cmd *cmd, > > > return msg_doit(nlh, NULL, NULL); > > > } > > > > > > +static void cmd_node_set_key_help(struct cmdl *cmdl) { > > > + fprintf(stderr, > > > + "Usage: %s node set key KEY [algname ALGNAME] [nodeid > > NODEID]\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" > > > + "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]); } > > > + > > > +static int cmd_node_set_key(struct nlmsghdr *nlh, const struct cmd *cmd, > > > + struct cmdl *cmdl, void *data) { > > > + struct { > > > + struct tipc_aead_key key; > > > + char mem[TIPC_AEAD_MAX_KEYLEN + 1]; > > > + } input = {}; > > > + struct opt opts[] = { > > > + { "algname", OPT_KEYVAL, NULL }, > > > + { "nodeid", OPT_KEYVAL, NULL }, > > > + { NULL } > > > + }; > > > + struct nlattr *nest; > > > + struct opt *opt_algname, *opt_nodeid; > > > + char buf[MNL_SOCKET_BUFFER_SIZE]; > > > + uint8_t id[TIPC_NODEID_LEN] = {0,}; > > > + int keysize; > > > + char *str; > > > + > > > + if (help_flag) { > > > + (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); > > > + if (str2key(str, &input.key)) { > > > + fprintf(stderr, "error, invalid key input\n"); > > > + return -EINVAL; > > > + } > > > + > > > + if (parse_opts(opts, cmdl) < 0) > > > + return -EINVAL; > > > + > > > + /* Get algorithm name, default: "gcm(aes)" */ > > > + opt_algname = get_opt(opts, "algname"); > > > + if (!opt_algname) > > > + strcpy(input.key.alg_name, "gcm(aes)"); > > > + else > > > + strcpy(input.key.alg_name, opt_algname->val); > > > + > > > + /* Get node identity */ > > > + opt_nodeid = get_opt(opts, "nodeid"); > > > + if (opt_nodeid && str2nodeid(opt_nodeid->val, id)) { > > > + fprintf(stderr, "error, invalid node identity\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); > > > + mnl_attr_nest_end(nlh, nest); > > > + return msg_doit(nlh, NULL, NULL); > > > +} > > > + > > > +static int cmd_node_flush_key(struct nlmsghdr *nlh, const struct cmd > > *cmd, > > > + struct cmdl *cmdl, void *data) { > > > + char buf[MNL_SOCKET_BUFFER_SIZE]; > > > + > > > + if (help_flag) { > > > + (cmd->help)(cmdl); > > > + return -EINVAL; > > > + } > > > + > > > + /* Init & do the command */ > > > + nlh = msg_init(buf, TIPC_NL_KEY_FLUSH); > > > + if (!nlh) { > > > + fprintf(stderr, "error, message initialisation failed\n"); > > > + return -1; > > > + } > > > + return msg_doit(nlh, NULL, NULL); > > > +} > > > + > > > static int nodeid_get_cb(const struct nlmsghdr *nlh, void *data) { > > > struct nlattr *info[TIPC_NLA_MAX + 1] = {}; @@ -270,13 +375,34 @@ > > > static int cmd_node_set_netid(struct nlmsghdr *nlh, const struct cmd *cmd, > > > return msg_doit(nlh, NULL, NULL); > > > } > > > > > > +static void cmd_node_flush_help(struct cmdl *cmdl) { > > > + fprintf(stderr, > > > + "Usage: %s node flush PROPERTY\n\n" > > > + "PROPERTIES\n" > > > + " key - Flush all symmetric-keys\n", > > > + cmdl->argv[0]); > > > +} > > > + > > > +static int cmd_node_flush(struct nlmsghdr *nlh, const struct cmd *cmd, > > > + struct cmdl *cmdl, void *data) > > > +{ > > > + const struct cmd cmds[] = { > > > + { "key", cmd_node_flush_key, NULL }, > > > + { NULL } > > > + }; > > > + > > > + return run_cmd(nlh, cmd, cmds, cmdl, NULL); } > > > + > > > static void cmd_node_set_help(struct cmdl *cmdl) { > > > fprintf(stderr, > > > "Usage: %s node set PROPERTY\n\n" > > > "PROPERTIES\n" > > > " identity NODEID - Set node identity\n" > > > - " clusterid CLUSTERID - Set local cluster id\n", > > > + " clusterid CLUSTERID - Set local cluster id\n" > > > + " key PROPERTY - Set symmetric-key\n", > > > cmdl->argv[0]); > > > } > > > > > > @@ -288,6 +414,7 @@ static int cmd_node_set(struct nlmsghdr *nlh, > > const struct cmd *cmd, > > > { "identity", cmd_node_set_nodeid, NULL }, > > > { "netid", cmd_node_set_netid, NULL }, > > > { "clusterid", cmd_node_set_netid, NULL }, > > > + { "key", cmd_node_set_key, cmd_node_set_key_help }, > > > { NULL } > > > }; > > > > > > @@ -325,7 +452,8 @@ void cmd_node_help(struct cmdl *cmdl) > > > "COMMANDS\n" > > > " list - List remote nodes\n" > > > " get - Get local node parameters\n" > > > - " set - Set local node parameters\n", > > > + " set - Set local node parameters\n" > > > + " flush - Flush local node parameters\n", > > > cmdl->argv[0]); > > > } > > > > > > @@ -336,6 +464,7 @@ int cmd_node(struct nlmsghdr *nlh, const struct > > cmd *cmd, struct cmdl *cmdl, > > > { "list", cmd_node_list, NULL }, > > > { "get", cmd_node_get, cmd_node_get_help }, > > > { "set", cmd_node_set, cmd_node_set_help }, > > > + { "flush", cmd_node_flush, cmd_node_flush_help}, > > > { NULL } > > > }; > > > > > > _______________________________________________ tipc-discussion mailing list tipc-discussion@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/tipc-discussion