Skip site navigation (1)Skip section navigation (2)
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>