aboutsummaryrefslogtreecommitdiffstats
path: root/package/mac80211/patches/550-ath9k_mmic_verify.patch
blob: d280dff99ce2d7d5c0cd8aeb7959d8ac3a6be664 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -814,16 +814,17 @@ static bool ath9k_rx_accept(struct ath_c
 			    struct ath_rx_status *rx_stats,
 			    bool *decrypt_error)
 {
-#define is_mc_or_valid_tkip_keyix ((is_mc ||			\
-		(rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID && \
-		test_bit(rx_stats->rs_keyix, common->tkip_keymap))))
-
+	bool is_mc, is_valid_tkip, mic_error = false;
 	struct ath_hw *ah = common->ah;
 	__le16 fc;
 	u8 rx_status_len = ah->caps.rx_status_len;
 
 	fc = hdr->frame_control;
 
+	is_mc = !!is_multicast_ether_addr(hdr->addr1);
+	is_valid_tkip = rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID &&
+		test_bit(rx_stats->rs_keyix, common->tkip_keymap);
+
 	if (!rx_stats->rs_datalen)
 		return false;
         /*
@@ -853,19 +854,19 @@ static bool ath9k_rx_accept(struct ath_c
 		if (rx_stats->rs_status & ATH9K_RXERR_DECRYPT) {
 			*decrypt_error = true;
 		} else if (rx_stats->rs_status & ATH9K_RXERR_MIC) {
-			bool is_mc;
 			/*
 			 * The MIC error bit is only valid if the frame
 			 * is not a control frame or fragment, and it was
-			 * decrypted using a valid TKIP key.
+			 * decrypted using a valid TKIP key. For multicast
+			 * frames the hardware will not return a valid
+			 * key index, so accept the MIC bit for those
+			 * as well.
 			 */
-			is_mc = !!is_multicast_ether_addr(hdr->addr1);
-
 			if (!ieee80211_is_ctl(fc) &&
 			    !ieee80211_has_morefrags(fc) &&
 			    !(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) &&
-			    is_mc_or_valid_tkip_keyix)
-				rxs->flag |= RX_FLAG_MMIC_ERROR;
+			    (is_mc || is_valid_tkip))
+				mic_error = true;
 			else
 				rx_stats->rs_status &= ~ATH9K_RXERR_MIC;
 		}
@@ -886,6 +887,22 @@ static bool ath9k_rx_accept(struct ath_c
 			}
 		}
 	}
+
+	/*
+	 * For unicast frames the MIC error bit can have false positives,
+	 * so all MIC error reports need to be validated in software.
+	 * False negatives are not common, so skip software verification
+	 * if the hardware considers the MIC valid.
+	 */
+	if (is_valid_tkip && ieee80211_is_data_present(hdr->frame_control) &&
+	    !(rx_stats->rs_status & (ATH9K_RXERR_DECRYPT | ATH9K_RXERR_CRC |
+				     ATH9K_RXERR_MIC))) {
+		/* Strip the Michael MIC */
+		rx_stats->rs_datalen -= 8;
+		rxs->flag |= RX_FLAG_MMIC_STRIPPED;
+	} else if (is_mc && mic_error) {
+		rxs->flag |= RX_FLAG_MMIC_ERROR;
+	}
 	return true;
 }