summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Bergamini <damien@cvs.openbsd.org>2007-08-01 12:59:34 +0000
committerDamien Bergamini <damien@cvs.openbsd.org>2007-08-01 12:59:34 +0000
commitcadc81b281ad7376a5ad46d616500de1a977316c (patch)
treef0d0f8d14d5f8ed19085f8c209cee956aede4d36
parentccbbf750f01f5f5f9266a13d1d91f1f105d7474a (diff)
group key handshake message 1 is very different between RSN and WPA1.
RSN uses a GTK KDE while WPA1 stores the GTK in the EAPOL-Key frame data field (encrypted) and uses some bits in the info field. split ieee80211_recv_group_msg1() in two separate functions.
-rw-r--r--sys/net80211/ieee80211_crypto.c4
-rw-r--r--sys/net80211/ieee80211_input.c71
2 files changed, 66 insertions, 9 deletions
diff --git a/sys/net80211/ieee80211_crypto.c b/sys/net80211/ieee80211_crypto.c
index 8fa037913c5..da7419022af 100644
--- a/sys/net80211/ieee80211_crypto.c
+++ b/sys/net80211/ieee80211_crypto.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ieee80211_crypto.c,v 1.28 2007/08/01 12:23:26 damien Exp $ */
+/* $OpenBSD: ieee80211_crypto.c,v 1.29 2007/08/01 12:59:33 damien Exp $ */
/* $NetBSD: ieee80211_crypto.c,v 1.5 2003/12/14 09:56:53 dyoung Exp $ */
/*-
@@ -779,7 +779,7 @@ ieee80211_eapol_key_decrypt(struct ieee80211_eapol_key *key,
}
/*
- * Return the length in bytes of keys used by the specified cipher.
+ * Return the length in bytes of a cipher suite key (see Table 60).
*/
int
ieee80211_cipher_keylen(enum ieee80211_cipher cipher)
diff --git a/sys/net80211/ieee80211_input.c b/sys/net80211/ieee80211_input.c
index 391c207db52..289d21ee428 100644
--- a/sys/net80211/ieee80211_input.c
+++ b/sys/net80211/ieee80211_input.c
@@ -1,5 +1,5 @@
/* $NetBSD: ieee80211_input.c,v 1.24 2004/05/31 11:12:24 dyoung Exp $ */
-/* $OpenBSD: ieee80211_input.c,v 1.52 2007/08/01 12:47:55 damien Exp $ */
+/* $OpenBSD: ieee80211_input.c,v 1.53 2007/08/01 12:59:33 damien Exp $ */
/*-
* Copyright (c) 2001 Atsushi Onoe
* Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
@@ -106,8 +106,10 @@ void ieee80211_recv_4way_msg3(struct ieee80211com *,
const struct ieee80211_eapol_key *, struct ieee80211_node *);
void ieee80211_recv_4way_msg4(struct ieee80211com *,
const struct ieee80211_eapol_key *, struct ieee80211_node *);
-void ieee80211_recv_group_msg1(struct ieee80211com *,
+void ieee80211_recv_rsn_group_msg1(struct ieee80211com *,
const struct ieee80211_eapol_key *, struct ieee80211_node *);
+void ieee80211_recv_wpa_group_msg1(struct ieee80211com *,
+ struct ieee80211_eapol_key *, struct ieee80211_node *);
void ieee80211_recv_group_msg2(struct ieee80211com *,
const struct ieee80211_eapol_key *, struct ieee80211_node *);
void ieee80211_recv_eapol_key_req(struct ieee80211com *,
@@ -2090,7 +2092,7 @@ ieee80211_recv_4way_msg3(struct ieee80211com *ic,
}
frm += 2 + frm[1];
}
- /* first RSN IE is mandatory */
+ /* first WPA/RSN IE is mandatory */
if (rsn1 == NULL)
return;
/* key data must be encrypted if GTK is included */
@@ -2207,7 +2209,7 @@ ieee80211_recv_4way_msg4(struct ieee80211com *ic,
* supplicant (see 8.5.4.1).
*/
void
-ieee80211_recv_group_msg1(struct ieee80211com *ic,
+ieee80211_recv_rsn_group_msg1(struct ieee80211com *ic,
const struct ieee80211_eapol_key *key, struct ieee80211_node *ni)
{
struct ieee80211_key k;
@@ -2278,6 +2280,58 @@ ieee80211_recv_group_msg1(struct ieee80211com *ic,
ieee80211_send_group_msg2(ic, ni);
}
+void
+ieee80211_recv_wpa_group_msg1(struct ieee80211com *ic,
+ struct ieee80211_eapol_key *key, struct ieee80211_node *ni)
+{
+ struct ieee80211_key k;
+ u_int16_t info;
+
+ if (ic->ic_opmode != IEEE80211_M_STA &&
+ ic->ic_opmode != IEEE80211_M_IBSS)
+ return;
+
+ if (BE_READ_8(key->replaycnt) <= ni->ni_replaycnt)
+ return;
+
+ /*
+ * EAPOL-Key data field is encrypted even though WPA1 doesn't set
+ * the ENCRYPTED bit in the info field.
+ */
+ if (!ni->ni_ptk_ok ||
+ ieee80211_eapol_key_decrypt(key, ni->ni_ptk.kek) != 0)
+ return;
+
+ info = BE_READ_2(key->info);
+
+ /* install the GTK */
+ memset(&k, 0, sizeof k);
+ k.k_id = (info >> EAPOL_KEY_WPA_KID_SHIFT) & 3;
+ k.k_cipher = ni->ni_group_cipher;
+ k.k_flags = IEEE80211_KEY_GROUP;
+ if (info & EAPOL_KEY_WPA_TX)
+ k.k_flags |= IEEE80211_KEY_TX;
+ k.k_len = BE_READ_2(key->keylen);
+ /* check that key length matches group cipher */
+ if (k.k_len != ieee80211_cipher_keylen(k.k_cipher))
+ return;
+ memcpy(k.k_key, (u_int8_t *)&key[1], k.k_len);
+ k.k_rsc = LE_READ_8(key->rsc);
+ if ((*ic->ic_set_key)(ic, ni, &k) != 0)
+ return;
+
+ /* update the last seen value of the key replay counter field */
+ ni->ni_replaycnt = BE_READ_8(key->replaycnt);
+
+ if (ic->ic_if.if_flags & IFF_DEBUG)
+ printf("%s: received msg %d/%d of the %s handshake from %s\n",
+ ic->ic_if.if_xname, 1, 2, "group key",
+ ether_sprintf(ni->ni_macaddr));
+
+ /* send message 2 to authenticator */
+ ieee80211_send_group_msg2(ic, ni);
+}
+
/*
* Group Key Handshake Message 2 is sent by the supplicant to the
* authenticator (see 8.5.4.2).
@@ -2448,9 +2502,12 @@ ieee80211_recv_eapol(struct ieee80211com *ic, struct mbuf *m0,
ieee80211_recv_4way_msg1(ic, key, ni);
} else {
/* Group Key Handshake */
- if (info & EAPOL_KEY_KEYACK)
- ieee80211_recv_group_msg1(ic, key, ni);
- else
+ if (info & EAPOL_KEY_KEYACK) {
+ if (key->desc == EAPOL_KEY_DESC_WPA1)
+ ieee80211_recv_wpa_group_msg1(ic, key, ni);
+ else
+ ieee80211_recv_rsn_group_msg1(ic, key, ni);
+ } else
ieee80211_recv_group_msg2(ic, key, ni);
}
out: