From: Eric Biggers Date: Wed, 18 Feb 2026 21:35:00 +0000 (-0800) Subject: wifi: mac80211: Use AES-CMAC library in ieee80211_aes_cmac() X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=c9de7246d5422bbea5374a402e761cf7725a263e;p=thirdparty%2Fkernel%2Flinux.git wifi: mac80211: Use AES-CMAC library in ieee80211_aes_cmac() Now that AES-CMAC has a library API, convert the mac80211 AES-CMAC packet authentication code to use it instead of a "cmac(aes)" crypto_shash. This has multiple benefits, such as: - It's faster. The AES-CMAC code is now called directly, without unnecessary overhead such as indirect calls. - MAC calculation can no longer fail. - The AES-CMAC key struct is now a fixed size, allowing it to be embedded directly into 'struct ieee80211_key' rather than using a separate allocation. Note that although this increases the size of the 'u.cmac' field of 'struct ieee80211_key', it doesn't cause it to exceed the size of the largest variant of the union 'u'. Therefore, the size of 'struct ieee80211_key' itself is unchanged. Acked-by: Johannes Berg Reviewed-by: Ard Biesheuvel Link: https://lore.kernel.org/r/20260218213501.136844-15-ebiggers@kernel.org Signed-off-by: Eric Biggers --- diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index cf0f7780fb109..0afbe4f4f9764 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig @@ -3,6 +3,7 @@ config MAC80211 tristate "Generic IEEE 802.11 Networking Stack (mac80211)" depends on CFG80211 select CRYPTO + select CRYPTO_LIB_AES_CBC_MACS select CRYPTO_LIB_ARC4 select CRYPTO_AES select CRYPTO_CCM diff --git a/net/mac80211/aes_cmac.c b/net/mac80211/aes_cmac.c index 0827965455dc0..55b674ad7d7a4 100644 --- a/net/mac80211/aes_cmac.c +++ b/net/mac80211/aes_cmac.c @@ -7,10 +7,9 @@ #include #include -#include #include #include -#include +#include #include #include "key.h" @@ -20,65 +19,25 @@ static const u8 zero[IEEE80211_CMAC_256_MIC_LEN]; -int ieee80211_aes_cmac(struct crypto_shash *tfm, const u8 *aad, - const u8 *data, size_t data_len, u8 *mic, - unsigned int mic_len) +void ieee80211_aes_cmac(const struct aes_cmac_key *key, const u8 *aad, + const u8 *data, size_t data_len, u8 *mic, + unsigned int mic_len) { - int err; - SHASH_DESC_ON_STACK(desc, tfm); + struct aes_cmac_ctx ctx; u8 out[AES_BLOCK_SIZE]; const __le16 *fc; - desc->tfm = tfm; - - err = crypto_shash_init(desc); - if (err) - return err; - err = crypto_shash_update(desc, aad, AAD_LEN); - if (err) - return err; + aes_cmac_init(&ctx, key); + aes_cmac_update(&ctx, aad, AAD_LEN); fc = (const __le16 *)aad; if (ieee80211_is_beacon(*fc)) { /* mask Timestamp field to zero */ - err = crypto_shash_update(desc, zero, 8); - if (err) - return err; - err = crypto_shash_update(desc, data + 8, - data_len - 8 - mic_len); - if (err) - return err; + aes_cmac_update(&ctx, zero, 8); + aes_cmac_update(&ctx, data + 8, data_len - 8 - mic_len); } else { - err = crypto_shash_update(desc, data, data_len - mic_len); - if (err) - return err; + aes_cmac_update(&ctx, data, data_len - mic_len); } - err = crypto_shash_finup(desc, zero, mic_len, out); - if (err) - return err; + aes_cmac_update(&ctx, zero, mic_len); + aes_cmac_final(&ctx, out); memcpy(mic, out, mic_len); - - return 0; -} - -struct crypto_shash *ieee80211_aes_cmac_key_setup(const u8 key[], - size_t key_len) -{ - struct crypto_shash *tfm; - - tfm = crypto_alloc_shash("cmac(aes)", 0, 0); - if (!IS_ERR(tfm)) { - int err = crypto_shash_setkey(tfm, key, key_len); - - if (err) { - crypto_free_shash(tfm); - return ERR_PTR(err); - } - } - - return tfm; -} - -void ieee80211_aes_cmac_key_free(struct crypto_shash *tfm) -{ - crypto_free_shash(tfm); } diff --git a/net/mac80211/aes_cmac.h b/net/mac80211/aes_cmac.h index 5f971a8298cbe..c7a6df47b3271 100644 --- a/net/mac80211/aes_cmac.h +++ b/net/mac80211/aes_cmac.h @@ -6,14 +6,10 @@ #ifndef AES_CMAC_H #define AES_CMAC_H -#include -#include +#include -struct crypto_shash *ieee80211_aes_cmac_key_setup(const u8 key[], - size_t key_len); -int ieee80211_aes_cmac(struct crypto_shash *tfm, const u8 *aad, - const u8 *data, size_t data_len, u8 *mic, - unsigned int mic_len); -void ieee80211_aes_cmac_key_free(struct crypto_shash *tfm); +void ieee80211_aes_cmac(const struct aes_cmac_key *key, const u8 *aad, + const u8 *data, size_t data_len, u8 *mic, + unsigned int mic_len); #endif /* AES_CMAC_H */ diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 04c8809173d7f..4b8965633df34 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -690,10 +690,9 @@ ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, * Initialize AES key state here as an optimization so that * it does not need to be initialized for every packet. */ - key->u.aes_cmac.tfm = - ieee80211_aes_cmac_key_setup(key_data, key_len); - if (IS_ERR(key->u.aes_cmac.tfm)) { - err = PTR_ERR(key->u.aes_cmac.tfm); + err = aes_cmac_preparekey(&key->u.aes_cmac.key, key_data, + key_len); + if (err) { kfree(key); return ERR_PTR(err); } @@ -750,10 +749,6 @@ static void ieee80211_key_free_common(struct ieee80211_key *key) case WLAN_CIPHER_SUITE_CCMP_256: ieee80211_aes_key_free(key->u.ccmp.tfm); break; - case WLAN_CIPHER_SUITE_AES_CMAC: - case WLAN_CIPHER_SUITE_BIP_CMAC_256: - ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm); - break; case WLAN_CIPHER_SUITE_BIP_GMAC_128: case WLAN_CIPHER_SUITE_BIP_GMAC_256: ieee80211_aes_gmac_key_free(key->u.aes_gmac.tfm); diff --git a/net/mac80211/key.h b/net/mac80211/key.h index 1fa0f4f78962e..826e4e9387c55 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -93,7 +94,7 @@ struct ieee80211_key { } ccmp; struct { u8 rx_pn[IEEE80211_CMAC_PN_LEN]; - struct crypto_shash *tfm; + struct aes_cmac_key key; u32 replays; /* dot11RSNAStatsCMACReplays */ u32 icverrors; /* dot11RSNAStatsCMACICVErrors */ } aes_cmac; diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index fdf98c21d32c0..59324b367bddc 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -872,11 +872,8 @@ ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx, bip_aad(skb, aad); - if (ieee80211_aes_cmac(key->u.aes_cmac.tfm, aad, - skb->data + 24, skb->len - 24, - mmie->mic, mic_len)) - return TX_DROP; - + ieee80211_aes_cmac(&key->u.aes_cmac.key, aad, skb->data + 24, + skb->len - 24, mmie->mic, mic_len); return TX_CONTINUE; } @@ -918,10 +915,8 @@ ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx, if (!(status->flag & RX_FLAG_DECRYPTED)) { /* hardware didn't decrypt/verify MIC */ bip_aad(skb, aad); - if (ieee80211_aes_cmac(key->u.aes_cmac.tfm, aad, - skb->data + 24, skb->len - 24, - mic, mic_len)) - return RX_DROP_U_DECRYPT_FAIL; + ieee80211_aes_cmac(&key->u.aes_cmac.key, aad, skb->data + 24, + skb->len - 24, mic, mic_len); if (crypto_memneq(mic, mmie->mic, mic_len)) { key->u.aes_cmac.icverrors++; return RX_DROP_U_MIC_FAIL;