PERFORCE change 67111 for review
Sam Leffler
sam at FreeBSD.org
Tue Dec 14 22:36:12 PST 2004
http://perforce.freebsd.org/chv.cgi?CH=67111
Change 67111 by sam at 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;
More information about the p4-projects
mailing list