FT: Fix FTIE generation for 4-way handshake after FT protocol run

wpa_insert_pmkid() did not support cases where the original RSN IE
included any PMKIDs. That case can happen when PTK rekeying through
4-way handshake is used after FT protocol run. Such a 4-way handshake
used to fail with wpa_supplicant being unable to build the EAPOL-Key msg
2/4.

Fix this by extending wpa_insert_pmkid() to support removal of the old
PMKIDs, if needed.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
Jouni Malinen 2015-12-10 00:06:06 +02:00 committed by Jouni Malinen
parent cc02fd3eff
commit 59e78c2408
4 changed files with 36 additions and 12 deletions

View file

@ -2298,14 +2298,19 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
pos += wpa_ie_len;
#ifdef CONFIG_IEEE80211R
if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
int res = wpa_insert_pmkid(kde, pos - kde, sm->pmk_r1_name);
int res;
size_t elen;
elen = pos - kde;
res = wpa_insert_pmkid(kde, &elen, sm->pmk_r1_name);
if (res < 0) {
wpa_printf(MSG_ERROR, "FT: Failed to insert "
"PMKR1Name into RSN IE in EAPOL-Key data");
os_free(kde);
return;
}
pos += res;
pos -= wpa_ie_len;
pos += elen;
}
#endif /* CONFIG_IEEE80211R */
if (gtk) {

View file

@ -1280,13 +1280,13 @@ int wpa_compare_rsn_ie(int ft_initial_assoc,
#ifdef CONFIG_IEEE80211R
int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid)
int wpa_insert_pmkid(u8 *ies, size_t *ies_len, const u8 *pmkid)
{
u8 *start, *end, *rpos, *rend;
int added = 0;
start = ies;
end = ies + ies_len;
end = ies + *ies_len;
while (start < end) {
if (*start == WLAN_EID_RSN)
@ -1339,11 +1339,29 @@ int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid)
added += 2 + PMKID_LEN;
start[1] += 2 + PMKID_LEN;
} else {
/* PMKID-Count was included; use it */
if (WPA_GET_LE16(rpos) != 0) {
wpa_printf(MSG_ERROR, "FT: Unexpected PMKID "
"in RSN IE in EAPOL-Key data");
u16 num_pmkid;
if (rend - rpos < 2)
return -1;
num_pmkid = WPA_GET_LE16(rpos);
/* PMKID-Count was included; use it */
if (num_pmkid != 0) {
u8 *after;
if (num_pmkid * PMKID_LEN > rend - rpos - 2)
return -1;
/*
* PMKID may have been included in RSN IE in
* (Re)Association Request frame, so remove the old
* PMKID(s) first before adding the new one.
*/
wpa_printf(MSG_DEBUG,
"FT: Remove %u old PMKID(s) from RSN IE",
num_pmkid);
after = rpos + 2 + num_pmkid * PMKID_LEN;
os_memmove(rpos + 2, after, rend - after);
start[1] -= num_pmkid * PMKID_LEN;
added -= num_pmkid * PMKID_LEN;
}
WPA_PUT_LE16(rpos, 1);
rpos += 2;
@ -1356,7 +1374,9 @@ int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid)
wpa_hexdump(MSG_DEBUG, "FT: RSN IE after modification "
"(PMKID inserted)", start, 2 + start[1]);
return added;
*ies_len += added;
return 0;
}
#endif /* CONFIG_IEEE80211R */

View file

@ -409,7 +409,7 @@ u32 wpa_akm_to_suite(int akm);
int wpa_compare_rsn_ie(int ft_initial_assoc,
const u8 *ie1, size_t ie1len,
const u8 *ie2, size_t ie2len);
int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid);
int wpa_insert_pmkid(u8 *ies, size_t *ies_len, const u8 *pmkid);
struct wpa_ft_ies {
const u8 *mdie;

View file

@ -364,13 +364,12 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
if (rsn_ie_buf == NULL)
return -1;
os_memcpy(rsn_ie_buf, wpa_ie, wpa_ie_len);
res = wpa_insert_pmkid(rsn_ie_buf, wpa_ie_len,
res = wpa_insert_pmkid(rsn_ie_buf, &wpa_ie_len,
sm->pmk_r1_name);
if (res < 0) {
os_free(rsn_ie_buf);
return -1;
}
wpa_ie_len += res;
if (sm->assoc_resp_ies) {
os_memcpy(rsn_ie_buf + wpa_ie_len, sm->assoc_resp_ies,