diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 56b8cfb8e..b4c6e032c 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -790,6 +790,78 @@ static void wpa_report_ie_mismatch(struct wpa_sm *sm, } +#ifdef CONFIG_IEEE80211R + +static int ft_validate_mdie(struct wpa_sm *sm, + const unsigned char *src_addr, + struct wpa_eapol_ie_parse *ie) +{ + struct rsn_mdie *mdie; + + /* TODO: verify that full MDIE matches with the one from scan + * results, not only mobility domain */ + + mdie = (struct rsn_mdie *) (ie->mdie + 2); + if (ie->mdie == NULL || ie->mdie_len < 2 + sizeof(*mdie) || + os_memcmp(mdie->mobility_domain, sm->mobility_domain, + MOBILITY_DOMAIN_ID_LEN) != 0) { + wpa_printf(MSG_DEBUG, "FT: MDIE in msg 3/4 did not " + "match with the current mobility domain"); + return -1; + } + + return 0; +} + + +static int ft_validate_rsnie(struct wpa_sm *sm, + const unsigned char *src_addr, + struct wpa_eapol_ie_parse *ie) +{ + struct wpa_ie_data rsn; + + if (!ie->rsn_ie) + return 0; + + /* + * Verify that PMKR1Name from EAPOL-Key message 3/4 + * matches with the value we derived. + */ + if (wpa_parse_wpa_ie_rsn(ie->rsn_ie, ie->rsn_ie_len, &rsn) < 0 || + rsn.num_pmkid != 1 || rsn.pmkid == NULL) { + wpa_printf(MSG_DEBUG, "FT: No PMKR1Name in " + "FT 4-way handshake message 3/4"); + return -1; + } + + if (os_memcmp(rsn.pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN) != 0) { + wpa_printf(MSG_DEBUG, "FT: PMKR1Name mismatch in " + "FT 4-way handshake message 3/4"); + wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name from Authenticator", + rsn.pmkid, WPA_PMK_NAME_LEN); + wpa_hexdump(MSG_DEBUG, "FT: Derived PMKR1Name", + sm->pmk_r1_name, WPA_PMK_NAME_LEN); + return -1; + } + + return 0; +} + + +static int wpa_supplicant_validate_ie_ft(struct wpa_sm *sm, + const unsigned char *src_addr, + struct wpa_eapol_ie_parse *ie) +{ + if (ft_validate_mdie(sm, src_addr, ie) < 0 || + ft_validate_rsnie(sm, src_addr, ie) < 0) + return -1; + + return 0; +} + +#endif /* CONFIG_IEEE80211R */ + + static int wpa_supplicant_validate_ie(struct wpa_sm *sm, const unsigned char *src_addr, struct wpa_eapol_ie_parse *ie) @@ -841,19 +913,9 @@ static int wpa_supplicant_validate_ie(struct wpa_sm *sm, } #ifdef CONFIG_IEEE80211R - if (wpa_key_mgmt_ft(sm->key_mgmt)) { - struct rsn_mdie *mdie; - /* TODO: verify that full MDIE matches with the one from scan - * results, not only mobility domain */ - mdie = (struct rsn_mdie *) (ie->mdie + 2); - if (ie->mdie == NULL || ie->mdie_len < 2 + sizeof(*mdie) || - os_memcmp(mdie->mobility_domain, sm->mobility_domain, - MOBILITY_DOMAIN_ID_LEN) != 0) { - wpa_printf(MSG_DEBUG, "FT: MDIE in msg 3/4 did not " - "match with the current mobility domain"); - return -1; - } - } + if (wpa_key_mgmt_ft(sm->key_mgmt) && + wpa_supplicant_validate_ie_ft(sm, src_addr, ie) < 0) + return -1; #endif /* CONFIG_IEEE80211R */ return 0; @@ -954,34 +1016,6 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, if (wpa_supplicant_validate_ie(sm, sm->bssid, &ie) < 0) goto failed; -#ifdef CONFIG_IEEE80211R - if (wpa_key_mgmt_ft(sm->key_mgmt) && ie.rsn_ie) { - struct wpa_ie_data rsn; - /* - * Verify that PMKR1Name from EAPOL-Key message 3/4 matches - * with the value we derived. - */ - if (wpa_parse_wpa_ie_rsn(ie.rsn_ie, ie.rsn_ie_len, &rsn) < 0 || - rsn.num_pmkid != 1 || rsn.pmkid == NULL) { - wpa_printf(MSG_DEBUG, "FT: No PMKR1Name in " - "FT 4-way handshake message 3/4"); - return; - } - - if (os_memcmp(rsn.pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN) != - 0) { - wpa_printf(MSG_DEBUG, "FT: PMKR1Name mismatch in " - "FT 4-way handshake message 3/4"); - wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name from " - "Authenticator", - rsn.pmkid, WPA_PMK_NAME_LEN); - wpa_hexdump(MSG_DEBUG, "FT: Derived PMKR1Name", - sm->pmk_r1_name, WPA_PMK_NAME_LEN); - return; - } - } -#endif /* CONFIG_IEEE80211R */ - if (os_memcmp(sm->anonce, key->key_nonce, WPA_NONCE_LEN) != 0) { wpa_printf(MSG_WARNING, "WPA: ANonce from message 1 of 4-Way " "Handshake differs from 3 of 4-Way Handshake - drop"