Date: Wed, 15 Dec 2004 06:36:11 GMT From: Sam Leffler <sam@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 67111 for review Message-ID: <200412150636.iBF6aBYn017209@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=67111 Change 67111 by sam@sam_ebb on 2004/12/15 06:35:36 Relearn how WPA keying is supposed to work and fix WPA+WME while we're at it: o WPA/802.11i has a unicast key and a group key; in station mode everything is sent with the unicast key--we were consulting the destination mac address and incorrectly using the group key o (perpetuate fallback use of the default tx key to maintain compatibility with the way wpa_supplicant works) o correct EAPOL encryption logic to check unicast key instead of assuming other state implies this With these changes WPA+WME station and ap operation works (but only with newish 5212 parts and only with an unreleased hal). Affected files ... .. //depot/projects/wifi/sys/net80211/ieee80211_output.c#26 edit Differences ... ==== //depot/projects/wifi/sys/net80211/ieee80211_output.c#26 (text+ko) ==== @@ -386,35 +386,37 @@ return 0; } +#define KEY_UNDEFINED(k) ((k).wk_cipher == &ieee80211_cipher_none) /* - * Return the transmit key to use in sending a frame to the specified - * destination. Multicast traffic always uses the group key which is - * installed the default tx key. Otherwise if a unicast key is set - * we use that. When no unicast key is set we fall back to the default - * transmit key unless WPA is enabled in which case there should be - * a unicast frame so we don't want to use a default key (which in - * this case is the group/multicast key). + * Return the transmit key to use in sending a unicast frame. + * If a unicast key is set we use that. When no unicast key is set + * we fall back to the default transmit key. */ static __inline struct ieee80211_key * -ieee80211_crypto_getkey(struct ieee80211com *ic, - const u_int8_t mac[IEEE80211_ADDR_LEN], struct ieee80211_node *ni) +ieee80211_crypto_getucastkey(struct ieee80211com *ic, struct ieee80211_node *ni) { -#define KEY_UNDEFINED(k) ((k).wk_cipher == &ieee80211_cipher_none) - if (IEEE80211_IS_MULTICAST(mac)) { + if (KEY_UNDEFINED(ni->ni_ucastkey)) { if (ic->ic_def_txkey == IEEE80211_KEYIX_NONE || KEY_UNDEFINED(ic->ic_nw_keys[ic->ic_def_txkey])) return NULL; return &ic->ic_nw_keys[ic->ic_def_txkey]; - } else if (KEY_UNDEFINED(ni->ni_ucastkey)) { - if ((ic->ic_flags & IEEE80211_F_WPA) || - ic->ic_def_txkey == IEEE80211_KEYIX_NONE || - KEY_UNDEFINED(ic->ic_nw_keys[ic->ic_def_txkey])) - return NULL; - return &ic->ic_nw_keys[ic->ic_def_txkey]; } else { return &ni->ni_ucastkey; } -#undef KEY_UNDEFINED +} + +/* + * Return the transmit key to use in sending a multicast frame. + * Multicast traffic always uses the group key which is installed as + * the default tx key. + */ +static __inline struct ieee80211_key * +ieee80211_crypto_getmcastkey(struct ieee80211com *ic, struct ieee80211_node *ni) +{ + if (ic->ic_def_txkey == IEEE80211_KEYIX_NONE || + KEY_UNDEFINED(ic->ic_nw_keys[ic->ic_def_txkey])) + return NULL; + return &ic->ic_nw_keys[ic->ic_def_txkey]; } /* @@ -449,11 +451,15 @@ * routines, but they will/should discard it. */ if (ic->ic_flags & IEEE80211_F_PRIVACY) { - key = ieee80211_crypto_getkey(ic, eh.ether_dhost, ni); + if (ic->ic_opmode == IEEE80211_M_STA || + !IEEE80211_IS_MULTICAST(eh.ether_dhost)) + key = ieee80211_crypto_getucastkey(ic, ni); + else + key = ieee80211_crypto_getmcastkey(ic, ni); if (key == NULL && eh.ether_type != htons(ETHERTYPE_PAE)) { IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO, "[%s] no default transmit key (%s) deftxkey %u\n", - ether_sprintf(ni->ni_macaddr), __func__, + ether_sprintf(eh.ether_dhost), __func__, ic->ic_def_txkey); ic->ic_stats.is_tx_nodefkey++; } @@ -536,13 +542,14 @@ htole16(ni->ni_txseqs[0] << IEEE80211_SEQ_SEQ_SHIFT); ni->ni_txseqs[0]++; } - if (eh.ether_type != htons(ETHERTYPE_PAE) || - (key != NULL && (ic->ic_flags & IEEE80211_F_WPA))) { + if (key != NULL) { /* * IEEE 802.1X: send EAPOL frames always in the clear. * WPA/WPA2: encrypt EAPOL keys when pairwise keys are set. */ - if (key != NULL) { + if (eh.ether_type != htons(ETHERTYPE_PAE) || + ((ic->ic_flags & IEEE80211_F_WPA) && + !KEY_UNDEFINED(ni->ni_ucastkey))) { wh->i_fc[1] |= IEEE80211_FC1_WEP; /* XXX do fragmentation */ if (!ieee80211_crypto_enmic(ic, key, m)) { @@ -564,6 +571,7 @@ m_freem(m); return NULL; } +#undef KEY_UNDEFINED /* * Add a supported rates element id to a frame. @@ -1563,7 +1571,7 @@ ni->ni_savedq.ifq_drops, IEEE80211_PS_MAX_QUEUE); #ifdef IEEE80211_DEBUG if (ieee80211_msg_dumppkts(ic)) - ieee80211_dump_pkt(mtod(m, caddr_t), m->m_len, -1, -1); + ieee80211_dump_pkt(ic, mtod(m, caddr_t), m->m_len, -1, -1); #endif m_freem(m); return;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200412150636.iBF6aBYn017209>