diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index da01494a3..51b24f430 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -3297,6 +3297,12 @@ const u8 * wpa_sm_get_anonce(struct wpa_sm *sm) #endif /* CONFIG_TESTING_OPTIONS */ +unsigned int wpa_sm_get_key_mgmt(struct wpa_sm *sm) +{ + return sm->key_mgmt; +} + + #ifdef CONFIG_FILS struct wpabuf * fils_build_auth(struct wpa_sm *sm, int dh_group, const u8 *md) diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h index 81c01713d..21f4b1781 100644 --- a/src/rsn_supp/wpa.h +++ b/src/rsn_supp/wpa.h @@ -353,6 +353,9 @@ static inline int wpa_fils_is_completed(struct wpa_sm *sm) 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_add_mdie(struct wpa_sm *sm, u8 *ies, size_t ies_len, + const u8 *mdie); +const u8 * wpa_sm_get_ft_md(struct wpa_sm *sm); int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len, int ft_action, const u8 *target_ap, const u8 *ric_ies, size_t ric_ies_len); @@ -377,6 +380,12 @@ static inline int wpa_ft_prepare_auth_request(struct wpa_sm *sm, return 0; } +static inline int wpa_ft_add_mdie(struct wpa_sm *sm, u8 *ies, size_t ies_len, + const u8 *mdie) +{ + return 0; +} + static inline int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len, int ft_action, const u8 *target_ap) @@ -429,6 +438,7 @@ extern unsigned int tdls_testing; int wpa_wnmsleep_install_key(struct wpa_sm *sm, u8 subelem_id, u8 *buf); void wpa_sm_set_test_assoc_ie(struct wpa_sm *sm, struct wpabuf *buf); const u8 * wpa_sm_get_anonce(struct wpa_sm *sm); +unsigned int wpa_sm_get_key_mgmt(struct wpa_sm *sm); struct wpabuf * fils_build_auth(struct wpa_sm *sm, int dh_group, const u8 *md); int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data, diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c index a543b7c73..5eadd1592 100644 --- a/src/rsn_supp/wpa_ft.c +++ b/src/rsn_supp/wpa_ft.c @@ -151,6 +151,7 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, struct rsn_ftie *ftie; struct rsn_ie_hdr *rsnie; u16 capab; + int mdie_len; sm->ft_completed = 0; sm->ft_reassoc_completed = 0; @@ -247,14 +248,13 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, rsnie->len = (pos - (u8 *) rsnie) - 2; /* MDIE */ - *pos++ = WLAN_EID_MOBILITY_DOMAIN; - *pos++ = sizeof(*mdie); - mdie = (struct rsn_mdie *) pos; - pos += sizeof(*mdie); - os_memcpy(mdie->mobility_domain, sm->mobility_domain, - MOBILITY_DOMAIN_ID_LEN); - mdie->ft_capab = ap_mdie && ap_mdie[1] >= 3 ? ap_mdie[4] : - sm->mdie_ft_capab; + mdie_len = wpa_ft_add_mdie(sm, pos, buf_len - (pos - buf), ap_mdie); + if (mdie_len <= 0) { + os_free(buf); + return NULL; + } + mdie = (struct rsn_mdie *) (pos + 2); + pos += mdie_len; /* FTIE[SNonce, [R1KH-ID,] R0KH-ID ] */ ftie_pos = pos; @@ -373,6 +373,37 @@ int wpa_ft_prepare_auth_request(struct wpa_sm *sm, const u8 *mdie) } +int wpa_ft_add_mdie(struct wpa_sm *sm, u8 *buf, size_t buf_len, + const u8 *ap_mdie) +{ + u8 *pos = buf; + struct rsn_mdie *mdie; + + if (buf_len < 2 + sizeof(*mdie)) { + wpa_printf(MSG_INFO, + "FT: Failed to add MDIE: short buffer, length=%zu", + buf_len); + return 0; + } + + *pos++ = WLAN_EID_MOBILITY_DOMAIN; + *pos++ = sizeof(*mdie); + mdie = (struct rsn_mdie *) pos; + os_memcpy(mdie->mobility_domain, sm->mobility_domain, + MOBILITY_DOMAIN_ID_LEN); + mdie->ft_capab = ap_mdie && ap_mdie[1] >= 3 ? ap_mdie[4] : + sm->mdie_ft_capab; + + return 2 + sizeof(*mdie); +} + + +const u8 * wpa_sm_get_ft_md(struct wpa_sm *sm) +{ + return sm->mobility_domain; +} + + int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len, int ft_action, const u8 *target_ap, const u8 *ric_ies, size_t ric_ies_len) diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 7e7e84afb..c8f4802a9 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -2716,6 +2716,29 @@ static u8 * wpas_populate_assoc_ies( } #endif /* CONFIG_OWE */ +#ifdef CONFIG_IEEE80211R + /* + * Add MDIE under these conditions: the network profile allows FT, + * the AP supports FT, and the mobility domain ID matches. + */ + if (wpa_key_mgmt_ft(wpa_sm_get_key_mgmt(wpa_s->wpa))) { + const u8 *mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN); + + if (mdie && mdie[1] >= MOBILITY_DOMAIN_ID_LEN) { + const u8 *md = mdie + 2; + const u8 *wpa_md = wpa_sm_get_ft_md(wpa_s->wpa); + + if (os_memcmp(md, wpa_md, + MOBILITY_DOMAIN_ID_LEN) == 0) { + /* Add mobility domain IE */ + wpa_ie_len += wpa_ft_add_mdie( + wpa_s->wpa, wpa_ie + wpa_ie_len, + max_wpa_ie_len - wpa_ie_len, mdie); + } + } + } +#endif /* CONFIG_IEEE80211R */ + params->wpa_ie = wpa_ie; params->wpa_ie_len = wpa_ie_len; params->auth_alg = algs;