summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Bergamini <damien@cvs.openbsd.org>2008-08-12 18:22:42 +0000
committerDamien Bergamini <damien@cvs.openbsd.org>2008-08-12 18:22:42 +0000
commit8321c622bc4b888984d8c49d465de349ddf196a6 (patch)
tree61d2fe7a42cde40203f51a35710d475f7154fd82
parentab5a9e9d81fc4c62ba8686abf635e9b0da2420c9 (diff)
process IGTK KDEs in EAPOL-Key frames and install integrity group keys
if MFP was negotiated with the peer (not possible yet).
-rw-r--r--sys/net80211/ieee80211.h5
-rw-r--r--sys/net80211/ieee80211_node.h16
-rw-r--r--sys/net80211/ieee80211_pae_input.c143
-rw-r--r--sys/net80211/ieee80211_pae_output.c70
4 files changed, 174 insertions, 60 deletions
diff --git a/sys/net80211/ieee80211.h b/sys/net80211/ieee80211.h
index d50766ef7b6..8ed2c5d880f 100644
--- a/sys/net80211/ieee80211.h
+++ b/sys/net80211/ieee80211.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ieee80211.h,v 1.39 2008/08/12 16:51:39 damien Exp $ */
+/* $OpenBSD: ieee80211.h,v 1.40 2008/08/12 18:22:41 damien Exp $ */
/* $NetBSD: ieee80211.h,v 1.6 2004/04/30 23:51:53 dyoung Exp $ */
/*-
@@ -581,7 +581,8 @@ enum {
IEEE80211_KDE_SMK = 5,
IEEE80211_KDE_NONCE = 6,
IEEE80211_KDE_LIFETIME = 7,
- IEEE80211_KDE_ERROR = 8
+ IEEE80211_KDE_ERROR = 8,
+ IEEE80211_KDE_IGTK = 9 /* 11w */
};
/*
diff --git a/sys/net80211/ieee80211_node.h b/sys/net80211/ieee80211_node.h
index 8e375b81895..a60079601ef 100644
--- a/sys/net80211/ieee80211_node.h
+++ b/sys/net80211/ieee80211_node.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ieee80211_node.h,v 1.30 2008/08/02 08:24:15 damien Exp $ */
+/* $OpenBSD: ieee80211_node.h,v 1.31 2008/08/12 18:22:41 damien Exp $ */
/* $NetBSD: ieee80211_node.h,v 1.9 2004/04/30 22:57:32 dyoung Exp $ */
/*-
@@ -154,6 +154,7 @@ struct ieee80211_node {
u_int ni_rsnakms;
u_int ni_rsnciphers;
enum ieee80211_cipher ni_rsngroupcipher;
+ enum ieee80211_cipher ni_rsngroupmgmtcipher;
u_int16_t ni_rsncaps;
enum ieee80211_cipher ni_rsncipher;
u_int8_t ni_nonce[EAPOL_KEY_NONCE_LEN];
@@ -179,13 +180,16 @@ struct ieee80211_node {
int ni_state;
u_int8_t ni_flags; /* special-purpose state */
-#define IEEE80211_NODE_ERP 0x01
-#define IEEE80211_NODE_QOS 0x02
-#define IEEE80211_NODE_REKEY 0x04 /* GTK rekeying in progress */
-#define IEEE80211_NODE_RXPROT 0x08 /* RX protection ON */
-#define IEEE80211_NODE_TXPROT 0x10 /* TX protection ON */
+#define IEEE80211_NODE_ERP 0x01
+#define IEEE80211_NODE_QOS 0x02
+#define IEEE80211_NODE_REKEY 0x04 /* GTK rekeying in progress */
+#define IEEE80211_NODE_RXPROT 0x08 /* RX protection ON */
+#define IEEE80211_NODE_TXPROT 0x10 /* TX protection ON */
#define IEEE80211_NODE_TXRXPROT \
(IEEE80211_NODE_TXPROT | IEEE80211_NODE_RXPROT)
+#define IEEE80211_NODE_RXMGMTPROT 0x20 /* RX MMPDU protection ON */
+#define IEEE80211_NODE_TXMGMTPROT 0x40 /* TX MMPDU protection ON */
+#define IEEE80211_NODE_MFP 0x80 /* MFP negotiated */
};
RB_HEAD(ieee80211_tree, ieee80211_node);
diff --git a/sys/net80211/ieee80211_pae_input.c b/sys/net80211/ieee80211_pae_input.c
index ca08d4e8ad3..9c46df076ef 100644
--- a/sys/net80211/ieee80211_pae_input.c
+++ b/sys/net80211/ieee80211_pae_input.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ieee80211_pae_input.c,v 1.8 2008/08/12 17:53:13 damien Exp $ */
+/* $OpenBSD: ieee80211_pae_input.c,v 1.9 2008/08/12 18:22:41 damien Exp $ */
/*-
* Copyright (c) 2007,2008 Damien Bergamini <damien.bergamini@free.fr>
@@ -16,6 +16,12 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+/*
+ * This code implements the 4-Way Handshake and Group Key Handshake protocols
+ * (both Supplicant and Authenticator Key Receive state machines) defined in
+ * IEEE Std 802.11-2007 section 8.5.
+ */
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/mbuf.h>
@@ -165,8 +171,7 @@ ieee80211_eapol_key_input(struct ieee80211com *ic, struct mbuf *m0,
}
/*
- * 4-Way Handshake Message 1 is sent by the authenticator to the supplicant
- * (see 8.5.3.1).
+ * Process Message 1 of the 4-Way Handshake (sent by Authenticator).
*/
void
ieee80211_recv_4way_msg1(struct ieee80211com *ic,
@@ -186,8 +191,6 @@ ieee80211_recv_4way_msg1(struct ieee80211com *ic,
ic->ic_stats.is_rx_eapol_replay++;
return;
}
- /* save authenticator's nonce (ANonce) */
- memcpy(ni->ni_nonce, key->nonce, EAPOL_KEY_NONCE_LEN);
/* parse key data field (may contain an encapsulated PMKID) */
frm = (const u_int8_t *)&key[1];
@@ -216,16 +219,20 @@ ieee80211_recv_4way_msg1(struct ieee80211com *ic,
if (pmkid != NULL && pmkid[1] < 4 + 16)
return;
- /* generate a new supplicant's nonce (SNonce) */
- arc4random_buf(ic->ic_nonce, EAPOL_KEY_NONCE_LEN);
-
- /* retrieve PMK and derive TPTK */
- if ((pmk = ieee80211_get_pmk(ic, ni, pmkid)) == NULL) {
+ /* retrieve PMK */
+ if ((pmk = ieee80211_get_pmk(ic, ni, &pmkid[6])) == NULL) {
/* no PMK configured for this STA/PMKID */
return;
}
+ /* save authenticator's nonce (ANonce) */
+ memcpy(ni->ni_nonce, key->nonce, EAPOL_KEY_NONCE_LEN);
+
+ /* generate supplicant's nonce (SNonce) */
+ arc4random_buf(ic->ic_nonce, EAPOL_KEY_NONCE_LEN);
+
+ /* derive TPTK */
ieee80211_derive_ptk(ni->ni_rsnakms, pmk, ni->ni_macaddr,
- ic->ic_myaddr, key->nonce, ic->ic_nonce, &tptk);
+ ic->ic_myaddr, ni->ni_nonce, ic->ic_nonce, &tptk);
if (ic->ic_if.if_flags & IFF_DEBUG)
printf("%s: received msg %d/%d of the %s handshake from %s\n",
@@ -237,8 +244,7 @@ ieee80211_recv_4way_msg1(struct ieee80211com *ic,
}
/*
- * 4-Way Handshake Message 2 is sent by the supplicant to the authenticator
- * (see 8.5.3.2).
+ * Process Message 2 of the 4-Way Handshake (sent by Supplicant).
*/
void
ieee80211_recv_4way_msg2(struct ieee80211com *ic,
@@ -306,8 +312,7 @@ ieee80211_recv_4way_msg2(struct ieee80211com *ic,
}
/*
- * 4-Way Handshake Message 3 is sent by the authenticator to the supplicant
- * (see 8.5.3.3).
+ * Process Message 3 of the 4-Way Handshake (sent by Authenticator).
*/
void
ieee80211_recv_4way_msg3(struct ieee80211com *ic,
@@ -316,7 +321,7 @@ ieee80211_recv_4way_msg3(struct ieee80211com *ic,
struct ieee80211_ptk tptk;
struct ieee80211_key *k;
const u_int8_t *frm, *efrm;
- const u_int8_t *rsnie1, *rsnie2, *gtk;
+ const u_int8_t *rsnie1, *rsnie2, *gtk, *igtk;
const u_int8_t *pmk;
u_int16_t info, reason = 0;
int keylen;
@@ -371,7 +376,7 @@ ieee80211_recv_4way_msg3(struct ieee80211com *ic,
* RSN IEs in message 3/4. We only take into account the IE of the
* version of the protocol we negotiated at association time.
*/
- rsnie1 = rsnie2 = gtk = NULL;
+ rsnie1 = rsnie2 = gtk = igtk = NULL;
while (frm + 2 <= efrm) {
if (frm + 2 + frm[1] > efrm)
break;
@@ -393,6 +398,10 @@ ieee80211_recv_4way_msg3(struct ieee80211com *ic,
case IEEE80211_KDE_GTK:
gtk = frm;
break;
+ case IEEE80211_KDE_IGTK:
+ if (ni->ni_flags & IEEE80211_NODE_MFP)
+ igtk = frm;
+ break;
}
} else if (memcmp(&frm[2], MICROSOFT_OUI, 3) == 0) {
switch (frm[5]) {
@@ -418,6 +427,12 @@ ieee80211_recv_4way_msg3(struct ieee80211com *ic,
DPRINTF(("GTK not encrypted\n"));
return;
}
+ /* GTK KDE must be included if IGTK KDE is present */
+ if (igtk != NULL && gtk == NULL) {
+ DPRINTF(("IGTK KDE found but GTK KDE missing\n"));
+ return;
+ }
+
/*
* Check that first WPA/RSN IE is identical to the one received in
* the beacon or probe response frame.
@@ -485,6 +500,7 @@ ieee80211_recv_4way_msg3(struct ieee80211com *ic,
reason = IEEE80211_REASON_AUTH_LEAVE;
goto deauth;
}
+ ni->ni_flags &= ~IEEE80211_NODE_TXRXPROT;
ni->ni_flags |= IEEE80211_NODE_RXPROT;
}
if (gtk != NULL) {
@@ -519,6 +535,35 @@ ieee80211_recv_4way_msg3(struct ieee80211com *ic,
goto deauth;
}
}
+ if (igtk != NULL) { /* implies MFP && gtk != NULL */
+ u_int16_t kid;
+
+ /* check that the IGTK KDE is valid */
+ if (igtk[1] != 4 + 24) {
+ reason = IEEE80211_REASON_AUTH_LEAVE;
+ goto deauth;
+ }
+ kid = LE_READ_2(&igtk[6]);
+ if (kid != 4 && kid != 5) {
+ DPRINTF(("unsupported IGTK id %u\n", kid));
+ reason = IEEE80211_REASON_AUTH_LEAVE;
+ goto deauth;
+ }
+ /* map IGTK to 802.11 key */
+ k = &ic->ic_nw_keys[kid];
+ memset(k, 0, sizeof(*k));
+ k->k_id = kid; /* either 4 or 5 */
+ k->k_cipher = ni->ni_rsngroupmgmtcipher;
+ k->k_flags = IEEE80211_KEY_IGTK;
+ k->k_mgmt_rsc = LE_READ_6(&igtk[8]); /* IPN */
+ k->k_len = 16;
+ memcpy(k->k_key, &igtk[14], k->k_len);
+ /* install the IGTK */
+ if ((*ic->ic_set_key)(ic, ni, k) != 0) {
+ reason = IEEE80211_REASON_AUTH_LEAVE;
+ goto deauth;
+ }
+ }
if (info & EAPOL_KEY_INSTALL)
ni->ni_flags |= IEEE80211_NODE_TXRXPROT;
@@ -540,8 +585,7 @@ ieee80211_recv_4way_msg3(struct ieee80211com *ic,
}
/*
- * 4-Way Handshake Message 4 is sent by the supplicant to the authenticator
- * (see 8.5.3.4).
+ * Process Message 4 of the 4-Way Handshake (sent by Supplicant).
*/
void
ieee80211_recv_4way_msg4(struct ieee80211com *ic,
@@ -655,8 +699,7 @@ ieee80211_recv_4way_msg2or4(struct ieee80211com *ic,
}
/*
- * Group Key Handshake Message 1 is sent by the authenticator to the
- * supplicant (see 8.5.4.1).
+ * Process Message 1 of the RSN Group Key Handshake (sent by Authenticator).
*/
void
ieee80211_recv_rsn_group_msg1(struct ieee80211com *ic,
@@ -664,9 +707,8 @@ ieee80211_recv_rsn_group_msg1(struct ieee80211com *ic,
{
struct ieee80211_key *k;
const u_int8_t *frm, *efrm;
- const u_int8_t *gtk;
- u_int16_t info;
- u_int8_t kid;
+ const u_int8_t *gtk, *igtk;
+ u_int16_t info, kid, reason = 0;
int keylen;
if (ic->ic_opmode != IEEE80211_M_STA &&
@@ -696,7 +738,7 @@ ieee80211_recv_rsn_group_msg1(struct ieee80211com *ic,
frm = (const u_int8_t *)&key[1];
efrm = frm + BE_READ_2(key->paylen);
- gtk = NULL;
+ gtk = igtk = NULL;
while (frm + 2 <= efrm) {
if (frm + 2 + frm[1] > efrm)
break;
@@ -709,6 +751,10 @@ ieee80211_recv_rsn_group_msg1(struct ieee80211com *ic,
case IEEE80211_KDE_GTK:
gtk = frm;
break;
+ case IEEE80211_KDE_IGTK:
+ if (ni->ni_flags & IEEE80211_NODE_MFP)
+ igtk = frm;
+ break;
}
}
break;
@@ -739,10 +785,35 @@ ieee80211_recv_rsn_group_msg1(struct ieee80211com *ic,
k->k_len = keylen;
/* install the GTK */
if ((*ic->ic_set_key)(ic, ni, k) != 0) {
- IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DEAUTH,
- IEEE80211_REASON_AUTH_LEAVE);
- ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
- return;
+ reason = IEEE80211_REASON_AUTH_LEAVE;
+ goto deauth;
+ }
+ if (igtk != NULL) { /* implies MFP */
+ /* check that the IGTK KDE is valid */
+ if (igtk[1] != 4 + 24) {
+ reason = IEEE80211_REASON_AUTH_LEAVE;
+ goto deauth;
+ }
+ kid = LE_READ_2(&igtk[6]);
+ if (kid != 4 && kid != 5) {
+ DPRINTF(("unsupported IGTK id %u\n", kid));
+ reason = IEEE80211_REASON_AUTH_LEAVE;
+ goto deauth;
+ }
+ /* map IGTK to 802.11 key */
+ k = &ic->ic_nw_keys[kid];
+ memset(k, 0, sizeof(*k));
+ k->k_id = kid; /* either 4 or 5 */
+ k->k_cipher = ni->ni_rsngroupmgmtcipher;
+ k->k_flags = IEEE80211_KEY_IGTK;
+ k->k_mgmt_rsc = LE_READ_6(&igtk[8]); /* IPN */
+ k->k_len = 16;
+ memcpy(k->k_key, &igtk[14], k->k_len);
+ /* install the IGTK */
+ if ((*ic->ic_set_key)(ic, ni, k) != 0) {
+ reason = IEEE80211_REASON_AUTH_LEAVE;
+ goto deauth;
+ }
}
if (info & EAPOL_KEY_SECURE) {
if (ic->ic_opmode != IEEE80211_M_IBSS ||
@@ -761,9 +832,16 @@ ieee80211_recv_rsn_group_msg1(struct ieee80211com *ic,
ether_sprintf(ni->ni_macaddr));
/* send message 2 to authenticator */
- (void)ieee80211_send_group_msg2(ic, ni, k);
+ (void)ieee80211_send_group_msg2(ic, ni, NULL);
+ return;
+ deauth:
+ IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DEAUTH, reason);
+ ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
}
+/*
+ * Process Message 1 of the WPA Group Key Handshake (sent by Authenticator).
+ */
void
ieee80211_recv_wpa_group_msg1(struct ieee80211com *ic,
struct ieee80211_eapol_key *key, struct ieee80211_node *ni)
@@ -847,8 +925,7 @@ ieee80211_recv_wpa_group_msg1(struct ieee80211com *ic,
}
/*
- * Group Key Handshake Message 2 is sent by the supplicant to the
- * authenticator (see 8.5.4.2).
+ * Process Message 2 of the Group Key Handshake (sent by Supplicant).
*/
void
ieee80211_recv_group_msg2(struct ieee80211com *ic,
@@ -917,7 +994,7 @@ ieee80211_recv_eapol_key_req(struct ieee80211com *ic,
if (!(info & EAPOL_KEY_KEYMIC) ||
ieee80211_eapol_key_check_mic(key, ni->ni_ptk.kck) != 0) {
- DPRINTF(("key MIC failed\n"));
+ DPRINTF(("key request MIC failed\n"));
ic->ic_stats.is_rx_eapol_badmic++;
return;
}
diff --git a/sys/net80211/ieee80211_pae_output.c b/sys/net80211/ieee80211_pae_output.c
index b1e2c04bcc9..66b406978e1 100644
--- a/sys/net80211/ieee80211_pae_output.c
+++ b/sys/net80211/ieee80211_pae_output.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ieee80211_pae_output.c,v 1.5 2008/08/02 08:33:21 damien Exp $ */
+/* $OpenBSD: ieee80211_pae_output.c,v 1.6 2008/08/12 18:22:41 damien Exp $ */
/*-
* Copyright (c) 2007,2008 Damien Bergamini <damien.bergamini@free.fr>
@@ -16,6 +16,12 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+/*
+ * This code implements the 4-Way Handshake and Group Key Handshake protocols
+ * (both Supplicant and Authenticator Key Transmit state machines) defined in
+ * IEEE Std 802.11-2007 section 8.5.
+ */
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/mbuf.h>
@@ -45,9 +51,11 @@
int ieee80211_send_eapol_key(struct ieee80211com *, struct mbuf *,
struct ieee80211_node *, const struct ieee80211_ptk *);
-u_int8_t *ieee80211_add_gtk_kde(u_int8_t *, struct ieee80211_node *,
+u_int8_t *ieee80211_add_gtk_kde(u_int8_t *, struct ieee80211_node *,
const struct ieee80211_key *);
u_int8_t *ieee80211_add_pmkid_kde(u_int8_t *, const u_int8_t *);
+u_int8_t *ieee80211_add_igtk_kde(u_int8_t *,
+ const struct ieee80211_key *);
struct mbuf *ieee80211_get_eapol_key(int, int, u_int);
/*
@@ -199,6 +207,24 @@ ieee80211_add_pmkid_kde(u_int8_t *frm, const u_int8_t *pmkid)
return frm + IEEE80211_PMKID_LEN;
}
+/*
+ * Add an IGTK KDE to an EAPOL-Key frame (see Figure 8-32a).
+ */
+u_int8_t *
+ieee80211_add_igtk_kde(u_int8_t *frm, const struct ieee80211_key *k)
+{
+ KASSERT(k->k_flags & IEEE80211_KEY_IGTK);
+
+ *frm++ = IEEE80211_ELEMID_VENDOR;
+ *frm++ = 4 + 24;
+ memcpy(frm, IEEE80211_OUI, 3); frm += 3;
+ *frm++ = IEEE80211_KDE_IGTK;
+ LE_WRITE_2(frm, k->k_id); frm += 2;
+ LE_WRITE_6(frm, k->k_tsc); frm += 6; /* IPN */
+ memcpy(frm, k->k_key, 16);
+ return frm + 16;
+}
+
struct mbuf *
ieee80211_get_eapol_key(int flags, int type, u_int pktlen)
{
@@ -223,8 +249,7 @@ ieee80211_get_eapol_key(int flags, int type, u_int pktlen)
}
/*
- * 4-Way Handshake Message 1 is sent by the authenticator to the supplicant
- * (see 8.5.3.1).
+ * Send 4-Way Handshake Message 1 to the supplicant.
*/
int
ieee80211_send_4way_msg1(struct ieee80211com *ic, struct ieee80211_node *ni)
@@ -279,8 +304,7 @@ ieee80211_send_4way_msg1(struct ieee80211com *ic, struct ieee80211_node *ni)
}
/*
- * 4-Way Handshake Message 2 is sent by the supplicant to the authenticator
- * (see 8.5.3.2).
+ * Send 4-Way Handshake Message 2 to the authenticator.
*/
int
ieee80211_send_4way_msg2(struct ieee80211com *ic, struct ieee80211_node *ni,
@@ -310,7 +334,7 @@ ieee80211_send_4way_msg2(struct ieee80211com *ic, struct ieee80211_node *ni,
frm = (u_int8_t *)&key[1];
/* add the WPA/RSN IE used in the (Re)Association Request */
if (ni->ni_rsnprotos == IEEE80211_PROTO_WPA) {
- u_int16_t keylen;
+ int keylen;
frm = ieee80211_add_wpa(frm, ic, ni);
/* WPA sets the key length field here */
keylen = ieee80211_cipher_keylen(ni->ni_rsncipher);
@@ -329,8 +353,7 @@ ieee80211_send_4way_msg2(struct ieee80211com *ic, struct ieee80211_node *ni,
}
/*
- * 4-Way Handshake Message 3 is sent by the authenticator to the supplicant
- * (see 8.5.3.3).
+ * Send 4-Way Handshake Message 3 to the supplicant.
*/
int
ieee80211_send_4way_msg3(struct ieee80211com *ic, struct ieee80211_node *ni)
@@ -355,6 +378,7 @@ ieee80211_send_4way_msg3(struct ieee80211com *ic, struct ieee80211_node *ni)
2 + 48 +
((ni->ni_rsnprotos == IEEE80211_PROTO_RSN) ?
2 + 6 + k->k_len : 0) +
+ ((ni->ni_flags & IEEE80211_NODE_MFP) ? 2 + 28 : 0) +
8);
if (m == NULL)
return ENOMEM;
@@ -378,9 +402,15 @@ ieee80211_send_4way_msg3(struct ieee80211com *ic, struct ieee80211_node *ni)
/* add the WPA/RSN IE included in Beacon/Probe Response */
if (ni->ni_rsnprotos == IEEE80211_PROTO_RSN) {
frm = ieee80211_add_rsn(frm, ic, ic->ic_bss);
- /* encapsulate the GTK and ask for encryption */
+ /* encapsulate the GTK */
frm = ieee80211_add_gtk_kde(frm, ni, k);
LE_WRITE_6(key->rsc, k->k_tsc);
+ /* encapsulate the IGTK if MFP was negotiated */
+ if (ni->ni_flags & IEEE80211_NODE_MFP) {
+ frm = ieee80211_add_igtk_kde(frm,
+ &ic->ic_nw_keys[ic->ic_igtk_kid]);
+ }
+ /* ask that the EAPOL-Key frame be encrypted */
info |= EAPOL_KEY_ENCRYPTED | EAPOL_KEY_SECURE;
} else /* WPA */
frm = ieee80211_add_wpa(frm, ic, ic->ic_bss);
@@ -399,8 +429,7 @@ ieee80211_send_4way_msg3(struct ieee80211com *ic, struct ieee80211_node *ni)
}
/*
- * 4-Way Handshake Message 4 is sent by the supplicant to the authenticator
- * (see 8.5.3.4).
+ * Send 4-Way Handshake Message 4 to the authenticator.
*/
int
ieee80211_send_4way_msg4(struct ieee80211com *ic, struct ieee80211_node *ni)
@@ -421,7 +450,7 @@ ieee80211_send_4way_msg4(struct ieee80211com *ic, struct ieee80211_node *ni)
BE_WRITE_8(key->replaycnt, ni->ni_replaycnt);
if (ni->ni_rsnprotos == IEEE80211_PROTO_WPA) {
- u_int16_t keylen;
+ int keylen;
/* WPA sets the key length field here */
keylen = ieee80211_cipher_keylen(ni->ni_rsncipher);
BE_WRITE_2(key->keylen, keylen);
@@ -443,8 +472,7 @@ ieee80211_send_4way_msg4(struct ieee80211com *ic, struct ieee80211_node *ni)
}
/*
- * Group Key Handshake Message 1 is sent by the authenticator to the
- * supplicant (see 8.5.4.1).
+ * Send Group Key Handshake Message 1 to the supplicant.
*/
int
ieee80211_send_group_msg1(struct ieee80211com *ic, struct ieee80211_node *ni)
@@ -467,6 +495,7 @@ ieee80211_send_group_msg1(struct ieee80211com *ic, struct ieee80211_node *ni)
m = ieee80211_get_eapol_key(M_DONTWAIT, MT_DATA,
((ni->ni_rsnprotos == IEEE80211_PROTO_WPA) ?
k->k_len : 2 + 6 + k->k_len) +
+ ((ni->ni_flags & IEEE80211_NODE_MFP) ? 2 + 28 : 0) +
8);
if (m == NULL)
return ENOMEM;
@@ -488,9 +517,13 @@ ieee80211_send_group_msg1(struct ieee80211com *ic, struct ieee80211_node *ni)
info |= (k->k_id & 0x3) << EAPOL_KEY_WPA_KID_SHIFT;
if (ni->ni_rsncipher == IEEE80211_CIPHER_USEGROUP)
info |= EAPOL_KEY_WPA_TX;
- } else /* RSN */
+ } else { /* RSN */
frm = ieee80211_add_gtk_kde(frm, ni, k);
-
+ if (ni->ni_flags & IEEE80211_NODE_MFP) {
+ frm = ieee80211_add_igtk_kde(frm,
+ &ic->ic_nw_keys[ic->ic_igtk_kid]);
+ }
+ }
/* RSC = last transmit sequence number for the GTK */
LE_WRITE_6(key->rsc, k->k_tsc);
@@ -508,8 +541,7 @@ ieee80211_send_group_msg1(struct ieee80211com *ic, struct ieee80211_node *ni)
}
/*
- * Group Key Handshake Message 2 is sent by the supplicant to the
- * authenticator (see 8.5.4.2).
+ * Send Group Key Handshake Message 2 to the authenticator.
*/
int
ieee80211_send_group_msg2(struct ieee80211com *ic, struct ieee80211_node *ni,