* Re: [PATCH 01/31] crypto: Introduce crypto_pool
@ 2022-08-22 5:35 kernel test robot
0 siblings, 0 replies; 2+ messages in thread
From: kernel test robot @ 2022-08-22 5:35 UTC (permalink / raw)
To: kbuild
[-- Attachment #1: Type: text/plain, Size: 4977 bytes --]
BCC: lkp(a)intel.com
CC: kbuild-all(a)lists.01.org
In-Reply-To: <20220818170005.747015-2-dima@arista.com>
References: <20220818170005.747015-2-dima@arista.com>
TO: Dmitry Safonov <dima@arista.com>
TO: Eric Dumazet <edumazet@google.com>
TO: "David S. Miller" <davem@davemloft.net>
CC: netdev(a)vger.kernel.org
TO: linux-kernel(a)vger.kernel.org
CC: Dmitry Safonov <dima@arista.com>
CC: Andy Lutomirski <luto@amacapital.net>
CC: Ard Biesheuvel <ardb@kernel.org>
CC: Bob Gilligan <gilligan@arista.com>
CC: David Ahern <dsahern@kernel.org>
CC: Eric Biggers <ebiggers@kernel.org>
CC: Francesco Ruggeri <fruggeri@arista.com>
CC: Herbert Xu <herbert@gondor.apana.org.au>
CC: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
CC: Ivan Delalande <colona@arista.com>
CC: Jakub Kicinski <kuba@kernel.org>
CC: Leonard Crestez <cdleonard@gmail.com>
CC: Paolo Abeni <pabeni@redhat.com>
CC: Salam Noureddine <noureddine@arista.com>
CC: Shuah Khan <skhan@linuxfoundation.org>
CC: linux-crypto(a)vger.kernel.org
Hi Dmitry,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on e34cfee65ec891a319ce79797dda18083af33a76]
url: https://github.com/intel-lab-lkp/linux/commits/Dmitry-Safonov/net-tcp-Add-TCP-AO-support/20220819-010628
base: e34cfee65ec891a319ce79797dda18083af33a76
:::::: branch date: 4 days ago
:::::: commit date: 4 days ago
config: x86_64-randconfig-m001 (https://download.01.org/0day-ci/archive/20220822/202208221327.PD3sMUrp-lkp(a)intel.com/config)
compiler: gcc-11 (Debian 11.3.0-5) 11.3.0
If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <lkp@intel.com>
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
smatch warnings:
crypto/crypto_pool.c:161 crypto_pool_alloc_ahash() error: testing array offset 'i' after use.
vim +/i +161 crypto/crypto_pool.c
f4c3873630fc8c4 Dmitry Safonov 2022-08-18 130
f4c3873630fc8c4 Dmitry Safonov 2022-08-18 131 /**
f4c3873630fc8c4 Dmitry Safonov 2022-08-18 132 * crypto_pool_alloc_ahash - allocates pool for ahash requests
f4c3873630fc8c4 Dmitry Safonov 2022-08-18 133 * @alg: name of async hash algorithm
f4c3873630fc8c4 Dmitry Safonov 2022-08-18 134 */
f4c3873630fc8c4 Dmitry Safonov 2022-08-18 135 int crypto_pool_alloc_ahash(const char *alg)
f4c3873630fc8c4 Dmitry Safonov 2022-08-18 136 {
f4c3873630fc8c4 Dmitry Safonov 2022-08-18 137 unsigned int i;
f4c3873630fc8c4 Dmitry Safonov 2022-08-18 138 int err;
f4c3873630fc8c4 Dmitry Safonov 2022-08-18 139
f4c3873630fc8c4 Dmitry Safonov 2022-08-18 140 /* slow-path */
f4c3873630fc8c4 Dmitry Safonov 2022-08-18 141 mutex_lock(&cpool_mutex);
f4c3873630fc8c4 Dmitry Safonov 2022-08-18 142 err = crypto_pool_scratch_alloc();
f4c3873630fc8c4 Dmitry Safonov 2022-08-18 143 if (err)
f4c3873630fc8c4 Dmitry Safonov 2022-08-18 144 goto out;
f4c3873630fc8c4 Dmitry Safonov 2022-08-18 145
f4c3873630fc8c4 Dmitry Safonov 2022-08-18 146 for (i = 0; i < last_allocated; i++) {
f4c3873630fc8c4 Dmitry Safonov 2022-08-18 147 if (cpool[i].alg && !strcmp(cpool[i].alg, alg)) {
f4c3873630fc8c4 Dmitry Safonov 2022-08-18 148 if (kref_read(&cpool[i].kref) > 0) {
f4c3873630fc8c4 Dmitry Safonov 2022-08-18 149 kref_get(&cpool[i].kref);
f4c3873630fc8c4 Dmitry Safonov 2022-08-18 150 goto out;
f4c3873630fc8c4 Dmitry Safonov 2022-08-18 151 } else {
f4c3873630fc8c4 Dmitry Safonov 2022-08-18 152 break;
f4c3873630fc8c4 Dmitry Safonov 2022-08-18 153 }
f4c3873630fc8c4 Dmitry Safonov 2022-08-18 154 }
f4c3873630fc8c4 Dmitry Safonov 2022-08-18 155 }
f4c3873630fc8c4 Dmitry Safonov 2022-08-18 156
f4c3873630fc8c4 Dmitry Safonov 2022-08-18 157 for (i = 0; i < last_allocated; i++) {
f4c3873630fc8c4 Dmitry Safonov 2022-08-18 158 if (!cpool[i].alg)
f4c3873630fc8c4 Dmitry Safonov 2022-08-18 159 break;
f4c3873630fc8c4 Dmitry Safonov 2022-08-18 160 }
f4c3873630fc8c4 Dmitry Safonov 2022-08-18 @161 if (i >= CPOOL_SIZE) {
f4c3873630fc8c4 Dmitry Safonov 2022-08-18 162 err = -ENOSPC;
f4c3873630fc8c4 Dmitry Safonov 2022-08-18 163 goto out;
f4c3873630fc8c4 Dmitry Safonov 2022-08-18 164 }
f4c3873630fc8c4 Dmitry Safonov 2022-08-18 165
f4c3873630fc8c4 Dmitry Safonov 2022-08-18 166 err = __cpool_alloc_ahash(&cpool[i], alg);
f4c3873630fc8c4 Dmitry Safonov 2022-08-18 167 if (!err && last_allocated <= i)
f4c3873630fc8c4 Dmitry Safonov 2022-08-18 168 last_allocated++;
f4c3873630fc8c4 Dmitry Safonov 2022-08-18 169 out:
f4c3873630fc8c4 Dmitry Safonov 2022-08-18 170 mutex_unlock(&cpool_mutex);
f4c3873630fc8c4 Dmitry Safonov 2022-08-18 171 return err ?: (int)i;
f4c3873630fc8c4 Dmitry Safonov 2022-08-18 172 }
f4c3873630fc8c4 Dmitry Safonov 2022-08-18 173 EXPORT_SYMBOL_GPL(crypto_pool_alloc_ahash);
f4c3873630fc8c4 Dmitry Safonov 2022-08-18 174
--
0-DAY CI Kernel Test Service
https://01.org/lkp
^ permalink raw reply [flat|nested] 2+ messages in thread* [PATCH 00/31] net/tcp: Add TCP-AO support @ 2022-08-18 16:59 Dmitry Safonov 2022-08-18 16:59 ` [PATCH 01/31] crypto: Introduce crypto_pool Dmitry Safonov 0 siblings, 1 reply; 2+ messages in thread From: Dmitry Safonov @ 2022-08-18 16:59 UTC (permalink / raw) To: Eric Dumazet, David S. Miller, linux-kernel Cc: Dmitry Safonov, Andy Lutomirski, Ard Biesheuvel, Bob Gilligan, David Ahern, Dmitry Safonov, Eric Biggers, Francesco Ruggeri, Herbert Xu, Hideaki YOSHIFUJI, Ivan Delalande, Jakub Kicinski, Leonard Crestez, Paolo Abeni, Salam Noureddine, Shuah Khan, netdev, linux-crypto This patchset implements the TCP-AO option as described in RFC5925. There is a request from industry to move away from TCP-MD5SIG and it seems the time is right to have a TCP-AO upstreamed. This TCP option is meant to replace the TCP MD5 option and address its shortcomings. Specifically, it provides more secure hashing, key rotation and support for long-lived connections (see the summary of TCP-AO advantages over TCP-MD5 in (1.3) of RFC5925). The patch series starts with six patches that are not specific to TCP-AO but implement a general crypto facility that we thought is useful to eliminate code duplication between TCP-MD5SIG and TCP-AO as well as other crypto users. These six patches are being submitted separately in a different patchset [1]. Including them here will show better the gain in code sharing. Next are 18 patches that implement the actual TCP-AO option, followed by patches implementing selftests. The patch set was written as a collaboration of three authors (in alphabetical order): Dmitry Safonov, Francesco Ruggeri and Salam Noureddine. Additional credits should be given to Prasad Koya, who was involved in early prototyping a few years back. There is also a separate submission done by Leonard Crestez whom we thank for his efforts getting an implementation of RFC5925 submitted for review upstream [2]. This is an independent implementation that makes different design decisions. For example, we chose a similar design to the TCP-MD5SIG implementation and used setsockopt()s to program per-socket keys, avoiding the extra complexity of managing a centralized key database in the kernel. A centralized database in the kernel has dubious benefits since it doesn’t eliminate per-socket setsockopts needed to specify which sockets need TCP-AO and what are the currently preferred keys. It also complicates traffic key caching and preventing deletion of in-use keys. In this implementation, a centralized database of keys can be thought of as living in user space and user applications would have to program those keys on matching sockets. On the server side, the user application programs keys (MKTS in TCP-AO nomenclature) on the listening socket for all peers that are expected to connect. Prefix matching on the peer address is supported. When a peer issues a successful connect, all the MKTs matching the IP address of the peer are copied to the newly created socket. On the active side, when a connect() is issued all MKTs that do not match the peer are deleted from the socket since they will never match the peer. This implementation uses three setsockopt()s for adding, deleting and modifying keys on a socket. All three setsockopt()s have extensive sanity checks that prevent inconsistencies in the keys on a given socket. A getsockopt() is provided to get key information from any given socket. Few things to note about this implementation: - Traffic keys are cached for established connections avoiding the cost of such calculation for each packet received or sent. - Great care has been taken to avoid deleting in-use MKTs as required by the RFC. - Any crypto algorithm supported by the Linux kernel can be used to calculate packet hashes. - Fastopen works with TCP-AO but hasn’t been tested extensively. - Tested for interop with other major networking vendors (on linux-4.19), including testing for key rotation and long lived connections. There are a couple of limitations that we’re aware of, including (but not limited to) the following: - setsockopt(TCP_REPAIR) not supported yet - IPv4-mapped-IPv6 addresses not tested - static key not implemented yet - CONFIG_TCP_AO depends on CONFIG_TCP_MD5SIG - A small window for a race condition exists between accept and key adding/deletion on a listening socket but can be easily overcome by using the getsockopt() to make sure the right keys are there on a newly accepted connection - Key matching by TCP port numbers, peer ranges, asterisks is unsupported as it’s unlikely to be useful [1]: https://lore.kernel.org/all/20220726201600.1715505-1-dima@arista.com/ [2]: https://lore.kernel.org/all/cover.1658815925.git.cdleonard@gmail.com/ Cc: Andy Lutomirski <luto@amacapital.net> Cc: Ard Biesheuvel <ardb@kernel.org> Cc: Bob Gilligan <gilligan@arista.com> Cc: David Ahern <dsahern@kernel.org> Cc: "David S. Miller" <davem@davemloft.net> Cc: Dmitry Safonov <0x7f454c46@gmail.com> Cc: Eric Biggers <ebiggers@kernel.org> Cc: Eric Dumazet <edumazet@google.com> Cc: Francesco Ruggeri <fruggeri@arista.com> Cc: Herbert Xu <herbert@gondor.apana.org.au> Cc: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org> Cc: Ivan Delalande <colona@arista.com> Cc: Jakub Kicinski <kuba@kernel.org> Cc: Leonard Crestez <cdleonard@gmail.com> Cc: Paolo Abeni <pabeni@redhat.com> Cc: Salam Noureddine <noureddine@arista.com> Cc: Shuah Khan <shuah@kernel.org> Cc: netdev@vger.kernel.org Cc: linux-crypto@vger.kernel.org Cc: linux-kernel@vger.kernel.org Dmitry Safonov (31): crypto: Introduce crypto_pool crypto_pool: Add crypto_pool_reserve_scratch() net/tcp: Separate tcp_md5sig_info allocation into tcp_md5sig_info_add() net/tcp: Disable TCP-MD5 static key on tcp_md5sig_info destruction net/tcp: Use crypto_pool for TCP-MD5 net/ipv6: sr: Switch to using crypto_pool tcp: Add TCP-AO config and structures net/tcp: Introduce TCP_AO setsockopt()s net/tcp: Prevent TCP-MD5 with TCP-AO being set net/tcp: Calculate TCP-AO traffic keys net/tcp: Add TCP-AO sign to outgoing packets net/tcp: Add tcp_parse_auth_options() net/tcp: Add AO sign to RST packets net/tcp: Add TCP-AO sign to twsk net/tcp: Wire TCP-AO to request sockets net/tcp: Sign SYN-ACK segments with TCP-AO net/tcp: Verify inbound TCP-AO signed segments net/tcp: Add TCP-AO segments counters net/tcp: Add TCP-AO SNE support net/tcp: Add tcp_hash_fail() ratelimited logs net/tcp: Ignore specific ICMPs for TCP-AO connections net/tcp: Add option for TCP-AO to (not) hash header net/tcp: Add getsockopt(TCP_AO_GET) net/tcp: Allow asynchronous delete for TCP-AO keys (MKTs) selftests/net: Add TCP-AO library selftests/net: Verify that TCP-AO complies with ignoring ICMPs selftest/net: Add TCP-AO ICMPs accept test selftest/tcp-ao: Add a test for MKT matching selftest/tcp-ao: Add test for TCP-AO add setsockopt() command selftests/tcp-ao: Add TCP-AO + TCP-MD5 + no sign listen socket tests selftests/aolib: Add test/benchmark for removing MKTs crypto/Kconfig | 12 + crypto/Makefile | 1 + crypto/crypto_pool.c | 323 +++ include/crypto/pool.h | 33 + include/linux/sockptr.h | 23 + include/linux/tcp.h | 24 + include/net/dropreason.h | 25 + include/net/seg6_hmac.h | 7 - include/net/tcp.h | 193 +- include/net/tcp_ao.h | 283 +++ include/uapi/linux/snmp.h | 5 + include/uapi/linux/tcp.h | 62 + net/ipv4/Kconfig | 15 +- net/ipv4/Makefile | 1 + net/ipv4/proc.c | 5 + net/ipv4/tcp.c | 191 +- net/ipv4/tcp_ao.c | 1939 +++++++++++++++++ net/ipv4/tcp_input.c | 94 +- net/ipv4/tcp_ipv4.c | 385 +++- net/ipv4/tcp_minisocks.c | 37 +- net/ipv4/tcp_output.c | 188 +- net/ipv6/Kconfig | 2 +- net/ipv6/Makefile | 1 + net/ipv6/seg6.c | 3 - net/ipv6/seg6_hmac.c | 204 +- net/ipv6/tcp_ao.c | 151 ++ net/ipv6/tcp_ipv6.c | 327 ++- tools/testing/selftests/Makefile | 1 + tools/testing/selftests/net/tcp_ao/.gitignore | 2 + tools/testing/selftests/net/tcp_ao/Makefile | 50 + .../selftests/net/tcp_ao/bench-lookups.c | 403 ++++ .../selftests/net/tcp_ao/connect-deny.c | 217 ++ tools/testing/selftests/net/tcp_ao/connect.c | 81 + .../selftests/net/tcp_ao/icmps-accept.c | 1 + .../selftests/net/tcp_ao/icmps-discard.c | 447 ++++ .../testing/selftests/net/tcp_ao/lib/aolib.h | 333 +++ .../selftests/net/tcp_ao/lib/netlink.c | 341 +++ tools/testing/selftests/net/tcp_ao/lib/proc.c | 267 +++ .../testing/selftests/net/tcp_ao/lib/setup.c | 297 +++ tools/testing/selftests/net/tcp_ao/lib/sock.c | 294 +++ .../testing/selftests/net/tcp_ao/lib/utils.c | 30 + .../selftests/net/tcp_ao/setsockopt-closed.c | 191 ++ .../selftests/net/tcp_ao/unsigned-md5.c | 483 ++++ 43 files changed, 7516 insertions(+), 456 deletions(-) create mode 100644 crypto/crypto_pool.c create mode 100644 include/crypto/pool.h create mode 100644 include/net/tcp_ao.h create mode 100644 net/ipv4/tcp_ao.c create mode 100644 net/ipv6/tcp_ao.c create mode 100644 tools/testing/selftests/net/tcp_ao/.gitignore create mode 100644 tools/testing/selftests/net/tcp_ao/Makefile create mode 100644 tools/testing/selftests/net/tcp_ao/bench-lookups.c create mode 100644 tools/testing/selftests/net/tcp_ao/connect-deny.c create mode 100644 tools/testing/selftests/net/tcp_ao/connect.c create mode 120000 tools/testing/selftests/net/tcp_ao/icmps-accept.c create mode 100644 tools/testing/selftests/net/tcp_ao/icmps-discard.c create mode 100644 tools/testing/selftests/net/tcp_ao/lib/aolib.h create mode 100644 tools/testing/selftests/net/tcp_ao/lib/netlink.c create mode 100644 tools/testing/selftests/net/tcp_ao/lib/proc.c create mode 100644 tools/testing/selftests/net/tcp_ao/lib/setup.c create mode 100644 tools/testing/selftests/net/tcp_ao/lib/sock.c create mode 100644 tools/testing/selftests/net/tcp_ao/lib/utils.c create mode 100644 tools/testing/selftests/net/tcp_ao/setsockopt-closed.c create mode 100644 tools/testing/selftests/net/tcp_ao/unsigned-md5.c base-commit: e34cfee65ec891a319ce79797dda18083af33a76 -- 2.37.2 ^ permalink raw reply [flat|nested] 2+ messages in thread
* [PATCH 01/31] crypto: Introduce crypto_pool 2022-08-18 16:59 [PATCH 00/31] net/tcp: Add TCP-AO support Dmitry Safonov @ 2022-08-18 16:59 ` Dmitry Safonov 0 siblings, 0 replies; 2+ messages in thread From: Dmitry Safonov @ 2022-08-18 16:59 UTC (permalink / raw) To: Eric Dumazet, David S. Miller, linux-kernel Cc: Dmitry Safonov, Andy Lutomirski, Ard Biesheuvel, Bob Gilligan, David Ahern, Dmitry Safonov, Eric Biggers, Francesco Ruggeri, Herbert Xu, Hideaki YOSHIFUJI, Ivan Delalande, Jakub Kicinski, Leonard Crestez, Paolo Abeni, Salam Noureddine, Shuah Khan, netdev, linux-crypto Introduce a per-CPU pool of async crypto requests that can be used in bh-disabled contexts (designed with net RX/TX softirqs as users in mind). Allocation can sleep and is a slow-path. Initial implementation has only ahash as a backend and a fix-sized array of possible algorithms used in parallel. Signed-off-by: Dmitry Safonov <dima@arista.com> --- crypto/Kconfig | 6 + crypto/Makefile | 1 + crypto/crypto_pool.c | 291 ++++++++++++++++++++++++++++++++++++++++++ include/crypto/pool.h | 34 +++++ 4 files changed, 332 insertions(+) create mode 100644 crypto/crypto_pool.c create mode 100644 include/crypto/pool.h diff --git a/crypto/Kconfig b/crypto/Kconfig index bb427a835e44..aeddaa3dcc77 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -2128,6 +2128,12 @@ config CRYPTO_STATS config CRYPTO_HASH_INFO bool +config CRYPTO_POOL + tristate "Per-CPU crypto pool" + default n + help + Per-CPU pool of crypto requests ready for usage in atomic contexts. + source "drivers/crypto/Kconfig" source "crypto/asymmetric_keys/Kconfig" source "certs/Kconfig" diff --git a/crypto/Makefile b/crypto/Makefile index a6f94e04e1da..b0f54cb9cea1 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -63,6 +63,7 @@ obj-$(CONFIG_CRYPTO_ACOMP2) += crypto_acompress.o cryptomgr-y := algboss.o testmgr.o obj-$(CONFIG_CRYPTO_MANAGER2) += cryptomgr.o +obj-$(CONFIG_CRYPTO_POOL) += crypto_pool.o obj-$(CONFIG_CRYPTO_USER) += crypto_user.o crypto_user-y := crypto_user_base.o crypto_user-$(CONFIG_CRYPTO_STATS) += crypto_user_stat.o diff --git a/crypto/crypto_pool.c b/crypto/crypto_pool.c new file mode 100644 index 000000000000..a5b6e6cf818a --- /dev/null +++ b/crypto/crypto_pool.c @@ -0,0 +1,291 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include <crypto/pool.h> +#include <linux/kref.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/percpu.h> +#include <linux/workqueue.h> + +static unsigned long scratch_size = DEFAULT_CRYPTO_POOL_SCRATCH_SZ; +static DEFINE_PER_CPU(void *, crypto_pool_scratch); + +struct crypto_pool_entry { + struct ahash_request * __percpu *req; + const char *alg; + struct kref kref; + bool needs_key; +}; + +#define CPOOL_SIZE (PAGE_SIZE/sizeof(struct crypto_pool_entry)) +static struct crypto_pool_entry cpool[CPOOL_SIZE]; +static int last_allocated; +static DEFINE_MUTEX(cpool_mutex); + +static int crypto_pool_scratch_alloc(void) +{ + int cpu; + + lockdep_assert_held(&cpool_mutex); + + for_each_possible_cpu(cpu) { + void *scratch = per_cpu(crypto_pool_scratch, cpu); + + if (scratch) + continue; + + scratch = kmalloc_node(scratch_size, GFP_KERNEL, + cpu_to_node(cpu)); + if (!scratch) + return -ENOMEM; + per_cpu(crypto_pool_scratch, cpu) = scratch; + } + return 0; +} + +static void crypto_pool_scratch_free(void) +{ + int cpu; + + lockdep_assert_held(&cpool_mutex); + + for_each_possible_cpu(cpu) { + void *scratch = per_cpu(crypto_pool_scratch, cpu); + + if (!scratch) + continue; + per_cpu(crypto_pool_scratch, cpu) = NULL; + kfree(scratch); + } +} + +static int __cpool_alloc_ahash(struct crypto_pool_entry *e, const char *alg) +{ + struct crypto_ahash *hash; + int cpu, ret = -ENOMEM; + + e->alg = kstrdup(alg, GFP_KERNEL); + if (!e->alg) + return -ENOMEM; + + e->req = alloc_percpu(struct ahash_request *); + if (!e->req) + goto out_free_alg; + + hash = crypto_alloc_ahash(alg, 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(hash)) { + ret = PTR_ERR(hash); + goto out_free_req; + } + + /* If hash has .setkey(), allocate ahash per-cpu, not only request */ + e->needs_key = crypto_ahash_get_flags(hash) & CRYPTO_TFM_NEED_KEY; + + for_each_possible_cpu(cpu) { + struct ahash_request *req; + + if (!hash) + hash = crypto_alloc_ahash(alg, 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(hash)) + goto out_free; + + req = ahash_request_alloc(hash, GFP_KERNEL); + if (!req) + goto out_free; + + ahash_request_set_callback(req, 0, NULL, NULL); + + *per_cpu_ptr(e->req, cpu) = req; + + if (e->needs_key) + hash = NULL; + } + kref_init(&e->kref); + return 0; + +out_free: + if (!IS_ERR_OR_NULL(hash) && e->needs_key) + crypto_free_ahash(hash); + + for_each_possible_cpu(cpu) { + if (*per_cpu_ptr(e->req, cpu) == NULL) + break; + hash = crypto_ahash_reqtfm(*per_cpu_ptr(e->req, cpu)); + ahash_request_free(*per_cpu_ptr(e->req, cpu)); + if (e->needs_key) { + crypto_free_ahash(hash); + hash = NULL; + } + } + + if (hash) + crypto_free_ahash(hash); +out_free_req: + free_percpu(e->req); +out_free_alg: + kfree(e->alg); + e->alg = NULL; + return ret; +} + +/** + * crypto_pool_alloc_ahash - allocates pool for ahash requests + * @alg: name of async hash algorithm + */ +int crypto_pool_alloc_ahash(const char *alg) +{ + unsigned int i; + int err; + + /* slow-path */ + mutex_lock(&cpool_mutex); + err = crypto_pool_scratch_alloc(); + if (err) + goto out; + + for (i = 0; i < last_allocated; i++) { + if (cpool[i].alg && !strcmp(cpool[i].alg, alg)) { + if (kref_read(&cpool[i].kref) > 0) { + kref_get(&cpool[i].kref); + goto out; + } else { + break; + } + } + } + + for (i = 0; i < last_allocated; i++) { + if (!cpool[i].alg) + break; + } + if (i >= CPOOL_SIZE) { + err = -ENOSPC; + goto out; + } + + err = __cpool_alloc_ahash(&cpool[i], alg); + if (!err && last_allocated <= i) + last_allocated++; +out: + mutex_unlock(&cpool_mutex); + return err ?: (int)i; +} +EXPORT_SYMBOL_GPL(crypto_pool_alloc_ahash); + +static void __cpool_free_entry(struct crypto_pool_entry *e) +{ + struct crypto_ahash *hash = NULL; + int cpu; + + for_each_possible_cpu(cpu) { + if (*per_cpu_ptr(e->req, cpu) == NULL) + continue; + + hash = crypto_ahash_reqtfm(*per_cpu_ptr(e->req, cpu)); + ahash_request_free(*per_cpu_ptr(e->req, cpu)); + if (e->needs_key) { + crypto_free_ahash(hash); + hash = NULL; + } + } + if (hash) + crypto_free_ahash(hash); + free_percpu(e->req); + kfree(e->alg); + memset(e, 0, sizeof(*e)); +} + +static void cpool_cleanup_work_cb(struct work_struct *work) +{ + unsigned int i; + bool free_scratch = true; + + mutex_lock(&cpool_mutex); + for (i = 0; i < last_allocated; i++) { + if (kref_read(&cpool[i].kref) > 0) { + free_scratch = false; + continue; + } + if (!cpool[i].alg) + continue; + __cpool_free_entry(&cpool[i]); + } + if (free_scratch) + crypto_pool_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); +} + +/** + * crypto_pool_release - decreases number of users for a pool. If it was + * the last user of the pool, releases any memory that was consumed. + * @id: crypto_pool that was previously allocated by crypto_pool_alloc_ahash() + */ +void crypto_pool_release(unsigned int id) +{ + if (WARN_ON_ONCE(id > last_allocated || !cpool[id].alg)) + return; + + /* slow-path */ + kref_put(&cpool[id].kref, cpool_schedule_cleanup); +} +EXPORT_SYMBOL_GPL(crypto_pool_release); + +/** + * crypto_pool_add - increases number of users (refcounter) for a pool + * @id: crypto_pool that was previously allocated by crypto_pool_alloc_ahash() + */ +void crypto_pool_add(unsigned int id) +{ + if (WARN_ON_ONCE(id > last_allocated || !cpool[id].alg)) + return; + kref_get(&cpool[id].kref); +} +EXPORT_SYMBOL_GPL(crypto_pool_add); + +/** + * crypto_pool_get - disable bh and start using crypto_pool + * @id: crypto_pool that was previously allocated by crypto_pool_alloc_ahash() + * @c: returned crypto_pool for usage (uninitialized on failure) + */ +int crypto_pool_get(unsigned int id, struct crypto_pool *c) +{ + struct crypto_pool_ahash *ret = (struct crypto_pool_ahash *)c; + + local_bh_disable(); + if (WARN_ON_ONCE(id > last_allocated || !cpool[id].alg)) { + local_bh_enable(); + return -EINVAL; + } + ret->req = *this_cpu_ptr(cpool[id].req); + ret->base.scratch = this_cpu_read(crypto_pool_scratch); + return 0; +} +EXPORT_SYMBOL_GPL(crypto_pool_get); + +/** + * crypto_pool_algo - return algorithm of crypto_pool + * @id: crypto_pool that was previously allocated by crypto_pool_alloc_ahash() + * @buf: buffer to return name of algorithm + * @buf_len: size of @buf + */ +size_t crypto_pool_algo(unsigned int id, char *buf, size_t buf_len) +{ + size_t ret = 0; + + /* slow-path */ + mutex_lock(&cpool_mutex); + if (cpool[id].alg) + ret = strscpy(buf, cpool[id].alg, buf_len); + mutex_unlock(&cpool_mutex); + return ret; +} +EXPORT_SYMBOL_GPL(crypto_pool_algo); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Per-CPU pool of crypto requests"); diff --git a/include/crypto/pool.h b/include/crypto/pool.h new file mode 100644 index 000000000000..2c61aa45faff --- /dev/null +++ b/include/crypto/pool.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +#ifndef _CRYPTO_POOL_H +#define _CRYPTO_POOL_H + +#include <crypto/hash.h> + +#define DEFAULT_CRYPTO_POOL_SCRATCH_SZ 128 + +struct crypto_pool { + void *scratch; +}; + +/* + * struct crypto_pool_ahash - per-CPU pool of ahash_requests + * @base: common members that can be used by any async crypto ops + * @req: pre-allocated ahash request + */ +struct crypto_pool_ahash { + struct crypto_pool base; + struct ahash_request *req; +}; + +int crypto_pool_alloc_ahash(const char *alg); +void crypto_pool_add(unsigned int id); +void crypto_pool_release(unsigned int id); + +int crypto_pool_get(unsigned int id, struct crypto_pool *c); +static inline void crypto_pool_put(void) +{ + local_bh_enable(); +} +size_t crypto_pool_algo(unsigned int id, char *buf, size_t buf_len); + +#endif /* _CRYPTO_POOL_H */ -- 2.37.2 ^ permalink raw reply related [flat|nested] 2+ messages in thread
end of thread, other threads:[~2022-08-22 5:35 UTC | newest] Thread overview: 2+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2022-08-22 5:35 [PATCH 01/31] crypto: Introduce crypto_pool kernel test robot -- strict thread matches above, loose matches on Subject: below -- 2022-08-18 16:59 [PATCH 00/31] net/tcp: Add TCP-AO support Dmitry Safonov 2022-08-18 16:59 ` [PATCH 01/31] crypto: Introduce crypto_pool Dmitry Safonov
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.