Commit daef1ee3 authored by Tuong Lien's avatar Tuong Lien Committed by David S. Miller

tipc: introduce encryption master key

In addition to the supported cluster & per-node encryption keys for the
en/decryption of TIPC messages, we now introduce one option for user to
set a cluster key as 'master key', which is simply a symmetric key like
the former but has a longer life cycle. It has two purposes:

- Authentication of new member nodes in the cluster. New nodes, having
  no knowledge of current session keys in the cluster will still be
  able to join the cluster as long as they know the master key. This is
  because all neighbor discovery (LINK_CONFIG) messages must be
  encrypted with this key.

- Encryption of session encryption keys during automatic exchange and
  update of those.This is a feature we will introduce in a later commit
  in this series.

We insert the new key into the currently unused slot 0 in the key array
and start using it immediately once the user has set it.
After joining, a node only knowing the master key should be fully
communicable to existing nodes in the cluster, although those nodes may
have their own session keys activated (i.e. not the master one). To
support this, we define a 'grace period', starting from the time a node
itself reports having no RX keys, so the existing nodes will use the
master key for encryption instead. The grace period can be extended but
will automatically stop after e.g. 5 seconds without a new report. This
is also the basis for later key exchanging feature as the new node will
be impossible to decrypt anything without the support from master key.

For user to set a master key, we define a new netlink flag -
'TIPC_NLA_NODE_KEY_MASTER', so it can be added to the current 'set key'
netlink command to specify the setting key to be a master key.

Above all, the traditional cluster/per-node key mechanism is guaranteed
to work when user comes not to use this master key option. This is also
compatible to legacy nodes without the feature supported.

Even this master key can be updated without any interruption of cluster
connectivity but is so is needed, this has to be coordinated and set by
the user.
Acked-by: default avatarJon Maloy <jmaloy@redhat.com>
Signed-off-by: default avatarTuong Lien <tuong.t.lien@dektech.com.au>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f779bf79
...@@ -165,6 +165,7 @@ enum { ...@@ -165,6 +165,7 @@ enum {
TIPC_NLA_NODE_UP, /* flag */ TIPC_NLA_NODE_UP, /* flag */
TIPC_NLA_NODE_ID, /* data */ TIPC_NLA_NODE_ID, /* data */
TIPC_NLA_NODE_KEY, /* data */ TIPC_NLA_NODE_KEY, /* data */
TIPC_NLA_NODE_KEY_MASTER, /* flag */
__TIPC_NLA_NODE_MAX, __TIPC_NLA_NODE_MAX,
TIPC_NLA_NODE_MAX = __TIPC_NLA_NODE_MAX - 1 TIPC_NLA_NODE_MAX = __TIPC_NLA_NODE_MAX - 1
......
This diff is collapsed.
...@@ -74,7 +74,7 @@ extern int sysctl_tipc_max_tfms __read_mostly; ...@@ -74,7 +74,7 @@ extern int sysctl_tipc_max_tfms __read_mostly;
* 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
* 1 0 9 8 7 6 5 4|3 2 1 0 9 8 7 6|5 4 3 2 1 0 9 8|7 6 5 4 3 2 1 0 * 1 0 9 8 7 6 5 4|3 2 1 0 9 8 7 6|5 4 3 2 1 0 9 8|7 6 5 4 3 2 1 0
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* w0:|Ver=7| User |D|TX |RX |K| Rsvd | * w0:|Ver=7| User |D|TX |RX |K|M|N| Rsvd |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* w1:| Seqno | * w1:| Seqno |
* w2:| (8 octets) | * w2:| (8 octets) |
...@@ -101,6 +101,9 @@ extern int sysctl_tipc_max_tfms __read_mostly; ...@@ -101,6 +101,9 @@ extern int sysctl_tipc_max_tfms __read_mostly;
* RX : Currently RX active key corresponding to the destination * RX : Currently RX active key corresponding to the destination
* node's TX key (when the "D" bit is set) * node's TX key (when the "D" bit is set)
* K : Keep-alive bit (for RPS, LINK_PROTOCOL/STATE_MSG only) * K : Keep-alive bit (for RPS, LINK_PROTOCOL/STATE_MSG only)
* M : Bit indicates if sender has master key
* N : Bit indicates if sender has no RX keys corresponding to the
* receiver's TX (when the "D" bit is set)
* Rsvd : Reserved bit, field * Rsvd : Reserved bit, field
* Word1-2: * Word1-2:
* Seqno : The 64-bit sequence number of the encrypted message, also * Seqno : The 64-bit sequence number of the encrypted message, also
...@@ -117,7 +120,9 @@ struct tipc_ehdr { ...@@ -117,7 +120,9 @@ struct tipc_ehdr {
__u8 destined:1, __u8 destined:1,
user:4, user:4,
version:3; version:3;
__u8 reserved_1:3, __u8 reserved_1:1,
rx_nokey:1,
master_key:1,
keepalive:1, keepalive:1,
rx_key_active:2, rx_key_active:2,
tx_key:2; tx_key:2;
...@@ -128,7 +133,9 @@ struct tipc_ehdr { ...@@ -128,7 +133,9 @@ struct tipc_ehdr {
__u8 tx_key:2, __u8 tx_key:2,
rx_key_active:2, rx_key_active:2,
keepalive:1, keepalive:1,
reserved_1:3; master_key:1,
rx_nokey:1,
reserved_1:1;
#else #else
#error "Please fix <asm/byteorder.h>" #error "Please fix <asm/byteorder.h>"
#endif #endif
...@@ -158,7 +165,7 @@ int tipc_crypto_xmit(struct net *net, struct sk_buff **skb, ...@@ -158,7 +165,7 @@ int tipc_crypto_xmit(struct net *net, struct sk_buff **skb,
int tipc_crypto_rcv(struct net *net, struct tipc_crypto *rx, int tipc_crypto_rcv(struct net *net, struct tipc_crypto *rx,
struct sk_buff **skb, struct tipc_bearer *b); struct sk_buff **skb, struct tipc_bearer *b);
int tipc_crypto_key_init(struct tipc_crypto *c, struct tipc_aead_key *ukey, int tipc_crypto_key_init(struct tipc_crypto *c, struct tipc_aead_key *ukey,
u8 mode); u8 mode, bool master_key);
void tipc_crypto_key_flush(struct tipc_crypto *c); void tipc_crypto_key_flush(struct tipc_crypto *c);
int tipc_aead_key_validate(struct tipc_aead_key *ukey, struct genl_info *info); int tipc_aead_key_validate(struct tipc_aead_key *ukey, struct genl_info *info);
bool tipc_ehdr_validate(struct sk_buff *skb); bool tipc_ehdr_validate(struct sk_buff *skb);
......
...@@ -127,7 +127,9 @@ struct tipc_skb_cb { ...@@ -127,7 +127,9 @@ struct tipc_skb_cb {
#ifdef CONFIG_TIPC_CRYPTO #ifdef CONFIG_TIPC_CRYPTO
u8 encrypted:1; u8 encrypted:1;
u8 decrypted:1; u8 decrypted:1;
u8 probe:1; #define SKB_PROBING 1
#define SKB_GRACING 2
u8 xmit_type:2;
u8 tx_clone_deferred:1; u8 tx_clone_deferred:1;
#endif #endif
}; };
......
...@@ -108,6 +108,7 @@ const struct nla_policy tipc_nl_node_policy[TIPC_NLA_NODE_MAX + 1] = { ...@@ -108,6 +108,7 @@ const struct nla_policy tipc_nl_node_policy[TIPC_NLA_NODE_MAX + 1] = {
.len = TIPC_NODEID_LEN}, .len = TIPC_NODEID_LEN},
[TIPC_NLA_NODE_KEY] = { .type = NLA_BINARY, [TIPC_NLA_NODE_KEY] = { .type = NLA_BINARY,
.len = TIPC_AEAD_KEY_SIZE_MAX}, .len = TIPC_AEAD_KEY_SIZE_MAX},
[TIPC_NLA_NODE_KEY_MASTER] = { .type = NLA_FLAG },
}; };
/* Properties valid for media, bearer and link */ /* Properties valid for media, bearer and link */
......
...@@ -2875,6 +2875,7 @@ static int __tipc_nl_node_set_key(struct sk_buff *skb, struct genl_info *info) ...@@ -2875,6 +2875,7 @@ static int __tipc_nl_node_set_key(struct sk_buff *skb, struct genl_info *info)
struct tipc_crypto *tx = tipc_net(net)->crypto_tx, *c = tx; struct tipc_crypto *tx = tipc_net(net)->crypto_tx, *c = tx;
struct tipc_node *n = NULL; struct tipc_node *n = NULL;
struct tipc_aead_key *ukey; struct tipc_aead_key *ukey;
bool master_key = false;
u8 *id, *own_id, mode; u8 *id, *own_id, mode;
int rc = 0; int rc = 0;
...@@ -2905,6 +2906,7 @@ static int __tipc_nl_node_set_key(struct sk_buff *skb, struct genl_info *info) ...@@ -2905,6 +2906,7 @@ static int __tipc_nl_node_set_key(struct sk_buff *skb, struct genl_info *info)
switch (rc) { switch (rc) {
case -ENODATA: case -ENODATA:
mode = CLUSTER_KEY; mode = CLUSTER_KEY;
master_key = !!(attrs[TIPC_NLA_NODE_KEY_MASTER]);
break; break;
case 0: case 0:
mode = PER_NODE_KEY; mode = PER_NODE_KEY;
...@@ -2921,11 +2923,11 @@ static int __tipc_nl_node_set_key(struct sk_buff *skb, struct genl_info *info) ...@@ -2921,11 +2923,11 @@ static int __tipc_nl_node_set_key(struct sk_buff *skb, struct genl_info *info)
} }
/* Initiate the TX/RX key */ /* Initiate the TX/RX key */
rc = tipc_crypto_key_init(c, ukey, mode); rc = tipc_crypto_key_init(c, ukey, mode, master_key);
if (n) if (n)
tipc_node_put(n); tipc_node_put(n);
if (rc < 0) { if (unlikely(rc < 0)) {
GENL_SET_ERR_MSG(info, "unable to initiate or attach new key"); GENL_SET_ERR_MSG(info, "unable to initiate or attach new key");
return rc; return rc;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment