From nobody Thu Apr 9 14:08:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1D28230EF82; Sat, 7 Mar 2026 22:46:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772923575; cv=none; b=NwZLIoX2nfOkzGiHEFikczX7BNyetKmRvCQbWEG91Ywkh0myvi4iXjkrL5GfOADp9HEiuqSM0J1SR7F0i3OGBHWi2HTAHriIffesW3wduxGJVFCskVmvyHb44JmTcu97u4SQVHTkS7qFH8YKRJ9IiLvDACnaSp96PDlbCVYqQuo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772923575; c=relaxed/simple; bh=XvVoqZTH1UMU+rp/+jfDmpOYMCXjxsiugo9h4jyyOTo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=LvAJ/v7hyWI+15dgIlDL/WIxy37UsyVm2YY0VCVRwPvgit9tRl5Q2YS4FDC/XOgyCmOU2B/os9BsWHmaTRe4ef7hVehSIQHFvMmxe3LWu7oF8BiUUUv4I0A8Tr8EM35RB0Y1t/f7Frql3y19ICSXGkWZP0SE5czQT+lYc1WyL6Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=A1He2TgJ; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="A1He2TgJ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 508B9C2BC87; Sat, 7 Mar 2026 22:46:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1772923574; bh=XvVoqZTH1UMU+rp/+jfDmpOYMCXjxsiugo9h4jyyOTo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=A1He2TgJVisXhshbCSo2K9rvMYPSdAu2qT9cjT2z4spW9+W5/6zVg81Pz6GmSQXod XZyHCx1brx9XMDJeG6mJ4Za3pjUOLf/S7jfH5GYbBd1yMQJ0g8AhiuIRq7003jIshU NFBIY/wtC4UgBRQp7XcYQYVeBCwd4rKUFjOOoVKI5bV9oP8AgXtiKKmv5M6BBl3kia JPaRJVinNwoF3SP3VjDTGaUBXROIwvtHcyb/2Rwir6oUe59iSe2OblcHtlVcvMSoO+ gDpScy63stWODXepIOLkDtJreIGc+Yb5pAlj+/tElhBgs64sq6E68eDHvaoAESgBdA TYhPENAW2xj9A== From: Eric Biggers To: netdev@vger.kernel.org Cc: linux-crypto@vger.kernel.org, linux-kernel@vger.kernel.org, Eric Dumazet , Neal Cardwell , Kuniyuki Iwashima , "David S . Miller" , David Ahern , Jakub Kicinski , Paolo Abeni , Simon Horman , Ard Biesheuvel , "Jason A . Donenfeld" , Herbert Xu , Dmitry Safonov <0x7f454c46@gmail.com>, Eric Biggers Subject: [RFC PATCH 1/8] net/tcp-ao: Drop support for most non-RFC-specified algorithms Date: Sat, 7 Mar 2026 14:43:34 -0800 Message-ID: <20260307224341.5644-2-ebiggers@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260307224341.5644-1-ebiggers@kernel.org> References: <20260307224341.5644-1-ebiggers@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" RFC 5926 (https://datatracker.ietf.org/doc/html/rfc5926) specifies the use of AES-128-CMAC and HMAC-SHA1 with TCP-AO. This includes a specification for how traffic keys shall be derived for each algorithm. Support for any other algorithms with TCP-AO isn't standardized, though an expired Internet Draft (a work-in-progress document, not a standard) from 2019 does propose adding HMAC-SHA256 support: https://datatracker.ietf.org/doc/html/draft-nayak-tcp-sha2-03 Since both documents specify the KDF for each algorithm individually, it isn't necessarily clear how any other algorithm should be integrated. Nevertheless, the Linux implementation of TCP-AO allows userspace to specify the MAC algorithm as a string tcp_ao_add::alg_name naming either "cmac(aes128)" or an arbitrary algorithm in the crypto_ahash API. The set of valid strings is undocumented. The implementation assumes that "cmac(aes128)" is the only algorithm that requires an entropy extraction step and that all algorithms accept keys with length equal to the untruncated MAC; thus, arbitrary HMAC algorithms probably do work, but some other MAC algorithms like AES-256-CMAC have never actually worked. Unfortunately, this undocumented string allows many obsolete, insecure, or redundant algorithms. For example, "hmac(md5)" and the non-cryptographic "crc32" are accepted. It also ties the implementation to crypto_ahash and requires that most memory be dynamically allocated, making the implementation unnecessarily complex and inefficient. Fortunately, it's very likely that only a few algorithms are actually used in practice. Let's restrict the set of allowed algorithms to "cmac(aes128)" (or "cmac(aes)" with keylen=3D16), "hmac(sha1)", and "hmac(sha256)". The first two are the actually standard ones, while HMAC-SHA256 seems like a reasonable algorithm to continue supporting as a Linux extension, considering the Internet Draft for it and the fact that SHA-256 is the usual choice of upgrade from the outdated SHA-1. Signed-off-by: Eric Biggers Reviewed-by: Ard Biesheuvel --- net/ipv4/tcp_ao.c | 4 ++ tools/testing/selftests/net/tcp_ao/config | 1 - .../selftests/net/tcp_ao/key-management.c | 41 ++----------------- 3 files changed, 7 insertions(+), 39 deletions(-) diff --git a/net/ipv4/tcp_ao.c b/net/ipv4/tcp_ao.c index a97cdf3e6af4c..b21bd69b4e829 100644 --- a/net/ipv4/tcp_ao.c +++ b/net/ipv4/tcp_ao.c @@ -1561,10 +1561,14 @@ static struct tcp_ao_key *tcp_ao_key_alloc(struct s= ock *sk, cmd->alg_name[ARRAY_SIZE(cmd->alg_name) - 1] =3D '\0'; =20 /* RFC5926, 3.1.1.2. KDF_AES_128_CMAC */ if (!strcmp("cmac(aes128)", algo)) algo =3D "cmac(aes)"; + else if (strcmp("hmac(sha1)", algo) && + strcmp("hmac(sha256)", algo) && + (strcmp("cmac(aes)", algo) || cmd->keylen !=3D 16)) + return ERR_PTR(-ENOENT); =20 /* Full TCP header (th->doff << 2) should fit into scratch area, * see tcp_ao_hash_header(). */ pool_id =3D tcp_sigpool_alloc_ahash(algo, 60); diff --git a/tools/testing/selftests/net/tcp_ao/config b/tools/testing/self= tests/net/tcp_ao/config index 971cb6fa2d630..0ec38c167e6df 100644 --- a/tools/testing/selftests/net/tcp_ao/config +++ b/tools/testing/selftests/net/tcp_ao/config @@ -1,7 +1,6 @@ CONFIG_CRYPTO_HMAC=3Dy -CONFIG_CRYPTO_RMD160=3Dy CONFIG_CRYPTO_SHA1=3Dy CONFIG_IPV6=3Dy CONFIG_IPV6_MULTIPLE_TABLES=3Dy CONFIG_NET_L3_MASTER_DEV=3Dy CONFIG_NET_VRF=3Dy diff --git a/tools/testing/selftests/net/tcp_ao/key-management.c b/tools/te= sting/selftests/net/tcp_ao/key-management.c index 69d9a7a05d5c1..d86bb380b79f7 100644 --- a/tools/testing/selftests/net/tcp_ao/key-management.c +++ b/tools/testing/selftests/net/tcp_ao/key-management.c @@ -378,35 +378,10 @@ static void check_listen_socket(void) this_ip_dest, DEFAULT_TEST_PREFIX, false, true, 20, 10, FAULT_CURRNEXT); close(sk); } =20 -static const char *fips_fpath =3D "/proc/sys/crypto/fips_enabled"; -static bool is_fips_enabled(void) -{ - static int fips_checked =3D -1; - FILE *fenabled; - int enabled; - - if (fips_checked >=3D 0) - return !!fips_checked; - if (access(fips_fpath, R_OK)) { - if (errno !=3D ENOENT) - test_error("Can't open %s", fips_fpath); - fips_checked =3D 0; - return false; - } - fenabled =3D fopen(fips_fpath, "r"); - if (!fenabled) - test_error("Can't open %s", fips_fpath); - if (fscanf(fenabled, "%d", &enabled) !=3D 1) - test_error("Can't read from %s", fips_fpath); - fclose(fenabled); - fips_checked =3D !!enabled; - return !!fips_checked; -} - struct test_key { char password[TCP_AO_MAXKEYLEN]; const char *alg; unsigned int len; uint8_t client_keyid; @@ -428,18 +403,11 @@ struct key_collection { }; =20 static struct key_collection collection; =20 #define TEST_MAX_MACLEN 16 -const char *test_algos[] =3D { - "cmac(aes128)", - "hmac(sha1)", "hmac(sha512)", "hmac(sha384)", "hmac(sha256)", - "hmac(sha224)", "hmac(sha3-512)", - /* only if !CONFIG_FIPS */ -#define TEST_NON_FIPS_ALGOS 2 - "hmac(rmd160)", "hmac(md5)" -}; +const char *test_algos[] =3D { "cmac(aes128)", "hmac(sha1)", "hmac(sha256)= " }; const unsigned int test_maclens[] =3D { 1, 4, 12, 16 }; #define MACLEN_SHIFT 2 #define ALGOS_SHIFT 4 =20 static unsigned int make_mask(unsigned int shift, unsigned int prev_shift) @@ -450,11 +418,11 @@ static unsigned int make_mask(unsigned int shift, uns= igned int prev_shift) } =20 static void init_key_in_collection(unsigned int index, bool randomized) { struct test_key *key =3D &collection.keys[index]; - unsigned int algos_nr, algos_index; + unsigned int algos_index; =20 /* Same for randomized and non-randomized test flows */ key->client_keyid =3D index; key->server_keyid =3D 127 + index; key->matches_client =3D 1; @@ -472,14 +440,11 @@ static void init_key_in_collection(unsigned int index= , bool randomized) unsigned int shift =3D MACLEN_SHIFT; =20 key->maclen =3D test_maclens[index & make_mask(shift, 0)]; algos_index =3D index & make_mask(ALGOS_SHIFT, shift); } - algos_nr =3D ARRAY_SIZE(test_algos); - if (is_fips_enabled()) - algos_nr -=3D TEST_NON_FIPS_ALGOS; - key->alg =3D test_algos[algos_index % algos_nr]; + key->alg =3D test_algos[algos_index % ARRAY_SIZE(test_algos)]; } =20 static int init_default_key_collection(unsigned int nr_keys, bool randomiz= ed) { size_t key_sz =3D sizeof(collection.keys[0]); --=20 2.53.0 From nobody Thu Apr 9 14:08:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 930F331F9A6; Sat, 7 Mar 2026 22:46:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772923575; cv=none; b=Q3GrG6c55G26UcZgwXAZKZp071eE45LS3JeTLbgXvt0PqT2Ir0Jb4eOv9vm1Ji7itztLFHyw9mG4HcgKCiNDdU/8+g16Kpedl5LdLDwnNB6WZ7RIBcZQmv9QMg+fujUVtf8h1ieG+Vtno+o5e6UPZlhXJ+/A8ZWPIGslWqrb1oc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772923575; c=relaxed/simple; bh=JdP43UekUUIF5xjIRJ50CJU+NjrHRTlXAUqp4IINmQE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=CkDGCkjqTZnEB90RfAXOUtFvNNAiKY95vgYv1l3kQhDbcfeuK9lgFvSoZ1eTMDzukWOgXqZWCFWRAKYMCfs20RnCx/Yakx1qVyA0Xju8JWp73ixzCi8u451WtKICTDr/PAXcXAZcA74PYmTW/6afeIHXUSVO+GMOzQJMzZF6bow= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=QoU71WrA; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="QoU71WrA" Received: by smtp.kernel.org (Postfix) with ESMTPSA id DEC7CC2BCB1; Sat, 7 Mar 2026 22:46:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1772923575; bh=JdP43UekUUIF5xjIRJ50CJU+NjrHRTlXAUqp4IINmQE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=QoU71WrAMYeUuK4HXnzJGTotaK4TxnZdIkyyfpPLjQHOSbEXhB+hm4KI3wYXD6bVn riVxhNqcDb/gZvPUkHNOUpXNIwipaf6eNa7uxccRY1tVbUqX5VMCfRIjoDuU7pbxbr Fzqs/3jx65+CTIPBrEOH+q5uWO/L9pqWjya9vY12B0radrBvffQQgT1qpW0PUrIfXq jl6fNtqM0xiD0wSPZt0NPoVrOJnfeHbt1cZ1S7FxviWvlGT2bLyKVC459nVm8OQrAo flhDDFB/xQJBjapm1ONAbp39ThU1cL8bNIyjxTV+c3nG+mjWX2kD6b3b7Z8Ix94Cm9 yKKWyyQB7uCKg== From: Eric Biggers To: netdev@vger.kernel.org Cc: linux-crypto@vger.kernel.org, linux-kernel@vger.kernel.org, Eric Dumazet , Neal Cardwell , Kuniyuki Iwashima , "David S . Miller" , David Ahern , Jakub Kicinski , Paolo Abeni , Simon Horman , Ard Biesheuvel , "Jason A . Donenfeld" , Herbert Xu , Dmitry Safonov <0x7f454c46@gmail.com>, Eric Biggers Subject: [RFC PATCH 2/8] net/tcp-ao: Use crypto library API instead of crypto_ahash Date: Sat, 7 Mar 2026 14:43:35 -0800 Message-ID: <20260307224341.5644-3-ebiggers@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260307224341.5644-1-ebiggers@kernel.org> References: <20260307224341.5644-1-ebiggers@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Currently the kernel's TCP-AO implementation does the MAC and KDF computations using the crypto_ahash API. This API is inefficient and difficult to use, and it has required extensive workarounds in the form of per-CPU preallocated objects (tcp_sigpool) to work at all. Let's use lib/crypto/ instead. This means switching to straightforward stack-allocated structures, virtually addressed buffers, and direct function calls. It also means removing quite a bit of error handling. This makes TCP-AO quite a bit faster. This also enables many additional cleanups, which later commits will handle: removing tcp-sigpool, removing support for crypto_tfm cloning, removing more error handling, and replacing more dynamically-allocated buffers with stack buffers based on the now-statically-known limits. Signed-off-by: Eric Biggers Reviewed-by: Ard Biesheuvel --- include/net/tcp_ao.h | 27 +- net/ipv4/Kconfig | 5 +- net/ipv4/tcp_ao.c | 523 +++++++++++----------- net/ipv6/tcp_ao.c | 63 ++- tools/testing/selftests/net/tcp_ao/config | 2 - 5 files changed, 304 insertions(+), 316 deletions(-) diff --git a/include/net/tcp_ao.h b/include/net/tcp_ao.h index 1e9e27d6e06ba..f845bc631bc1e 100644 --- a/include/net/tcp_ao.h +++ b/include/net/tcp_ao.h @@ -1,11 +1,10 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ #ifndef _TCP_AO_H #define _TCP_AO_H =20 -#define TCP_AO_KEY_ALIGN 1 -#define __tcp_ao_key_align __aligned(TCP_AO_KEY_ALIGN) +#include /* for SHA256_DIGEST_SIZE */ =20 union tcp_ao_addr { struct in_addr a4; #if IS_ENABLED(CONFIG_IPV6) struct in6_addr a6; @@ -30,15 +29,26 @@ struct tcp_ao_counters { atomic64_t key_not_found; atomic64_t ao_required; atomic64_t dropped_icmp; }; =20 +enum tcp_ao_algo_id { + TCP_AO_ALGO_HMAC_SHA1 =3D 1, /* specified by RFC 5926 */ + TCP_AO_ALGO_HMAC_SHA256 =3D 2, /* Linux extension */ + TCP_AO_ALGO_AES_128_CMAC =3D 3, /* specified by RFC 5926 */ +}; + +#define TCP_AO_MAX_MAC_LEN SHA256_DIGEST_SIZE +#define TCP_AO_MAX_TRAFFIC_KEY_LEN SHA256_DIGEST_SIZE + +struct tcp_ao_mac_ctx; + struct tcp_ao_key { struct hlist_node node; union tcp_ao_addr addr; - u8 key[TCP_AO_MAXKEYLEN] __tcp_ao_key_align; - unsigned int tcp_sigpool_id; + u8 key[TCP_AO_MAXKEYLEN]; + enum tcp_ao_algo_id algo; unsigned int digest_size; int l3index; u8 prefixlen; u8 family; u8 keylen; @@ -166,18 +176,19 @@ struct tcp6_ao_context { __be16 dport; __be32 sisn; __be32 disn; }; =20 -struct tcp_sigpool; /* Established states are fast-path and there always is current_key/rnext_= key */ #define TCP_AO_ESTABLISHED (TCPF_ESTABLISHED | TCPF_FIN_WAIT1 | TCPF_FIN_W= AIT2 | \ TCPF_CLOSE_WAIT | TCPF_LAST_ACK | TCPF_CLOSING) =20 int tcp_ao_transmit_skb(struct sock *sk, struct sk_buff *skb, struct tcp_ao_key *key, struct tcphdr *th, __u8 *hash_location); +void tcp_ao_mac_update(struct tcp_ao_mac_ctx *mac_ctx, const void *data, + size_t data_len); 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, const u8 *tkey, int hash_offset, u32 sne); int tcp_parse_ao(struct sock *sk, int cmd, unsigned short int family, @@ -186,12 +197,12 @@ struct tcp_ao_key *tcp_ao_established_key(const struc= t sock *sk, struct tcp_ao_info *ao, int sndid, int rcvid); int tcp_ao_copy_all_matching(const struct sock *sk, struct sock *newsk, struct request_sock *req, struct sk_buff *skb, int family); -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_calc_traffic_key(const struct tcp_ao_key *mkt, u8 *traffic_key, + const void *input, unsigned int input_len); void tcp_ao_destroy_sock(struct sock *sk, bool twsk); void tcp_ao_time_wait(struct tcp_timewait_sock *tcptw, struct tcp_sock *tp= ); bool tcp_ao_ignore_icmp(const struct sock *sk, int family, int type, int c= ode); int tcp_ao_get_mkts(struct sock *sk, sockptr_t optval, sockptr_t optlen); int tcp_ao_get_sock_info(struct sock *sk, sockptr_t optval, sockptr_t optl= en); @@ -232,11 +243,11 @@ struct tcp_ao_key *tcp_v4_ao_lookup_rsk(const struct = sock *sk, int sndid, int rcvid); int tcp_v4_ao_hash_skb(char *ao_hash, struct tcp_ao_key *key, const struct sock *sk, const struct sk_buff *skb, const u8 *tkey, int hash_offset, u32 sne); /* ipv6 specific functions */ -int tcp_v6_ao_hash_pseudoheader(struct tcp_sigpool *hp, +int tcp_v6_ao_hash_pseudoheader(struct tcp_ao_mac_ctx *mac_ctx, 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, diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig index df922f9f52891..0fa293527cee9 100644 --- a/net/ipv4/Kconfig +++ b/net/ipv4/Kconfig @@ -745,13 +745,14 @@ config DEFAULT_TCP_CONG config TCP_SIGPOOL tristate =20 config TCP_AO bool "TCP: Authentication Option (RFC5925)" - select CRYPTO + select CRYPTO_LIB_AES_CBC_MACS + select CRYPTO_LIB_SHA1 + select CRYPTO_LIB_SHA256 select CRYPTO_LIB_UTILS - select TCP_SIGPOOL depends on 64BIT && IPV6 !=3D m # seq-number extension needs WRITE_ONCE(u= 64) help TCP-AO specifies the use of stronger Message Authentication Codes (MACs= ), protects against replays for long-lived TCP connections, and provides more details on the association of security with TCP diff --git a/net/ipv4/tcp_ao.c b/net/ipv4/tcp_ao.c index b21bd69b4e829..0d24cbd66c9a1 100644 --- a/net/ipv4/tcp_ao.c +++ b/net/ipv4/tcp_ao.c @@ -7,11 +7,13 @@ * Francesco Ruggeri * Salam Noureddine */ #define pr_fmt(fmt) "TCP: " fmt =20 -#include +#include +#include +#include #include #include #include =20 #include @@ -19,36 +21,137 @@ #include #include =20 DEFINE_STATIC_KEY_DEFERRED_FALSE(tcp_ao_needed, HZ); =20 -int tcp_ao_calc_traffic_key(struct tcp_ao_key *mkt, u8 *key, void *ctx, - unsigned int len, struct tcp_sigpool *hp) -{ - struct scatterlist sg; - int ret; +static const struct tcp_ao_algo { + const char *name; + unsigned int digest_size; +} tcp_ao_algos[] =3D { + [TCP_AO_ALGO_HMAC_SHA1] =3D { + .name =3D "hmac(sha1)", + .digest_size =3D SHA1_DIGEST_SIZE, + }, + [TCP_AO_ALGO_HMAC_SHA256] =3D { + .name =3D "hmac(sha256)", + .digest_size =3D SHA256_DIGEST_SIZE, + }, + [TCP_AO_ALGO_AES_128_CMAC] =3D { + .name =3D "cmac(aes128)", + .digest_size =3D AES_BLOCK_SIZE, /* same as AES_KEYSIZE_128 */ + }, +}; + +struct tcp_ao_mac_ctx { + enum tcp_ao_algo_id algo; + union { + struct hmac_sha1_ctx hmac_sha1; + struct hmac_sha256_ctx hmac_sha256; + struct { + struct aes_cmac_key key; + struct aes_cmac_ctx ctx; + } aes_cmac; + }; +}; + +static const struct tcp_ao_algo *tcp_ao_find_algo(const char *name) +{ + for (size_t i =3D 0; i < ARRAY_SIZE(tcp_ao_algos); i++) { + const struct tcp_ao_algo *algo =3D &tcp_ao_algos[i]; + + if (!algo->name) + continue; + if (WARN_ON_ONCE(algo->digest_size > TCP_AO_MAX_MAC_LEN || + algo->digest_size > + TCP_AO_MAX_TRAFFIC_KEY_LEN)) + continue; + if (strcmp(name, algo->name) =3D=3D 0) + return algo; + } + return NULL; +} =20 - if (crypto_ahash_setkey(crypto_ahash_reqtfm(hp->req), - mkt->key, mkt->keylen)) - goto clear_hash; +static void tcp_ao_mac_init(struct tcp_ao_mac_ctx *mac_ctx, + enum tcp_ao_algo_id algo, const u8 *traffic_key) +{ + mac_ctx->algo =3D algo; + switch (mac_ctx->algo) { + case TCP_AO_ALGO_HMAC_SHA1: + hmac_sha1_init_usingrawkey(&mac_ctx->hmac_sha1, traffic_key, + SHA1_DIGEST_SIZE); + return; + case TCP_AO_ALGO_HMAC_SHA256: + hmac_sha256_init_usingrawkey(&mac_ctx->hmac_sha256, traffic_key, + SHA256_DIGEST_SIZE); + return; + case TCP_AO_ALGO_AES_128_CMAC: + aes_cmac_preparekey(&mac_ctx->aes_cmac.key, traffic_key, + AES_KEYSIZE_128); + aes_cmac_init(&mac_ctx->aes_cmac.ctx, &mac_ctx->aes_cmac.key); + return; + default: + WARN_ON_ONCE(1); /* algo was validated earlier. */ + } +} =20 - ret =3D crypto_ahash_init(hp->req); - if (ret) - goto clear_hash; +void tcp_ao_mac_update(struct tcp_ao_mac_ctx *mac_ctx, const void *data, + size_t data_len) +{ + switch (mac_ctx->algo) { + case TCP_AO_ALGO_HMAC_SHA1: + hmac_sha1_update(&mac_ctx->hmac_sha1, data, data_len); + return; + case TCP_AO_ALGO_HMAC_SHA256: + hmac_sha256_update(&mac_ctx->hmac_sha256, data, data_len); + return; + case TCP_AO_ALGO_AES_128_CMAC: + aes_cmac_update(&mac_ctx->aes_cmac.ctx, data, data_len); + return; + default: + WARN_ON_ONCE(1); /* algo was validated earlier. */ + } +} =20 - sg_init_one(&sg, ctx, len); - ahash_request_set_crypt(hp->req, &sg, key, len); - crypto_ahash_update(hp->req); +static void tcp_ao_mac_final(struct tcp_ao_mac_ctx *mac_ctx, u8 *out) +{ + switch (mac_ctx->algo) { + case TCP_AO_ALGO_HMAC_SHA1: + hmac_sha1_final(&mac_ctx->hmac_sha1, out); + return; + case TCP_AO_ALGO_HMAC_SHA256: + hmac_sha256_final(&mac_ctx->hmac_sha256, out); + return; + case TCP_AO_ALGO_AES_128_CMAC: + aes_cmac_final(&mac_ctx->aes_cmac.ctx, out); + return; + default: + WARN_ON_ONCE(1); /* algo was validated earlier. */ + } +} =20 - ret =3D crypto_ahash_final(hp->req); - if (ret) - goto clear_hash; +void tcp_ao_calc_traffic_key(const struct tcp_ao_key *mkt, u8 *traffic_key, + const void *input, unsigned int input_len) +{ + switch (mkt->algo) { + case TCP_AO_ALGO_HMAC_SHA1: + hmac_sha1_usingrawkey(mkt->key, mkt->keylen, input, input_len, + traffic_key); + return; + case TCP_AO_ALGO_HMAC_SHA256: + hmac_sha256_usingrawkey(mkt->key, mkt->keylen, input, input_len, + traffic_key); + return; + case TCP_AO_ALGO_AES_128_CMAC: { + struct aes_cmac_key k; =20 - return 0; -clear_hash: - memset(key, 0, tcp_ao_digest_size(mkt)); - return 1; + aes_cmac_preparekey(&k, mkt->key, AES_KEYSIZE_128); + aes_cmac(&k, input, input_len, traffic_key); + return; + } + default: + WARN_ON_ONCE(1); /* algo was validated earlier. */ + } } =20 bool tcp_ao_ignore_icmp(const struct sock *sk, int family, int type, int c= ode) { bool ignore_icmp =3D false; @@ -252,33 +355,30 @@ static struct tcp_ao_key *tcp_ao_copy_key(struct sock= *sk, if (!new_key) return NULL; =20 *new_key =3D *key; INIT_HLIST_NODE(&new_key->node); - tcp_sigpool_get(new_key->tcp_sigpool_id); atomic64_set(&new_key->pkt_good, 0); atomic64_set(&new_key->pkt_bad, 0); =20 return new_key; } =20 static void tcp_ao_key_free_rcu(struct rcu_head *head) { struct tcp_ao_key *key =3D container_of(head, struct tcp_ao_key, rcu); =20 - tcp_sigpool_release(key->tcp_sigpool_id); kfree_sensitive(key); } =20 static void tcp_ao_info_free(struct tcp_ao_info *ao) { struct tcp_ao_key *key; struct hlist_node *n; =20 hlist_for_each_entry_safe(key, n, &ao->head, node) { hlist_del(&key->node); - tcp_sigpool_release(key->tcp_sigpool_id); kfree_sensitive(key); } kfree(ao); static_branch_slow_dec_deferred(&tcp_ao_needed); } @@ -344,33 +444,26 @@ static int tcp_v4_ao_calc_key(struct tcp_ao_key *mkt,= u8 *key, struct kdf_input_block { u8 counter; u8 label[6]; struct tcp4_ao_context ctx; __be16 outlen; - } __packed * tmp; - struct tcp_sigpool hp; - int err; - - err =3D tcp_sigpool_start(mkt->tcp_sigpool_id, &hp); - if (err) - return err; - - tmp =3D hp.scratch; - tmp->counter =3D 1; - memcpy(tmp->label, "TCP-AO", 6); - tmp->ctx.saddr =3D saddr; - tmp->ctx.daddr =3D daddr; - tmp->ctx.sport =3D sport; - tmp->ctx.dport =3D dport; - tmp->ctx.sisn =3D sisn; - tmp->ctx.disn =3D disn; - tmp->outlen =3D htons(tcp_ao_digest_size(mkt) * 8); /* in bits */ - - err =3D tcp_ao_calc_traffic_key(mkt, key, tmp, sizeof(*tmp), &hp); - tcp_sigpool_end(&hp); - - return err; + } __packed input =3D { + .counter =3D 1, + .label =3D "TCP-AO", + .ctx =3D { + .saddr =3D saddr, + .daddr =3D daddr, + .sport =3D sport, + .dport =3D dport, + .sisn =3D sisn, + .disn =3D disn, + }, + .outlen =3D htons(tcp_ao_digest_size(mkt) * 8), /* in bits */ + }; + + tcp_ao_calc_traffic_key(mkt, key, &input, sizeof(input)); + return 0; } =20 int tcp_v4_ao_calc_key_sk(struct tcp_ao_key *mkt, u8 *key, const struct sock *sk, __be32 sisn, __be32 disn, bool send) @@ -433,60 +526,57 @@ static int tcp_ao_calc_key_skb(struct tcp_ao_key *mkt= , u8 *key, return tcp_v6_ao_calc_key_skb(mkt, key, skb, sisn, disn); #endif return -EAFNOSUPPORT; } =20 -static int tcp_v4_ao_hash_pseudoheader(struct tcp_sigpool *hp, +static int tcp_v4_ao_hash_pseudoheader(struct tcp_ao_mac_ctx *mac_ctx, __be32 daddr, __be32 saddr, int nbytes) { - struct tcp4_pseudohdr *bp; - struct scatterlist sg; + struct tcp4_pseudohdr phdr =3D { + .saddr =3D saddr, + .daddr =3D daddr, + .pad =3D 0, + .protocol =3D IPPROTO_TCP, + .len =3D cpu_to_be16(nbytes), + }; =20 - bp =3D hp->scratch; - bp->saddr =3D saddr; - bp->daddr =3D daddr; - bp->pad =3D 0; - bp->protocol =3D IPPROTO_TCP; - bp->len =3D cpu_to_be16(nbytes); - - sg_init_one(&sg, bp, sizeof(*bp)); - ahash_request_set_crypt(hp->req, &sg, NULL, sizeof(*bp)); - return crypto_ahash_update(hp->req); + tcp_ao_mac_update(mac_ctx, &phdr, sizeof(phdr)); + return 0; } =20 static int tcp_ao_hash_pseudoheader(unsigned short int family, const struct sock *sk, const struct sk_buff *skb, - struct tcp_sigpool *hp, int nbytes) + struct tcp_ao_mac_ctx *mac_ctx, int nbytes) { const struct tcphdr *th =3D tcp_hdr(skb); =20 /* TODO: Can we rely on checksum being zero to mean outbound pkt? */ if (!th->check) { if (family =3D=3D AF_INET) - return tcp_v4_ao_hash_pseudoheader(hp, sk->sk_daddr, + return tcp_v4_ao_hash_pseudoheader(mac_ctx, sk->sk_daddr, sk->sk_rcv_saddr, skb->len); #if IS_ENABLED(CONFIG_IPV6) else if (family =3D=3D AF_INET6) - return tcp_v6_ao_hash_pseudoheader(hp, &sk->sk_v6_daddr, + return tcp_v6_ao_hash_pseudoheader(mac_ctx, &sk->sk_v6_daddr, &sk->sk_v6_rcv_saddr, skb->len); #endif else return -EAFNOSUPPORT; } =20 if (family =3D=3D AF_INET) { const struct iphdr *iph =3D ip_hdr(skb); =20 - return tcp_v4_ao_hash_pseudoheader(hp, iph->daddr, + return tcp_v4_ao_hash_pseudoheader(mac_ctx, iph->daddr, iph->saddr, skb->len); #if IS_ENABLED(CONFIG_IPV6) } else if (family =3D=3D AF_INET6) { const struct ipv6hdr *iph =3D ipv6_hdr(skb); =20 - return tcp_v6_ao_hash_pseudoheader(hp, &iph->daddr, + return tcp_v6_ao_hash_pseudoheader(mac_ctx, &iph->daddr, &iph->saddr, skb->len); #endif } return -EAFNOSUPPORT; } @@ -504,35 +594,24 @@ u32 tcp_ao_compute_sne(u32 next_sne, u32 next_seq, u3= 2 seq) } =20 return sne; } =20 -/* tcp_ao_hash_sne(struct tcp_sigpool *hp) - * @hp - used for hashing - * @sne - sne value - */ -static int tcp_ao_hash_sne(struct tcp_sigpool *hp, u32 sne) +static void tcp_ao_hash_sne(struct tcp_ao_mac_ctx *mac_ctx, u32 sne) { - struct scatterlist sg; - __be32 *bp; - - bp =3D (__be32 *)hp->scratch; - *bp =3D htonl(sne); + __be32 sne_be32 =3D htonl(sne); =20 - sg_init_one(&sg, bp, sizeof(*bp)); - ahash_request_set_crypt(hp->req, &sg, NULL, sizeof(*bp)); - return crypto_ahash_update(hp->req); + tcp_ao_mac_update(mac_ctx, &sne_be32, sizeof(sne_be32)); } =20 -static int tcp_ao_hash_header(struct tcp_sigpool *hp, - const struct tcphdr *th, - bool exclude_options, u8 *hash, - int hash_offset, int hash_len) +static void tcp_ao_hash_header(struct tcp_ao_mac_ctx *mac_ctx, + const struct tcphdr *th, bool exclude_options, + u8 *hash, int hash_offset, int hash_len) { - struct scatterlist sg; - u8 *hdr =3D hp->scratch; - int err, len; + /* Full TCP header (th->doff << 2) should fit into scratch area. */ + u8 hdr[60]; + int len; =20 /* We are not allowed to change tcphdr, make a local copy */ if (exclude_options) { len =3D sizeof(*th) + sizeof(struct tcp_ao_hdr) + hash_len; memcpy(hdr, th, sizeof(*th)); @@ -548,126 +627,105 @@ static int tcp_ao_hash_header(struct tcp_sigpool *h= p, /* zero out tcp-ao hash */ ((struct tcphdr *)hdr)->check =3D 0; memset(hdr + hash_offset, 0, hash_len); } =20 - sg_init_one(&sg, hdr, len); - ahash_request_set_crypt(hp->req, &sg, NULL, len); - err =3D crypto_ahash_update(hp->req); - WARN_ON_ONCE(err !=3D 0); - return err; + tcp_ao_mac_update(mac_ctx, hdr, len); } =20 int tcp_ao_hash_hdr(unsigned short int family, char *ao_hash, struct tcp_ao_key *key, const u8 *tkey, const union tcp_ao_addr *daddr, const union tcp_ao_addr *saddr, const struct tcphdr *th, u32 sne) { - int tkey_len =3D tcp_ao_digest_size(key); int hash_offset =3D ao_hash - (char *)th; - struct tcp_sigpool hp; - void *hash_buf =3D NULL; - - hash_buf =3D kmalloc(tkey_len, GFP_ATOMIC); - if (!hash_buf) - goto clear_hash_noput; - - if (tcp_sigpool_start(key->tcp_sigpool_id, &hp)) - goto clear_hash_noput; - - if (crypto_ahash_setkey(crypto_ahash_reqtfm(hp.req), tkey, tkey_len)) - goto clear_hash; - - if (crypto_ahash_init(hp.req)) - goto clear_hash; + struct tcp_ao_mac_ctx mac_ctx; + u8 hash_buf[TCP_AO_MAX_MAC_LEN]; =20 - if (tcp_ao_hash_sne(&hp, sne)) - goto clear_hash; + tcp_ao_mac_init(&mac_ctx, key->algo, tkey); + tcp_ao_hash_sne(&mac_ctx, sne); if (family =3D=3D AF_INET) { - if (tcp_v4_ao_hash_pseudoheader(&hp, daddr->a4.s_addr, - saddr->a4.s_addr, th->doff * 4)) - goto clear_hash; + tcp_v4_ao_hash_pseudoheader(&mac_ctx, daddr->a4.s_addr, + saddr->a4.s_addr, th->doff * 4); #if IS_ENABLED(CONFIG_IPV6) } else if (family =3D=3D AF_INET6) { - if (tcp_v6_ao_hash_pseudoheader(&hp, &daddr->a6, - &saddr->a6, th->doff * 4)) - goto clear_hash; + tcp_v6_ao_hash_pseudoheader(&mac_ctx, &daddr->a6, + &saddr->a6, th->doff * 4); #endif } else { WARN_ON_ONCE(1); goto clear_hash; } - if (tcp_ao_hash_header(&hp, th, - !!(key->keyflags & TCP_AO_KEYF_EXCLUDE_OPT), - ao_hash, hash_offset, tcp_ao_maclen(key))) - goto clear_hash; - ahash_request_set_crypt(hp.req, NULL, hash_buf, 0); - if (crypto_ahash_final(hp.req)) - goto clear_hash; + tcp_ao_hash_header(&mac_ctx, th, + !!(key->keyflags & TCP_AO_KEYF_EXCLUDE_OPT), + ao_hash, hash_offset, tcp_ao_maclen(key)); + tcp_ao_mac_final(&mac_ctx, hash_buf); =20 memcpy(ao_hash, hash_buf, tcp_ao_maclen(key)); - tcp_sigpool_end(&hp); - kfree(hash_buf); return 0; =20 clear_hash: - tcp_sigpool_end(&hp); -clear_hash_noput: memset(ao_hash, 0, tcp_ao_maclen(key)); - kfree(hash_buf); return 1; } =20 +static void tcp_ao_hash_skb_data(struct tcp_ao_mac_ctx *mac_ctx, + const struct sk_buff *skb, + unsigned int header_len) +{ + const unsigned int head_data_len =3D skb_headlen(skb) > header_len ? + skb_headlen(skb) - header_len : 0; + const struct skb_shared_info *shi =3D skb_shinfo(skb); + struct sk_buff *frag_iter; + unsigned int i; + + tcp_ao_mac_update(mac_ctx, (const u8 *)tcp_hdr(skb) + header_len, + head_data_len); + + for (i =3D 0; i < shi->nr_frags; ++i) { + const skb_frag_t *f =3D &shi->frags[i]; + u32 p_off, p_len, copied; + const void *vaddr; + struct page *p; + + skb_frag_foreach_page(f, skb_frag_off(f), skb_frag_size(f), + p, p_off, p_len, copied) { + vaddr =3D kmap_local_page(p); + tcp_ao_mac_update(mac_ctx, vaddr + p_off, p_len); + kunmap_local(vaddr); + } + } + + skb_walk_frags(skb, frag_iter) + tcp_ao_hash_skb_data(mac_ctx, frag_iter, 0); +} + 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, const u8 *tkey, int hash_offset, u32 sne) { const struct tcphdr *th =3D tcp_hdr(skb); - int tkey_len =3D tcp_ao_digest_size(key); - struct tcp_sigpool hp; - void *hash_buf =3D NULL; - - hash_buf =3D kmalloc(tkey_len, GFP_ATOMIC); - if (!hash_buf) - goto clear_hash_noput; - - if (tcp_sigpool_start(key->tcp_sigpool_id, &hp)) - goto clear_hash_noput; - - if (crypto_ahash_setkey(crypto_ahash_reqtfm(hp.req), tkey, tkey_len)) - goto clear_hash; - - /* For now use sha1 by default. Depends on alg in tcp_ao_key */ - if (crypto_ahash_init(hp.req)) - goto clear_hash; + struct tcp_ao_mac_ctx mac_ctx; + u8 hash_buf[TCP_AO_MAX_MAC_LEN]; =20 - if (tcp_ao_hash_sne(&hp, sne)) - goto clear_hash; - if (tcp_ao_hash_pseudoheader(family, sk, skb, &hp, skb->len)) - goto clear_hash; - if (tcp_ao_hash_header(&hp, th, - !!(key->keyflags & TCP_AO_KEYF_EXCLUDE_OPT), - ao_hash, hash_offset, tcp_ao_maclen(key))) - goto clear_hash; - if (tcp_sigpool_hash_skb_data(&hp, skb, th->doff << 2)) - goto clear_hash; - ahash_request_set_crypt(hp.req, NULL, hash_buf, 0); - if (crypto_ahash_final(hp.req)) + tcp_ao_mac_init(&mac_ctx, key->algo, tkey); + tcp_ao_hash_sne(&mac_ctx, sne); + if (tcp_ao_hash_pseudoheader(family, sk, skb, &mac_ctx, skb->len)) goto clear_hash; + tcp_ao_hash_header(&mac_ctx, th, + !!(key->keyflags & TCP_AO_KEYF_EXCLUDE_OPT), + ao_hash, hash_offset, tcp_ao_maclen(key)); + tcp_ao_hash_skb_data(&mac_ctx, skb, th->doff << 2); + tcp_ao_mac_final(&mac_ctx, hash_buf); =20 memcpy(ao_hash, hash_buf, tcp_ao_maclen(key)); - tcp_sigpool_end(&hp); - kfree(hash_buf); return 0; =20 clear_hash: - tcp_sigpool_end(&hp); -clear_hash_noput: memset(ao_hash, 0, tcp_ao_maclen(key)); - kfree(hash_buf); return 1; } =20 int tcp_v4_ao_hash_skb(char *ao_hash, struct tcp_ao_key *key, const struct sock *sk, const struct sk_buff *skb, @@ -1278,11 +1336,10 @@ int tcp_ao_copy_all_matching(const struct sock *sk,= struct sock *newsk, return 0; =20 free_and_exit: hlist_for_each_entry_safe(key, key_head, &new_ao->head, node) { hlist_del(&key->node); - tcp_sigpool_release(key->tcp_sigpool_id); atomic_sub(tcp_ao_sizeof_key(key), &newsk->sk_omem_alloc); kfree_sensitive(key); } free_ao: kfree(new_ao); @@ -1334,27 +1391,14 @@ static int tcp_ao_verify_ipv4(struct sock *sk, stru= ct tcp_ao_add *cmd, =20 *addr =3D (union tcp_ao_addr *)&sin->sin_addr; return 0; } =20 -static int tcp_ao_parse_crypto(struct tcp_ao_add *cmd, struct tcp_ao_key *= key) +static int tcp_ao_parse_crypto(const struct tcp_ao_add *cmd, + struct tcp_ao_key *key) { unsigned int syn_tcp_option_space; - bool is_kdf_aes_128_cmac =3D false; - struct crypto_ahash *tfm; - struct tcp_sigpool hp; - void *tmp_key =3D NULL; - int err; - - /* RFC5926, 3.1.1.2. KDF_AES_128_CMAC */ - if (!strcmp("cmac(aes128)", cmd->alg_name)) { - strscpy(cmd->alg_name, "cmac(aes)", sizeof(cmd->alg_name)); - is_kdf_aes_128_cmac =3D (cmd->keylen !=3D 16); - tmp_key =3D kmalloc(cmd->keylen, GFP_KERNEL); - if (!tmp_key) - return -ENOMEM; - } =20 key->maclen =3D cmd->maclen ?: 12; /* 12 is the default in RFC5925 */ =20 /* Check: maclen + tcp-ao header <=3D (MAX_TCP_OPTION_SPACE - mss * - tstamp (including sackperm) @@ -1386,68 +1430,31 @@ static int tcp_ao_parse_crypto(struct tcp_ao_add *c= md, struct tcp_ao_key *key) */ syn_tcp_option_space =3D MAX_TCP_OPTION_SPACE; syn_tcp_option_space -=3D TCPOLEN_MSS_ALIGNED; syn_tcp_option_space -=3D TCPOLEN_TSTAMP_ALIGNED; syn_tcp_option_space -=3D TCPOLEN_WSCALE_ALIGNED; - if (tcp_ao_len_aligned(key) > syn_tcp_option_space) { - err =3D -EMSGSIZE; - goto err_kfree; - } - - key->keylen =3D cmd->keylen; - memcpy(key->key, cmd->key, cmd->keylen); - - err =3D tcp_sigpool_start(key->tcp_sigpool_id, &hp); - if (err) - goto err_kfree; - - tfm =3D crypto_ahash_reqtfm(hp.req); - if (is_kdf_aes_128_cmac) { - void *scratch =3D hp.scratch; - struct scatterlist sg; - - memcpy(tmp_key, cmd->key, cmd->keylen); - sg_init_one(&sg, tmp_key, cmd->keylen); - - /* Using zero-key of 16 bytes as described in RFC5926 */ - memset(scratch, 0, 16); - err =3D crypto_ahash_setkey(tfm, scratch, 16); - if (err) - goto err_pool_end; - - err =3D crypto_ahash_init(hp.req); - if (err) - goto err_pool_end; - - ahash_request_set_crypt(hp.req, &sg, key->key, cmd->keylen); - err =3D crypto_ahash_update(hp.req); - if (err) - goto err_pool_end; - - err |=3D crypto_ahash_final(hp.req); - if (err) - goto err_pool_end; - key->keylen =3D 16; + if (tcp_ao_len_aligned(key) > syn_tcp_option_space) + return -EMSGSIZE; + + if (key->algo =3D=3D TCP_AO_ALGO_AES_128_CMAC && + cmd->keylen !=3D AES_KEYSIZE_128) { + /* RFC5926, 3.1.1.2. KDF_AES_128_CMAC */ + static const u8 zeroes[AES_KEYSIZE_128]; + struct aes_cmac_key extractor; + + aes_cmac_preparekey(&extractor, zeroes, AES_KEYSIZE_128); + aes_cmac(&extractor, cmd->key, cmd->keylen, key->key); + key->keylen =3D AES_KEYSIZE_128; + } else { + memcpy(key->key, cmd->key, cmd->keylen); + key->keylen =3D cmd->keylen; } =20 - err =3D crypto_ahash_setkey(tfm, key->key, key->keylen); - if (err) - goto err_pool_end; - - tcp_sigpool_end(&hp); - kfree_sensitive(tmp_key); - if (tcp_ao_maclen(key) > key->digest_size) return -EINVAL; =20 return 0; - -err_pool_end: - tcp_sigpool_end(&hp); -err_kfree: - kfree_sensitive(tmp_key); - return err; } =20 #if IS_ENABLED(CONFIG_IPV6) static int tcp_ao_verify_ipv6(struct sock *sk, struct tcp_ao_add *cmd, union tcp_ao_addr **paddr, @@ -1547,58 +1554,37 @@ static struct tcp_ao_info *getsockopt_ao_info(struc= t sock *sk) #define TCP_AO_GET_KEYF_VALID (TCP_AO_KEYF_IFINDEX) =20 static struct tcp_ao_key *tcp_ao_key_alloc(struct sock *sk, struct tcp_ao_add *cmd) { - const char *algo =3D cmd->alg_name; - unsigned int digest_size; - struct crypto_ahash *tfm; + const struct tcp_ao_algo *algo; struct tcp_ao_key *key; - struct tcp_sigpool hp; - int err, pool_id; size_t size; =20 /* Force null-termination of alg_name */ cmd->alg_name[ARRAY_SIZE(cmd->alg_name) - 1] =3D '\0'; =20 - /* RFC5926, 3.1.1.2. KDF_AES_128_CMAC */ - if (!strcmp("cmac(aes128)", algo)) - algo =3D "cmac(aes)"; - else if (strcmp("hmac(sha1)", algo) && - strcmp("hmac(sha256)", algo) && - (strcmp("cmac(aes)", algo) || cmd->keylen !=3D 16)) - return ERR_PTR(-ENOENT); - - /* Full TCP header (th->doff << 2) should fit into scratch area, - * see tcp_ao_hash_header(). + /* + * For backwards compatibility, accept "cmac(aes)" as an alias for + * "cmac(aes128)", provided that the key length is exactly 128 bits. */ - pool_id =3D tcp_sigpool_alloc_ahash(algo, 60); - if (pool_id < 0) - return ERR_PTR(pool_id); - - err =3D tcp_sigpool_start(pool_id, &hp); - if (err) - goto err_free_pool; + if (strcmp(cmd->alg_name, "cmac(aes)") =3D=3D 0 && + cmd->keylen =3D=3D AES_KEYSIZE_128) + strscpy(cmd->alg_name, "cmac(aes128)"); =20 - tfm =3D crypto_ahash_reqtfm(hp.req); - digest_size =3D crypto_ahash_digestsize(tfm); - tcp_sigpool_end(&hp); + algo =3D tcp_ao_find_algo(cmd->alg_name); + if (!algo) + return ERR_PTR(-ENOENT); =20 - size =3D sizeof(struct tcp_ao_key) + (digest_size << 1); + size =3D sizeof(struct tcp_ao_key) + (algo->digest_size << 1); key =3D sock_kmalloc(sk, size, GFP_KERNEL); - if (!key) { - err =3D -ENOMEM; - goto err_free_pool; - } + if (!key) + return ERR_PTR(-ENOMEM); =20 - key->tcp_sigpool_id =3D pool_id; - key->digest_size =3D digest_size; + key->algo =3D algo - tcp_ao_algos; + key->digest_size =3D algo->digest_size; return key; - -err_free_pool: - tcp_sigpool_release(pool_id); - return ERR_PTR(err); } =20 static int tcp_ao_add_cmd(struct sock *sk, unsigned short int family, sockptr_t optval, int optlen) { @@ -1755,11 +1741,10 @@ static int tcp_ao_add_cmd(struct sock *sk, unsigned= short int family, WRITE_ONCE(ao_info->rnext_key, key); return 0; =20 err_free_sock: atomic_sub(tcp_ao_sizeof_key(key), &sk->sk_omem_alloc); - tcp_sigpool_release(key->tcp_sigpool_id); kfree_sensitive(key); err_free_ao: if (first) kfree(ao_info); return ret; @@ -2286,11 +2271,15 @@ static int tcp_ao_copy_mkts_to_user(const struct so= ck *sk, opt_out.keylen =3D key->keylen; opt_out.ifindex =3D key->l3index; opt_out.pkt_good =3D atomic64_read(&key->pkt_good); opt_out.pkt_bad =3D atomic64_read(&key->pkt_bad); memcpy(&opt_out.key, key->key, key->keylen); - tcp_sigpool_algo(key->tcp_sigpool_id, opt_out.alg_name, 64); + if (key->algo =3D=3D TCP_AO_ALGO_AES_128_CMAC) + /* This is needed for backwards compatibility. */ + strscpy(opt_out.alg_name, "cmac(aes)"); + else + strscpy(opt_out.alg_name, tcp_ao_algos[key->algo].name); =20 /* Copy key to user */ if (copy_to_sockptr_offset(optval, out_offset, &opt_out, bytes_to_write)) return -EFAULT; diff --git a/net/ipv6/tcp_ao.c b/net/ipv6/tcp_ao.c index 3c09ac26206e3..2dcfe9dda7f4a 100644 --- a/net/ipv6/tcp_ao.c +++ b/net/ipv6/tcp_ao.c @@ -5,11 +5,10 @@ * * Authors: Dmitry Safonov * Francesco Ruggeri * Salam Noureddine */ -#include #include =20 #include #include =20 @@ -22,33 +21,26 @@ static int tcp_v6_ao_calc_key(struct tcp_ao_key *mkt, u= 8 *key, struct kdf_input_block { u8 counter; u8 label[6]; struct tcp6_ao_context ctx; __be16 outlen; - } __packed * tmp; - struct tcp_sigpool hp; - int err; - - err =3D tcp_sigpool_start(mkt->tcp_sigpool_id, &hp); - if (err) - return err; - - tmp =3D hp.scratch; - tmp->counter =3D 1; - memcpy(tmp->label, "TCP-AO", 6); - tmp->ctx.saddr =3D *saddr; - tmp->ctx.daddr =3D *daddr; - tmp->ctx.sport =3D sport; - tmp->ctx.dport =3D dport; - tmp->ctx.sisn =3D sisn; - tmp->ctx.disn =3D disn; - tmp->outlen =3D htons(tcp_ao_digest_size(mkt) * 8); /* in bits */ - - err =3D tcp_ao_calc_traffic_key(mkt, key, tmp, sizeof(*tmp), &hp); - tcp_sigpool_end(&hp); - - return err; + } __packed input =3D { + .counter =3D 1, + .label =3D "TCP-AO", + .ctx =3D { + .saddr =3D *saddr, + .daddr =3D *daddr, + .sport =3D sport, + .dport =3D dport, + .sisn =3D sisn, + .disn =3D disn, + }, + .outlen =3D htons(tcp_ao_digest_size(mkt) * 8), /* in bits */ + }; + + tcp_ao_calc_traffic_key(mkt, key, &input, sizeof(input)); + return 0; } =20 int tcp_v6_ao_calc_key_skb(struct tcp_ao_key *mkt, u8 *key, const struct sk_buff *skb, __be32 sisn, __be32 disn) @@ -110,27 +102,24 @@ struct tcp_ao_key *tcp_v6_ao_lookup_rsk(const struct = sock *sk, l3index =3D l3mdev_master_ifindex_by_index(sock_net(sk), ireq->ir_iif); return tcp_ao_do_lookup(sk, l3index, (union tcp_ao_addr *)addr, AF_INET6, sndid, rcvid); } =20 -int tcp_v6_ao_hash_pseudoheader(struct tcp_sigpool *hp, +int tcp_v6_ao_hash_pseudoheader(struct tcp_ao_mac_ctx *mac_ctx, const struct in6_addr *daddr, const struct in6_addr *saddr, int nbytes) { - struct tcp6_pseudohdr *bp; - struct scatterlist sg; - - bp =3D hp->scratch; /* 1. TCP pseudo-header (RFC2460) */ - bp->saddr =3D *saddr; - bp->daddr =3D *daddr; - bp->len =3D cpu_to_be32(nbytes); - bp->protocol =3D cpu_to_be32(IPPROTO_TCP); - - sg_init_one(&sg, bp, sizeof(*bp)); - ahash_request_set_crypt(hp->req, &sg, NULL, sizeof(*bp)); - return crypto_ahash_update(hp->req); + struct tcp6_pseudohdr phdr =3D { + .saddr =3D *saddr, + .daddr =3D *daddr, + .len =3D cpu_to_be32(nbytes), + .protocol =3D cpu_to_be32(IPPROTO_TCP), + }; + + tcp_ao_mac_update(mac_ctx, &phdr, sizeof(phdr)); + return 0; } =20 int tcp_v6_ao_hash_skb(char *ao_hash, struct tcp_ao_key *key, const struct sock *sk, const struct sk_buff *skb, const u8 *tkey, int hash_offset, u32 sne) diff --git a/tools/testing/selftests/net/tcp_ao/config b/tools/testing/self= tests/net/tcp_ao/config index 0ec38c167e6df..1b120bfd89c40 100644 --- a/tools/testing/selftests/net/tcp_ao/config +++ b/tools/testing/selftests/net/tcp_ao/config @@ -1,7 +1,5 @@ -CONFIG_CRYPTO_HMAC=3Dy -CONFIG_CRYPTO_SHA1=3Dy CONFIG_IPV6=3Dy CONFIG_IPV6_MULTIPLE_TABLES=3Dy CONFIG_NET_L3_MASTER_DEV=3Dy CONFIG_NET_VRF=3Dy CONFIG_TCP_AO=3Dy --=20 2.53.0 From nobody Thu Apr 9 14:08:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3959B3290DF; Sat, 7 Mar 2026 22:46:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772923576; cv=none; b=YsInF+SUKPNdnFqPHOxcq4cWEqnVHz1gyRmqWeMI+pjcbcNALgjtjsohe2Hl8Gqz/csrVk025BG1C0gjFlp1EtNwbXEB+Wa4tdIvgBGoSfMEYnniC7qQrJAayCxjL8/Yz6t4YxHcCcCqVR3LYLr3ZmfWxOCuZTmUg0jFr1ibC2w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772923576; c=relaxed/simple; bh=eK+nF1llosEuHJOw579w9iMuF/N+H6mhCQHWy1C6Dw8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=CCXkPdF4/iTMUIgPGFVD7XSQLoB6TT/qbWql0AKMfZ44VrqqNh7RWkydNQiaDERaSUFvYJGtHBJ4Akp/Tes63bDKABj6/3Iq351vdydsOBf3qPsiaI6/fyk0ErRXHq9XDbYuh5+jSnRCPVDJzzlkZQmGB6jUV4x4gg8FM9ZAGNo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=YKEXN6G/; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="YKEXN6G/" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7DDA7C2BC9E; Sat, 7 Mar 2026 22:46:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1772923576; bh=eK+nF1llosEuHJOw579w9iMuF/N+H6mhCQHWy1C6Dw8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=YKEXN6G/P3jQVQ0dAV0fxtqzirn2BVk9O8E/CNHDNVbW5o77qdm8A5JDXd/5rUpRs GeqNTSMGQm3W794X1fMKkT7n9Vtaw14YLyEEmHhX4r3nAXis6XdmBaY3rncH7RkX5t f0kCQhzsS8Ve29qYdcXP2RqC7aL7+r6Kgpb5Fo98BMotiaI91cdRhnGSHChJEJTpTr RBzCRUsAoArFjiPTy91xvqMNVUWZHk5It+3Vbw/H0PIYgnaZona20FhPNsAZjOGyKH 6Nr6mIIaF5FAXhse9Loyf2H+Q/ZtgDl3tK83CULIptyqMV0DToIwdF0ig0gzU9oGZa Oaq6BLEa1PeNg== From: Eric Biggers To: netdev@vger.kernel.org Cc: linux-crypto@vger.kernel.org, linux-kernel@vger.kernel.org, Eric Dumazet , Neal Cardwell , Kuniyuki Iwashima , "David S . Miller" , David Ahern , Jakub Kicinski , Paolo Abeni , Simon Horman , Ard Biesheuvel , "Jason A . Donenfeld" , Herbert Xu , Dmitry Safonov <0x7f454c46@gmail.com>, Eric Biggers Subject: [RFC PATCH 3/8] net/tcp-ao: Use stack-allocated MAC and traffic_key buffers Date: Sat, 7 Mar 2026 14:43:36 -0800 Message-ID: <20260307224341.5644-4-ebiggers@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260307224341.5644-1-ebiggers@kernel.org> References: <20260307224341.5644-1-ebiggers@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Now that the maximum MAC and traffic key lengths are statically-known small values, allocate MACs and traffic keys on the stack instead of with kmalloc. This eliminates multiple failure-prone GFP_ATOMIC allocations. Note that some cases such as tcp_ao_prepare_reset() are left unchanged for now since they would require slightly wider changes. Signed-off-by: Eric Biggers Reviewed-by: Ard Biesheuvel --- net/ipv4/tcp_ao.c | 44 +++++++++++--------------------------------- net/ipv6/tcp_ao.c | 17 +++++------------ 2 files changed, 16 insertions(+), 45 deletions(-) diff --git a/net/ipv4/tcp_ao.c b/net/ipv4/tcp_ao.c index 0d24cbd66c9a1..69f1d6d26562e 100644 --- a/net/ipv4/tcp_ao.c +++ b/net/ipv4/tcp_ao.c @@ -737,26 +737,19 @@ int tcp_v4_ao_hash_skb(char *ao_hash, struct tcp_ao_k= ey *key, =20 int tcp_v4_ao_synack_hash(char *ao_hash, struct tcp_ao_key *ao_key, struct request_sock *req, const struct sk_buff *skb, int hash_offset, u32 sne) { - void *hash_buf =3D NULL; + u8 tkey_buf[TCP_AO_MAX_TRAFFIC_KEY_LEN]; int err; =20 - hash_buf =3D kmalloc(tcp_ao_digest_size(ao_key), GFP_ATOMIC); - if (!hash_buf) - return -ENOMEM; - - err =3D tcp_v4_ao_calc_key_rsk(ao_key, hash_buf, req); + err =3D tcp_v4_ao_calc_key_rsk(ao_key, tkey_buf, req); if (err) - goto out; + return err; =20 - err =3D tcp_ao_hash_skb(AF_INET, ao_hash, ao_key, req_to_sk(req), skb, - hash_buf, hash_offset, sne); -out: - kfree(hash_buf); - return err; + return tcp_ao_hash_skb(AF_INET, ao_hash, ao_key, req_to_sk(req), skb, + tkey_buf, hash_offset, sne); } =20 struct tcp_ao_key *tcp_v4_ao_lookup_rsk(const struct sock *sk, struct request_sock *req, int sndid, int rcvid) @@ -867,13 +860,13 @@ int tcp_ao_prepare_reset(const struct sock *sk, struc= t sk_buff *skb, int tcp_ao_transmit_skb(struct sock *sk, struct sk_buff *skb, struct tcp_ao_key *key, struct tcphdr *th, __u8 *hash_location) { struct tcp_skb_cb *tcb =3D TCP_SKB_CB(skb); + u8 tkey_buf[TCP_AO_MAX_TRAFFIC_KEY_LEN]; struct tcp_sock *tp =3D tcp_sk(sk); struct tcp_ao_info *ao; - void *tkey_buf =3D NULL; u8 *traffic_key; u32 sne; =20 ao =3D rcu_dereference_protected(tcp_sk(sk)->ao_info, lockdep_sock_is_held(sk)); @@ -881,13 +874,10 @@ int tcp_ao_transmit_skb(struct sock *sk, struct sk_bu= ff *skb, if (unlikely(tcb->tcp_flags & TCPHDR_SYN)) { __be32 disn; =20 if (!(tcb->tcp_flags & TCPHDR_ACK)) { disn =3D 0; - tkey_buf =3D kmalloc(tcp_ao_digest_size(key), GFP_ATOMIC); - if (!tkey_buf) - return -ENOMEM; traffic_key =3D tkey_buf; } else { disn =3D ao->risn; } tp->af_specific->ao_calc_key_sk(key, traffic_key, @@ -895,11 +885,10 @@ int tcp_ao_transmit_skb(struct sock *sk, struct sk_bu= ff *skb, } sne =3D tcp_ao_compute_sne(READ_ONCE(ao->snd_sne), READ_ONCE(tp->snd_una), ntohl(th->seq)); tp->af_specific->calc_ao_hash(hash_location, key, sk, skb, traffic_key, hash_location - (u8 *)th, sne); - kfree(tkey_buf); return 0; } =20 static struct tcp_ao_key *tcp_ao_inbound_lookup(unsigned short int family, const struct sock *sk, const struct sk_buff *skb, @@ -961,54 +950,48 @@ tcp_ao_verify_hash(const struct sock *sk, const struc= t sk_buff *skb, const struct tcp_ao_hdr *aoh, struct tcp_ao_key *key, u8 *traffic_key, u8 *phash, u32 sne, int l3index) { const struct tcphdr *th =3D tcp_hdr(skb); u8 maclen =3D tcp_ao_hdr_maclen(aoh); - void *hash_buf =3D NULL; + u8 hash_buf[TCP_AO_MAX_MAC_LEN]; =20 if (maclen !=3D tcp_ao_maclen(key)) { NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPAOBAD); atomic64_inc(&info->counters.pkt_bad); atomic64_inc(&key->pkt_bad); trace_tcp_ao_wrong_maclen(sk, skb, aoh->keyid, aoh->rnext_keyid, maclen); return SKB_DROP_REASON_TCP_AOFAILURE; } =20 - 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 (crypto_memneq(phash, hash_buf, maclen)) { NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPAOBAD); atomic64_inc(&info->counters.pkt_bad); atomic64_inc(&key->pkt_bad); trace_tcp_ao_mismatch(sk, skb, aoh->keyid, aoh->rnext_keyid, maclen); - kfree(hash_buf); return SKB_DROP_REASON_TCP_AOFAILURE; } NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPAOGOOD); atomic64_inc(&info->counters.pkt_good); atomic64_inc(&key->pkt_good); - kfree(hash_buf); return SKB_NOT_DROPPED_YET; } =20 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, int l3index, const struct tcp_ao_hdr *aoh) { + u8 tkey_buf[TCP_AO_MAX_TRAFFIC_KEY_LEN]; const struct tcphdr *th =3D tcp_hdr(skb); u8 maclen =3D tcp_ao_hdr_maclen(aoh); 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; int state; u32 sne =3D 0; @@ -1112,18 +1095,13 @@ tcp_inbound_ao_hash(struct sock *sk, const struct s= k_buff *skb, } else { WARN_ONCE(1, "TCP-AO: Unexpected sk_state %d", 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, l3index); - kfree(traffic_key); - return ret; + tcp_ao_calc_key_skb(key, tkey_buf, skb, sisn, disn, family); + return tcp_ao_verify_hash(sk, skb, family, info, aoh, key, + tkey_buf, phash, sne, l3index); =20 key_not_found: NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPAOKEYNOTFOUND); atomic64_inc(&info->counters.key_not_found); trace_tcp_ao_key_not_found(sk, skb, aoh->keyid, diff --git a/net/ipv6/tcp_ao.c b/net/ipv6/tcp_ao.c index 2dcfe9dda7f4a..bf30b970181d7 100644 --- a/net/ipv6/tcp_ao.c +++ b/net/ipv6/tcp_ao.c @@ -136,22 +136,15 @@ int tcp_v6_parse_ao(struct sock *sk, int cmd, =20 int tcp_v6_ao_synack_hash(char *ao_hash, struct tcp_ao_key *ao_key, struct request_sock *req, const struct sk_buff *skb, int hash_offset, u32 sne) { - void *hash_buf =3D NULL; + u8 tkey_buf[TCP_AO_MAX_TRAFFIC_KEY_LEN]; int err; =20 - hash_buf =3D kmalloc(tcp_ao_digest_size(ao_key), GFP_ATOMIC); - if (!hash_buf) - return -ENOMEM; - - err =3D tcp_v6_ao_calc_key_rsk(ao_key, hash_buf, req); + err =3D tcp_v6_ao_calc_key_rsk(ao_key, tkey_buf, req); if (err) - goto out; + return err; =20 - err =3D tcp_ao_hash_skb(AF_INET6, ao_hash, ao_key, req_to_sk(req), skb, - hash_buf, hash_offset, sne); -out: - kfree(hash_buf); - return err; + return tcp_ao_hash_skb(AF_INET6, ao_hash, ao_key, req_to_sk(req), skb, + tkey_buf, hash_offset, sne); } --=20 2.53.0 From nobody Thu Apr 9 14:08:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A2CBE3385AC; Sat, 7 Mar 2026 22:46:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772923576; cv=none; b=hSnXkkCSJuqzMWLKrkwy3lP0ax7xOcmNPJIM8uwCJnVZpMX6RhPU6ojcq+luCbN4W+fWpRsFYXL6febh4w39T+d+1l9YORIZxcNCM/kRgCf7I+PV2loExItgvYYXkyBdEBCssWk0PZkh2FWNPqWDTMPrQ4fonvETEnEaP7TsvJQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772923576; c=relaxed/simple; bh=t0xxkmc+LBcvhVMdCIXmj9CBTstJxk/Y/EgILiuujh0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=E9uX93gqbPdoLYhJAhUsniUd9sN65qCrB4XlSJC5XC5Dk+YRO5thdCnBIqkf4SYxLq5h+/sxfxEWIPG+wfV95VElb4VaC80s4qd6D57mB5UCjYsoVtO8vzm3/uUZGpHYYBa3ZLHsxpSmBk7m1DRw3pcVVQK3was+GP+2NEDlr1U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Wwd3asBC; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Wwd3asBC" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1AE8CC19422; Sat, 7 Mar 2026 22:46:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1772923576; bh=t0xxkmc+LBcvhVMdCIXmj9CBTstJxk/Y/EgILiuujh0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Wwd3asBCuCi8ove4fLbCCyXK2DSwEZ5Uuvi4QJ1fiet4GOnVPrrqt8ZuDce3W4+C8 ync+RPBVvIF1sJUnwCzlr+2Q4fNBFzkz6M4A7ioJFa78wFgaroD4SCxDhi/jkSr1Et Ke7S5EMGu6rueB91RYtsY1eHTgDAzFLl12sBg2d7mVwSTR/nSYe956GWlOrH9VpTDS nBMpG0WkhGxPKKl+laA0HBZ10wQryx2lUVAiSdFPASPSiBPTewN8q3lUZ8l0yDuxGL p7HhaXkakhn3FhcfFAJ/jkMt6VFY9NFzuBqJGX3LX7FZNzgc0lgf8tVKqCoq+QZES1 pELer0uPAFGJQ== From: Eric Biggers To: netdev@vger.kernel.org Cc: linux-crypto@vger.kernel.org, linux-kernel@vger.kernel.org, Eric Dumazet , Neal Cardwell , Kuniyuki Iwashima , "David S . Miller" , David Ahern , Jakub Kicinski , Paolo Abeni , Simon Horman , Ard Biesheuvel , "Jason A . Donenfeld" , Herbert Xu , Dmitry Safonov <0x7f454c46@gmail.com>, Eric Biggers Subject: [RFC PATCH 4/8] net/tcp-ao: Return void from functions that can no longer fail Date: Sat, 7 Mar 2026 14:43:37 -0800 Message-ID: <20260307224341.5644-5-ebiggers@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260307224341.5644-1-ebiggers@kernel.org> References: <20260307224341.5644-1-ebiggers@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Since tcp-ao now uses the crypto library API instead of crypto_ahash, and MACs and keys now have a statically-known maximum size, many tcp-ao functions can no longer fail. Propagate this change up into the return types of various functions. Signed-off-by: Eric Biggers Reviewed-by: Ard Biesheuvel --- include/net/tcp.h | 8 +-- include/net/tcp_ao.h | 44 +++++++-------- net/ipv4/tcp_ao.c | 128 ++++++++++++++++++++++-------------------- net/ipv4/tcp_output.c | 10 +--- net/ipv6/tcp_ao.c | 65 ++++++++++----------- 5 files changed, 123 insertions(+), 132 deletions(-) diff --git a/include/net/tcp.h b/include/net/tcp.h index 978eea2d5df04..18fb675d05bc4 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -2426,13 +2426,13 @@ struct tcp_sock_af_ops { #ifdef CONFIG_TCP_AO int (*ao_parse)(struct sock *sk, int optname, sockptr_t optval, int optle= n); struct tcp_ao_key *(*ao_lookup)(const struct sock *sk, struct sock *addr_sk, int sndid, int rcvid); - int (*ao_calc_key_sk)(struct tcp_ao_key *mkt, u8 *key, - const struct sock *sk, - __be32 sisn, __be32 disn, bool send); + void (*ao_calc_key_sk)(struct tcp_ao_key *mkt, u8 *key, + const struct sock *sk, + __be32 sisn, __be32 disn, bool send); int (*calc_ao_hash)(char *location, struct tcp_ao_key *ao, const struct sock *sk, const struct sk_buff *skb, const u8 *tkey, int hash_offset, u32 sne); #endif }; @@ -2449,11 +2449,11 @@ struct tcp_request_sock_ops { #endif #ifdef CONFIG_TCP_AO struct tcp_ao_key *(*ao_lookup)(const struct sock *sk, struct request_sock *req, int sndid, int rcvid); - int (*ao_calc_key)(struct tcp_ao_key *mkt, u8 *key, struct request_sock *= sk); + void (*ao_calc_key)(struct tcp_ao_key *mkt, u8 *key, struct request_sock = *sk); int (*ao_synack_hash)(char *ao_hash, struct tcp_ao_key *mkt, struct request_sock *req, const struct sk_buff *skb, int hash_offset, u32 sne); #endif #ifdef CONFIG_SYN_COOKIES diff --git a/include/net/tcp_ao.h b/include/net/tcp_ao.h index f845bc631bc1e..2f20c57ea46b2 100644 --- a/include/net/tcp_ao.h +++ b/include/net/tcp_ao.h @@ -180,13 +180,13 @@ struct tcp6_ao_context { =20 /* Established states are fast-path and there always is current_key/rnext_= key */ #define TCP_AO_ESTABLISHED (TCPF_ESTABLISHED | TCPF_FIN_WAIT1 | TCPF_FIN_W= AIT2 | \ TCPF_CLOSE_WAIT | TCPF_LAST_ACK | TCPF_CLOSING) =20 -int tcp_ao_transmit_skb(struct sock *sk, struct sk_buff *skb, - struct tcp_ao_key *key, struct tcphdr *th, - __u8 *hash_location); +void tcp_ao_transmit_skb(struct sock *sk, struct sk_buff *skb, + struct tcp_ao_key *key, struct tcphdr *th, + __u8 *hash_location); void tcp_ao_mac_update(struct tcp_ao_mac_ctx *mac_ctx, const void *data, size_t data_len); 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, @@ -231,32 +231,33 @@ int tcp_v4_parse_ao(struct sock *sk, int cmd, sockptr= _t optval, int optlen); struct tcp_ao_key *tcp_v4_ao_lookup(const struct sock *sk, struct sock *ad= dr_sk, int sndid, int rcvid); int tcp_v4_ao_synack_hash(char *ao_hash, struct tcp_ao_key *mkt, struct request_sock *req, const struct sk_buff *skb, int hash_offset, u32 sne); -int tcp_v4_ao_calc_key_sk(struct tcp_ao_key *mkt, u8 *key, - const struct sock *sk, - __be32 sisn, __be32 disn, bool send); -int tcp_v4_ao_calc_key_rsk(struct tcp_ao_key *mkt, u8 *key, - struct request_sock *req); +void tcp_v4_ao_calc_key_sk(struct tcp_ao_key *mkt, u8 *key, + const struct sock *sk, + __be32 sisn, __be32 disn, bool send); +void tcp_v4_ao_calc_key_rsk(struct tcp_ao_key *mkt, u8 *key, + struct request_sock *req); struct tcp_ao_key *tcp_v4_ao_lookup_rsk(const struct sock *sk, struct request_sock *req, int sndid, int rcvid); int tcp_v4_ao_hash_skb(char *ao_hash, struct tcp_ao_key *key, const struct sock *sk, const struct sk_buff *skb, const u8 *tkey, int hash_offset, u32 sne); /* ipv6 specific functions */ -int tcp_v6_ao_hash_pseudoheader(struct tcp_ao_mac_ctx *mac_ctx, - 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); -int tcp_v6_ao_calc_key_rsk(struct tcp_ao_key *mkt, u8 *key, - struct request_sock *req); +void tcp_v6_ao_hash_pseudoheader(struct tcp_ao_mac_ctx *mac_ctx, + const struct in6_addr *daddr, + const struct in6_addr *saddr, int nbytes); +void tcp_v6_ao_calc_key_skb(struct tcp_ao_key *mkt, u8 *key, + const struct sk_buff *skb, __be32 sisn, + __be32 disn); +void tcp_v6_ao_calc_key_sk(struct tcp_ao_key *mkt, u8 *key, + const struct sock *sk, __be32 sisn, + __be32 disn, bool send); +void tcp_v6_ao_calc_key_rsk(struct tcp_ao_key *mkt, u8 *key, + struct request_sock *req); struct tcp_ao_key *tcp_v6_ao_lookup(const struct sock *sk, struct sock *addr_sk, int sndid, int rcvid); struct tcp_ao_key *tcp_v6_ao_lookup_rsk(const struct sock *sk, struct request_sock *req, int sndid, int rcvid); @@ -272,15 +273,14 @@ void tcp_ao_finish_connect(struct sock *sk, struct sk= _buff *skb); void tcp_ao_connect_init(struct sock *sk); void tcp_ao_syncookie(struct sock *sk, const struct sk_buff *skb, struct request_sock *req, unsigned short int family); #else /* CONFIG_TCP_AO */ =20 -static inline int tcp_ao_transmit_skb(struct sock *sk, struct sk_buff *skb, - struct tcp_ao_key *key, struct tcphdr *th, - __u8 *hash_location) +static inline void tcp_ao_transmit_skb(struct sock *sk, struct sk_buff *sk= b, + struct tcp_ao_key *key, + struct tcphdr *th, __u8 *hash_location) { - return 0; } =20 static inline void tcp_ao_syncookie(struct sock *sk, const struct sk_buff = *skb, struct request_sock *req, unsigned short int family) { diff --git a/net/ipv4/tcp_ao.c b/net/ipv4/tcp_ao.c index 69f1d6d26562e..36a64c1cd8c99 100644 --- a/net/ipv4/tcp_ao.c +++ b/net/ipv4/tcp_ao.c @@ -433,14 +433,14 @@ void tcp_ao_time_wait(struct tcp_timewait_sock *tcptw= , struct tcp_sock *tp) tcptw->ao_info =3D NULL; } } =20 /* 4 tuple and ISNs are expected in NBO */ -static int tcp_v4_ao_calc_key(struct tcp_ao_key *mkt, u8 *key, - __be32 saddr, __be32 daddr, - __be16 sport, __be16 dport, - __be32 sisn, __be32 disn) +static void tcp_v4_ao_calc_key(struct tcp_ao_key *mkt, u8 *key, + __be32 saddr, __be32 daddr, + __be16 sport, __be16 dport, + __be32 sisn, __be32 disn) { /* See RFC5926 3.1.1 */ struct kdf_input_block { u8 counter; u8 label[6]; @@ -459,91 +459,92 @@ static int tcp_v4_ao_calc_key(struct tcp_ao_key *mkt,= u8 *key, }, .outlen =3D htons(tcp_ao_digest_size(mkt) * 8), /* in bits */ }; =20 tcp_ao_calc_traffic_key(mkt, key, &input, sizeof(input)); - return 0; } =20 -int tcp_v4_ao_calc_key_sk(struct tcp_ao_key *mkt, u8 *key, - const struct sock *sk, - __be32 sisn, __be32 disn, bool send) +void tcp_v4_ao_calc_key_sk(struct tcp_ao_key *mkt, u8 *key, + const struct sock *sk, + __be32 sisn, __be32 disn, bool send) { if (send) - return tcp_v4_ao_calc_key(mkt, key, sk->sk_rcv_saddr, - sk->sk_daddr, htons(sk->sk_num), - sk->sk_dport, sisn, disn); + tcp_v4_ao_calc_key(mkt, key, sk->sk_rcv_saddr, sk->sk_daddr, + htons(sk->sk_num), sk->sk_dport, sisn, disn); else - return tcp_v4_ao_calc_key(mkt, key, sk->sk_daddr, - sk->sk_rcv_saddr, sk->sk_dport, - htons(sk->sk_num), disn, sisn); + tcp_v4_ao_calc_key(mkt, key, sk->sk_daddr, sk->sk_rcv_saddr, + sk->sk_dport, htons(sk->sk_num), disn, sisn); } =20 static int tcp_ao_calc_key_sk(struct tcp_ao_key *mkt, u8 *key, const struct sock *sk, __be32 sisn, __be32 disn, bool send) { - if (mkt->family =3D=3D AF_INET) - return tcp_v4_ao_calc_key_sk(mkt, key, sk, sisn, disn, send); + if (mkt->family =3D=3D AF_INET) { + tcp_v4_ao_calc_key_sk(mkt, key, sk, sisn, disn, send); + return 0; + } #if IS_ENABLED(CONFIG_IPV6) - else if (mkt->family =3D=3D AF_INET6) - return tcp_v6_ao_calc_key_sk(mkt, key, sk, sisn, disn, send); + if (mkt->family =3D=3D AF_INET6) { + tcp_v6_ao_calc_key_sk(mkt, key, sk, sisn, disn, send); + return 0; + } #endif - else - return -EOPNOTSUPP; + return -EOPNOTSUPP; } =20 -int tcp_v4_ao_calc_key_rsk(struct tcp_ao_key *mkt, u8 *key, - struct request_sock *req) +void tcp_v4_ao_calc_key_rsk(struct tcp_ao_key *mkt, u8 *key, + struct request_sock *req) { struct inet_request_sock *ireq =3D inet_rsk(req); =20 - return tcp_v4_ao_calc_key(mkt, key, - ireq->ir_loc_addr, ireq->ir_rmt_addr, - htons(ireq->ir_num), ireq->ir_rmt_port, - htonl(tcp_rsk(req)->snt_isn), - htonl(tcp_rsk(req)->rcv_isn)); + tcp_v4_ao_calc_key(mkt, key, ireq->ir_loc_addr, ireq->ir_rmt_addr, + htons(ireq->ir_num), ireq->ir_rmt_port, + htonl(tcp_rsk(req)->snt_isn), + 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) +static void 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); =20 - return tcp_v4_ao_calc_key(mkt, key, iph->saddr, iph->daddr, - th->source, th->dest, sisn, disn); + tcp_v4_ao_calc_key(mkt, key, iph->saddr, iph->daddr, th->source, + th->dest, sisn, disn); } =20 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 (family =3D=3D AF_INET) { + tcp_v4_ao_calc_key_skb(mkt, key, skb, sisn, disn); + return 0; + } #if IS_ENABLED(CONFIG_IPV6) - else if (family =3D=3D AF_INET6) - return tcp_v6_ao_calc_key_skb(mkt, key, skb, sisn, disn); + if (family =3D=3D AF_INET6) { + tcp_v6_ao_calc_key_skb(mkt, key, skb, sisn, disn); + return 0; + } #endif return -EAFNOSUPPORT; } =20 -static int tcp_v4_ao_hash_pseudoheader(struct tcp_ao_mac_ctx *mac_ctx, - __be32 daddr, __be32 saddr, - int nbytes) +static void tcp_v4_ao_hash_pseudoheader(struct tcp_ao_mac_ctx *mac_ctx, + __be32 daddr, __be32 saddr, int nbytes) { struct tcp4_pseudohdr phdr =3D { .saddr =3D saddr, .daddr =3D daddr, .pad =3D 0, .protocol =3D IPPROTO_TCP, .len =3D cpu_to_be16(nbytes), }; =20 tcp_ao_mac_update(mac_ctx, &phdr, sizeof(phdr)); - return 0; } =20 static int tcp_ao_hash_pseudoheader(unsigned short int family, const struct sock *sk, const struct sk_buff *skb, @@ -551,35 +552,42 @@ static int tcp_ao_hash_pseudoheader(unsigned short in= t family, { const struct tcphdr *th =3D tcp_hdr(skb); =20 /* TODO: Can we rely on checksum being zero to mean outbound pkt? */ if (!th->check) { - if (family =3D=3D AF_INET) - return tcp_v4_ao_hash_pseudoheader(mac_ctx, sk->sk_daddr, - sk->sk_rcv_saddr, skb->len); + if (family =3D=3D AF_INET) { + tcp_v4_ao_hash_pseudoheader(mac_ctx, sk->sk_daddr, + sk->sk_rcv_saddr, skb->len); + return 0; + } #if IS_ENABLED(CONFIG_IPV6) - else if (family =3D=3D AF_INET6) - return tcp_v6_ao_hash_pseudoheader(mac_ctx, &sk->sk_v6_daddr, - &sk->sk_v6_rcv_saddr, skb->len); + if (family =3D=3D AF_INET6) { + tcp_v6_ao_hash_pseudoheader(mac_ctx, &sk->sk_v6_daddr, + &sk->sk_v6_rcv_saddr, + skb->len); + return 0; + } #endif - else - return -EAFNOSUPPORT; + return -EAFNOSUPPORT; } =20 if (family =3D=3D AF_INET) { const struct iphdr *iph =3D ip_hdr(skb); =20 - return tcp_v4_ao_hash_pseudoheader(mac_ctx, iph->daddr, - iph->saddr, skb->len); + tcp_v4_ao_hash_pseudoheader(mac_ctx, iph->daddr, iph->saddr, + skb->len); + return 0; + } #if IS_ENABLED(CONFIG_IPV6) - } else if (family =3D=3D AF_INET6) { + if (family =3D=3D AF_INET6) { const struct ipv6hdr *iph =3D ipv6_hdr(skb); =20 - return tcp_v6_ao_hash_pseudoheader(mac_ctx, &iph->daddr, - &iph->saddr, skb->len); -#endif + tcp_v6_ao_hash_pseudoheader(mac_ctx, &iph->daddr, &iph->saddr, + skb->len); + return 0; } +#endif return -EAFNOSUPPORT; } =20 u32 tcp_ao_compute_sne(u32 next_sne, u32 next_seq, u32 seq) { @@ -738,15 +746,12 @@ int tcp_v4_ao_hash_skb(char *ao_hash, struct tcp_ao_k= ey *key, int tcp_v4_ao_synack_hash(char *ao_hash, struct tcp_ao_key *ao_key, struct request_sock *req, const struct sk_buff *skb, int hash_offset, u32 sne) { u8 tkey_buf[TCP_AO_MAX_TRAFFIC_KEY_LEN]; - int err; =20 - err =3D tcp_v4_ao_calc_key_rsk(ao_key, tkey_buf, req); - if (err) - return err; + tcp_v4_ao_calc_key_rsk(ao_key, tkey_buf, req); =20 return tcp_ao_hash_skb(AF_INET, ao_hash, ao_key, req_to_sk(req), skb, tkey_buf, hash_offset, sne); } =20 @@ -855,13 +860,13 @@ int tcp_ao_prepare_reset(const struct sock *sk, struc= t sk_buff *skb, snd_basis, seq); } return 0; } =20 -int tcp_ao_transmit_skb(struct sock *sk, struct sk_buff *skb, - struct tcp_ao_key *key, struct tcphdr *th, - __u8 *hash_location) +void tcp_ao_transmit_skb(struct sock *sk, struct sk_buff *skb, + struct tcp_ao_key *key, struct tcphdr *th, + __u8 *hash_location) { struct tcp_skb_cb *tcb =3D TCP_SKB_CB(skb); u8 tkey_buf[TCP_AO_MAX_TRAFFIC_KEY_LEN]; struct tcp_sock *tp =3D tcp_sk(sk); struct tcp_ao_info *ao; @@ -885,11 +890,10 @@ int tcp_ao_transmit_skb(struct sock *sk, struct sk_bu= ff *skb, } sne =3D tcp_ao_compute_sne(READ_ONCE(ao->snd_sne), READ_ONCE(tp->snd_una), ntohl(th->seq)); tp->af_specific->calc_ao_hash(hash_location, key, sk, skb, traffic_key, hash_location - (u8 *)th, sne); - return 0; } =20 static struct tcp_ao_key *tcp_ao_inbound_lookup(unsigned short int family, const struct sock *sk, const struct sk_buff *skb, int sndid, int rcvid, int l3index) diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 326b58ff1118d..8145f9aad77b3 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -1644,18 +1644,12 @@ static int __tcp_transmit_skb(struct sock *sk, stru= ct sk_buff *skb, sk_gso_disable(sk); tp->af_specific->calc_md5_hash(opts.hash_location, key.md5_key, sk, skb); #endif } else if (tcp_key_is_ao(&key)) { - int err; - - err =3D tcp_ao_transmit_skb(sk, skb, key.ao_key, th, - opts.hash_location); - if (err) { - sk_skb_reason_drop(sk, skb, SKB_DROP_REASON_NOT_SPECIFIED); - return -ENOMEM; - } + tcp_ao_transmit_skb(sk, skb, key.ao_key, th, + opts.hash_location); } =20 /* BPF prog is the last one writing header option */ bpf_skops_write_hdr_opt(sk, skb, NULL, NULL, 0, &opts); =20 diff --git a/net/ipv6/tcp_ao.c b/net/ipv6/tcp_ao.c index bf30b970181d7..01a8472805d1d 100644 --- a/net/ipv6/tcp_ao.c +++ b/net/ipv6/tcp_ao.c @@ -10,15 +10,15 @@ #include =20 #include #include =20 -static int tcp_v6_ao_calc_key(struct tcp_ao_key *mkt, u8 *key, - const struct in6_addr *saddr, - const struct in6_addr *daddr, - __be16 sport, __be16 dport, - __be32 sisn, __be32 disn) +static void tcp_v6_ao_calc_key(struct tcp_ao_key *mkt, u8 *key, + const struct in6_addr *saddr, + const struct in6_addr *daddr, + __be16 sport, __be16 dport, + __be32 sisn, __be32 disn) { struct kdf_input_block { u8 counter; u8 label[6]; struct tcp6_ao_context ctx; @@ -36,49 +36,46 @@ static int tcp_v6_ao_calc_key(struct tcp_ao_key *mkt, u= 8 *key, }, .outlen =3D htons(tcp_ao_digest_size(mkt) * 8), /* in bits */ }; =20 tcp_ao_calc_traffic_key(mkt, key, &input, sizeof(input)); - return 0; } =20 -int tcp_v6_ao_calc_key_skb(struct tcp_ao_key *mkt, u8 *key, - const struct sk_buff *skb, - __be32 sisn, __be32 disn) +void 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); =20 - return tcp_v6_ao_calc_key(mkt, key, &iph->saddr, - &iph->daddr, th->source, - th->dest, sisn, disn); + tcp_v6_ao_calc_key(mkt, key, &iph->saddr, &iph->daddr, th->source, + th->dest, sisn, disn); } =20 -int tcp_v6_ao_calc_key_sk(struct tcp_ao_key *mkt, u8 *key, - const struct sock *sk, __be32 sisn, - __be32 disn, bool send) +void tcp_v6_ao_calc_key_sk(struct tcp_ao_key *mkt, u8 *key, + const struct sock *sk, __be32 sisn, + __be32 disn, bool send) { if (send) - return tcp_v6_ao_calc_key(mkt, key, &sk->sk_v6_rcv_saddr, - &sk->sk_v6_daddr, htons(sk->sk_num), - sk->sk_dport, sisn, disn); + tcp_v6_ao_calc_key(mkt, key, &sk->sk_v6_rcv_saddr, + &sk->sk_v6_daddr, htons(sk->sk_num), + sk->sk_dport, sisn, disn); else - return tcp_v6_ao_calc_key(mkt, key, &sk->sk_v6_daddr, - &sk->sk_v6_rcv_saddr, sk->sk_dport, - htons(sk->sk_num), disn, sisn); + tcp_v6_ao_calc_key(mkt, key, &sk->sk_v6_daddr, + &sk->sk_v6_rcv_saddr, sk->sk_dport, + htons(sk->sk_num), disn, sisn); } =20 -int tcp_v6_ao_calc_key_rsk(struct tcp_ao_key *mkt, u8 *key, - struct request_sock *req) +void tcp_v6_ao_calc_key_rsk(struct tcp_ao_key *mkt, u8 *key, + struct request_sock *req) { struct inet_request_sock *ireq =3D inet_rsk(req); =20 - return tcp_v6_ao_calc_key(mkt, key, - &ireq->ir_v6_loc_addr, &ireq->ir_v6_rmt_addr, - htons(ireq->ir_num), ireq->ir_rmt_port, - htonl(tcp_rsk(req)->snt_isn), - htonl(tcp_rsk(req)->rcv_isn)); + tcp_v6_ao_calc_key(mkt, key, + &ireq->ir_v6_loc_addr, &ireq->ir_v6_rmt_addr, + htons(ireq->ir_num), ireq->ir_rmt_port, + htonl(tcp_rsk(req)->snt_isn), + htonl(tcp_rsk(req)->rcv_isn)); } =20 struct tcp_ao_key *tcp_v6_ao_lookup(const struct sock *sk, struct sock *addr_sk, int sndid, int rcvid) @@ -102,24 +99,23 @@ struct tcp_ao_key *tcp_v6_ao_lookup_rsk(const struct s= ock *sk, l3index =3D l3mdev_master_ifindex_by_index(sock_net(sk), ireq->ir_iif); return tcp_ao_do_lookup(sk, l3index, (union tcp_ao_addr *)addr, AF_INET6, sndid, rcvid); } =20 -int tcp_v6_ao_hash_pseudoheader(struct tcp_ao_mac_ctx *mac_ctx, - const struct in6_addr *daddr, - const struct in6_addr *saddr, int nbytes) +void tcp_v6_ao_hash_pseudoheader(struct tcp_ao_mac_ctx *mac_ctx, + const struct in6_addr *daddr, + const struct in6_addr *saddr, int nbytes) { /* 1. TCP pseudo-header (RFC2460) */ struct tcp6_pseudohdr phdr =3D { .saddr =3D *saddr, .daddr =3D *daddr, .len =3D cpu_to_be32(nbytes), .protocol =3D cpu_to_be32(IPPROTO_TCP), }; =20 tcp_ao_mac_update(mac_ctx, &phdr, sizeof(phdr)); - return 0; } =20 int tcp_v6_ao_hash_skb(char *ao_hash, struct tcp_ao_key *key, const struct sock *sk, const struct sk_buff *skb, const u8 *tkey, int hash_offset, u32 sne) @@ -137,14 +133,11 @@ int tcp_v6_parse_ao(struct sock *sk, int cmd, int tcp_v6_ao_synack_hash(char *ao_hash, struct tcp_ao_key *ao_key, struct request_sock *req, const struct sk_buff *skb, int hash_offset, u32 sne) { u8 tkey_buf[TCP_AO_MAX_TRAFFIC_KEY_LEN]; - int err; =20 - err =3D tcp_v6_ao_calc_key_rsk(ao_key, tkey_buf, req); - if (err) - return err; + tcp_v6_ao_calc_key_rsk(ao_key, tkey_buf, req); =20 return tcp_ao_hash_skb(AF_INET6, ao_hash, ao_key, req_to_sk(req), skb, tkey_buf, hash_offset, sne); } --=20 2.53.0 From nobody Thu Apr 9 14:08:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 67E113431E9; Sat, 7 Mar 2026 22:46:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772923577; cv=none; b=gkv2QZBexcdVWohCNQKyBOAeR0oXjGxsJgUeik70tuyAD1XivTimMUjIqPAW9Mwo0bL8XfP5woDKaC8spEEfqlXDI8pFDBqyGyqtBkklOsMzThqZojRkWVLdmaYTuAzW8PQOsHG50jE9nfY1bhz5EJjYE61gdIxHQFmbfKtK1is= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772923577; c=relaxed/simple; bh=ETOBZymeHG+RfWz4RBdVFEwQAwJS577BxMSzcKm1fqs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=M8TOshxVmjQcBRbudZEZhpg6boyAaorm0VIkckMeeftn1DQCbSuRDmjPYtCHp8qoSbB6rmqa2tfXJRu9FQo1rBzJR4zvZ6NHwndTEZGJ8F6izoVwE/IGe1jxVFQpZ0dogfzY3O7zRzF+qDtuDB5ssfjbViiLLTdtRjIOPAJizY0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=r2FcKZp5; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="r2FcKZp5" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A900EC2BCB1; Sat, 7 Mar 2026 22:46:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1772923577; bh=ETOBZymeHG+RfWz4RBdVFEwQAwJS577BxMSzcKm1fqs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=r2FcKZp5Gq5+gML2nV5uie7rnpHlrCdqYX2KdodAEdveX77T8nspebQ8IDxtVNM4l 2E5Y7LMGjvBLK4Mr8EvkvxdiXiEe4vUymx7Q0d/wqYG5CNWaHNOSQRmF22O17K5jl6 up197/NQWHVX7r8AeCGMrlAX34HiZ0v0NJa8WubN9M5uBDLr4XTB3gIBT6XACDtAj3 lsLfKUYFzGypqLKGITzPtmPS3yi9ezGpe9n7MTVoQgmllXfme+cOouQTvO36DYXKEk Vg3z2xwCNTl99C6xNvrHqpH0lFYUliEO674MpAx4AIbzVw3G6GllvF2oHbzVYAF+8/ Ft0M8zHDBq0lw== From: Eric Biggers To: netdev@vger.kernel.org Cc: linux-crypto@vger.kernel.org, linux-kernel@vger.kernel.org, Eric Dumazet , Neal Cardwell , Kuniyuki Iwashima , "David S . Miller" , David Ahern , Jakub Kicinski , Paolo Abeni , Simon Horman , Ard Biesheuvel , "Jason A . Donenfeld" , Herbert Xu , Dmitry Safonov <0x7f454c46@gmail.com>, Eric Biggers Subject: [RFC PATCH 5/8] net/tcp: Remove tcp_sigpool Date: Sat, 7 Mar 2026 14:43:38 -0800 Message-ID: <20260307224341.5644-6-ebiggers@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260307224341.5644-1-ebiggers@kernel.org> References: <20260307224341.5644-1-ebiggers@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" tcp_sigpool is no longer used. It existed only as a workaround for issues in the design of the crypto_ahash API, which have been avoided by switching to the much easier-to-use library APIs instead. Remove it. Signed-off-by: Eric Biggers Reviewed-by: Ard Biesheuvel --- include/net/tcp.h | 34 ---- net/ipv4/Kconfig | 3 - net/ipv4/Makefile | 1 - net/ipv4/tcp_sigpool.c | 366 ----------------------------------------- 4 files changed, 404 deletions(-) delete mode 100644 net/ipv4/tcp_sigpool.c diff --git a/include/net/tcp.h b/include/net/tcp.h index 18fb675d05bc4..73e7c1c1050b8 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -1968,44 +1968,10 @@ struct tcp6_pseudohdr { struct in6_addr daddr; __be32 len; __be32 protocol; /* including padding */ }; =20 -/* - * struct tcp_sigpool - per-CPU pool of ahash_requests - * @scratch: per-CPU temporary area, that can be used between - * tcp_sigpool_start() and tcp_sigpool_end() to perform - * crypto request - * @req: pre-allocated ahash request - */ -struct tcp_sigpool { - void *scratch; - struct ahash_request *req; -}; - -int tcp_sigpool_alloc_ahash(const char *alg, size_t scratch_size); -void tcp_sigpool_get(unsigned int id); -void tcp_sigpool_release(unsigned int id); -int tcp_sigpool_hash_skb_data(struct tcp_sigpool *hp, - const struct sk_buff *skb, - unsigned int header_len); - -/** - * tcp_sigpool_start - disable bh and start using tcp_sigpool_ahash - * @id: tcp_sigpool that was previously allocated by tcp_sigpool_alloc_aha= sh() - * @c: returned tcp_sigpool for usage (uninitialized on failure) - * - * Returns: 0 on success, error otherwise. - */ -int tcp_sigpool_start(unsigned int id, struct tcp_sigpool *c); -/** - * tcp_sigpool_end - enable bh and stop using tcp_sigpool - * @c: tcp_sigpool context that was returned by tcp_sigpool_start() - */ -void tcp_sigpool_end(struct tcp_sigpool *c); -size_t tcp_sigpool_algo(unsigned int id, char *buf, size_t buf_len); -/* - functions */ void tcp_v4_md5_hash_skb(char *md5_hash, const struct tcp_md5sig_key *key, const struct sock *sk, const struct sk_buff *skb); int tcp_md5_do_add(struct sock *sk, const union tcp_md5_addr *addr, int family, u8 prefixlen, int l3index, u8 flags, const u8 *newkey, u8 newkeylen); diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig index 0fa293527cee9..7b945a5186c9b 100644 --- a/net/ipv4/Kconfig +++ b/net/ipv4/Kconfig @@ -740,13 +740,10 @@ config DEFAULT_TCP_CONG default "dctcp" if DEFAULT_DCTCP default "cdg" if DEFAULT_CDG default "bbr" if DEFAULT_BBR default "cubic" =20 -config TCP_SIGPOOL - tristate - config TCP_AO bool "TCP: Authentication Option (RFC5925)" select CRYPTO_LIB_AES_CBC_MACS select CRYPTO_LIB_SHA1 select CRYPTO_LIB_SHA256 diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile index 18108a6f04999..f98d4734e4eeb 100644 --- a/net/ipv4/Makefile +++ b/net/ipv4/Makefile @@ -58,11 +58,10 @@ obj-$(CONFIG_TCP_CONG_NV) +=3D tcp_nv.o obj-$(CONFIG_TCP_CONG_VENO) +=3D tcp_veno.o obj-$(CONFIG_TCP_CONG_SCALABLE) +=3D tcp_scalable.o obj-$(CONFIG_TCP_CONG_LP) +=3D tcp_lp.o obj-$(CONFIG_TCP_CONG_YEAH) +=3D tcp_yeah.o obj-$(CONFIG_TCP_CONG_ILLINOIS) +=3D tcp_illinois.o -obj-$(CONFIG_TCP_SIGPOOL) +=3D tcp_sigpool.o obj-$(CONFIG_NET_SOCK_MSG) +=3D tcp_bpf.o obj-$(CONFIG_BPF_SYSCALL) +=3D udp_bpf.o obj-$(CONFIG_NETLABEL) +=3D cipso_ipv4.o =20 obj-$(CONFIG_XFRM) +=3D xfrm4_policy.o xfrm4_state.o xfrm4_input.o \ diff --git a/net/ipv4/tcp_sigpool.c b/net/ipv4/tcp_sigpool.c deleted file mode 100644 index 10b2e5970c402..0000000000000 --- a/net/ipv4/tcp_sigpool.c +++ /dev/null @@ -1,366 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later - -#include -#include -#include -#include -#include -#include -#include -#include - -static size_t __scratch_size; -struct sigpool_scratch { - local_lock_t bh_lock; - void __rcu *pad; -}; - -static DEFINE_PER_CPU(struct sigpool_scratch, sigpool_scratch) =3D { - .bh_lock =3D INIT_LOCAL_LOCK(bh_lock), -}; - -struct sigpool_entry { - struct crypto_ahash *hash; - const char *alg; - struct kref kref; - uint16_t needs_key:1, - reserved:15; -}; - -#define CPOOL_SIZE (PAGE_SIZE / sizeof(struct sigpool_entry)) -static struct sigpool_entry cpool[CPOOL_SIZE]; -static unsigned int cpool_populated; -static DEFINE_MUTEX(cpool_mutex); - -/* Slow-path */ -struct scratches_to_free { - struct rcu_head rcu; - unsigned int cnt; - void *scratches[]; -}; - -static void free_old_scratches(struct rcu_head *head) -{ - struct scratches_to_free *stf; - - stf =3D container_of(head, struct scratches_to_free, rcu); - while (stf->cnt--) - kfree(stf->scratches[stf->cnt]); - kfree(stf); -} - -/** - * sigpool_reserve_scratch - re-allocates scratch buffer, slow-path - * @size: request size for the scratch/temp buffer - */ -static int sigpool_reserve_scratch(size_t size) -{ - struct scratches_to_free *stf; - size_t stf_sz =3D struct_size(stf, scratches, num_possible_cpus()); - int cpu, err =3D 0; - - lockdep_assert_held(&cpool_mutex); - if (__scratch_size >=3D size) - return 0; - - stf =3D kmalloc(stf_sz, GFP_KERNEL); - if (!stf) - return -ENOMEM; - stf->cnt =3D 0; - - size =3D max(size, __scratch_size); - cpus_read_lock(); - for_each_possible_cpu(cpu) { - void *scratch, *old_scratch; - - scratch =3D kmalloc_node(size, GFP_KERNEL, cpu_to_node(cpu)); - if (!scratch) { - err =3D -ENOMEM; - break; - } - - old_scratch =3D rcu_replace_pointer(per_cpu(sigpool_scratch.pad, cpu), - scratch, lockdep_is_held(&cpool_mutex)); - if (!cpu_online(cpu) || !old_scratch) { - kfree(old_scratch); - continue; - } - stf->scratches[stf->cnt++] =3D old_scratch; - } - cpus_read_unlock(); - if (!err) - __scratch_size =3D size; - - call_rcu(&stf->rcu, free_old_scratches); - return err; -} - -static void sigpool_scratch_free(void) -{ - int cpu; - - for_each_possible_cpu(cpu) - kfree(rcu_replace_pointer(per_cpu(sigpool_scratch.pad, cpu), - NULL, lockdep_is_held(&cpool_mutex))); - __scratch_size =3D 0; -} - -static int __cpool_try_clone(struct crypto_ahash *hash) -{ - struct crypto_ahash *tmp; - - tmp =3D crypto_clone_ahash(hash); - if (IS_ERR(tmp)) - return PTR_ERR(tmp); - - crypto_free_ahash(tmp); - return 0; -} - -static int __cpool_alloc_ahash(struct sigpool_entry *e, const char *alg) -{ - struct crypto_ahash *cpu0_hash; - int ret; - - e->alg =3D kstrdup(alg, GFP_KERNEL); - if (!e->alg) - return -ENOMEM; - - cpu0_hash =3D crypto_alloc_ahash(alg, 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(cpu0_hash)) { - ret =3D PTR_ERR(cpu0_hash); - goto out_free_alg; - } - - e->needs_key =3D crypto_ahash_get_flags(cpu0_hash) & CRYPTO_TFM_NEED_KEY; - - ret =3D __cpool_try_clone(cpu0_hash); - if (ret) - goto out_free_cpu0_hash; - e->hash =3D cpu0_hash; - kref_init(&e->kref); - return 0; - -out_free_cpu0_hash: - crypto_free_ahash(cpu0_hash); -out_free_alg: - kfree(e->alg); - e->alg =3D NULL; - return ret; -} - -/** - * tcp_sigpool_alloc_ahash - allocates pool for ahash requests - * @alg: name of async hash algorithm - * @scratch_size: reserve a tcp_sigpool::scratch buffer of this size - */ -int tcp_sigpool_alloc_ahash(const char *alg, size_t scratch_size) -{ - int i, ret; - - /* slow-path */ - mutex_lock(&cpool_mutex); - ret =3D sigpool_reserve_scratch(scratch_size); - if (ret) - goto out; - for (i =3D 0; i < cpool_populated; i++) { - if (!cpool[i].alg) - continue; - if (strcmp(cpool[i].alg, alg)) - continue; - - /* pairs with tcp_sigpool_release() */ - if (!kref_get_unless_zero(&cpool[i].kref)) - kref_init(&cpool[i].kref); - ret =3D i; - goto out; - } - - for (i =3D 0; i < cpool_populated; i++) { - if (!cpool[i].alg) - break; - } - if (i >=3D CPOOL_SIZE) { - ret =3D -ENOSPC; - goto out; - } - - ret =3D __cpool_alloc_ahash(&cpool[i], alg); - if (!ret) { - ret =3D i; - if (i =3D=3D cpool_populated) - cpool_populated++; - } -out: - mutex_unlock(&cpool_mutex); - return ret; -} -EXPORT_SYMBOL_GPL(tcp_sigpool_alloc_ahash); - -static void __cpool_free_entry(struct sigpool_entry *e) -{ - crypto_free_ahash(e->hash); - kfree(e->alg); - memset(e, 0, sizeof(*e)); -} - -static void cpool_cleanup_work_cb(struct work_struct *work) -{ - bool free_scratch =3D true; - unsigned int i; - - mutex_lock(&cpool_mutex); - for (i =3D 0; i < cpool_populated; i++) { - if (kref_read(&cpool[i].kref) > 0) { - free_scratch =3D false; - continue; - } - if (!cpool[i].alg) - continue; - __cpool_free_entry(&cpool[i]); - } - if (free_scratch) - sigpool_scratch_free(); - mutex_unlock(&cpool_mutex); -} - -static DECLARE_WORK(cpool_cleanup_work, cpool_cleanup_work_cb); -static void cpool_schedule_cleanup(struct kref *kref) -{ - schedule_work(&cpool_cleanup_work); -} - -/** - * tcp_sigpool_release - decreases number of users for a pool. If it was - * the last user of the pool, releases any memory that was consumed. - * @id: tcp_sigpool that was previously allocated by tcp_sigpool_alloc_aha= sh() - */ -void tcp_sigpool_release(unsigned int id) -{ - if (WARN_ON_ONCE(id >=3D cpool_populated || !cpool[id].alg)) - return; - - /* slow-path */ - kref_put(&cpool[id].kref, cpool_schedule_cleanup); -} -EXPORT_SYMBOL_GPL(tcp_sigpool_release); - -/** - * tcp_sigpool_get - increases number of users (refcounter) for a pool - * @id: tcp_sigpool that was previously allocated by tcp_sigpool_alloc_aha= sh() - */ -void tcp_sigpool_get(unsigned int id) -{ - if (WARN_ON_ONCE(id >=3D cpool_populated || !cpool[id].alg)) - return; - kref_get(&cpool[id].kref); -} -EXPORT_SYMBOL_GPL(tcp_sigpool_get); - -int tcp_sigpool_start(unsigned int id, struct tcp_sigpool *c) __cond_acqui= res(0, RCU_BH) -{ - struct crypto_ahash *hash; - - rcu_read_lock_bh(); - if (WARN_ON_ONCE(id >=3D cpool_populated || !cpool[id].alg)) { - rcu_read_unlock_bh(); - return -EINVAL; - } - - hash =3D crypto_clone_ahash(cpool[id].hash); - if (IS_ERR(hash)) { - rcu_read_unlock_bh(); - return PTR_ERR(hash); - } - - c->req =3D ahash_request_alloc(hash, GFP_ATOMIC); - if (!c->req) { - crypto_free_ahash(hash); - rcu_read_unlock_bh(); - return -ENOMEM; - } - ahash_request_set_callback(c->req, 0, NULL, NULL); - - /* Pairs with tcp_sigpool_reserve_scratch(), scratch area is - * valid (allocated) until tcp_sigpool_end(). - */ - local_lock_nested_bh(&sigpool_scratch.bh_lock); - c->scratch =3D rcu_dereference_bh(*this_cpu_ptr(&sigpool_scratch.pad)); - return 0; -} -EXPORT_SYMBOL_GPL(tcp_sigpool_start); - -void tcp_sigpool_end(struct tcp_sigpool *c) __releases(RCU_BH) -{ - struct crypto_ahash *hash =3D crypto_ahash_reqtfm(c->req); - - local_unlock_nested_bh(&sigpool_scratch.bh_lock); - rcu_read_unlock_bh(); - ahash_request_free(c->req); - crypto_free_ahash(hash); -} -EXPORT_SYMBOL_GPL(tcp_sigpool_end); - -/** - * tcp_sigpool_algo - return algorithm of tcp_sigpool - * @id: tcp_sigpool that was previously allocated by tcp_sigpool_alloc_aha= sh() - * @buf: buffer to return name of algorithm - * @buf_len: size of @buf - */ -size_t tcp_sigpool_algo(unsigned int id, char *buf, size_t buf_len) -{ - if (WARN_ON_ONCE(id >=3D cpool_populated || !cpool[id].alg)) - return -EINVAL; - - return strscpy(buf, cpool[id].alg, buf_len); -} -EXPORT_SYMBOL_GPL(tcp_sigpool_algo); - -/** - * tcp_sigpool_hash_skb_data - hash data in skb with initialized tcp_sigpo= ol - * @hp: tcp_sigpool pointer - * @skb: buffer to add sign for - * @header_len: TCP header length for this segment - */ -int tcp_sigpool_hash_skb_data(struct tcp_sigpool *hp, - const struct sk_buff *skb, - unsigned int header_len) -{ - const unsigned int head_data_len =3D skb_headlen(skb) > header_len ? - skb_headlen(skb) - header_len : 0; - const struct skb_shared_info *shi =3D skb_shinfo(skb); - const struct tcphdr *tp =3D tcp_hdr(skb); - struct ahash_request *req =3D hp->req; - struct sk_buff *frag_iter; - struct scatterlist sg; - unsigned int i; - - sg_init_table(&sg, 1); - - sg_set_buf(&sg, ((u8 *)tp) + header_len, head_data_len); - ahash_request_set_crypt(req, &sg, NULL, head_data_len); - if (crypto_ahash_update(req)) - return 1; - - for (i =3D 0; i < shi->nr_frags; ++i) { - const skb_frag_t *f =3D &shi->frags[i]; - unsigned int offset =3D skb_frag_off(f); - struct page *page; - - page =3D skb_frag_page(f) + (offset >> PAGE_SHIFT); - sg_set_page(&sg, page, skb_frag_size(f), offset_in_page(offset)); - ahash_request_set_crypt(req, &sg, NULL, skb_frag_size(f)); - if (crypto_ahash_update(req)) - return 1; - } - - skb_walk_frags(skb, frag_iter) - if (tcp_sigpool_hash_skb_data(hp, frag_iter, 0)) - return 1; - - return 0; -} -EXPORT_SYMBOL(tcp_sigpool_hash_skb_data); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Per-CPU pool of crypto requests"); --=20 2.53.0 From nobody Thu Apr 9 14:08:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C96EF346770; Sat, 7 Mar 2026 22:46:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772923577; cv=none; b=kHnRjJnl8qvHtYxNEi4Tb+quhjNqgcAN3zZMuoOsKIEQs/nbiNLNDxjOZJU0tZpGbzM+jPSpmdkxGvmVjrBzRwhFKQhSKR1cZQeAT3b9ibrcXX/Vo7wR7Z/0cB27iMfH8Rps/Ihe248m7GNRMNtkjuklsdXfQIGmoAglhwxTJ6s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772923577; c=relaxed/simple; bh=NaDEjwP1efsfHD7GRkA/+b8LQpDP7b8fj8TiHJoftd8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=XMSXsQv7B98Se5d9Comm7QYiLqtNjDtk7QiTSx6wkAEmHQIB8wgTqfj5gXd7PTVFHPRrAx3GLzka++WrcqVe4e7Plisy2j7lzC3snTZ07a3RqBDbw8WuP95lp9wZf1LfxeGazbH/O9r5S3gXBYwkaM23WJ/G32zetjmwOAVsvOM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=mUDay2dm; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="mUDay2dm" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 42ABAC19423; Sat, 7 Mar 2026 22:46:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1772923577; bh=NaDEjwP1efsfHD7GRkA/+b8LQpDP7b8fj8TiHJoftd8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=mUDay2dmzhc40wywat/XlLuCHs5kjflNQggo4QFHRXd8CK6EDj5fJst6SkEv6kJy/ RGj4O24n1d/S44F5/0FFQcIvyc/eRHiVikyt1q/uCfQnzRsRwj+pvMm2bEY6civ3ri 6xyCsKOY8s0TI9yFjXorlW9byaceFuBMsRlvNyF1p0N3/MnO+BjB2P7oJS36k8/foy OCmQ/ErPucxvJIWHYFvaLbEBA9Uh8gPNdmSPY+EjVPusQbmPe17G8EDkYS9MDhXeWk NQAiDCvQwG7arXajjAeooWvTVQkMosBJLF3CtI4qHSdvkvwQsM17UTujCL9TKNenCm 7Pk23nR/ey0EA== From: Eric Biggers To: netdev@vger.kernel.org Cc: linux-crypto@vger.kernel.org, linux-kernel@vger.kernel.org, Eric Dumazet , Neal Cardwell , Kuniyuki Iwashima , "David S . Miller" , David Ahern , Jakub Kicinski , Paolo Abeni , Simon Horman , Ard Biesheuvel , "Jason A . Donenfeld" , Herbert Xu , Dmitry Safonov <0x7f454c46@gmail.com>, Eric Biggers Subject: [RFC PATCH 6/8] crypto: hash - Remove support for cloning hash tfms Date: Sat, 7 Mar 2026 14:43:39 -0800 Message-ID: <20260307224341.5644-7-ebiggers@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260307224341.5644-1-ebiggers@kernel.org> References: <20260307224341.5644-1-ebiggers@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Hash transformation cloning no longer has a user, and there's a good chance no new one will appear because the library API solves the problem in a much simpler and more efficient way. Remove support for it. Signed-off-by: Eric Biggers Reviewed-by: Ard Biesheuvel --- crypto/ahash.c | 70 ------------------------------------------- crypto/cmac.c | 16 ---------- crypto/cryptd.c | 16 ---------- crypto/hmac.c | 31 ------------------- crypto/shash.c | 37 ----------------------- include/crypto/hash.h | 8 ----- 6 files changed, 178 deletions(-) diff --git a/crypto/ahash.c b/crypto/ahash.c index 7a730324c50e2..85dcd120de3ee 100644 --- a/crypto/ahash.c +++ b/crypto/ahash.c @@ -860,80 +860,10 @@ bool crypto_hash_alg_has_setkey(struct hash_alg_commo= n *halg) =20 return __crypto_ahash_alg(alg)->setkey !=3D ahash_nosetkey; } EXPORT_SYMBOL_GPL(crypto_hash_alg_has_setkey); =20 -struct crypto_ahash *crypto_clone_ahash(struct crypto_ahash *hash) -{ - struct hash_alg_common *halg =3D crypto_hash_alg_common(hash); - struct crypto_tfm *tfm =3D crypto_ahash_tfm(hash); - struct crypto_ahash *fb =3D NULL; - struct crypto_ahash *nhash; - struct ahash_alg *alg; - int err; - - if (!crypto_hash_alg_has_setkey(halg)) { - tfm =3D crypto_tfm_get(tfm); - if (IS_ERR(tfm)) - return ERR_CAST(tfm); - - return hash; - } - - nhash =3D crypto_clone_tfm(&crypto_ahash_type, tfm); - - if (IS_ERR(nhash)) - return nhash; - - nhash->reqsize =3D hash->reqsize; - nhash->statesize =3D hash->statesize; - - if (likely(hash->using_shash)) { - struct crypto_shash **nctx =3D crypto_ahash_ctx(nhash); - struct crypto_shash *shash; - - shash =3D crypto_clone_shash(ahash_to_shash(hash)); - if (IS_ERR(shash)) { - err =3D PTR_ERR(shash); - goto out_free_nhash; - } - crypto_ahash_tfm(nhash)->exit =3D crypto_exit_ahash_using_shash; - nhash->using_shash =3D true; - *nctx =3D shash; - return nhash; - } - - if (crypto_ahash_need_fallback(hash)) { - fb =3D crypto_clone_ahash(crypto_ahash_fb(hash)); - err =3D PTR_ERR(fb); - if (IS_ERR(fb)) - goto out_free_nhash; - - crypto_ahash_tfm(nhash)->fb =3D crypto_ahash_tfm(fb); - } - - err =3D -ENOSYS; - alg =3D crypto_ahash_alg(hash); - if (!alg->clone_tfm) - goto out_free_fb; - - err =3D alg->clone_tfm(nhash, hash); - if (err) - goto out_free_fb; - - crypto_ahash_tfm(nhash)->exit =3D crypto_ahash_exit_tfm; - - return nhash; - -out_free_fb: - crypto_free_ahash(fb); -out_free_nhash: - crypto_free_ahash(nhash); - return ERR_PTR(err); -} -EXPORT_SYMBOL_GPL(crypto_clone_ahash); - static int ahash_default_export_core(struct ahash_request *req, void *out) { return -ENOSYS; } =20 diff --git a/crypto/cmac.c b/crypto/cmac.c index 1b03964abe007..83e58937f0136 100644 --- a/crypto/cmac.c +++ b/crypto/cmac.c @@ -149,25 +149,10 @@ static int cmac_init_tfm(struct crypto_shash *tfm) ctx->child =3D cipher; =20 return 0; } =20 -static int cmac_clone_tfm(struct crypto_shash *tfm, struct crypto_shash *o= tfm) -{ - struct cmac_tfm_ctx *octx =3D crypto_shash_ctx(otfm); - struct cmac_tfm_ctx *ctx =3D crypto_shash_ctx(tfm); - struct crypto_cipher *cipher; - - cipher =3D crypto_clone_cipher(octx->child); - if (IS_ERR(cipher)) - return PTR_ERR(cipher); - - ctx->child =3D cipher; - - return 0; -} - static void cmac_exit_tfm(struct crypto_shash *tfm) { struct cmac_tfm_ctx *ctx =3D crypto_shash_ctx(tfm); crypto_free_cipher(ctx->child); } @@ -220,11 +205,10 @@ static int cmac_create(struct crypto_template *tmpl, = struct rtattr **tb) inst->alg.init =3D crypto_cmac_digest_init; inst->alg.update =3D crypto_cmac_digest_update; inst->alg.finup =3D crypto_cmac_digest_finup; inst->alg.setkey =3D crypto_cmac_digest_setkey; inst->alg.init_tfm =3D cmac_init_tfm; - inst->alg.clone_tfm =3D cmac_clone_tfm; inst->alg.exit_tfm =3D cmac_exit_tfm; =20 inst->free =3D shash_free_singlespawn_instance; =20 err =3D shash_register_instance(tmpl, inst); diff --git a/crypto/cryptd.c b/crypto/cryptd.c index cd38f46761767..e2958020f1ae4 100644 --- a/crypto/cryptd.c +++ b/crypto/cryptd.c @@ -450,25 +450,10 @@ static int cryptd_hash_init_tfm(struct crypto_ahash *= tfm) sizeof(struct cryptd_hash_request_ctx) + crypto_shash_descsize(hash)); return 0; } =20 -static int cryptd_hash_clone_tfm(struct crypto_ahash *ntfm, - struct crypto_ahash *tfm) -{ - struct cryptd_hash_ctx *nctx =3D crypto_ahash_ctx(ntfm); - struct cryptd_hash_ctx *ctx =3D crypto_ahash_ctx(tfm); - struct crypto_shash *hash; - - hash =3D crypto_clone_shash(ctx->child); - if (IS_ERR(hash)) - return PTR_ERR(hash); - - nctx->child =3D hash; - return 0; -} - static void cryptd_hash_exit_tfm(struct crypto_ahash *tfm) { struct cryptd_hash_ctx *ctx =3D crypto_ahash_ctx(tfm); =20 crypto_free_shash(ctx->child); @@ -697,11 +682,10 @@ static int cryptd_create_hash(struct crypto_template = *tmpl, struct rtattr **tb, inst->alg.halg.digestsize =3D alg->digestsize; inst->alg.halg.statesize =3D alg->statesize; inst->alg.halg.base.cra_ctxsize =3D sizeof(struct cryptd_hash_ctx); =20 inst->alg.init_tfm =3D cryptd_hash_init_tfm; - inst->alg.clone_tfm =3D cryptd_hash_clone_tfm; inst->alg.exit_tfm =3D cryptd_hash_exit_tfm; =20 inst->alg.init =3D cryptd_hash_init_enqueue; inst->alg.update =3D cryptd_hash_update_enqueue; inst->alg.final =3D cryptd_hash_final_enqueue; diff --git a/crypto/hmac.c b/crypto/hmac.c index 148af460ae974..807e08b252c55 100644 --- a/crypto/hmac.c +++ b/crypto/hmac.c @@ -156,24 +156,10 @@ static int hmac_init_tfm(struct crypto_shash *parent) =20 tctx->hash =3D hash; return 0; } =20 -static int hmac_clone_tfm(struct crypto_shash *dst, struct crypto_shash *s= rc) -{ - struct hmac_ctx *sctx =3D crypto_shash_ctx(src); - struct hmac_ctx *dctx =3D crypto_shash_ctx(dst); - struct crypto_shash *hash; - - hash =3D crypto_clone_shash(sctx->hash); - if (IS_ERR(hash)) - return PTR_ERR(hash); - - dctx->hash =3D hash; - return 0; -} - static void hmac_exit_tfm(struct crypto_shash *parent) { struct hmac_ctx *tctx =3D crypto_shash_ctx(parent); =20 crypto_free_shash(tctx->hash); @@ -233,11 +219,10 @@ static int __hmac_create_shash(struct crypto_template= *tmpl, inst->alg.import =3D hmac_import; inst->alg.export_core =3D hmac_export_core; inst->alg.import_core =3D hmac_import_core; inst->alg.setkey =3D hmac_setkey; inst->alg.init_tfm =3D hmac_init_tfm; - inst->alg.clone_tfm =3D hmac_clone_tfm; inst->alg.exit_tfm =3D hmac_exit_tfm; =20 inst->free =3D shash_free_singlespawn_instance; =20 err =3D shash_register_instance(tmpl, inst); @@ -421,25 +406,10 @@ static int hmac_init_ahash_tfm(struct crypto_ahash *p= arent) =20 tctx->hash =3D hash; return 0; } =20 -static int hmac_clone_ahash_tfm(struct crypto_ahash *dst, - struct crypto_ahash *src) -{ - struct ahash_hmac_ctx *sctx =3D crypto_ahash_ctx(src); - struct ahash_hmac_ctx *dctx =3D crypto_ahash_ctx(dst); - struct crypto_ahash *hash; - - hash =3D crypto_clone_ahash(sctx->hash); - if (IS_ERR(hash)) - return PTR_ERR(hash); - - dctx->hash =3D hash; - return 0; -} - static void hmac_exit_ahash_tfm(struct crypto_ahash *parent) { struct ahash_hmac_ctx *tctx =3D crypto_ahash_ctx(parent); =20 crypto_free_ahash(tctx->hash); @@ -501,11 +471,10 @@ static int hmac_create_ahash(struct crypto_template *= tmpl, struct rtattr **tb, inst->alg.import =3D hmac_import_ahash; inst->alg.export_core =3D hmac_export_core_ahash; inst->alg.import_core =3D hmac_import_core_ahash; inst->alg.setkey =3D hmac_setkey_ahash; inst->alg.init_tfm =3D hmac_init_ahash_tfm; - inst->alg.clone_tfm =3D hmac_clone_ahash_tfm; inst->alg.exit_tfm =3D hmac_exit_ahash_tfm; =20 inst->free =3D ahash_free_singlespawn_instance; =20 err =3D ahash_register_instance(tmpl, inst); diff --git a/crypto/shash.c b/crypto/shash.c index 2f07d0bd1f61b..351cba3c11070 100644 --- a/crypto/shash.c +++ b/crypto/shash.c @@ -393,47 +393,10 @@ int crypto_has_shash(const char *alg_name, u32 type, = u32 mask) { return crypto_type_has_alg(alg_name, &crypto_shash_type, type, mask); } EXPORT_SYMBOL_GPL(crypto_has_shash); =20 -struct crypto_shash *crypto_clone_shash(struct crypto_shash *hash) -{ - struct crypto_tfm *tfm =3D crypto_shash_tfm(hash); - struct shash_alg *alg =3D crypto_shash_alg(hash); - struct crypto_shash *nhash; - int err; - - if (!crypto_shash_alg_has_setkey(alg)) { - tfm =3D crypto_tfm_get(tfm); - if (IS_ERR(tfm)) - return ERR_CAST(tfm); - - return hash; - } - - if (!alg->clone_tfm && (alg->init_tfm || alg->base.cra_init)) - return ERR_PTR(-ENOSYS); - - nhash =3D crypto_clone_tfm(&crypto_shash_type, tfm); - if (IS_ERR(nhash)) - return nhash; - - if (alg->clone_tfm) { - err =3D alg->clone_tfm(nhash, hash); - if (err) { - crypto_free_shash(nhash); - return ERR_PTR(err); - } - } - - if (alg->exit_tfm) - crypto_shash_tfm(nhash)->exit =3D crypto_shash_exit_tfm; - - return nhash; -} -EXPORT_SYMBOL_GPL(crypto_clone_shash); - int hash_prepare_alg(struct hash_alg_common *alg) { struct crypto_alg *base =3D &alg->base; =20 if (alg->digestsize > HASH_MAX_DIGESTSIZE) diff --git a/include/crypto/hash.h b/include/crypto/hash.h index 586700332c731..e474f8461ea19 100644 --- a/include/crypto/hash.h +++ b/include/crypto/hash.h @@ -146,11 +146,10 @@ struct ahash_request { * requirement of the transformation and put any software * fallbacks in place. * @exit_tfm: Deinitialize the cryptographic transformation object. * This is a counterpart to @init_tfm, used to remove * various changes set in @init_tfm. - * @clone_tfm: Copy transform into new object, may allocate memory. * @halg: see struct hash_alg_common */ struct ahash_alg { int (*init)(struct ahash_request *req); int (*update)(struct ahash_request *req); @@ -163,11 +162,10 @@ struct ahash_alg { int (*import_core)(struct ahash_request *req, const void *in); int (*setkey)(struct crypto_ahash *tfm, const u8 *key, unsigned int keylen); int (*init_tfm)(struct crypto_ahash *tfm); void (*exit_tfm)(struct crypto_ahash *tfm); - int (*clone_tfm)(struct crypto_ahash *dst, struct crypto_ahash *src); =20 struct hash_alg_common halg; }; =20 struct shash_desc { @@ -237,11 +235,10 @@ struct shash_desc { * requirement of the transformation and put any software * fallbacks in place. * @exit_tfm: Deinitialize the cryptographic transformation object. * This is a counterpart to @init_tfm, used to remove * various changes set in @init_tfm. - * @clone_tfm: Copy transform into new object, may allocate memory. * @descsize: Size of the operational state for the message digest. This s= tate * size is the memory size that needs to be allocated for * shash_desc.__ctx * @halg: see struct hash_alg_common * @HASH_ALG_COMMON: see struct hash_alg_common @@ -261,11 +258,10 @@ struct shash_alg { int (*import_core)(struct shash_desc *desc, const void *in); int (*setkey)(struct crypto_shash *tfm, const u8 *key, unsigned int keylen); int (*init_tfm)(struct crypto_shash *tfm); void (*exit_tfm)(struct crypto_shash *tfm); - int (*clone_tfm)(struct crypto_shash *dst, struct crypto_shash *src); =20 unsigned int descsize; =20 union { struct HASH_ALG_COMMON; @@ -320,12 +316,10 @@ static inline struct crypto_ahash *__crypto_ahash_cas= t(struct crypto_tfm *tfm) * of an error, PTR_ERR() returns the error code. */ struct crypto_ahash *crypto_alloc_ahash(const char *alg_name, u32 type, u32 mask); =20 -struct crypto_ahash *crypto_clone_ahash(struct crypto_ahash *tfm); - static inline struct crypto_tfm *crypto_ahash_tfm(struct crypto_ahash *tfm) { return &tfm->base; } =20 @@ -757,12 +751,10 @@ static inline void ahash_request_set_virt(struct ahas= h_request *req, * of an error, PTR_ERR() returns the error code. */ struct crypto_shash *crypto_alloc_shash(const char *alg_name, u32 type, u32 mask); =20 -struct crypto_shash *crypto_clone_shash(struct crypto_shash *tfm); - int crypto_has_shash(const char *alg_name, u32 type, u32 mask); =20 static inline struct crypto_tfm *crypto_shash_tfm(struct crypto_shash *tfm) { return &tfm->base; --=20 2.53.0 From nobody Thu Apr 9 14:08:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 629953491D6; Sat, 7 Mar 2026 22:46:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772923578; cv=none; b=mLF1/b6Kqk5GfyIuf8iWWgMjh6BQQ9HdYZHqGozKGuQHPvHgBhv8jfP77tKH2xzy3NjJogFMYQ6ttB3BOu1i9TSozpKR3ARGQ4gPV6WQ9C2LmlViOqqwXHbz37ZQv6LVfXIWNEj5pGgpch8xiOYya4+ZU5cHA+zzQIPddtFIzz0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772923578; c=relaxed/simple; bh=WQ9EOLjzb3i+YgCwyjm5urNHc/DtubdXpLVFU8D2oJs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=QRnh+YDTrYRgJ0W7eBqGb6rQH7HUs/kMNgyLx/+Kx3/ou6eOMEPsawyuJk7xvM8lwotD7nkUrMXSRW+8kEcGqtNNZQnLgepQXx3Js4ERaMtJPSpzKLxS8wTnwb/dhTc6fV/saBrKsbNlOJucDYQjnJHXbsIggyNLY/W7B5sdBLM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=hEdIdGQk; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="hEdIdGQk" Received: by smtp.kernel.org (Postfix) with ESMTPSA id CFFA4C2BCB4; Sat, 7 Mar 2026 22:46:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1772923578; bh=WQ9EOLjzb3i+YgCwyjm5urNHc/DtubdXpLVFU8D2oJs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=hEdIdGQkQS3a4EBY31JV8NJIMUIB2o6b44AA57ReuBEirsrD91dZ17hZimuZV+GAv DzqFIvpNkCRaZ7xHspY16vCu9qUCGd5gjb9rUGNFxwJi50aeF3UEYNlw/dzE4hWPV6 an4KUpmXp+YBIlW64F0dbw55RBHDncqBtYOa6fzA0XD4nkO/8lE+D9eUdmr2nXv7mD L2eTN6XYxgLVTJP15Ic3SCDTGKKY7hMJqXfRgfBT/I/t/7u21S+HJ6SYhw/O9GgMDo b+rqhT26Aq+s3GLJT229Xwy6IbM6lO4hgnpiExBcqe6R06fBvMlDZKy8bqVIgZxBSw JOTAXeyx2hkZQ== From: Eric Biggers To: netdev@vger.kernel.org Cc: linux-crypto@vger.kernel.org, linux-kernel@vger.kernel.org, Eric Dumazet , Neal Cardwell , Kuniyuki Iwashima , "David S . Miller" , David Ahern , Jakub Kicinski , Paolo Abeni , Simon Horman , Ard Biesheuvel , "Jason A . Donenfeld" , Herbert Xu , Dmitry Safonov <0x7f454c46@gmail.com>, Eric Biggers Subject: [RFC PATCH 7/8] crypto: cipher - Remove support for cloning cipher tfms Date: Sat, 7 Mar 2026 14:43:40 -0800 Message-ID: <20260307224341.5644-8-ebiggers@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260307224341.5644-1-ebiggers@kernel.org> References: <20260307224341.5644-1-ebiggers@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Since the only caller of crypto_clone_cipher() was cmac_clone_tfm() which has been removed, remove crypto_clone_cipher() as well. Signed-off-by: Eric Biggers Reviewed-by: Ard Biesheuvel --- crypto/cipher.c | 28 ---------------------------- include/crypto/internal/cipher.h | 2 -- 2 files changed, 30 deletions(-) diff --git a/crypto/cipher.c b/crypto/cipher.c index 1fe62bf79656b..c9dab656a622e 100644 --- a/crypto/cipher.c +++ b/crypto/cipher.c @@ -87,33 +87,5 @@ void crypto_cipher_decrypt_one(struct crypto_cipher *tfm, u8 *dst, const u8 *src) { cipher_crypt_one(tfm, dst, src, false); } EXPORT_SYMBOL_NS_GPL(crypto_cipher_decrypt_one, "CRYPTO_INTERNAL"); - -struct crypto_cipher *crypto_clone_cipher(struct crypto_cipher *cipher) -{ - struct crypto_tfm *tfm =3D crypto_cipher_tfm(cipher); - struct crypto_alg *alg =3D tfm->__crt_alg; - struct crypto_cipher *ncipher; - struct crypto_tfm *ntfm; - - if (alg->cra_init) - return ERR_PTR(-ENOSYS); - - if (unlikely(!crypto_mod_get(alg))) - return ERR_PTR(-ESTALE); - - ntfm =3D __crypto_alloc_tfmgfp(alg, CRYPTO_ALG_TYPE_CIPHER, - CRYPTO_ALG_TYPE_MASK, GFP_ATOMIC); - if (IS_ERR(ntfm)) { - crypto_mod_put(alg); - return ERR_CAST(ntfm); - } - - ntfm->crt_flags =3D tfm->crt_flags; - - ncipher =3D __crypto_cipher_cast(ntfm); - - return ncipher; -} -EXPORT_SYMBOL_GPL(crypto_clone_cipher); diff --git a/include/crypto/internal/cipher.h b/include/crypto/internal/cip= her.h index 5030f6d2df315..a9174ba902500 100644 --- a/include/crypto/internal/cipher.h +++ b/include/crypto/internal/cipher.h @@ -174,12 +174,10 @@ void crypto_cipher_encrypt_one(struct crypto_cipher *= tfm, * the plaintext and ciphertext buffers are at least one block in size. */ void crypto_cipher_decrypt_one(struct crypto_cipher *tfm, u8 *dst, const u8 *src); =20 -struct crypto_cipher *crypto_clone_cipher(struct crypto_cipher *cipher); - struct crypto_cipher_spawn { struct crypto_spawn base; }; =20 static inline int crypto_grab_cipher(struct crypto_cipher_spawn *spawn, --=20 2.53.0 From nobody Thu Apr 9 14:08:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F050134D4D3; Sat, 7 Mar 2026 22:46:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772923579; cv=none; b=OAAb0gLQ7DcRLg2bxrKNGH7g3pWOPwe8D3QbHgabXc54OS7jacd/5+xJ9NWunIHycfThAxk9//cUSlsNuiImqK+VUkOusz1qdHgWdxpFiBxRCaCKK9tlipVaHsqclrZEmIqmWRD0mj8z/l32Nc9w15GZlTPud2Itt8D4Nhw/6Tc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772923579; c=relaxed/simple; bh=Tj1UiXBp5rN/yqKvjZfr5OUuq0XLn4r2ZzolzarWTFU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=iYD3c3kRY9hjW+wYmdGvc04RbmSryy+x0YSu4KmgpX2y7yrTVCqlGpUlqWQRxalhmm0d5hSkuOaCa9Uhnur5P0yru5g17ZC+RdnDQAz2exdsF2urVSSbjyHUW6RqzygCmqhi6hp263mHNs2qbIdSt2RQS2dVWACLDQde+Uhnves= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Hs6UvOXA; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Hs6UvOXA" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 685E3C2BC9E; Sat, 7 Mar 2026 22:46:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1772923578; bh=Tj1UiXBp5rN/yqKvjZfr5OUuq0XLn4r2ZzolzarWTFU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Hs6UvOXAO5+xom5yAVnoxONW17fDxefETodyDnYCp/8x+3a285avpF52GigBP57PQ bE2OyTvV++sAjdOYYGN0Oy12YtxOrs2cU3G1thmy/lh5YAci1ZzsplZXPsKvkUXTis PMHTvpAoFaaMf9QDWgtXGPOtR5P0aQud+bJ9FW0YJy9bpYjv6g4CEPOK3qTezao+L1 vlSg27rr7S9VA2IMKO76Xu8iKf7etEX1E8OlLr57Uc/tk2T6UyFg7AZcf1w0HZoM3Z RoWww5UVyMwZ/+7ue/tIE61nj/CygjmhdSQ+dXbj98HETaFHEn132WiYFcwv6G22YP VEmpRfPDaOJ3g== From: Eric Biggers To: netdev@vger.kernel.org Cc: linux-crypto@vger.kernel.org, linux-kernel@vger.kernel.org, Eric Dumazet , Neal Cardwell , Kuniyuki Iwashima , "David S . Miller" , David Ahern , Jakub Kicinski , Paolo Abeni , Simon Horman , Ard Biesheuvel , "Jason A . Donenfeld" , Herbert Xu , Dmitry Safonov <0x7f454c46@gmail.com>, Eric Biggers Subject: [RFC PATCH 8/8] crypto: api - Remove core support for cloning tfms Date: Sat, 7 Mar 2026 14:43:41 -0800 Message-ID: <20260307224341.5644-9-ebiggers@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260307224341.5644-1-ebiggers@kernel.org> References: <20260307224341.5644-1-ebiggers@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Since all callers of crypto_clone_tfm() have been removed, remove it. Signed-off-by: Eric Biggers Reviewed-by: Ard Biesheuvel --- crypto/api.c | 26 -------------------------- crypto/internal.h | 2 -- 2 files changed, 28 deletions(-) diff --git a/crypto/api.c b/crypto/api.c index 74e17d5049c99..d019d1979857d 100644 --- a/crypto/api.c +++ b/crypto/api.c @@ -558,36 +558,10 @@ void *crypto_create_tfm_node(struct crypto_alg *alg, out: return mem; } EXPORT_SYMBOL_GPL(crypto_create_tfm_node); =20 -void *crypto_clone_tfm(const struct crypto_type *frontend, - struct crypto_tfm *otfm) -{ - struct crypto_alg *alg =3D otfm->__crt_alg; - struct crypto_tfm *tfm; - char *mem; - - mem =3D ERR_PTR(-ESTALE); - if (unlikely(!crypto_mod_get(alg))) - goto out; - - mem =3D crypto_alloc_tfmmem(alg, frontend, otfm->node, GFP_ATOMIC); - if (IS_ERR(mem)) { - crypto_mod_put(alg); - goto out; - } - - tfm =3D (struct crypto_tfm *)(mem + frontend->tfmsize); - tfm->crt_flags =3D otfm->crt_flags; - tfm->fb =3D tfm; - -out: - return mem; -} -EXPORT_SYMBOL_GPL(crypto_clone_tfm); - struct crypto_alg *crypto_find_alg(const char *alg_name, const struct crypto_type *frontend, u32 type, u32 mask) { if (frontend) { diff --git a/crypto/internal.h b/crypto/internal.h index 8fbe0226d48e2..96f84abfac91e 100644 --- a/crypto/internal.h +++ b/crypto/internal.h @@ -124,12 +124,10 @@ struct crypto_tfm *__crypto_alloc_tfmgfp(struct crypt= o_alg *alg, u32 type, u32 mask, gfp_t gfp); struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type, u32 mask); void *crypto_create_tfm_node(struct crypto_alg *alg, const struct crypto_type *frontend, int node); -void *crypto_clone_tfm(const struct crypto_type *frontend, - struct crypto_tfm *otfm); =20 static inline void *crypto_create_tfm(struct crypto_alg *alg, const struct crypto_type *frontend) { return crypto_create_tfm_node(alg, frontend, NUMA_NO_NODE); --=20 2.53.0