summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorDamien Bergamini <damien@cvs.openbsd.org>2007-08-03 16:51:07 +0000
committerDamien Bergamini <damien@cvs.openbsd.org>2007-08-03 16:51:07 +0000
commit69e7d352546777fc42fce40fff48d89cf7e80e15 (patch)
tree1a06eb2572cf6c80f0b70c6551616bbd4f783731 /sys
parent417f2dcb45a6c362809659e8a00256ea2751eaae (diff)
add a ni_eapol_desc field to struct ieee80211_node to know whether
a station is using WPA1 or RSN descriptors. make sure that a station that advertises WPA1 capability in an IE uses the WPA1 EAPOL-Key descriptor type and not the RSN one. fix construction of EAPOL-Key frames for WPA1. i can now successfuly complete a 4-way and group-key handshake with both a WPA1 and a WPA2 access point. add some TKIP encapsulation code (no SW crypto yet). ok deraadt@
Diffstat (limited to 'sys')
-rw-r--r--sys/net80211/ieee80211_crypto.c105
-rw-r--r--sys/net80211/ieee80211_input.c16
-rw-r--r--sys/net80211/ieee80211_node.h3
-rw-r--r--sys/net80211/ieee80211_output.c106
-rw-r--r--sys/net80211/ieee80211_proto.h6
5 files changed, 187 insertions, 49 deletions
diff --git a/sys/net80211/ieee80211_crypto.c b/sys/net80211/ieee80211_crypto.c
index e40fb03b3bd..83e3fe30d03 100644
--- a/sys/net80211/ieee80211_crypto.c
+++ b/sys/net80211/ieee80211_crypto.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ieee80211_crypto.c,v 1.30 2007/08/01 15:40:40 damien Exp $ */
+/* $OpenBSD: ieee80211_crypto.c,v 1.31 2007/08/03 16:51:06 damien Exp $ */
/* $NetBSD: ieee80211_crypto.c,v 1.5 2003/12/14 09:56:53 dyoung Exp $ */
/*-
@@ -78,6 +78,10 @@ struct mbuf *ieee80211_ccmp_encrypt(struct ieee80211com *, struct mbuf *,
struct ieee80211_key *);
struct mbuf *ieee80211_ccmp_decrypt(struct ieee80211com *, struct mbuf *,
struct ieee80211_key *);
+struct mbuf *ieee80211_tkip_encrypt(struct ieee80211com *, struct mbuf *,
+ struct ieee80211_key *);
+struct mbuf *ieee80211_tkip_decrypt(struct ieee80211com *, struct mbuf *,
+ struct ieee80211_key *);
void ieee80211_aes_key_wrap(const u_int8_t *, size_t, const u_int8_t *,
size_t, u_int8_t *);
int ieee80211_aes_key_unwrap(const u_int8_t *, size_t, const u_int8_t *,
@@ -135,13 +139,16 @@ ieee80211_encrypt(struct ieee80211com *ic, struct mbuf *m0,
k = &ni->ni_pairwise_key;
switch (k->k_cipher) {
- case IEEE80211_CIPHER_CCMP:
- m0 = ieee80211_ccmp_encrypt(ic, m0, k);
- break;
case IEEE80211_CIPHER_WEP40:
case IEEE80211_CIPHER_WEP104:
m0 = ieee80211_wep_crypt(&ic->ic_if, m0, 1);
break;
+ case IEEE80211_CIPHER_TKIP:
+ m0 = ieee80211_tkip_encrypt(ic, m0, k);
+ break;
+ case IEEE80211_CIPHER_CCMP:
+ m0 = ieee80211_ccmp_encrypt(ic, m0, k);
+ break;
default:
/* should not get there */
m_freem(m0);
@@ -170,13 +177,16 @@ ieee80211_decrypt(struct ieee80211com *ic, struct mbuf *m0,
k = &ni->ni_pairwise_key;
switch (k->k_cipher) {
- case IEEE80211_CIPHER_CCMP:
- m0 = ieee80211_ccmp_decrypt(ic, m0, k);
- break;
case IEEE80211_CIPHER_WEP40:
case IEEE80211_CIPHER_WEP104:
m0 = ieee80211_wep_crypt(&ic->ic_if, m0, 0);
break;
+ case IEEE80211_CIPHER_TKIP:
+ m0 = ieee80211_tkip_decrypt(ic, m0, k);
+ break;
+ case IEEE80211_CIPHER_CCMP:
+ m0 = ieee80211_ccmp_decrypt(ic, m0, k);
+ break;
default:
/* should not get there */
m_freem(m0);
@@ -263,6 +273,87 @@ ieee80211_ccmp_decrypt(struct ieee80211com *ic, struct mbuf *m0,
return m0;
}
+#define IEEE80211_TKIP_HDRLEN 8
+#define IEEE80211_TKIP_MICLEN 8
+#define IEEE80211_TKIP_ICVLEN 4
+
+struct mbuf *
+ieee80211_tkip_encrypt(struct ieee80211com *ic, struct mbuf *m0,
+ struct ieee80211_key *k)
+{
+ struct ieee80211_frame *wh;
+ size_t hdrlen = sizeof(*wh); /* XXX QoS */
+ u_int8_t *ivp;
+
+ M_PREPEND(m0, IEEE80211_TKIP_HDRLEN, M_NOWAIT);
+ if (m0 == NULL)
+ return m0;
+ wh = mtod(m0, struct ieee80211_frame *);
+ ovbcopy(mtod(m0, u_int8_t *) + IEEE80211_TKIP_HDRLEN, wh, hdrlen);
+ ivp = (u_int8_t *)wh + hdrlen;
+
+ ivp[0] = k->k_tsc >> 8; /* TSC1 */
+ /* WEP Seed = (TSC1 | 0x20) & 0x7f (see 8.3.2.2) */
+ ivp[1] = (ivp[0] | 0x20) & 0x7f;
+ ivp[2] = k->k_tsc; /* TSC0 */
+ ivp[3] = k->k_id << 6 | IEEE80211_WEP_EXTIV; /* KeyID | ExtIV */
+ ivp[4] = k->k_tsc >> 16; /* TSC2 */
+ ivp[5] = k->k_tsc >> 24; /* TSC3 */
+ ivp[6] = k->k_tsc >> 32; /* TSC4 */
+ ivp[7] = k->k_tsc >> 40; /* TSC5 */
+
+ /* XXX encrypt payload if HW encryption not supported */
+
+ k->k_tsc++; /* increment the 48-bit TSC */
+
+ return m0;
+}
+
+struct mbuf *
+ieee80211_tkip_decrypt(struct ieee80211com *ic, struct mbuf *m0,
+ struct ieee80211_key *k)
+{
+ struct ieee80211_frame *wh;
+ size_t hdrlen = sizeof(*wh); /* XXX QoS */
+ u_int64_t tsc;
+ u_int8_t *ivp;
+
+ wh = mtod(m0, struct ieee80211_frame *);
+ ivp = (u_int8_t *)wh + hdrlen;
+
+ /* check that ExtIV bit is be set */
+ if (!(ivp[3] & IEEE80211_WEP_EXTIV)) {
+ m_freem(m0);
+ return NULL;
+ }
+ /* extract the 48-bit TSC from the TKIP header */
+ tsc = (u_int64_t)ivp[2] |
+ (u_int64_t)ivp[0] << 8 |
+ (u_int64_t)ivp[4] << 16 |
+ (u_int64_t)ivp[5] << 24 |
+ (u_int64_t)ivp[6] << 32 |
+ (u_int64_t)ivp[7] << 40;
+ /* NB: the keys are refreshed, we'll never overflow the 48 bits */
+ if (tsc <= k->k_rsc) {
+ /* replayed frame, discard */
+ /* XXX statistics */
+ m_freem(m0);
+ return NULL;
+ }
+
+ /* XXX decrypt payload if HW encryption not supported */
+
+ ovbcopy(mtod(m0, u_int8_t *),
+ mtod(m0, u_int8_t *) + IEEE80211_TKIP_HDRLEN, hdrlen);
+ m_adj(m0, IEEE80211_TKIP_HDRLEN);
+ m_adj(m0, -IEEE80211_TKIP_ICVLEN);
+
+ /* update last seen packet number */
+ k->k_rsc = tsc;
+
+ return m0;
+}
+
/* Round up to a multiple of IEEE80211_WEP_KEYLEN + IEEE80211_WEP_IVLEN */
#define klen_round(x) \
(((x) + (IEEE80211_WEP_KEYLEN + IEEE80211_WEP_IVLEN - 1)) & \
diff --git a/sys/net80211/ieee80211_input.c b/sys/net80211/ieee80211_input.c
index 6526ac7f418..9831f537106 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.59 2007/08/01 18:14:00 damien Exp $ */
+/* $OpenBSD: ieee80211_input.c,v 1.60 2007/08/03 16:51:06 damien Exp $ */
/*-
* Copyright (c) 2001 Atsushi Onoe
* Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
@@ -2020,7 +2020,7 @@ ieee80211_recv_4way_msg2(struct ieee80211com *ic,
* The RSN IE must match bit-wise with what the STA included in its
* (Re)Association Request.
*/
- if (rsn[1] != ni->ni_rsnie[1] ||
+ if (ni->ni_rsnie == NULL || rsn[1] != ni->ni_rsnie[1] ||
memcmp(rsn, ni->ni_rsnie, 2 + rsn[1]) != 0)
return;
@@ -2103,7 +2103,7 @@ ieee80211_recv_4way_msg3(struct ieee80211com *ic,
* Check that first RSN IE is identical to the one received in
* the beacon or probe response frame.
*/
- if (rsn1[1] != ni->ni_rsnie[1] ||
+ if (ni->ni_rsnie == NULL || rsn1[1] != ni->ni_rsnie[1] ||
memcmp(rsn1, ni->ni_rsnie, 2 + rsn1[1]) != 0)
return;
@@ -2291,7 +2291,7 @@ ieee80211_recv_rsn_group_msg1(struct ieee80211com *ic,
ether_sprintf(ni->ni_macaddr));
/* send message 2 to authenticator */
- ieee80211_send_group_msg2(ic, ni);
+ ieee80211_send_group_msg2(ic, ni, k);
}
void
@@ -2346,7 +2346,7 @@ ieee80211_recv_wpa_group_msg1(struct ieee80211com *ic,
ether_sprintf(ni->ni_macaddr));
/* send message 2 to authenticator */
- ieee80211_send_group_msg2(ic, ni);
+ ieee80211_send_group_msg2(ic, ni, k);
}
/*
@@ -2436,7 +2436,7 @@ ieee80211_print_eapol_key(struct ieee80211com *ic,
printf("\n");
printf("Key RSC=0x");
for (i = 0; i < 8; i++)
- printf("%02x", key->replaycnt[i]);
+ printf("%02x", key->rsc[i]);
printf("\n");
printf("Key MIC=0x");
for (i = 0; i < EAPOL_KEY_MIC_LEN; i++)
@@ -2462,9 +2462,7 @@ ieee80211_recv_eapol(struct ieee80211com *ic, struct mbuf *m0,
m_adj(m0, sizeof(struct ether_header));
key = mtod(m0, struct ieee80211_eapol_key *);
- if (key->type != EAPOL_KEY ||
- (key->desc != EAPOL_KEY_DESC_IEEE80211 &&
- key->desc != EAPOL_KEY_DESC_WPA1))
+ if (key->type != EAPOL_KEY || key->desc != ni->ni_eapol_desc)
goto out;
/* check packet body length */
diff --git a/sys/net80211/ieee80211_node.h b/sys/net80211/ieee80211_node.h
index 72919b64588..bf4401021ef 100644
--- a/sys/net80211/ieee80211_node.h
+++ b/sys/net80211/ieee80211_node.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ieee80211_node.h,v 1.20 2007/08/01 15:40:40 damien Exp $ */
+/* $OpenBSD: ieee80211_node.h,v 1.21 2007/08/03 16:51:06 damien Exp $ */
/* $NetBSD: ieee80211_node.h,v 1.9 2004/04/30 22:57:32 dyoung Exp $ */
/*-
@@ -120,6 +120,7 @@ struct ieee80211_node {
u_int ni_akmset;
u_int16_t ni_rsncaps;
int ni_port_valid;
+ u_int8_t ni_eapol_desc;
u_int8_t ni_nonce[EAPOL_KEY_NONCE_LEN];
u_int64_t ni_replaycnt;
u_int8_t ni_replaycnt_ok;
diff --git a/sys/net80211/ieee80211_output.c b/sys/net80211/ieee80211_output.c
index 4d052815c0a..181d7d5af34 100644
--- a/sys/net80211/ieee80211_output.c
+++ b/sys/net80211/ieee80211_output.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ieee80211_output.c,v 1.53 2007/08/01 13:10:01 damien Exp $ */
+/* $OpenBSD: ieee80211_output.c,v 1.54 2007/08/03 16:51:06 damien Exp $ */
/* $NetBSD: ieee80211_output.c,v 1.13 2004/05/31 11:02:55 dyoung Exp $ */
/*-
@@ -1104,6 +1104,7 @@ ieee80211_get_deauth(struct ieee80211com *ic, struct ieee80211_node *ni,
if (m == NULL)
return NULL;
MH_ALIGN(m, 2);
+
m->m_pkthdr.len = m->m_len = 2;
*mtod(m, u_int16_t *) = htole16(reason);
@@ -1526,7 +1527,7 @@ ieee80211_send_eapol_key(struct ieee80211com *ic, struct mbuf *m,
key = (struct ieee80211_eapol_key *)&eh[1];
key->version = EAPOL_VERSION;
key->type = EAPOL_KEY;
- key->desc = EAPOL_KEY_DESC_IEEE80211; /* XXX WPA1 */
+ key->desc = ni->ni_eapol_desc;
info = BE_READ_2(key->info);
/* use V2 descriptor only when pairwise cipher is CCMP */
@@ -1630,7 +1631,7 @@ ieee80211_send_4way_msg1(struct ieee80211com *ic, struct ieee80211_node *ni)
u_int8_t *frm;
m = ieee80211_get_eapol_key(M_DONTWAIT, MT_DATA,
- 2 + 20);
+ (ni->ni_eapol_desc == EAPOL_KEY_DESC_IEEE80211) ? 2 + 20 : 0);
if (m == NULL)
return ENOMEM;
key = mtod(m, struct ieee80211_eapol_key *);
@@ -1643,13 +1644,15 @@ ieee80211_send_4way_msg1(struct ieee80211com *ic, struct ieee80211_node *ni)
get_random_bytes(ni->ni_nonce, EAPOL_KEY_NONCE_LEN);
memcpy(key->nonce, ni->ni_nonce, EAPOL_KEY_NONCE_LEN);
- /* XXX retrieve PMKID from the PMKSA cache */
-
keylen = ieee80211_cipher_keylen(ni->ni_pairwise_cipher);
BE_WRITE_2(key->keylen, keylen);
frm = (u_int8_t *)&key[1];
- frm = ieee80211_add_pmkid_kde(frm, pmkid);
+ /* WPA1 does not have PMKID KDE */
+ if (ni->ni_eapol_desc == EAPOL_KEY_DESC_IEEE80211) {
+ /* XXX retrieve PMKID from the PMKSA cache */
+ frm = ieee80211_add_pmkid_kde(frm, pmkid);
+ }
m->m_pkthdr.len = m->m_len = frm - (u_int8_t *)key;
@@ -1675,7 +1678,7 @@ ieee80211_send_4way_msg2(struct ieee80211com *ic, struct ieee80211_node *ni,
u_int8_t *frm;
m = ieee80211_get_eapol_key(M_DONTWAIT, MT_DATA,
- 2 + 44);
+ 2 + 48);
if (m == NULL)
return ENOMEM;
key = mtod(m, struct ieee80211_eapol_key *);
@@ -1687,11 +1690,19 @@ ieee80211_send_4way_msg2(struct ieee80211com *ic, struct ieee80211_node *ni,
/* copy key replay counter from authenticator */
BE_WRITE_8(key->replaycnt, ni->ni_replaycnt);
+ /* copy the supplicant's nonce (SNonce) */
memcpy(key->nonce, snonce, EAPOL_KEY_NONCE_LEN);
frm = (u_int8_t *)&key[1];
- /* add the RSN IE used in the (Re)Association Request */
- frm = ieee80211_add_rsn(frm, ic, ni);
+ /* add the WPA/RSN IE used in the (Re)Association Request */
+ if (ni->ni_eapol_desc == EAPOL_KEY_DESC_WPA1) {
+ u_int16_t keylen;
+ frm = ieee80211_add_wpa1(frm, ic, ni);
+ /* WPA1 sets the key length field here */
+ keylen = ieee80211_cipher_keylen(ni->ni_pairwise_cipher);
+ BE_WRITE_2(key->keylen, keylen);
+ } else /* RSN */
+ frm = ieee80211_add_rsn(frm, ic, ni);
m->m_pkthdr.len = m->m_len = frm - (u_int8_t *)key;
@@ -1717,32 +1728,38 @@ ieee80211_send_4way_msg3(struct ieee80211com *ic, struct ieee80211_node *ni)
u_int8_t *frm;
m = ieee80211_get_eapol_key(M_DONTWAIT, MT_DATA,
- 2 + 44 +
- 2 + 6 + gtk->k_len +
+ 2 + 48 +
+ ((ni->ni_eapol_desc == EAPOL_KEY_DESC_IEEE80211) ?
+ 2 + 6 + gtk->k_len : 0) +
8);
if (m == NULL)
return ENOMEM;
key = mtod(m, struct ieee80211_eapol_key *);
memset(key, 0, sizeof(*key));
- /* XXX no need to encrypt if GTK is not included */
info = EAPOL_KEY_PAIRWISE | EAPOL_KEY_INSTALL | EAPOL_KEY_KEYACK |
- EAPOL_KEY_KEYMIC | EAPOL_KEY_SECURE | EAPOL_KEY_ENCRYPTED;
- BE_WRITE_2(key->info, info);
+ EAPOL_KEY_KEYMIC | EAPOL_KEY_SECURE;
BE_WRITE_8(key->replaycnt, ni->ni_replaycnt);
- /* use same Nonce as Message 1 */
+ /* use same nonce as in Message 1 */
memcpy(key->nonce, ni->ni_nonce, EAPOL_KEY_NONCE_LEN);
keylen = ieee80211_cipher_keylen(ni->ni_pairwise_cipher);
BE_WRITE_2(key->keylen, keylen);
frm = (u_int8_t *)&key[1];
- /* add the RSN IE included in Beacon/Probe Response */
- frm = ieee80211_add_rsn(frm, ic, ni);
- /* XXX always include GTK? */
- frm = ieee80211_add_gtk_kde(frm, gtk);
- LE_WRITE_8(key->rsc, gtk->k_rsc);
+ /* add the WPA/RSN IE included in Beacon/Probe Response */
+ if (ni->ni_eapol_desc == EAPOL_KEY_DESC_IEEE80211) {
+ frm = ieee80211_add_rsn(frm, ic, ic->ic_bss);
+ /* RSN: encapsulate the GTK and ask for encryption */
+ frm = ieee80211_add_gtk_kde(frm, gtk);
+ LE_WRITE_8(key->rsc, gtk->k_rsc);
+ info |= EAPOL_KEY_ENCRYPTED;
+ } else /* WPA1 */
+ frm = ieee80211_add_wpa1(frm, ic, ic->ic_bss);
+
+ /* write the key info field */
+ BE_WRITE_2(key->info, info);
m->m_pkthdr.len = m->m_len = frm - (u_int8_t *)key;
@@ -1765,7 +1782,7 @@ ieee80211_send_4way_msg4(struct ieee80211com *ic, struct ieee80211_node *ni)
struct mbuf *m;
u_int16_t info;
- m = ieee80211_get_eapol_key(M_DONTWAIT, MT_DATA, 8);
+ m = ieee80211_get_eapol_key(M_DONTWAIT, MT_DATA, 0);
if (m == NULL)
return ENOMEM;
key = mtod(m, struct ieee80211_eapol_key *);
@@ -1777,6 +1794,13 @@ ieee80211_send_4way_msg4(struct ieee80211com *ic, struct ieee80211_node *ni)
/* copy key replay counter from authenticator */
BE_WRITE_8(key->replaycnt, ni->ni_replaycnt);
+ if (ni->ni_eapol_desc == EAPOL_KEY_DESC_WPA1) {
+ u_int16_t keylen;
+ /* WPA1 sets the key length field here */
+ keylen = ieee80211_cipher_keylen(ni->ni_pairwise_cipher);
+ BE_WRITE_2(key->keylen, keylen);
+ }
+
/* empty key data field */
m->m_pkthdr.len = m->m_len = sizeof(*key);
@@ -1802,7 +1826,8 @@ ieee80211_send_group_msg1(struct ieee80211com *ic, struct ieee80211_node *ni)
u_int8_t *frm;
m = ieee80211_get_eapol_key(M_DONTWAIT, MT_DATA,
- 2 + 6 + gtk->k_len +
+ ((ni->ni_eapol_desc == EAPOL_KEY_DESC_WPA1) ?
+ gtk->k_len : 2 + 6 + gtk->k_len) +
8);
if (m == NULL)
return ENOMEM;
@@ -1811,14 +1836,26 @@ ieee80211_send_group_msg1(struct ieee80211com *ic, struct ieee80211_node *ni)
info = EAPOL_KEY_KEYACK | EAPOL_KEY_KEYMIC | EAPOL_KEY_SECURE |
EAPOL_KEY_ENCRYPTED;
- BE_WRITE_2(key->info, info);
BE_WRITE_8(key->replaycnt, ni->ni_replaycnt);
frm = (u_int8_t *)&key[1];
- frm = ieee80211_add_gtk_kde(frm, gtk);
+ if (ni->ni_eapol_desc == EAPOL_KEY_DESC_WPA1) {
+ /* WPA1 does not have GTK KDE */
+ BE_WRITE_2(key->keylen, gtk->k_len);
+ memcpy(frm, gtk->k_key, gtk->k_len);
+ frm += gtk->k_len;
+ info |= gtk->k_id << EAPOL_KEY_WPA_KID_SHIFT;
+ if (gtk->k_flags & IEEE80211_KEY_TX)
+ info |= EAPOL_KEY_WPA_TX;
+ } else /* RSN */
+ frm = ieee80211_add_gtk_kde(frm, gtk);
+
LE_WRITE_8(key->rsc, gtk->k_rsc);
+ /* write the key info field */
+ BE_WRITE_2(key->info, info);
+
m->m_pkthdr.len = m->m_len = frm - (u_int8_t *)key;
if (ic->ic_if.if_flags & IFF_DEBUG)
@@ -1834,7 +1871,8 @@ ieee80211_send_group_msg1(struct ieee80211com *ic, struct ieee80211_node *ni)
* authenticator (see 8.5.4.2).
*/
int
-ieee80211_send_group_msg2(struct ieee80211com *ic, struct ieee80211_node *ni)
+ieee80211_send_group_msg2(struct ieee80211com *ic, struct ieee80211_node *ni,
+ const struct ieee80211_key *gtk)
{
struct ieee80211_eapol_key *key;
u_int16_t info;
@@ -1847,11 +1885,19 @@ ieee80211_send_group_msg2(struct ieee80211com *ic, struct ieee80211_node *ni)
memset(key, 0, sizeof(*key));
info = EAPOL_KEY_KEYMIC | EAPOL_KEY_SECURE;
- BE_WRITE_2(key->info, info);
/* copy key replay counter from authenticator */
BE_WRITE_8(key->replaycnt, ni->ni_replaycnt);
+ if (ni->ni_eapol_desc == EAPOL_KEY_DESC_WPA1) {
+ /* WPA1 sets the key length and key id fields here */
+ BE_WRITE_2(key->keylen, gtk->k_len);
+ info |= (gtk->k_id & 3) << EAPOL_KEY_WPA_KID_SHIFT;
+ }
+
+ /* write the key info field */
+ BE_WRITE_2(key->info, info);
+
/* empty key data field */
m->m_pkthdr.len = m->m_len = sizeof(*key);
@@ -1870,11 +1916,10 @@ ieee80211_send_group_msg2(struct ieee80211com *ic, struct ieee80211_node *ni)
*/
int
ieee80211_send_eapol_key_req(struct ieee80211com *ic,
- struct ieee80211_node *ni, int is4way)
+ struct ieee80211_node *ni, u_int16_t info, u_int64_t tsc)
{
struct ieee80211_eapol_key *key;
struct mbuf *m;
- u_int16_t info;
m = ieee80211_get_eapol_key(M_DONTWAIT, MT_DATA, 0);
if (m == NULL)
@@ -1882,9 +1927,12 @@ ieee80211_send_eapol_key_req(struct ieee80211com *ic,
key = mtod(m, struct ieee80211_eapol_key *);
memset(key, 0, sizeof(*key));
- info = is4way ? EAPOL_KEY_PAIRWISE : 0;
BE_WRITE_2(key->info, info);
+ /* in case of TKIP MIC failure, fill the RSC field */
+ if (info & EAPOL_KEY_ERROR)
+ LE_WRITE_8(key->rsc, tsc);
+
/* use our separate key replay counter for key requests */
BE_WRITE_8(key->replaycnt, ic->ic_keyreplaycnt);
ic->ic_keyreplaycnt++;
diff --git a/sys/net80211/ieee80211_proto.h b/sys/net80211/ieee80211_proto.h
index e71667be7ef..a778c85a553 100644
--- a/sys/net80211/ieee80211_proto.h
+++ b/sys/net80211/ieee80211_proto.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ieee80211_proto.h,v 1.25 2007/08/01 12:47:55 damien Exp $ */
+/* $OpenBSD: ieee80211_proto.h,v 1.26 2007/08/03 16:51:06 damien Exp $ */
/* $NetBSD: ieee80211_proto.h,v 1.3 2003/10/13 04:23:56 dyoung Exp $ */
/*-
@@ -86,9 +86,9 @@ extern int ieee80211_send_4way_msg4(struct ieee80211com *,
extern int ieee80211_send_group_msg1(struct ieee80211com *,
struct ieee80211_node *);
extern int ieee80211_send_group_msg2(struct ieee80211com *,
- struct ieee80211_node *);
+ struct ieee80211_node *, const struct ieee80211_key *);
extern int ieee80211_send_eapol_key_req(struct ieee80211com *,
- struct ieee80211_node *, int);
+ struct ieee80211_node *, u_int16_t, u_int64_t);
extern void ieee80211_pwrsave(struct ieee80211com *, struct ieee80211_node *,
struct mbuf *);
extern struct mbuf *ieee80211_decap(struct ifnet *, struct mbuf *, int);