Esempio n. 1
0
int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
				 size_t ies_len, const u8 *src_addr)
{
	struct wpa_ft_ies parse;
	struct rsn_mdie *mdie;
	struct rsn_ftie *ftie;
	unsigned int count;
	u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN];

	wpa_hexdump(MSG_DEBUG, "FT: Response IEs", ies, ies_len);

	if (!wpa_key_mgmt_ft(sm->key_mgmt)) {
		wpa_printf(MSG_DEBUG, "FT: Reject FT IEs since FT is not "
			   "enabled for this connection");
		return -1;
	}

	if (wpa_ft_parse_ies(ies, ies_len, &parse) < 0) {
		wpa_printf(MSG_DEBUG, "FT: Failed to parse IEs");
		return -1;
	}

	mdie = (struct rsn_mdie *) parse.mdie;
	if (mdie == NULL || parse.mdie_len < sizeof(*mdie) ||
	    os_memcmp(mdie->mobility_domain, sm->mobility_domain,
		      MOBILITY_DOMAIN_ID_LEN) != 0) {
		wpa_printf(MSG_DEBUG, "FT: Invalid MDIE");
		return -1;
	}

	ftie = (struct rsn_ftie *) parse.ftie;
	if (ftie == NULL || parse.ftie_len < sizeof(*ftie)) {
		wpa_printf(MSG_DEBUG, "FT: Invalid FTIE");
		return -1;
	}

	if (os_memcmp(ftie->snonce, sm->snonce, WPA_NONCE_LEN) != 0) {
		wpa_printf(MSG_DEBUG, "FT: SNonce mismatch in FTIE");
		wpa_hexdump(MSG_DEBUG, "FT: Received SNonce",
			    ftie->snonce, WPA_NONCE_LEN);
		wpa_hexdump(MSG_DEBUG, "FT: Expected SNonce",
			    sm->snonce, WPA_NONCE_LEN);
		return -1;
	}

	if (os_memcmp(ftie->anonce, sm->anonce, WPA_NONCE_LEN) != 0) {
		wpa_printf(MSG_DEBUG, "FT: ANonce mismatch in FTIE");
		wpa_hexdump(MSG_DEBUG, "FT: Received ANonce",
			    ftie->anonce, WPA_NONCE_LEN);
		wpa_hexdump(MSG_DEBUG, "FT: Expected ANonce",
			    sm->anonce, WPA_NONCE_LEN);
		return -1;
	}

	if (parse.r0kh_id == NULL) {
		wpa_printf(MSG_DEBUG, "FT: No R0KH-ID subelem in FTIE");
		return -1;
	}

	if (parse.r0kh_id_len != sm->r0kh_id_len ||
	    os_memcmp_const(parse.r0kh_id, sm->r0kh_id, parse.r0kh_id_len) != 0)
	{
		wpa_printf(MSG_DEBUG, "FT: R0KH-ID in FTIE did not match with "
			   "the current R0KH-ID");
		wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID in FTIE",
			    parse.r0kh_id, parse.r0kh_id_len);
		wpa_hexdump(MSG_DEBUG, "FT: The current R0KH-ID",
			    sm->r0kh_id, sm->r0kh_id_len);
		return -1;
	}

	if (parse.r1kh_id == NULL) {
		wpa_printf(MSG_DEBUG, "FT: No R1KH-ID subelem in FTIE");
		return -1;
	}

	if (os_memcmp_const(parse.r1kh_id, sm->r1kh_id, FT_R1KH_ID_LEN) != 0) {
		wpa_printf(MSG_DEBUG, "FT: Unknown R1KH-ID used in "
			   "ReassocResp");
		return -1;
	}

	if (parse.rsn_pmkid == NULL ||
	    os_memcmp_const(parse.rsn_pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN))
	{
		wpa_printf(MSG_DEBUG, "FT: No matching PMKR1Name (PMKID) in "
			   "RSNIE (pmkid=%d)", !!parse.rsn_pmkid);
		return -1;
	}

	count = 3;
	if (parse.ric)
		count += ieee802_11_ie_count(parse.ric, parse.ric_len);
	if (ftie->mic_control[1] != count) {
		wpa_printf(MSG_DEBUG, "FT: Unexpected IE count in MIC "
			   "Control: received %u expected %u",
			   ftie->mic_control[1], count);
		return -1;
	}

	if (wpa_ft_mic(sm->ptk.kck, sm->ptk.kck_len, sm->own_addr, src_addr, 6,
		       parse.mdie - 2, parse.mdie_len + 2,
		       parse.ftie - 2, parse.ftie_len + 2,
		       parse.rsn - 2, parse.rsn_len + 2,
		       parse.ric, parse.ric_len,
		       mic) < 0) {
		wpa_printf(MSG_DEBUG, "FT: Failed to calculate MIC");
		return -1;
	}

	if (os_memcmp_const(mic, ftie->mic, 16) != 0) {
		wpa_printf(MSG_DEBUG, "FT: Invalid MIC in FTIE");
		wpa_hexdump(MSG_MSGDUMP, "FT: Received MIC", ftie->mic, 16);
		wpa_hexdump(MSG_MSGDUMP, "FT: Calculated MIC", mic, 16);
		return -1;
	}

	if (wpa_ft_process_gtk_subelem(sm, parse.gtk, parse.gtk_len) < 0)
		return -1;

