Linux CIFS filesystem development
 help / color / mirror / Atom feed
From: netdev-bot+sashiko@kernel.org
To: lucien.xin@gmail.com
Cc: netdev@vger.kernel.org, quic@lists.linux.dev,
	davem@davemloft.net, kuba@kernel.org, edumazet@google.com,
	pabeni@redhat.com, horms@kernel.org, metze@samba.org,
	mbuhl@openbsd.org, tfanelli@redhat.com, hepengtao@xiaomi.com,
	dreibh@simula.no, linux-cifs@vger.kernel.org, pc@manguebit.org,
	linkinjeon@kernel.org, tom@talpey.com,
	kernel-tls-handshake@lists.linux.dev, chuck.lever@oracle.com,
	jlayton@kernel.org, steved@redhat.com, hare@suse.de,
	aahringo@redhat.com, dhowells@redhat.com, matttbe@kernel.org,
	mail@johnericson.me, xiyou.wangcong@gmail.com,
	alibuda@linux.alibaba.com, jbaron@akamai.com,
	illiliti@protonmail.com, sd@queasysnail.net,
	marcelo.leitner@gmail.com, daniel@haxx.se,
	andrew.gospodarek@broadcom.com, mef@scarletmail.rutgers.edu,
	paul@jakma.org, kuniyu@google.com
Subject: Re: [PATCH net-next v16 12/15] quic: add crypto packet encryption and decryption
Date: Wed, 07 Oct 2026 01:05:23 +0000	[thread overview]
Message-ID: <179133512379.434549.1011079085204348692@kernel.org> (raw)
In-Reply-To: <4dc3c5117810571e41211781bd0280510460e4da.1791227050.git.lucien.xin@gmail.com>

Thank you for your contribution! Sashiko AI review found 5 potential
issue(s) to consider.

Critical: 0 · High: 0 · Medium: 2 · Low: 3

If you believe none of the issues are legitimate, please reply to each
issue of Medium severity or higher and explain why the AI is wrong.
If any of them are legitimate and you plan to respin, please let patchwork
know by including "pw-bot: cr" as a separate line at the end of your reply
(one such reply per series is enough).

- [Medium] The AEAD integrity limit that this patch enforces does not
  count failures across the whole connection, as RFC 9001 §6.6 requires.
