diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 105f1412b..1f76e9607 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -1633,10 +1633,12 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) return; } - /* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, GTK[GN]) + /* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, [MDIE], + GTK[GN], IGTK, [FTIE], [TIE * 2]) */ os_memset(rsc, 0, WPA_KEY_RSC_LEN); wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, rsc); + /* If FT is used, wpa_auth->wpa_ie includes both RSNIE and MDIE */ wpa_ie = sm->wpa_auth->wpa_ie; wpa_ie_len = sm->wpa_auth->wpa_ie_len; if (sm->wpa == WPA_VERSION_WPA && @@ -1669,8 +1671,10 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) if (gtk) kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len; #ifdef CONFIG_IEEE80211R - if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) - kde_len += 2 + PMKID_LEN; + if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { + kde_len += 2 + PMKID_LEN; /* PMKR1Name into RSN IE */ + kde_len += 300; /* FTIE + 2 * TIE */ + } #endif /* CONFIG_IEEE80211R */ kde = os_malloc(kde_len); if (kde == NULL) @@ -1700,6 +1704,40 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) } pos = ieee80211w_kde_add(sm, pos); +#ifdef CONFIG_IEEE80211R + if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { + int res; + struct wpa_auth_config *conf; + + conf = &sm->wpa_auth->conf; + res = wpa_write_ftie(conf, conf->r0_key_holder, + conf->r0_key_holder_len, + NULL, NULL, pos, kde + kde_len - pos, + NULL, 0); + if (res < 0) { + wpa_printf(MSG_ERROR, "FT: Failed to insert FTIE " + "into EAPOL-Key Key Data"); + os_free(kde); + return; + } + pos += res; + + /* TIE[ReassociationDeadline] (TU) */ + *pos++ = WLAN_EID_TIMEOUT_INTERVAL; + *pos++ = 5; + *pos++ = WLAN_TIMEOUT_REASSOC_DEADLINE; + WPA_PUT_LE32(pos, conf->reassociation_deadline); + pos += 4; + + /* TIE[KeyLifetime] (seconds) */ + *pos++ = WLAN_EID_TIMEOUT_INTERVAL; + *pos++ = 5; + *pos++ = WLAN_TIMEOUT_KEY_LIFETIME; + WPA_PUT_LE32(pos, conf->r0_key_lifetime * 60); + pos += 4; + } +#endif /* CONFIG_IEEE80211R */ + wpa_send_eapol(sm->wpa_auth, sm, (secure ? WPA_KEY_INFO_SECURE : 0) | WPA_KEY_INFO_MIC | WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL | diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c index 6e45af8e7..2c441ebdd 100644 --- a/src/ap/wpa_auth_ft.c +++ b/src/ap/wpa_auth_ft.c @@ -97,11 +97,11 @@ int wpa_write_mdie(struct wpa_auth_config *conf, u8 *buf, size_t len) } -static int wpa_write_ftie(struct wpa_auth_config *conf, const u8 *r0kh_id, - size_t r0kh_id_len, - const u8 *anonce, const u8 *snonce, - u8 *buf, size_t len, const u8 *subelem, - size_t subelem_len) +int wpa_write_ftie(struct wpa_auth_config *conf, const u8 *r0kh_id, + size_t r0kh_id_len, + const u8 *anonce, const u8 *snonce, + u8 *buf, size_t len, const u8 *subelem, + size_t subelem_len) { u8 *pos = buf, *ielen; struct rsn_ftie *hdr; diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h index 6d6ed54b9..a7cbfd06f 100644 --- a/src/ap/wpa_auth_i.h +++ b/src/ap/wpa_auth_i.h @@ -214,6 +214,11 @@ void wpa_smk_m3(struct wpa_authenticator *wpa_auth, #ifdef CONFIG_IEEE80211R int wpa_write_mdie(struct wpa_auth_config *conf, u8 *buf, size_t len); +int wpa_write_ftie(struct wpa_auth_config *conf, const u8 *r0kh_id, + size_t r0kh_id_len, + const u8 *anonce, const u8 *snonce, + u8 *buf, size_t len, const u8 *subelem, + size_t subelem_len); int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, const u8 *pmk, struct wpa_ptk *ptk, size_t ptk_len); struct wpa_ft_pmk_cache * wpa_ft_pmk_cache_init(void);