]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: mac80211: refactor CMAC packet handlers
authorChien Wong <m@xv97.com>
Thu, 13 Nov 2025 14:05:11 +0000 (22:05 +0800)
committerJohannes Berg <johannes.berg@intel.com>
Thu, 20 Nov 2025 10:56:19 +0000 (11:56 +0100)
Merge CMAC-128 and CMAC-256 handlers since they are almost the same.
This removes duplication.

The comment 'MIC = AES-128-CMAC(IGTK, AAD ...' is out-dated since CMAC
is also used with BIGTK, as is the comment for CMAC-256. Simply remove
the comments.

Tested-on: mac80211_hwsim

Signed-off-by: Chien Wong <m@xv97.com>
Link: https://patch.msgid.link/20251113140511.48658-6-m@xv97.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/rx.c
net/mac80211/tx.c
net/mac80211/wpa.c
net/mac80211/wpa.h

index cc26c279984d748f77f54add32655e4414213886..6a1899512d07875c5eb436e98d82e40f683015fa 100644 (file)
@@ -2215,10 +2215,12 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
                        rx, IEEE80211_CCMP_256_MIC_LEN);
                break;
        case WLAN_CIPHER_SUITE_AES_CMAC:
-               result = ieee80211_crypto_aes_cmac_decrypt(rx);
+               result = ieee80211_crypto_aes_cmac_decrypt(
+                       rx, IEEE80211_CMAC_128_MIC_LEN);
                break;
        case WLAN_CIPHER_SUITE_BIP_CMAC_256:
-               result = ieee80211_crypto_aes_cmac_256_decrypt(rx);
+               result = ieee80211_crypto_aes_cmac_decrypt(
+                       rx, IEEE80211_CMAC_256_MIC_LEN);
                break;
        case WLAN_CIPHER_SUITE_BIP_GMAC_128:
        case WLAN_CIPHER_SUITE_BIP_GMAC_256:
index e7b141c55f7a900964b15e72686544328d240bc3..9d8b0a25f73c34baefc5a06d453d4f562d8d25da 100644 (file)
@@ -1062,9 +1062,11 @@ ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx)
                return ieee80211_crypto_ccmp_encrypt(
                        tx, IEEE80211_CCMP_256_MIC_LEN);
        case WLAN_CIPHER_SUITE_AES_CMAC:
-               return ieee80211_crypto_aes_cmac_encrypt(tx);
+               return ieee80211_crypto_aes_cmac_encrypt(
+                       tx, IEEE80211_CMAC_128_MIC_LEN);
        case WLAN_CIPHER_SUITE_BIP_CMAC_256:
-               return ieee80211_crypto_aes_cmac_256_encrypt(tx);
+               return ieee80211_crypto_aes_cmac_encrypt(
+                       tx, IEEE80211_CMAC_256_MIC_LEN);
        case WLAN_CIPHER_SUITE_BIP_GMAC_128:
        case WLAN_CIPHER_SUITE_BIP_GMAC_256:
                return ieee80211_crypto_aes_gmac_encrypt(tx);
index 7431ccecd17f8c98e17bfa03a8dd82edbb9242d7..4a858112e4ef94f2160a00e8c34e3cd9c0c9690f 100644 (file)
@@ -828,12 +828,14 @@ static inline void bip_ipn_swap(u8 *d, const u8 *s)
 
 
 ieee80211_tx_result
-ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx)
+ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx,
+                                 unsigned int mic_len)
 {
        struct sk_buff *skb;
        struct ieee80211_tx_info *info;
        struct ieee80211_key *key = tx->key;
-       struct ieee80211_mmie *mmie;
+       struct ieee80211_mmie_var *mmie;
+       size_t mmie_len;
        u8 aad[20];
        u64 pn64;
 
@@ -848,62 +850,14 @@ ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx)
            !(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIE))
                return TX_CONTINUE;
 
