mirror of
https://github.com/vanhoefm/fragattacks.git
synced 2024-11-28 18:28:23 -05:00
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.
This commit is contained in:
parent
0ae145cde8
commit
e7846b6859
@ -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,
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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 */
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user