diff options
Diffstat (limited to 'package/kernel/mac80211/patches/ath10k/300-ath10k-add-CCMP-PN-replay-protection-for-fragmented-.patch')
-rw-r--r-- | package/kernel/mac80211/patches/ath10k/300-ath10k-add-CCMP-PN-replay-protection-for-fragmented-.patch | 180 |
1 files changed, 0 insertions, 180 deletions
diff --git a/package/kernel/mac80211/patches/ath10k/300-ath10k-add-CCMP-PN-replay-protection-for-fragmented-.patch b/package/kernel/mac80211/patches/ath10k/300-ath10k-add-CCMP-PN-replay-protection-for-fragmented-.patch deleted file mode 100644 index 0ce49b22ab..0000000000 --- a/package/kernel/mac80211/patches/ath10k/300-ath10k-add-CCMP-PN-replay-protection-for-fragmented-.patch +++ /dev/null @@ -1,180 +0,0 @@ -From: Wen Gong <wgong@codeaurora.org> -Date: Tue, 11 May 2021 20:02:52 +0200 -Subject: [PATCH] ath10k: add CCMP PN replay protection for fragmented - frames for PCIe - -PN replay check for not fragmented frames is finished in the firmware, -but this was not done for fragmented frames when ath10k is used with -QCA6174/QCA6377 PCIe. mac80211 has the function -ieee80211_rx_h_defragment() for PN replay check for fragmented frames, -but this does not get checked with QCA6174 due to the -ieee80211_has_protected() condition not matching the cleared Protected -bit case. - -Validate the PN of received fragmented frames within ath10k when CCMP is -used and drop the fragment if the PN is not correct (incremented by -exactly one from the previous fragment). This applies only for -QCA6174/QCA6377 PCIe. - -Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00110-QCARMSWP-1 - -Cc: stable@vger.kernel.org -Signed-off-by: Wen Gong <wgong@codeaurora.org> -Signed-off-by: Jouni Malinen <jouni@codeaurora.org> -Signed-off-by: Johannes Berg <johannes.berg@intel.com> ---- - ---- a/drivers/net/wireless/ath/ath10k/htt.h -+++ b/drivers/net/wireless/ath/ath10k/htt.h -@@ -846,6 +846,7 @@ enum htt_security_types { - - #define ATH10K_HTT_TXRX_PEER_SECURITY_MAX 2 - #define ATH10K_TXRX_NUM_EXT_TIDS 19 -+#define ATH10K_TXRX_NON_QOS_TID 16 - - enum htt_security_flags { - #define HTT_SECURITY_TYPE_MASK 0x7F ---- a/drivers/net/wireless/ath/ath10k/htt_rx.c -+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c -@@ -1746,16 +1746,87 @@ static void ath10k_htt_rx_h_csum_offload - msdu->ip_summed = ath10k_htt_rx_get_csum_state(msdu); - } - -+static u64 ath10k_htt_rx_h_get_pn(struct ath10k *ar, struct sk_buff *skb, -+ u16 offset, -+ enum htt_rx_mpdu_encrypt_type enctype) -+{ -+ struct ieee80211_hdr *hdr; -+ u64 pn = 0; -+ u8 *ehdr; -+ -+ hdr = (struct ieee80211_hdr *)(skb->data + offset); -+ ehdr = skb->data + offset + ieee80211_hdrlen(hdr->frame_control); -+ -+ if (enctype == HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2) { -+ pn = ehdr[0]; -+ pn |= (u64)ehdr[1] << 8; -+ pn |= (u64)ehdr[4] << 16; -+ pn |= (u64)ehdr[5] << 24; -+ pn |= (u64)ehdr[6] << 32; -+ pn |= (u64)ehdr[7] << 40; -+ } -+ return pn; -+} -+ -+static bool ath10k_htt_rx_h_frag_pn_check(struct ath10k *ar, -+ struct sk_buff *skb, -+ u16 peer_id, -+ u16 offset, -+ enum htt_rx_mpdu_encrypt_type enctype) -+{ -+ struct ath10k_peer *peer; -+ union htt_rx_pn_t *last_pn, new_pn = {0}; -+ struct ieee80211_hdr *hdr; -+ bool more_frags; -+ u8 tid, frag_number; -+ u32 seq; -+ -+ peer = ath10k_peer_find_by_id(ar, peer_id); -+ if (!peer) { -+ ath10k_dbg(ar, ATH10K_DBG_HTT, "invalid peer for frag pn check\n"); -+ return false; -+ } -+ -+ hdr = (struct ieee80211_hdr *)(skb->data + offset); -+ if (ieee80211_is_data_qos(hdr->frame_control)) -+ tid = ieee80211_get_tid(hdr); -+ else -+ tid = ATH10K_TXRX_NON_QOS_TID; -+ -+ last_pn = &peer->frag_tids_last_pn[tid]; -+ new_pn.pn48 = ath10k_htt_rx_h_get_pn(ar, skb, offset, enctype); -+ more_frags = ieee80211_has_morefrags(hdr->frame_control); -+ frag_number = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG; -+ seq = (__le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; -+ -+ if (frag_number == 0) { -+ last_pn->pn48 = new_pn.pn48; -+ peer->frag_tids_seq[tid] = seq; -+ } else { -+ if (seq != peer->frag_tids_seq[tid]) -+ return false; -+ -+ if (new_pn.pn48 != last_pn->pn48 + 1) -+ return false; -+ -+ last_pn->pn48 = new_pn.pn48; -+ } -+ -+ return true; -+} -+ - static void ath10k_htt_rx_h_mpdu(struct ath10k *ar, - struct sk_buff_head *amsdu, - struct ieee80211_rx_status *status, - bool fill_crypt_header, - u8 *rx_hdr, -- enum ath10k_pkt_rx_err *err) -+ enum ath10k_pkt_rx_err *err, -+ u16 peer_id, -+ bool frag) - { - struct sk_buff *first; - struct sk_buff *last; -- struct sk_buff *msdu; -+ struct sk_buff *msdu, *temp; - struct htt_rx_desc *rxd; - struct ieee80211_hdr *hdr; - enum htt_rx_mpdu_encrypt_type enctype; -@@ -1768,6 +1839,7 @@ static void ath10k_htt_rx_h_mpdu(struct - bool is_decrypted; - bool is_mgmt; - u32 attention; -+ bool frag_pn_check = true; - - if (skb_queue_empty(amsdu)) - return; -@@ -1866,6 +1938,24 @@ static void ath10k_htt_rx_h_mpdu(struct - } - - skb_queue_walk(amsdu, msdu) { -+ if (frag && !fill_crypt_header && is_decrypted && -+ enctype == HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2) -+ frag_pn_check = ath10k_htt_rx_h_frag_pn_check(ar, -+ msdu, -+ peer_id, -+ 0, -+ enctype); -+ -+ if (!frag_pn_check) { -+ /* Discard the fragment with invalid PN */ -+ temp = msdu->prev; -+ __skb_unlink(msdu, amsdu); -+ dev_kfree_skb_any(msdu); -+ msdu = temp; -+ frag_pn_check = true; -+ continue; -+ } -+ - ath10k_htt_rx_h_csum_offload(msdu); - ath10k_htt_rx_h_undecap(ar, msdu, status, first_hdr, enctype, - is_decrypted); -@@ -2071,7 +2161,8 @@ static int ath10k_htt_rx_handle_amsdu(st - ath10k_htt_rx_h_unchain(ar, &amsdu, &drop_cnt, &unchain_cnt); - - ath10k_htt_rx_h_filter(ar, &amsdu, rx_status, &drop_cnt_filter); -- ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status, true, first_hdr, &err); -+ ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status, true, first_hdr, &err, 0, -+ false); - msdus_to_queue = skb_queue_len(&amsdu); - ath10k_htt_rx_h_enqueue(ar, &amsdu, rx_status); - -@@ -3027,7 +3118,7 @@ static int ath10k_htt_rx_in_ord_ind(stru - ath10k_htt_rx_h_ppdu(ar, &amsdu, status, vdev_id); - ath10k_htt_rx_h_filter(ar, &amsdu, status, NULL); - ath10k_htt_rx_h_mpdu(ar, &amsdu, status, false, NULL, -- NULL); -+ NULL, peer_id, frag); - ath10k_htt_rx_h_enqueue(ar, &amsdu, status); - break; - case -EAGAIN: |