From e7846b68592a1ef0669b70989ed2a9f44fb2d397 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 10 Apr 2010 11:36:35 +0300 Subject: [PATCH] FT: Clean up wpa_sm_set_ft_params() by using common parse Instead of parsing the IEs in the callers, use the already existing parser in wpa_ft.c to handle MDIE and FTIE from initial MD association response. In addition, this provides more complete access to association response IEs to FT code which will be needed to fix FT 4-way handshake message 2/4. --- src/rsn_supp/wpa.h | 4 +- src/rsn_supp/wpa_ft.c | 100 ++++++++++++++++++-------------- wpa_supplicant/events.c | 65 ++++----------------- wpa_supplicant/mlme.c | 42 +------------- wpa_supplicant/sme.c | 2 +- wpa_supplicant/wpa_supplicant.c | 2 +- 6 files changed, 71 insertions(+), 144 deletions(-) diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h index 0d4405b53..72bf8f455 100644 --- a/src/rsn_supp/wpa.h +++ b/src/rsn_supp/wpa.h @@ -278,9 +278,7 @@ static inline int wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer) #ifdef CONFIG_IEEE80211R -int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *mobility_domain, - const u8 *r0kh_id, size_t r0kh_id_len, - const u8 *r1kh_id); +int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *ies, size_t ies_len); int wpa_ft_prepare_auth_request(struct wpa_sm *sm, const u8 *mdie); int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len, int ft_action, const u8 *target_ap, diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c index 50f48edd7..d3051f81a 100644 --- a/src/rsn_supp/wpa_ft.c +++ b/src/rsn_supp/wpa_ft.c @@ -24,6 +24,31 @@ #ifdef CONFIG_IEEE80211R +struct wpa_ft_ies { + const u8 *mdie; + size_t mdie_len; + const u8 *ftie; + size_t ftie_len; + const u8 *r1kh_id; + const u8 *gtk; + size_t gtk_len; + const u8 *r0kh_id; + size_t r0kh_id_len; + const u8 *rsn; + size_t rsn_len; + const u8 *rsn_pmkid; + const u8 *tie; + size_t tie_len; + const u8 *igtk; + size_t igtk_len; + const u8 *ric; + size_t ric_len; +}; + +static int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, + struct wpa_ft_ies *parse); + + int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr, const struct wpa_eapol_key *key, struct wpa_ptk *ptk, size_t ptk_len) @@ -62,34 +87,40 @@ int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr, /** * wpa_sm_set_ft_params - Set FT (IEEE 802.11r) parameters * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @mobility_domain: Mobility domain identifier (2 octets + 1 octet) - * @r0kh_id: PMK-R0 key holder identity (1-48 octets) - * @r0kh_id_len: R0KH-ID length (1-48) - * @r1kh_id: PMK-R1 key holder identity (16 octets) + * @ies: Association Response IEs or %NULL to clear FT parameters + * @ies_len: Length of ies buffer in octets * Returns: 0 on success, -1 on failure */ -int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *mobility_domain, - const u8 *r0kh_id, size_t r0kh_id_len, - const u8 *r1kh_id) +int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *ies, size_t ies_len) { - if (sm && mobility_domain) { + struct wpa_ft_ies ft; + + if (sm == NULL) + return 0; + + if (wpa_ft_parse_ies(ies, ies_len, &ft) < 0) + return -1; + + if (ft.mdie && ft.mdie_len < MOBILITY_DOMAIN_ID_LEN + 1) + return -1; + + if (ft.mdie) { wpa_hexdump(MSG_DEBUG, "FT: Mobility domain", - mobility_domain, MOBILITY_DOMAIN_ID_LEN); - os_memcpy(sm->mobility_domain, mobility_domain, + ft.mdie, MOBILITY_DOMAIN_ID_LEN); + os_memcpy(sm->mobility_domain, ft.mdie, MOBILITY_DOMAIN_ID_LEN); - sm->mdie_ft_capab = mobility_domain[MOBILITY_DOMAIN_ID_LEN]; + sm->mdie_ft_capab = ft.mdie[MOBILITY_DOMAIN_ID_LEN]; wpa_printf(MSG_DEBUG, "FT: Capability and Policy: 0x%02x", sm->mdie_ft_capab); - } else if (sm) + } else os_memset(sm->mobility_domain, 0, MOBILITY_DOMAIN_ID_LEN); - if (sm && r0kh_id) { - if (r0kh_id_len > FT_R0KH_ID_MAX_LEN) - return -1; - wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID", r0kh_id, r0kh_id_len); - os_memcpy(sm->r0kh_id, r0kh_id, r0kh_id_len); - sm->r0kh_id_len = r0kh_id_len; - } else if (sm) { + if (ft.r0kh_id) { + wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID", + ft.r0kh_id, ft.r0kh_id_len); + os_memcpy(sm->r0kh_id, ft.r0kh_id, ft.r0kh_id_len); + sm->r0kh_id_len = ft.r0kh_id_len; + } else { /* FIX: When should R0KH-ID be cleared? We need to keep the * old R0KH-ID in order to be able to use this during FT. */ /* @@ -98,10 +129,11 @@ int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *mobility_domain, */ } - if (sm && r1kh_id) { - wpa_hexdump(MSG_DEBUG, "FT: R1KH-ID", r1kh_id, FT_R1KH_ID_LEN); - os_memcpy(sm->r1kh_id, r1kh_id, FT_R1KH_ID_LEN); - } else if (sm) + if (ft.r1kh_id) { + wpa_hexdump(MSG_DEBUG, "FT: R1KH-ID", + ft.r1kh_id, FT_R1KH_ID_LEN); + os_memcpy(sm->r1kh_id, ft.r1kh_id, FT_R1KH_ID_LEN); + } else os_memset(sm->r1kh_id, 0, FT_R1KH_ID_LEN); return 0; @@ -296,28 +328,6 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, } -struct wpa_ft_ies { - const u8 *mdie; - size_t mdie_len; - const u8 *ftie; - size_t ftie_len; - const u8 *r1kh_id; - const u8 *gtk; - size_t gtk_len; - const u8 *r0kh_id; - size_t r0kh_id_len; - const u8 *rsn; - size_t rsn_len; - const u8 *rsn_pmkid; - const u8 *tie; - size_t tie_len; - const u8 *igtk; - size_t igtk_len; - const u8 *ric; - size_t ric_len; -}; - - static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len, struct wpa_ft_ies *parse) { diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index afd06b4a4..d43a17266 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -956,58 +956,11 @@ static void wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s, #endif /* CONFIG_NO_SCAN_PROCESSING */ -#ifdef CONFIG_IEEE80211R -static void wpa_assoc_set_ft_params(struct wpa_supplicant *wpa_s, - const u8 *ftie, const u8 *mdie) -{ - const u8 *mobility_domain = NULL; - const u8 *r0kh_id = NULL; - size_t r0kh_id_len = 0; - const u8 *r1kh_id = NULL; - struct rsn_ftie *hdr; - const u8 *pos, *end; - - if (mdie == NULL || ftie == NULL) - return; - - if (mdie[1] >= MOBILITY_DOMAIN_ID_LEN) { - mobility_domain = mdie + 2; -#ifdef CONFIG_SME - wpa_s->sme.ft_used = 1; - os_memcpy(wpa_s->sme.mobility_domain, mobility_domain, 2); -#endif /* CONFIG_SME */ - } - if (ftie[1] >= sizeof(struct rsn_ftie)) { - end = ftie + 2 + ftie[1]; - hdr = (struct rsn_ftie *) (ftie + 2); - pos = (const u8 *) (hdr + 1); - while (pos + 1 < end) { - if (pos + 2 + pos[1] > end) - break; - if (pos[0] == FTIE_SUBELEM_R1KH_ID && - pos[1] == FT_R1KH_ID_LEN) - r1kh_id = pos + 2; - else if (pos[0] == FTIE_SUBELEM_R0KH_ID && - pos[1] >= 1 && pos[1] <= FT_R0KH_ID_MAX_LEN) { - r0kh_id = pos + 2; - r0kh_id_len = pos[1]; - } - pos += 2 + pos[1]; - } - } - wpa_sm_set_ft_params(wpa_s->wpa, mobility_domain, r0kh_id, - r0kh_id_len, r1kh_id); -} -#endif /* CONFIG_IEEE80211R */ - static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s, union wpa_event_data *data) { int l, len, found = 0, wpa_found, rsn_found; const u8 *p; -#ifdef CONFIG_IEEE80211R - const u8 *mdie = NULL, *ftie = NULL; -#endif /* CONFIG_IEEE80211R */ wpa_printf(MSG_DEBUG, "Association info event"); if (data->assoc_info.req_ies) @@ -1065,12 +1018,11 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s, return -1; } } -#endif /* CONFIG_SME */ p = data->assoc_info.resp_ies; l = data->assoc_info.resp_ies_len; - /* Go through the IEs and make a copy of the FT/MD IE, if present. */ + /* Go through the IEs and make a copy of the MDIE, if present. */ while (p && l >= 2) { len = p[1] + 2; if (len > l) { @@ -1078,15 +1030,20 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s, p, l); break; } - if (p[0] == WLAN_EID_FAST_BSS_TRANSITION) - ftie = p; - else if (p[0] == WLAN_EID_MOBILITY_DOMAIN) - mdie = p; + if (p[0] == WLAN_EID_MOBILITY_DOMAIN && + p[1] >= MOBILITY_DOMAIN_ID_LEN) { + wpa_s->sme.ft_used = 1; + os_memcpy(wpa_s->sme.mobility_domain, p + 2, + MOBILITY_DOMAIN_ID_LEN); + break; + } l -= len; p += len; } +#endif /* CONFIG_SME */ - wpa_assoc_set_ft_params(wpa_s, ftie, mdie); + wpa_sm_set_ft_params(wpa_s->wpa, data->assoc_info.resp_ies, + data->assoc_info.resp_ies_len); #endif /* CONFIG_IEEE80211R */ /* WPA/RSN IE from Beacon/ProbeResp */ diff --git a/wpa_supplicant/mlme.c b/wpa_supplicant/mlme.c index b013a74a5..c9a1c289c 100644 --- a/wpa_supplicant/mlme.c +++ b/wpa_supplicant/mlme.c @@ -996,45 +996,6 @@ static void ieee80211_rx_mgmt_disassoc(struct wpa_supplicant *wpa_s, } -static int ieee80211_ft_assoc_resp(struct wpa_supplicant *wpa_s, - struct ieee802_11_elems *elems) -{ -#ifdef CONFIG_IEEE80211R - const u8 *mobility_domain = NULL; - const u8 *r0kh_id = NULL; - size_t r0kh_id_len = 0; - const u8 *r1kh_id = NULL; - struct rsn_ftie *hdr; - const u8 *pos, *end; - - if (elems->mdie && elems->mdie_len >= MOBILITY_DOMAIN_ID_LEN) - mobility_domain = elems->mdie; - if (elems->ftie && elems->ftie_len >= sizeof(struct rsn_ftie)) { - end = elems->ftie + elems->ftie_len; - hdr = (struct rsn_ftie *) elems->ftie; - pos = (const u8 *) (hdr + 1); - while (pos + 1 < end) { - if (pos + 2 + pos[1] > end) - break; - if (pos[0] == FTIE_SUBELEM_R1KH_ID && - pos[1] == FT_R1KH_ID_LEN) - r1kh_id = pos + 2; - else if (pos[0] == FTIE_SUBELEM_R0KH_ID && - pos[1] >= 1 && pos[1] <= FT_R0KH_ID_MAX_LEN) { - r0kh_id = pos + 2; - r0kh_id_len = pos[1]; - } - pos += 2 + pos[1]; - } - } - return wpa_sm_set_ft_params(wpa_s->wpa, mobility_domain, r0kh_id, - r0kh_id_len, r1kh_id); -#else /* CONFIG_IEEE80211R */ - return 0; -#endif /* CONFIG_IEEE80211R */ -} - - static void ieee80211_build_tspec(struct wpabuf *buf) { struct wmm_tspec_element *tspec; @@ -1194,7 +1155,8 @@ static void ieee80211_rx_mgmt_assoc_resp(struct wpa_supplicant *wpa_s, "Resp failed"); return; } - } else if (ieee80211_ft_assoc_resp(wpa_s, &elems) < 0) + } else if (wpa_sm_set_ft_params(wpa_s->wpa, pos, + len - (pos - (u8 *) mgmt)) < 0) return; wpa_printf(MSG_DEBUG, "MLME: associated"); diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index 800731db5..a31f2dbaa 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -160,7 +160,7 @@ void sme_authenticate(struct wpa_supplicant *wpa_s, ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN); if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN) md = ie + 2; - wpa_sm_set_ft_params(wpa_s->wpa, md, NULL, 0, NULL); + wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0); if (md) { /* Prepare for the next transition */ wpa_ft_prepare_auth_request(wpa_s->wpa, ie); diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index c5387bfd6..0eba4a0b7 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -1037,7 +1037,7 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN); if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN) md = ie + 2; - wpa_sm_set_ft_params(wpa_s->wpa, md, NULL, 0, NULL); + wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0); if (md) { /* Prepare for the next transition */ wpa_ft_prepare_auth_request(wpa_s->wpa, ie);