aboutsummaryrefslogtreecommitdiffstats
path: root/package/kernel/mac80211/patches/ath10k/300-ath10k-add-CCMP-PN-replay-protection-for-fragmented-.patch
diff options
context:
space:
mode:
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-.patch180
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: