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:
parent
cc02fd3eff
commit
59e78c2408
4 changed files with 36 additions and 12 deletions
|
@ -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) {
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue