From: "Jérémy Jean" <jeremy.jean@oss.cyber.gouv.fr>
To: netdev-bot+sashiko@kernel.org
Cc: sd@queasysnail.net, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org, stable@vger.kernel.org,
kuba@kernel.org
Subject: Re: [PATCH net] macsec: prevent AES-GCM nonce reuse after packet number wrap
Date: Fri, 02 Oct 2026 17:22:26 +0200 [thread overview]
Message-ID: <5a337607032eaf65e513af47177bc755@oss.cyber.gouv.fr> (raw)
In-Reply-To: <179094094507.434549.10343867236114211128@kernel.org>
On 2026-10-02 13:35, netdev-bot+sashiko@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential
> issue(s) to consider.
>
> Critical: 0 · High: 0 · Medium: 1 · Low: 0
>
> 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 code change is correct.
>
> --
>
> macsec: prevent AES-GCM nonce reuse after packet number wrap
>
> With 32-bit packet numbers, the TX SA wraps next_pn to zero after
> allocating 0xffffffff. tx_sa_update_pn() used to advance the counter
> past zero, so later frames could reuse PN 1, 2, ... under the same key.
> This patch makes tx_sa_update_pn() return early when the stored PN is
> zero, so next_pn stays at zero after a wrap.
>
>> diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
>> index 78a19b1346321..233391acebb0f 100644
>> --- a/drivers/net/macsec.c
>> +++ b/drivers/net/macsec.c
>> @@ -486,6 +486,9 @@ static pn_t tx_sa_update_pn(struct macsec_tx_sa
>> *tx_sa,
>> spin_lock_bh(&tx_sa->lock);
>>
>> pn = tx_sa->next_pn_halves;
>> + if (unlikely(pn.full64 == 0))
>> + goto out;
>> +
>
> [Severity: Medium]
> The code change looks right. The commit message may describe less than
> the patch actually fixes and changes, though. It says:
>
> Packets already in flight can still be processed after that.
> [ ... ]
> Keep next_pn at zero after wrap so all late packets are dropped.
>
> Is late in-flight packets the only way to hit the nonce reuse? A
> wrapped
> SA can also be reactivated from userspace without a new PN. In
> macsec_upd_txsa(), MACSEC_SA_ATTR_PN is optional:
>
> drivers/net/macsec.c:macsec_upd_txsa() {
> ...
> if (tb_sa[MACSEC_SA_ATTR_ACTIVE])
> tx_sa->active = nla_get_u8(tb_sa[MACSEC_SA_ATTR_ACTIVE]);
>
> was_operational = secy->operational;
> if (assoc_num == tx_sc->encoding_sa)
> secy->operational = tx_sa->active;
> ...
> }
>
> macsec_start_xmit() only checks secy->operational. macsec_encrypt()
> never checks tx_sa->active, and its only guard is the PN check:
>
> drivers/net/macsec.c:macsec_encrypt() {
> ...
> pn = tx_sa_update_pn(tx_sa, secy);
> if (pn.full64 == 0) {
> macsec_txsa_put(tx_sa);
> kfree_skb(skb);
> return ERR_PTR(-ENOLINK);
> }
> ...
> }
>
> Before this patch, the first frame after an UPD_TXSA that only sets
> ACTIVE would get PN 0 and be dropped. Every frame after it would go out
> with PN 1, 2, 3 ... under the same key and salt, for as long as the SA
> stayed in use. That is sustained nonce reuse, not a short race window.
> Should the commit message mention this path, especially since the patch
> is tagged for stable?
>
> There is also a user-visible behaviour change here. After this patch,
> reactivating a wrapped SA without a new PN drops every frame and counts
> it in tx_dropped. The goto out also skips __macsec_pn_wrapped(), so
> nothing clears tx_sa->active or secy->operational again. The SA and
> SecY keep reporting active and operational while all TX is dropped,
> until a new PN or SA is installed.
>
> Could the commit message document this as well?
>
>> if (secy->xpn)
>> tx_sa->next_pn++;
>> else
>
> [ ... ]
AFAICT, sashiko is partly right. Reactivating the SA after PN wrap
without a PN update could indeed also lead to nonce reuse: before the
fix, the counter could advance from 0 to 1. Yet, the security fix
provided in the diff is the correct one: further PN allocations return
0 and the corresponding packets are dropped. However, I believe that
the statement "macsec_encrypt() never checks tx_sa->active" is
misleading: the check is performed in macsec_txsa_get(), which is
called by macsec_encrypt(), but reactivation makes that check pass.
The observation about active and operational remaining true after
reactivation is also correct, although packets are dropped because
next_pn remains 0.
Here is a rewording of the final part that should cover the comment:
---
After allocating the last valid packet number, MACsec wraps next_pn to
zero and deactivates the transmit SA. This happens for both 32- and
64-bit types of packet numbers (at values 0xffffffff and
0xffffffffffffffff, respectively).
TX packets that were still getting processed during deactivation keep
being processed and then receive packet numbers. The first gets 0 and
is correctly dropped, but next_pn is incremented to 1, which makes the
next packet take number 1. It then does not get dropped and may induce
a reuse of the AES-GCM nonce corresponding to value 1.
This race affects TX packets that have already passed the SA activity
check: packets that observe the inactive SA are correctly dropped.
Reactivating the SA after PN wrap without a packet number can also
cause nonce reuse. Keep next_pn at 0 after wrap, even if the SA is
reactivated, so further packet number allocations return 0 and the
corresponding packets are dropped.
---
Please tell me whether I should submit this as a v2.
Jérémy
next prev parent reply other threads:[~2026-10-02 15:22 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-30 20:33 [PATCH net] macsec: prevent AES-GCM nonce reuse after packet number wrap Jérémy Jean
2026-09-30 20:38 ` netdev-bot+sinfo
2026-10-01 9:43 ` Sabrina Dubroca
2026-10-01 15:08 ` Jérémy Jean
2026-10-02 11:35 ` netdev-bot+sashiko
2026-10-02 15:22 ` Jérémy Jean [this message]
2026-10-08 0:07 ` Jakub Kicinski
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=5a337607032eaf65e513af47177bc755@oss.cyber.gouv.fr \
--to=jeremy.jean@oss.cyber.gouv.fr \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev-bot+sashiko@kernel.org \
--cc=netdev@vger.kernel.org \
--cc=sd@queasysnail.net \
--cc=stable@vger.kernel.org \
/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