From nobody Sun Feb 8 12:36:55 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4E008C001DC for ; Wed, 19 Jul 2023 20:28:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230053AbjGSU2G (ORCPT ); Wed, 19 Jul 2023 16:28:06 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58122 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231414AbjGSU1j (ORCPT ); Wed, 19 Jul 2023 16:27:39 -0400 Received: from mail-wm1-x331.google.com (mail-wm1-x331.google.com [IPv6:2a00:1450:4864:20::331]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 471A02698 for ; Wed, 19 Jul 2023 13:27:01 -0700 (PDT) Received: by mail-wm1-x331.google.com with SMTP id 5b1f17b1804b1-3fbc244d307so298835e9.1 for ; Wed, 19 Jul 2023 13:27:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=arista.com; s=google; t=1689798419; x=1692390419; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=npV6eGK6CYODCUVjiXICFILgmjeTFY92Sj3PqChb+Mk=; b=bL1R+N0lrxrKJndQyhoZ2ZbedkNtoNacjLRfB6WD3FL0JZq8iiV5kA1Z/eg5DIjnXM dnfNaMi3HEk35kOKuTFi5RRpYZ6WlhWo66HELVCTkZjD4syTfOYHNGC6RjKbLzY+zgK5 pjOMB12mcHwAcGcttDuTH7retgMWvN57FGoTAk5NH+uNx3ClvviSLycJKiRz1DkwTT1D 3S/8TMFn/BA8MMwRvkUPumBXK1k5BI2NvY3lrpsFtg9fPZHkU6h5c78vqDK4zF07X6c2 lPA3MilV3EYgE2fseYV3igB+l62Nc/+5CKdxfBbxK6tkYg/vgGjtxtTIS9CnVsH3Zm77 v9Kw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1689798419; x=1692390419; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=npV6eGK6CYODCUVjiXICFILgmjeTFY92Sj3PqChb+Mk=; b=Gv1KHvnfcLVJrxz1x0Vmr8Wj9paZpGjwyGrGDTSF4mal0+OTVnUMprlwoi0KZohj9e cqcC1FSJIU6g0k2kpmVlci2gYBqvPYMtOPP4OSv1T1y3E6PIDAGuWwqK8cd3PLgE4YIW mWuV/HHVOGCxPxhHaF6j6zNLgIfLC00qQEstNm+azfipmUcoH/UyY+9NbkiGk/GSO9PU 59CWg0mazWbcEhvYLyTnh54LW169XZVsbpGBHonzC4ZKVK/+YzRXm5GuY2dPfpS3Qrdc wKCtlyODBJvnX5Pl0c9BmxSF7CGlKlA3HnzFmJvxLLLl3HZ0JE00w/m9MnpmJvS4ZYY3 kx4w== X-Gm-Message-State: ABy/qLapGAPyUgslXGAIx9Z+m/ZBro9kYXqADOWtiRcFR5tuU6jJInfu 0BT41X86ioMCy2PkrDDDffDJug== X-Google-Smtp-Source: APBJJlG4NOxl8r1DgCIkku2TIFLnGKc4dyB/Og58j0Px09mDhG+M8ywe8ch3/iygO7Lt1N3qLp16rg== X-Received: by 2002:a1c:e90d:0:b0:3fa:e92e:7a7b with SMTP id q13-20020a1ce90d000000b003fae92e7a7bmr5201724wmc.15.1689798419255; Wed, 19 Jul 2023 13:26:59 -0700 (PDT) Received: from Mindolluin.ire.aristanetworks.com ([217.173.96.166]) by smtp.gmail.com with ESMTPSA id 3-20020a05600c234300b003fc04d13242sm2432319wmq.0.2023.07.19.13.26.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 19 Jul 2023 13:26:58 -0700 (PDT) From: Dmitry Safonov To: David Ahern , Eric Dumazet , Paolo Abeni , Jakub Kicinski , "David S. Miller" Cc: linux-kernel@vger.kernel.org, Dmitry Safonov , Andy Lutomirski , Ard Biesheuvel , Bob Gilligan , Dan Carpenter , David Laight , Dmitry Safonov <0x7f454c46@gmail.com>, Donald Cassidy , Eric Biggers , "Eric W. Biederman" , Francesco Ruggeri , "Gaillardetz, Dominik" , Herbert Xu , Hideaki YOSHIFUJI , Ivan Delalande , Leonard Crestez , Salam Noureddine , "Tetreault, Francois" , netdev@vger.kernel.org Subject: [PATCH v8 12/23] net/tcp: Verify inbound TCP-AO signed segments Date: Wed, 19 Jul 2023 21:26:17 +0100 Message-ID: <20230719202631.472019-13-dima@arista.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230719202631.472019-1-dima@arista.com> References: <20230719202631.472019-1-dima@arista.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Now there is a common function to verify signature on TCP segments: tcp_inbound_hash(). It has checks for all possible cross-interactions with MD5 signs as well as with unsigned segments. The rules from RFC5925 are: (1) Any TCP segment can have at max only one signature. (2) TCP connections can't switch between using TCP-MD5 and TCP-AO. (3) TCP-AO connections can't stop using AO, as well as unsigned connections can't suddenly start using AO. Co-developed-by: Francesco Ruggeri Signed-off-by: Francesco Ruggeri Co-developed-by: Salam Noureddine Signed-off-by: Salam Noureddine Signed-off-by: Dmitry Safonov --- include/net/dropreason-core.h | 17 ++++ include/net/tcp.h | 53 ++++++++++- include/net/tcp_ao.h | 17 ++++ net/ipv4/tcp.c | 39 ++------ net/ipv4/tcp_ao.c | 167 ++++++++++++++++++++++++++++++++++ net/ipv4/tcp_ipv4.c | 10 +- net/ipv6/tcp_ao.c | 12 +++ net/ipv6/tcp_ipv6.c | 11 ++- 8 files changed, 283 insertions(+), 43 deletions(-) diff --git a/include/net/dropreason-core.h b/include/net/dropreason-core.h index 383ac5215284..0ff272d3b680 100644 --- a/include/net/dropreason-core.h +++ b/include/net/dropreason-core.h @@ -24,6 +24,10 @@ FN(TCP_MD5NOTFOUND) \ FN(TCP_MD5UNEXPECTED) \ FN(TCP_MD5FAILURE) \ + FN(TCP_AONOTFOUND) \ + FN(TCP_AOUNEXPECTED) \ + FN(TCP_AOKEYNOTFOUND) \ + FN(TCP_AOFAILURE) \ FN(SOCKET_BACKLOG) \ FN(TCP_FLAGS) \ FN(TCP_ZEROWINDOW) \ @@ -160,6 +164,19 @@ enum skb_drop_reason { * to LINUX_MIB_TCPMD5FAILURE */ SKB_DROP_REASON_TCP_MD5FAILURE, + /** + * @SKB_DROP_REASON_TCP_AONOTFOUND: no TCP-AO hash and one was expected + */ + SKB_DROP_REASON_TCP_AONOTFOUND, + /** + * @SKB_DROP_REASON_TCP_AOUNEXPECTED: TCP-AO hash is present and it + * was not expected. + */ + SKB_DROP_REASON_TCP_AOUNEXPECTED, + /** @SKB_DROP_REASON_TCP_AOKEYNOTFOUND: TCP-AO key is unknown */ + SKB_DROP_REASON_TCP_AOKEYNOTFOUND, + /** @SKB_DROP_REASON_TCP_AOFAILURE: TCP-AO hash is wrong */ + SKB_DROP_REASON_TCP_AOFAILURE, /** * @SKB_DROP_REASON_SOCKET_BACKLOG: failed to add skb to socket backlog ( * see LINUX_MIB_TCPBACKLOGDROP) diff --git a/include/net/tcp.h b/include/net/tcp.h index 77896df7952e..67b46787c3dd 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -1733,7 +1733,7 @@ tcp_md5_do_lookup_any_l3index(const struct sock *sk, enum skb_drop_reason tcp_inbound_md5_hash(const struct sock *sk, const struct sk_buff *skb, const void *saddr, const void *daddr, - int family, int dif, int sdif); + int family, int l3index, const __u8 *hash_location); =20 =20 #define tcp_twsk_md5_key(twsk) ((twsk)->tw_md5_key) @@ -1755,7 +1755,7 @@ tcp_md5_do_lookup_any_l3index(const struct sock *sk, static inline enum skb_drop_reason tcp_inbound_md5_hash(const struct sock *sk, const struct sk_buff *skb, const void *saddr, const void *daddr, - int family, int dif, int sdif) + int family, int l3index, const __u8 *hash_location) { return SKB_NOT_DROPPED_YET; } @@ -2592,4 +2592,53 @@ static inline bool tcp_ao_required(struct sock *sk, = const void *saddr, return false; } =20 +/* Called with rcu_read_lock() */ +static inline enum skb_drop_reason +tcp_inbound_hash(struct sock *sk, const struct request_sock *req, + const struct sk_buff *skb, + const void *saddr, const void *daddr, + int family, int dif, int sdif) +{ + const struct tcphdr *th =3D tcp_hdr(skb); + const struct tcp_ao_hdr *aoh; + const __u8 *md5_location; + int l3index; + + /* Invalid option or two times meet any of auth options */ + if (tcp_parse_auth_options(th, &md5_location, &aoh)) + return SKB_DROP_REASON_TCP_AUTH_HDR; + + if (req) { + if (tcp_rsk_used_ao(req) !=3D !!aoh) + return SKB_DROP_REASON_TCP_AOFAILURE; + } + + /* sdif set, means packet ingressed via a device + * in an L3 domain and dif is set to the l3mdev + */ + l3index =3D sdif ? dif : 0; + + /* Fast path: unsigned segments */ + if (likely(!md5_location && !aoh)) { + /* Drop if there's TCP-MD5 or TCP-AO key with any rcvid/sndid + * for the remote peer. On TCP-AO established connection + * the last key is impossible to remove, so there's + * always at least one current_key. + */ + if (tcp_ao_required(sk, saddr, family)) + return SKB_DROP_REASON_TCP_AONOTFOUND; + if (unlikely(tcp_md5_do_lookup(sk, l3index, saddr, family))) { + NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMD5NOTFOUND); + return SKB_DROP_REASON_TCP_MD5NOTFOUND; + } + return SKB_NOT_DROPPED_YET; + } + + if (aoh) + return tcp_inbound_ao_hash(sk, skb, family, req, aoh); + + return tcp_inbound_md5_hash(sk, skb, saddr, daddr, family, + l3index, md5_location); +} + #endif /* _TCP_H */ diff --git a/include/net/tcp_ao.h b/include/net/tcp_ao.h index 4979c993973f..1b7ca7bf93a3 100644 --- a/include/net/tcp_ao.h +++ b/include/net/tcp_ao.h @@ -112,6 +112,9 @@ struct tcp6_ao_context { }; struct tcp_sigpool; =20 +#define TCP_AO_ESTABLISHED (TCPF_ESTABLISHED|TCPF_FIN_WAIT1|TCPF_FIN_WAIT2= |\ + TCPF_CLOSE|TCPF_CLOSE_WAIT|TCPF_LAST_ACK|TCPF_CLOSING) + int tcp_ao_hash_skb(unsigned short int family, char *ao_hash, struct tcp_ao_key *key, const struct sock *sk, const struct sk_buff *skb, @@ -127,6 +130,10 @@ int tcp_ao_calc_traffic_key(struct tcp_ao_key *mkt, u8= *key, void *ctx, unsigned int len, struct tcp_sigpool *hp); void tcp_ao_destroy_sock(struct sock *sk, bool twsk); void tcp_ao_time_wait(struct tcp_timewait_sock *tcptw, struct tcp_sock *tp= ); +enum skb_drop_reason tcp_inbound_ao_hash(struct sock *sk, + const struct sk_buff *skb, unsigned short int family, + const struct request_sock *req, + const struct tcp_ao_hdr *aoh); struct tcp_ao_key *tcp_ao_do_lookup(const struct sock *sk, const union tcp_ao_addr *addr, int family, int sndid, int rcvid, u16 port); @@ -162,6 +169,9 @@ int tcp_v4_ao_hash_skb(char *ao_hash, struct tcp_ao_key= *key, int tcp_v6_ao_hash_pseudoheader(struct tcp_sigpool *hp, const struct in6_addr *daddr, const struct in6_addr *saddr, int nbytes); +int tcp_v6_ao_calc_key_skb(struct tcp_ao_key *mkt, u8 *key, + const struct sk_buff *skb, __be32 sisn, + __be32 disn); int tcp_v6_ao_calc_key_sk(struct tcp_ao_key *mkt, u8 *key, const struct sock *sk, __be32 sisn, __be32 disn, bool send); @@ -197,6 +207,13 @@ static inline void tcp_ao_syncookie(struct sock *sk, c= onst struct sk_buff *skb, { } =20 +static inline enum skb_drop_reason tcp_inbound_ao_hash(struct sock *sk, + const struct sk_buff *skb, unsigned short int family, + const struct request_sock *req, const struct tcp_ao_hdr *aoh) +{ + return SKB_NOT_DROPPED_YET; +} + static inline struct tcp_ao_key *tcp_ao_do_lookup(const struct sock *sk, const union tcp_ao_addr *addr, int family, int sndid, int rcvid, u16 port) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 0f9bc2b64018..fcedec0ae08e 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -4368,42 +4368,23 @@ EXPORT_SYMBOL(tcp_md5_hash_key); enum skb_drop_reason tcp_inbound_md5_hash(const struct sock *sk, const struct sk_buff *skb, const void *saddr, const void *daddr, - int family, int dif, int sdif) + int family, int l3index, const __u8 *hash_location) { - /* - * This gets called for each TCP segment that arrives - * so we want to be efficient. + /* This gets called for each TCP segment that has TCP-MD5 option. * We have 3 drop cases: * o No MD5 hash and one expected. * o MD5 hash and we're not expecting one. * o MD5 hash and its wrong. */ - const __u8 *hash_location =3D NULL; - struct tcp_md5sig_key *hash_expected; const struct tcphdr *th =3D tcp_hdr(skb); const struct tcp_sock *tp =3D tcp_sk(sk); - int genhash, l3index; + struct tcp_md5sig_key *key; + int genhash; u8 newhash[16]; =20 - /* sdif set, means packet ingressed via a device - * in an L3 domain and dif is set to the l3mdev - */ - l3index =3D sdif ? dif : 0; + key =3D tcp_md5_do_lookup(sk, l3index, saddr, family); =20 - hash_expected =3D tcp_md5_do_lookup(sk, l3index, saddr, family); - if (tcp_parse_auth_options(th, &hash_location, NULL)) - return SKB_DROP_REASON_TCP_AUTH_HDR; - - /* We've parsed the options - do we have a hash? */ - if (!hash_expected && !hash_location) - return SKB_NOT_DROPPED_YET; - - if (hash_expected && !hash_location) { - NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMD5NOTFOUND); - return SKB_DROP_REASON_TCP_MD5NOTFOUND; - } - - if (!hash_expected && hash_location) { + if (!key && hash_location) { NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMD5UNEXPECTED); return SKB_DROP_REASON_TCP_MD5UNEXPECTED; } @@ -4413,14 +4394,10 @@ tcp_inbound_md5_hash(const struct sock *sk, const s= truct sk_buff *skb, * IPv4-mapped case. */ if (family =3D=3D AF_INET) - genhash =3D tcp_v4_md5_hash_skb(newhash, - hash_expected, - NULL, skb); + genhash =3D tcp_v4_md5_hash_skb(newhash, key, NULL, skb); else - genhash =3D tp->af_specific->calc_md5_hash(newhash, - hash_expected, + genhash =3D tp->af_specific->calc_md5_hash(newhash, key, NULL, skb); - if (genhash || memcmp(hash_location, newhash, 16) !=3D 0) { NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMD5FAILURE); if (family =3D=3D AF_INET) { diff --git a/net/ipv4/tcp_ao.c b/net/ipv4/tcp_ao.c index 0233cf363de9..073be1680818 100644 --- a/net/ipv4/tcp_ao.c +++ b/net/ipv4/tcp_ao.c @@ -321,6 +321,30 @@ int tcp_v4_ao_calc_key_rsk(struct tcp_ao_key *mkt, u8 = *key, htonl(tcp_rsk(req)->rcv_isn)); } =20 +static int tcp_v4_ao_calc_key_skb(struct tcp_ao_key *mkt, u8 *key, + const struct sk_buff *skb, + __be32 sisn, __be32 disn) +{ + const struct iphdr *iph =3D ip_hdr(skb); + const struct tcphdr *th =3D tcp_hdr(skb); + + return tcp_v4_ao_calc_key(mkt, key, iph->saddr, iph->daddr, + th->source, th->dest, sisn, disn); +} + +static int tcp_ao_calc_key_skb(struct tcp_ao_key *mkt, u8 *key, + const struct sk_buff *skb, __be32 sisn, + __be32 disn, int family) +{ + if (family =3D=3D AF_INET) + return tcp_v4_ao_calc_key_skb(mkt, key, skb, sisn, disn); +#if IS_ENABLED(CONFIG_IPV6) + else if (family =3D=3D AF_INET6) + return tcp_v6_ao_calc_key_skb(mkt, key, skb, sisn, disn); +#endif + return -EAFNOSUPPORT; +} + static int tcp_v4_ao_hash_pseudoheader(struct tcp_sigpool *hp, __be32 daddr, __be32 saddr, int nbytes) @@ -711,6 +735,149 @@ void tcp_ao_syncookie(struct sock *sk, const struct s= k_buff *skb, treq->maclen =3D tcp_ao_maclen(key); } =20 +static enum skb_drop_reason +tcp_ao_verify_hash(const struct sock *sk, const struct sk_buff *skb, + unsigned short int family, struct tcp_ao_info *info, + const struct tcp_ao_hdr *aoh, struct tcp_ao_key *key, + u8 *traffic_key, u8 *phash, u32 sne) +{ + u8 maclen =3D aoh->length - sizeof(struct tcp_ao_hdr); + const struct tcphdr *th =3D tcp_hdr(skb); + void *hash_buf =3D NULL; + + if (maclen !=3D tcp_ao_maclen(key)) + return SKB_DROP_REASON_TCP_AOFAILURE; + + hash_buf =3D kmalloc(tcp_ao_digest_size(key), GFP_ATOMIC); + if (!hash_buf) + return SKB_DROP_REASON_NOT_SPECIFIED; + + /* XXX: make it per-AF callback? */ + tcp_ao_hash_skb(family, hash_buf, key, sk, skb, traffic_key, + (phash - (u8 *)th), sne); + if (memcmp(phash, hash_buf, maclen)) { + kfree(hash_buf); + return SKB_DROP_REASON_TCP_AOFAILURE; + } + kfree(hash_buf); + return SKB_NOT_DROPPED_YET; +} + +enum skb_drop_reason +tcp_inbound_ao_hash(struct sock *sk, const struct sk_buff *skb, + unsigned short int family, const struct request_sock *req, + const struct tcp_ao_hdr *aoh) +{ + const struct tcphdr *th =3D tcp_hdr(skb); + u8 *phash =3D (u8 *)(aoh + 1); /* hash goes just after the header */ + struct tcp_ao_info *info; + enum skb_drop_reason ret; + struct tcp_ao_key *key; + __be32 sisn, disn; + u8 *traffic_key; + u32 sne =3D 0; + + info =3D rcu_dereference(tcp_sk(sk)->ao_info); + if (!info) + return SKB_DROP_REASON_TCP_AOUNEXPECTED; + + if (unlikely(th->syn)) { + sisn =3D th->seq; + disn =3D 0; + } + + /* Fast-path */ + /* TODO: fix fastopen and simultaneous open (TCPF_SYN_RECV) */ + if (likely((1 << sk->sk_state) & (TCP_AO_ESTABLISHED | TCPF_SYN_RECV))) { + enum skb_drop_reason err; + struct tcp_ao_key *current_key; + + /* Check if this socket's rnext_key matches the keyid in the + * packet. If not we lookup the key based on the keyid + * matching the rcvid in the mkt. + */ + key =3D READ_ONCE(info->rnext_key); + if (key->rcvid !=3D aoh->keyid) { + key =3D tcp_ao_established_key(info, -1, aoh->keyid); + if (!key) + goto key_not_found; + } + + /* Delayed retransmitted SYN */ + if (unlikely(th->syn && !th->ack)) + goto verify_hash; + + sne =3D 0; + /* Established socket, traffic key are cached */ + traffic_key =3D rcv_other_key(key); + err =3D tcp_ao_verify_hash(sk, skb, family, info, aoh, key, + traffic_key, phash, sne); + if (err) + return err; + current_key =3D READ_ONCE(info->current_key); + /* Key rotation: the peer asks us to use new key (RNext) */ + if (unlikely(aoh->rnext_keyid !=3D current_key->sndid)) { + /* If the key is not found we do nothing. */ + key =3D tcp_ao_established_key(info, aoh->rnext_keyid, -1); + if (key) + /* pairs with tcp_ao_del_cmd */ + WRITE_ONCE(info->current_key, key); + } + return SKB_NOT_DROPPED_YET; + } + + /* Lookup key based on peer address and keyid. + * current_key and rnext_key must not be used on tcp listen + * sockets as otherwise: + * - request sockets would race on those key pointers + * - tcp_ao_del_cmd() allows async key removal + */ + key =3D tcp_ao_inbound_lookup(family, sk, skb, -1, aoh->keyid); + if (!key) + goto key_not_found; + + if (th->syn && !th->ack) + goto verify_hash; + + if ((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_NEW_SYN_RECV)) { + /* Make the initial syn the likely case here */ + if (unlikely(req)) { + sne =3D 0; + sisn =3D htonl(tcp_rsk(req)->rcv_isn); + disn =3D htonl(tcp_rsk(req)->snt_isn); + } else if (unlikely(th->ack && !th->syn)) { + /* Possible syncookie packet */ + sisn =3D htonl(ntohl(th->seq) - 1); + disn =3D htonl(ntohl(th->ack_seq) - 1); + sne =3D 0; + } else if (unlikely(!th->syn)) { + /* no way to figure out initial sisn/disn - drop */ + return SKB_DROP_REASON_TCP_FLAGS; + } + } else if (sk->sk_state =3D=3D TCP_SYN_SENT) { + disn =3D info->lisn; + if (th->syn || th->rst) + sisn =3D th->seq; + else + sisn =3D info->risn; + } else { + WARN_ONCE(1, "TCP-AO: Unexpected sk_state %d", sk->sk_state); + return SKB_DROP_REASON_TCP_AOFAILURE; + } +verify_hash: + traffic_key =3D kmalloc(tcp_ao_digest_size(key), GFP_ATOMIC); + if (!traffic_key) + return SKB_DROP_REASON_NOT_SPECIFIED; + tcp_ao_calc_key_skb(key, traffic_key, skb, sisn, disn, family); + ret =3D tcp_ao_verify_hash(sk, skb, family, info, aoh, key, + traffic_key, phash, sne); + kfree(traffic_key); + return ret; + +key_not_found: + return SKB_DROP_REASON_TCP_AOKEYNOTFOUND; +} + static int tcp_ao_cache_traffic_keys(const struct sock *sk, struct tcp_ao_info *ao, struct tcp_ao_key *ao_key) diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 43a5de1b14fa..a10a5011c60f 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -2197,9 +2197,9 @@ int tcp_v4_rcv(struct sk_buff *skb) if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb)) drop_reason =3D SKB_DROP_REASON_XFRM_POLICY; else - drop_reason =3D tcp_inbound_md5_hash(sk, skb, - &iph->saddr, &iph->daddr, - AF_INET, dif, sdif); + drop_reason =3D tcp_inbound_hash(sk, req, skb, + &iph->saddr, &iph->daddr, + AF_INET, dif, sdif); if (unlikely(drop_reason)) { sk_drops_add(sk, skb); reqsk_put(req); @@ -2276,8 +2276,8 @@ int tcp_v4_rcv(struct sk_buff *skb) goto discard_and_relse; } =20 - drop_reason =3D tcp_inbound_md5_hash(sk, skb, &iph->saddr, - &iph->daddr, AF_INET, dif, sdif); + drop_reason =3D tcp_inbound_hash(sk, NULL, skb, &iph->saddr, &iph->daddr, + AF_INET, dif, sdif); if (drop_reason) goto discard_and_relse; =20 diff --git a/net/ipv6/tcp_ao.c b/net/ipv6/tcp_ao.c index ec320781bc5c..984a75f96e20 100644 --- a/net/ipv6/tcp_ao.c +++ b/net/ipv6/tcp_ao.c @@ -49,6 +49,18 @@ static int tcp_v6_ao_calc_key(struct tcp_ao_key *mkt, u8= *key, return err; } =20 +int tcp_v6_ao_calc_key_skb(struct tcp_ao_key *mkt, u8 *key, + const struct sk_buff *skb, + __be32 sisn, __be32 disn) +{ + const struct ipv6hdr *iph =3D ipv6_hdr(skb); + const struct tcphdr *th =3D tcp_hdr(skb); + + return tcp_v6_ao_calc_key(mkt, key, &iph->saddr, + &iph->daddr, th->source, + th->dest, sisn, disn); +} + int tcp_v6_ao_calc_key_sk(struct tcp_ao_key *mkt, u8 *key, const struct sock *sk, __be32 sisn, __be32 disn, bool send) diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 1ef428d9f052..026e2d49706a 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1779,9 +1779,9 @@ INDIRECT_CALLABLE_SCOPE int tcp_v6_rcv(struct sk_buff= *skb) struct sock *nsk; =20 sk =3D req->rsk_listener; - drop_reason =3D tcp_inbound_md5_hash(sk, skb, - &hdr->saddr, &hdr->daddr, - AF_INET6, dif, sdif); + drop_reason =3D tcp_inbound_hash(sk, req, skb, + &hdr->saddr, &hdr->daddr, + AF_INET6, dif, sdif); if (drop_reason) { sk_drops_add(sk, skb); reqsk_put(req); @@ -1854,8 +1854,8 @@ INDIRECT_CALLABLE_SCOPE int tcp_v6_rcv(struct sk_buff= *skb) goto discard_and_relse; } =20 - drop_reason =3D tcp_inbound_md5_hash(sk, skb, &hdr->saddr, &hdr->daddr, - AF_INET6, dif, sdif); + drop_reason =3D tcp_inbound_hash(sk, NULL, skb, &hdr->saddr, &hdr->daddr, + AF_INET6, dif, sdif); if (drop_reason) goto discard_and_relse; =20 @@ -2083,6 +2083,7 @@ static const struct tcp_sock_af_ops tcp_sock_ipv6_map= ped_specific =3D { .ao_lookup =3D tcp_v6_ao_lookup, .calc_ao_hash =3D tcp_v4_ao_hash_skb, .ao_parse =3D tcp_v6_parse_ao, + .ao_calc_key_sk =3D tcp_v4_ao_calc_key_sk, #endif }; #endif --=20 2.41.0