wifi: ath12k: fix wrong handling of CCMP256 and GCMP ciphers
[ Upstream commit f5d6b15d9503263d9425dcde9cc2fd401a32b0f2 ]
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: d889913205 ("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>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
3fffbb8d33
commit
7e48e3ddf9
@@ -1868,8 +1868,7 @@ static void ath12k_dp_rx_h_csum_offload(struct ath12k *ar, struct sk_buff *msdu)
|
|||||||
CHECKSUM_NONE : CHECKSUM_UNNECESSARY;
|
CHECKSUM_NONE : CHECKSUM_UNNECESSARY;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ath12k_dp_rx_crypto_mic_len(struct ath12k *ar,
|
int ath12k_dp_rx_crypto_mic_len(struct ath12k *ar, enum hal_encrypt_type enctype)
|
||||||
enum hal_encrypt_type enctype)
|
|
||||||
{
|
{
|
||||||
switch (enctype) {
|
switch (enctype) {
|
||||||
case HAL_ENCRYPT_TYPE_OPEN:
|
case HAL_ENCRYPT_TYPE_OPEN:
|
||||||
|
|||||||
@@ -143,4 +143,7 @@ int ath12k_dp_htt_tlv_iter(struct ath12k_base *ab, const void *ptr, size_t len,
|
|||||||
int (*iter)(struct ath12k_base *ar, u16 tag, u16 len,
|
int (*iter)(struct ath12k_base *ar, u16 tag, u16 len,
|
||||||
const void *ptr, void *data),
|
const void *ptr, void *data),
|
||||||
void *data);
|
void *data);
|
||||||
|
|
||||||
|
int ath12k_dp_rx_crypto_mic_len(struct ath12k *ar, enum hal_encrypt_type enctype);
|
||||||
|
|
||||||
#endif /* ATH12K_DP_RX_H */
|
#endif /* ATH12K_DP_RX_H */
|
||||||
|
|||||||
@@ -3864,8 +3864,8 @@ static int ath12k_install_key(struct ath12k_vif *arvif,
|
|||||||
|
|
||||||
switch (key->cipher) {
|
switch (key->cipher) {
|
||||||
case WLAN_CIPHER_SUITE_CCMP:
|
case WLAN_CIPHER_SUITE_CCMP:
|
||||||
|
case WLAN_CIPHER_SUITE_CCMP_256:
|
||||||
arg.key_cipher = WMI_CIPHER_AES_CCM;
|
arg.key_cipher = WMI_CIPHER_AES_CCM;
|
||||||
/* TODO: Re-check if flag is valid */
|
|
||||||
key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV_MGMT;
|
key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV_MGMT;
|
||||||
break;
|
break;
|
||||||
case WLAN_CIPHER_SUITE_TKIP:
|
case WLAN_CIPHER_SUITE_TKIP:
|
||||||
@@ -3873,12 +3873,10 @@ static int ath12k_install_key(struct ath12k_vif *arvif,
|
|||||||
arg.key_txmic_len = 8;
|
arg.key_txmic_len = 8;
|
||||||
arg.key_rxmic_len = 8;
|
arg.key_rxmic_len = 8;
|
||||||
break;
|
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:
|
||||||
case WLAN_CIPHER_SUITE_GCMP_256:
|
case WLAN_CIPHER_SUITE_GCMP_256:
|
||||||
arg.key_cipher = WMI_CIPHER_AES_GCM;
|
arg.key_cipher = WMI_CIPHER_AES_GCM;
|
||||||
|
key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV_MGMT;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ath12k_warn(ar->ab, "cipher %d is not supported\n", key->cipher);
|
ath12k_warn(ar->ab, "cipher %d is not supported\n", key->cipher);
|
||||||
@@ -5725,6 +5723,8 @@ static int ath12k_mac_mgmt_tx_wmi(struct ath12k *ar, struct ath12k_vif *arvif,
|
|||||||
struct ath12k_base *ab = ar->ab;
|
struct ath12k_base *ab = ar->ab;
|
||||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||||
struct ieee80211_tx_info *info;
|
struct ieee80211_tx_info *info;
|
||||||
|
enum hal_encrypt_type enctype;
|
||||||
|
unsigned int mic_len;
|
||||||
dma_addr_t paddr;
|
dma_addr_t paddr;
|
||||||
int buf_id;
|
int buf_id;
|
||||||
int ret;
|
int ret;
|
||||||
@@ -5738,12 +5738,16 @@ static int ath12k_mac_mgmt_tx_wmi(struct ath12k *ar, struct ath12k_vif *arvif,
|
|||||||
return -ENOSPC;
|
return -ENOSPC;
|
||||||
|
|
||||||
info = IEEE80211_SKB_CB(skb);
|
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) ||
|
if ((ieee80211_is_action(hdr->frame_control) ||
|
||||||
ieee80211_is_deauth(hdr->frame_control) ||
|
ieee80211_is_deauth(hdr->frame_control) ||
|
||||||
ieee80211_is_disassoc(hdr->frame_control)) &&
|
ieee80211_is_disassoc(hdr->frame_control)) &&
|
||||||
ieee80211_has_protected(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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user