From patchwork Thu Jul 2 11:52:20 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ralf Lici X-Patchwork-Id: 5070 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7000:1887:b0:869:83bc:8c48 with SMTP id r7csp550846max; Thu, 2 Jul 2026 04:53:34 -0700 (PDT) X-Forwarded-Encrypted: i=2; AFNElJ/Aqwpz7YECYUZQgBYz3yrAxu2HK48MYSn4j/QFyEY023yLTZtWbeY0gbCyn0ODrB3vPnkTPkpWweE=@openvpn.net X-Received: by 2002:a05:6830:6a87:b0:7e9:3765:79c2 with SMTP id 46e09a7af769-7eb503b8dd2mr3490699a34.12.1782993214623; Thu, 02 Jul 2026 04:53:34 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1782993214; cv=none; d=google.com; s=arc-20260327; b=X82U2B8/zM93tfpxYz1AQaFZg7ximF0yuWwcIB754EDN3Ug96vEaDmHTi2DGQzHiCh 5/4q1C+0en7Y0Ppob8oTibtHs9liFHjziKc8Mbe0rTOMnF+h8aeghV0f0ob+RNRlqVz+ R5VF7KHTekpMy1P5U0aM9hmGIj5EBTHUvLAJbPTOMDaII5UgERvsy4o3kD2+bhBTmNiL kgMA2bgKymatmFMBtEM1FQFOG0gBfzdUT6B7Ec571Tlv5SKeTQFo0dEzx/5467jrvbrN ZbkJMNPJmpsq4n/bEp16/G9dHnO5yZBsY+tMazeBx35y7W1QGeAJ0LrsFvQ4gUp+uwfV rAXQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20260327; h=errors-to:content-transfer-encoding:list-subscribe:list-help :list-post:list-archive:list-unsubscribe:list-id:precedence:subject :mime-version:references:in-reply-to:message-id:date:to:from :dkim-signature:dkim-signature:dkim-signature:dkim-signature; bh=Ek2GcsRXmHkxzQRZpwxaY2tdyszfq6BkCzviEGigdDs=; fh=4NbAC/LsuMLI0S0hprUlLSLCiHwg6SCAifhH718Jh0Q=; b=U3tRx4Jjo7hp6IuJu9FdZi6gqPyym7MrpAhDyXe7CNIbJ/VPxzmL//9SLb9z+/JiFb SGOntGu4BRZIQ+zvHBQslNtTOvYqh37/s/hDqlnSajBoTpbfTt1AknxxOJ9smp4s8eqC zNgiXSlBr8e4r0jn0NQEwlUahq+jsaXGDrL+ZNVYx/ofZ8Zdlbdwhnswt+ErdeRcjOtL w3kZW+AG3x6wqA/FyhVG5M58tt3pN2WnGYirCJ5LXaIVh4shHLU2kmP5L6uWNWoLZfZy 9aJl8MfO2le03Q5ZuUZp9+el3cWEU5S86xS7umnLGw/waBwE3BuDigs37/ixhfdiqMGD 1HVQ==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@lists.sourceforge.net header.s=beta header.b=m0h2f6gu; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=EoGCUJ7b; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=OUuD5W4Y; dkim=neutral (body hash did not verify) header.i=@mandelbit.com header.s=MBO0001 header.b=s310XksO; spf=pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) smtp.mailfrom=openvpn-devel-bounces@lists.sourceforge.net Received: from lists.sourceforge.net (lists.sourceforge.net. [216.105.38.7]) by mx.google.com with ESMTPS id 46e09a7af769-7eb54549699si2271054a34.100.2026.07.02.04.53.34 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jul 2026 04:53:34 -0700 (PDT) Received-SPF: pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) client-ip=216.105.38.7; Authentication-Results: mx.google.com; dkim=pass header.i=@lists.sourceforge.net header.s=beta header.b=m0h2f6gu; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=EoGCUJ7b; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=OUuD5W4Y; dkim=neutral (body hash did not verify) header.i=@mandelbit.com header.s=MBO0001 header.b=s310XksO; spf=pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) smtp.mailfrom=openvpn-devel-bounces@lists.sourceforge.net DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.sourceforge.net; s=beta; h=Content-Transfer-Encoding:Content-Type: List-Subscribe:List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id: Subject:MIME-Version:References:In-Reply-To:Message-ID:Date:To:From:Sender: Reply-To:Cc:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=Ek2GcsRXmHkxzQRZpwxaY2tdyszfq6BkCzviEGigdDs=; b=m0h2f6gupwFmMwJnJPnYzmnuvz d70p5OzYLokqtx5RRFMwLy7gLRm+Z0ks2KiGGWmFRfDiOmsxUrQ9IBEXAy2ukgSi7cKb3yavGQdsl IxCxKzEORgFC//VsNEAGJnwN8CWhOK9lflHjNWDopsxs0N+Jl88B6QHoty2LEEpgUvQI=; Received: from [127.0.0.1] (helo=sfs-ml-3.v29.lw.sourceforge.com) by sfs-ml-3.v29.lw.sourceforge.com with esmtp (Exim 4.95) (envelope-from ) id 1wfFz0-0001hX-VB; Thu, 02 Jul 2026 11:53:31 +0000 Received: from [172.30.29.66] (helo=mx.sourceforge.net) by sfs-ml-3.v29.lw.sourceforge.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.95) (envelope-from ) id 1wfFyx-0001h9-U5 for openvpn-devel@lists.sourceforge.net; Thu, 02 Jul 2026 11:53:28 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=Content-Transfer-Encoding:MIME-Version:References: In-Reply-To:Message-ID:Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=OK7NpS4CfLQYxY/MnzoqmDnwV3lrxJ1QqVFCDCWJ/nc=; b=EoGCUJ7bBjmwHs9qZ1+6fr+TXo V0GubqFWcribie372KBkjY8TB+ybTPkkRByOl8GcwMxvUc9SUngIQGMqpa1/eGVDen932P2A2716R u0OFGqFNBYbue7Xbzo9d2zxTJOJ4EU0SiLSGiEwDvF5LdBDvACPyQBKjvxUaInj8AgqA=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID: Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=OK7NpS4CfLQYxY/MnzoqmDnwV3lrxJ1QqVFCDCWJ/nc=; b=OUuD5W4YMhnhiWyWxd5UgXTOn7 +PInsh9YuSCqkoFecUHU+bDl+qecQ11Ewkv3cuq4jPsZSeJhUe75UFC8j8UFySG/skGHtYpIW2zWb n343nXJjY2Uvo4ssbABjCh0PiOSaTbz4XiTR8LovwznCHKUaF/gmoybXOdP/zvolFDbU=; Received: from mout-b-107.mailbox.org ([195.10.208.47]) by sfi-mx-2.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.95) id 1wfFyw-0004K6-Un for openvpn-devel@lists.sourceforge.net; Thu, 02 Jul 2026 11:53:28 +0000 Received: from smtp2.mailbox.org (smtp2.mailbox.org [10.196.197.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-b-107.mailbox.org (Postfix) with ESMTPS id 4grZyd6CxMzDs5H; Thu, 2 Jul 2026 13:53:13 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mandelbit.com; s=MBO0001; t=1782993193; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=OK7NpS4CfLQYxY/MnzoqmDnwV3lrxJ1QqVFCDCWJ/nc=; b=s310XksOQLPXwn1TOG5qn8xoYH1spohxVCHW5nA8SWlDNngr/RcFAn+cO0mkkhovIecGfV LfJaXf5c6LsZ5lBNYxtXwES/F9msBOXiikncLG+MA3nYrUKTMjc4MbTalp5ebUoXXDKLpW hZHd06wIkDTYeBeGOUobgziyyCD1E6VTilaJciyy6HshpMXj4n9j/OMnOucBce2h10v913 5BYgMc+FJkmvgJLjPgXuKIuUibkKwCfaNr+QnDsiNKy51X2MvT17hUg/JIGsvUomjASG1f AdMR+Ewifq+C6hSuzhX+HX8WkihFkSVV4nE9n4a8lbUyK/3BdU4hDXqEjY/5FQ== From: Ralf Lici To: openvpn-devel@lists.sourceforge.net Date: Thu, 2 Jul 2026 13:52:20 +0200 Message-ID: In-Reply-To: References: MIME-Version: 1.0 X-Spam-Score: -0.2 (/) X-Spam-Report: Spam detection software, running on the system "sfi-spamd-2.hosts.colo.sdot.me", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: crypto_aead.c now contains both AEAD packet operations and key slot setup, destruction and cipher introspection. Those lifecycle helpers are used by the generic crypto state code and do not need to li [...] Content analysis details: (-0.2 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain X-Headers-End: 1wfFyw-0004K6-Un Subject: [Openvpn-devel] [RFC ovpn net-next v2 05/14] ovpn: move key slot lifecycle out of AEAD X-BeenThere: openvpn-devel@lists.sourceforge.net X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox X-GMAIL-THRID: 1869603893200521771 X-GMAIL-MSGID: 1869603893200521771 crypto_aead.c now contains both AEAD packet operations and key slot setup, destruction and cipher introspection. Those lifecycle helpers are used by the generic crypto state code and do not need to live with the per-packet encrypt and decrypt path. Move key slot lifecycle code into crypto_key.c and expose it through ovpn_crypto_key_slot helpers. This leaves crypto_aead.c focused on AEAD packet processing without changing key allocation, validation or teardown behavior. Signed-off-by: Ralf Lici --- No changes since v1 https://lore.kernel.org/openvpn-devel/1a0ef417303069c983fc8eb9effcede54c231e26.1782919654.git.ralf@mandelbit.com/ drivers/net/ovpn/Makefile | 1 + drivers/net/ovpn/crypto.c | 7 +- drivers/net/ovpn/crypto.h | 7 ++ drivers/net/ovpn/crypto_aead.c | 158 ------------------------------ drivers/net/ovpn/crypto_aead.h | 5 - drivers/net/ovpn/crypto_key.c | 172 +++++++++++++++++++++++++++++++++ 6 files changed, 183 insertions(+), 167 deletions(-) create mode 100644 drivers/net/ovpn/crypto_key.c diff --git a/drivers/net/ovpn/Makefile b/drivers/net/ovpn/Makefile index 229be66167e1..704af1deb7c1 100644 --- a/drivers/net/ovpn/Makefile +++ b/drivers/net/ovpn/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_OVPN) := ovpn.o ovpn-y += bind.o ovpn-y += crypto.o ovpn-y += crypto_aead.o +ovpn-y += crypto_key.o ovpn-y += main.o ovpn-y += io.o ovpn-y += netlink.o diff --git a/drivers/net/ovpn/crypto.c b/drivers/net/ovpn/crypto.c index 90580e32052f..239d95492574 100644 --- a/drivers/net/ovpn/crypto.c +++ b/drivers/net/ovpn/crypto.c @@ -15,7 +15,6 @@ #include "ovpnpriv.h" #include "main.h" #include "pktid.h" -#include "crypto_aead.h" #include "crypto.h" static void ovpn_ks_destroy_rcu(struct rcu_head *head) @@ -23,7 +22,7 @@ static void ovpn_ks_destroy_rcu(struct rcu_head *head) struct ovpn_crypto_key_slot *ks; ks = container_of(head, struct ovpn_crypto_key_slot, rcu); - ovpn_aead_crypto_key_slot_destroy(ks); + ovpn_crypto_key_slot_destroy(ks); } void ovpn_crypto_key_slot_release(struct kref *kref) @@ -89,7 +88,7 @@ int ovpn_crypto_state_reset(struct ovpn_crypto_state *cs, pkr->slot != OVPN_KEY_SLOT_SECONDARY) return -EINVAL; - new = ovpn_aead_crypto_key_slot_new(&pkr->key); + new = ovpn_crypto_key_slot_new(&pkr->key); if (IS_ERR(new)) return PTR_ERR(new); @@ -202,7 +201,7 @@ int ovpn_crypto_config_get(struct ovpn_crypto_state *cs, return -ENOENT; } - keyconf->cipher_alg = ovpn_aead_crypto_alg(ks); + keyconf->cipher_alg = ovpn_crypto_key_slot_alg(ks); keyconf->key_id = ks->key_id; rcu_read_unlock(); diff --git a/drivers/net/ovpn/crypto.h b/drivers/net/ovpn/crypto.h index 2be7ff54fc40..3b21b42a25eb 100644 --- a/drivers/net/ovpn/crypto.h +++ b/drivers/net/ovpn/crypto.h @@ -136,6 +136,13 @@ static inline void ovpn_crypto_key_slot_put(struct ovpn_crypto_key_slot *ks) int ovpn_crypto_state_reset(struct ovpn_crypto_state *cs, const struct ovpn_peer_key_reset *pkr); +struct ovpn_crypto_key_slot * +ovpn_crypto_key_slot_new(const struct ovpn_key_config *kc); + +void ovpn_crypto_key_slot_destroy(struct ovpn_crypto_key_slot *ks); + +enum ovpn_cipher_alg ovpn_crypto_key_slot_alg(struct ovpn_crypto_key_slot *ks); + void ovpn_crypto_key_slot_delete(struct ovpn_crypto_state *cs, enum ovpn_key_slot slot); diff --git a/drivers/net/ovpn/crypto_aead.c b/drivers/net/ovpn/crypto_aead.c index d2e3532934fb..5306c0d2b5c8 100644 --- a/drivers/net/ovpn/crypto_aead.c +++ b/drivers/net/ovpn/crypto_aead.c @@ -24,8 +24,6 @@ #include "proto.h" #include "skb.h" -#define ALG_NAME_AES "gcm(aes)" -#define ALG_NAME_CHACHAPOLY "rfc7539(chacha20,poly1305)" #define OVPN_AEAD_DECRYPT_FAILURE_NOTIFY BIT_ULL(35) #define OVPN_AEAD_DECRYPT_FAILURE_LIMIT BIT_ULL(36) #define OVPN_AEAD_DECRYPT_FAILURE_NOTIFY_BIT 0 @@ -351,159 +349,3 @@ int ovpn_aead_decrypt(struct ovpn_peer *peer, struct ovpn_crypto_key_slot *ks, /* decrypt it */ return crypto_aead_decrypt(req); } - -/* Initialize a struct crypto_aead object */ -static struct crypto_aead *ovpn_aead_init(const char *title, - const char *alg_name, - const unsigned char *key, - unsigned int keylen) -{ - struct crypto_aead *aead; - int ret; - - aead = crypto_alloc_aead(alg_name, 0, 0); - if (IS_ERR(aead)) { - ret = PTR_ERR(aead); - pr_err("%s crypto_alloc_aead failed, err=%d\n", title, ret); - aead = NULL; - goto error; - } - - ret = crypto_aead_setkey(aead, key, keylen); - if (ret) { - pr_err("%s crypto_aead_setkey size=%u failed, err=%d\n", title, - keylen, ret); - goto error; - } - - ret = crypto_aead_setauthsize(aead, OVPN_AEAD_TAG_SIZE); - if (ret) { - pr_err("%s crypto_aead_setauthsize failed, err=%d\n", title, - ret); - goto error; - } - - /* basic AEAD assumption - * all current algorithms use OVPN_NONCE_SIZE. - * ovpn_aead_crypto_tmp_size and ovpn_aead_encrypt/decrypt - * expect this. - */ - if (crypto_aead_ivsize(aead) != OVPN_NONCE_SIZE) { - pr_err("%s IV size must be %d\n", title, OVPN_NONCE_SIZE); - ret = -EINVAL; - goto error; - } - - pr_debug("********* Cipher %s (%s)\n", alg_name, title); - pr_debug("*** IV size=%u\n", crypto_aead_ivsize(aead)); - pr_debug("*** req size=%u\n", crypto_aead_reqsize(aead)); - pr_debug("*** block size=%u\n", crypto_aead_blocksize(aead)); - pr_debug("*** auth size=%u\n", crypto_aead_authsize(aead)); - pr_debug("*** alignmask=0x%x\n", crypto_aead_alignmask(aead)); - - return aead; - -error: - crypto_free_aead(aead); - return ERR_PTR(ret); -} - -void ovpn_aead_crypto_key_slot_destroy(struct ovpn_crypto_key_slot *ks) -{ - if (!ks) - return; - - crypto_free_aead(ks->encrypt); - crypto_free_aead(ks->decrypt); - kfree(ks); -} - -struct ovpn_crypto_key_slot * -ovpn_aead_crypto_key_slot_new(const struct ovpn_key_config *kc) -{ - struct ovpn_crypto_key_slot *ks = NULL; - const char *alg_name; - int ret; - - /* validate crypto alg */ - switch (kc->cipher_alg) { - case OVPN_CIPHER_ALG_AES_GCM: - alg_name = ALG_NAME_AES; - break; - case OVPN_CIPHER_ALG_CHACHA20_POLY1305: - alg_name = ALG_NAME_CHACHAPOLY; - break; - default: - return ERR_PTR(-EOPNOTSUPP); - } - - if (kc->encrypt.nonce_tail_size != OVPN_NONCE_TAIL_SIZE || - kc->decrypt.nonce_tail_size != OVPN_NONCE_TAIL_SIZE) - return ERR_PTR(-EINVAL); - - /* build the key slot */ - ks = kmalloc_obj(*ks); - if (!ks) - return ERR_PTR(-ENOMEM); - - ks->encrypt = NULL; - ks->decrypt = NULL; - kref_init(&ks->refcount); - ks->key_id = kc->key_id; - ks->cipher_alg = kc->cipher_alg; - ovpn_key_usage_limit_init(&ks->usage_limit, kc->cipher_alg); - ovpn_key_usage_init(&ks->usage_xmit); - ovpn_key_usage_init(&ks->usage_recv); - atomic64_set(&ks->decrypt_failures, 0); - ks->decrypt_failure_flags = 0; - - ks->encrypt = ovpn_aead_init("encrypt", alg_name, - kc->encrypt.cipher_key, - kc->encrypt.cipher_key_size); - if (IS_ERR(ks->encrypt)) { - ret = PTR_ERR(ks->encrypt); - ks->encrypt = NULL; - goto destroy_ks; - } - - ks->decrypt = ovpn_aead_init("decrypt", alg_name, - kc->decrypt.cipher_key, - kc->decrypt.cipher_key_size); - if (IS_ERR(ks->decrypt)) { - ret = PTR_ERR(ks->decrypt); - ks->decrypt = NULL; - goto destroy_ks; - } - - memcpy(ks->nonce_tail_xmit, kc->encrypt.nonce_tail, - OVPN_NONCE_TAIL_SIZE); - memcpy(ks->nonce_tail_recv, kc->decrypt.nonce_tail, - OVPN_NONCE_TAIL_SIZE); - - /* init packet ID generation/validation */ - ovpn_pktid_xmit_init(&ks->pid_xmit); - ovpn_pktid_recv_init(&ks->pid_recv); - - return ks; - -destroy_ks: - ovpn_aead_crypto_key_slot_destroy(ks); - return ERR_PTR(ret); -} - -enum ovpn_cipher_alg ovpn_aead_crypto_alg(struct ovpn_crypto_key_slot *ks) -{ - const char *alg_name; - - if (!ks->encrypt) - return OVPN_CIPHER_ALG_NONE; - - alg_name = crypto_tfm_alg_name(crypto_aead_tfm(ks->encrypt)); - - if (!strcmp(alg_name, ALG_NAME_AES)) - return OVPN_CIPHER_ALG_AES_GCM; - else if (!strcmp(alg_name, ALG_NAME_CHACHAPOLY)) - return OVPN_CIPHER_ALG_CHACHA20_POLY1305; - else - return OVPN_CIPHER_ALG_NONE; -} diff --git a/drivers/net/ovpn/crypto_aead.h b/drivers/net/ovpn/crypto_aead.h index e5ff0b9b5ee3..57a7b88cd6c5 100644 --- a/drivers/net/ovpn/crypto_aead.h +++ b/drivers/net/ovpn/crypto_aead.h @@ -20,11 +20,6 @@ int ovpn_aead_encrypt(struct ovpn_peer *peer, struct ovpn_crypto_key_slot *ks, int ovpn_aead_decrypt(struct ovpn_peer *peer, struct ovpn_crypto_key_slot *ks, struct sk_buff *skb); -struct ovpn_crypto_key_slot * -ovpn_aead_crypto_key_slot_new(const struct ovpn_key_config *kc); -void ovpn_aead_crypto_key_slot_destroy(struct ovpn_crypto_key_slot *ks); - -enum ovpn_cipher_alg ovpn_aead_crypto_alg(struct ovpn_crypto_key_slot *ks); bool ovpn_aead_decrypt_failure_record(struct ovpn_crypto_key_slot *ks); #endif /* _NET_OVPN_OVPNAEAD_H_ */ diff --git a/drivers/net/ovpn/crypto_key.c b/drivers/net/ovpn/crypto_key.c new file mode 100644 index 000000000000..08fce700811f --- /dev/null +++ b/drivers/net/ovpn/crypto_key.c @@ -0,0 +1,172 @@ +// SPDX-License-Identifier: GPL-2.0 +/* OpenVPN data channel offload + * + * Copyright (C) 2026 OpenVPN, Inc. + * + * Author: Ralf Lici + * Antonio Quartulli + */ + +#include + +#include "ovpnpriv.h" +#include "crypto.h" +#include "pktid.h" +#include "proto.h" + +#define ALG_NAME_AES "gcm(aes)" +#define ALG_NAME_CHACHAPOLY "rfc7539(chacha20,poly1305)" + +/* initialize a struct crypto_aead object */ +static struct crypto_aead *ovpn_aead_init(const char *title, + const char *alg_name, + const unsigned char *key, + unsigned int keylen) +{ + struct crypto_aead *aead; + int ret; + + aead = crypto_alloc_aead(alg_name, 0, 0); + if (IS_ERR(aead)) { + ret = PTR_ERR(aead); + pr_err("%s crypto_alloc_aead failed, err=%d\n", title, ret); + aead = NULL; + goto error; + } + + ret = crypto_aead_setkey(aead, key, keylen); + if (ret) { + pr_err("%s crypto_aead_setkey size=%u failed, err=%d\n", title, + keylen, ret); + goto error; + } + + ret = crypto_aead_setauthsize(aead, OVPN_AEAD_TAG_SIZE); + if (ret) { + pr_err("%s crypto_aead_setauthsize failed, err=%d\n", title, + ret); + goto error; + } + + /* Basic AEAD assumption: all current algorithms use OVPN_NONCE_SIZE. + * ovpn_aead_crypto_tmp_size and ovpn_aead_encrypt/decrypt expect this. + */ + if (crypto_aead_ivsize(aead) != OVPN_NONCE_SIZE) { + pr_err("%s IV size must be %d\n", title, OVPN_NONCE_SIZE); + ret = -EINVAL; + goto error; + } + + pr_debug("********* Cipher %s (%s)\n", alg_name, title); + pr_debug("*** IV size=%u\n", crypto_aead_ivsize(aead)); + pr_debug("*** req size=%u\n", crypto_aead_reqsize(aead)); + pr_debug("*** block size=%u\n", crypto_aead_blocksize(aead)); + pr_debug("*** auth size=%u\n", crypto_aead_authsize(aead)); + pr_debug("*** alignmask=0x%x\n", crypto_aead_alignmask(aead)); + + return aead; + +error: + crypto_free_aead(aead); + return ERR_PTR(ret); +} + +void ovpn_crypto_key_slot_destroy(struct ovpn_crypto_key_slot *ks) +{ + if (!ks) + return; + + crypto_free_aead(ks->encrypt); + crypto_free_aead(ks->decrypt); + kfree(ks); +} + +struct ovpn_crypto_key_slot * +ovpn_crypto_key_slot_new(const struct ovpn_key_config *kc) +{ + struct ovpn_crypto_key_slot *ks = NULL; + const char *alg_name; + int ret; + + /* validate crypto alg */ + switch (kc->cipher_alg) { + case OVPN_CIPHER_ALG_AES_GCM: + alg_name = ALG_NAME_AES; + break; + case OVPN_CIPHER_ALG_CHACHA20_POLY1305: + alg_name = ALG_NAME_CHACHAPOLY; + break; + default: + return ERR_PTR(-EOPNOTSUPP); + } + + if (kc->encrypt.nonce_tail_size != OVPN_NONCE_TAIL_SIZE || + kc->decrypt.nonce_tail_size != OVPN_NONCE_TAIL_SIZE) + return ERR_PTR(-EINVAL); + + /* build the key slot */ + ks = kmalloc_obj(*ks); + if (!ks) + return ERR_PTR(-ENOMEM); + + ks->encrypt = NULL; + ks->decrypt = NULL; + kref_init(&ks->refcount); + ks->key_id = kc->key_id; + ks->cipher_alg = kc->cipher_alg; + ovpn_key_usage_limit_init(&ks->usage_limit, kc->cipher_alg); + ovpn_key_usage_init(&ks->usage_xmit); + ovpn_key_usage_init(&ks->usage_recv); + atomic64_set(&ks->decrypt_failures, 0); + ks->decrypt_failure_flags = 0; + + ks->encrypt = ovpn_aead_init("encrypt", alg_name, + kc->encrypt.cipher_key, + kc->encrypt.cipher_key_size); + if (IS_ERR(ks->encrypt)) { + ret = PTR_ERR(ks->encrypt); + ks->encrypt = NULL; + goto destroy_ks; + } + + ks->decrypt = ovpn_aead_init("decrypt", alg_name, + kc->decrypt.cipher_key, + kc->decrypt.cipher_key_size); + if (IS_ERR(ks->decrypt)) { + ret = PTR_ERR(ks->decrypt); + ks->decrypt = NULL; + goto destroy_ks; + } + + memcpy(ks->nonce_tail_xmit, kc->encrypt.nonce_tail, + OVPN_NONCE_TAIL_SIZE); + memcpy(ks->nonce_tail_recv, kc->decrypt.nonce_tail, + OVPN_NONCE_TAIL_SIZE); + + /* init packet ID generation/validation */ + ovpn_pktid_xmit_init(&ks->pid_xmit); + ovpn_pktid_recv_init(&ks->pid_recv); + + return ks; + +destroy_ks: + ovpn_crypto_key_slot_destroy(ks); + return ERR_PTR(ret); +} + +enum ovpn_cipher_alg ovpn_crypto_key_slot_alg(struct ovpn_crypto_key_slot *ks) +{ + const char *alg_name; + + if (!ks->encrypt) + return OVPN_CIPHER_ALG_NONE; + + alg_name = crypto_tfm_alg_name(crypto_aead_tfm(ks->encrypt)); + + if (!strcmp(alg_name, ALG_NAME_AES)) + return OVPN_CIPHER_ALG_AES_GCM; + else if (!strcmp(alg_name, ALG_NAME_CHACHAPOLY)) + return OVPN_CIPHER_ALG_CHACHA20_POLY1305; + else + return OVPN_CIPHER_ALG_NONE; +}