Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tipc: add support for AEAD key setting via netlink

This commit adds two netlink commands to TIPC in order for user to be
able to set or remove AEAD keys:
- TIPC_NL_KEY_SET
- TIPC_NL_KEY_FLUSH

When the 'KEY_SET' is given along with the key data, the key will be
initiated and attached to TIPC crypto. On the other hand, the
'KEY_FLUSH' command will remove all existing keys if any.

Acked-by: Ying Xue <ying.xue@windreiver.com>
Acked-by: Jon Maloy <jon.maloy@ericsson.com>
Signed-off-by: Tuong Lien <tuong.t.lien@dektech.com.au>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Tuong Lien and committed by
David S. Miller
e1f32190 fc1b6d6d

+160 -1
+4
include/uapi/linux/tipc_netlink.h
··· 63 63 TIPC_NL_PEER_REMOVE, 64 64 TIPC_NL_BEARER_ADD, 65 65 TIPC_NL_UDP_GET_REMOTEIP, 66 + TIPC_NL_KEY_SET, 67 + TIPC_NL_KEY_FLUSH, 66 68 67 69 __TIPC_NL_CMD_MAX, 68 70 TIPC_NL_CMD_MAX = __TIPC_NL_CMD_MAX - 1 ··· 162 160 TIPC_NLA_NODE_UNSPEC, 163 161 TIPC_NLA_NODE_ADDR, /* u32 */ 164 162 TIPC_NLA_NODE_UP, /* flag */ 163 + TIPC_NLA_NODE_ID, /* data */ 164 + TIPC_NLA_NODE_KEY, /* data */ 165 165 166 166 __TIPC_NLA_NODE_MAX, 167 167 TIPC_NLA_NODE_MAX = __TIPC_NLA_NODE_MAX - 1
+17 -1
net/tipc/netlink.c
··· 102 102 const struct nla_policy tipc_nl_node_policy[TIPC_NLA_NODE_MAX + 1] = { 103 103 [TIPC_NLA_NODE_UNSPEC] = { .type = NLA_UNSPEC }, 104 104 [TIPC_NLA_NODE_ADDR] = { .type = NLA_U32 }, 105 - [TIPC_NLA_NODE_UP] = { .type = NLA_FLAG } 105 + [TIPC_NLA_NODE_UP] = { .type = NLA_FLAG }, 106 + [TIPC_NLA_NODE_ID] = { .type = NLA_BINARY, 107 + .len = TIPC_NODEID_LEN}, 108 + [TIPC_NLA_NODE_KEY] = { .type = NLA_BINARY, 109 + .len = TIPC_AEAD_KEY_SIZE_MAX}, 106 110 }; 107 111 108 112 /* Properties valid for media, bearer and link */ ··· 259 255 .validate = GENL_DONT_VALIDATE_STRICT | 260 256 GENL_DONT_VALIDATE_DUMP_STRICT, 261 257 .dumpit = tipc_udp_nl_dump_remoteip, 258 + }, 259 + #endif 260 + #ifdef CONFIG_TIPC_CRYPTO 261 + { 262 + .cmd = TIPC_NL_KEY_SET, 263 + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 264 + .doit = tipc_nl_node_set_key, 265 + }, 266 + { 267 + .cmd = TIPC_NL_KEY_FLUSH, 268 + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 269 + .doit = tipc_nl_node_flush_key, 262 270 }, 263 271 #endif 264 272 };
+135
net/tipc/node.c
··· 2760 2760 return skb->len; 2761 2761 } 2762 2762 2763 + #ifdef CONFIG_TIPC_CRYPTO 2764 + static int tipc_nl_retrieve_key(struct nlattr **attrs, 2765 + struct tipc_aead_key **key) 2766 + { 2767 + struct nlattr *attr = attrs[TIPC_NLA_NODE_KEY]; 2768 + 2769 + if (!attr) 2770 + return -ENODATA; 2771 + 2772 + *key = (struct tipc_aead_key *)nla_data(attr); 2773 + if (nla_len(attr) < tipc_aead_key_size(*key)) 2774 + return -EINVAL; 2775 + 2776 + return 0; 2777 + } 2778 + 2779 + static int tipc_nl_retrieve_nodeid(struct nlattr **attrs, u8 **node_id) 2780 + { 2781 + struct nlattr *attr = attrs[TIPC_NLA_NODE_ID]; 2782 + 2783 + if (!attr) 2784 + return -ENODATA; 2785 + 2786 + if (nla_len(attr) < TIPC_NODEID_LEN) 2787 + return -EINVAL; 2788 + 2789 + *node_id = (u8 *)nla_data(attr); 2790 + return 0; 2791 + } 2792 + 2793 + int __tipc_nl_node_set_key(struct sk_buff *skb, struct genl_info *info) 2794 + { 2795 + struct nlattr *attrs[TIPC_NLA_NODE_MAX + 1]; 2796 + struct net *net = sock_net(skb->sk); 2797 + struct tipc_net *tn = tipc_net(net); 2798 + struct tipc_node *n = NULL; 2799 + struct tipc_aead_key *ukey; 2800 + struct tipc_crypto *c; 2801 + u8 *id, *own_id; 2802 + int rc = 0; 2803 + 2804 + if (!info->attrs[TIPC_NLA_NODE]) 2805 + return -EINVAL; 2806 + 2807 + rc = nla_parse_nested(attrs, TIPC_NLA_NODE_MAX, 2808 + info->attrs[TIPC_NLA_NODE], 2809 + tipc_nl_node_policy, info->extack); 2810 + if (rc) 2811 + goto exit; 2812 + 2813 + own_id = tipc_own_id(net); 2814 + if (!own_id) { 2815 + rc = -EPERM; 2816 + goto exit; 2817 + } 2818 + 2819 + rc = tipc_nl_retrieve_key(attrs, &ukey); 2820 + if (rc) 2821 + goto exit; 2822 + 2823 + rc = tipc_aead_key_validate(ukey); 2824 + if (rc) 2825 + goto exit; 2826 + 2827 + rc = tipc_nl_retrieve_nodeid(attrs, &id); 2828 + switch (rc) { 2829 + case -ENODATA: 2830 + /* Cluster key mode */ 2831 + rc = tipc_crypto_key_init(tn->crypto_tx, ukey, CLUSTER_KEY); 2832 + break; 2833 + case 0: 2834 + /* Per-node key mode */ 2835 + if (!memcmp(id, own_id, NODE_ID_LEN)) { 2836 + c = tn->crypto_tx; 2837 + } else { 2838 + n = tipc_node_find_by_id(net, id) ?: 2839 + tipc_node_create(net, 0, id, 0xffffu, 0, true); 2840 + if (unlikely(!n)) { 2841 + rc = -ENOMEM; 2842 + break; 2843 + } 2844 + c = n->crypto_rx; 2845 + } 2846 + 2847 + rc = tipc_crypto_key_init(c, ukey, PER_NODE_KEY); 2848 + if (n) 2849 + tipc_node_put(n); 2850 + break; 2851 + default: 2852 + break; 2853 + } 2854 + 2855 + exit: 2856 + return (rc < 0) ? rc : 0; 2857 + } 2858 + 2859 + int tipc_nl_node_set_key(struct sk_buff *skb, struct genl_info *info) 2860 + { 2861 + int err; 2862 + 2863 + rtnl_lock(); 2864 + err = __tipc_nl_node_set_key(skb, info); 2865 + rtnl_unlock(); 2866 + 2867 + return err; 2868 + } 2869 + 2870 + int __tipc_nl_node_flush_key(struct sk_buff *skb, struct genl_info *info) 2871 + { 2872 + struct net *net = sock_net(skb->sk); 2873 + struct tipc_net *tn = tipc_net(net); 2874 + struct tipc_node *n; 2875 + 2876 + tipc_crypto_key_flush(tn->crypto_tx); 2877 + rcu_read_lock(); 2878 + list_for_each_entry_rcu(n, &tn->node_list, list) 2879 + tipc_crypto_key_flush(n->crypto_rx); 2880 + rcu_read_unlock(); 2881 + 2882 + pr_info("All keys are flushed!\n"); 2883 + return 0; 2884 + } 2885 + 2886 + int tipc_nl_node_flush_key(struct sk_buff *skb, struct genl_info *info) 2887 + { 2888 + int err; 2889 + 2890 + rtnl_lock(); 2891 + err = __tipc_nl_node_flush_key(skb, info); 2892 + rtnl_unlock(); 2893 + 2894 + return err; 2895 + } 2896 + #endif 2897 + 2763 2898 /** 2764 2899 * tipc_node_dump - dump TIPC node data 2765 2900 * @n: tipc node to be dumped
+4
net/tipc/node.h
··· 119 119 int tipc_nl_node_dump_monitor(struct sk_buff *skb, struct netlink_callback *cb); 120 120 int tipc_nl_node_dump_monitor_peer(struct sk_buff *skb, 121 121 struct netlink_callback *cb); 122 + #ifdef CONFIG_TIPC_CRYPTO 123 + int tipc_nl_node_set_key(struct sk_buff *skb, struct genl_info *info); 124 + int tipc_nl_node_flush_key(struct sk_buff *skb, struct genl_info *info); 125 + #endif 122 126 void tipc_node_pre_cleanup_net(struct net *exit_net); 123 127 #endif