Multicast decryption fixes for iwx(4).
authorstsp <stsp@openbsd.org>
Mon, 19 Apr 2021 14:27:25 +0000 (14:27 +0000)
committerstsp <stsp@openbsd.org>
Mon, 19 Apr 2021 14:27:25 +0000 (14:27 +0000)
Pick the correct key for multicast frames in iwx_ccmp_decap().
Comparing the PN of a multicast frame against the last-seen PN of
the pairwise key is obviously wrong. We need to check the multicast
frame's PN against the last-seen PN of the group key.

Update crypto-offloading checks in iwx_rx_frame() to match recent
WPA1/TKIP groupcipher fixes made in athn(4).
The code inherited from iwm(4) only looked at the pairwise key, and
unlike iwx(4) and athn(4), iwm(4) only offloads pairwise crypto.

Found while investigating a question from zxystd at OpenIntelWireless.

sys/dev/pci/if_iwx.c

index b634fde..cdb3baf 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_iwx.c,v 1.51 2021/04/14 18:38:54 stsp Exp $        */
+/*     $OpenBSD: if_iwx.c,v 1.52 2021/04/19 14:27:25 stsp Exp $        */
 
 /*
  * Copyright (c) 2014, 2016 genua gmbh <info@genua.de>
@@ -3252,7 +3252,7 @@ int
 iwx_ccmp_decap(struct iwx_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
 {
        struct ieee80211com *ic = &sc->sc_ic;
-       struct ieee80211_key *k = &ni->ni_pairwise_key;
+       struct ieee80211_key *k;
        struct ieee80211_frame *wh;
        uint64_t pn, *prsc;
        uint8_t *ivp;
@@ -3263,6 +3263,11 @@ iwx_ccmp_decap(struct iwx_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
        hdrlen = ieee80211_get_hdrlen(wh);
        ivp = (uint8_t *)wh + hdrlen;
 
+       /* find key for decryption */
+       k = ieee80211_get_rxkey(ic, m, ni);
+       if (k == NULL || k->k_cipher != IEEE80211_CIPHER_CCMP)
+               return 1;
+
        /* Check that ExtIV bit is be set. */
        if (!(ivp[3] & IEEE80211_WEP_EXTIV))
                return 1;
@@ -3327,7 +3332,10 @@ iwx_rx_frame(struct iwx_softc *sc, struct mbuf *m, int chanidx,
        if (((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_CTL)
            && (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) &&
            (ni->ni_flags & IEEE80211_NODE_RXPROT) &&
-           ni->ni_pairwise_key.k_cipher == IEEE80211_CIPHER_CCMP) {
+           ((!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
+           ni->ni_rsncipher == IEEE80211_CIPHER_CCMP) ||
+           (IEEE80211_IS_MULTICAST(wh->i_addr1) &&
+           ni->ni_rsngroupcipher == IEEE80211_CIPHER_CCMP))) {
                if ((rx_pkt_status & IWX_RX_MPDU_RES_STATUS_SEC_ENC_MSK) !=
                    IWX_RX_MPDU_RES_STATUS_SEC_CCM_ENC) {
                        ic->ic_stats.is_ccmp_dec_errs++;