Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/2215694/?format=api
{ "id": 2215694, "url": "http://patchwork.ozlabs.org/api/patches/2215694/?format=api", "web_url": "http://patchwork.ozlabs.org/project/linux-cifs-client/patch/e893bba9e4bb56c7aeefec5f9b2a255afc9c7fb7.1774410440.git.lucien.xin@gmail.com/", "project": { "id": 12, "url": "http://patchwork.ozlabs.org/api/projects/12/?format=api", "name": "Linux CIFS Client", "link_name": "linux-cifs-client", "list_id": "linux-cifs.vger.kernel.org", "list_email": "linux-cifs@vger.kernel.org", "web_url": "", "scm_url": "", "webscm_url": "", "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<e893bba9e4bb56c7aeefec5f9b2a255afc9c7fb7.1774410440.git.lucien.xin@gmail.com>", "list_archive_url": null, "date": "2026-03-25T03:47:16", "name": "[net-next,v11,11/15] quic: add crypto key derivation and installation", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "c479a19a4b5bf19574ff832af55f0f90269fc1af", "submitter": { "id": 61073, "url": "http://patchwork.ozlabs.org/api/people/61073/?format=api", "name": "Xin Long", "email": "lucien.xin@gmail.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/linux-cifs-client/patch/e893bba9e4bb56c7aeefec5f9b2a255afc9c7fb7.1774410440.git.lucien.xin@gmail.com/mbox/", "series": [ { "id": 497380, "url": "http://patchwork.ozlabs.org/api/series/497380/?format=api", "web_url": "http://patchwork.ozlabs.org/project/linux-cifs-client/list/?series=497380", "date": "2026-03-25T03:47:06", "name": "net: introduce QUIC infrastructure and core subcomponents", "version": 11, "mbox": "http://patchwork.ozlabs.org/series/497380/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2215694/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2215694/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "\n <linux-cifs+bounces-10513-incoming=patchwork.ozlabs.org@vger.kernel.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "linux-cifs@vger.kernel.org" ], "Delivered-To": "patchwork-incoming@legolas.ozlabs.org", "Authentication-Results": [ "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256\n header.s=20251104 header.b=kPdUG2JL;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=2600:3c04:e001:36c::12fc:5321; helo=tor.lore.kernel.org;\n envelope-from=linux-cifs+bounces-10513-incoming=patchwork.ozlabs.org@vger.kernel.org;\n receiver=patchwork.ozlabs.org)", "smtp.subspace.kernel.org;\n\tdkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com\n header.b=\"kPdUG2JL\"", "smtp.subspace.kernel.org;\n arc=none smtp.client-ip=209.85.219.43", "smtp.subspace.kernel.org;\n dmarc=pass (p=none dis=none) header.from=gmail.com", "smtp.subspace.kernel.org;\n spf=pass smtp.mailfrom=gmail.com" ], "Received": [ "from tor.lore.kernel.org (tor.lore.kernel.org\n [IPv6:2600:3c04:e001:36c::12fc:5321])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fgY0w43JYz1y1G\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 25 Mar 2026 14:53:36 +1100 (AEDT)", "from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby tor.lore.kernel.org (Postfix) with ESMTP id 777A330DF16A\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 25 Mar 2026 03:49:58 +0000 (UTC)", "from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id 763D328B4FA;\n\tWed, 25 Mar 2026 03:49:54 +0000 (UTC)", "from mail-qv1-f43.google.com (mail-qv1-f43.google.com\n [209.85.219.43])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits))\n\t(No client certificate requested)\n\tby smtp.subspace.kernel.org (Postfix) with ESMTPS id 25E832EA48F\n\tfor <linux-cifs@vger.kernel.org>; Wed, 25 Mar 2026 03:49:51 +0000 (UTC)", "by mail-qv1-f43.google.com with SMTP id\n 6a1803df08f44-89a6ac6f389so22461656d6.3\n for <linux-cifs@vger.kernel.org>;\n Tue, 24 Mar 2026 20:49:51 -0700 (PDT)", "from wsfd-netdev58.anl.eng.rdu2.dc.redhat.com ([66.187.232.140])\n by smtp.gmail.com with ESMTPSA id\n d75a77b69052e-50b36cb2e29sm150093001cf.1.2026.03.24.20.49.48\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Tue, 24 Mar 2026 20:49:50 -0700 (PDT)" ], "ARC-Seal": "i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1774410594; cv=none;\n b=lk+/q5VFCC3GlGIdPIk5bU/IW4lXDfIqx5vwEGXHJWIGG5+1Np5N4a32OmpNUCXOoRWZOf8gbnOxpS4B41dp7NaFAhzXKLC+JfDIPucYF5qV2XErJA63FNRJ0W4x49lLrg6KVJFgR1ah0P4geDRY4GmbgXlpY57ejCZlKkreDQc=", "ARC-Message-Signature": "i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1774410594; c=relaxed/simple;\n\tbh=Y3uz7M3DbloxmtPSHdV0KreoNCcUh7wTesOmnv+jSis=;\n\th=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References:\n\t MIME-Version;\n b=EBIbkNtEI97TGCwqKf9alyX5BJDSmS7Amc5yE26RNgZ0UDRZraO/fDhy/q/l0m3TN6ERo7Y4qnmwC9gDa68jCEiq74bluq21yiKCuJUBGADbZklmEjzeRWYXScIY+W7Sifgfjj6p/+p2mU4Ws2WjNvBZCdJhiKi79O2j+4XpSiE=", "ARC-Authentication-Results": "i=1; smtp.subspace.kernel.org;\n dmarc=pass (p=none dis=none) header.from=gmail.com;\n spf=pass smtp.mailfrom=gmail.com;\n dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com\n header.b=kPdUG2JL; arc=none smtp.client-ip=209.85.219.43", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=gmail.com; s=20251104; t=1774410591; x=1775015391;\n darn=vger.kernel.org;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:from:to:cc:subject:date\n :message-id:reply-to;\n bh=dvTZSekEY4mj2qYQvkOI+FQr4ctSeXK/je2dq/WR3eI=;\n b=kPdUG2JLXSyLkyakHetGQqzeS2dM4njXSaeUccqWnpWjMGihZI7eHEyhBDn7+twJLb\n y+GFVL49Rw1wtaCVmMLS2Qt1liH4FU+sZKDqjuSYi/46AYJYBK2CV7ZAlwdt351TqqVt\n JUx8ftiMvgE49a2HdO5nNAbdaLTDXOrloA1oTTZuMSyyOxB605X8TR/LcCYy9xSOUjY9\n W+xwcbjXQPGcT1yhvYG1aesRUgm8xRMdu+mlF3+3qfvtC8RG5kQTGrJYJFH0p+99EUjT\n iv7Yfw8V1NXWbX/5M+xsc3GaG8ETfZr7EXWxLblhN87uOjF71PpdCf6gy4DZV8B/Ptsu\n yhww==", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1774410591; x=1775015391;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from\n :to:cc:subject:date:message-id:reply-to;\n bh=dvTZSekEY4mj2qYQvkOI+FQr4ctSeXK/je2dq/WR3eI=;\n b=kdeBzOpPMaqxTolcrgq9XlykVVtbyOj9YTTC6se8og7Y5M3Cfe+5gakMw2atLNtQZW\n 8eRtGFP0eBnvdR3OcPAUx5mO/vXnEx369SqV5OWlwNowfKPmYSQ8hznyUnoMzwd1UUOs\n 26gJhNx4kW1Wurdid5iSxU7ftduozlStGeRc/HYMK4a1MJadGYUpxIxPHXZDuIhLx/j6\n rKw6uVhnekirOdxRDv9mViOWqNis2uGOTRbGizNMUEIGtVexaJGVemxr3vTjh9iGsA/g\n BC2k5hI01v6AvSMX+x2rhe8NuM3VRGflROrIdJGcrxrrU7qmGCE2gznCYWP6vq+hGtUi\n aX8g==", "X-Forwarded-Encrypted": "i=1;\n AJvYcCWDEXnmANPCDaRc3Bdzw2f/3Bv1vatWLPh7PCGqOz7iUIgKUC/iXu1smxRyAIBesrFVcQAsc0IeAQnk@vger.kernel.org", "X-Gm-Message-State": "AOJu0YxIqj/tTMsJkZOVz97qEGWFbBmilBnvivv/+dTWK2UsslKKA8wz\n\t+5xMBhuoPl8ROCoJkTEL/jDQrXjtNZVFkhJgFNwgK/5h/7vruU5Aps+B", "X-Gm-Gg": "ATEYQzzCvpdlQVir84xhx4JHStEyYjNrdu5p0guw9VMgXLZ2wQmQGcdX9/nDSirjEuX\n\tbBshag8lUAbjiYML31pknDElfmBxk8RXYIsWUieFr38WE+tqtQAb/HtAjyHlyKMLNEy99d42+j2\n\tYQWIEbUhQ4FQUWD9VxrxL6FelTJjWiG9eAIrmS8060AZnqmpL1IA+Uux7BFNpFkv62sWaK5BuA6\n\t9uvS+l2dbdmYdngDS0R7+er4BnZxws6U9NDLpky8Zl6FWdvcXuqFQgD+foFYTZDIzyS3IMGemTc\n\tHs3z1c9gcZCOsWF15C0yOD+hR3rotlpXX5VFXdrytO+qMkeML2EhjHFcCxXMwIO/icL4/L8X/l/\n\tL5q3GQVqPuvlD7BMlDajxXkieNa8wbCuJcprUpCzLsIQL28sLbc1NJxeSw6FFM6Xr9OAkOKzM0X\n\t0pMyevhymcdV5BYZRJUOoAVznF9pki4EQpwZweQmN5NUzQom179iDcKH8HtAgT4n1rQFEcRvnzv\n\tjd9uyjQQzdABPWkVtW8CsMk8JimddK7gVMjLbZOaIYQS94dAncNUzpAPDYweltBhA==", "X-Received": "by 2002:a05:622a:1390:b0:50b:48de:5448 with SMTP id\n d75a77b69052e-50b80cd3538mr31729831cf.6.1774410590863;\n Tue, 24 Mar 2026 20:49:50 -0700 (PDT)", "From": "Xin Long <lucien.xin@gmail.com>", "To": "network dev <netdev@vger.kernel.org>,\n\tquic@lists.linux.dev", "Cc": "davem@davemloft.net,\n\tkuba@kernel.org,\n\tEric Dumazet <edumazet@google.com>,\n\tPaolo Abeni <pabeni@redhat.com>,\n\tSimon Horman <horms@kernel.org>,\n\tStefan Metzmacher <metze@samba.org>,\n\tMoritz Buhl <mbuhl@openbsd.org>,\n\tTyler Fanelli <tfanelli@redhat.com>,\n\tPengtao He <hepengtao@xiaomi.com>,\n\tThomas Dreibholz <dreibh@simula.no>,\n\tlinux-cifs@vger.kernel.org,\n\tSteve French <smfrench@gmail.com>,\n\tNamjae Jeon <linkinjeon@kernel.org>,\n\tPaulo Alcantara <pc@manguebit.com>,\n\tTom Talpey <tom@talpey.com>,\n\tkernel-tls-handshake@lists.linux.dev,\n\tChuck Lever <chuck.lever@oracle.com>,\n\tJeff Layton <jlayton@kernel.org>,\n\tSteve Dickson <steved@redhat.com>,\n\tHannes Reinecke <hare@suse.de>,\n\tAlexander Aring <aahringo@redhat.com>,\n\tDavid Howells <dhowells@redhat.com>,\n\tMatthieu Baerts <matttbe@kernel.org>,\n\tJohn Ericson <mail@johnericson.me>,\n\tCong Wang <xiyou.wangcong@gmail.com>,\n\t\"D . Wythe\" <alibuda@linux.alibaba.com>,\n\tJason Baron <jbaron@akamai.com>,\n\tilliliti <illiliti@protonmail.com>,\n\tSabrina Dubroca <sd@queasysnail.net>,\n\tMarcelo Ricardo Leitner <marcelo.leitner@gmail.com>,\n\tDaniel Stenberg <daniel@haxx.se>,\n\tAndy Gospodarek <andrew.gospodarek@broadcom.com>,\n\t\"Marc E . Fiuczynski\" <marc@fiuczynski.com>", "Subject": "[PATCH net-next v11 11/15] quic: add crypto key derivation and\n installation", "Date": "Tue, 24 Mar 2026 23:47:16 -0400", "Message-ID": "\n <e893bba9e4bb56c7aeefec5f9b2a255afc9c7fb7.1774410440.git.lucien.xin@gmail.com>", "X-Mailer": "git-send-email 2.47.1", "In-Reply-To": "<cover.1774410440.git.lucien.xin@gmail.com>", "References": "<cover.1774410440.git.lucien.xin@gmail.com>", "Precedence": "bulk", "X-Mailing-List": "linux-cifs@vger.kernel.org", "List-Id": "<linux-cifs.vger.kernel.org>", "List-Subscribe": "<mailto:linux-cifs+subscribe@vger.kernel.org>", "List-Unsubscribe": "<mailto:linux-cifs+unsubscribe@vger.kernel.org>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit" }, "content": "This patch introduces 'quic_crypto', a component responsible for QUIC\nencryption key derivation and installation across the various key\nlevels: Initial, Handshake, 0-RTT (Early), and 1-RTT (Application).\n\nIt provides helpers to derive and install initial secrets, set traffic\nsecrets and install the corresponding keys, and perform key updates to\nenable forward secrecy. Additionally, it implements stateless reset\ntoken generation, used to support connection reset without state.\n\n- quic_crypto_initial_keys_install(): Derive and install initial keys.\n\n- quic_crypto_set_cipher(): Allocate all transforms based on the cipher\n type provided.\n\n- quic_crypto_set_secret(): Set the traffic secret and install derived\n keys.\n\n- quic_crypto_key_update(): Rekey and install new keys to the !phase\n side.\n\n- quic_crypto_generate_stateless_reset_token(): Generate token for\n stateless reset.\n\nThese mechanisms are essential for establishing and maintaining secure\ncommunication throughout the QUIC connection lifecycle.\n\nSigned-off-by: Pengtao He <hepengtao@xiaomi.com>\nSigned-off-by: Moritz Buhl <mbuhl@openbsd.org>\nSigned-off-by: Xin Long <lucien.xin@gmail.com>\n---\nv3:\n - Remove lock from quic_net, since Initial packet decryption for ALPN\n will be handled serially in a workqueue when ALPN demux is enabled.\nv4:\n - Use local cipher pointer in quic_crypto_set_secret() to avoid a\n warning from Smatch.\nv5:\n - Change the timestamp variables from u32 to u64, which provides\n sufficient precision for timestamps in microsecond.\nv8:\n - Remove the redundant err initialization in quic_net_init(), since err\n is now assigned from quic_crypto_set_cipher().\nv10:\n - Fix header protection key passed to pr_debug().\n - Fix typo: \"For example,to ...\" -> \"For example, to ...\" in comment.\n - Remove redundant initialization of err in quic_crypto_set_cipher().\nv11:\n - Note for AI reviews: later patches guarantee all tfms (including\n secret_tfm) are set before any quic_crypto function uses them.\n - Set maximum line length to 80 characters.\n - Merge quic_crypto_rx/tx_keys_derive_and_install() to\n quic_crypto_keys_derive_and_install() with an extra parameter to\n reduce code duplication (noted by AI review).\n - Change flag parameter type to u32 in quic_crypto_set_secret() and\n quic_crypto_set_cipher().\n---\n net/quic/Makefile | 2 +-\n net/quic/crypto.c | 566 ++++++++++++++++++++++++++++++++++++++++++++\n net/quic/crypto.h | 80 +++++++\n net/quic/protocol.c | 14 +-\n net/quic/protocol.h | 2 +\n net/quic/socket.c | 2 +\n net/quic/socket.h | 7 +\n 7 files changed, 671 insertions(+), 2 deletions(-)\n create mode 100644 net/quic/crypto.c\n create mode 100644 net/quic/crypto.h", "diff": "diff --git a/net/quic/Makefile b/net/quic/Makefile\nindex 9d8e18297911..58bb18f7926d 100644\n--- a/net/quic/Makefile\n+++ b/net/quic/Makefile\n@@ -6,4 +6,4 @@\n obj-$(CONFIG_IP_QUIC) += quic.o\n \n quic-y := common.o family.o protocol.o socket.o stream.o connid.o path.o \\\n-\t cong.o pnspace.o\n+\t cong.o pnspace.o crypto.o\ndiff --git a/net/quic/crypto.c b/net/quic/crypto.c\nnew file mode 100644\nindex 000000000000..218d3fe49dff\n--- /dev/null\n+++ b/net/quic/crypto.c\n@@ -0,0 +1,566 @@\n+// SPDX-License-Identifier: GPL-2.0-or-later\n+/* QUIC kernel implementation\n+ * (C) Copyright Red Hat Corp. 2023\n+ *\n+ * This file is part of the QUIC kernel implementation\n+ *\n+ * Initialization/cleanup for QUIC protocol support.\n+ *\n+ * Written or modified by:\n+ * Xin Long <lucien.xin@gmail.com>\n+ */\n+\n+#include <crypto/skcipher.h>\n+#include <linux/skbuff.h>\n+#include <crypto/aead.h>\n+#include <crypto/hkdf.h>\n+#include <linux/quic.h>\n+#include <net/tls.h>\n+\n+#include \"common.h\"\n+#include \"crypto.h\"\n+\n+#define QUIC_RANDOM_DATA_LEN\t32\n+\n+static u8 quic_random_data[QUIC_RANDOM_DATA_LEN] __read_mostly;\n+\n+/* HKDF-Extract. */\n+static int quic_crypto_hkdf_extract(struct crypto_shash *tfm,\n+\t\t\t\t struct quic_data *srt,\n+\t\t\t\t struct quic_data *hash,\n+\t\t\t\t struct quic_data *key)\n+{\n+\treturn hkdf_extract(tfm, hash->data, hash->len, srt->data, srt->len,\n+\t\t\t key->data);\n+}\n+\n+#define QUIC_MAX_INFO_LEN\t256\n+\n+/* HKDF-Expand-Label. */\n+static int quic_crypto_hkdf_expand(struct crypto_shash *tfm,\n+\t\t\t\t struct quic_data *srt,\n+\t\t\t\t struct quic_data *label,\n+\t\t\t\t struct quic_data *hash,\n+\t\t\t\t struct quic_data *key)\n+{\n+\tu8 info[QUIC_MAX_INFO_LEN], *p = info;\n+\tu8 LABEL[] = \"tls13 \";\n+\tu32 infolen;\n+\tint err;\n+\n+\t/* rfc8446#section-7.1:\n+\t *\n+\t * HKDF-Expand-Label(Secret, Label, Context, Length) =\n+\t * HKDF-Expand(Secret, HkdfLabel, Length)\n+\t *\n+\t * Where HkdfLabel is specified as:\n+\t *\n+\t * struct {\n+\t * uint16 length = Length;\n+\t * opaque label<7..255> = \"tls13 \" + Label;\n+\t * opaque context<0..255> = Context;\n+\t * } HkdfLabel;\n+\t */\n+\t*p++ = (u8)(key->len / QUIC_MAX_INFO_LEN);\n+\t*p++ = (u8)(key->len % QUIC_MAX_INFO_LEN);\n+\t*p++ = (u8)(sizeof(LABEL) - 1 + label->len);\n+\tp = quic_put_data(p, LABEL, sizeof(LABEL) - 1);\n+\tp = quic_put_data(p, label->data, label->len);\n+\tif (hash) {\n+\t\t*p++ = (u8)hash->len;\n+\t\tp = quic_put_data(p, hash->data, hash->len);\n+\t} else {\n+\t\t*p++ = 0;\n+\t}\n+\tinfolen = (u32)(p - info);\n+\n+\terr = crypto_shash_setkey(tfm, srt->data, srt->len);\n+\tif (err)\n+\t\treturn err;\n+\n+\treturn hkdf_expand(tfm, info, infolen, key->data, key->len);\n+}\n+\n+#define KEY_LABEL_V1\t\t\"quic key\"\n+#define IV_LABEL_V1\t\t\"quic iv\"\n+#define HP_KEY_LABEL_V1\t\t\"quic hp\"\n+\n+#define KU_LABEL_V1\t\t\"quic ku\"\n+\n+/* rfc9369#section-3.3.2:\n+ *\n+ * The labels used in rfc9001 to derive packet protection keys, header\n+ * protection keys, Retry Integrity Tag keys, and key updates change from \"quic\n+ * key\" to \"quicv2 key\", from \"quic iv\" to \"quicv2 iv\", from \"quic hp\" to\n+ * \"quicv2 hp\", and from \"quic ku\" to \"quicv2 ku\".\n+ */\n+#define KEY_LABEL_V2\t\t\"quicv2 key\"\n+#define IV_LABEL_V2\t\t\"quicv2 iv\"\n+#define HP_KEY_LABEL_V2\t\t\"quicv2 hp\"\n+\n+#define KU_LABEL_V2\t\t\"quicv2 ku\"\n+\n+/* Packet Protection Keys. */\n+static int quic_crypto_keys_derive(struct crypto_shash *tfm,\n+\t\t\t\t struct quic_data *s, struct quic_data *k,\n+\t\t\t\t struct quic_data *i, struct quic_data *hp_k,\n+\t\t\t\t u32 version)\n+{\n+\tstruct quic_data hp_k_l = {HP_KEY_LABEL_V1, strlen(HP_KEY_LABEL_V1)};\n+\tstruct quic_data k_l = {KEY_LABEL_V1, strlen(KEY_LABEL_V1)};\n+\tstruct quic_data i_l = {IV_LABEL_V1, strlen(IV_LABEL_V1)};\n+\tstruct quic_data z = {};\n+\tint err;\n+\n+\t/* rfc9001#section-5.1:\n+\t *\n+\t * The current encryption level secret and the label \"quic key\" are\n+\t * input to the KDF to produce the AEAD key; the label \"quic iv\" is\n+\t * used to derive the Initialization Vector (IV). The header protection\n+\t * key uses the \"quic hp\" label. Using these labels provides key\n+\t * separation between QUIC and TLS.\n+\t */\n+\tif (version == QUIC_VERSION_V2) {\n+\t\tquic_data(&hp_k_l, HP_KEY_LABEL_V2, strlen(HP_KEY_LABEL_V2));\n+\t\tquic_data(&k_l, KEY_LABEL_V2, strlen(KEY_LABEL_V2));\n+\t\tquic_data(&i_l, IV_LABEL_V2, strlen(IV_LABEL_V2));\n+\t}\n+\n+\terr = quic_crypto_hkdf_expand(tfm, s, &k_l, &z, k);\n+\tif (err)\n+\t\treturn err;\n+\terr = quic_crypto_hkdf_expand(tfm, s, &i_l, &z, i);\n+\tif (err)\n+\t\treturn err;\n+\t/* Don't change hp key for key update. */\n+\tif (!hp_k)\n+\t\treturn 0;\n+\n+\treturn quic_crypto_hkdf_expand(tfm, s, &hp_k_l, &z, hp_k);\n+}\n+\n+/* Derive and install reception (RX) or transmission (TX) packet protection\n+ * keys for the current key phase. This installs AEAD protection key, IV, and\n+ * optionally header protection key.\n+ */\n+static int quic_crypto_keys_derive_and_install(struct quic_crypto *crypto,\n+\t\t\t\t\t bool rx)\n+{\n+\tstruct quic_data srt = {}, k, iv, hp_k = {}, *hp = NULL;\n+\tu8 key[QUIC_KEY_LEN], hp_key[QUIC_KEY_LEN] = {};\n+\tint err, phase = crypto->key_phase;\n+\tu32 keylen, ivlen = QUIC_IV_LEN;\n+\tstruct crypto_skcipher *hp_tfm;\n+\tstruct crypto_aead *tfm;\n+\n+\tkeylen = crypto->cipher->keylen;\n+\tquic_data(&k, key, keylen);\n+\n+\tif (rx) {\n+\t\tquic_data(&srt, crypto->rx_secret, crypto->cipher->secretlen);\n+\t\tquic_data(&iv, crypto->rx_iv[phase], ivlen);\n+\t\ttfm = crypto->rx_tfm[phase];\n+\t\thp_tfm = crypto->rx_hp_tfm;\n+\t} else {\n+\t\tquic_data(&srt, crypto->tx_secret, crypto->cipher->secretlen);\n+\t\tquic_data(&iv, crypto->tx_iv[phase], ivlen);\n+\t\ttfm = crypto->tx_tfm[phase];\n+\t\thp_tfm = crypto->tx_hp_tfm;\n+\t}\n+\n+\t/* Only derive header protection key when not in key update. */\n+\tif (!crypto->key_pending)\n+\t\thp = quic_data(&hp_k, hp_key, keylen);\n+\terr = quic_crypto_keys_derive(crypto->secret_tfm, &srt, &k, &iv, hp,\n+\t\t\t\t crypto->version);\n+\tif (err)\n+\t\tgoto out;\n+\terr = crypto_aead_setauthsize(tfm, QUIC_TAG_LEN);\n+\tif (err)\n+\t\tgoto out;\n+\terr = crypto_aead_setkey(tfm, key, keylen);\n+\tif (err)\n+\t\tgoto out;\n+\tif (hp) {\n+\t\terr = crypto_skcipher_setkey(hp_tfm, hp_key, keylen);\n+\t\tif (err)\n+\t\t\tgoto out;\n+\t}\n+\tpr_debug(\"%s: rx: %d k: %16phN, iv: %12phN, hp_k:%16phN\\n\", __func__,\n+\t\t rx, k.data, iv.data, hp_key);\n+out:\n+\tmemzero_explicit(key, sizeof(key));\n+\tmemzero_explicit(hp_key, sizeof(hp_key));\n+\treturn err;\n+}\n+\n+#define QUIC_CIPHER_MIN TLS_CIPHER_AES_GCM_128\n+#define QUIC_CIPHER_MAX TLS_CIPHER_CHACHA20_POLY1305\n+\n+#define TLS_CIPHER_AES_GCM_128_SECRET_SIZE\t\t32\n+#define TLS_CIPHER_AES_GCM_256_SECRET_SIZE\t\t48\n+#define TLS_CIPHER_AES_CCM_128_SECRET_SIZE\t\t32\n+#define TLS_CIPHER_CHACHA20_POLY1305_SECRET_SIZE\t32\n+\n+#define CIPHER_DESC(type, aead_n, skc_n, sha_n)[type - QUIC_CIPHER_MIN] = { \\\n+\t.secretlen = type ## _SECRET_SIZE, \\\n+\t.keylen = type ## _KEY_SIZE, \\\n+\t.aead = aead_n, \\\n+\t.skc = skc_n, \\\n+\t.shash = sha_n, \\\n+}\n+\n+static struct quic_cipher ciphers[QUIC_CIPHER_MAX + 1 - QUIC_CIPHER_MIN] = {\n+\tCIPHER_DESC(TLS_CIPHER_AES_GCM_128,\n+\t\t \"gcm(aes)\", \"ecb(aes)\", \"hmac(sha256)\"),\n+\tCIPHER_DESC(TLS_CIPHER_AES_GCM_256,\n+\t\t \"gcm(aes)\", \"ecb(aes)\", \"hmac(sha384)\"),\n+\tCIPHER_DESC(TLS_CIPHER_AES_CCM_128,\n+\t\t \"ccm(aes)\", \"ecb(aes)\", \"hmac(sha256)\"),\n+\tCIPHER_DESC(TLS_CIPHER_CHACHA20_POLY1305,\n+\t\t \"rfc7539(chacha20,poly1305)\", \"chacha20\", \"hmac(sha256)\"),\n+};\n+\n+int quic_crypto_set_cipher(struct quic_crypto *crypto, u32 type, u32 flag)\n+{\n+\tstruct quic_cipher *cipher;\n+\tvoid *tfm;\n+\tint err;\n+\n+\tif (type < QUIC_CIPHER_MIN || type > QUIC_CIPHER_MAX)\n+\t\treturn -EINVAL;\n+\n+\tcipher = &ciphers[type - QUIC_CIPHER_MIN];\n+\ttfm = crypto_alloc_shash(cipher->shash, 0, 0);\n+\tif (IS_ERR(tfm))\n+\t\treturn PTR_ERR(tfm);\n+\tcrypto->secret_tfm = tfm;\n+\n+\t/* Request only synchronous crypto by specifying CRYPTO_ALG_ASYNC. This\n+\t * ensures tag generation does not rely on async callbacks.\n+\t */\n+\ttfm = crypto_alloc_aead(cipher->aead, 0, CRYPTO_ALG_ASYNC);\n+\tif (IS_ERR(tfm)) {\n+\t\terr = PTR_ERR(tfm);\n+\t\tgoto err;\n+\t}\n+\tcrypto->tag_tfm = tfm;\n+\n+\t/* Allocate AEAD and HP transform for each RX key phase. */\n+\ttfm = crypto_alloc_aead(cipher->aead, 0, flag);\n+\tif (IS_ERR(tfm)) {\n+\t\terr = PTR_ERR(tfm);\n+\t\tgoto err;\n+\t}\n+\tcrypto->rx_tfm[0] = tfm;\n+\ttfm = crypto_alloc_aead(cipher->aead, 0, flag);\n+\tif (IS_ERR(tfm)) {\n+\t\terr = PTR_ERR(tfm);\n+\t\tgoto err;\n+\t}\n+\tcrypto->rx_tfm[1] = tfm;\n+\ttfm = crypto_alloc_sync_skcipher(cipher->skc, 0, 0);\n+\tif (IS_ERR(tfm)) {\n+\t\terr = PTR_ERR(tfm);\n+\t\tgoto err;\n+\t}\n+\tcrypto->rx_hp_tfm = tfm;\n+\n+\t/* Allocate AEAD and HP transform for each TX key phase. */\n+\ttfm = crypto_alloc_aead(cipher->aead, 0, flag);\n+\tif (IS_ERR(tfm)) {\n+\t\terr = PTR_ERR(tfm);\n+\t\tgoto err;\n+\t}\n+\tcrypto->tx_tfm[0] = tfm;\n+\ttfm = crypto_alloc_aead(cipher->aead, 0, flag);\n+\tif (IS_ERR(tfm)) {\n+\t\terr = PTR_ERR(tfm);\n+\t\tgoto err;\n+\t}\n+\tcrypto->tx_tfm[1] = tfm;\n+\ttfm = crypto_alloc_sync_skcipher(cipher->skc, 0, 0);\n+\tif (IS_ERR(tfm)) {\n+\t\terr = PTR_ERR(tfm);\n+\t\tgoto err;\n+\t}\n+\tcrypto->tx_hp_tfm = tfm;\n+\n+\tcrypto->cipher = cipher;\n+\tcrypto->cipher_type = type;\n+\treturn 0;\n+err:\n+\tquic_crypto_free(crypto);\n+\treturn err;\n+}\n+\n+int quic_crypto_set_secret(struct quic_crypto *crypto,\n+\t\t\t struct quic_crypto_secret *srt,\n+\t\t\t u32 version, u32 flag)\n+{\n+\tstruct quic_cipher *cipher;\n+\tint err;\n+\n+\t/* If no cipher has been initialized yet, set it up. */\n+\tif (!crypto->cipher) {\n+\t\terr = quic_crypto_set_cipher(crypto, srt->type, flag);\n+\t\tif (err)\n+\t\t\treturn err;\n+\t}\n+\tcipher = crypto->cipher;\n+\n+\t/* Handle RX path setup. */\n+\tif (!srt->send) {\n+\t\tcrypto->version = version;\n+\t\tmemcpy(crypto->rx_secret, srt->secret, cipher->secretlen);\n+\t\terr = quic_crypto_keys_derive_and_install(crypto, true);\n+\t\tif (err)\n+\t\t\treturn err;\n+\t\tcrypto->recv_ready = 1;\n+\t\treturn 0;\n+\t}\n+\n+\t/* Handle TX path setup. */\n+\tcrypto->version = version;\n+\tmemcpy(crypto->tx_secret, srt->secret, cipher->secretlen);\n+\terr = quic_crypto_keys_derive_and_install(crypto, false);\n+\tif (err)\n+\t\treturn err;\n+\tcrypto->send_ready = 1;\n+\treturn 0;\n+}\n+\n+int quic_crypto_get_secret(struct quic_crypto *crypto,\n+\t\t\t struct quic_crypto_secret *srt)\n+{\n+\tu8 *secret;\n+\n+\tif (!crypto->cipher)\n+\t\treturn -EINVAL;\n+\tsrt->type = crypto->cipher_type;\n+\tsecret = srt->send ? crypto->tx_secret : crypto->rx_secret;\n+\tmemcpy(srt->secret, secret, crypto->cipher->secretlen);\n+\treturn 0;\n+}\n+\n+/* Initiating a Key Update. */\n+int quic_crypto_key_update(struct quic_crypto *crypto)\n+{\n+\tu8 tx_secret[QUIC_SECRET_LEN], rx_secret[QUIC_SECRET_LEN];\n+\tstruct quic_data l = {KU_LABEL_V1, strlen(KU_LABEL_V1)};\n+\tstruct quic_data z = {}, k, srt;\n+\tu32 secret_len;\n+\tint err;\n+\n+\tif (crypto->key_pending || !crypto->recv_ready)\n+\t\treturn -EINVAL;\n+\n+\t/* rfc9001#section-6.1:\n+\t *\n+\t * Endpoints maintain separate read and write secrets for packet\n+\t * protection. An endpoint initiates a key update by updating its\n+\t * packet protection write secret and using that to protect new\n+\t * packets. The endpoint creates a new write secret from the existing\n+\t * write secret. This uses the KDF function provided by TLS with a\n+\t * label of \"quic ku\". The corresponding key and IV are created from\n+\t * that secret. The header protection key is not updated.\n+\t *\n+\t * For example, to update write keys with TLS 1.3, HKDF-Expand-Label is\n+\t * used as:\n+\t * secret_<n+1> = HKDF-Expand-Label(secret_<n>, \"quic ku\",\n+\t * \"\", Hash.length)\n+\t */\n+\tsecret_len = crypto->cipher->secretlen;\n+\tif (crypto->version == QUIC_VERSION_V2)\n+\t\tquic_data(&l, KU_LABEL_V2, strlen(KU_LABEL_V2));\n+\n+\tcrypto->key_pending = 1;\n+\tmemcpy(tx_secret, crypto->tx_secret, secret_len);\n+\tmemcpy(rx_secret, crypto->rx_secret, secret_len);\n+\tcrypto->key_phase = !crypto->key_phase;\n+\n+\tquic_data(&srt, tx_secret, secret_len);\n+\tquic_data(&k, crypto->tx_secret, secret_len);\n+\terr = quic_crypto_hkdf_expand(crypto->secret_tfm, &srt, &l, &z, &k);\n+\tif (err)\n+\t\tgoto err;\n+\terr = quic_crypto_keys_derive_and_install(crypto, false);\n+\tif (err)\n+\t\tgoto err;\n+\n+\tquic_data(&srt, rx_secret, secret_len);\n+\tquic_data(&k, crypto->rx_secret, secret_len);\n+\terr = quic_crypto_hkdf_expand(crypto->secret_tfm, &srt, &l, &z, &k);\n+\tif (err)\n+\t\tgoto err;\n+\terr = quic_crypto_keys_derive_and_install(crypto, true);\n+\tif (err)\n+\t\tgoto err;\n+out:\n+\tmemzero_explicit(tx_secret, sizeof(tx_secret));\n+\tmemzero_explicit(rx_secret, sizeof(rx_secret));\n+\treturn err;\n+err:\n+\tcrypto->key_pending = 0;\n+\tmemcpy(crypto->tx_secret, tx_secret, secret_len);\n+\tmemcpy(crypto->rx_secret, rx_secret, secret_len);\n+\tcrypto->key_phase = !crypto->key_phase;\n+\tgoto out;\n+}\n+\n+void quic_crypto_free(struct quic_crypto *crypto)\n+{\n+\tif (crypto->tag_tfm)\n+\t\tcrypto_free_aead(crypto->tag_tfm);\n+\tif (crypto->rx_tfm[0])\n+\t\tcrypto_free_aead(crypto->rx_tfm[0]);\n+\tif (crypto->rx_tfm[1])\n+\t\tcrypto_free_aead(crypto->rx_tfm[1]);\n+\tif (crypto->tx_tfm[0])\n+\t\tcrypto_free_aead(crypto->tx_tfm[0]);\n+\tif (crypto->tx_tfm[1])\n+\t\tcrypto_free_aead(crypto->tx_tfm[1]);\n+\tif (crypto->secret_tfm)\n+\t\tcrypto_free_shash(crypto->secret_tfm);\n+\tif (crypto->rx_hp_tfm)\n+\t\tcrypto_free_skcipher(crypto->rx_hp_tfm);\n+\tif (crypto->tx_hp_tfm)\n+\t\tcrypto_free_skcipher(crypto->tx_hp_tfm);\n+\n+\tmemzero_explicit(crypto, offsetof(struct quic_crypto, send_offset));\n+}\n+\n+#define QUIC_INITIAL_SALT_V1 \\\n+\t\"\\x38\\x76\\x2c\\xf7\\xf5\\x59\\x34\\xb3\\x4d\\x17\" \\\n+\t\"\\x9a\\xe6\\xa4\\xc8\\x0c\\xad\\xcc\\xbb\\x7f\\x0a\"\n+\n+#define QUIC_INITIAL_SALT_V2 \\\n+\t\"\\x0d\\xed\\xe3\\xde\\xf7\\x00\\xa6\\xdb\\x81\\x93\" \\\n+\t\"\\x81\\xbe\\x6e\\x26\\x9d\\xcb\\xf9\\xbd\\x2e\\xd9\"\n+\n+#define QUIC_INITIAL_SALT_LEN\t20\n+\n+/* Initial Secrets. */\n+int quic_crypto_initial_keys_install(struct quic_crypto *crypto,\n+\t\t\t\t struct quic_conn_id *conn_id,\n+\t\t\t\t u32 version, bool is_serv)\n+{\n+\tu8 secret[TLS_CIPHER_AES_GCM_128_SECRET_SIZE];\n+\tstruct quic_data salt, s, k, l, dcid, z = {};\n+\tstruct quic_crypto_secret srt = {};\n+\tchar *tl, *rl, *sal;\n+\tint err;\n+\n+\t/* rfc9001#section-5.2:\n+\t *\n+\t * The secret used by clients to construct Initial packets uses the PRK\n+\t * and the label \"client in\" as input to the HKDF-Expand-Label function\n+\t * from TLS [TLS13] to produce a 32-byte secret. Packets constructed by\n+\t * the server use the same process with the label \"server in\". The hash\n+\t * function for HKDF when deriving initial secrets and keys is SHA-256\n+\t * [SHA].\n+\t *\n+\t * This process in pseudocode is:\n+\t *\n+\t * initial_salt = 0x38762cf7f55934b34d179ae6a4c80cadccbb7f0a\n+\t * initial_secret = HKDF-Extract(initial_salt,\n+\t * client_dst_connection_id)\n+\t *\n+\t * client_initial_secret = HKDF-Expand-Label(initial_secret,\n+\t * \"client in\", \"\",\n+\t * Hash.length)\n+\t * server_initial_secret = HKDF-Expand-Label(initial_secret,\n+\t * \"server in\", \"\",\n+\t * Hash.length)\n+\t */\n+\tif (is_serv) {\n+\t\trl = \"client in\";\n+\t\ttl = \"server in\";\n+\t} else {\n+\t\ttl = \"client in\";\n+\t\trl = \"server in\";\n+\t}\n+\tsal = QUIC_INITIAL_SALT_V1;\n+\tif (version == QUIC_VERSION_V2)\n+\t\tsal = QUIC_INITIAL_SALT_V2;\n+\tquic_data(&salt, sal, QUIC_INITIAL_SALT_LEN);\n+\tquic_data(&dcid, conn_id->data, conn_id->len);\n+\tquic_data(&s, secret, TLS_CIPHER_AES_GCM_128_SECRET_SIZE);\n+\terr = quic_crypto_hkdf_extract(crypto->secret_tfm, &salt, &dcid, &s);\n+\tif (err)\n+\t\tgoto out;\n+\n+\tquic_data(&l, tl, strlen(tl));\n+\tquic_data(&k, srt.secret, TLS_CIPHER_AES_GCM_128_SECRET_SIZE);\n+\tsrt.type = TLS_CIPHER_AES_GCM_128;\n+\tsrt.send = 1;\n+\terr = quic_crypto_hkdf_expand(crypto->secret_tfm, &s, &l, &z, &k);\n+\tif (err)\n+\t\tgoto out;\n+\terr = quic_crypto_set_secret(crypto, &srt, version, 0);\n+\tif (err)\n+\t\tgoto out;\n+\n+\tquic_data(&l, rl, strlen(rl));\n+\tquic_data(&k, srt.secret, TLS_CIPHER_AES_GCM_128_SECRET_SIZE);\n+\tsrt.type = TLS_CIPHER_AES_GCM_128;\n+\tsrt.send = 0;\n+\terr = quic_crypto_hkdf_expand(crypto->secret_tfm, &s, &l, &z, &k);\n+\tif (err)\n+\t\tgoto out;\n+\terr = quic_crypto_set_secret(crypto, &srt, version, 0);\n+out:\n+\tmemzero_explicit(secret, sizeof(secret));\n+\tmemzero_explicit(&srt, sizeof(srt));\n+\treturn err;\n+}\n+\n+/* Generate a derived key using HKDF-Extract and HKDF-Expand with a given\n+ * label.\n+ */\n+static int quic_crypto_generate_key(struct quic_crypto *crypto, void *data,\n+\t\t\t\t u32 len, char *label, u8 *token,\n+\t\t\t\t u32 key_len)\n+{\n+\tstruct crypto_shash *tfm = crypto->secret_tfm;\n+\tu8 secret[TLS_CIPHER_AES_GCM_128_SECRET_SIZE];\n+\tstruct quic_data salt, s, l, k, z = {};\n+\tint err;\n+\n+\tquic_data(&salt, data, len);\n+\tquic_data(&k, quic_random_data, QUIC_RANDOM_DATA_LEN);\n+\tquic_data(&s, secret, TLS_CIPHER_AES_GCM_128_SECRET_SIZE);\n+\terr = quic_crypto_hkdf_extract(tfm, &salt, &k, &s);\n+\tif (err)\n+\t\tgoto out;\n+\n+\tquic_data(&l, label, strlen(label));\n+\tquic_data(&k, token, key_len);\n+\terr = quic_crypto_hkdf_expand(tfm, &s, &l, &z, &k);\n+out:\n+\tmemzero_explicit(secret, sizeof(secret));\n+\treturn err;\n+}\n+\n+/* Derive a stateless reset token from connection-specific input. */\n+int quic_crypto_generate_stateless_reset_token(struct quic_crypto *crypto,\n+\t\t\t\t\t void *data, u32 len, u8 *key,\n+\t\t\t\t\t u32 key_len)\n+{\n+\treturn quic_crypto_generate_key(crypto, data, len, \"stateless_reset\",\n+\t\t\t\t\tkey, key_len);\n+}\n+\n+/* Derive a session ticket key using HKDF from connection-specific input. */\n+int quic_crypto_generate_session_ticket_key(struct quic_crypto *crypto,\n+\t\t\t\t\t void *data, u32 len, u8 *key,\n+\t\t\t\t\t u32 key_len)\n+{\n+\treturn quic_crypto_generate_key(crypto, data, len, \"session_ticket\",\n+\t\t\t\t\tkey, key_len);\n+}\n+\n+void quic_crypto_init(void)\n+{\n+\tget_random_bytes(quic_random_data, QUIC_RANDOM_DATA_LEN);\n+}\ndiff --git a/net/quic/crypto.h b/net/quic/crypto.h\nnew file mode 100644\nindex 000000000000..f9450e55d6dd\n--- /dev/null\n+++ b/net/quic/crypto.h\n@@ -0,0 +1,80 @@\n+/* SPDX-License-Identifier: GPL-2.0-or-later */\n+/* QUIC kernel implementation\n+ * (C) Copyright Red Hat Corp. 2023\n+ *\n+ * This file is part of the QUIC kernel implementation\n+ *\n+ * Written or modified by:\n+ * Xin Long <lucien.xin@gmail.com>\n+ */\n+\n+#define QUIC_TAG_LEN\t16\n+#define QUIC_IV_LEN\t12\n+#define QUIC_KEY_LEN\t32\n+#define QUIC_SECRET_LEN\t48\n+\n+#define QUIC_TOKEN_FLAG_REGULAR\t\t0\n+#define QUIC_TOKEN_FLAG_RETRY\t\t1\n+#define QUIC_TOKEN_TIMEOUT_RETRY\t3000000\n+#define QUIC_TOKEN_TIMEOUT_REGULAR\t600000000\n+\n+struct quic_cipher {\n+\tu32 secretlen; /* Length of the traffic secret */\n+\tu32 keylen; /* Length of the AEAD key */\n+\n+\tchar *shash; /* Name of hash algorithm used for key derivation */\n+\tchar *aead; /* Name of AEAD algorithm used for payload en/decryption */\n+\tchar *skc; /* Name of cipher algorithm used for header protection */\n+};\n+\n+struct quic_crypto {\n+\tstruct crypto_skcipher *tx_hp_tfm; /* TX header protection tfm */\n+\tstruct crypto_skcipher *rx_hp_tfm; /* RX header protection tfm */\n+\tstruct crypto_shash *secret_tfm; /* Key derivation (HKDF) tfm */\n+\tstruct crypto_aead *tx_tfm[2]; /* AEAD tfm for TX (key phase 0 and 1) */\n+\tstruct crypto_aead *rx_tfm[2]; /* AEAD tfm for RX (key phase 0 and 1) */\n+\tstruct crypto_aead *tag_tfm; /* AEAD tfm used for token validation */\n+\tstruct quic_cipher *cipher; /* Cipher info (selected cipher suite) */\n+\tu32 cipher_type; /* Cipher suite (e.g., AES_GCM_128, etc.) */\n+\n+\tu8 tx_secret[QUIC_SECRET_LEN]; /* TX secret (derived or from user) */\n+\tu8 rx_secret[QUIC_SECRET_LEN]; /* RX secret (derived or from user) */\n+\tu8 tx_iv[2][QUIC_IV_LEN]; /* IVs for TX (key phase 0 and 1) */\n+\tu8 rx_iv[2][QUIC_IV_LEN]; /* IVs for RX (key phase 0 and 1) */\n+\n+\t/* Timestamp 1st packet sent after key update */\n+\tu64 key_update_send_time;\n+\tu64 key_update_time; /* Timestamp old keys retained after key update */\n+\tu32 version; /* QUIC version in use */\n+\n+\tu8 ticket_ready:1; /* True if a session ticket is ready to read */\n+\tu8 key_pending:1; /* A key update is in progress */\n+\tu8 send_ready:1; /* TX encryption context is initialized */\n+\tu8 recv_ready:1; /* RX decryption context is initialized */\n+\tu8 key_phase:1; /* Current key phase being used (0 or 1) */\n+\n+\tu64 send_offset; /* Number of handshake bytes sent by user */\n+\tu64 recv_offset; /* Number of handshake bytes read by user */\n+};\n+\n+int quic_crypto_set_secret(struct quic_crypto *crypto,\n+\t\t\t struct quic_crypto_secret *srt,\n+\t\t\t u32 version, u32 flag);\n+int quic_crypto_get_secret(struct quic_crypto *crypto,\n+\t\t\t struct quic_crypto_secret *srt);\n+int quic_crypto_set_cipher(struct quic_crypto *crypto,\n+\t\t\t u32 type, u32 flag);\n+int quic_crypto_key_update(struct quic_crypto *crypto);\n+\n+int quic_crypto_initial_keys_install(struct quic_crypto *crypto,\n+\t\t\t\t struct quic_conn_id *conn_id,\n+\t\t\t\t u32 version, bool is_serv);\n+int quic_crypto_generate_session_ticket_key(struct quic_crypto *crypto,\n+\t\t\t\t\t void *data, u32 len, u8 *key,\n+\t\t\t\t\t u32 key_len);\n+int quic_crypto_generate_stateless_reset_token(struct quic_crypto *crypto,\n+\t\t\t\t\t void *data, u32 len, u8 *key,\n+\t\t\t\t\t u32 key_len);\n+\n+void quic_crypto_free(struct quic_crypto *crypto);\n+void quic_crypto_init(void);\ndiff --git a/net/quic/protocol.c b/net/quic/protocol.c\nindex fd528fb2fc46..7f055c88bbde 100644\n--- a/net/quic/protocol.c\n+++ b/net/quic/protocol.c\n@@ -256,15 +256,24 @@ static void quic_protosw_exit(void)\n static int __net_init quic_net_init(struct net *net)\n {\n \tstruct quic_net *qn = quic_net(net);\n-\tint err = 0;\n+\tint err;\n \n \tqn->stat = alloc_percpu(struct quic_mib);\n \tif (!qn->stat)\n \t\treturn -ENOMEM;\n \n+\terr = quic_crypto_set_cipher(&qn->crypto, TLS_CIPHER_AES_GCM_128,\n+\t\t\t\t CRYPTO_ALG_ASYNC);\n+\tif (err) {\n+\t\tfree_percpu(qn->stat);\n+\t\tqn->stat = NULL;\n+\t\treturn err;\n+\t}\n+\n #if IS_ENABLED(CONFIG_PROC_FS)\n \terr = quic_net_proc_init(net);\n \tif (err) {\n+\t\tquic_crypto_free(&qn->crypto);\n \t\tfree_percpu(qn->stat);\n \t\tqn->stat = NULL;\n \t}\n@@ -279,6 +288,7 @@ static void __net_exit quic_net_exit(struct net *net)\n #if IS_ENABLED(CONFIG_PROC_FS)\n \tquic_net_proc_exit(net);\n #endif\n+\tquic_crypto_free(&qn->crypto);\n \tfree_percpu(qn->stat);\n \tqn->stat = NULL;\n }\n@@ -333,6 +343,8 @@ static __init int quic_init(void)\n \tsysctl_quic_wmem[1] = 16 * 1024;\n \tsysctl_quic_wmem[2] = max(64 * 1024, max_share);\n \n+\tquic_crypto_init();\n+\n \terr = percpu_counter_init(&quic_sockets_allocated, 0, GFP_KERNEL);\n \tif (err)\n \t\tgoto err_percpu_counter;\ndiff --git a/net/quic/protocol.h b/net/quic/protocol.h\nindex fbd0fe39eccc..b8584e72ff14 100644\n--- a/net/quic/protocol.h\n+++ b/net/quic/protocol.h\n@@ -49,6 +49,8 @@ struct quic_net {\n #if IS_ENABLED(CONFIG_PROC_FS)\n \tstruct proc_dir_entry *proc_net; /* procfs entry for QUIC stats */\n #endif\n+\t/* Context for decrypting Initial packets for ALPN */\n+\tstruct quic_crypto crypto;\n };\n \n struct quic_net *quic_net(struct net *net);\ndiff --git a/net/quic/socket.c b/net/quic/socket.c\nindex 3b66cf8a942a..4016de4b39fe 100644\n--- a/net/quic/socket.c\n+++ b/net/quic/socket.c\n@@ -68,6 +68,8 @@ static void quic_destroy_sock(struct sock *sk)\n \n \tfor (i = 0; i < QUIC_PNSPACE_MAX; i++)\n \t\tquic_pnspace_free(quic_pnspace(sk, i));\n+\tfor (i = 0; i < QUIC_CRYPTO_MAX; i++)\n+\t\tquic_crypto_free(quic_crypto(sk, i));\n \n \tquic_path_unbind(sk, quic_paths(sk), 0);\n \tquic_path_unbind(sk, quic_paths(sk), 1);\ndiff --git a/net/quic/socket.h b/net/quic/socket.h\nindex 68c7b22d1e88..d7811391cc8b 100644\n--- a/net/quic/socket.h\n+++ b/net/quic/socket.h\n@@ -16,6 +16,7 @@\n #include \"family.h\"\n #include \"stream.h\"\n #include \"connid.h\"\n+#include \"crypto.h\"\n #include \"path.h\"\n #include \"cong.h\"\n \n@@ -45,6 +46,7 @@ struct quic_sock {\n \tstruct quic_path_group\t\tpaths;\n \tstruct quic_cong\t\tcong;\n \tstruct quic_pnspace\t\tspace[QUIC_PNSPACE_MAX];\n+\tstruct quic_crypto\t\tcrypto[QUIC_CRYPTO_MAX];\n };\n \n struct quic6_sock {\n@@ -112,6 +114,11 @@ static inline struct quic_pnspace *quic_pnspace(const struct sock *sk, u8 level)\n \treturn &quic_sk(sk)->space[level % QUIC_CRYPTO_EARLY];\n }\n \n+static inline struct quic_crypto *quic_crypto(const struct sock *sk, u8 level)\n+{\n+\treturn &quic_sk(sk)->crypto[level];\n+}\n+\n static inline bool quic_is_establishing(struct sock *sk)\n {\n \treturn sk->sk_state == QUIC_SS_ESTABLISHING;\n", "prefixes": [ "net-next", "v11", "11/15" ] }