net/tcp: Add TCP-AO config and structures
authorDmitry Safonov <dima@arista.com>
Mon, 23 Oct 2023 19:21:54 +0000 (20:21 +0100)
committerDavid S. Miller <davem@davemloft.net>
Fri, 27 Oct 2023 09:35:44 +0000 (10:35 +0100)
Introduce new kernel config option and common structures as well as
helpers to be used by TCP-AO code.

Co-developed-by: Francesco Ruggeri <fruggeri@arista.com>
Signed-off-by: Francesco Ruggeri <fruggeri@arista.com>
Co-developed-by: Salam Noureddine <noureddine@arista.com>
Signed-off-by: Salam Noureddine <noureddine@arista.com>
Signed-off-by: Dmitry Safonov <dima@arista.com>
Acked-by: David Ahern <dsahern@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/tcp.h
include/net/tcp.h
include/net/tcp_ao.h [new file with mode: 0644]
include/uapi/linux/tcp.h
net/ipv4/Kconfig

index 6df715b..64e7b56 100644 (file)
@@ -447,13 +447,18 @@ struct tcp_sock {
        bool    syn_smc;        /* SYN includes SMC */
 #endif
 
-#ifdef CONFIG_TCP_MD5SIG
-/* TCP AF-Specific parts; only used by MD5 Signature support so far */
+#if defined(CONFIG_TCP_MD5SIG) || defined(CONFIG_TCP_AO)
+/* TCP AF-Specific parts; only used by TCP-AO/MD5 Signature support so far */
        const struct tcp_sock_af_ops    *af_specific;
 
+#ifdef CONFIG_TCP_MD5SIG
 /* TCP MD5 Signature Option information */
        struct tcp_md5sig_info  __rcu *md5sig_info;
 #endif
+#ifdef CONFIG_TCP_AO
+       struct tcp_ao_info      __rcu *ao_info;
+#endif
+#endif
 
 /* TCP fastopen related information */
        struct tcp_fastopen_request *fastopen_req;
index f6e2db5..3153712 100644 (file)
@@ -37,6 +37,7 @@
 #include <net/snmp.h>
 #include <net/ip.h>
 #include <net/tcp_states.h>
+#include <net/tcp_ao.h>
 #include <net/inet_ecn.h>
 #include <net/dst.h>
 #include <net/mptcp.h>
@@ -1688,12 +1689,7 @@ static inline void tcp_clear_all_retrans_hints(struct tcp_sock *tp)
        tp->retransmit_skb_hint = NULL;
 }
 
-union tcp_md5_addr {
-       struct in_addr  a4;
-#if IS_ENABLED(CONFIG_IPV6)
-       struct in6_addr a6;
-#endif
-};
+#define tcp_md5_addr tcp_ao_addr
 
 /* - key database */
 struct tcp_md5sig_key {
diff --git a/include/net/tcp_ao.h b/include/net/tcp_ao.h
new file mode 100644 (file)
index 0000000..af76e1c
--- /dev/null
@@ -0,0 +1,90 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+#ifndef _TCP_AO_H
+#define _TCP_AO_H
+
+#define TCP_AO_KEY_ALIGN       1
+#define __tcp_ao_key_align __aligned(TCP_AO_KEY_ALIGN)
+
+union tcp_ao_addr {
+       struct in_addr  a4;
+#if IS_ENABLED(CONFIG_IPV6)
+       struct in6_addr a6;
+#endif
+};
+
+struct tcp_ao_hdr {
+       u8      kind;
+       u8      length;
+       u8      keyid;
+       u8      rnext_keyid;
+};
+
+struct tcp_ao_key {
+       struct hlist_node       node;
+       union tcp_ao_addr       addr;
+       u8                      key[TCP_AO_MAXKEYLEN] __tcp_ao_key_align;
+       unsigned int            tcp_sigpool_id;
+       unsigned int            digest_size;
+       u8                      prefixlen;
+       u8                      family;
+       u8                      keylen;
+       u8                      keyflags;
+       u8                      sndid;
+       u8                      rcvid;
+       u8                      maclen;
+       struct rcu_head         rcu;
+       u8                      traffic_keys[];
+};
+
+static inline u8 *rcv_other_key(struct tcp_ao_key *key)
+{
+       return key->traffic_keys;
+}
+
+static inline u8 *snd_other_key(struct tcp_ao_key *key)
+{
+       return key->traffic_keys + key->digest_size;
+}
+
+static inline int tcp_ao_maclen(const struct tcp_ao_key *key)
+{
+       return key->maclen;
+}
+
+static inline int tcp_ao_len(const struct tcp_ao_key *key)
+{
+       return tcp_ao_maclen(key) + sizeof(struct tcp_ao_hdr);
+}
+
+static inline unsigned int tcp_ao_digest_size(struct tcp_ao_key *key)
+{
+       return key->digest_size;
+}
+
+static inline int tcp_ao_sizeof_key(const struct tcp_ao_key *key)
+{
+       return sizeof(struct tcp_ao_key) + (key->digest_size << 1);
+}
+
+struct tcp_ao_info {
+       /* List of tcp_ao_key's */
+       struct hlist_head       head;
+       /* current_key and rnext_key aren't maintained on listen sockets.
+        * Their purpose is to cache keys on established connections,
+        * saving needless lookups. Never dereference any of them from
+        * listen sockets.
+        * ::current_key may change in RX to the key that was requested by
+        * the peer, please use READ_ONCE()/WRITE_ONCE() in order to avoid
+        * load/store tearing.
+        * Do the same for ::rnext_key, if you don't hold socket lock
+        * (it's changed only by userspace request in setsockopt()).
+        */
+       struct tcp_ao_key       *current_key;
+       struct tcp_ao_key       *rnext_key;
+       u32                     flags;
+       __be32                  lisn;
+       __be32                  risn;
+       struct rcu_head         rcu;
+};
+
+#endif /* _TCP_AO_H */
index 8aa3916..74a1267 100644 (file)
@@ -361,6 +361,8 @@ struct tcp_diag_md5sig {
        __u8    tcpm_key[TCP_MD5SIG_MAXKEYLEN];
 };
 
+#define TCP_AO_MAXKEYLEN       80
+
 /* setsockopt(fd, IPPROTO_TCP, TCP_ZEROCOPY_RECEIVE, ...) */
 
 #define TCP_RECEIVE_ZEROCOPY_FLAG_TLB_CLEAN_HINT 0x1
index 89e2ab0..8e94ed7 100644 (file)
@@ -744,6 +744,19 @@ config DEFAULT_TCP_CONG
 config TCP_SIGPOOL
        tristate
 
+config TCP_AO
+       bool "TCP: Authentication Option (RFC5925)"
+       select CRYPTO
+       select TCP_SIGPOOL
+       depends on 64BIT && IPV6 != m # seq-number extension needs WRITE_ONCE(u64)
+       help
+         TCP-AO specifies the use of stronger Message Authentication Codes (MACs),
+         protects against replays for long-lived TCP connections, and
+         provides more details on the association of security with TCP
+         connections than TCP MD5 (See RFC5925)
+
+         If unsure, say N.
+
 config TCP_MD5SIG
        bool "TCP: MD5 Signature Option support (RFC2385)"
        select CRYPTO