wifi: ath12k: fix wrong handling of CCMP256 and GCMP ciphers
authorRameshkumar Sundaram <rameshkumar.sundaram@oss.qualcomm.com>
Tue, 15 Apr 2025 19:58:11 +0000 (01:28 +0530)
committerJeff Johnson <jeff.johnson@oss.qualcomm.com>
Thu, 17 Apr 2025 22:49:34 +0000 (15:49 -0700)
Currently for CCMP256, GCMP128 and GCMP256 ciphers, in
ath12k_install_key() IEEE80211_KEY_FLAG_GENERATE_IV_MGMT is not set and
in ath12k_mac_mgmt_tx_wmi() a length of IEEE80211_CCMP_MIC_LEN is reserved
for all ciphers.

This results in unexpected drop of protected management frames in case
either of above 3 ciphers is used. The reason is, without
IEEE80211_KEY_FLAG_GENERATE_IV_MGMT set, mac80211 will not generate
CCMP/GCMP headers in TX frame for ath12k.
Also MIC length reserved is wrong and such frames are dropped by hardware.

Fix this by setting IEEE80211_KEY_FLAG_GENERATE_IV_MGMT flag for above
ciphers and by reserving proper MIC length for those ciphers.

Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3

Fixes: d889913205cf ("wifi: ath12k: driver for Qualcomm Wi-Fi 7 devices")
Signed-off-by: Rameshkumar Sundaram <rameshkumar.sundaram@oss.qualcomm.com>
Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com>
Link: https://patch.msgid.link/20250415195812.2633923-2-rameshkumar.sundaram@oss.qualcomm.com
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
drivers/net/wireless/ath/ath12k/dp_rx.c
drivers/net/wireless/ath/ath12k/dp_rx.h
drivers/net/wireless/ath/ath12k/mac.c

index 8193f95..a9ac9da 100644 (file)
@@ -1941,8 +1941,7 @@ static void ath12k_dp_rx_h_csum_offload(struct sk_buff *msdu,
                           CHECKSUM_NONE : CHECKSUM_UNNECESSARY;
 }
 
-static int ath12k_dp_rx_crypto_mic_len(struct ath12k *ar,
-                                      enum hal_encrypt_type enctype)
+int ath12k_dp_rx_crypto_mic_len(struct ath12k *ar, enum hal_encrypt_type enctype)
 {
        switch (enctype) {
        case HAL_ENCRYPT_TYPE_OPEN:
index 19fb41e..f5c05f1 100644 (file)
@@ -163,4 +163,7 @@ int ath12k_dp_htt_tlv_iter(struct ath12k_base *ab, const void *ptr, size_t len,
                           void *data);
 void ath12k_dp_rx_h_fetch_info(struct ath12k_base *ab,  struct hal_rx_desc *rx_desc,
                               struct ath12k_dp_rx_info *rx_info);
+
+int ath12k_dp_rx_crypto_mic_len(struct ath12k *ar, enum hal_encrypt_type enctype);
+
 #endif /* ATH12K_DP_RX_H */
index f83783b..6a9a5b8 100644 (file)
@@ -4719,8 +4719,8 @@ static int ath12k_install_key(struct ath12k_link_vif *arvif,
 
        switch (key->cipher) {
        case WLAN_CIPHER_SUITE_CCMP:
+       case WLAN_CIPHER_SUITE_CCMP_256:
                arg.key_cipher = WMI_CIPHER_AES_CCM;
-               /* TODO: Re-check if flag is valid */
                key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV_MGMT;
                break;
        case WLAN_CIPHER_SUITE_TKIP:
@@ -4728,12 +4728,10 @@ static int ath12k_install_key(struct ath12k_link_vif *arvif,
                arg.key_txmic_len = 8;
                arg.key_rxmic_len = 8;
                break;
-       case WLAN_CIPHER_SUITE_CCMP_256:
-               arg.key_cipher = WMI_CIPHER_AES_CCM;
-               break;
        case WLAN_CIPHER_SUITE_GCMP:
        case WLAN_CIPHER_SUITE_GCMP_256:
                arg.key_cipher = WMI_CIPHER_AES_GCM;
+               key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV_MGMT;
                break;
        default:
                ath12k_warn(ar->ab, "cipher %d is not supported\n", key->cipher);
@@ -7153,6 +7151,8 @@ static int ath12k_mac_mgmt_tx_wmi(struct ath12k *ar, struct ath12k_link_vif *arv
        struct ath12k_base *ab = ar->ab;
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
        struct ieee80211_tx_info *info;
+       enum hal_encrypt_type enctype;
+       unsigned int mic_len;
        dma_addr_t paddr;
        int buf_id;
        int ret;
@@ -7168,12 +7168,16 @@ static int ath12k_mac_mgmt_tx_wmi(struct ath12k *ar, struct ath12k_link_vif *arv
                return -ENOSPC;
 
        info = IEEE80211_SKB_CB(skb);
-       if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP)) {
+       if ((ATH12K_SKB_CB(skb)->flags & ATH12K_SKB_CIPHER_SET) &&
+           !(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP)) {
                if ((ieee80211_is_action(hdr->frame_control) ||
                     ieee80211_is_deauth(hdr->frame_control) ||
                     ieee80211_is_disassoc(hdr->frame_control)) &&
                     ieee80211_has_protected(hdr->frame_control)) {
-                       skb_put(skb, IEEE80211_CCMP_MIC_LEN);
+                       enctype =
+                           ath12k_dp_tx_get_encrypt_type(ATH12K_SKB_CB(skb)->cipher);
+                       mic_len = ath12k_dp_rx_crypto_mic_len(ar, enctype);
+                       skb_put(skb, mic_len);
                }
        }