Jiri Slaby 2d5821
From: Scott Dial <scott@scottdial.com>
Jiri Slaby 2d5821
Date: Fri, 24 Apr 2020 18:51:08 -0400
Jiri Slaby 2d5821
Subject: net: macsec: preserve ingress frame ordering
Jiri Slaby 2d5821
Git-commit: ab046a5d4be4c90a3952a0eae75617b49c0cb01b
Jiri Slaby 2d5821
Patch-mainline: 5.7-rc5
Jiri Slaby 2d5821
References: networking-stable-20_05_12
Jiri Slaby 2d5821
Jiri Slaby 2d5821
MACsec decryption always occurs in a softirq context. Since
Jiri Slaby 2d5821
the FPU may not be usable in the softirq context, the call to
Jiri Slaby 2d5821
decrypt may be scheduled on the cryptd work queue. The cryptd
Jiri Slaby 2d5821
work queue does not provide ordering guarantees. Therefore,
Jiri Slaby 2d5821
preserving order requires masking out ASYNC implementations
Jiri Slaby 2d5821
of gcm(aes).
Jiri Slaby 2d5821
Jiri Slaby 2d5821
For instance, an Intel CPU with AES-NI makes available the
Jiri Slaby 2d5821
generic-gcm-aesni driver from the aesni_intel module to
Jiri Slaby 2d5821
implement gcm(aes). However, this implementation requires
Jiri Slaby 2d5821
the FPU, so it is not always available to use from a softirq
Jiri Slaby 2d5821
context, and will fallback to the cryptd work queue, which
Jiri Slaby 2d5821
does not preserve frame ordering. With this change, such a
Jiri Slaby 2d5821
system would select gcm_base(ctr(aes-aesni),ghash-generic).
Jiri Slaby 2d5821
While the aes-aesni implementation prefers to use the FPU, it
Jiri Slaby 2d5821
will fallback to the aes-asm implementation if unavailable.
Jiri Slaby 2d5821
Jiri Slaby 2d5821
By using a synchronous version of gcm(aes), the decryption
Jiri Slaby 2d5821
will complete before returning from crypto_aead_decrypt().
Jiri Slaby 2d5821
Therefore, the macsec_decrypt_done() callback will be called
Jiri Slaby 2d5821
before returning from macsec_decrypt(). Thus, the order of
Jiri Slaby 2d5821
calls to macsec_post_decrypt() for the frames is preserved.
Jiri Slaby 2d5821
Jiri Slaby 2d5821
While it's presumable that the pure AES-NI version of gcm(aes)
Jiri Slaby 2d5821
is more performant, the hybrid solution is capable of gigabit
Jiri Slaby 2d5821
speeds on modest hardware. Regardless, preserving the order
Jiri Slaby 2d5821
of frames is paramount for many network protocols (e.g.,
Jiri Slaby 2d5821
triggering TCP retries). Within the MACsec driver itself, the
Jiri Slaby 2d5821
replay protection is tripped by the out-of-order frames, and
Jiri Slaby 2d5821
can cause frames to be dropped.
Jiri Slaby 2d5821
Jiri Slaby 2d5821
This bug has been present in this code since it was added in
Jiri Slaby 2d5821
v4.6, however it may not have been noticed since not all CPUs
Jiri Slaby 2d5821
have FPU offload available. Additionally, the bug manifests
Jiri Slaby 2d5821
as occasional out-of-order packets that are easily
Jiri Slaby 2d5821
misattributed to other network phenomena.
Jiri Slaby 2d5821
Jiri Slaby 2d5821
When this code was added in v4.6, the crypto/gcm.c code did
Jiri Slaby 2d5821
not restrict selection of the ghash function based on the
Jiri Slaby 2d5821
ASYNC flag. For instance, x86 CPUs with PCLMULQDQ would
Jiri Slaby 2d5821
select the ghash-clmulni driver instead of ghash-generic,
Jiri Slaby 2d5821
which submits to the cryptd work queue if the FPU is busy.
Jiri Slaby 2d5821
However, this bug was was corrected in v4.8 by commit
Jiri Slaby 2d5821
b30bdfa86431afbafe15284a3ad5ac19b49b88e3, and was backported
Jiri Slaby 2d5821
all the way back to the v3.14 stable branch, so this patch
Jiri Slaby 2d5821
should be applicable back to the v4.6 stable branch.
Jiri Slaby 2d5821
Jiri Slaby 2d5821
Signed-off-by: Scott Dial <scott@scottdial.com>
Jiri Slaby 2d5821
Signed-off-by: David S. Miller <davem@davemloft.net>
Jiri Slaby 2d5821
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Jiri Slaby 2d5821
---
Jiri Slaby 2d5821
 drivers/net/macsec.c |    3 ++-
Jiri Slaby 2d5821
 1 file changed, 2 insertions(+), 1 deletion(-)
Jiri Slaby 2d5821
Jiri Slaby 2d5821
--- a/drivers/net/macsec.c
Jiri Slaby 2d5821
+++ b/drivers/net/macsec.c
Jiri Slaby 2d5821
@@ -1312,7 +1312,8 @@ static struct crypto_aead *macsec_alloc_
Jiri Slaby 2d5821
 	struct crypto_aead *tfm;
Jiri Slaby 2d5821
 	int ret;
Jiri Slaby 2d5821
 
Jiri Slaby 2d5821
-	tfm = crypto_alloc_aead("gcm(aes)", 0, 0);
Jiri Slaby 2d5821
+	/* Pick a sync gcm(aes) cipher to ensure order is preserved. */
Jiri Slaby 2d5821
+	tfm = crypto_alloc_aead("gcm(aes)", 0, CRYPTO_ALG_ASYNC);
Jiri Slaby 2d5821
 
Jiri Slaby 2d5821
 	if (IS_ERR(tfm))
Jiri Slaby 2d5821
 		return tfm;