- [Medium] quic_crypto_generate_token() writes the raw 64-bit
  quic_ktime_get_us() timestamp (ktime_get(), i.e. CLOCK_MONOTONIC in µs…
- [Low] The kernel-doc of quic_crypto_verify_token() says "Return: 0 if
  the token is valid, -EINVAL if invalid, or another negative error…
- [Low] quic_crypto_decrypt() counts every non-EINPROGRESS failure of
  quic_crypto_payload_protect() toward the AEAD integrity limit, not…
- [Low] async_pending[] is used as a quiescence check before re-keying a
  tfm, but both sides use unordered atomics.

--

quic: add crypto packet encryption and decryption

This patch adds AEAD payload protection and QUIC header protection for
TX and RX via quic_crypto_encrypt() and quic_crypto_decrypt(). It also
adds helpers to compute the Retry integrity tag, and to generate and
verify Retry/address validation tokens.

> diff --git a/net/quic/crypto.c b/net/quic/crypto.c
> index 4bb6acea5112a..fa326cc9266a8 100644
> --- a/net/quic/crypto.c
> +++ b/net/quic/crypto.c
> @@ -270,6 +271,484 @@ ciphers[QUIC_CIPHER_MAX + 1 - QUIC_CIPHER_MIN] = {

[ ... ]

> +int quic_crypto_decrypt(struct quic_crypto *crypto, struct sk_buff *skb,
> +			gfp_t gfp)
> +{

[ ... ]

> +	phase = cb->key_phase;
> +	if (phase != crypto->key_phase && !crypto->key_pending) {
> +		if (!crypto->send_ready) /* Not ready for key update. */
> +			return -EINVAL;
> +		if (!cb->backlog) /* Key update requires process context. */
> +			return -EKEYREVOKED;
> +		/* Cannot do key update while async crypto is in progress. */
> +		if (unlikely(atomic_read(&crypto->async_pending[phase])))
> +			return -EBUSY;
> +		err = quic_crypto_key_update(crypto); /* Perform key update. */

[Severity: Low]
Is the ordering here strong enough for async_pending[] to work as a
quiescence check before re-keying?

quic_crypto_done() signals completion with a plain atomic_dec(). Per
Documentation/atomic_t.txt, that operation is unordered:

    atomic_dec(&crypto->async_pending[cb->key_phase]);

This side reads the counter with a relaxed atomic_read(). When it sees 0,
it calls quic_crypto_key_update(), which rewrites the key schedule through
crypto_aead_setkey().

Nothing orders the completing CPU's loads of the key schedule during the
AEAD operation before its decrement. The socket lock does not cover this,
because the decrement happens before cb->crypto_done() takes the lock
again.

On weakly ordered architectures, can the re-keying CPU see 0 and overwrite
the key while the completing request's reads are still unordered? Would
atomic_dec_return_release(), or smp_mb__before_atomic() plus atomic_dec(),
in quic_crypto_done() paired with atomic_read_acquire() here be needed?

> +		if (err) {
> +			cb->errcode = QUIC_TRANSPORT_ERROR_KEY_UPDATE;
> +			return err;
> +		}
> +		cb->sync = 1;
> +		cb->key_update = 1; /* Mark packet as triggering key update. */
> +	}
> +
> +	err = quic_crypto_payload_protect(crypto, skb, false, gfp);
> +	if (err) {
> +		if (err == -EINPROGRESS)
> +			return err;
> +		/* When using the old keys can not decrypt the packets, the
> +		 * peer might start another key_update. Thus, clear the last
> +		 * key_pending so that next packets will trigger the new
> +		 * key-update.
> +		 */
> +		if (crypto->key_pending && phase != crypto->key_phase) {
> +			crypto->key_pending = 0;
> +			crypto->key_update_time = 0;
> +			crypto->key_update_send_time = 0;
> +		}
> +		goto err;
> +	}

[Severity: Low]
Should every quic_crypto_payload_protect() failure count toward the AEAD
integrity limit?

All of these reach the err label and increment rx_fails[cb->key_phase]:

  - -ENOMEM from quic_crypto_aead_mem_alloc()
  - a negative skb_to_sgvec() result
  - on the resume path, any async engine error delivered in
    cb->crypto_err

RFC 9001 section 6.6 counts only received packets that fail
authentication.

Under sustained allocation failure, could a legitimate connection end up
with -EKEYEXPIRED (AEAD_LIMIT_REACHED) instead of just dropping packets?

[ ... ]

> +	return 0;
> +err:
> +	if (++crypto->rx_fails[cb->key_phase] >= crypto->cipher->rxlimit)
> +		err = -EKEYEXPIRED;
> +	return err;
> +}

[Severity: Medium]
Does this enforce the integrity limit across the whole connection, as
RFC 9001 section 6.6 requires?

The comment on the QUIC_AEAD_RX_* constants cites that section. It says
endpoints MUST count packets that fail authentication during the lifetime
of a connection, across all keys.

Two things seem to weaken the limit here.

First, cb->key_phase comes from the key bit after header protection is
removed, and the packet has not been authenticated yet. Forged
short-header packets therefore spread across both rx_fails[] slots, which
allows about 2 * rxlimit forgeries.

Second, quic_crypto_keys_derive_and_install() resets the slot on every RX
key install. That includes each key update reached through
quic_crypto_decrypt()->quic_crypto_key_update():

net/quic/crypto.c:quic_crypto_keys_derive_and_install() {
    ...
	if (rx) {
		crypto->rx_fails[phase] = 0;
    ...
}

For AES-CCM (rxlimit 2965820, about 2^21.5), an off-path sender would get
roughly (2 + number of key updates) * rxlimit forgery attempts.

Would a single connection-wide failure counter, not indexed by key phase
and not reset on key install, be more appropriate? tx_count could stay
per key.

[ ... ]

> @@ -560,6 +1039,234 @@ int quic_crypto_initial_keys_install(struct quic_crypto *crypto,

[ ... ]

> +int quic_crypto_generate_token(struct quic_crypto *crypto, void *addr,
> +			       u32 addrlen, struct quic_conn_id *conn_id,
> +			       u8 *token, u32 *tlen)
> +{
> +	u8 *token_buf, *p, flag = *token;
> +	u64 ts = quic_ktime_get_us();
> +	u32 len, tslen = sizeof(ts);
> +	int err;
> +
> +	len = sizeof(flag) + addrlen + tslen + conn_id->len + QUIC_TAG_LEN;
> +	token_buf = kmalloc(len, GFP_KERNEL);
> +	if (!token_buf)
> +		return -ENOMEM;
> +
> +	p = token_buf;
> +	p = quic_put_int(p, flag, sizeof(flag));
> +	p = quic_put_data(p, addr, addrlen);
> +	p = quic_put_int(p, ts, tslen);
> +	quic_put_data(p, conn_id->data, conn_id->len);

[Severity: Medium]
Does this expose the server's uptime to any client that receives a token?

ts is the raw ktime_get() value, in microseconds since boot.
quic_crypto_token_protect() only authenticates the flag, address and
timestamp as associated data. It does not encrypt them:

	aead_request_set_ad(req, adlen);
	aead_request_set_crypt(req, sg, sg, len - adlen - extra, nonce);

Tokens are sent to unauthenticated clients in Retry packets and NEW_TOKEN
frames, so the monotonic clock can be read from them in plaintext. TCP
avoids a similar leak with per-connection timestamp offsets
(secure_tcp_ts_off).

The v14 change moved the timestamp from the encrypted part into the AAD
so it could be used for the nonce. That change appears to have introduced
this exposure.

The serialized address is also sent in plaintext. For IPv6,
quic_v6_get_msg_addrs() in net/quic/family.c sets:

	sa->v6.sin6_scope_id = skb->skb_iif;

Would the server's ingress ifindex end up in the token as well?

[ ... ]

> +/* Validate a Retry or address validation token.
> + *
> + * Decrypts and authenticates the token, checks the client address and validates
> + * the timestamp against the timeout selected by the token flag. For a Retry
> + * token, extracts the original destination connection ID.
> + *
> + * Return: 0 if the token is valid, -EINVAL if invalid, or another negative
> + * error code.
> + */
> +int quic_crypto_verify_token(struct quic_crypto *crypto, void *addr,
> +			     u32 addrlen, struct quic_conn_id *conn_id,
> +			     u8 *token, u32 len)
> +{

[ ... ]

> +	err = quic_crypto_token_protect(crypto, token_buf, len,
> +					sizeof(flag) + addrlen + tslen, false);
> +	if (err)
> +		goto out;
> +
> +	err = -EINVAL;

[Severity: Low]
The kernel-doc says -EINVAL is returned for an invalid token. Does a
forged or tampered token actually return -EINVAL?

A tag mismatch makes crypto_aead_decrypt() return -EBADMSG. That value is
returned unchanged through the goto out above, before err is set to
-EINVAL. A token key that was never set would give -ENOKEY in the same
way.

Only the length precheck and the address, timestamp and ODCID length
checks return -EINVAL.

Should the comment be updated, or should authentication failures be
mapped to -EINVAL?

-- 
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/cover.1791227050.git.lucien.xin%40gmail.com

         reply	other threads:[~2026-10-07  1:05 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-05 19:03 [PATCH net-next v16 00/15] net: introduce QUIC infrastructure and core subcomponents Xin Long
2026-10-05 19:03 ` [PATCH net-next v16 01/15] net: define IPPROTO_QUIC and SOL_QUIC constants Xin Long
2026-10-05 19:03 ` [PATCH net-next v16 02/15] net: build socket infrastructure for QUIC protocol Xin Long
2026-10-05 19:03 ` [PATCH net-next v16 03/15] quic: provide common utilities and data structures Xin Long
2026-10-05 19:03 ` [PATCH net-next v16 04/15] quic: provide family ops for address and protocol Xin Long
2026-10-07  1:05   ` netdev-bot+sashiko
2026-10-07 18:41     ` Xin Long
2026-10-09  1:18     ` Xin Long
2026-10-05 19:04 ` [PATCH net-next v16 05/15] quic: provide quic.h header files for kernel and userspace Xin Long
2026-10-05 19:04 ` [PATCH net-next v16 06/15] quic: add stream management Xin Long
2026-10-07  1:05   ` netdev-bot+sashiko
2026-10-09  1:28     ` Xin Long
2026-10-05 19:04 ` [PATCH net-next v16 07/15] quic: add connection id management Xin Long
2026-10-05 19:04 ` [PATCH net-next v16 08/15] quic: add path management Xin Long
2026-10-07  1:05   ` netdev-bot+sashiko
2026-10-07 19:11     ` Xin Long
2026-10-09  1:37     ` Xin Long
2026-10-05 19:04 ` [PATCH net-next v16 09/15] quic: add congestion control Xin Long
2026-10-07  1:05   ` netdev-bot+sashiko
2026-10-09  1:42     ` Xin Long
2026-10-05 19:04 ` [PATCH net-next v16 10/15] quic: add packet number space Xin Long
2026-10-05 19:04 ` [PATCH net-next v16 11/15] quic: add crypto key derivation and installation Xin Long
2026-10-07  1:05   ` netdev-bot+sashiko
2026-10-09  1:44     ` Xin Long
2026-10-05 19:04 ` [PATCH net-next v16 12/15] quic: add crypto packet encryption and decryption Xin Long
2026-10-07  1:05   ` netdev-bot+sashiko [this message]
2026-10-09  1:48     ` Xin Long
2026-10-05 19:04 ` [PATCH net-next v16 13/15] quic: add timer management Xin Long
2026-10-05 19:04 ` [PATCH net-next v16 14/15] quic: add packet builder base Xin Long
2026-10-05 19:04 ` [PATCH net-next v16 15/15] quic: add packet parser base Xin Long
2026-10-07  1:05   ` netdev-bot+sashiko
2026-10-09  1:55     ` Xin Long
2026-10-07 19:19 ` [PATCH net-next v16 00/15] net: introduce QUIC infrastructure and core subcomponents Xin Long

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=179133512379.434549.1011079085204348692@kernel.org \
    --to=netdev-bot+sashiko@kernel.org \
    --cc=aahringo@redhat.com \
    --cc=alibuda@linux.alibaba.com \
    --cc=andrew.gospodarek@broadcom.com \
    --cc=chuck.lever@oracle.com \
    --cc=daniel@haxx.se \
    --cc=davem@davemloft.net \
    --cc=dhowells@redhat.com \
    --cc=dreibh@simula.no \
    --cc=edumazet@google.com \
    --cc=hare@suse.de \
    --cc=hepengtao@xiaomi.com \
    --cc=horms@kernel.org \
    --cc=illiliti@protonmail.com \
    --cc=jbaron@akamai.com \
    --cc=jlayton@kernel.org \
    --cc=kernel-tls-handshake@lists.linux.dev \
    --cc=kuba@kernel.org \
    --cc=kuniyu@google.com \
    --cc=linkinjeon@kernel.org \
    --cc=linux-cifs@vger.kernel.org \
    --cc=lucien.xin@gmail.com \
    --cc=mail@johnericson.me \
    --cc=marcelo.leitner@gmail.com \
    --cc=matttbe@kernel.org \
    --cc=mbuhl@openbsd.org \
    --cc=mef@scarletmail.rutgers.edu \
    --cc=metze@samba.org \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=paul@jakma.org \
    --cc=pc@manguebit.org \
    --cc=quic@lists.linux.dev \
    --cc=sd@queasysnail.net \
    --cc=steved@redhat.com \
    --cc=tfanelli@redhat.com \
    --cc=tom@talpey.com \
    --cc=xiyou.wangcong@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox