Skip to content

Commit

Permalink
tipc: introduce TIPC encryption & authentication
Browse files Browse the repository at this point in the history
This commit offers an option to encrypt and authenticate all messaging,
including the neighbor discovery messages. The currently most advanced
algorithm supported is the AEAD AES-GCM (like IPSec or TLS). All
encryption/decryption is done at the bearer layer, just before leaving
or after entering TIPC.

Supported features:
- Encryption & authentication of all TIPC messages (header + data);
- Two symmetric-key modes: Cluster and Per-node;
- Automatic key switching;
- Key-expired revoking (sequence number wrapped);
- Lock-free encryption/decryption (RCU);
- Asynchronous crypto, Intel AES-NI supported;
- Multiple cipher transforms;
- Logs & statistics;

Two key modes:
- Cluster key mode: One single key is used for both TX & RX in all
nodes in the cluster.
- Per-node key mode: Each nodes in the cluster has one specific TX key.
For RX, a node requires its peers' TX key to be able to decrypt the
messages from those peers.

Key setting from user-space is performed via netlink by a user program
(e.g. the iproute2 'tipc' tool).

Internal key state machine:

                                 Attach    Align(RX)
                                     +-+   +-+
                                     | V   | V
        +---------+      Attach     +---------+
        |  IDLE   |---------------->| PENDING |(user = 0)
        +---------+                 +---------+
           A   A                   Switch|  A
           |   |                         |  |
           |   | Free(switch/revoked)    |  |
     (Free)|   +----------------------+  |  |Timeout
           |              (TX)        |  |  |(RX)
           |                          |  |  |
           |                          |  v  |
        +---------+      Switch     +---------+
        | PASSIVE |<----------------| ACTIVE  |
        +---------+       (RX)      +---------+
        (user = 1)                  (user >= 1)

The number of TFMs is 10 by default and can be changed via the procfs
'net/tipc/max_tfms'. At this moment, as for simplicity, this file is
also used to print the crypto statistics at runtime:

echo 0xfff1 > /proc/sys/net/tipc/max_tfms

The patch defines a new TIPC version (v7) for the encryption message (-
backward compatibility as well). The message is basically encapsulated
as follows:

   +----------------------------------------------------------+
   | TIPCv7 encryption  | Original TIPCv2    | Authentication |
   | header             | packet (encrypted) | Tag            |
   +----------------------------------------------------------+

The throughput is about ~40% for small messages (compared with non-
encryption) and ~9% for large messages. With the support from hardware
crypto i.e. the Intel AES-NI CPU instructions, the throughput increases
upto ~85% for small messages and ~55% for large messages.

By default, the new feature is inactive (i.e. no encryption) until user
sets a key for TIPC. There is however also a new option - "TIPC_CRYPTO"
in the kernel configuration to enable/disable the new code when needed.

MAINTAINERS | add two new files 'crypto.h' & 'crypto.c' in tipc

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>
  • Loading branch information
Tuong Lien authored and David S. Miller committed Nov 8, 2019
1 parent 134bdac commit fc1b6d6
Show file tree
Hide file tree
Showing 17 changed files with 2,385 additions and 46 deletions.
15 changes: 15 additions & 0 deletions net/tipc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,21 @@ config TIPC_MEDIA_UDP
Saying Y here will enable support for running TIPC over IP/UDP
bool
default y
config TIPC_CRYPTO
bool "TIPC encryption support"
depends on TIPC
select CRYPTO
select CRYPTO_AES
select CRYPTO_GCM
help
Saying Y here will enable support for TIPC encryption.
All TIPC messages will be encrypted/decrypted by using the currently most
advanced algorithm: AEAD AES-GCM (like IPSec or TLS) before leaving/
entering the TIPC stack.
Key setting from user-space is performed via netlink by a user program
(e.g. the iproute2 'tipc' tool).
bool
default y

config TIPC_DIAG
tristate "TIPC: socket monitoring interface"
Expand Down
1 change: 1 addition & 0 deletions net/tipc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ CFLAGS_trace.o += -I$(src)
tipc-$(CONFIG_TIPC_MEDIA_UDP) += udp_media.o
tipc-$(CONFIG_TIPC_MEDIA_IB) += ib_media.o
tipc-$(CONFIG_SYSCTL) += sysctl.o
tipc-$(CONFIG_TIPC_CRYPTO) += crypto.o


obj-$(CONFIG_TIPC_DIAG) += diag.o
Expand Down
2 changes: 1 addition & 1 deletion net/tipc/bcast.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ static struct tipc_bc_base *tipc_bc_base(struct net *net)
*/
int tipc_bcast_get_mtu(struct net *net)
{
return tipc_link_mtu(tipc_bc_sndlink(net)) - INT_H_SIZE;
return tipc_link_mss(tipc_bc_sndlink(net));
}

void tipc_bcast_disable_rcast(struct net *net)
Expand Down
35 changes: 27 additions & 8 deletions net/tipc/bearer.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include "netlink.h"
#include "udp_media.h"
#include "trace.h"
#include "crypto.h"

#define MAX_ADDR_STR 60

Expand Down Expand Up @@ -516,18 +517,24 @@ void tipc_bearer_xmit_skb(struct net *net, u32 bearer_id,

rcu_read_lock();
b = bearer_get(net, bearer_id);
if (likely(b && (test_bit(0, &b->up) || msg_is_reset(hdr))))
b->media->send_msg(net, skb, b, dest);
else
if (likely(b && (test_bit(0, &b->up) || msg_is_reset(hdr)))) {
#ifdef CONFIG_TIPC_CRYPTO
tipc_crypto_xmit(net, &skb, b, dest, NULL);
if (skb)
#endif
b->media->send_msg(net, skb, b, dest);
} else {
kfree_skb(skb);
}
rcu_read_unlock();
}

