From: Felix Fietkau Date: Sat, 9 Jul 2011 03:33:59 +0000 (+0000) Subject: ath9k: add more fixes for TKIP MIC validation X-Git-Tag: reboot~16269 X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=891a96d5885dad7496417946f289eaa28b2d8892;p=openwrt%2Fstaging%2Fxback.git ath9k: add more fixes for TKIP MIC validation SVN-Revision: 27564 --- diff --git a/package/mac80211/patches/550-ath9k_mmic_verify.patch b/package/mac80211/patches/550-ath9k_mmic_verify.patch index d280dff99c..053d543cb0 100644 --- a/package/mac80211/patches/550-ath9k_mmic_verify.patch +++ b/package/mac80211/patches/550-ath9k_mmic_verify.patch @@ -1,6 +1,6 @@ --- 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 +@@ -814,16 +814,19 @@ static bool ath9k_rx_accept(struct ath_c struct ath_rx_status *rx_stats, bool *decrypt_error) { @@ -8,7 +8,7 @@ - (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; ++ bool is_mc, is_valid_tkip, strip_mic, mic_error = false; struct ath_hw *ah = common->ah; __le16 fc; u8 rx_status_len = ah->caps.rx_status_len; @@ -18,37 +18,40 @@ + 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); ++ strip_mic = is_valid_tkip && !(rx_stats->rs_status & ++ (ATH9K_RXERR_DECRYPT | ATH9K_RXERR_CRC | ATH9K_RXERR_MIC)); + 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) { +@@ -850,25 +853,9 @@ static bool ath9k_rx_accept(struct ath_c + if (rx_stats->rs_status & ATH9K_RXERR_PHY) + return false; + +- if (rx_stats->rs_status & ATH9K_RXERR_DECRYPT) { ++ if (rx_stats->rs_status & ATH9K_RXERR_DECRYPT) *decrypt_error = true; - } else if (rx_stats->rs_status & ATH9K_RXERR_MIC) { +- } 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 +- /* +- * 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) && + +- 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 +- else +- rx_stats->rs_status &= ~ATH9K_RXERR_MIC; +- } + /* + * Reject error frames with the exception of + * decryption and MIC failures. For monitor mode, +@@ -886,6 +873,18 @@ static bool ath9k_rx_accept(struct ath_c } } } @@ -59,15 +62,21 @@ + * 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; ++ if (strip_mic) + rxs->flag |= RX_FLAG_MMIC_STRIPPED; -+ } else if (is_mc && mic_error) { ++ else if (is_mc && mic_error) + rxs->flag |= RX_FLAG_MMIC_ERROR; -+ } ++ return true; } +@@ -1882,6 +1881,9 @@ int ath_rx_tasklet(struct ath_softc *sc, + ath9k_rx_skb_postprocess(common, hdr_skb, &rs, + rxs, decrypt_error); + ++ if (rxs->flag & RX_FLAG_MMIC_STRIPPED) ++ skb_trim(skb, skb->len - 8); ++ + /* We will now give hardware our shiny new allocated skb */ + bf->bf_mpdu = requeue_skb; + bf->bf_buf_addr = dma_map_single(sc->dev, requeue_skb->data,