/*
* hostapd - IEEE 802.11i-2004 / WPA Authenticator
- * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
#ifndef CONFIG_NATIVE_WINDOWS
#include "common.h"
+#include "eloop.h"
+#include "crypto/aes_wrap.h"
+#include "crypto/crypto.h"
+#include "crypto/sha1.h"
+#include "crypto/sha256.h"
+#include "eapol_auth/eapol_auth_sm.h"
#include "config.h"
-#include "eapol_sm.h"
#include "wpa.h"
-#include "sha1.h"
-#include "sha256.h"
-#include "rc4.h"
-#include "aes_wrap.h"
-#include "crypto.h"
-#include "eloop.h"
#include "ieee802_11.h"
#include "pmksa_cache.h"
#include "state_machine.h"
static void wpa_group_sm_step(struct wpa_authenticator *wpa_auth,
struct wpa_group *group);
static void wpa_request_new_ptk(struct wpa_state_machine *sm);
+static int wpa_gtk_update(struct wpa_authenticator *wpa_auth,
+ struct wpa_group *group);
static const u32 dot11RSNAConfigGroupUpdateCount = 4;
static const u32 dot11RSNAConfigPairwiseUpdateCount = 4;
}
-static inline int wpa_auth_get_seqnum_igtk(struct wpa_authenticator *wpa_auth,
- const u8 *addr, int idx, u8 *seq)
-{
- if (wpa_auth->cb.get_seqnum_igtk == NULL)
- return -1;
- return wpa_auth->cb.get_seqnum_igtk(wpa_auth->cb.ctx, addr, idx, seq);
-}
-
-
static inline int
wpa_auth_send_eapol(struct wpa_authenticator *wpa_auth, const u8 *addr,
const u8 *data, size_t data_len, int encrypt)
}
-static struct wpa_group * wpa_group_init(struct wpa_authenticator *wpa_auth,
- int vlan_id)
+static void wpa_group_set_key_len(struct wpa_group *group, int cipher)
{
- struct wpa_group *group;
- u8 buf[ETH_ALEN + 8 + sizeof(group)];
- u8 rkey[32];
-
- group = os_zalloc(sizeof(struct wpa_group));
- if (group == NULL)
- return NULL;
-
- group->GTKAuthenticator = TRUE;
- group->vlan_id = vlan_id;
-
- switch (wpa_auth->conf.wpa_group) {
+ switch (cipher) {
case WPA_CIPHER_CCMP:
group->GTK_len = 16;
break;
group->GTK_len = 5;
break;
}
+}
+
+
+static struct wpa_group * wpa_group_init(struct wpa_authenticator *wpa_auth,
+ int vlan_id)
+{
+ struct wpa_group *group;
+ u8 buf[ETH_ALEN + 8 + sizeof(group)];
+ u8 rkey[32];
+
+ group = os_zalloc(sizeof(struct wpa_group));
+ if (group == NULL)
+ return NULL;
+
+ group->GTKAuthenticator = TRUE;
+ group->vlan_id = vlan_id;
+
+ wpa_group_set_key_len(group, wpa_auth->conf.wpa_group);
/* Counter = PRF-256(Random number, "Init Counter",
* Local MAC Address || Time)
int wpa_reconfig(struct wpa_authenticator *wpa_auth,
struct wpa_auth_config *conf)
{
+ struct wpa_group *group;
if (wpa_auth == NULL)
return 0;
return -1;
}
+ /*
+ * Reinitialize GTK to make sure it is suitable for the new
+ * configuration.
+ */
+ group = wpa_auth->group;
+ wpa_group_set_key_len(group, wpa_auth->conf.wpa_group);
+ group->GInit = TRUE;
+ wpa_group_sm_step(wpa_auth, group);
+ group->GInit = FALSE;
+ wpa_group_sm_step(wpa_auth, group);
+
return 0;
}
return;
}
+ if (sm->wpa == WPA_VERSION_WPA2) {
+ if (key->type != EAPOL_KEY_TYPE_RSN) {
+ wpa_printf(MSG_DEBUG, "Ignore EAPOL-Key with "
+ "unexpected type %d in RSN mode",
+ key->type);
+ return;
+ }
+ } else {
+ if (key->type != EAPOL_KEY_TYPE_WPA) {
+ wpa_printf(MSG_DEBUG, "Ignore EAPOL-Key with "
+ "unexpected type %d in WPA mode",
+ key->type);
+ return;
+ }
+ }
+
/* FIX: verify that the EAPOL-Key frame was encrypted if pairwise keys
* are set */
igtk.keyid[0] = gsm->GN_igtk;
igtk.keyid[1] = 0;
- if (wpa_auth_get_seqnum_igtk(sm->wpa_auth, NULL, gsm->GN_igtk, igtk.pn)
- < 0)
+ if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, igtk.pn) < 0)
os_memset(igtk.pn, 0, sizeof(igtk.pn));
os_memcpy(igtk.igtk, gsm->IGTK[gsm->GN_igtk - 4], WPA_IGTK_LEN);
pos = wpa_add_kde(pos, RSN_KEY_DATA_IGTK,