Merge branch 'tipc-encryption' into next

Tuong Lien  says:

====================

This series adds two new options in the 'iproute2/tipc' command, enabling users
to use the new TIPC encryption features, i.e. the master key and rekeying which
have been recently merged in kernel.

The help menu of the "tipc node set key" command is also updated accordingly:

 # tipc node set key --help
Usage: tipc node set key KEY [algname ALGNAME] [PROPERTIES]
       tipc node set key rekeying REKEYING

KEY
  Symmetric KEY & SALT as a composite ASCII or hex string (0x...) in form:
  [KEY: 16, 24 or 32 octets][SALT: 4 octets]

ALGNAME
  Cipher algorithm [default: "gcm(aes)"]

PROPERTIES
  master                - Set KEY as a cluster master key
  <empty>               - Set KEY as a cluster key
  nodeid NODEID         - Set KEY as a per-node key for own or peer

REKEYING
  INTERVAL              - Set rekeying interval (in minutes) [0: disable]
  now                   - Trigger one (first) rekeying immediately

EXAMPLES
  tipc node set key this_is_a_master_key master
  tipc node set key 0x746869735F69735F615F6B657931365F73616C74
  tipc node set key this_is_a_key16_salt algname "gcm(aes)" nodeid 1001002
  tipc node set key rekeying 600

====================

Signed-off-by: David Ahern <dsahern@gmail.com>
This commit is contained in:
David Ahern 2020-10-20 09:05:00 -06:00
commit 2b7a768408
3 changed files with 62 additions and 22 deletions

View File

@ -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;

View File

@ -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);

View File

@ -160,19 +160,27 @@ 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"
" %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"
"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"
" <empty> - 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_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"
" %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,
@ -187,35 +195,49 @@ 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 },
{ "rekeying", OPT_KEYVAL, NULL },
{ NULL }
};
struct nlattr *nest;
struct opt *opt_algname, *opt_nodeid;
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;
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;
}
/* 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)
@ -230,17 +252,34 @@ 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 (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);
}