#ifdef CONFIG_IEEE80211W
	if (wpa_ft_process_igtk_subelem(sm, parse.igtk, parse.igtk_len) < 0)
		return -1;
#endif /* CONFIG_IEEE80211W */

	if (sm->set_ptk_after_assoc) {
		wpa_printf(MSG_DEBUG, "FT: Try to set PTK again now that we "
			   "are associated");
		if (wpa_ft_install_ptk(sm, src_addr) < 0)
			return -1;
		sm->set_ptk_after_assoc = 0;
	}

	if (parse.ric) {
		wpa_hexdump(MSG_MSGDUMP, "FT: RIC Response",
			    parse.ric, parse.ric_len);
		/* TODO: parse response and inform driver about results when
		 * using wpa_supplicant SME */
	}

	wpa_printf(MSG_DEBUG, "FT: Completed successfully");

	return 0;
}
Esempio n. 2
0
int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
                                 size_t ies_len, const u8 *src_addr)
{
    struct wpa_ft_ies parse;
    struct rsn_mdie *mdie;
    struct rsn_ftie *ftie;
    size_t count;
    u8 mic[16];

    wpa_hexdump(MSG_DEBUG, "FT: Response IEs", ies, ies_len);

    if (sm->key_mgmt != WPA_KEY_MGMT_FT_IEEE8021X &&
            sm->key_mgmt != WPA_KEY_MGMT_FT_PSK) {
        wpa_printf(MSG_DEBUG, "FT: Reject FT IEs since FT is not "
                   "enabled for this connection");
        return -1;
    }

    if (wpa_ft_parse_ies(ies, ies_len, &parse) < 0) {
        wpa_printf(MSG_DEBUG, "FT: Failed to parse IEs");
        return -1;
    }

    mdie = (struct rsn_mdie *) parse.mdie;
    if (mdie == NULL || parse.mdie_len < sizeof(*mdie) ||
            os_memcmp(mdie->mobility_domain, sm->mobility_domain,
                      MOBILITY_DOMAIN_ID_LEN) != 0) {
        wpa_printf(MSG_DEBUG, "FT: Invalid MDIE");
        return -1;
    }

    ftie = (struct rsn_ftie *) parse.ftie;
    if (ftie == NULL || parse.ftie_len < sizeof(*ftie)) {
        wpa_printf(MSG_DEBUG, "FT: Invalid FTIE");
        return -1;
    }

    if (parse.r0kh_id == NULL) {
        wpa_printf(MSG_DEBUG, "FT: No R0KH-ID subelem in FTIE");
        return -1;
    }

    if (parse.r0kh_id_len != sm->r0kh_id_len ||
            os_memcmp(parse.r0kh_id, sm->r0kh_id, parse.r0kh_id_len) != 0) {
        wpa_printf(MSG_DEBUG, "FT: R0KH-ID in FTIE did not match with "
                   "the current R0KH-ID");
        wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID in FTIE",
                    parse.r0kh_id, parse.r0kh_id_len);
        wpa_hexdump(MSG_DEBUG, "FT: The current R0KH-ID",
                    sm->r0kh_id, sm->r0kh_id_len);
        return -1;
    }

    if (parse.r1kh_id == NULL) {
        wpa_printf(MSG_DEBUG, "FT: No R1KH-ID subelem in FTIE");
        return -1;
    }

    if (os_memcmp(parse.r1kh_id, sm->r1kh_id, FT_R1KH_ID_LEN) != 0) {
        wpa_printf(MSG_DEBUG, "FT: Unknown R1KH-ID used in "
                   "ReassocResp");
        return -1;
    }

    if (parse.rsn_pmkid == NULL ||
            os_memcmp(parse.rsn_pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN)) {
        wpa_printf(MSG_DEBUG, "FT: No matching PMKR1Name (PMKID) in "
                   "RSNIE (pmkid=%d)", !!parse.rsn_pmkid);
        return -1;
    }

    count = 3;
    if (parse.tie)
        count++;

    if (ftie->mic_control[1] != count) {
        wpa_printf(MSG_DEBUG, "FT: Unexpected IE count in FTIE (%d)",
                   ftie->mic_control[1]);
        return -1;
    }

    if (wpa_ft_mic(sm->ptk.kck, sm->own_addr, src_addr, 6,
                   parse.mdie - 2, parse.mdie_len + 2,
                   parse.ftie - 2, parse.ftie_len + 2,
                   parse.rsn - 2, parse.rsn_len + 2, NULL, 0,
                   mic) < 0) {
        wpa_printf(MSG_DEBUG, "FT: Failed to calculate MIC");
        return -1;
    }

    if (os_memcmp(mic, ftie->mic, 16) != 0) {
        wpa_printf(MSG_DEBUG, "FT: Invalid MIC in FTIE");
        wpa_hexdump(MSG_MSGDUMP, "FT: Received MIC", ftie->mic, 16);
        wpa_hexdump(MSG_MSGDUMP, "FT: Calculated MIC", mic, 16);
        return -1;
    }

    if (wpa_ft_process_gtk_subelem(sm, parse.gtk, parse.gtk_len) < 0)
        return -1;

#ifdef CONFIG_IEEE80211W
    if (wpa_ft_process_igtk_subelem(sm, parse.igtk, parse.igtk_len) < 0)
        return -1;
#endif /* CONFIG_IEEE80211W */

    return 0;
}