diff options
author | Stefan Sperling <stsp@cvs.openbsd.org> | 2021-04-19 14:27:26 +0000 |
---|---|---|
committer | Stefan Sperling <stsp@cvs.openbsd.org> | 2021-04-19 14:27:26 +0000 |
commit | f3974ee7ff6d93ac824fb9caa58b2673fa7a73f6 (patch) | |
tree | 3a04168846b8eccf1534241ed49c32f24ae8c94f /sys | |
parent | b0a38277d6ad477388e7164bb7297a4c753582ac (diff) |
Multicast decryption fixes for iwx(4).
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.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/pci/if_iwx.c | 14 |
1 files changed, 11 insertions, 3 deletions
diff --git a/sys/dev/pci/if_iwx.c b/sys/dev/pci/if_iwx.c index b634fded702..cdb3bafe26a 100644 --- a/sys/dev/pci/if_iwx.c +++ b/sys/dev/pci/if_iwx.c @@ -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++; |