From patchwork Mon Aug 9 21:35:30 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leonard Crestez X-Patchwork-Id: 12427325 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 206B8C4338F for ; Mon, 9 Aug 2021 21:36:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 065716023B for ; Mon, 9 Aug 2021 21:36:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236474AbhHIVgO (ORCPT ); Mon, 9 Aug 2021 17:36:14 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58578 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236422AbhHIVgK (ORCPT ); Mon, 9 Aug 2021 17:36:10 -0400 Received: from mail-ed1-x530.google.com (mail-ed1-x530.google.com [IPv6:2a00:1450:4864:20::530]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8EE47C0613D3; Mon, 9 Aug 2021 14:35:49 -0700 (PDT) Received: by mail-ed1-x530.google.com with SMTP id g21so26857345edb.4; Mon, 09 Aug 2021 14:35:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=1gnFFzCzb9HRi8cj9pNhx2u1e8nNwY9we1X1pLyKCow=; b=YuLzyQ546sfSMcAHN5LtP7oMSOqB/MD7Y+7RxbQjHQgbovNd3EVzXPx+JkS3bR55Rn 94Njr55Rc9dIPAd9O/hN2+l59K9gFDQQUphW4WMNNoSqoeY0lndIlVBHjMoXQjlNHIiF HLT0NSpzZHAJy2vx/uSbKI7mtXr6glhWYs+feL4NBejZ3IQuonsTbobdNMAqg0WXJp4c uDP6EHxk1xiYiKn5lPWUtKOLBrNush2fV9/IUtLzd6brSTJgvpBJrP42TBC+tyz6C1QY wIZdMgC6WgbcMETL7zB4WKNN0cQvBlj6icPZTaOeVQcjGffFrBOHMSzFDeVtSFPQ7FKg l4Kw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=1gnFFzCzb9HRi8cj9pNhx2u1e8nNwY9we1X1pLyKCow=; b=B38R734OW0s0JZthmSsEYRKP9uj9gH3QlLMY67Pj16ei4+0tCRz22DtvlEsnhS8MuX MBtxUw3XoW9EqwnCfAz3nNXhBYKDeL5EFz09QHD+GKpl/EmTM5LeLyFD909/q2pfqXHI wCUGWJcAyrl3hZIoSAeOnJwvj+mXDNlSNuZ3qQ0qI/kIHdRlBfSa1YUuGWnCNB/yqUMs RjhWz4BBC70Sbzn2lfJxg7NtxBFw2AuVMca0KtihdRfxu2aAqHiBWeK8SgHZI9119qYd E2ktEM2CiTomliKRAl9aiqZxDSdtF2jOGpblq4TUFlooQwWmPRf+4tVDAQ0nGXpPCCnL Vdkw== X-Gm-Message-State: AOAM533ZokRFYAZwhcAPsLnjuVPisdRIjNuHgxYNf4wQuyYNx+6ZTXFQ rxHwAwa/ANOU12r6N9NZbjo= X-Google-Smtp-Source: ABdhPJyJs5pIz6PtItBV8LByozeHE3+Y2JAq1Y3xez5XhPx/xv0/af25A3JQ270fNlULZmbg2wwglg== X-Received: by 2002:aa7:c246:: with SMTP id y6mr409772edo.335.1628544948142; Mon, 09 Aug 2021 14:35:48 -0700 (PDT) Received: from localhost.localdomain ([2a04:241e:502:1d80:688d:23e:82c6:84aa]) by smtp.gmail.com with ESMTPSA id v24sm5542932edt.41.2021.08.09.14.35.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Aug 2021 14:35:47 -0700 (PDT) From: Leonard Crestez To: Eric Dumazet , "David S. Miller" , Herbert Xu , Kuniyuki Iwashima , David Ahern Cc: Hideaki YOSHIFUJI , Jakub Kicinski , Yuchung Cheng , Francesco Ruggeri , Mat Martineau , Christoph Paasch , Ivan Delalande , Priyaranjan Jha , Menglong Dong , linux-kernel@vger.kernel.org, linux-crypto@vger.kernel.org, netdev@vger.kernel.org Subject: [RFCv2 1/9] tcp: authopt: Initial support and key management Date: Tue, 10 Aug 2021 00:35:30 +0300 Message-Id: <67c1471683200188b96a3f712dd2e8def7978462.1628544649.git.cdleonard@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC This commit add support to add and remove keys but does not use them further. Similar to tcp md5 a single point to a struct tcp_authopt_info* struct is added to struct tcp_sock in order to avoid increasing memory usage for everybody. The data structures related to tcp_authopt are initialized on setsockopt and only removed on socket close. Signed-off-by: Leonard Crestez --- include/linux/tcp.h | 6 ++ include/net/tcp.h | 1 + include/net/tcp_authopt.h | 55 ++++++++++++ include/uapi/linux/tcp.h | 72 ++++++++++++++++ net/ipv4/Kconfig | 14 ++++ net/ipv4/Makefile | 1 + net/ipv4/tcp.c | 27 ++++++ net/ipv4/tcp_authopt.c | 172 ++++++++++++++++++++++++++++++++++++++ net/ipv4/tcp_ipv4.c | 2 + 9 files changed, 350 insertions(+) create mode 100644 include/net/tcp_authopt.h create mode 100644 net/ipv4/tcp_authopt.c diff --git a/include/linux/tcp.h b/include/linux/tcp.h index 48d8a363319e..cfddfc720b00 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -140,10 +140,12 @@ struct tcp_request_sock { static inline struct tcp_request_sock *tcp_rsk(const struct request_sock *req) { return (struct tcp_request_sock *)req; } +struct tcp_authopt_info; + struct tcp_sock { /* inet_connection_sock has to be the first member of tcp_sock */ struct inet_connection_sock inet_conn; u16 tcp_header_len; /* Bytes of tcp header to send */ u16 gso_segs; /* Max number of segs per GSO packet */ @@ -403,10 +405,14 @@ struct tcp_sock { /* TCP MD5 Signature Option information */ struct tcp_md5sig_info __rcu *md5sig_info; #endif +#ifdef CONFIG_TCP_AUTHOPT + struct tcp_authopt_info __rcu *authopt_info; +#endif + /* TCP fastopen related information */ struct tcp_fastopen_request *fastopen_req; /* fastopen_rsk points to request_sock that resulted in this big * socket. Used to retransmit SYNACKs etc. */ diff --git a/include/net/tcp.h b/include/net/tcp.h index 3166dc15d7d6..bb76554e8fe5 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -182,10 +182,11 @@ void tcp_time_wait(struct sock *sk, int state, int timeo); #define TCPOPT_WINDOW 3 /* Window scaling */ #define TCPOPT_SACK_PERM 4 /* SACK Permitted */ #define TCPOPT_SACK 5 /* SACK Block */ #define TCPOPT_TIMESTAMP 8 /* Better RTT estimations/PAWS */ #define TCPOPT_MD5SIG 19 /* MD5 Signature (RFC2385) */ +#define TCPOPT_AUTHOPT 29 /* Auth Option (RFC5925) */ #define TCPOPT_MPTCP 30 /* Multipath TCP (RFC6824) */ #define TCPOPT_FASTOPEN 34 /* Fast open (RFC7413) */ #define TCPOPT_EXP 254 /* Experimental */ /* Magic number to be after the option value for sharing TCP * experimental options. See draft-ietf-tcpm-experimental-options-00.txt diff --git a/include/net/tcp_authopt.h b/include/net/tcp_authopt.h new file mode 100644 index 000000000000..458d108bb7a8 --- /dev/null +++ b/include/net/tcp_authopt.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +#ifndef _LINUX_TCP_AUTHOPT_H +#define _LINUX_TCP_AUTHOPT_H + +#include + +/* Representation of a Master Key Tuple as per RFC5925 */ +struct tcp_authopt_key_info { + struct hlist_node node; + /* Local identifier */ + u32 local_id; + u32 flags; + /* Wire identifiers */ + u8 send_id, recv_id; + u8 alg_id; + u8 keylen; + u8 key[TCP_AUTHOPT_MAXKEYLEN]; + struct rcu_head rcu; + struct sockaddr_storage addr; +}; + +/* Per-socket information regarding tcp_authopt */ +struct tcp_authopt_info { + /* List of tcp_authopt_key_info */ + struct hlist_head head; + u32 flags; + u32 src_isn; + u32 dst_isn; + struct rcu_head rcu; +}; + +#ifdef CONFIG_TCP_AUTHOPT +void tcp_authopt_clear(struct sock *sk); +int tcp_set_authopt(struct sock *sk, sockptr_t optval, unsigned int optlen); +int tcp_get_authopt_val(struct sock *sk, struct tcp_authopt *key); +int tcp_set_authopt_key(struct sock *sk, sockptr_t optval, unsigned int optlen); +#else +static inline int tcp_set_authopt(struct sock *sk, sockptr_t optval, unsigned int optlen) +{ + return -ENOPROTOOPT; +} +static inline int tcp_get_authopt_val(struct sock *sk, struct tcp_authopt *key) +{ + return -ENOPROTOOPT; +} +static inline void tcp_authopt_clear(struct sock *sk) +{ +} +static inline int tcp_set_authopt_key(struct sock *sk, sockptr_t optval, unsigned int optlen) +{ + return -ENOPROTOOPT; +} +#endif + +#endif /* _LINUX_TCP_AUTHOPT_H */ diff --git a/include/uapi/linux/tcp.h b/include/uapi/linux/tcp.h index 8fc09e8638b3..bc47664156eb 100644 --- a/include/uapi/linux/tcp.h +++ b/include/uapi/linux/tcp.h @@ -126,10 +126,12 @@ enum { #define TCP_INQ 36 /* Notify bytes available to read as a cmsg on read */ #define TCP_CM_INQ TCP_INQ #define TCP_TX_DELAY 37 /* delay outgoing packets by XX usec */ +#define TCP_AUTHOPT 38 /* TCP Authentication Option (RFC2385) */ +#define TCP_AUTHOPT_KEY 39 /* TCP Authentication Option update key (RFC2385) */ #define TCP_REPAIR_ON 1 #define TCP_REPAIR_OFF 0 #define TCP_REPAIR_OFF_NO_WP -1 /* Turn off without window probes */ @@ -340,10 +342,80 @@ struct tcp_diag_md5sig { __u16 tcpm_keylen; __be32 tcpm_addr[4]; __u8 tcpm_key[TCP_MD5SIG_MAXKEYLEN]; }; +/** + * enum tcp_authopt_flag - flags for `tcp_authopt.flags` + */ +enum tcp_authopt_flag { + /** + * @TCP_AUTHOPT_FLAG_REJECT_UNEXPECTED: + * Configure behavior of segments with TCP-AO coming from hosts for which no + * key is configured. The default recommended by RFC is to silently accept + * such connections. + */ + TCP_AUTHOPT_FLAG_REJECT_UNEXPECTED = (1 << 2), +}; + +/** + * struct tcp_authopt - Per-socket options related to TCP Authentication Option + */ +struct tcp_authopt { + /** @flags: Combination of &enum tcp_authopt_flag */ + __u32 flags; +}; + +/** + * enum tcp_authopt_key_flag - flags for `tcp_authopt.flags` + * + * @TCP_AUTHOPT_KEY_DEL: Delete the key by local_id and ignore all other fields. + * @TCP_AUTHOPT_KEY_EXCLUDE_OPTS: Exclude TCP options from signature. + * @TCP_AUTHOPT_KEY_ADDR_BIND: Key only valid for `tcp_authopt.addr` + */ +enum tcp_authopt_key_flag { + TCP_AUTHOPT_KEY_DEL = (1 << 0), + TCP_AUTHOPT_KEY_EXCLUDE_OPTS = (1 << 1), + TCP_AUTHOPT_KEY_ADDR_BIND = (1 << 2), +}; + +/* for TCP_AUTHOPT_KEY socket option */ +#define TCP_AUTHOPT_MAXKEYLEN 80 + +enum tcp_authopt_alg { + TCP_AUTHOPT_ALG_HMAC_SHA_1_96 = 1, + TCP_AUTHOPT_ALG_AES_128_CMAC_96 = 2, +}; + +/** + * struct tcp_authopt_key - TCP Authentication KEY + * + * Each key is identified by a non-zero local_id which is managed by the application. + */ +struct tcp_authopt_key { + /** @flags: Combination of &enum tcp_authopt_key_flag */ + __u32 flags; + /** @local_id: Local identifier */ + __u32 local_id; + /** @send_id: keyid value for send */ + __u8 send_id; + /** @recv_id: keyid value for receive */ + __u8 recv_id; + /** @alg: One of &enum tcp_authopt_alg */ + __u8 alg; + /** @keylen: Length of the key buffer */ + __u8 keylen; + /** @key: Secret key */ + __u8 key[TCP_AUTHOPT_MAXKEYLEN]; + /** + * @addr: Key is only valid for this address + * + * Ignored unless TCP_AUTHOPT_KEY_ADDR_BIND flag is set + */ + struct __kernel_sockaddr_storage addr; +}; + /* setsockopt(fd, IPPROTO_TCP, TCP_ZEROCOPY_RECEIVE, ...) */ #define TCP_RECEIVE_ZEROCOPY_FLAG_TLB_CLEAN_HINT 0x1 struct tcp_zerocopy_receive { __u64 address; /* in: address of mapping */ diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig index 87983e70f03f..6459f4ea6f1d 100644 --- a/net/ipv4/Kconfig +++ b/net/ipv4/Kconfig @@ -740,5 +740,19 @@ config TCP_MD5SIG RFC2385 specifies a method of giving MD5 protection to TCP sessions. Its main (only?) use is to protect BGP sessions between core routers on the Internet. If unsure, say N. + +config TCP_AUTHOPT + bool "TCP: Authentication Option support (RFC5925)" + select CRYPTO + select CRYPTO_SHA1 + select CRYPTO_HMAC + select CRYPTO_AES + select CRYPTO_CMAC + help + RFC5925 specifies a new method of giving protection to TCP sessions. + Its intended use is to protect BGP sessions between core routers + on the Internet. It obsoletes TCP MD5 (RFC2385) but is incompatible. + + If unsure, say N. diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile index bbdd9c44f14e..d336f32ce177 100644 --- a/net/ipv4/Makefile +++ b/net/ipv4/Makefile @@ -59,10 +59,11 @@ obj-$(CONFIG_TCP_CONG_NV) += tcp_nv.o obj-$(CONFIG_TCP_CONG_VENO) += tcp_veno.o obj-$(CONFIG_TCP_CONG_SCALABLE) += tcp_scalable.o obj-$(CONFIG_TCP_CONG_LP) += tcp_lp.o obj-$(CONFIG_TCP_CONG_YEAH) += tcp_yeah.o obj-$(CONFIG_TCP_CONG_ILLINOIS) += tcp_illinois.o +obj-$(CONFIG_TCP_AUTHOPT) += tcp_authopt.o obj-$(CONFIG_NET_SOCK_MSG) += tcp_bpf.o obj-$(CONFIG_BPF_SYSCALL) += udp_bpf.o obj-$(CONFIG_NETLABEL) += cipso_ipv4.o obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \ diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index f931def6302e..fd90e80afa2c 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -271,10 +271,11 @@ #include #include #include #include +#include #include #include #include #include @@ -3573,10 +3574,16 @@ static int do_tcp_setsockopt(struct sock *sk, int level, int optname, case TCP_MD5SIG: case TCP_MD5SIG_EXT: err = tp->af_specific->md5_parse(sk, optname, optval, optlen); break; #endif + case TCP_AUTHOPT: + err = tcp_set_authopt(sk, optval, optlen); + break; + case TCP_AUTHOPT_KEY: + err = tcp_set_authopt_key(sk, optval, optlen); + break; case TCP_USER_TIMEOUT: /* Cap the max time in ms TCP will retry or probe the window * before giving up and aborting (ETIMEDOUT) a connection. */ if (val < 0) @@ -4219,10 +4226,30 @@ static int do_tcp_getsockopt(struct sock *sk, int level, if (!err && copy_to_user(optval, &zc, len)) err = -EFAULT; return err; } #endif +#ifdef CONFIG_TCP_AUTHOPT + case TCP_AUTHOPT: { + struct tcp_authopt info; + + if (get_user(len, optlen)) + return -EFAULT; + + lock_sock(sk); + tcp_get_authopt_val(sk, &info); + release_sock(sk); + + len = min_t(unsigned int, len, sizeof(info)); + if (put_user(len, optlen)) + return -EFAULT; + if (copy_to_user(optval, &info, len)) + return -EFAULT; + return 0; + } +#endif + default: return -ENOPROTOOPT; } if (put_user(len, optlen)) diff --git a/net/ipv4/tcp_authopt.c b/net/ipv4/tcp_authopt.c new file mode 100644 index 000000000000..5fa7bce8891b --- /dev/null +++ b/net/ipv4/tcp_authopt.c @@ -0,0 +1,172 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include +#include +#include +#include + +struct tcp_authopt_key_info *__tcp_authopt_key_info_lookup(const struct sock *sk, + struct tcp_authopt_info *info, + int key_id) +{ + struct tcp_authopt_key_info *key; + + hlist_for_each_entry_rcu(key, &info->head, node, lockdep_sock_is_held(sk)) + if (key->local_id == key_id) + return key; + + return NULL; +} + +static struct tcp_authopt_info *__tcp_authopt_info_get_or_create(struct sock *sk) +{ + struct tcp_sock *tp = tcp_sk(sk); + struct tcp_authopt_info *info; + + info = rcu_dereference_check(tp->authopt_info, lockdep_sock_is_held(sk)); + if (info) + return info; + + info = kmalloc(sizeof(*info), GFP_KERNEL | __GFP_ZERO); + if (!info) + return ERR_PTR(-ENOMEM); + + sk_nocaps_add(sk, NETIF_F_GSO_MASK); + INIT_HLIST_HEAD(&info->head); + rcu_assign_pointer(tp->authopt_info, info); + + return info; +} + +int tcp_set_authopt(struct sock *sk, sockptr_t optval, unsigned int optlen) +{ + struct tcp_authopt opt; + struct tcp_authopt_info *info; + + WARN_ON(!lockdep_sock_is_held(sk)); + + /* If userspace optlen is too short fill the rest with zeros */ + if (optlen > sizeof(opt)) + return -EINVAL; + memset(&opt, 0, sizeof(opt)); + if (copy_from_sockptr(&opt, optval, optlen)) + return -EFAULT; + + info = __tcp_authopt_info_get_or_create(sk); + if (IS_ERR(info)) + return PTR_ERR(info); + + info->flags = opt.flags & TCP_AUTHOPT_FLAG_REJECT_UNEXPECTED); + + return 0; +} + +int tcp_get_authopt_val(struct sock *sk, struct tcp_authopt *opt) +{ + struct tcp_sock *tp = tcp_sk(sk); + struct tcp_authopt_info *info; + + WARN_ON(!lockdep_sock_is_held(sk)); + memset(opt, 0, sizeof(*opt)); + info = rcu_dereference_check(tp->authopt_info, lockdep_sock_is_held(sk)); + if (!info) + return -EINVAL; + opt->flags = info->flags & TCP_AUTHOPT_FLAG_REJECT_UNEXPECTED; + + return 0; +} + +static void tcp_authopt_key_del(struct sock *sk, + struct tcp_authopt_info *info, + struct tcp_authopt_key_info *key) +{ + hlist_del_rcu(&key->node); + atomic_sub(sizeof(*key), &sk->sk_omem_alloc); + kfree_rcu(key, rcu); +} + +/* free info and keys but don't touch tp->authopt_info */ +void __tcp_authopt_info_free(struct sock *sk, struct tcp_authopt_info *info) +{ + struct hlist_node *n; + struct tcp_authopt_key_info *key; + + hlist_for_each_entry_safe(key, n, &info->head, node) + tcp_authopt_key_del(sk, info, key); + kfree_rcu(info, rcu); +} + +/* free everything and clear tcp_sock.authopt_info to NULL */ +void tcp_authopt_clear(struct sock *sk) +{ + struct tcp_authopt_info *info; + + info = rcu_dereference_protected(tcp_sk(sk)->authopt_info, lockdep_sock_is_held(sk)); + if (info) { + __tcp_authopt_info_free(sk, info); + tcp_sk(sk)->authopt_info = NULL; + } +} + +int tcp_set_authopt_key(struct sock *sk, sockptr_t optval, unsigned int optlen) +{ + struct tcp_authopt_key opt; + struct tcp_authopt_info *info; + struct tcp_authopt_key_info *key_info; + + /* If userspace optlen is too short fill the rest with zeros */ + if (optlen > sizeof(opt)) + return -EINVAL; + memset(&opt, 0, sizeof(opt)); + if (copy_from_sockptr(&opt, optval, optlen)) + return -EFAULT; + + if (opt.keylen > TCP_AUTHOPT_MAXKEYLEN) + return -EINVAL; + + if (opt.local_id == 0) + return -EINVAL; + + /* Delete is a special case: we ignore all fields other than local_id */ + if (opt.flags & TCP_AUTHOPT_KEY_DEL) { + info = rcu_dereference_check(tcp_sk(sk)->authopt_info, lockdep_sock_is_held(sk)); + if (!info) + return -ENOENT; + key_info = __tcp_authopt_key_info_lookup(sk, info, opt.local_id); + if (!key_info) + return -ENOENT; + tcp_authopt_key_del(sk, info, key_info); + return 0; + } + + /* Initialize tcp_authopt_info if not already set */ + info = __tcp_authopt_info_get_or_create(sk); + if (IS_ERR(info)) + return PTR_ERR(info); + + /* check key family */ + if (opt.flags & TCP_AUTHOPT_KEY_ADDR_BIND) { + if (sk->sk_family != opt.addr.ss_family) + return -EINVAL; + } + + /* If an old value exists for same local_id it is deleted */ + key_info = __tcp_authopt_key_info_lookup(sk, info, opt.local_id); + if (key_info) + tcp_authopt_key_del(sk, info, key_info); + key_info = sock_kmalloc(sk, sizeof(*key_info), GFP_KERNEL | __GFP_ZERO); + if (!key_info) + return -ENOMEM; + key_info->local_id = opt.local_id; + key_info->flags = opt.flags & (TCP_AUTHOPT_KEY_EXCLUDE_OPTS | TCP_AUTHOPT_KEY_ADDR_BIND); + key_info->send_id = opt.send_id; + key_info->recv_id = opt.recv_id; + key_info->alg_id = opt.alg; + key_info->keylen = opt.keylen; + memcpy(key_info->key, opt.key, opt.keylen); + memcpy(&key_info->addr, &opt.addr, sizeof(key_info->addr)); + hlist_add_head_rcu(&key_info->node, &info->head); + + return 0; +} diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 2e62e0d6373a..1348615c7576 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -60,10 +60,11 @@ #include #include #include #include +#include #include #include #include #include #include @@ -2256,10 +2257,11 @@ void tcp_v4_destroy_sock(struct sock *sk) tcp_clear_md5_list(sk); kfree_rcu(rcu_dereference_protected(tp->md5sig_info, 1), rcu); tp->md5sig_info = NULL; } #endif + tcp_authopt_clear(sk); /* Clean up a referenced TCP bind bucket. */ if (inet_csk(sk)->icsk_bind_hash) inet_put_port(sk); From patchwork Mon Aug 9 21:35:31 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leonard Crestez X-Patchwork-Id: 12427323 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id E66C8C43216 for ; Mon, 9 Aug 2021 21:35:57 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C78D960E09 for ; Mon, 9 Aug 2021 21:35:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236485AbhHIVgQ (ORCPT ); Mon, 9 Aug 2021 17:36:16 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58586 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236431AbhHIVgM (ORCPT ); Mon, 9 Aug 2021 17:36:12 -0400 Received: from mail-ed1-x529.google.com (mail-ed1-x529.google.com [IPv6:2a00:1450:4864:20::529]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 27BEAC0613D3; Mon, 9 Aug 2021 14:35:51 -0700 (PDT) Received: by mail-ed1-x529.google.com with SMTP id z11so26792688edb.11; Mon, 09 Aug 2021 14:35:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=xTuLF9iVakUmuqWJrh4h5lRJip3NOmzubsD/v0KQcZA=; b=OBPJ0qXOXuC8Q2RURZH5gWPAOhnjSas8fv7kEniK06s2zzigGPhoNyIcuhNZmPQNWB cyDZWQg/C9ZcsTPGVkHVCSFZdGeRIlkqoKa08+ORKV9ZuFLidfau9O7JHQck/QXUhAeU 4hTu4Gg1br5ghQ8ETMKeKvdboF+TudIEGDqGbG+vDwGGpE2Q0SGGw9Z/H0dxRCS2Yd8I 7/UUmIGcdoyKTO9HW9Ol2NvZtFHyi7UTDSDmRpWbM8JVE9LXnT+hMfsvP4g60yczy620 7yvnZd8DdLPR87xM98ncW2KAhQ2A4yL2kKStpa2JTCouu3otz3ErOVlMUMi8Ae2xkbFl WhdQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=xTuLF9iVakUmuqWJrh4h5lRJip3NOmzubsD/v0KQcZA=; b=E88f/J+xOJsQp0E9WQdd+l/IfcMbreXmuRjBMC1QKDE2nj3ZVyiMTMQRJ1htxfCmsG 8Q8p3TlQZ5LKZwgwr2FHGHEX0yEbF3uxoX+Cb9icBJlrNg+VsqtAyL88sc+MonYPNsOd ymtP7/FPt8+wpIYgQgJzfsNpi5illhk0MhjAjfsAvfR6hAzJE3HZuBAghSci9gcUauBf kD9yqZJspTh9nc2QTlSsRDyAhcM3aJDa3hyiLDhFtYeouPCRWLuFlWbf46iyygpHJw7T AOKTv/pODJnbE0IahiMqiRyuq8w62jN6NAOoRPX1y1vFw1SqzM1xY7ktAr94y/f04MTe WuyA== X-Gm-Message-State: AOAM5317SAt819thk8qivBx0h8LVJSPAt8fl/DJpGrsDJ5HAaBz1A7f8 7+NGbAX54yKTVP/6JbAAGRHqwGXwbvJ2zdcBVY5Q0A== X-Google-Smtp-Source: ABdhPJwTcFW1pOJ6TbegiE/FAa/N0N0L3ttk2Zvoqrtul5wnWl+kps21MPw1urobkzOMri+YY4xjnQ== X-Received: by 2002:a05:6402:1591:: with SMTP id c17mr453524edv.15.1628544949721; Mon, 09 Aug 2021 14:35:49 -0700 (PDT) Received: from localhost.localdomain ([2a04:241e:502:1d80:688d:23e:82c6:84aa]) by smtp.gmail.com with ESMTPSA id v24sm5542932edt.41.2021.08.09.14.35.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Aug 2021 14:35:49 -0700 (PDT) From: Leonard Crestez To: Eric Dumazet , "David S. Miller" , Herbert Xu , Kuniyuki Iwashima , David Ahern Cc: Hideaki YOSHIFUJI , Jakub Kicinski , Yuchung Cheng , Francesco Ruggeri , Mat Martineau , Christoph Paasch , Ivan Delalande , Priyaranjan Jha , Menglong Dong , linux-kernel@vger.kernel.org, linux-crypto@vger.kernel.org, netdev@vger.kernel.org Subject: [RFCv2 2/9] docs: Add user documentation for tcp_authopt Date: Tue, 10 Aug 2021 00:35:31 +0300 Message-Id: X-Mailer: git-send-email 2.25.1 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC The .rst documentation contains a brief description of the user interface and includes kernel-doc generated from uapi header. Signed-off-by: Leonard Crestez --- Documentation/networking/index.rst | 1 + Documentation/networking/tcp_authopt.rst | 44 ++++++++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 Documentation/networking/tcp_authopt.rst diff --git a/Documentation/networking/index.rst b/Documentation/networking/index.rst index 58bc8cd367c6..f5c324a060d8 100644 --- a/Documentation/networking/index.rst +++ b/Documentation/networking/index.rst @@ -100,10 +100,11 @@ Contents: strparser switchdev sysfs-tagging tc-actions-env-rules tcp-thin + tcp_authopt team timestamping tipc tproxy tuntap diff --git a/Documentation/networking/tcp_authopt.rst b/Documentation/networking/tcp_authopt.rst new file mode 100644 index 000000000000..484f66f41ad5 --- /dev/null +++ b/Documentation/networking/tcp_authopt.rst @@ -0,0 +1,44 @@ +.. SPDX-License-Identifier: GPL-2.0 + +========================= +TCP Authentication Option +========================= + +The TCP Authentication option specified by RFC5925 replaces the TCP MD5 +Signature option. It similar in goals but not compatible in either wire formats +or ABI. + +Interface +========= + +Individual keys can be added to or removed from a TCP socket by using +TCP_AUTHOPT_KEY setsockopt and a ``struct tcp_authopt_key``. There is no +support for reading back keys and updates always replace the old key. These +structures represent "Master Key Tuples (MKTs)" as described by the RFC. + +Per-socket options can set or read using the TCP_AUTHOPT sockopt and a ``struct +tcp_authopt``. This is optional: doing setsockopt TCP_AUTHOPT_KEY is +sufficient to enable the feature. + +Configuration associated with TCP Authentication is indepedently attached to +each TCP socket. After listen and accept the newly returned socket gets an +independent copy of relevant settings from the listen socket. + +Key binding +----------- + +Keys can be bound to remote addresses in a way that is similar to TCP_MD5. + + * The full address must match (/32 or /128) + * Ports are ignored + * Address binding is optional, by default keys match all addresses + +RFC5925 requires that key ids do not overlap when tcp identifiers (addr/port) +overlap. This is not enforced by linux, configuring ambiguous keys will result +in packet drops and lost connections. + +ABI Reference +============= + +.. kernel-doc:: include/uapi/linux/tcp.h + :identifiers: tcp_authopt tcp_authopt_flag tcp_authopt_key tcp_authopt_key_flag tcp_authopt_alg From patchwork Mon Aug 9 21:35:32 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leonard Crestez X-Patchwork-Id: 12427329 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7C4EDC4338F for ; Mon, 9 Aug 2021 21:36:09 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 60F956023B for ; Mon, 9 Aug 2021 21:36:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236538AbhHIVgZ (ORCPT ); Mon, 9 Aug 2021 17:36:25 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58604 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236464AbhHIVgO (ORCPT ); Mon, 9 Aug 2021 17:36:14 -0400 Received: from mail-ed1-x530.google.com (mail-ed1-x530.google.com [IPv6:2a00:1450:4864:20::530]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 10A69C06179A; Mon, 9 Aug 2021 14:35:53 -0700 (PDT) Received: by mail-ed1-x530.google.com with SMTP id f13so26778057edq.13; Mon, 09 Aug 2021 14:35:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=fasABbnv0ss+6Ti472SFTrit1e7cgBKyXjzgRW209bE=; b=OxsBFjhd43xtBK276GdVF+4UfZJ3GgjuE396jxCJVnnZ0Sx49cbjilCv24aySNsr0e 3eP8QEYE7DinNTYA8Mu3ak6iocY9xkaYBxxec8wUccDxx8mcgAtXg3Ljo7LK2YR+oBMQ Bh2iZZQRA0NZzpt43WxpUPZc3hnCHtgzKA7U6n6OyTLPYRuqAjdKGF9hPHKknn+6G6tX E9Zayxek6bHp2ZIexcnsmiVWU47oj8+qfhWYsRNYr7CP1SLSfdcYpAbNRFVqCs1gHabm ELA2u+hsJt2EMXeVsSXpngAwDxl62JfdcaaCSd2V9pmpOBRx7anwaowAjmg22Fk7+EbK KQ1w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=fasABbnv0ss+6Ti472SFTrit1e7cgBKyXjzgRW209bE=; b=ZF2RUmpjRdiOSrWRxJSPkXNcB9rES78uvfgV1JYNwqK/v71z3hX0lF/108QdvOmAs8 o44UZJ9cciPxqWbwNRuqXVk7pZOJcdFD4vvDg7+MiYWzzVKirPQxFdc2In1tzowjOwnz sHOi7HywKLOH/WHSUa+baTKkotqAmO0X/TpCyP0gFPIcSk8QY7pJddw3oiE/IbVUo094 BLmHRqE60n0EgrzRKU4i3mA5APYIWMGk3XiOh6xXXhXyTY0MfqlS8rFj/psd4ssWUZMI 7z+/1OQgiFkkxciBhn0CbwM72t/HfqQlU78vGGKfpGAhg6Q5oTyoNt1WNleKZf4HNEPm ZQqw== X-Gm-Message-State: AOAM530VWuklXcg2F4ZJmwaeJwLMDat9pSt2rULtuL5luFlZ/TDQPhUc xPHkLCJmaBHqh4MCIPLk3zc= X-Google-Smtp-Source: ABdhPJw3Qiy1bSZxtekOkTBCmgs0FQ3cgfvXHmQ/ZJJWovH+MFQn1k5JfStgdpS+6xsQpSkbECIdHQ== X-Received: by 2002:aa7:cc02:: with SMTP id q2mr493658edt.154.1628544951383; Mon, 09 Aug 2021 14:35:51 -0700 (PDT) Received: from localhost.localdomain ([2a04:241e:502:1d80:688d:23e:82c6:84aa]) by smtp.gmail.com with ESMTPSA id v24sm5542932edt.41.2021.08.09.14.35.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Aug 2021 14:35:51 -0700 (PDT) From: Leonard Crestez To: Eric Dumazet , "David S. Miller" , Herbert Xu , Kuniyuki Iwashima , David Ahern Cc: Hideaki YOSHIFUJI , Jakub Kicinski , Yuchung Cheng , Francesco Ruggeri , Mat Martineau , Christoph Paasch , Ivan Delalande , Priyaranjan Jha , Menglong Dong , linux-kernel@vger.kernel.org, linux-crypto@vger.kernel.org, netdev@vger.kernel.org Subject: [RFCv2 3/9] tcp: authopt: Add crypto initialization Date: Tue, 10 Aug 2021 00:35:32 +0300 Message-Id: X-Mailer: git-send-email 2.25.1 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC The crypto_shash API is used in order to compute packet signatures. The API comes with several unfortunate limitations: 1) Allocating a crypto_shash can sleep and must be done in user context. 2) Packet signatures must be computed in softirq context 3) Packet signatures use dynamic "traffic keys" which require exclusive access to crypto_shash for crypto_setkey. The solution is to allocate one crypto_shash for each possible cpu for each algorithm at setsockopt time. The per-cpu tfm is then borrowed from softirq context, signatures are computed and the tfm is returned. The pool for each algorithm is reference counted, initialized at setsockopt time and released in tcp_authopt_key_info's rcu callback Signed-off-by: Leonard Crestez --- include/net/tcp_authopt.h | 3 + net/ipv4/tcp_authopt.c | 177 +++++++++++++++++++++++++++++++++++++- 2 files changed, 178 insertions(+), 2 deletions(-) diff --git a/include/net/tcp_authopt.h b/include/net/tcp_authopt.h index 458d108bb7a8..bd5ba95e15de 100644 --- a/include/net/tcp_authopt.h +++ b/include/net/tcp_authopt.h @@ -2,10 +2,12 @@ #ifndef _LINUX_TCP_AUTHOPT_H #define _LINUX_TCP_AUTHOPT_H #include +struct tcp_authopt_alg_imp; + /* Representation of a Master Key Tuple as per RFC5925 */ struct tcp_authopt_key_info { struct hlist_node node; /* Local identifier */ u32 local_id; @@ -15,10 +17,11 @@ struct tcp_authopt_key_info { u8 alg_id; u8 keylen; u8 key[TCP_AUTHOPT_MAXKEYLEN]; struct rcu_head rcu; struct sockaddr_storage addr; + struct tcp_authopt_alg_imp *alg; }; /* Per-socket information regarding tcp_authopt */ struct tcp_authopt_info { /* List of tcp_authopt_key_info */ diff --git a/net/ipv4/tcp_authopt.c b/net/ipv4/tcp_authopt.c index 5fa7bce8891b..799607fc076f 100644 --- a/net/ipv4/tcp_authopt.c +++ b/net/ipv4/tcp_authopt.c @@ -4,10 +4,161 @@ #include #include #include #include +/* All current algorithms have a mac length of 12 but crypto API digestsize can be larger */ +#define TCP_AUTHOPT_MAXMACBUF 20 +#define TCP_AUTHOPT_MAX_TRAFFIC_KEY_LEN 20 + +struct tcp_authopt_alg_imp { + /* Name of algorithm in crypto-api */ + const char *alg_name; + /* One of the TCP_AUTHOPT_ALG_* constants from uapi */ + u8 alg_id; + /* Length of traffic key */ + u8 traffic_key_len; + /* Length of mac in TCP option */ + u8 maclen; + + /* shared crypto_shash */ + spinlock_t lock; + int ref_cnt; + struct crypto_shash *tfm; +}; + +static struct tcp_authopt_alg_imp tcp_authopt_alg_list[] = { + { + .alg_id = TCP_AUTHOPT_ALG_HMAC_SHA_1_96, + .alg_name = "hmac(sha1)", + .traffic_key_len = 20, + .maclen = 12, + .lock = __SPIN_LOCK_UNLOCKED(tcp_authopt_alg_list[0].lock), + }, + { + .alg_id = TCP_AUTHOPT_ALG_AES_128_CMAC_96, + .alg_name = "cmac(aes)", + .traffic_key_len = 16, + .maclen = 12, + .lock = __SPIN_LOCK_UNLOCKED(tcp_authopt_alg_list[1].lock), + }, +}; + +/* get a pointer to the tcp_authopt_alg instance or NULL if id invalid */ +static inline struct tcp_authopt_alg_imp *tcp_authopt_alg_get(int alg_num) +{ + if (alg_num <= 0 || alg_num > 2) + return NULL; + return &tcp_authopt_alg_list[alg_num - 1]; +} + +/* Mark an algorithm as in-use from user context */ +static int tcp_authopt_alg_require(struct tcp_authopt_alg_imp *alg) +{ + struct crypto_shash *tfm = NULL; + bool need_init = false; + + might_sleep(); + + /* If we're the first user then we need to initialize shash but we might lose the race. */ + spin_lock_bh(&alg->lock); + WARN_ON(alg->ref_cnt < 0); + if (alg->ref_cnt == 0) + need_init = true; + else + ++alg->ref_cnt; + spin_unlock_bh(&alg->lock); + + /* Already initialized */ + if (!need_init) + return 0; + + tfm = crypto_alloc_shash(alg->alg_name, 0, 0); + if (IS_ERR(tfm)) + return PTR_ERR(tfm); + + spin_lock_bh(&alg->lock); + if (alg->ref_cnt == 0) + /* race won */ + alg->tfm = tfm; + else + /* race lost, free tfm later */ + need_init = false; + ++alg->ref_cnt; + spin_unlock_bh(&alg->lock); + + if (!need_init) + crypto_free_shash(tfm); + else + pr_info("initialized tcp-ao %s", alg->alg_name); + + return 0; +} + +static void tcp_authopt_alg_release(struct tcp_authopt_alg_imp *alg) +{ + struct crypto_shash *tfm_to_free = NULL; + + spin_lock_bh(&alg->lock); + --alg->ref_cnt; + WARN_ON(alg->ref_cnt < 0); + if (alg->ref_cnt == 0) { + tfm_to_free = alg->tfm; + alg->tfm = NULL; + } + spin_unlock_bh(&alg->lock); + + if (tfm_to_free) { + pr_info("released tcp-ao %s", alg->alg_name); + crypto_free_shash(tfm_to_free); + } +} + +/* increase reference count on an algorithm that is already in use */ +static void tcp_authopt_alg_incref(struct tcp_authopt_alg_imp *alg) +{ + spin_lock_bh(&alg->lock); + WARN_ON(alg->ref_cnt <= 0); + ++alg->ref_cnt; + spin_unlock_bh(&alg->lock); +} + +static struct crypto_shash *tcp_authopt_alg_get_tfm(struct tcp_authopt_alg_imp *alg) +{ + spin_lock_bh(&alg->lock); + WARN_ON(alg->ref_cnt < 0); + return alg->tfm; +} + +static void tcp_authopt_alg_put_tfm(struct tcp_authopt_alg_imp *alg, struct crypto_shash *tfm) +{ + WARN_ON(tfm != alg->tfm); + spin_unlock_bh(&alg->lock); +} + +static struct crypto_shash *tcp_authopt_get_kdf_shash(struct tcp_authopt_key_info *key) +{ + return tcp_authopt_alg_get_tfm(key->alg); +} + +static void tcp_authopt_put_kdf_shash(struct tcp_authopt_key_info *key, + struct crypto_shash *tfm) +{ + return tcp_authopt_alg_put_tfm(key->alg, tfm); +} + +static struct crypto_shash *tcp_authopt_get_mac_shash(struct tcp_authopt_key_info *key) +{ + return tcp_authopt_alg_get_tfm(key->alg); +} + +static void tcp_authopt_put_mac_shash(struct tcp_authopt_key_info *key, + struct crypto_shash *tfm) +{ + return tcp_authopt_alg_put_tfm(key->alg, tfm); +} + struct tcp_authopt_key_info *__tcp_authopt_key_info_lookup(const struct sock *sk, struct tcp_authopt_info *info, int key_id) { struct tcp_authopt_key_info *key; @@ -75,17 +226,25 @@ int tcp_get_authopt_val(struct sock *sk, struct tcp_authopt *opt) opt->flags = info->flags & TCP_AUTHOPT_FLAG_REJECT_UNEXPECTED; return 0; } +static void tcp_authopt_key_free_rcu(struct rcu_head *rcu) +{ + struct tcp_authopt_key_info *key = container_of(rcu, struct tcp_authopt_key_info, rcu); + + tcp_authopt_alg_release(key->alg); + kfree(key); +} + static void tcp_authopt_key_del(struct sock *sk, struct tcp_authopt_info *info, struct tcp_authopt_key_info *key) { hlist_del_rcu(&key->node); atomic_sub(sizeof(*key), &sk->sk_omem_alloc); - kfree_rcu(key, rcu); + call_rcu(&key->rcu, tcp_authopt_key_free_rcu); } /* free info and keys but don't touch tp->authopt_info */ void __tcp_authopt_info_free(struct sock *sk, struct tcp_authopt_info *info) { @@ -112,10 +271,12 @@ void tcp_authopt_clear(struct sock *sk) int tcp_set_authopt_key(struct sock *sk, sockptr_t optval, unsigned int optlen) { struct tcp_authopt_key opt; struct tcp_authopt_info *info; struct tcp_authopt_key_info *key_info; + struct tcp_authopt_alg_imp *alg; + int err; /* If userspace optlen is too short fill the rest with zeros */ if (optlen > sizeof(opt)) return -EINVAL; memset(&opt, 0, sizeof(opt)); @@ -149,22 +310,34 @@ int tcp_set_authopt_key(struct sock *sk, sockptr_t optval, unsigned int optlen) if (opt.flags & TCP_AUTHOPT_KEY_ADDR_BIND) { if (sk->sk_family != opt.addr.ss_family) return -EINVAL; } + /* check the algorithm */ + alg = tcp_authopt_alg_get(opt.alg); + if (!alg) + return -EINVAL; + WARN_ON(alg->alg_id != opt.alg); + err = tcp_authopt_alg_require(alg); + if (err) + return err; + /* If an old value exists for same local_id it is deleted */ key_info = __tcp_authopt_key_info_lookup(sk, info, opt.local_id); if (key_info) tcp_authopt_key_del(sk, info, key_info); key_info = sock_kmalloc(sk, sizeof(*key_info), GFP_KERNEL | __GFP_ZERO); - if (!key_info) + if (!key_info) { + tcp_authopt_alg_release(alg); return -ENOMEM; + } key_info->local_id = opt.local_id; key_info->flags = opt.flags & (TCP_AUTHOPT_KEY_EXCLUDE_OPTS | TCP_AUTHOPT_KEY_ADDR_BIND); key_info->send_id = opt.send_id; key_info->recv_id = opt.recv_id; key_info->alg_id = opt.alg; + key_info->alg = alg; key_info->keylen = opt.keylen; memcpy(key_info->key, opt.key, opt.keylen); memcpy(&key_info->addr, &opt.addr, sizeof(key_info->addr)); hlist_add_head_rcu(&key_info->node, &info->head); From patchwork Mon Aug 9 21:35:33 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leonard Crestez X-Patchwork-Id: 12427327 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6FE84C43214 for ; Mon, 9 Aug 2021 21:36:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5DFC860E09 for ; Mon, 9 Aug 2021 21:36:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236511AbhHIVgW (ORCPT ); Mon, 9 Aug 2021 17:36:22 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58598 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236480AbhHIVgP (ORCPT ); Mon, 9 Aug 2021 17:36:15 -0400 Received: from mail-ed1-x530.google.com (mail-ed1-x530.google.com [IPv6:2a00:1450:4864:20::530]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 93552C0613D3; Mon, 9 Aug 2021 14:35:54 -0700 (PDT) Received: by mail-ed1-x530.google.com with SMTP id cf5so26817410edb.2; Mon, 09 Aug 2021 14:35:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=sECuFuwNziqBea61i4S+XM2biqZXHcwLl3C80WbXApg=; b=GZB/mPEvUGNXSFNAh5fqRF7/epC6wMwJgOQq7x4N90lbj8aeiJSVpywhNTVAs6NZZD qZ/r/Wfo8VMZhEKpYeq9nx5SH48tqiemNXNYJimSrj4VYaENEqopEOjwQnXnVQc+lwUZ jtt8xicYd+nEPYHd4l5EWO4qixbB76ZLq85zfEQJcgJIz3+RwANQGXEccQMxF8UbYbUz 2y2W8UM06ffG0lHMG02a63blNHldmQsVBbTeZpVsb1pwIDvSWJQ05tPHOELEz0DV78L/ 2vIdEAvqE7Qm/sy3iP/g0eAlpqzE495r/ov8pPdq+hFDY2K5ckeTZp1ob0k9Uq2cksIG T1ow== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=sECuFuwNziqBea61i4S+XM2biqZXHcwLl3C80WbXApg=; b=QD3RQHXBuMWj8V5bzsScD1k5QhzU4Au0s+i22AAQLJ2+j5eTAsHRiDRXV1t6LxYzki yjBAuNI+F7Sssw/rHogH06fuhV1Zk5/zlnaGdGaWfetz/6deRkXlziTXvDuzp98xvNXj tdoswwcKHZJs1qOe3a9QhkcBjVSD2QtR2rx9MT0i5F7yTNok32jqj6IzMh4naujGbxNn MSM0/KdFQA8Grp/7GIQFAmXrq9Wamh23PL3XsJQ9UWfl2Yc/mmxkvdjrrRBoTnBFcZ5P 3sOtVTPaOXO5a4aY6ikyrKdNdu1gODxkHI0y5scAZGycKMR424pPes95WYHzJvTW+8UY URJw== X-Gm-Message-State: AOAM532+Ki+ABQEEbpSNVISNe6jpWzI+IKgyEGY5hxrql9BOynskc5Jn KB2Cll3oGsH10S2eMDzOP84= X-Google-Smtp-Source: ABdhPJwoJzuy9vYGILwqJnUIpMgagImeyF5oj/dWxnlhWHgSiKTJhaJ61ZwjUFPqIZhL7lg4y8evDg== X-Received: by 2002:aa7:c7d0:: with SMTP id o16mr448141eds.75.1628544953220; Mon, 09 Aug 2021 14:35:53 -0700 (PDT) Received: from localhost.localdomain ([2a04:241e:502:1d80:688d:23e:82c6:84aa]) by smtp.gmail.com with ESMTPSA id v24sm5542932edt.41.2021.08.09.14.35.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Aug 2021 14:35:52 -0700 (PDT) From: Leonard Crestez To: Eric Dumazet , "David S. Miller" , Herbert Xu , Kuniyuki Iwashima , David Ahern Cc: Hideaki YOSHIFUJI , Jakub Kicinski , Yuchung Cheng , Francesco Ruggeri , Mat Martineau , Christoph Paasch , Ivan Delalande , Priyaranjan Jha , Menglong Dong , linux-kernel@vger.kernel.org, linux-crypto@vger.kernel.org, netdev@vger.kernel.org Subject: [RFCv2 4/9] tcp: authopt: Compute packet signatures Date: Tue, 10 Aug 2021 00:35:33 +0300 Message-Id: <346319324bb9accf73b79dbb6d00017726c16508.1628544649.git.cdleonard@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC Computing tcp authopt packet signatures is a two step process: * traffic key is computed based on tcp 4-tuple, initial sequence numbers and the secret key. * packet mac is computed based on traffic key and content of individual packets. The traffic key could be cached for established sockets but it is not. A single code path exists for ipv4/ipv6 and input/output. This keeps the code short but slightly slower due to lots of conditionals. On output we read remote IP address from socket members on output, we can't use skb network header because it's computed after TCP options. On input we read remote IP address from skb network headers, we can't use socket binding members because those are not available for SYN. Signed-off-by: Leonard Crestez --- net/ipv4/tcp_authopt.c | 467 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 467 insertions(+) diff --git a/net/ipv4/tcp_authopt.c b/net/ipv4/tcp_authopt.c index 799607fc076f..a42daadf6b7d 100644 --- a/net/ipv4/tcp_authopt.c +++ b/net/ipv4/tcp_authopt.c @@ -341,5 +341,472 @@ int tcp_set_authopt_key(struct sock *sk, sockptr_t optval, unsigned int optlen) memcpy(&key_info->addr, &opt.addr, sizeof(key_info->addr)); hlist_add_head_rcu(&key_info->node, &info->head); return 0; } + +/* feed traffic key into shash */ +static int tcp_authopt_shash_traffic_key(struct shash_desc *desc, + struct sock *sk, + struct sk_buff *skb, + bool input, + bool ipv6) +{ + struct tcphdr *th = tcp_hdr(skb); + int err; + __be32 sisn, disn; + __be16 digestbits = htons(crypto_shash_digestsize(desc->tfm) * 8); + + // RFC5926 section 3.1.1.1 + err = crypto_shash_update(desc, "\x01TCP-AO", 7); + if (err) + return err; + + /* Addresses from packet on input and from socket on output + * This is because on output MAC is computed before prepending IP header + */ + if (input) { + if (ipv6) + err = crypto_shash_update(desc, (u8 *)&ipv6_hdr(skb)->saddr, 32); + else + err = crypto_shash_update(desc, (u8 *)&ip_hdr(skb)->saddr, 8); + if (err) + return err; + } else { + if (ipv6) { + struct in6_addr *saddr; + struct in6_addr *daddr; + + saddr = &sk->sk_v6_rcv_saddr; + daddr = &sk->sk_v6_daddr; + err = crypto_shash_update(desc, (u8 *)&sk->sk_v6_rcv_saddr, 16); + if (err) + return err; + err = crypto_shash_update(desc, (u8 *)&sk->sk_v6_daddr, 16); + if (err) + return err; + } else { + err = crypto_shash_update(desc, (u8 *)&sk->sk_rcv_saddr, 4); + if (err) + return err; + err = crypto_shash_update(desc, (u8 *)&sk->sk_daddr, 4); + if (err) + return err; + } + } + + /* TCP ports from header */ + err = crypto_shash_update(desc, (u8 *)&th->source, 4); + if (err) + return err; + + /* special cases for SYN and SYN/ACK */ + if (th->syn && !th->ack) { + sisn = th->seq; + disn = 0; + } else if (th->syn && th->ack) { + sisn = th->seq; + disn = htonl(ntohl(th->ack_seq) - 1); + } else { + struct tcp_authopt_info *authopt_info; + + /* Fetching authopt_info like this means it's possible that authopt_info + * was deleted while we were hashing. If that happens we drop the packet + * which should be fine. + * + * A better solution might be to always pass info as a parameter, or + * compute traffic_key for established sockets separately. + */ + rcu_read_lock(); + authopt_info = rcu_dereference(tcp_sk(sk)->authopt_info); + if (!authopt_info) { + rcu_read_unlock(); + return -EINVAL; + } + /* Initial sequence numbers for ESTABLISHED connections from info */ + if (input) { + sisn = htonl(authopt_info->dst_isn); + disn = htonl(authopt_info->src_isn); + } else { + sisn = htonl(authopt_info->src_isn); + disn = htonl(authopt_info->dst_isn); + } + rcu_read_unlock(); + } + + err = crypto_shash_update(desc, (u8 *)&sisn, 4); + if (err) + return err; + err = crypto_shash_update(desc, (u8 *)&disn, 4); + if (err) + return err; + + err = crypto_shash_update(desc, (u8 *)&digestbits, 2); + if (err) + return err; + + return 0; +} + +/* Convert a variable-length key to a 16-byte fixed-length key for AES-CMAC + * This is described in RFC5926 section 3.1.1.2 + */ +static int aes_setkey_derived(struct crypto_shash *tfm, u8 *key, size_t keylen) +{ + static const u8 zeros[16] = {0}; + u8 derived_key[16]; + int err; + + if (WARN_ON(crypto_shash_digestsize(tfm) != 16)) + return -EINVAL; + err = crypto_shash_setkey(tfm, zeros, sizeof(zeros)); + if (err) + return err; + err = crypto_shash_tfm_digest(tfm, key, keylen, derived_key); + if (err) + return err; + return crypto_shash_setkey(tfm, derived_key, sizeof(derived_key)); +} + +static int tcp_authopt_get_traffic_key(struct sock *sk, + struct sk_buff *skb, + struct tcp_authopt_key_info *key, + bool input, + bool ipv6, + u8 *traffic_key) +{ + SHASH_DESC_ON_STACK(desc, kdf_tfm); + struct crypto_shash *kdf_tfm; + int err; + + kdf_tfm = tcp_authopt_get_kdf_shash(key); + if (IS_ERR(kdf_tfm)) + return PTR_ERR(kdf_tfm); + if (WARN_ON(crypto_shash_digestsize(kdf_tfm) != key->alg->traffic_key_len)) { + err = -EINVAL; + goto out; + } + + if (key->alg_id == TCP_AUTHOPT_ALG_AES_128_CMAC_96 && key->keylen != 16) { + err = aes_setkey_derived(kdf_tfm, key->key, key->keylen); + if (err) + goto out; + } else { + err = crypto_shash_setkey(kdf_tfm, key->key, key->keylen); + if (err) + goto out; + } + + desc->tfm = kdf_tfm; + err = crypto_shash_init(desc); + if (err) + goto out; + + err = tcp_authopt_shash_traffic_key(desc, sk, skb, input, ipv6); + if (err) + goto out; + + err = crypto_shash_final(desc, traffic_key); + if (err) + goto out; + //printk("traffic_key: %*phN\n", 20, traffic_key); + +out: + tcp_authopt_put_kdf_shash(key, kdf_tfm); + return err; +} + +static int crypto_shash_update_zero(struct shash_desc *desc, int len) +{ + u8 zero = 0; + int i, err; + + for (i = 0; i < len; ++i) { + err = crypto_shash_update(desc, &zero, 1); + if (err) + return err; + } + + return 0; +} + +static int tcp_authopt_hash_tcp4_pseudoheader(struct shash_desc *desc, + __be32 saddr, + __be32 daddr, + int nbytes) +{ + struct tcp4_pseudohdr phdr = { + .saddr = saddr, + .daddr = daddr, + .pad = 0, + .protocol = IPPROTO_TCP, + .len = htons(nbytes) + }; + return crypto_shash_update(desc, (u8 *)&phdr, sizeof(phdr)); +} + +static int tcp_authopt_hash_tcp6_pseudoheader(struct shash_desc *desc, + struct in6_addr *saddr, + struct in6_addr *daddr, + u32 plen) +{ + int err; + u32 buf[2]; + + buf[0] = htonl(plen); + buf[1] = htonl(IPPROTO_TCP); + + err = crypto_shash_update(desc, (u8 *)saddr, sizeof(*saddr)); + if (err) + return err; + err = crypto_shash_update(desc, (u8 *)daddr, sizeof(*daddr)); + if (err) + return err; + return crypto_shash_update(desc, (u8 *)&buf, sizeof(buf)); +} + +/* TCP authopt as found in header */ +struct tcphdr_authopt { + u8 num; + u8 len; + u8 keyid; + u8 rnextkeyid; + u8 mac[0]; +}; + +/* Find TCP_AUTHOPT in header. + * + * Returns pointer to TCP_AUTHOPT or NULL if not found. + */ +static u8 *tcp_authopt_find_option(struct tcphdr *th) +{ + int length = (th->doff << 2) - sizeof(*th); + u8 *ptr = (u8 *)(th + 1); + + while (length >= 2) { + int opcode = *ptr++; + int opsize; + + switch (opcode) { + case TCPOPT_EOL: + return NULL; + case TCPOPT_NOP: + length--; + continue; + default: + if (length < 2) + return NULL; + opsize = *ptr++; + if (opsize < 2) + return NULL; + if (opsize > length) + return NULL; + if (opcode == TCPOPT_AUTHOPT) + return ptr - 2; + } + ptr += opsize - 2; + length -= opsize; + } + return NULL; +} + +/** Hash tcphdr options. + * If include_options is false then only the TCPOPT_AUTHOPT option itself is hashed + * Maybe we could skip option parsing by assuming the AUTHOPT header is at hash_location-4? + */ +static int tcp_authopt_hash_opts(struct shash_desc *desc, + struct tcphdr *th, + bool include_options) +{ + int err; + /* start of options */ + u8 *tcp_opts = (u8 *)(th + 1); + /* end of options */ + u8 *tcp_data = ((u8 *)th) + th->doff * 4; + /* pointer to TCPOPT_AUTHOPT */ + u8 *authopt_ptr = tcp_authopt_find_option(th); + u8 authopt_len; + + if (!authopt_ptr) + return -EINVAL; + authopt_len = *(authopt_ptr + 1); + + if (include_options) { + err = crypto_shash_update(desc, tcp_opts, authopt_ptr - tcp_opts + 4); + if (err) + return err; + err = crypto_shash_update_zero(desc, authopt_len - 4); + if (err) + return err; + err = crypto_shash_update(desc, + authopt_ptr + authopt_len, + tcp_data - (authopt_ptr + authopt_len)); + if (err) + return err; + } else { + err = crypto_shash_update(desc, authopt_ptr, 4); + if (err) + return err; + err = crypto_shash_update_zero(desc, authopt_len - 4); + if (err) + return err; + } + + return 0; +} + +static int skb_shash_frags(struct shash_desc *desc, + struct sk_buff *skb) +{ + struct sk_buff *frag_iter; + int err, i; + + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + skb_frag_t *f = &skb_shinfo(skb)->frags[i]; + u32 p_off, p_len, copied; + struct page *p; + u8 *vaddr; + + skb_frag_foreach_page(f, skb_frag_off(f), skb_frag_size(f), + p, p_off, p_len, copied) { + vaddr = kmap_atomic(p); + err = crypto_shash_update(desc, vaddr + p_off, p_len); + kunmap_atomic(vaddr); + if (err) + return err; + } + } + + skb_walk_frags(skb, frag_iter) { + err = skb_shash_frags(desc, frag_iter); + if (err) + return err; + } + + return 0; +} + +static int tcp_authopt_hash_packet(struct crypto_shash *tfm, + struct sock *sk, + struct sk_buff *skb, + bool input, + bool ipv6, + bool include_options, + u8 *macbuf) +{ + struct tcphdr *th = tcp_hdr(skb); + SHASH_DESC_ON_STACK(desc, tfm); + int err; + + /* NOTE: SNE unimplemented */ + __be32 sne = 0; + + desc->tfm = tfm; + err = crypto_shash_init(desc); + if (err) + return err; + + err = crypto_shash_update(desc, (u8 *)&sne, 4); + if (err) + return err; + + if (ipv6) { + struct in6_addr *saddr; + struct in6_addr *daddr; + + if (input) { + saddr = &ipv6_hdr(skb)->saddr; + daddr = &ipv6_hdr(skb)->daddr; + } else { + saddr = &sk->sk_v6_rcv_saddr; + daddr = &sk->sk_v6_daddr; + } + err = tcp_authopt_hash_tcp6_pseudoheader(desc, saddr, daddr, skb->len); + if (err) + return err; + } else { + __be32 saddr; + __be32 daddr; + + if (input) { + saddr = ip_hdr(skb)->saddr; + daddr = ip_hdr(skb)->daddr; + } else { + saddr = sk->sk_rcv_saddr; + daddr = sk->sk_daddr; + } + err = tcp_authopt_hash_tcp4_pseudoheader(desc, saddr, daddr, skb->len); + if (err) + return err; + } + + // TCP header with checksum set to zero + { + struct tcphdr hashed_th = *th; + + hashed_th.check = 0; + err = crypto_shash_update(desc, (u8 *)&hashed_th, sizeof(hashed_th)); + if (err) + return err; + } + + // TCP options + err = tcp_authopt_hash_opts(desc, th, include_options); + if (err) + return err; + + // Rest of SKB->data + err = crypto_shash_update(desc, (u8 *)th + th->doff * 4, skb_headlen(skb) - th->doff * 4); + if (err) + return err; + + err = skb_shash_frags(desc, skb); + if (err) + return err; + + return crypto_shash_final(desc, macbuf); +} + +int __tcp_authopt_calc_mac(struct sock *sk, + struct sk_buff *skb, + struct tcp_authopt_key_info *key, + bool input, + char *macbuf) +{ + struct crypto_shash *mac_tfm; + u8 traffic_key[TCP_AUTHOPT_MAX_TRAFFIC_KEY_LEN]; + int err; + bool ipv6 = (sk->sk_family != AF_INET); + + if (sk->sk_family != AF_INET && sk->sk_family != AF_INET6) + return -EINVAL; + if (WARN_ON(key->alg->traffic_key_len > sizeof(traffic_key))) + return -ENOBUFS; + + err = tcp_authopt_get_traffic_key(sk, skb, key, input, ipv6, traffic_key); + if (err) + return err; + + mac_tfm = tcp_authopt_get_mac_shash(key); + if (IS_ERR(mac_tfm)) + return PTR_ERR(mac_tfm); + if (crypto_shash_digestsize(mac_tfm) > TCP_AUTHOPT_MAXMACBUF) { + err = -EINVAL; + goto out; + } + err = crypto_shash_setkey(mac_tfm, traffic_key, key->alg->traffic_key_len); + if (err) + goto out; + + err = tcp_authopt_hash_packet(mac_tfm, + sk, + skb, + input, + ipv6, + !(key->flags & TCP_AUTHOPT_KEY_EXCLUDE_OPTS), + macbuf); + //printk("mac: %*phN\n", key->maclen, macbuf); + +out: + tcp_authopt_put_mac_shash(key, mac_tfm); + return err; +} From patchwork Mon Aug 9 21:35:34 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leonard Crestez X-Patchwork-Id: 12427331 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 628A6C4320E for ; Mon, 9 Aug 2021 21:36:11 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 45B9F606A5 for ; Mon, 9 Aug 2021 21:36:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236559AbhHIVga (ORCPT ); Mon, 9 Aug 2021 17:36:30 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58618 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236489AbhHIVgR (ORCPT ); Mon, 9 Aug 2021 17:36:17 -0400 Received: from mail-ed1-x536.google.com (mail-ed1-x536.google.com [IPv6:2a00:1450:4864:20::536]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5700DC061796; Mon, 9 Aug 2021 14:35:56 -0700 (PDT) Received: by mail-ed1-x536.google.com with SMTP id by4so8069080edb.0; Mon, 09 Aug 2021 14:35:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=jwg/vlMjLeqvnzKvhuAvM489DRXjR5AM0zPOQaopkAM=; b=U7rXbzLgI7rCzUkZmArmJGz6d3kZ/uGPQ8DuU+I+R6GW3gaSzf6BX0q3LycRrVdGjd EMek1OE1jFPL46BxtuZikhguMKqmuCt5rXclhZY0BipENVnM2kOVEkdVNqwXfvAOhTbs +TWfU2KbWGskE3wOrzIbGW9piCJj6Rv2ZqtnScPimjE3kQt3c29y0PzzHm6J1O+vt6d7 BP6Kc7Q/ocob9yzkQguZ7mo4lbeRQFCjpQS3HX+aDuIS41z1WEw9pAlv9ADSlDFAFiMA OyDz5RTxKxKJoWxVY1tN99N1cG58RwiCGmzWv5ykx3yHp08RiUkaYEE0vkn2Ckw/IxXh FY0Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=jwg/vlMjLeqvnzKvhuAvM489DRXjR5AM0zPOQaopkAM=; b=VBZyluPXSyKneFGENNM2IzSxwvZEqgNDCO+FWBIcgdBFKXeaLhriOJr60SJDyCWeWK 1nmb5EyXpgdX68SyayLd9pzKscM9PaiibXJnmyC299i/t9k0iq9X+7lbli5B1iyAcGMo PJxBsWMTEG/g+pHVBqq1WBUy0a0qPoJ3OZQO5effrwgJsh2+0sziNtoHKQS+WD7sNMjS lizxMbwaaBPBhZGprvScg0I9BiRdSvLksf8ntVjNpJheJUGjVVCyb4hl5+pKXVEJE61U ccf2kJpxTAXD6ZzMIECJl2DW62pWy17qG7q8MT42U5h93FffBNbezsKxnlaWCcaNdgjp JJjg== X-Gm-Message-State: AOAM531gASASWPWPRn+1yQTfIDHao3GqhJT3zQlY9l/K4PBxNbxem3Kn qCTdvAwPVVr1qya0zTu92Cs= X-Google-Smtp-Source: ABdhPJwfdDlOw/JIChnvUlsK4HmbwACkFuhpXdoHne0/WCxITRL/k851OzuES6BP5vJ9vtIKektKhQ== X-Received: by 2002:aa7:d757:: with SMTP id a23mr458430eds.29.1628544954877; Mon, 09 Aug 2021 14:35:54 -0700 (PDT) Received: from localhost.localdomain ([2a04:241e:502:1d80:688d:23e:82c6:84aa]) by smtp.gmail.com with ESMTPSA id v24sm5542932edt.41.2021.08.09.14.35.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Aug 2021 14:35:54 -0700 (PDT) From: Leonard Crestez To: Eric Dumazet , "David S. Miller" , Herbert Xu , Kuniyuki Iwashima , David Ahern Cc: Hideaki YOSHIFUJI , Jakub Kicinski , Yuchung Cheng , Francesco Ruggeri , Mat Martineau , Christoph Paasch , Ivan Delalande , Priyaranjan Jha , Menglong Dong , linux-kernel@vger.kernel.org, linux-crypto@vger.kernel.org, netdev@vger.kernel.org Subject: [RFCv2 5/9] tcp: authopt: Hook into tcp core Date: Tue, 10 Aug 2021 00:35:34 +0300 Message-Id: <28ccc211be7d2886b6c2a287a6fcfd55ee3b6e2b.1628544649.git.cdleonard@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC The tcp_authopt features exposes a minimal interface to the rest of the TCP stack. Only a few functions are exposed and if the feature is disabled they return neutral values, avoiding ifdefs in the rest of the code. Add calls into tcp authopt from send, receive and accept code. Signed-off-by: Leonard Crestez --- include/net/tcp_authopt.h | 55 +++++++++ net/ipv4/tcp_authopt.c | 227 ++++++++++++++++++++++++++++++++++++++ net/ipv4/tcp_input.c | 17 +++ net/ipv4/tcp_ipv4.c | 3 + net/ipv4/tcp_minisocks.c | 2 + net/ipv4/tcp_output.c | 56 +++++++++- net/ipv6/tcp_ipv6.c | 4 + 7 files changed, 363 insertions(+), 1 deletion(-) diff --git a/include/net/tcp_authopt.h b/include/net/tcp_authopt.h index bd5ba95e15de..28ebc77473a4 100644 --- a/include/net/tcp_authopt.h +++ b/include/net/tcp_authopt.h @@ -15,10 +15,11 @@ struct tcp_authopt_key_info { /* Wire identifiers */ u8 send_id, recv_id; u8 alg_id; u8 keylen; u8 key[TCP_AUTHOPT_MAXKEYLEN]; + u8 maclen; struct rcu_head rcu; struct sockaddr_storage addr; struct tcp_authopt_alg_imp *alg; }; @@ -31,15 +32,52 @@ struct tcp_authopt_info { u32 dst_isn; struct rcu_head rcu; }; #ifdef CONFIG_TCP_AUTHOPT +struct tcp_authopt_key_info *tcp_authopt_select_key(const struct sock *sk, + const struct sock *addr_sk, + u8 *rnextkeyid); void tcp_authopt_clear(struct sock *sk); int tcp_set_authopt(struct sock *sk, sockptr_t optval, unsigned int optlen); int tcp_get_authopt_val(struct sock *sk, struct tcp_authopt *key); int tcp_set_authopt_key(struct sock *sk, sockptr_t optval, unsigned int optlen); +int tcp_authopt_hash( + char *hash_location, + struct tcp_authopt_key_info *key, + struct sock *sk, struct sk_buff *skb); +int __tcp_authopt_openreq(struct sock *newsk, const struct sock *oldsk, struct request_sock *req); +static inline int tcp_authopt_openreq( + struct sock *newsk, + const struct sock *oldsk, + struct request_sock *req) +{ + if (!rcu_dereference(tcp_sk(oldsk)->authopt_info)) + return 0; + else + return __tcp_authopt_openreq(newsk, oldsk, req); +} +int __tcp_authopt_inbound_check( + struct sock *sk, + struct sk_buff *skb, + struct tcp_authopt_info *info); +static inline int tcp_authopt_inbound_check(struct sock *sk, struct sk_buff *skb) +{ + struct tcp_authopt_info *info = rcu_dereference(tcp_sk(sk)->authopt_info); + + if (info) + return __tcp_authopt_inbound_check(sk, skb, info); + else + return 0; +} #else +static struct tcp_authopt_key_info *tcp_authopt_select_key(const struct sock *sk, + const struct sock *addr_sk, + u8 *rnextkeyid); +{ + return NULL; +} static inline int tcp_set_authopt(struct sock *sk, sockptr_t optval, unsigned int optlen) { return -ENOPROTOOPT; } static inline int tcp_get_authopt_val(struct sock *sk, struct tcp_authopt *key) @@ -51,8 +89,25 @@ static inline void tcp_authopt_clear(struct sock *sk) } static inline int tcp_set_authopt_key(struct sock *sk, sockptr_t optval, unsigned int optlen) { return -ENOPROTOOPT; } +static inline int tcp_authopt_hash( + char *hash_location, + struct tcp_authopt_key_info *key, + struct sock *sk, struct sk_buff *skb) +{ + return -EINVAL; +} +static inline int tcp_authopt_openreq(struct sock *newsk, + const struct sock *oldsk, + struct request_sock *req) +{ + return 0; +} +static inline int tcp_authopt_inbound_check(struct sock *sk, struct sk_buff *skb) +{ + return 0; +} #endif #endif /* _LINUX_TCP_AUTHOPT_H */ diff --git a/net/ipv4/tcp_authopt.c b/net/ipv4/tcp_authopt.c index a42daadf6b7d..493461e46460 100644 --- a/net/ipv4/tcp_authopt.c +++ b/net/ipv4/tcp_authopt.c @@ -168,10 +168,66 @@ struct tcp_authopt_key_info *__tcp_authopt_key_info_lookup(const struct sock *sk return key; return NULL; } +struct tcp_authopt_key_info *tcp_authopt_lookup_send(struct tcp_authopt_info *info, + const struct sock *addr_sk, + int send_id) +{ + struct tcp_authopt_key_info *result = NULL; + struct tcp_authopt_key_info *key; + + hlist_for_each_entry_rcu(key, &info->head, node, 0) { + if (send_id >= 0 && key->send_id != send_id) + continue; + if (key->flags & TCP_AUTHOPT_KEY_ADDR_BIND) { + if (addr_sk->sk_family == AF_INET) { + struct sockaddr_in *key_addr = (struct sockaddr_in *)&key->addr; + const struct in_addr *daddr = + (const struct in_addr *)&addr_sk->sk_daddr; + + if (WARN_ON(key_addr->sin_family != AF_INET)) + continue; + if (memcmp(daddr, &key_addr->sin_addr, sizeof(*daddr))) + continue; + } + if (addr_sk->sk_family == AF_INET6) { + struct sockaddr_in6 *key_addr = (struct sockaddr_in6 *)&key->addr; + const struct in6_addr *daddr = &addr_sk->sk_v6_daddr; + + if (WARN_ON(key_addr->sin6_family != AF_INET6)) + continue; + if (memcmp(daddr, &key_addr->sin6_addr, sizeof(*daddr))) + continue; + } + } + if (result && net_ratelimit()) + pr_warn("ambiguous tcp authentication keys configured for send\n"); + result = key; + } + + return result; +} + +/* Select key for sending + * addr_sk is the sock used for comparing daddr, it is only different from sk in + * the synack case. + */ +struct tcp_authopt_key_info *tcp_authopt_select_key(const struct sock *sk, + const struct sock *addr_sk, + u8 *rnextkeyid) +{ + struct tcp_authopt_info *info; + + info = rcu_dereference(tcp_sk(sk)->authopt_info); + if (!info) + return NULL; + + return tcp_authopt_lookup_send(info, addr_sk, -1); +} + static struct tcp_authopt_info *__tcp_authopt_info_get_or_create(struct sock *sk) { struct tcp_sock *tp = tcp_sk(sk); struct tcp_authopt_info *info; @@ -336,16 +392,69 @@ int tcp_set_authopt_key(struct sock *sk, sockptr_t optval, unsigned int optlen) key_info->recv_id = opt.recv_id; key_info->alg_id = opt.alg; key_info->alg = alg; key_info->keylen = opt.keylen; memcpy(key_info->key, opt.key, opt.keylen); + key_info->maclen = alg->maclen; memcpy(&key_info->addr, &opt.addr, sizeof(key_info->addr)); hlist_add_head_rcu(&key_info->node, &info->head); return 0; } +static int tcp_authopt_clone_keys(struct sock *newsk, + const struct sock *oldsk, + struct tcp_authopt_info *new_info, + struct tcp_authopt_info *old_info) +{ + struct tcp_authopt_key_info *old_key; + struct tcp_authopt_key_info *new_key; + + hlist_for_each_entry_rcu(old_key, &old_info->head, node, lockdep_sock_is_held(sk)) { + new_key = sock_kmalloc(newsk, sizeof(*new_key), GFP_ATOMIC); + if (!new_key) + return -ENOMEM; + memcpy(new_key, old_key, sizeof(*new_key)); + tcp_authopt_alg_incref(old_key->alg); + hlist_add_head_rcu(&new_key->node, &new_info->head); + } + + return 0; +} + +/** Called to create accepted sockets. + * + * Need to copy authopt info from listen socket. + */ +int __tcp_authopt_openreq(struct sock *newsk, const struct sock *oldsk, struct request_sock *req) +{ + struct tcp_authopt_info *old_info; + struct tcp_authopt_info *new_info; + int err; + + old_info = rcu_dereference(tcp_sk(oldsk)->authopt_info); + if (!old_info) + return 0; + + new_info = kmalloc(sizeof(*new_info), GFP_ATOMIC | __GFP_ZERO); + if (!new_info) + return -ENOMEM; + + sk_nocaps_add(newsk, NETIF_F_GSO_MASK); + new_info->src_isn = tcp_rsk(req)->snt_isn; + new_info->dst_isn = tcp_rsk(req)->rcv_isn; + INIT_HLIST_HEAD(&new_info->head); + err = tcp_authopt_clone_keys(newsk, oldsk, new_info, old_info); + if (err) { + __tcp_authopt_info_free(newsk, new_info); + return err; + } + rcu_assign_pointer(tcp_sk(newsk)->authopt_info, new_info); + + return 0; +} + /* feed traffic key into shash */ static int tcp_authopt_shash_traffic_key(struct shash_desc *desc, struct sock *sk, struct sk_buff *skb, bool input, @@ -808,5 +917,123 @@ int __tcp_authopt_calc_mac(struct sock *sk, out: tcp_authopt_put_mac_shash(key, mac_tfm); return err; } + +int tcp_authopt_hash(char *hash_location, + struct tcp_authopt_key_info *key, + struct sock *sk, + struct sk_buff *skb) +{ + /* MAC inside option is truncated to 12 bytes but crypto API needs output + * buffer to be large enough so we use a buffer on the stack. + */ + u8 macbuf[TCP_AUTHOPT_MAXMACBUF]; + int err; + + if (WARN_ON(key->maclen > sizeof(macbuf))) + return -ENOBUFS; + + err = __tcp_authopt_calc_mac(sk, skb, key, false, macbuf); + if (err) { + memset(hash_location, 0, key->maclen); + return err; + } + memcpy(hash_location, macbuf, key->maclen); + + return 0; +} + +static struct tcp_authopt_key_info *tcp_authopt_lookup_recv(struct sock *sk, + struct sk_buff *skb, + struct tcp_authopt_info *info, + int recv_id) +{ + struct tcp_authopt_key_info *result = NULL; + struct tcp_authopt_key_info *key; + + /* multiple matches will cause occasional failures */ + hlist_for_each_entry_rcu(key, &info->head, node, 0) { + if (recv_id >= 0 && key->recv_id != recv_id) + continue; + if (key->flags & TCP_AUTHOPT_KEY_ADDR_BIND) { + if (sk->sk_family == AF_INET) { + struct sockaddr_in *key_addr = (struct sockaddr_in *)&key->addr; + struct iphdr *iph = (struct iphdr *)skb_network_header(skb); + + if (WARN_ON(key_addr->sin_family != AF_INET)) + continue; + if (WARN_ON(iph->version != 4)) + continue; + if (memcmp(&iph->saddr, &key_addr->sin_addr, sizeof(iph->saddr))) + continue; + } + if (sk->sk_family == AF_INET6) { + struct sockaddr_in6 *key_addr = (struct sockaddr_in6 *)&key->addr; + struct ipv6hdr *iph = (struct ipv6hdr *)skb_network_header(skb); + + if (WARN_ON(key_addr->sin6_family != AF_INET6)) + continue; + if (WARN_ON(iph->version != 6)) + continue; + if (memcmp(&iph->saddr, &key_addr->sin6_addr, sizeof(iph->saddr))) + continue; + } + } + if (result && net_ratelimit()) + pr_warn("ambiguous tcp authentication keys configured for receive\n"); + result = key; + } + + return result; +} + +int __tcp_authopt_inbound_check(struct sock *sk, struct sk_buff *skb, struct tcp_authopt_info *info) +{ + struct tcphdr *th = (struct tcphdr *)skb_transport_header(skb); + struct tcphdr_authopt *opt; + struct tcp_authopt_key_info *key; + u8 macbuf[16]; + int err; + + opt = (struct tcphdr_authopt *)tcp_authopt_find_option(th); + key = tcp_authopt_lookup_recv(sk, skb, info, opt ? opt->keyid : -1); + + /* nothing found or expected */ + if (!opt && !key) + return 0; + if (!opt && key) { + net_info_ratelimited("TCP Authentication Missing\n"); + return -EINVAL; + } + if (opt && !key) { + /* RFC5925 Section 7.3: + * A TCP-AO implementation MUST allow for configuration of the behavior + * of segments with TCP-AO but that do not match an MKT. The initial + * default of this configuration SHOULD be to silently accept such + * connections. + */ + if (info->flags & TCP_AUTHOPT_FLAG_REJECT_UNEXPECTED) { + net_info_ratelimited("TCP Authentication Unexpected: Rejected\n"); + return -EINVAL; + } else { + net_info_ratelimited("TCP Authentication Unexpected: Accepted\n"); + return 0; + } + } + + /* bad inbound key len */ + if (key->maclen + 4 != opt->len) + return -EINVAL; + + err = __tcp_authopt_calc_mac(sk, skb, key, true, macbuf); + if (err) + return err; + + if (memcmp(macbuf, opt->mac, key->maclen)) { + net_info_ratelimited("TCP Authentication Failed\n"); + return -EINVAL; + } + + return 0; +} diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 3f7bd7ae7d7a..e0b51b2f747f 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -70,10 +70,11 @@ #include #include #include #include #include +#include #include #include #include #include #include @@ -5967,18 +5968,34 @@ void tcp_init_transfer(struct sock *sk, int bpf_op, struct sk_buff *skb) if (!icsk->icsk_ca_initialized) tcp_init_congestion_control(sk); tcp_init_buffer_space(sk); } +static void tcp_authopt_finish_connect(struct sock *sk, struct sk_buff *skb) +{ +#ifdef CONFIG_TCP_AUTHOPT + struct tcp_authopt_info *info; + + info = rcu_dereference_protected(tcp_sk(sk)->authopt_info, lockdep_sock_is_held(sk)); + if (!info) + return; + + info->src_isn = ntohl(tcp_hdr(skb)->ack_seq) - 1; + info->dst_isn = ntohl(tcp_hdr(skb)->seq); +#endif +} + void tcp_finish_connect(struct sock *sk, struct sk_buff *skb) { struct tcp_sock *tp = tcp_sk(sk); struct inet_connection_sock *icsk = inet_csk(sk); tcp_set_state(sk, TCP_ESTABLISHED); icsk->icsk_ack.lrcvtime = tcp_jiffies32; + tcp_authopt_finish_connect(sk, skb); + if (skb) { icsk->icsk_af_ops->sk_rx_dst_set(sk, skb); security_inet_conn_established(sk, skb); sk_mark_napi_id(sk, skb); } diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 1348615c7576..a1d39183908c 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -2060,10 +2060,13 @@ int tcp_v4_rcv(struct sk_buff *skb) goto discard_and_relse; if (tcp_v4_inbound_md5_hash(sk, skb, dif, sdif)) goto discard_and_relse; + if (tcp_authopt_inbound_check(sk, skb)) + goto discard_and_relse; + nf_reset_ct(skb); if (tcp_filter(sk, skb)) goto discard_and_relse; th = (const struct tcphdr *)skb->data; diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 0a4f3f16140a..4d7d86547b0e 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -24,10 +24,11 @@ #include #include #include #include #include +#include #include #include #include static bool tcp_in_window(u32 seq, u32 end_seq, u32 s_win, u32 e_win) @@ -539,10 +540,11 @@ struct sock *tcp_create_openreq_child(const struct sock *sk, #ifdef CONFIG_TCP_MD5SIG newtp->md5sig_info = NULL; /*XXX*/ if (newtp->af_specific->md5_lookup(sk, newsk)) newtp->tcp_header_len += TCPOLEN_MD5SIG_ALIGNED; #endif + tcp_authopt_openreq(newsk, sk, req); if (skb->len >= TCP_MSS_DEFAULT + newtp->tcp_header_len) newicsk->icsk_ack.last_seg_size = skb->len - newtp->tcp_header_len; newtp->rx_opt.mss_clamp = req->mss; tcp_ecn_openreq_child(newtp, req); newtp->fastopen_req = NULL; diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 29553fce8502..0e9ed6578809 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -37,10 +37,11 @@ #define pr_fmt(fmt) "TCP: " fmt #include #include +#include #include #include #include #include @@ -411,10 +412,11 @@ static inline bool tcp_urg_mode(const struct tcp_sock *tp) #define OPTION_SACK_ADVERTISE (1 << 0) #define OPTION_TS (1 << 1) #define OPTION_MD5 (1 << 2) #define OPTION_WSCALE (1 << 3) +#define OPTION_AUTHOPT (1 << 4) #define OPTION_FAST_OPEN_COOKIE (1 << 8) #define OPTION_SMC (1 << 9) #define OPTION_MPTCP (1 << 10) static void smc_options_write(__be32 *ptr, u16 *options) @@ -435,16 +437,21 @@ static void smc_options_write(__be32 *ptr, u16 *options) struct tcp_out_options { u16 options; /* bit field of OPTION_* */ u16 mss; /* 0 to disable */ u8 ws; /* window scale, 0 to disable */ u8 num_sack_blocks; /* number of SACK blocks to include */ - u8 hash_size; /* bytes in hash_location */ u8 bpf_opt_len; /* length of BPF hdr option */ +#ifdef CONFIG_TCP_AUTHOPT + u8 authopt_rnextkeyid; /* rnextkey */ +#endif __u8 *hash_location; /* temporary pointer, overloaded */ __u32 tsval, tsecr; /* need to include OPTION_TS */ struct tcp_fastopen_cookie *fastopen_cookie; /* Fast open cookie */ struct mptcp_out_options mptcp; +#ifdef CONFIG_TCP_AUTHOPT + struct tcp_authopt_key_info *authopt_key; +#endif }; static void mptcp_options_write(__be32 *ptr, const struct tcp_sock *tp, struct tcp_out_options *opts) { @@ -617,10 +624,24 @@ static void tcp_options_write(__be32 *ptr, struct tcp_sock *tp, /* overload cookie hash location */ opts->hash_location = (__u8 *)ptr; ptr += 4; } +#ifdef CONFIG_TCP_AUTHOPT + if (unlikely(OPTION_AUTHOPT & options)) { + struct tcp_authopt_key_info *key = opts->authopt_key; + + WARN_ON(!key); + *ptr++ = htonl((TCPOPT_AUTHOPT << 24) | ((4 + key->maclen) << 16) | + (key->send_id << 8) | opts->authopt_rnextkeyid); + /* overload cookie hash location */ + opts->hash_location = (__u8 *)ptr; + /* maclen is currently always 12 but try to align nicely anyway. */ + ptr += (key->maclen + 3) / 4; + } +#endif + if (unlikely(opts->mss)) { *ptr++ = htonl((TCPOPT_MSS << 24) | (TCPOLEN_MSS << 16) | opts->mss); } @@ -752,10 +773,28 @@ static void mptcp_set_option_cond(const struct request_sock *req, } } } } +static int tcp_authopt_init_options(const struct sock *sk, + const struct sock *addr_sk, + struct tcp_out_options *opts) +{ +#ifdef CONFIG_TCP_AUTHOPT + struct tcp_authopt_key_info *key; + + key = tcp_authopt_select_key(sk, addr_sk, &opts->authopt_rnextkeyid); + if (key) { + opts->options |= OPTION_AUTHOPT; + opts->authopt_key = key; + return 4 + key->maclen; + } +#endif + + return 0; +} + /* Compute TCP options for SYN packets. This is not the final * network wire format yet. */ static unsigned int tcp_syn_options(struct sock *sk, struct sk_buff *skb, struct tcp_out_options *opts, @@ -774,10 +813,11 @@ static unsigned int tcp_syn_options(struct sock *sk, struct sk_buff *skb, opts->options |= OPTION_MD5; remaining -= TCPOLEN_MD5SIG_ALIGNED; } } #endif + remaining -= tcp_authopt_init_options(sk, sk, opts); /* We always get an MSS option. The option bytes which will be seen in * normal data packets should timestamps be used, must be in the MSS * advertised. But we subtract them from tp->mss_cache so that * calculations in tcp_sendmsg are simpler etc. So account for this @@ -862,10 +902,11 @@ static unsigned int tcp_synack_options(const struct sock *sk, */ if (synack_type != TCP_SYNACK_COOKIE) ireq->tstamp_ok &= !ireq->sack_ok; } #endif + remaining -= tcp_authopt_init_options(sk, req_to_sk(req), opts); /* We always send an MSS option. */ opts->mss = mss; remaining -= TCPOLEN_MSS_ALIGNED; @@ -930,10 +971,11 @@ static unsigned int tcp_established_options(struct sock *sk, struct sk_buff *skb opts->options |= OPTION_MD5; size += TCPOLEN_MD5SIG_ALIGNED; } } #endif + size += tcp_authopt_init_options(sk, sk, opts); if (likely(tp->rx_opt.tstamp_ok)) { opts->options |= OPTION_TS; opts->tsval = skb ? tcp_skb_timestamp(skb) + tp->tsoffset : 0; opts->tsecr = tp->rx_opt.ts_recent; @@ -1365,10 +1407,17 @@ static int __tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, sk_nocaps_add(sk, NETIF_F_GSO_MASK); tp->af_specific->calc_md5_hash(opts.hash_location, md5, sk, skb); } #endif +#ifdef CONFIG_TCP_AUTHOPT + if (opts.authopt_key) { + sk_nocaps_add(sk, NETIF_F_GSO_MASK); + err = tcp_authopt_hash(opts.hash_location, opts.authopt_key, sk, skb); + WARN_ON(err); // FIXME + } +#endif /* BPF prog is the last one writing header option */ bpf_skops_write_hdr_opt(sk, skb, NULL, NULL, 0, &opts); INDIRECT_CALL_INET(icsk->icsk_af_ops->send_check, @@ -3602,10 +3651,15 @@ struct sk_buff *tcp_make_synack(const struct sock *sk, struct dst_entry *dst, if (md5) tcp_rsk(req)->af_specific->calc_md5_hash(opts.hash_location, md5, req_to_sk(req), skb); rcu_read_unlock(); #endif +#ifdef CONFIG_TCP_AUTHOPT + /* If signature fails we do nothing */ + if (opts.authopt_key) + tcp_authopt_hash(opts.hash_location, opts.authopt_key, req_to_sk(req), skb); +#endif bpf_skops_write_hdr_opt((struct sock *)sk, skb, req, syn_skb, synack_type, &opts); skb->skb_mstamp_ns = now; diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 0ce52d46e4f8..51381a9c2bd5 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -40,10 +40,11 @@ #include #include #include #include +#include #include #include #include #include #include @@ -1733,10 +1734,13 @@ INDIRECT_CALLABLE_SCOPE int tcp_v6_rcv(struct sk_buff *skb) goto discard_and_relse; if (tcp_v6_inbound_md5_hash(sk, skb, dif, sdif)) goto discard_and_relse; + if (tcp_authopt_inbound_check(sk, skb)) + goto discard_and_relse; + if (tcp_filter(sk, skb)) goto discard_and_relse; th = (const struct tcphdr *)skb->data; hdr = ipv6_hdr(skb); tcp_v6_fill_cb(skb, hdr, th); From patchwork Mon Aug 9 21:35:35 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leonard Crestez X-Patchwork-Id: 12427335 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9987BC432BE for ; Mon, 9 Aug 2021 21:36:20 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7EF7E6023B for ; Mon, 9 Aug 2021 21:36:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236648AbhHIVgk (ORCPT ); Mon, 9 Aug 2021 17:36:40 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58604 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236431AbhHIVgU (ORCPT ); Mon, 9 Aug 2021 17:36:20 -0400 Received: from mail-ed1-x52b.google.com (mail-ed1-x52b.google.com [IPv6:2a00:1450:4864:20::52b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DE604C0617A0; Mon, 9 Aug 2021 14:35:58 -0700 (PDT) Received: by mail-ed1-x52b.google.com with SMTP id cf5so26817612edb.2; Mon, 09 Aug 2021 14:35:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=PUqAlLNH4YeN3rVIdjP870cOs6LUxkdfXIiMuoP0+Is=; b=oWevK1wL/j6cgww4o6hyzrDD8dQCrAS/y+o0EtOyWjOY7BDIMroOQybLqmpJOB8SCf a9asCYzcjAq6uS2WqwsIzMnnyIO6ahqNwb9f2BiNthsZOMfu5oZbIp/lpkT7nRUb1xW/ 4Kmdw/kGfNzGR4XdKbUy/XgfWkAE5BfgpP0HmQHllzau+CPx/ZE+ZuK4DNyvAahdxZlN oOyARjtNX/ux7Tp2G43J8CLgJw29JtoQJHtzGFre/nxsdu/jg294EwN5zVX2ZJ5VLrl+ qXAYw9Yh4RwHcdqW8B+oGwrvbHUon6FB1aeJvXSLXm1ukET7z00unSqf3zWjgFZy0CRe PhaQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=PUqAlLNH4YeN3rVIdjP870cOs6LUxkdfXIiMuoP0+Is=; b=QGebICGeRXc1NGwEK056vCjPuOp/ZQWp35kbeNk7qNCIoIZMwbY/bIxwycEY3RzANJ IDNcPC86FJ13IdWwTDriRy74LwoL0bzkHHY47RPa9+z+mELY2JubsEqpl4T2x0D2FvB1 HULTrLkGEcCqQHhk9vGVNgW85PSJPKP8IP6Q3fg/kplpZOV5gxb5Hf8+tT2SS41cnHzG zYJ/78+s1vKl+KX06z+1/XK261NRYiSwtc4n4w9stDK7oLkn+wZyNptw03attuU2GMa7 udRtSoghKzSA6Ee7lj3/95hKuO10KWZaVWKpuAc0BG6L9g4E1CVvWpV+rzbJjtXOMHp8 6ofw== X-Gm-Message-State: AOAM5308O0FekEM2QBWR505SLVvcR7EsriSJri+7EMIGKDRcL5/btLVf Ele6ZrH4nj2SZU3G3gswtvE= X-Google-Smtp-Source: ABdhPJxs98lcTKdbiwlj5KLON0kuBiZw2trNEBqNZK3t2eFbjUMnnmEgPj3MFH5bCJ5rRCoh7EWN3A== X-Received: by 2002:a05:6402:424c:: with SMTP id g12mr446165edb.121.1628544956484; Mon, 09 Aug 2021 14:35:56 -0700 (PDT) Received: from localhost.localdomain ([2a04:241e:502:1d80:688d:23e:82c6:84aa]) by smtp.gmail.com with ESMTPSA id v24sm5542932edt.41.2021.08.09.14.35.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Aug 2021 14:35:56 -0700 (PDT) From: Leonard Crestez To: Eric Dumazet , "David S. Miller" , Herbert Xu , Kuniyuki Iwashima , David Ahern Cc: Hideaki YOSHIFUJI , Jakub Kicinski , Yuchung Cheng , Francesco Ruggeri , Mat Martineau , Christoph Paasch , Ivan Delalande , Priyaranjan Jha , Menglong Dong , linux-kernel@vger.kernel.org, linux-crypto@vger.kernel.org, netdev@vger.kernel.org Subject: [RFCv2 6/9] tcp: authopt: Add key selection controls Date: Tue, 10 Aug 2021 00:35:35 +0300 Message-Id: X-Mailer: git-send-email 2.25.1 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC The RFC requires that TCP can report the keyid and rnextkeyid values being sent or received, implement this via getsockopt values. The RFC also requires that user can select the sending key and that the sending key is automatically switched based on rnextkeyid. These requirements can conflict so we implement both and add a flag which specifies if user or peer request takes priority. Also add an option to control rnextkeyid explicitly from userspace. Signed-off-by: Leonard Crestez --- Documentation/networking/tcp_authopt.rst | 25 +++++++++++ include/net/tcp_authopt.h | 8 ++++ include/uapi/linux/tcp.h | 31 +++++++++++++ net/ipv4/tcp_authopt.c | 57 ++++++++++++++++++++++-- 4 files changed, 117 insertions(+), 4 deletions(-) diff --git a/Documentation/networking/tcp_authopt.rst b/Documentation/networking/tcp_authopt.rst index 484f66f41ad5..cded87a70d05 100644 --- a/Documentation/networking/tcp_authopt.rst +++ b/Documentation/networking/tcp_authopt.rst @@ -35,10 +35,35 @@ Keys can be bound to remote addresses in a way that is similar to TCP_MD5. RFC5925 requires that key ids do not overlap when tcp identifiers (addr/port) overlap. This is not enforced by linux, configuring ambiguous keys will result in packet drops and lost connections. +Key selection +------------- + +On getsockopt(TCP_AUTHOPT) information is provided about keyid/rnextkeyid in +the last send packet and about the keyid/rnextkeyd in the last valid received +packet. + +By default the sending keyid is selected to match the "rnextkeyid" value sent +by the remote side. If that keyid is not available (or for new connections) a +random matching key is selected. + +If the `TCP_AUTHOPT_LOCK_KEYID` is set then the sending key is selected by the +`tcp_authopt.send_local_id` field and rnextkeyid is ignored. If no key with +local_id == send_local_id is configured then a random matching key is +selected. + +The current sending key is cached in the socket and will not change unless +requested by remote rnextkeyid or by setsockopt. + +The rnextkeyid value sent on the wire is usually the recv_id of the current +key used for sending. If the TCP_AUTHOPT_LOCK_RNEXTKEY flag is set in +`tcp_authopt.flags` the value of `tcp_authopt.send_rnextkeyid` is send +instead. This can be used to implement smooth rollover: the peer will switch +its keyid to the received rnextkeyid when it is available. + ABI Reference ============= .. kernel-doc:: include/uapi/linux/tcp.h :identifiers: tcp_authopt tcp_authopt_flag tcp_authopt_key tcp_authopt_key_flag tcp_authopt_alg diff --git a/include/net/tcp_authopt.h b/include/net/tcp_authopt.h index 28ebc77473a4..759635346874 100644 --- a/include/net/tcp_authopt.h +++ b/include/net/tcp_authopt.h @@ -25,11 +25,19 @@ struct tcp_authopt_key_info { /* Per-socket information regarding tcp_authopt */ struct tcp_authopt_info { /* List of tcp_authopt_key_info */ struct hlist_head head; + /* Current send_key, cached. + * Once a key is found it only changes by user or remote request. + */ + struct tcp_authopt_key_info *send_key; u32 flags; + u32 local_send_id; + u8 send_rnextkeyid; + u8 recv_keyid; + u8 recv_rnextkeyid; u32 src_isn; u32 dst_isn; struct rcu_head rcu; }; diff --git a/include/uapi/linux/tcp.h b/include/uapi/linux/tcp.h index bc47664156eb..c04f5166ab33 100644 --- a/include/uapi/linux/tcp.h +++ b/include/uapi/linux/tcp.h @@ -346,10 +346,24 @@ struct tcp_diag_md5sig { /** * enum tcp_authopt_flag - flags for `tcp_authopt.flags` */ enum tcp_authopt_flag { + /** + * @TCP_AUTHOPT_FLAG_LOCK_KEYID: keyid controlled by sockopt + * + * If this is set `tcp_authopt.local_send_id` is used to determined sending + * key. Otherwise a key with send_id == recv_rnextkeyid is preferred. + */ + TCP_AUTHOPT_FLAG_LOCK_KEYID = (1 << 0), + /** + * @TCP_AUTHOPT_FLAG_LOCK_RNEXTKEYID: Override rnextkeyid from userspace + * + * If this is set then `tcp_authopt.send_rnextkeyid` is sent on outbound + * packets. Other the recv_id of the current sending key is sent. + */ + TCP_AUTHOPT_FLAG_LOCK_RNEXTKEYID = (1 << 1), /** * @TCP_AUTHOPT_FLAG_REJECT_UNEXPECTED: * Configure behavior of segments with TCP-AO coming from hosts for which no * key is configured. The default recommended by RFC is to silently accept * such connections. @@ -361,10 +375,27 @@ enum tcp_authopt_flag { * struct tcp_authopt - Per-socket options related to TCP Authentication Option */ struct tcp_authopt { /** @flags: Combination of &enum tcp_authopt_flag */ __u32 flags; + /** + * @local_send_id: `tcp_authopt_key.local_id` of preferred send key + * + * This is only used if `TCP_AUTHOPT_FLAG_LOCK_KEYID` is set + */ + __u32 local_send_id; + /** + * @send_rnextkeyid: The rnextkeyid to send in packets + * + * This is controlled by the user iff TCP_AUTHOPT_FLAG_LOCK_RNEXTKEYID is + * set. Otherwise rnextkeyid is the recv_id of the current key + */ + __u8 send_rnextkeyid; + /** @recv_keyid: A recently-received keyid value. Only for getsockopt. */ + __u8 recv_keyid; + /** @recv_rnextkeyid: A recently-received rnextkeyid value. Only for getsockopt. */ + __u8 recv_rnextkeyid; }; /** * enum tcp_authopt_key_flag - flags for `tcp_authopt.flags` * diff --git a/net/ipv4/tcp_authopt.c b/net/ipv4/tcp_authopt.c index 493461e46460..40412d9ea04e 100644 --- a/net/ipv4/tcp_authopt.c +++ b/net/ipv4/tcp_authopt.c @@ -215,17 +215,44 @@ struct tcp_authopt_key_info *tcp_authopt_lookup_send(struct tcp_authopt_info *in */ struct tcp_authopt_key_info *tcp_authopt_select_key(const struct sock *sk, const struct sock *addr_sk, u8 *rnextkeyid) { + struct tcp_authopt_key_info *key, *new_key; struct tcp_authopt_info *info; info = rcu_dereference(tcp_sk(sk)->authopt_info); if (!info) return NULL; - return tcp_authopt_lookup_send(info, addr_sk, -1); + key = info->send_key; + if (info->flags & TCP_AUTHOPT_FLAG_LOCK_KEYID) { + int local_send_id = info->local_send_id; + + if (local_send_id && (!key || key->local_id != local_send_id)) + new_key = __tcp_authopt_key_info_lookup(sk, info, local_send_id); + } else { + if (!key || key->send_id != info->recv_rnextkeyid) + new_key = tcp_authopt_lookup_send(info, addr_sk, info->recv_rnextkeyid); + } + if (!key && !new_key) + new_key = tcp_authopt_lookup_send(info, addr_sk, -1); + + // Change current key. + if (key != new_key && new_key) { + key = new_key; + info->send_key = key; + } + + if (key) { + if (info->flags & TCP_AUTHOPT_FLAG_LOCK_RNEXTKEYID) + *rnextkeyid = info->send_rnextkeyid; + else + *rnextkeyid = info->send_rnextkeyid = key->recv_id; + } + + return key; } static struct tcp_authopt_info *__tcp_authopt_info_get_or_create(struct sock *sk) { struct tcp_sock *tp = tcp_sk(sk); @@ -262,11 +289,17 @@ int tcp_set_authopt(struct sock *sk, sockptr_t optval, unsigned int optlen) info = __tcp_authopt_info_get_or_create(sk); if (IS_ERR(info)) return PTR_ERR(info); - info->flags = opt.flags & TCP_AUTHOPT_FLAG_REJECT_UNEXPECTED); + info->flags = opt.flags & + (TCP_AUTHOPT_FLAG_LOCK_KEYID | + TCP_AUTHOPT_FLAG_LOCK_RNEXTKEYID | + TCP_AUTHOPT_FLAG_REJECT_UNEXPECTED); + info->local_send_id = opt.local_send_id; + if (opt.flags & TCP_AUTHOPT_FLAG_LOCK_RNEXTKEYID) + info->send_rnextkeyid = opt.send_rnextkeyid; return 0; } int tcp_get_authopt_val(struct sock *sk, struct tcp_authopt *opt) @@ -277,11 +310,17 @@ int tcp_get_authopt_val(struct sock *sk, struct tcp_authopt *opt) WARN_ON(!lockdep_sock_is_held(sk)); memset(opt, 0, sizeof(*opt)); info = rcu_dereference_check(tp->authopt_info, lockdep_sock_is_held(sk)); if (!info) return -EINVAL; - opt->flags = info->flags & TCP_AUTHOPT_FLAG_REJECT_UNEXPECTED; + if (info->send_key) + opt->local_send_id = info->send_key->local_id; + else + opt->local_send_id = 0; + opt->send_rnextkeyid = info->send_rnextkeyid; + opt->recv_keyid = info->recv_keyid; + opt->recv_rnextkeyid = info->recv_rnextkeyid; return 0; } static void tcp_authopt_key_free_rcu(struct rcu_head *rcu) @@ -295,10 +334,12 @@ static void tcp_authopt_key_free_rcu(struct rcu_head *rcu) static void tcp_authopt_key_del(struct sock *sk, struct tcp_authopt_info *info, struct tcp_authopt_key_info *key) { hlist_del_rcu(&key->node); + if (info->send_key == key) + info->send_key = NULL; atomic_sub(sizeof(*key), &sk->sk_omem_alloc); call_rcu(&key->rcu, tcp_authopt_key_free_rcu); } /* free info and keys but don't touch tp->authopt_info */ @@ -440,10 +481,11 @@ int __tcp_authopt_openreq(struct sock *newsk, const struct sock *oldsk, struct r return -ENOMEM; sk_nocaps_add(newsk, NETIF_F_GSO_MASK); new_info->src_isn = tcp_rsk(req)->snt_isn; new_info->dst_isn = tcp_rsk(req)->rcv_isn; + new_info->local_send_id = old_info->local_send_id; INIT_HLIST_HEAD(&new_info->head); err = tcp_authopt_clone_keys(newsk, oldsk, new_info, old_info); if (err) { __tcp_authopt_info_free(newsk, new_info); return err; @@ -1016,11 +1058,11 @@ int __tcp_authopt_inbound_check(struct sock *sk, struct sk_buff *skb, struct tcp if (info->flags & TCP_AUTHOPT_FLAG_REJECT_UNEXPECTED) { net_info_ratelimited("TCP Authentication Unexpected: Rejected\n"); return -EINVAL; } else { net_info_ratelimited("TCP Authentication Unexpected: Accepted\n"); - return 0; + goto accept; } } /* bad inbound key len */ if (key->maclen + 4 != opt->len) @@ -1033,7 +1075,14 @@ int __tcp_authopt_inbound_check(struct sock *sk, struct sk_buff *skb, struct tcp if (memcmp(macbuf, opt->mac, key->maclen)) { net_info_ratelimited("TCP Authentication Failed\n"); return -EINVAL; } +accept: + /* Doing this for all valid packets will results in keyids temporarily + * flipping back and forth if packets are reordered or retransmitted. + */ + info->recv_keyid = opt->keyid; + info->recv_rnextkeyid = opt->rnextkeyid; + return 0; } From patchwork Mon Aug 9 21:35:36 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leonard Crestez X-Patchwork-Id: 12427333 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 55C1CC4320A for ; Mon, 9 Aug 2021 21:36:17 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 396EB606A5 for ; Mon, 9 Aug 2021 21:36:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236618AbhHIVgg (ORCPT ); Mon, 9 Aug 2021 17:36:36 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58642 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236482AbhHIVgU (ORCPT ); Mon, 9 Aug 2021 17:36:20 -0400 Received: from mail-ed1-x536.google.com (mail-ed1-x536.google.com [IPv6:2a00:1450:4864:20::536]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 769E2C0613D3; Mon, 9 Aug 2021 14:35:59 -0700 (PDT) Received: by mail-ed1-x536.google.com with SMTP id k9so9526436edr.10; Mon, 09 Aug 2021 14:35:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=B+LRcXpuFnJyK6gBZgDwQcVUjsT+Nceuc8wbNu08CP0=; b=gkxJN15wohSLkl4Va5+/AYBe29ZvKOdSlEFyxZERCUkvpyk7SL8zKdg6GC3FXfx0Jg Gry/YjLgNI543U23dVlYLx003jonsl7vy6Ja4JjPBDeglmZE+bbbl4Cu3yqmps1z3bBy 513YHoS0qUE5CXkfonwCdkWn3qvhLHW8H/z8LLASbK3T7C8yjwiUf5q/2Td0WSkDhZcR JqinluwaPd40srFZ6zuB38aUInGfv8pP6rY4chTKHB8mhKEaG8HyBBFWYl9t1tsy8yAN ll/1h2edrRgVxVUw7QYKyGRUUiY7p/Nc1f2PS/h3rg5hlm3SSU7nGtHTzanPBXs0MiGN wfuQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=B+LRcXpuFnJyK6gBZgDwQcVUjsT+Nceuc8wbNu08CP0=; b=B6GEZ8/cT8LvALii71ax4t1VG2Qd3Gr7V45PkFu0Qxvn8VIhuigqfUTi4RLAnuG7Ob jZjxtUTnN6zs5gaQfYmldObPJC4nadFXsDF9CbrXZUNukkLM+dpxW6xNP8K0ePbXxUvd 1rYvSffn7SOXiY6LMKHXnBX4JMHAGx/S9okX2ajxJHPWaCqXsu9kippKJlYDF4VoSMaT dcQEQYNUy95MSEA017UAALE+9/35hdbn2/lGrQNXeLnSwkq/03iQMY32eVkf76GuX40p YZoOO0Pgi17m8BVDbZL949KsaCUirvHZmrzUvks1oR2MsuzyeqEHEhehR+9QXSG8gm/q E3GQ== X-Gm-Message-State: AOAM533thcXrrV39tblE30ghkF+4ZURSmhsoPAjD2Y227Qf8rg6R136G zfhY8Rk+Mki0gYkLZb+MCgI= X-Google-Smtp-Source: ABdhPJw2EB1BIggJlJ2IUXocNiyu4x1CM8qSyj0Mi20D5xlK+gwfi4tPlfHlqsfo9fZBtQM/6FajxA== X-Received: by 2002:aa7:c3cf:: with SMTP id l15mr435786edr.83.1628544958062; Mon, 09 Aug 2021 14:35:58 -0700 (PDT) Received: from localhost.localdomain ([2a04:241e:502:1d80:688d:23e:82c6:84aa]) by smtp.gmail.com with ESMTPSA id v24sm5542932edt.41.2021.08.09.14.35.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Aug 2021 14:35:57 -0700 (PDT) From: Leonard Crestez To: Eric Dumazet , "David S. Miller" , Herbert Xu , Kuniyuki Iwashima , David Ahern Cc: Hideaki YOSHIFUJI , Jakub Kicinski , Yuchung Cheng , Francesco Ruggeri , Mat Martineau , Christoph Paasch , Ivan Delalande , Priyaranjan Jha , Menglong Dong , linux-kernel@vger.kernel.org, linux-crypto@vger.kernel.org, netdev@vger.kernel.org Subject: [RFCv2 7/9] tcp: authopt: Add snmp counters Date: Tue, 10 Aug 2021 00:35:36 +0300 Message-Id: X-Mailer: git-send-email 2.25.1 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC Add LINUX_MIB_TCPAUTHOPTFAILURE and increment on failure. This can be use by userspace to count the number of failed authentications. All types of authentication failures are reported under a single counter. Signed-off-by: Leonard Crestez --- include/uapi/linux/snmp.h | 1 + net/ipv4/proc.c | 1 + net/ipv4/tcp_authopt.c | 3 +++ 3 files changed, 5 insertions(+) diff --git a/include/uapi/linux/snmp.h b/include/uapi/linux/snmp.h index 904909d020e2..1d96030889a1 100644 --- a/include/uapi/linux/snmp.h +++ b/include/uapi/linux/snmp.h @@ -290,10 +290,11 @@ enum LINUX_MIB_TCPDUPLICATEDATAREHASH, /* TCPDuplicateDataRehash */ LINUX_MIB_TCPDSACKRECVSEGS, /* TCPDSACKRecvSegs */ LINUX_MIB_TCPDSACKIGNOREDDUBIOUS, /* TCPDSACKIgnoredDubious */ LINUX_MIB_TCPMIGRATEREQSUCCESS, /* TCPMigrateReqSuccess */ LINUX_MIB_TCPMIGRATEREQFAILURE, /* TCPMigrateReqFailure */ + LINUX_MIB_TCPAUTHOPTFAILURE, /* TCPAuthOptFailure */ __LINUX_MIB_MAX }; /* linux Xfrm mib definitions */ enum diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index b0d3a09dc84e..61dd06f8389c 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c @@ -295,10 +295,11 @@ static const struct snmp_mib snmp4_net_list[] = { SNMP_MIB_ITEM("TcpDuplicateDataRehash", LINUX_MIB_TCPDUPLICATEDATAREHASH), SNMP_MIB_ITEM("TCPDSACKRecvSegs", LINUX_MIB_TCPDSACKRECVSEGS), SNMP_MIB_ITEM("TCPDSACKIgnoredDubious", LINUX_MIB_TCPDSACKIGNOREDDUBIOUS), SNMP_MIB_ITEM("TCPMigrateReqSuccess", LINUX_MIB_TCPMIGRATEREQSUCCESS), SNMP_MIB_ITEM("TCPMigrateReqFailure", LINUX_MIB_TCPMIGRATEREQFAILURE), + SNMP_MIB_ITEM("TCPAuthOptFailure", LINUX_MIB_TCPAUTHOPTFAILURE), SNMP_MIB_SENTINEL }; static void icmpmsg_put_line(struct seq_file *seq, unsigned long *vals, unsigned short *type, int count) diff --git a/net/ipv4/tcp_authopt.c b/net/ipv4/tcp_authopt.c index 40412d9ea04e..bee8873423e4 100644 --- a/net/ipv4/tcp_authopt.c +++ b/net/ipv4/tcp_authopt.c @@ -1043,10 +1043,11 @@ int __tcp_authopt_inbound_check(struct sock *sk, struct sk_buff *skb, struct tcp /* nothing found or expected */ if (!opt && !key) return 0; if (!opt && key) { + NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPAUTHOPTFAILURE); net_info_ratelimited("TCP Authentication Missing\n"); return -EINVAL; } if (opt && !key) { /* RFC5925 Section 7.3: @@ -1054,10 +1055,11 @@ int __tcp_authopt_inbound_check(struct sock *sk, struct sk_buff *skb, struct tcp * of segments with TCP-AO but that do not match an MKT. The initial * default of this configuration SHOULD be to silently accept such * connections. */ if (info->flags & TCP_AUTHOPT_FLAG_REJECT_UNEXPECTED) { + NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPAUTHOPTFAILURE); net_info_ratelimited("TCP Authentication Unexpected: Rejected\n"); return -EINVAL; } else { net_info_ratelimited("TCP Authentication Unexpected: Accepted\n"); goto accept; @@ -1071,10 +1073,11 @@ int __tcp_authopt_inbound_check(struct sock *sk, struct sk_buff *skb, struct tcp err = __tcp_authopt_calc_mac(sk, skb, key, true, macbuf); if (err) return err; if (memcmp(macbuf, opt->mac, key->maclen)) { + NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPAUTHOPTFAILURE); net_info_ratelimited("TCP Authentication Failed\n"); return -EINVAL; } accept: From patchwork Mon Aug 9 21:35:37 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leonard Crestez X-Patchwork-Id: 12427337 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 37C07C4320A for ; Mon, 9 Aug 2021 21:36:31 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1EA8960C3E for ; Mon, 9 Aug 2021 21:36:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236689AbhHIVgu (ORCPT ); Mon, 9 Aug 2021 17:36:50 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58664 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236517AbhHIVgY (ORCPT ); Mon, 9 Aug 2021 17:36:24 -0400 Received: from mail-ed1-x52f.google.com (mail-ed1-x52f.google.com [IPv6:2a00:1450:4864:20::52f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id F10ABC0617A4; Mon, 9 Aug 2021 14:36:00 -0700 (PDT) Received: by mail-ed1-x52f.google.com with SMTP id f13so26778619edq.13; Mon, 09 Aug 2021 14:36:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=uG3oHTASBquJceLiOdEfcWQQkF/eH5moDohL/r9HsUw=; b=rcgmuQw6H5q2JM/IgIbadWTq3WVWGRiwykKjM/MnB18T5J2L2R+Vj9MAujuT+uedO4 ChMLLu1nKya6brD5LiIMGPVoTNpTnC6UnxzfgJNq7tRuwYL5RFDxzJq79BglW8BHVpke avUQEeUQ0pb2pCJKp9UNjJ79KaXeusdkw7zSTsg9aMYKYyKKhiqgnOTINpfn98U7uR6M PCd8RDtZv9CgUijpeT0MO3KaVsXy4casrSuZbz0EtZfS65SuV/KvXWkEJ5Boce4BTK9a 2VEWY+px19NfwLPo3qOkJQcoeJgFA1QKpOD8WHi3cSeEoijMOEpOyKETPyBDzYjFLt2g JVBQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=uG3oHTASBquJceLiOdEfcWQQkF/eH5moDohL/r9HsUw=; b=Q5F0mK/EzZR6oRs89SsCMA7uJ6u0bCWCVdMgS5wvEL+gTV2mdbCNa069hQ5DA5B0x3 45MN4RMqO/eLxBusrRqi2YMJB/0HHqTjEIZaRE1UXYwWmd2GMgOHg4y5pf6qLgj7ulMq 0yPAXxjhl6PrNHorPF8aCz6LHiGXM+8pskGrb3tqpmYZsMJ14sn1rEFwhKSNF1no9wJ9 kDQAAAMmyrwN5KivT7gMJCUqGGWXedwEdWafQeez/65j76jCRO37T2ETpcvTxNC+esXM aN/vDKvexvr6RY4nJieoTsqj9mMuE/IhVooJm3SVzlb/b8V0gbqQLBF6Yg0e//Gs5XeP 97Ug== X-Gm-Message-State: AOAM53206pcGKAh95sYarvCALHeQ3FsPNrMhvGsYq0qpUQt3xsbObCoh lGxL6F+aWcAxFZ+lnWR6l0M= X-Google-Smtp-Source: ABdhPJztgoQQKUJPRwBdJwQhSt0StxMgyBLPlqwpdUm4g094eDhkMGxjkrGSRVLyk0L48ZyioC3LCQ== X-Received: by 2002:a50:ac82:: with SMTP id x2mr461232edc.350.1628544959642; Mon, 09 Aug 2021 14:35:59 -0700 (PDT) Received: from localhost.localdomain ([2a04:241e:502:1d80:688d:23e:82c6:84aa]) by smtp.gmail.com with ESMTPSA id v24sm5542932edt.41.2021.08.09.14.35.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Aug 2021 14:35:59 -0700 (PDT) From: Leonard Crestez To: Eric Dumazet , "David S. Miller" , Herbert Xu , Kuniyuki Iwashima , David Ahern Cc: Hideaki YOSHIFUJI , Jakub Kicinski , Yuchung Cheng , Francesco Ruggeri , Mat Martineau , Christoph Paasch , Ivan Delalande , Priyaranjan Jha , Menglong Dong , linux-kernel@vger.kernel.org, linux-crypto@vger.kernel.org, netdev@vger.kernel.org Subject: [RFCv2 8/9] selftests: Initial TCP-AO support for nettest Date: Tue, 10 Aug 2021 00:35:37 +0300 Message-Id: <909135b0313fc7b4bb8dbbd7686770483887ccc1.1628544649.git.cdleonard@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC Signed-off-by: Leonard Crestez --- tools/testing/selftests/net/nettest.c | 43 ++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/net/nettest.c b/tools/testing/selftests/net/nettest.c index bd6288302094..48d8f3a6eb27 100644 --- a/tools/testing/selftests/net/nettest.c +++ b/tools/testing/selftests/net/nettest.c @@ -100,10 +100,12 @@ struct sock_args { struct sockaddr_in v4; struct sockaddr_in6 v6; } md5_prefix; unsigned int prefix_len; + const char *authopt_password; + /* expected addresses and device index for connection */ const char *expected_dev; const char *expected_server_dev; int expected_ifindex; @@ -250,10 +252,36 @@ static int switch_ns(const char *ns) close(fd); return ret; } +static int tcp_set_authopt(int sd, struct sock_args *args) +{ + struct tcp_authopt info; + struct tcp_authopt_key key; + int rc; + + memset(&info, 0, sizeof(info)); + info.local_send_id = 1; + + rc = setsockopt(sd, IPPROTO_TCP, TCP_AUTHOPT, &info, sizeof(info)); + if (rc < 0) + log_err_errno("setsockopt(TCP_AUHTOPT_KEY)"); + + memset(&key, 0, sizeof(key)); + strcpy((char *)key.key, args->authopt_password); + key.keylen = strlen(args->authopt_password); + key.alg = TCP_AUTHOPT_ALG_HMAC_SHA_1_96; + key.local_id = 1; + + rc = setsockopt(sd, IPPROTO_TCP, TCP_AUTHOPT_KEY, &key, sizeof(key)); + if (rc < 0) + log_err_errno("setsockopt(TCP_AUHTOPT_KEY)"); + + return rc; +} + static int tcp_md5sig(int sd, void *addr, socklen_t alen, struct sock_args *args) { int keylen = strlen(args->password); struct tcp_md5sig md5sig = {}; int opt = TCP_MD5SIG; @@ -1508,10 +1536,15 @@ static int do_server(struct sock_args *args, int ipc_fd) if (args->password && tcp_md5_remote(lsd, args)) { close(lsd); goto err_exit; } + if (args->authopt_password && tcp_set_authopt(lsd, args)) { + close(lsd); + goto err_exit; + } + ipc_write(ipc_fd, 1); while (1) { log_msg("waiting for client connection.\n"); FD_ZERO(&rfds); FD_SET(lsd, &rfds); @@ -1630,10 +1663,13 @@ static int connectsock(void *addr, socklen_t alen, struct sock_args *args) goto out; if (args->password && tcp_md5sig(sd, addr, alen, args)) goto err; + if (args->authopt_password && tcp_set_authopt(sd, args)) + goto err; + if (args->bind_test_only) goto out; if (connect(sd, addr, alen) < 0) { if (errno != EINPROGRESS) { @@ -1819,11 +1855,11 @@ static int ipc_parent(int cpid, int fd, struct sock_args *args) wait(&status); return client_status; } -#define GETOPT_STR "sr:l:c:p:t:g:P:DRn:M:X:m:d:I:BN:O:SCi6xL:0:1:2:3:Fbq" +#define GETOPT_STR "sr:l:c:p:t:g:P:DRn:M:X:m:A:d:I:BN:O:SCi6xL:0:1:2:3:Fbq" static void print_usage(char *prog) { printf( "usage: %s OPTS\n" @@ -1856,10 +1892,12 @@ static void print_usage(char *prog) " -n num number of times to send message\n" "\n" " -M password use MD5 sum protection\n" " -X password MD5 password for client mode\n" " -m prefix/len prefix and length to use for MD5 key\n" + " -A password use RFC5925 TCP Authentication option\n" + "\n" " -g grp multicast group (e.g., 239.1.1.1)\n" " -i interactive mode (default is echo and terminate)\n" "\n" " -0 addr Expected local address\n" " -1 addr Expected remote address\n" @@ -1970,10 +2008,13 @@ int main(int argc, char *argv[]) args.client_pw = optarg; break; case 'm': args.md5_prefix_str = optarg; break; + case 'A': + args.authopt_password = optarg; + break; case 'S': args.use_setsockopt = 1; break; case 'C': args.use_cmsg = 1; From patchwork Mon Aug 9 21:35:38 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leonard Crestez X-Patchwork-Id: 12427339 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2928AC4338F for ; Mon, 9 Aug 2021 21:36:36 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 119C960C3E for ; Mon, 9 Aug 2021 21:36:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236719AbhHIVg4 (ORCPT ); Mon, 9 Aug 2021 17:36:56 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58632 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236522AbhHIVgY (ORCPT ); Mon, 9 Aug 2021 17:36:24 -0400 Received: from mail-ed1-x534.google.com (mail-ed1-x534.google.com [IPv6:2a00:1450:4864:20::534]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A946EC0617B9; Mon, 9 Aug 2021 14:36:02 -0700 (PDT) Received: by mail-ed1-x534.google.com with SMTP id f13so26778707edq.13; Mon, 09 Aug 2021 14:36:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=E3jO1mj7XUbGg6uQHpuj74IXQp0/lQKR6D9BzqtSWcA=; b=I71UQb+QKnUupszJxZVDzmKvLYD7kslD5ooI8iSAqN2k8U34BNmaQuSDO9XxwdsIVP /8uGJzl3K9gCBEQngHEIfA4BQdBx3WttcUoO6bv8oLi/TZsncKkCYKysIMjwTdePJWh9 uMpZ06bub9LQxmiHMyF0BkEzMjrCMyVPplegHvB6HkHVTbhFKO6D04Zd9HovtYLZ1Pcw MnIF+x949ZQAkBUmWIGDTCE2WKwyB714+EE05jc7rAbpjkK+b82Gt3pMRrL4aIcPbFSa deXduyAB2SjCEvylx1Oh4w5joGBu8Ar3A41v8FLTilCPt3db5EkEs782+LNmofZVaOnx 32xw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=E3jO1mj7XUbGg6uQHpuj74IXQp0/lQKR6D9BzqtSWcA=; b=f/xpbJfC7ke1S2w4992a/F7FsExzcte+EIS5WP+iZC7HrZgvER2cPSeMLHu6McX2Dv Z+9OFHB6QP/wPlMx664gdvatSSVG0sT+slVZTJEelXTNlXb7fGS2FHDvLZVHpoqrSvc8 YPTmFTpolOWE/qFlvuPC5Vk/lkw9CuDsbEpOBAC7NDLTB1qQQTt/shvR7sXBj+gSNAEn V4nYmV+DLSonrTTD5LDWlLEsZaNb5OzKmjvMfUqk4wf58u9Ken9H0pL7T4onD5gLGktf FXyeVz2T7Ubk8fkqQt7YIL414Fv0xBZJTFsiUc3ak0Sp1L+ev4OXYryVCj6jddoc3NJ+ W+wA== X-Gm-Message-State: AOAM533ZHUr1J9wCb9JkbB94bcxdd1dBi47hopPU1S83t6EIGwBND6VU 5+DiYKiklXYyjc8pMYEftiw= X-Google-Smtp-Source: ABdhPJwN7vsmxv9PK+2n1Up1zehgDiPvQ0UZ47UNLzhNZQYMd6xZrIEOS7Y16G0S1+7febRMZp3d1g== X-Received: by 2002:a05:6402:214a:: with SMTP id bq10mr472497edb.296.1628544961303; Mon, 09 Aug 2021 14:36:01 -0700 (PDT) Received: from localhost.localdomain ([2a04:241e:502:1d80:688d:23e:82c6:84aa]) by smtp.gmail.com with ESMTPSA id v24sm5542932edt.41.2021.08.09.14.35.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Aug 2021 14:36:00 -0700 (PDT) From: Leonard Crestez To: Eric Dumazet , "David S. Miller" , Herbert Xu , Kuniyuki Iwashima , David Ahern Cc: Hideaki YOSHIFUJI , Jakub Kicinski , Yuchung Cheng , Francesco Ruggeri , Mat Martineau , Christoph Paasch , Ivan Delalande , Priyaranjan Jha , Menglong Dong , linux-kernel@vger.kernel.org, linux-crypto@vger.kernel.org, netdev@vger.kernel.org Subject: [RFCv2 9/9] selftests: Initial TCP-AO support for fcnal-test Date: Tue, 10 Aug 2021 00:35:38 +0300 Message-Id: <3f6d654c1c36f489b471e2892c9231d6fa8fad7a.1628544649.git.cdleonard@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC Just test that a correct password is required. Signed-off-by: Leonard Crestez --- tools/testing/selftests/net/fcnal-test.sh | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tools/testing/selftests/net/fcnal-test.sh b/tools/testing/selftests/net/fcnal-test.sh index a8ad92850e63..569c340040f4 100755 --- a/tools/testing/selftests/net/fcnal-test.sh +++ b/tools/testing/selftests/net/fcnal-test.sh @@ -788,10 +788,31 @@ ipv4_ping() } ################################################################################ # IPv4 TCP +# +# TCP Authentication Option Tests +# +ipv4_tcp_authopt() +{ + # basic use case + log_start + run_cmd nettest -s -A ${MD5_PW} & + sleep 1 + run_cmd_nsb nettest -r ${NSA_IP} -A ${MD5_PW} + log_test $? 0 "AO: Simple password" + + # wrong password + log_start + show_hint "Should timeout since client uses wrong password" + run_cmd nettest -s -A ${MD5_PW} & + sleep 1 + run_cmd_nsb nettest -r ${NSA_IP} -A ${MD5_WRONG_PW} + log_test $? 2 "AO: Client uses wrong password" +} + # # MD5 tests without VRF # ipv4_tcp_md5_novrf() { @@ -1119,10 +1140,11 @@ ipv4_tcp_novrf() show_hint "Should fail 'Connection refused'" run_cmd nettest -d ${NSA_DEV} -r ${a} log_test_addr ${a} $? 1 "No server, device client, local conn" ipv4_tcp_md5_novrf + ipv4_tcp_authopt } ipv4_tcp_vrf() { local a