Commit 1c8f11d0 authored by David S. Miller's avatar David S. Miller

Merge branch 'TIPC-Encryption'

Tuong Lien says:

====================
TIPC Encryption

This series provides TIPC encryption feature, kernel part. There will be
another one in the 'iproute2/tipc' for user space to set key.

v2: add select crypto 'aes(gcm)' for TIPC_CRYPTO in Kconfig
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents f1ff4e80 e1f32190
...@@ -233,6 +233,27 @@ struct tipc_sioc_nodeid_req { ...@@ -233,6 +233,27 @@ struct tipc_sioc_nodeid_req {
char node_id[TIPC_NODEID_LEN]; char node_id[TIPC_NODEID_LEN];
}; };
/*
* TIPC Crypto, AEAD
*/
#define TIPC_AEAD_ALG_NAME (32)
struct tipc_aead_key {
char alg_name[TIPC_AEAD_ALG_NAME];
unsigned int keylen; /* in bytes */
char key[];
};
#define TIPC_AEAD_KEYLEN_MIN (16 + 4)
#define TIPC_AEAD_KEYLEN_MAX (32 + 4)
#define TIPC_AEAD_KEY_SIZE_MAX (sizeof(struct tipc_aead_key) + \
TIPC_AEAD_KEYLEN_MAX)
static inline int tipc_aead_key_size(struct tipc_aead_key *key)
{
return sizeof(*key) + key->keylen;
}
/* The macros and functions below are deprecated: /* The macros and functions below are deprecated:
*/ */
......
...@@ -63,6 +63,8 @@ enum { ...@@ -63,6 +63,8 @@ enum {
TIPC_NL_PEER_REMOVE, TIPC_NL_PEER_REMOVE,
TIPC_NL_BEARER_ADD, TIPC_NL_BEARER_ADD,
TIPC_NL_UDP_GET_REMOTEIP, 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 = __TIPC_NL_CMD_MAX - 1 TIPC_NL_CMD_MAX = __TIPC_NL_CMD_MAX - 1
...@@ -160,6 +162,8 @@ enum { ...@@ -160,6 +162,8 @@ enum {
TIPC_NLA_NODE_UNSPEC, TIPC_NLA_NODE_UNSPEC,
TIPC_NLA_NODE_ADDR, /* u32 */ TIPC_NLA_NODE_ADDR, /* u32 */
TIPC_NLA_NODE_UP, /* flag */ 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 = __TIPC_NLA_NODE_MAX - 1 TIPC_NLA_NODE_MAX = __TIPC_NLA_NODE_MAX - 1
......
...@@ -35,6 +35,21 @@ config TIPC_MEDIA_UDP ...@@ -35,6 +35,21 @@ config TIPC_MEDIA_UDP
Saying Y here will enable support for running TIPC over IP/UDP Saying Y here will enable support for running TIPC over IP/UDP
bool bool
default y 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 config TIPC_DIAG
tristate "TIPC: socket monitoring interface" tristate "TIPC: socket monitoring interface"
......
...@@ -16,6 +16,7 @@ CFLAGS_trace.o += -I$(src) ...@@ -16,6 +16,7 @@ CFLAGS_trace.o += -I$(src)
tipc-$(CONFIG_TIPC_MEDIA_UDP) += udp_media.o tipc-$(CONFIG_TIPC_MEDIA_UDP) += udp_media.o
tipc-$(CONFIG_TIPC_MEDIA_IB) += ib_media.o tipc-$(CONFIG_TIPC_MEDIA_IB) += ib_media.o
tipc-$(CONFIG_SYSCTL) += sysctl.o tipc-$(CONFIG_SYSCTL) += sysctl.o
tipc-$(CONFIG_TIPC_CRYPTO) += crypto.o
obj-$(CONFIG_TIPC_DIAG) += diag.o obj-$(CONFIG_TIPC_DIAG) += diag.o
......
...@@ -84,7 +84,7 @@ static struct tipc_bc_base *tipc_bc_base(struct net *net) ...@@ -84,7 +84,7 @@ static struct tipc_bc_base *tipc_bc_base(struct net *net)
*/ */
int tipc_bcast_get_mtu(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) void tipc_bcast_disable_rcast(struct net *net)
......
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#include "netlink.h" #include "netlink.h"
#include "udp_media.h" #include "udp_media.h"
#include "trace.h" #include "trace.h"
#include "crypto.h"
#define MAX_ADDR_STR 60 #define MAX_ADDR_STR 60
...@@ -315,6 +316,7 @@ static int tipc_enable_bearer(struct net *net, const char *name, ...@@ -315,6 +316,7 @@ static int tipc_enable_bearer(struct net *net, const char *name,
b->net_plane = bearer_id + 'A'; b->net_plane = bearer_id + 'A';
b->priority = prio; b->priority = prio;
test_and_set_bit_lock(0, &b->up); test_and_set_bit_lock(0, &b->up);
refcount_set(&b->refcnt, 1);
res = tipc_disc_create(net, b, &b->bcast_addr, &skb); res = tipc_disc_create(net, b, &b->bcast_addr, &skb);
if (res) { if (res) {
...@@ -351,6 +353,17 @@ static int tipc_reset_bearer(struct net *net, struct tipc_bearer *b) ...@@ -351,6 +353,17 @@ static int tipc_reset_bearer(struct net *net, struct tipc_bearer *b)
return 0; return 0;
} }
bool tipc_bearer_hold(struct tipc_bearer *b)
{
return (b && refcount_inc_not_zero(&b->refcnt));
}
void tipc_bearer_put(struct tipc_bearer *b)
{
if (b && refcount_dec_and_test(&b->refcnt))
kfree_rcu(b, rcu);
}
/** /**
* bearer_disable * bearer_disable
* *
...@@ -369,7 +382,7 @@ static void bearer_disable(struct net *net, struct tipc_bearer *b) ...@@ -369,7 +382,7 @@ static void bearer_disable(struct net *net, struct tipc_bearer *b)
if (b->disc) if (b->disc)
tipc_disc_delete(b->disc); tipc_disc_delete(b->disc);
RCU_INIT_POINTER(tn->bearer_list[bearer_id], NULL); RCU_INIT_POINTER(tn->bearer_list[bearer_id], NULL);
kfree_rcu(b, rcu); tipc_bearer_put(b);
tipc_mon_delete(net, bearer_id); tipc_mon_delete(net, bearer_id);
} }
...@@ -504,10 +517,15 @@ void tipc_bearer_xmit_skb(struct net *net, u32 bearer_id, ...@@ -504,10 +517,15 @@ void tipc_bearer_xmit_skb(struct net *net, u32 bearer_id,
rcu_read_lock(); rcu_read_lock();
b = bearer_get(net, bearer_id); b = bearer_get(net, bearer_id);
if (likely(b && (test_bit(0, &b->up) || msg_is_reset(hdr)))) if (likely(b && (test_bit(0, &b->up) || msg_is_reset(hdr)))) {
b->media->send_msg(net, skb, b, dest); #ifdef CONFIG_TIPC_CRYPTO
else tipc_crypto_xmit(net, &skb, b, dest, NULL);
if (skb)
#endif
b->media->send_msg(net, skb, b, dest);
} else {
kfree_skb(skb); kfree_skb(skb);
}
rcu_read_unlock(); rcu_read_unlock();
} }
...@@ -515,7 +533,8 @@ void tipc_bearer_xmit_skb(struct net *net, u32 bearer_id, ...@@ -515,7 +533,8 @@ void tipc_bearer_xmit_skb(struct net *net, u32 bearer_id,
*/ */
void tipc_bearer_xmit(struct net *net, u32 bearer_id, void tipc_bearer_xmit(struct net *net, u32 bearer_id,
struct sk_buff_head *xmitq, struct sk_buff_head *xmitq,
struct tipc_media_addr *dst) struct tipc_media_addr *dst,
struct tipc_node *__dnode)
{ {
struct tipc_bearer *b; struct tipc_bearer *b;
struct sk_buff *skb, *tmp; struct sk_buff *skb, *tmp;
...@@ -529,10 +548,15 @@ void tipc_bearer_xmit(struct net *net, u32 bearer_id, ...@@ -529,10 +548,15 @@ void tipc_bearer_xmit(struct net *net, u32 bearer_id,
__skb_queue_purge(xmitq); __skb_queue_purge(xmitq);
skb_queue_walk_safe(xmitq, skb, tmp) { skb_queue_walk_safe(xmitq, skb, tmp) {
__skb_dequeue(xmitq); __skb_dequeue(xmitq);
if (likely(test_bit(0, &b->up) || msg_is_reset(buf_msg(skb)))) if (likely(test_bit(0, &b->up) || msg_is_reset(buf_msg(skb)))) {
b->media->send_msg(net, skb, b, dst); #ifdef CONFIG_TIPC_CRYPTO
else tipc_crypto_xmit(net, &skb, b, dst, __dnode);
if (skb)
#endif
b->media->send_msg(net, skb, b, dst);
} else {
kfree_skb(skb); kfree_skb(skb);
}
} }
rcu_read_unlock(); rcu_read_unlock();
} }
...@@ -543,6 +567,7 @@ void tipc_bearer_bc_xmit(struct net *net, u32 bearer_id, ...@@ -543,6 +567,7 @@ void tipc_bearer_bc_xmit(struct net *net, u32 bearer_id,
struct sk_buff_head *xmitq) struct sk_buff_head *xmitq)
{ {
struct tipc_net *tn = tipc_net(net); struct tipc_net *tn = tipc_net(net);
struct tipc_media_addr *dst;
int net_id = tn->net_id; int net_id = tn->net_id;
struct tipc_bearer *b; struct tipc_bearer *b;
struct sk_buff *skb, *tmp; struct sk_buff *skb, *tmp;
...@@ -557,7 +582,12 @@ void tipc_bearer_bc_xmit(struct net *net, u32 bearer_id, ...@@ -557,7 +582,12 @@ void tipc_bearer_bc_xmit(struct net *net, u32 bearer_id,
msg_set_non_seq(hdr, 1); msg_set_non_seq(hdr, 1);
msg_set_mc_netid(hdr, net_id); msg_set_mc_netid(hdr, net_id);
__skb_dequeue(xmitq); __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(); rcu_read_unlock();
} }
...@@ -584,6 +614,7 @@ static int tipc_l2_rcv_msg(struct sk_buff *skb, struct net_device *dev, ...@@ -584,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) && if (likely(b && test_bit(0, &b->up) &&
(skb->pkt_type <= PACKET_MULTICAST))) { (skb->pkt_type <= PACKET_MULTICAST))) {
skb_mark_not_on_list(skb); skb_mark_not_on_list(skb);
TIPC_SKB_CB(skb)->flags = 0;
tipc_rcv(dev_net(b->pt.dev), skb, b); tipc_rcv(dev_net(b->pt.dev), skb, b);
rcu_read_unlock(); rcu_read_unlock();
return NET_RX_SUCCESS; return NET_RX_SUCCESS;
......
...@@ -165,6 +165,7 @@ struct tipc_bearer { ...@@ -165,6 +165,7 @@ struct tipc_bearer {
struct tipc_discoverer *disc; struct tipc_discoverer *disc;
char net_plane; char net_plane;
unsigned long up; unsigned long up;
refcount_t refcnt;
}; };
struct tipc_bearer_names { struct tipc_bearer_names {
...@@ -210,6 +211,8 @@ int tipc_media_set_window(const char *name, u32 new_value); ...@@ -210,6 +211,8 @@ int tipc_media_set_window(const char *name, u32 new_value);
int tipc_media_addr_printf(char *buf, int len, struct tipc_media_addr *a); int tipc_media_addr_printf(char *buf, int len, struct tipc_media_addr *a);
int tipc_enable_l2_media(struct net *net, struct tipc_bearer *b, int tipc_enable_l2_media(struct net *net, struct tipc_bearer *b,
struct nlattr *attrs[]); struct nlattr *attrs[]);
bool tipc_bearer_hold(struct tipc_bearer *b);
void tipc_bearer_put(struct tipc_bearer *b);
void tipc_disable_l2_media(struct tipc_bearer *b); void tipc_disable_l2_media(struct tipc_bearer *b);
int tipc_l2_send_msg(struct net *net, struct sk_buff *buf, int tipc_l2_send_msg(struct net *net, struct sk_buff *buf,
struct tipc_bearer *b, struct tipc_media_addr *dest); struct tipc_bearer *b, struct tipc_media_addr *dest);
...@@ -229,7 +232,8 @@ void tipc_bearer_xmit_skb(struct net *net, u32 bearer_id, ...@@ -229,7 +232,8 @@ void tipc_bearer_xmit_skb(struct net *net, u32 bearer_id,
struct tipc_media_addr *dest); struct tipc_media_addr *dest);
void tipc_bearer_xmit(struct net *net, u32 bearer_id, void tipc_bearer_xmit(struct net *net, u32 bearer_id,
struct sk_buff_head *xmitq, 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, void tipc_bearer_bc_xmit(struct net *net, u32 bearer_id,
struct sk_buff_head *xmitq); struct sk_buff_head *xmitq);
void tipc_clone_to_loopback(struct net *net, struct sk_buff_head *pkts); void tipc_clone_to_loopback(struct net *net, struct sk_buff_head *pkts);
......
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#include "socket.h" #include "socket.h"
#include "bcast.h" #include "bcast.h"
#include "node.h" #include "node.h"
#include "crypto.h"
#include <linux/module.h> #include <linux/module.h>
...@@ -68,6 +69,11 @@ static int __net_init tipc_init_net(struct net *net) ...@@ -68,6 +69,11 @@ static int __net_init tipc_init_net(struct net *net)
INIT_LIST_HEAD(&tn->node_list); INIT_LIST_HEAD(&tn->node_list);
spin_lock_init(&tn->node_list_lock); 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); err = tipc_sk_rht_init(net);
if (err) if (err)
goto out_sk_rht; goto out_sk_rht;
...@@ -93,6 +99,11 @@ static int __net_init tipc_init_net(struct net *net) ...@@ -93,6 +99,11 @@ static int __net_init tipc_init_net(struct net *net)
out_nametbl: out_nametbl:
tipc_sk_rht_destroy(net); tipc_sk_rht_destroy(net);
out_sk_rht: out_sk_rht:
#ifdef CONFIG_TIPC_CRYPTO
tipc_crypto_stop(&tn->crypto_tx);
out_crypto:
#endif
return err; return err;
} }
...@@ -103,6 +114,9 @@ static void __net_exit tipc_exit_net(struct net *net) ...@@ -103,6 +114,9 @@ static void __net_exit tipc_exit_net(struct net *net)
tipc_bcast_stop(net); tipc_bcast_stop(net);
tipc_nametbl_stop(net); tipc_nametbl_stop(net);
tipc_sk_rht_destroy(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) static void __net_exit tipc_pernet_pre_exit(struct net *net)
......
...@@ -68,6 +68,9 @@ struct tipc_link; ...@@ -68,6 +68,9 @@ struct tipc_link;
struct tipc_name_table; struct tipc_name_table;
struct tipc_topsrv; struct tipc_topsrv;
struct tipc_monitor; struct tipc_monitor;
#ifdef CONFIG_TIPC_CRYPTO
struct tipc_crypto;
#endif
#define TIPC_MOD_VER "2.0.0" #define TIPC_MOD_VER "2.0.0"
...@@ -129,6 +132,11 @@ struct tipc_net { ...@@ -129,6 +132,11 @@ struct tipc_net {
/* Tracing of node internal messages */ /* Tracing of node internal messages */
struct packet_type loopback_pt; 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) static inline struct tipc_net *tipc_net(struct net *net)
......
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0 */
/**
* net/tipc/crypto.h: Include file for TIPC crypto
*
* Copyright (c) 2019, Ericsson AB
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the names of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef CONFIG_TIPC_CRYPTO
#ifndef _TIPC_CRYPTO_H
#define _TIPC_CRYPTO_H
#include "core.h"
#include "node.h"
#include "msg.h"
#include "bearer.h"
#define TIPC_EVERSION 7
/* AEAD aes(gcm) */
#define TIPC_AES_GCM_KEY_SIZE_128 16
#define TIPC_AES_GCM_KEY_SIZE_192 24
#define TIPC_AES_GCM_KEY_SIZE_256 32
#define TIPC_AES_GCM_SALT_SIZE 4
#define TIPC_AES_GCM_IV_SIZE 12
#define TIPC_AES_GCM_TAG_SIZE 16
/**
* TIPC crypto modes:
* - CLUSTER_KEY:
* One single key is used for both TX & RX in all nodes in the cluster.
* - PER_NODE_KEY:
* Each nodes in the cluster has one TX key, for RX a node needs to know
* its peers' TX key for the decryption of messages from those nodes.
*/
enum {
CLUSTER_KEY = 1,
PER_NODE_KEY = (1 << 1),
};
extern int sysctl_tipc_max_tfms __read_mostly;
/**
* TIPC encryption message format:
*
* 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
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* w0:|Ver=7| User |D|TX |RX |K| Rsvd |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* w1:| Seqno |
* w2:| (8 octets) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* w3:\ Prevnode \
* / (4 or 16 octets) /
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* \ \
* / Encrypted complete TIPC V2 header and user data /
* \ \
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* | AuthTag |
* | (16 octets) |
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* Word0:
* Ver : = 7 i.e. TIPC encryption message version
* User : = 7 (for LINK_PROTOCOL); = 13 (for LINK_CONFIG) or = 0
* D : The destined bit i.e. the message's destination node is
* "known" or not at the message encryption
* TX : TX key used for the message encryption
* RX : Currently RX active key corresponding to the destination
* node's TX key (when the "D" bit is set)
* K : Keep-alive bit (for RPS, LINK_PROTOCOL/STATE_MSG only)
* Rsvd : Reserved bit, field
* Word1-2:
* Seqno : The 64-bit sequence number of the encrypted message, also
* part of the nonce used for the message encryption/decryption
* Word3-:
* Prevnode: The source node address, or ID in case LINK_CONFIG only
* AuthTag : The authentication tag for the message integrity checking
* generated by the message encryption
*/
struct tipc_ehdr {
union {
struct {
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u8 destined:1,
user:4,
version:3;
__u8 reserved_1:3,
keepalive:1,
rx_key_active:2,
tx_key:2;
#elif defined(__BIG_ENDIAN_BITFIELD)
__u8 version:3,
user:4,
destined:1;
__u8 tx_key:2,
rx_key_active:2,
keepalive:1,
reserved_1:3;
#else
#error "Please fix <asm/byteorder.h>"
#endif
__be16 reserved_2;
} __packed;
__be32 w0;
};
__be64 seqno;
union {
__be32 addr;
__u8 id[NODE_ID_LEN]; /* For a LINK_CONFIG message only! */
};
#define EHDR_SIZE (offsetof(struct tipc_ehdr, addr) + sizeof(__be32))
#define EHDR_CFG_SIZE (sizeof(struct tipc_ehdr))
#define EHDR_MIN_SIZE (EHDR_SIZE)
#define EHDR_MAX_SIZE (EHDR_CFG_SIZE)
#define EMSG_OVERHEAD (EHDR_SIZE + TIPC_AES_GCM_TAG_SIZE)
} __packed;
int tipc_crypto_start(struct tipc_crypto **crypto, struct net *net,
struct tipc_node *node);
void tipc_crypto_stop(struct tipc_crypto **crypto);
void tipc_crypto_timeout(struct tipc_crypto *rx);
int tipc_crypto_xmit(struct net *net, struct sk_buff **skb,
struct tipc_bearer *b, struct tipc_media_addr *dst,
struct tipc_node *__dnode);
int tipc_crypto_rcv(struct net *net, struct tipc_crypto *rx,
struct sk_buff **skb, struct tipc_bearer *b);
int tipc_crypto_key_init(struct tipc_crypto *c, struct tipc_aead_key *ukey,
u8 mode);
void tipc_crypto_key_flush(struct tipc_crypto *c);
int tipc_aead_key_validate(struct tipc_aead_key *ukey);
bool tipc_ehdr_validate(struct sk_buff *skb);
#endif /* _TIPC_CRYPTO_H */
#endif
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#include "netlink.h" #include "netlink.h"
#include "monitor.h" #include "monitor.h"
#include "trace.h" #include "trace.h"
#include "crypto.h"
#include <linux/pkt_sched.h> #include <linux/pkt_sched.h>
...@@ -397,6 +398,15 @@ int tipc_link_mtu(struct tipc_link *l) ...@@ -397,6 +398,15 @@ int tipc_link_mtu(struct tipc_link *l)
return l->mtu; return l->mtu;
} }
int tipc_link_mss(struct tipc_link *l)
{
#ifdef CONFIG_TIPC_CRYPTO
return l->mtu - INT_H_SIZE - EMSG_OVERHEAD;
#else
return l->mtu - INT_H_SIZE;
#endif
}
u16 tipc_link_rcv_nxt(struct tipc_link *l) u16 tipc_link_rcv_nxt(struct tipc_link *l)
{ {
return l->rcv_nxt; return l->rcv_nxt;
...@@ -948,6 +958,7 @@ int tipc_link_xmit(struct tipc_link *l, struct sk_buff_head *list, ...@@ -948,6 +958,7 @@ int tipc_link_xmit(struct tipc_link *l, struct sk_buff_head *list,
u16 seqno = l->snd_nxt; u16 seqno = l->snd_nxt;
int pkt_cnt = skb_queue_len(list); int pkt_cnt = skb_queue_len(list);
int imp = msg_importance(hdr); int imp = msg_importance(hdr);
unsigned int mss = tipc_link_mss(l);
unsigned int maxwin = l->window; unsigned int maxwin = l->window;
unsigned int mtu = l->mtu; unsigned int mtu = l->mtu;
bool new_bundle; bool new_bundle;
...@@ -1000,8 +1011,7 @@ int tipc_link_xmit(struct tipc_link *l, struct sk_buff_head *list, ...@@ -1000,8 +1011,7 @@ int tipc_link_xmit(struct tipc_link *l, struct sk_buff_head *list,
continue; continue;
} }
if (tipc_msg_try_bundle(l->backlog[imp].target_bskb, &skb, if (tipc_msg_try_bundle(l->backlog[imp].target_bskb, &skb,
mtu - INT_H_SIZE, l->addr, mss, l->addr, &new_bundle)) {
&new_bundle)) {
if (skb) { if (skb) {
/* Keep a ref. to the skb for next try */ /* Keep a ref. to the skb for next try */
l->backlog[imp].target_bskb = skb; l->backlog[imp].target_bskb = skb;
...@@ -1154,7 +1164,7 @@ static int tipc_link_bc_retrans(struct tipc_link *l, struct tipc_link *r, ...@@ -1154,7 +1164,7 @@ static int tipc_link_bc_retrans(struct tipc_link *l, struct tipc_link *r,
if (time_before(jiffies, TIPC_SKB_CB(skb)->nxt_retr)) if (time_before(jiffies, TIPC_SKB_CB(skb)->nxt_retr))
continue; continue;
TIPC_SKB_CB(skb)->nxt_retr = TIPC_BC_RETR_LIM; TIPC_SKB_CB(skb)->nxt_retr = TIPC_BC_RETR_LIM;
_skb = __pskb_copy(skb, LL_MAX_HEADER + MIN_H_SIZE, GFP_ATOMIC); _skb = pskb_copy(skb, GFP_ATOMIC);
if (!_skb) if (!_skb)
return 0; return 0;
hdr = buf_msg(_skb); hdr = buf_msg(_skb);
...@@ -1430,8 +1440,7 @@ static int tipc_link_advance_transmq(struct tipc_link *l, u16 acked, u16 gap, ...@@ -1430,8 +1440,7 @@ static int tipc_link_advance_transmq(struct tipc_link *l, u16 acked, u16 gap,
if (time_before(jiffies, TIPC_SKB_CB(skb)->nxt_retr)) if (time_before(jiffies, TIPC_SKB_CB(skb)->nxt_retr))
continue; continue;
TIPC_SKB_CB(skb)->nxt_retr = TIPC_UC_RETR_TIME; TIPC_SKB_CB(skb)->nxt_retr = TIPC_UC_RETR_TIME;
_skb = __pskb_copy(skb, LL_MAX_HEADER + MIN_H_SIZE, _skb = pskb_copy(skb, GFP_ATOMIC);
GFP_ATOMIC);
if (!_skb) if (!_skb)
continue; continue;
hdr = buf_msg(_skb); hdr = buf_msg(_skb);
......
...@@ -141,6 +141,7 @@ void tipc_link_remove_bc_peer(struct tipc_link *snd_l, ...@@ -141,6 +141,7 @@ void tipc_link_remove_bc_peer(struct tipc_link *snd_l,
int tipc_link_bc_peers(struct tipc_link *l); int tipc_link_bc_peers(struct tipc_link *l);
void tipc_link_set_mtu(struct tipc_link *l, int mtu); void tipc_link_set_mtu(struct tipc_link *l, int mtu);
int tipc_link_mtu(struct tipc_link *l); int tipc_link_mtu(struct tipc_link *l);
int tipc_link_mss(struct tipc_link *l);
void tipc_link_bc_ack_rcv(struct tipc_link *l, u16 acked, void tipc_link_bc_ack_rcv(struct tipc_link *l, u16 acked,
struct sk_buff_head *xmitq); struct sk_buff_head *xmitq);
void tipc_link_build_bc_sync_msg(struct tipc_link *l, void tipc_link_build_bc_sync_msg(struct tipc_link *l,
......
...@@ -39,10 +39,16 @@ ...@@ -39,10 +39,16 @@
#include "msg.h" #include "msg.h"
#include "addr.h" #include "addr.h"
#include "name_table.h" #include "name_table.h"
#include "crypto.h"
#define MAX_FORWARD_SIZE 1024 #define MAX_FORWARD_SIZE 1024
#ifdef CONFIG_TIPC_CRYPTO
#define BUF_HEADROOM ALIGN(((LL_MAX_HEADER + 48) + EHDR_MAX_SIZE), 16)
#define BUF_TAILROOM (TIPC_AES_GCM_TAG_SIZE)
#else
#define BUF_HEADROOM (LL_MAX_HEADER + 48) #define BUF_HEADROOM (LL_MAX_HEADER + 48)
#define BUF_TAILROOM 16 #define BUF_TAILROOM 16
#endif
static unsigned int align(unsigned int i) static unsigned int align(unsigned int i)
{ {
...@@ -61,7 +67,11 @@ static unsigned int align(unsigned int i) ...@@ -61,7 +67,11 @@ static unsigned int align(unsigned int i)
struct sk_buff *tipc_buf_acquire(u32 size, gfp_t gfp) struct sk_buff *tipc_buf_acquire(u32 size, gfp_t gfp)
{ {
struct sk_buff *skb; struct sk_buff *skb;
#ifdef CONFIG_TIPC_CRYPTO
unsigned int buf_size = (BUF_HEADROOM + size + BUF_TAILROOM + 3) & ~3u;
#else
unsigned int buf_size = (BUF_HEADROOM + size + 3) & ~3u; unsigned int buf_size = (BUF_HEADROOM + size + 3) & ~3u;
#endif
skb = alloc_skb_fclone(buf_size, gfp); skb = alloc_skb_fclone(buf_size, gfp);
if (skb) { if (skb) {
...@@ -173,7 +183,7 @@ int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf) ...@@ -173,7 +183,7 @@ int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf)
} }
if (fragid == LAST_FRAGMENT) { if (fragid == LAST_FRAGMENT) {
TIPC_SKB_CB(head)->validated = false; TIPC_SKB_CB(head)->validated = 0;
if (unlikely(!tipc_msg_validate(&head))) if (unlikely(!tipc_msg_validate(&head)))
goto err; goto err;
*buf = head; *buf = head;
...@@ -271,6 +281,7 @@ bool tipc_msg_validate(struct sk_buff **_skb) ...@@ -271,6 +281,7 @@ bool tipc_msg_validate(struct sk_buff **_skb)
if (unlikely(TIPC_SKB_CB(skb)->validated)) if (unlikely(TIPC_SKB_CB(skb)->validated))
return true; return true;
if (unlikely(!pskb_may_pull(skb, MIN_H_SIZE))) if (unlikely(!pskb_may_pull(skb, MIN_H_SIZE)))
return false; return false;
...@@ -292,7 +303,7 @@ bool tipc_msg_validate(struct sk_buff **_skb) ...@@ -292,7 +303,7 @@ bool tipc_msg_validate(struct sk_buff **_skb)
if (unlikely(skb->len < msz)) if (unlikely(skb->len < msz))
return false; return false;
TIPC_SKB_CB(skb)->validated = true; TIPC_SKB_CB(skb)->validated = 1;
return true; return true;
} }
......
...@@ -102,16 +102,42 @@ struct plist; ...@@ -102,16 +102,42 @@ struct plist;
#define TIPC_MEDIA_INFO_OFFSET 5 #define TIPC_MEDIA_INFO_OFFSET 5
struct tipc_skb_cb { struct tipc_skb_cb {
struct sk_buff *tail; union {
unsigned long nxt_retr; struct {
unsigned long retr_stamp; struct sk_buff *tail;
u32 bytes_read; unsigned long nxt_retr;
u32 orig_member; unsigned long retr_stamp;
u16 chain_imp; u32 bytes_read;
u16 ackers; u32 orig_member;
u16 retr_cnt; u16 chain_imp;
bool validated; u16 ackers;
}; u16 retr_cnt;
} __packed;
#ifdef CONFIG_TIPC_CRYPTO
struct {
struct tipc_crypto *rx;
struct tipc_aead *last;
u8 recurs;
} tx_clone_ctx __packed;
#endif
} __packed;
union {
struct {
u8 validated:1;
#ifdef CONFIG_TIPC_CRYPTO
u8 encrypted:1;
u8 decrypted:1;
u8 probe:1;
u8 tx_clone_deferred:1;
#endif
};
u8 flags;
};
u8 reserved;
#ifdef CONFIG_TIPC_CRYPTO
void *crypto_ctx;
#endif
} __packed;
#define TIPC_SKB_CB(__skb) ((struct tipc_skb_cb *)&((__skb)->cb[0])) #define TIPC_SKB_CB(__skb) ((struct tipc_skb_cb *)&((__skb)->cb[0]))
......
...@@ -102,7 +102,11 @@ const struct nla_policy tipc_nl_link_policy[TIPC_NLA_LINK_MAX + 1] = { ...@@ -102,7 +102,11 @@ const struct nla_policy tipc_nl_link_policy[TIPC_NLA_LINK_MAX + 1] = {
const struct nla_policy tipc_nl_node_policy[TIPC_NLA_NODE_MAX + 1] = { const struct nla_policy tipc_nl_node_policy[TIPC_NLA_NODE_MAX + 1] = {
[TIPC_NLA_NODE_UNSPEC] = { .type = NLA_UNSPEC }, [TIPC_NLA_NODE_UNSPEC] = { .type = NLA_UNSPEC },
[TIPC_NLA_NODE_ADDR] = { .type = NLA_U32 }, [TIPC_NLA_NODE_ADDR] = { .type = NLA_U32 },
[TIPC_NLA_NODE_UP] = { .type = NLA_FLAG } [TIPC_NLA_NODE_UP] = { .type = NLA_FLAG },
[TIPC_NLA_NODE_ID] = { .type = NLA_BINARY,
.len = TIPC_NODEID_LEN},
[TIPC_NLA_NODE_KEY] = { .type = NLA_BINARY,
.len = TIPC_AEAD_KEY_SIZE_MAX},
}; };
/* Properties valid for media, bearer and link */ /* Properties valid for media, bearer and link */
...@@ -257,6 +261,18 @@ static const struct genl_ops tipc_genl_v2_ops[] = { ...@@ -257,6 +261,18 @@ static const struct genl_ops tipc_genl_v2_ops[] = {
.dumpit = tipc_udp_nl_dump_remoteip, .dumpit = tipc_udp_nl_dump_remoteip,
}, },
#endif #endif
#ifdef CONFIG_TIPC_CRYPTO
{
.cmd = TIPC_NL_KEY_SET,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = tipc_nl_node_set_key,
},
{
.cmd = TIPC_NL_KEY_FLUSH,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = tipc_nl_node_flush_key,
},
#endif
}; };
struct genl_family tipc_genl_family __ro_after_init = { struct genl_family tipc_genl_family __ro_after_init = {
......
This diff is collapsed.
...@@ -75,6 +75,15 @@ enum { ...@@ -75,6 +75,15 @@ enum {
void tipc_node_stop(struct net *net); void tipc_node_stop(struct net *net);
bool tipc_node_get_id(struct net *net, u32 addr, u8 *id); bool tipc_node_get_id(struct net *net, u32 addr, u8 *id);
u32 tipc_node_get_addr(struct tipc_node *node); u32 tipc_node_get_addr(struct tipc_node *node);
char *tipc_node_get_id_str(struct tipc_node *node);
void tipc_node_put(struct tipc_node *node);
struct tipc_node *tipc_node_create(struct net *net, u32 addr, u8 *peer_id,
u16 capabilities, u32 hash_mixes,
bool preliminary);
#ifdef CONFIG_TIPC_CRYPTO
struct tipc_crypto *tipc_node_crypto_rx(struct tipc_node *__n);
struct tipc_crypto *tipc_node_crypto_rx_by_list(struct list_head *pos);
#endif
u32 tipc_node_try_addr(struct net *net, u8 *id, u32 addr); u32 tipc_node_try_addr(struct net *net, u8 *id, u32 addr);
void tipc_node_check_dest(struct net *net, u32 onode, u8 *peer_id128, void tipc_node_check_dest(struct net *net, u32 onode, u8 *peer_id128,
struct tipc_bearer *bearer, struct tipc_bearer *bearer,
...@@ -110,5 +119,9 @@ int tipc_nl_node_get_monitor(struct sk_buff *skb, struct genl_info *info); ...@@ -110,5 +119,9 @@ int tipc_nl_node_get_monitor(struct sk_buff *skb, struct genl_info *info);
int tipc_nl_node_dump_monitor(struct sk_buff *skb, struct netlink_callback *cb); int tipc_nl_node_dump_monitor(struct sk_buff *skb, struct netlink_callback *cb);
int tipc_nl_node_dump_monitor_peer(struct sk_buff *skb, int tipc_nl_node_dump_monitor_peer(struct sk_buff *skb,
struct netlink_callback *cb); struct netlink_callback *cb);
#ifdef CONFIG_TIPC_CRYPTO
int tipc_nl_node_set_key(struct sk_buff *skb, struct genl_info *info);
int tipc_nl_node_flush_key(struct sk_buff *skb, struct genl_info *info);
#endif
void tipc_node_pre_cleanup_net(struct net *exit_net); void tipc_node_pre_cleanup_net(struct net *exit_net);
#endif #endif
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include "core.h" #include "core.h"
#include "trace.h" #include "trace.h"
#include "crypto.h"
#include <linux/sysctl.h> #include <linux/sysctl.h>
...@@ -64,6 +65,16 @@ static struct ctl_table tipc_table[] = { ...@@ -64,6 +65,16 @@ static struct ctl_table tipc_table[] = {
.mode = 0644, .mode = 0644,
.proc_handler = proc_doulongvec_minmax, .proc_handler = proc_doulongvec_minmax,
}, },
#ifdef CONFIG_TIPC_CRYPTO
{
.procname = "max_tfms",
.data = &sysctl_tipc_max_tfms,
.maxlen = sizeof(sysctl_tipc_max_tfms),
.mode = 0644,
.proc_handler = proc_dointvec_minmax,
.extra1 = SYSCTL_ONE,
},
#endif
{} {}
}; };
......
...@@ -372,6 +372,7 @@ static int tipc_udp_recv(struct sock *sk, struct sk_buff *skb) ...@@ -372,6 +372,7 @@ static int tipc_udp_recv(struct sock *sk, struct sk_buff *skb)
goto out; goto out;
if (b && test_bit(0, &b->up)) { if (b && test_bit(0, &b->up)) {
TIPC_SKB_CB(skb)->flags = 0;
tipc_rcv(sock_net(sk), skb, b); tipc_rcv(sock_net(sk), skb, b);
return 0; return 0;
} }
......
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