From: stsp Date: Mon, 3 May 2021 08:23:05 +0000 (+0000) Subject: work around an athn(4) device problem with bogus Michael MIC failures X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=0c4e73bb83f5a184d7a2bc98aba7ef12d0f5af2f;p=openbsd work around an athn(4) device problem with bogus Michael MIC failures Clients using Tx aggregation against an athn(4) hostap will send block ack request control frames whenever they need to sync their Tx block ack window. athn(4) dropped such frames due to bogus Michael MIC failures reported by the hardware decryption engine. Ignore such failures for control frames in order to fix athn(4) hostap mode against clients which use Tx aggregation. Additionally, only report Michael MIC failures to the net80211 stack if the offending client is actually using TKIP, which would also have prevented the problem since we require CCMP as group cipher in our default configuration. Problem reported and fix tested by kettenis@ --- diff --git a/sys/dev/ic/ar5008.c b/sys/dev/ic/ar5008.c index 2b77b0d686d..816a3b09ee2 100644 --- a/sys/dev/ic/ar5008.c +++ b/sys/dev/ic/ar5008.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ar5008.c,v 1.65 2021/04/15 18:25:43 stsp Exp $ */ +/* $OpenBSD: ar5008.c,v 1.66 2021/05/03 08:23:05 stsp Exp $ */ /*- * Copyright (c) 2009 Damien Bergamini @@ -865,7 +865,7 @@ ar5008_rx_process(struct athn_softc *sc, struct mbuf_list *ml) struct ieee80211_rxinfo rxi; struct ieee80211_node *ni; struct mbuf *m, *m1; - int error, len; + int error, len, michael_mic_failure = 0; bf = SIMPLEQ_FIRST(&rxq->head); if (__predict_false(bf == NULL)) { /* Should not happen. */ @@ -915,16 +915,12 @@ ar5008_rx_process(struct athn_softc *sc, struct mbuf_list *ml) ic->ic_stats.is_ccmp_dec_errs++; } else if (ds->ds_status8 & AR_RXS8_MICHAEL_ERR) { DPRINTFN(2, ("Michael MIC failure\n")); - /* Report Michael MIC failures to net80211. */ - ic->ic_stats.is_rx_locmicfail++; - ieee80211_michael_mic_failure(ic, 0); - /* - * XXX Check that it is not a control frame - * (invalid MIC failures on valid ctl frames). - */ + michael_mic_failure = 1; + } + if (!michael_mic_failure) { + ifp->if_ierrors++; + goto skip; } - ifp->if_ierrors++; - goto skip; } len = MS(ds->ds_status1, AR_RXS1_DATA_LEN); @@ -978,6 +974,25 @@ ar5008_rx_process(struct athn_softc *sc, struct mbuf_list *ml) wh = mtod(m, struct ieee80211_frame *); ni = ieee80211_find_rxnode(ic, wh); + if (michael_mic_failure) { + /* + * Check that it is not a control frame + * (invalid MIC failures on valid ctl frames). + */ + if (!(wh->i_fc[0] & IEEE80211_FC0_TYPE_CTL) && + (ic->ic_flags & IEEE80211_F_RSNON) && + (ni->ni_rsncipher == IEEE80211_CIPHER_TKIP || + ni->ni_rsngroupcipher == IEEE80211_CIPHER_TKIP)) { + /* Report Michael MIC failures to net80211. */ + ic->ic_stats.is_rx_locmicfail++; + ieee80211_michael_mic_failure(ic, 0); + ifp->if_ierrors++; + ieee80211_release_node(ic, ni); + m_freem(m); + goto skip; + } + } + /* Remove any HW padding after the 802.11 header. */ if (!(wh->i_fc[0] & IEEE80211_FC0_TYPE_CTL)) { u_int hdrlen = ieee80211_get_hdrlen(wh);