ath10k: fix pmf for action frames
Fix sending and receiveing protected managment frames.
Lack of protected flag for received protected action frames
causes report these frames as unprotected robust action frames.
If the driver in AP mode sent frame with protected flag and
CCMP header using IEEE80211_KEY_FLAG_SW_MGMT_TX flag,
the FW encrypted frames once again. From user side all
received SA Query Requests and Responses were skipped and
all protected action frames were sent as malformed packets.
Signed-off-by: Marek Kwaczynski <marek.kwaczynski@tieto.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 7026f02..1251804 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -54,7 +54,10 @@
switch (key->cipher) {
case WLAN_CIPHER_SUITE_CCMP:
arg.key_cipher = WMI_CIPHER_AES_CCM;
- key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
+ if (arvif->vdev_type == WMI_VDEV_TYPE_AP)
+ key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV_MGMT;
+ else
+ key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
break;
case WLAN_CIPHER_SUITE_TKIP:
arg.key_cipher = WMI_CIPHER_TKIP;
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 72cc4f2..e355d5e 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -639,6 +639,7 @@
struct sk_buff *wmi_skb;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
int len;
+ u32 buf_len = skb->len;
u16 fc;
hdr = (struct ieee80211_hdr *)skb->data;
@@ -648,6 +649,15 @@
return -EINVAL;
len = sizeof(cmd->hdr) + skb->len;
+
+ 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)) {
+ len += IEEE80211_CCMP_MIC_LEN;
+ buf_len += IEEE80211_CCMP_MIC_LEN;
+ }
+
len = round_up(len, 4);
wmi_skb = ath10k_wmi_alloc_skb(len);
@@ -659,7 +669,7 @@
cmd->hdr.vdev_id = __cpu_to_le32(ATH10K_SKB_CB(skb)->vdev_id);
cmd->hdr.tx_rate = 0;
cmd->hdr.tx_power = 0;
- cmd->hdr.buf_len = __cpu_to_le32((u32)(skb->len));
+ cmd->hdr.buf_len = __cpu_to_le32(buf_len);
memcpy(cmd->hdr.peer_macaddr.addr, ieee80211_get_DA(hdr), ETH_ALEN);
memcpy(cmd->buf, skb->data, skb->len);
@@ -957,10 +967,16 @@
* frames with Protected Bit set. */
if (ieee80211_has_protected(hdr->frame_control) &&
!ieee80211_is_auth(hdr->frame_control)) {
- status->flag |= RX_FLAG_DECRYPTED | RX_FLAG_IV_STRIPPED |
- RX_FLAG_MMIC_STRIPPED;
- hdr->frame_control = __cpu_to_le16(fc &
+ status->flag |= RX_FLAG_DECRYPTED;
+
+ if (!ieee80211_is_action(hdr->frame_control) &&
+ !ieee80211_is_deauth(hdr->frame_control) &&
+ !ieee80211_is_disassoc(hdr->frame_control)) {
+ status->flag |= RX_FLAG_IV_STRIPPED |
+ RX_FLAG_MMIC_STRIPPED;
+ hdr->frame_control = __cpu_to_le16(fc &
~IEEE80211_FCTL_PROTECTED);
+ }
}
ath10k_dbg(ATH10K_DBG_MGMT,