-       if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie)))
-               return TX_DROP;
-
-       mmie = skb_put(skb, sizeof(*mmie));
-       mmie->element_id = WLAN_EID_MMIE;
-       mmie->length = sizeof(*mmie) - 2;
-       mmie->key_id = cpu_to_le16(key->conf.keyidx);
-
-       /* PN = PN + 1 */
-       pn64 = atomic64_inc_return(&key->conf.tx_pn);
-
-       bip_ipn_set64(mmie->sequence_number, pn64);
-
-       if (info->control.hw_key)
-               return TX_CONTINUE;
-
-       bip_aad(skb, aad);
-
-       /*
-        * MIC = AES-128-CMAC(IGTK, AAD || Management Frame Body || MMIE, 64)
-        */
-       if (ieee80211_aes_cmac(key->u.aes_cmac.tfm, aad,
-                              skb->data + 24, skb->len - 24, mmie->mic,
-                              IEEE80211_CMAC_128_MIC_LEN))
-               return TX_DROP;
-
-       return TX_CONTINUE;
-}
+       mmie_len = sizeof(*mmie) + mic_len;
 
-ieee80211_tx_result
-ieee80211_crypto_aes_cmac_256_encrypt(struct ieee80211_tx_data *tx)
-{
-       struct sk_buff *skb;
-       struct ieee80211_tx_info *info;
-       struct ieee80211_key *key = tx->key;
-       struct ieee80211_mmie_16 *mmie;
-       u8 aad[20];
-       u64 pn64;
-
-       if (WARN_ON(skb_queue_len(&tx->skbs) != 1))
+       if (WARN_ON(skb_tailroom(skb) < mmie_len))
                return TX_DROP;
 
-       skb = skb_peek(&tx->skbs);
-
-       info = IEEE80211_SKB_CB(skb);
-
-       if (info->control.hw_key &&
-           !(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIE))
-               return TX_CONTINUE;
-
-       if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie)))
-               return TX_DROP;
-
-       mmie = skb_put(skb, sizeof(*mmie));
+       mmie = skb_put(skb, mmie_len);
        mmie->element_id = WLAN_EID_MMIE;
-       mmie->length = sizeof(*mmie) - 2;
+       mmie->length = mmie_len - 2;
        mmie->key_id = cpu_to_le16(key->conf.keyidx);
 
        /* PN = PN + 1 */
@@ -916,90 +870,40 @@ ieee80211_crypto_aes_cmac_256_encrypt(struct ieee80211_tx_data *tx)
 
        bip_aad(skb, aad);
 
-       /* MIC = AES-256-CMAC(IGTK, AAD || Management Frame Body || MMIE, 128)
-        */
        if (ieee80211_aes_cmac(key->u.aes_cmac.tfm, aad,
-                              skb->data + 24, skb->len - 24, mmie->mic,
-                              IEEE80211_CMAC_256_MIC_LEN))
+                              skb->data + 24, skb->len - 24,
+                              mmie->mic, mic_len))
                return TX_DROP;
 
        return TX_CONTINUE;
 }
 
 ieee80211_rx_result
-ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx)
+ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx,
+                                 unsigned int mic_len)
 {
        struct sk_buff *skb = rx->skb;
        struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
        struct ieee80211_key *key = rx->key;
-       struct ieee80211_mmie *mmie;
-       u8 aad[20], mic[8], ipn[6];
+       struct ieee80211_mmie_var *mmie;
+       size_t mmie_len;
+       u8 aad[20], mic[IEEE80211_CMAC_256_MIC_LEN], ipn[6];
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
 
        if (!ieee80211_is_mgmt(hdr->frame_control))
                return RX_CONTINUE;
 
-       /* management frames are already linear */
-
-       if (skb->len < 24 + sizeof(*mmie))
-               return RX_DROP_U_SHORT_CMAC;
-
-       mmie = (struct ieee80211_mmie *)
-               (skb->data + skb->len - sizeof(*mmie));
-       if (mmie->element_id != WLAN_EID_MMIE ||
-           mmie->length != sizeof(*mmie) - 2)
-               return RX_DROP_U_BAD_MMIE; /* Invalid MMIE */
-
-       bip_ipn_swap(ipn, mmie->sequence_number);
-
-       if (memcmp(ipn, key->u.aes_cmac.rx_pn, 6) <= 0) {
-               key->u.aes_cmac.replays++;
-               return RX_DROP_U_REPLAY;
-       }
-
-       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,
-                                      IEEE80211_CMAC_128_MIC_LEN))
-                       return RX_DROP_U_DECRYPT_FAIL;
-               if (crypto_memneq(mic, mmie->mic, sizeof(mmie->mic))) {
-                       key->u.aes_cmac.icverrors++;
-                       return RX_DROP_U_MIC_FAIL;
-               }
-       }
-
-       memcpy(key->u.aes_cmac.rx_pn, ipn, 6);
-
-       /* Remove MMIE */
-       skb_trim(skb, skb->len - sizeof(*mmie));
-
-       return RX_CONTINUE;
-}
-
-ieee80211_rx_result
-ieee80211_crypto_aes_cmac_256_decrypt(struct ieee80211_rx_data *rx)
-{
-       struct sk_buff *skb = rx->skb;
-       struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
-       struct ieee80211_key *key = rx->key;
-       struct ieee80211_mmie_16 *mmie;
-       u8 aad[20], mic[16], ipn[6];
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-
-       if (!ieee80211_is_mgmt(hdr->frame_control))
-               return RX_CONTINUE;
+       mmie_len = sizeof(*mmie) + mic_len;
 
        /* management frames are already linear */
 
-       if (skb->len < 24 + sizeof(*mmie))
-               return RX_DROP_U_SHORT_CMAC256;
+       if (skb->len < 24 + mmie_len)
+               return mic_len == IEEE80211_CMAC_128_MIC_LEN ?
+                       RX_DROP_U_SHORT_CMAC : RX_DROP_U_SHORT_CMAC256;
 
-       mmie = (struct ieee80211_mmie_16 *)
-               (skb->data + skb->len - sizeof(*mmie));
+       mmie = (struct ieee80211_mmie_var *)(skb->data + skb->len - mmie_len);
        if (mmie->element_id != WLAN_EID_MMIE ||
-           mmie->length != sizeof(*mmie) - 2)
+           mmie->length != mmie_len - 2)
                return RX_DROP_U_BAD_MMIE; /* Invalid MMIE */
 
        bip_ipn_swap(ipn, mmie->sequence_number);
@@ -1013,10 +917,10 @@ ieee80211_crypto_aes_cmac_256_decrypt(struct ieee80211_rx_data *rx)
                /* 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,
-                                      IEEE80211_CMAC_256_MIC_LEN))
+                                      skb->data + 24, skb->len - 24,
+                                      mic, mic_len))
                        return RX_DROP_U_DECRYPT_FAIL;
-               if (crypto_memneq(mic, mmie->mic, sizeof(mmie->mic))) {
+               if (crypto_memneq(mic, mmie->mic, mic_len)) {
                        key->u.aes_cmac.icverrors++;
                        return RX_DROP_U_MIC_FAIL;
                }
@@ -1025,7 +929,7 @@ ieee80211_crypto_aes_cmac_256_decrypt(struct ieee80211_rx_data *rx)
        memcpy(key->u.aes_cmac.rx_pn, ipn, 6);
 
        /* Remove MMIE */
-       skb_trim(skb, skb->len - sizeof(*mmie));
+       skb_trim(skb, skb->len - mmie_len);
 
        return RX_CONTINUE;
 }
index a9a81abb54796168ec9d0c4ccccaae966c76937c..6e8846dfe7107b5830de120b35c5a68565bdf8f6 100644 (file)
@@ -29,13 +29,11 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx,
                              unsigned int mic_len);
 
 ieee80211_tx_result
-ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx);
-ieee80211_tx_result
-ieee80211_crypto_aes_cmac_256_encrypt(struct ieee80211_tx_data *tx);
-ieee80211_rx_result
-ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx);
+ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx,
+                                 unsigned int mic_len);
 ieee80211_rx_result
-ieee80211_crypto_aes_cmac_256_decrypt(struct ieee80211_rx_data *rx);
+ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx,
+                                 unsigned int mic_len);
 ieee80211_tx_result
 ieee80211_crypto_aes_gmac_encrypt(struct ieee80211_tx_data *tx);
 ieee80211_rx_result