FT: Validate MDIE and FTIE in FT 4-way handshake message 2/4

This commit is contained in:
Jouni Malinen 2010-04-10 22:40:35 +03:00
parent 0d7b44099f
commit 0f857f43df
5 changed files with 67 additions and 13 deletions

View file

@ -539,6 +539,9 @@ void wpa_auth_sta_no_wpa(struct wpa_state_machine *sm)
static void wpa_free_sta_sm(struct wpa_state_machine *sm) static void wpa_free_sta_sm(struct wpa_state_machine *sm)
{ {
#ifdef CONFIG_IEEE80211R
os_free(sm->assoc_resp_ftie);
#endif /* CONFIG_IEEE80211R */
os_free(sm->last_rx_eapol_key); os_free(sm->last_rx_eapol_key);
os_free(sm->wpa_ie); os_free(sm->wpa_ie);
os_free(sm); os_free(sm);
@ -598,6 +601,56 @@ static int wpa_replay_counter_valid(struct wpa_state_machine *sm,
} }
#ifdef CONFIG_IEEE80211R
static int ft_check_msg_2_of_4(struct wpa_authenticator *wpa_auth,
struct wpa_state_machine *sm,
struct wpa_eapol_ie_parse *kde)
{
struct wpa_ie_data ie;
struct rsn_mdie *mdie;
if (wpa_parse_wpa_ie_rsn(kde->rsn_ie, kde->rsn_ie_len, &ie) < 0 ||
ie.num_pmkid != 1 || ie.pmkid == NULL) {
wpa_printf(MSG_DEBUG, "FT: No PMKR1Name in "
"FT 4-way handshake message 2/4");
return -1;
}
os_memcpy(sm->sup_pmk_r1_name, ie.pmkid, PMKID_LEN);
wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name from Supplicant",
sm->sup_pmk_r1_name, PMKID_LEN);
if (!kde->mdie || !kde->ftie) {
wpa_printf(MSG_DEBUG, "FT: No %s in FT 4-way handshake "
"message 2/4", kde->mdie ? "FTIE" : "MDIE");
return -1;
}
mdie = (struct rsn_mdie *) (kde->mdie + 2);
if (kde->mdie[1] < sizeof(struct rsn_mdie) ||
os_memcmp(wpa_auth->conf.mobility_domain, mdie->mobility_domain,
MOBILITY_DOMAIN_ID_LEN) != 0) {
wpa_printf(MSG_DEBUG, "FT: MDIE mismatch");
return -1;
}
if (sm->assoc_resp_ftie &&
(kde->ftie[1] != sm->assoc_resp_ftie[1] ||
os_memcmp(kde->ftie, sm->assoc_resp_ftie,
2 + sm->assoc_resp_ftie[1]) != 0)) {
wpa_printf(MSG_DEBUG, "FT: FTIE mismatch");
wpa_hexdump(MSG_DEBUG, "FT: FTIE in EAPOL-Key msg 2/4",
kde->ftie, kde->ftie_len);
wpa_hexdump(MSG_DEBUG, "FT: FTIE in (Re)AssocResp",
sm->assoc_resp_ftie, 2 + sm->assoc_resp_ftie[1]);
return -1;
}
return 0;
}
#endif /* CONFIG_IEEE80211R */
void wpa_receive(struct wpa_authenticator *wpa_auth, void wpa_receive(struct wpa_authenticator *wpa_auth,
struct wpa_state_machine *sm, struct wpa_state_machine *sm,
u8 *data, size_t data_len) u8 *data, size_t data_len)
@ -776,19 +829,9 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
return; return;
} }
#ifdef CONFIG_IEEE80211R #ifdef CONFIG_IEEE80211R
if (ft) { if (ft && ft_check_msg_2_of_4(wpa_auth, sm, &kde) < 0) {
struct wpa_ie_data ie; wpa_sta_disconnect(wpa_auth, sm->addr);
if (wpa_parse_wpa_ie_rsn(kde.rsn_ie, kde.rsn_ie_len, return;
&ie) < 0 ||
ie.num_pmkid != 1 || ie.pmkid == NULL) {
wpa_printf(MSG_DEBUG, "FT: No PMKR1Name in "
"FT 4-way handshake message 2/4");
wpa_sta_disconnect(wpa_auth, sm->addr);
return;
}
os_memcpy(sm->sup_pmk_r1_name, ie.pmkid, PMKID_LEN);
wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name from Supplicant",
sm->sup_pmk_r1_name, PMKID_LEN);
} }
#endif /* CONFIG_IEEE80211R */ #endif /* CONFIG_IEEE80211R */
break; break;

View file

@ -692,6 +692,11 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
ftie_len = res; ftie_len = res;
pos += res; pos += res;
os_free(sm->assoc_resp_ftie);
sm->assoc_resp_ftie = os_malloc(ftie_len);
if (sm->assoc_resp_ftie)
os_memcpy(sm->assoc_resp_ftie, ftie, ftie_len);
_ftie = (struct rsn_ftie *) (ftie + 2); _ftie = (struct rsn_ftie *) (ftie + 2);
if (auth_alg == WLAN_AUTH_FT) if (auth_alg == WLAN_AUTH_FT)
_ftie->mic_control[1] = 3; /* Information element count */ _ftie->mic_control[1] = 3; /* Information element count */

View file

@ -118,6 +118,7 @@ struct wpa_state_machine {
size_t r0kh_id_len; size_t r0kh_id_len;
u8 sup_pmk_r1_name[WPA_PMK_NAME_LEN]; /* PMKR1Name from EAPOL-Key u8 sup_pmk_r1_name[WPA_PMK_NAME_LEN]; /* PMKR1Name from EAPOL-Key
* message 2/4 */ * message 2/4 */
u8 *assoc_resp_ftie;
#endif /* CONFIG_IEEE80211R */ #endif /* CONFIG_IEEE80211R */
}; };

View file

@ -840,6 +840,9 @@ int wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie)
} else if (*pos == WLAN_EID_MOBILITY_DOMAIN) { } else if (*pos == WLAN_EID_MOBILITY_DOMAIN) {
ie->mdie = pos; ie->mdie = pos;
ie->mdie_len = pos[1] + 2; ie->mdie_len = pos[1] + 2;
} else if (*pos == WLAN_EID_FAST_BSS_TRANSITION) {
ie->ftie = pos;
ie->ftie_len = pos[1] + 2;
#endif /* CONFIG_IEEE80211R */ #endif /* CONFIG_IEEE80211R */
} else if (*pos == WLAN_EID_VENDOR_SPECIFIC) { } else if (*pos == WLAN_EID_VENDOR_SPECIFIC) {
ret = wpa_parse_generic(pos, end, ie); ret = wpa_parse_generic(pos, end, ie);

View file

@ -42,6 +42,8 @@ struct wpa_eapol_ie_parse {
#ifdef CONFIG_IEEE80211R #ifdef CONFIG_IEEE80211R
const u8 *mdie; const u8 *mdie;
size_t mdie_len; size_t mdie_len;
const u8 *ftie;
size_t ftie_len;
#endif /* CONFIG_IEEE80211R */ #endif /* CONFIG_IEEE80211R */
}; };