]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
FT: Fix FTIE generation for 4-way handshake after FT protocol run
authorJouni Malinen <jouni@qca.qualcomm.com>
Wed, 9 Dec 2015 22:06:06 +0000 (00:06 +0200)
committerJouni Malinen <j@w1.fi>
Wed, 9 Dec 2015 22:14:35 +0000 (00:14 +0200)
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>
src/ap/wpa_auth.c
src/common/wpa_common.c
src/common/wpa_common.h
src/rsn_supp/wpa.c

index c2c5693c51e63ded681b6f68b87a6702387c53ea..f70816598489fdba254992fac06393a8d97ac4c6 100644 (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) {
index f3ea281618d2b67b832d0addc152cb488f502fba..b5f57b3ec7f8323ae1c86c1d5c8f1680e84b7962 100644 (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 */
 
index ee71bfc092e0c12ab1a8c796640f0d8d38cd3f83..af1d0f0c6efbc10afcf64cff45b9c896d6730b5c 100644 (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;
index 7a708234b102c984b59f1d2b199eb6f4e7b07f73..9bde3c816a7aa77830e83ff200c1d14a6051813a 100644 (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,