/* tipc_bearer_xmit() -send buffer to destination over bearer
*/
void tipc_bearer_xmit(struct net *net, u32 bearer_id,
struct sk_buff_head *xmitq,
struct tipc_media_addr *dst)
struct tipc_media_addr *dst,
struct tipc_node *__dnode)
{
struct tipc_bearer *b;
struct sk_buff *skb, *tmp;
Expand All @@ -541,10 +548,15 @@ void tipc_bearer_xmit(struct net *net, u32 bearer_id,
__skb_queue_purge(xmitq);
skb_queue_walk_safe(xmitq, skb, tmp) {
__skb_dequeue(xmitq);
if (likely(test_bit(0, &b->up) || msg_is_reset(buf_msg(skb))))
b->media->send_msg(net, skb, b, dst);
else
if (likely(test_bit(0, &b->up) || msg_is_reset(buf_msg(skb)))) {
#ifdef CONFIG_TIPC_CRYPTO
tipc_crypto_xmit(net, &skb, b, dst, __dnode);
if (skb)
#endif
b->media->send_msg(net, skb, b, dst);
} else {
kfree_skb(skb);
}
}
rcu_read_unlock();
}
Expand All @@ -555,6 +567,7 @@ void tipc_bearer_bc_xmit(struct net *net, u32 bearer_id,
struct sk_buff_head *xmitq)
{
struct tipc_net *tn = tipc_net(net);
struct tipc_media_addr *dst;
int net_id = tn->net_id;
struct tipc_bearer *b;
struct sk_buff *skb, *tmp;
Expand All @@ -569,7 +582,12 @@ void tipc_bearer_bc_xmit(struct net *net, u32 bearer_id,
msg_set_non_seq(hdr, 1);
msg_set_mc_netid(hdr, net_id);
__skb_dequeue(xmitq);
b->media->send_msg(net, skb, b, &b->bcast_addr);
dst = &b->bcast_addr;
#ifdef CONFIG_TIPC_CRYPTO
tipc_crypto_xmit(net, &skb, b, dst, NULL);
if (skb)
#endif
b->media->send_msg(net, skb, b, dst);
}
rcu_read_unlock();
}
Expand All @@ -596,6 +614,7 @@ static int tipc_l2_rcv_msg(struct sk_buff *skb, struct net_device *dev,
if (likely(b && test_bit(0, &b->up) &&
(skb->pkt_type <= PACKET_MULTICAST))) {
skb_mark_not_on_list(skb);
TIPC_SKB_CB(skb)->flags = 0;
tipc_rcv(dev_net(b->pt.dev), skb, b);
rcu_read_unlock();
return NET_RX_SUCCESS;
Expand Down
3 changes: 2 additions & 1 deletion net/tipc/bearer.h
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,8 @@ void tipc_bearer_xmit_skb(struct net *net, u32 bearer_id,
struct tipc_media_addr *dest);
void tipc_bearer_xmit(struct net *net, u32 bearer_id,
struct sk_buff_head *xmitq,
struct tipc_media_addr *dst);
struct tipc_media_addr *dst,
struct tipc_node *__dnode);
void tipc_bearer_bc_xmit(struct net *net, u32 bearer_id,
struct sk_buff_head *xmitq);
void tipc_clone_to_loopback(struct net *net, struct sk_buff_head *pkts);
Expand Down
14 changes: 14 additions & 0 deletions net/tipc/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include "socket.h"
#include "bcast.h"
#include "node.h"
#include "crypto.h"

#include <linux/module.h>

Expand All @@ -68,6 +69,11 @@ static int __net_init tipc_init_net(struct net *net)
INIT_LIST_HEAD(&tn->node_list);
spin_lock_init(&tn->node_list_lock);

#ifdef CONFIG_TIPC_CRYPTO
err = tipc_crypto_start(&tn->crypto_tx, net, NULL);
if (err)
goto out_crypto;
#endif
err = tipc_sk_rht_init(net);
if (err)
goto out_sk_rht;
Expand All @@ -93,6 +99,11 @@ static int __net_init tipc_init_net(struct net *net)
out_nametbl:
tipc_sk_rht_destroy(net);
out_sk_rht:

#ifdef CONFIG_TIPC_CRYPTO
tipc_crypto_stop(&tn->crypto_tx);
out_crypto:
#endif
return err;
}

Expand All @@ -103,6 +114,9 @@ static void __net_exit tipc_exit_net(struct net *net)
tipc_bcast_stop(net);
tipc_nametbl_stop(net);
tipc_sk_rht_destroy(net);
#ifdef CONFIG_TIPC_CRYPTO
tipc_crypto_stop(&tipc_net(net)->crypto_tx);
#endif
}

static void __net_exit tipc_pernet_pre_exit(struct net *net)
Expand Down
8 changes: 8 additions & 0 deletions net/tipc/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ struct tipc_link;
struct tipc_name_table;
struct tipc_topsrv;
struct tipc_monitor;
#ifdef CONFIG_TIPC_CRYPTO
struct tipc_crypto;
#endif

#define TIPC_MOD_VER "2.0.0"

Expand Down Expand Up @@ -129,6 +132,11 @@ struct tipc_net {

/* Tracing of node internal messages */
struct packet_type loopback_pt;

#ifdef CONFIG_TIPC_CRYPTO
/* TX crypto handler */
struct tipc_crypto *crypto_tx;
#endif
};

static inline struct tipc_net *tipc_net(struct net *net)
Expand Down
Loading

0 comments on commit fc1b6d6

Please sign in to comment.