"initialization.");
} else {
wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "GMK rekeyd");
+ wpa_hexdump_key(MSG_DEBUG, "GMK",
+ wpa_auth->group->GMK, WPA_GMK_LEN);
}
if (wpa_auth->conf.wpa_gmk_rekey) {
os_free(group);
return NULL;
}
+ wpa_hexdump_key(MSG_DEBUG, "GMK", group->GMK, WPA_GMK_LEN);
sha1_prf(rkey, sizeof(rkey), "Init Counter", buf, sizeof(buf),
group->Counter, WPA_NONCE_LEN);
+ wpa_hexdump_key(MSG_DEBUG, "Key Counter",
+ group->Counter, WPA_NONCE_LEN);
group->GInit = TRUE;
wpa_group_sm_step(wpa_auth, group);
}
-static void wpa_gmk_to_gtk(const u8 *gmk, const u8 *addr, const u8 *gnonce,
- u8 *gtk, size_t gtk_len)
+static int wpa_gmk_to_gtk(const u8 *gmk, const char *label, const u8 *addr,
+ const u8 *gnonce, u8 *gtk, size_t gtk_len)
{
- u8 data[ETH_ALEN + WPA_NONCE_LEN];
+ u8 data[ETH_ALEN + WPA_NONCE_LEN + 8 + 16];
+ u8 *pos;
+ int ret = 0;
- /* GTK = PRF-X(GMK, "Group key expansion", AA || GNonce) */
+ /* GTK = PRF-X(GMK, "Group key expansion",
+ * AA || GNonce || Time || random data)
+ * The example described in the IEEE 802.11 standard uses only AA and
+ * GNonce as inputs here. Add some more entropy since this derivation
+ * is done only at the Authenticator and as such, does not need to be
+ * exactly same.
+ */
os_memcpy(data, addr, ETH_ALEN);
os_memcpy(data + ETH_ALEN, gnonce, WPA_NONCE_LEN);
+ pos = data + ETH_ALEN + WPA_NONCE_LEN;
+ wpa_get_ntp_timestamp(pos);
+ pos += 8;
+ if (os_get_random(pos, 16) < 0)
+ ret = -1;
#ifdef CONFIG_IEEE80211W
- sha256_prf(gmk, WPA_GMK_LEN, "Group key expansion",
- data, sizeof(data), gtk, gtk_len);
+ sha256_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data), gtk, gtk_len);
#else /* CONFIG_IEEE80211W */
- sha1_prf(gmk, WPA_GMK_LEN, "Group key expansion",
- data, sizeof(data), gtk, gtk_len);
+ if (sha1_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data), gtk, gtk_len)
+ < 0)
+ ret = -1;
#endif /* CONFIG_IEEE80211W */
- wpa_hexdump_key(MSG_DEBUG, "GMK", gmk, WPA_GMK_LEN);
- wpa_hexdump_key(MSG_DEBUG, "GTK", gtk, gtk_len);
+ return ret;
}
break;
case WPA_REAUTH:
case WPA_REAUTH_EAPOL:
+ if (!sm->started) {
+ /*
+ * When using WPS, we may end up here if the STA
+ * manages to re-associate without the previous STA
+ * entry getting removed. Consequently, we need to make
+ * sure that the WPA state machines gets initialized
+ * properly at this point.
+ */
+ wpa_printf(MSG_DEBUG, "WPA state machine had not been "
+ "started - initialize now");
+ sm->started = 1;
+ sm->Init = TRUE;
+ if (wpa_sm_step(sm) == 1)
+ return 1; /* should not really happen */
+ sm->Init = FALSE;
+ sm->AuthenticationRequest = TRUE;
+ break;
+ }
if (sm->GUpdateStationKeys) {
/*
* Reauthentication cancels the pending group key
{
int ret = 0;
- /* FIX: is this the correct way of getting GNonce? */
os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);
inc_byte_array(group->Counter, WPA_NONCE_LEN);
- wpa_gmk_to_gtk(group->GMK, wpa_auth->addr, group->GNonce,
- group->GTK[group->GN - 1], group->GTK_len);
+ if (wpa_gmk_to_gtk(group->GMK, "Group key expansion",
+ wpa_auth->addr, group->GNonce,
+ group->GTK[group->GN - 1], group->GTK_len) < 0)
+ ret = -1;
+ wpa_hexdump_key(MSG_DEBUG, "GTK",
+ group->GTK[group->GN - 1], group->GTK_len);
#ifdef CONFIG_IEEE80211W
if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) {
- if (os_get_random(group->IGTK[group->GN_igtk - 4],
- WPA_IGTK_LEN) < 0) {
- wpa_printf(MSG_INFO, "RSN: Failed to get new random "
- "IGTK");
+ os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);
+ inc_byte_array(group->Counter, WPA_NONCE_LEN);
+ if (wpa_gmk_to_gtk(group->GMK, "IGTK key expansion",
+ wpa_auth->addr, group->GNonce,
+ group->IGTK[group->GN_igtk - 4],
+ WPA_IGTK_LEN) < 0)
ret = -1;
- }
wpa_hexdump_key(MSG_DEBUG, "IGTK",
group->IGTK[group->GN_igtk - 4], WPA_IGTK_LEN);
}
}
-static void wpa_group_setkeysdone(struct wpa_authenticator *wpa_auth,
- struct wpa_group *group)
+static int wpa_group_setkeysdone(struct wpa_authenticator *wpa_auth,
+ struct wpa_group *group)
{
+ int ret = 0;
+
wpa_printf(MSG_DEBUG, "WPA: group state machine entering state "
"SETKEYSDONE (VLAN-ID %d)", group->vlan_id);
group->changed = TRUE;
group->wpa_group_state = WPA_GROUP_SETKEYSDONE;
- wpa_auth_set_key(wpa_auth, group->vlan_id,
- wpa_alg_enum(wpa_auth->conf.wpa_group),
- NULL, group->GN, group->GTK[group->GN - 1],
- group->GTK_len);
+ if (wpa_auth_set_key(wpa_auth, group->vlan_id,
+ wpa_alg_enum(wpa_auth->conf.wpa_group),
+ NULL, group->GN, group->GTK[group->GN - 1],
+ group->GTK_len) < 0)
+ ret = -1;
#ifdef CONFIG_IEEE80211W
- if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) {
- wpa_auth_set_key(wpa_auth, group->vlan_id, WPA_ALG_IGTK,
- NULL, group->GN_igtk,
- group->IGTK[group->GN_igtk - 4],
- WPA_IGTK_LEN);
- }
+ if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION &&
+ wpa_auth_set_key(wpa_auth, group->vlan_id, WPA_ALG_IGTK,
+ NULL, group->GN_igtk,
+ group->IGTK[group->GN_igtk - 4],
+ WPA_IGTK_LEN) < 0)
+ ret = -1;
#endif /* CONFIG_IEEE80211W */
+
+ return ret;
}