]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
FT: Allow wpa_supplicant to be configured to prepend PMKR1Name
authorJouni Malinen <j@w1.fi>
Sat, 3 Feb 2024 18:13:46 +0000 (20:13 +0200)
committerJouni Malinen <j@w1.fi>
Sat, 3 Feb 2024 18:58:01 +0000 (20:58 +0200)
The standard is somewhat unclear on whether the PMKIDs used in
(Re)Association Request frame (i.e., potential PMKIDs that could be used
for PMKSA caching during the initial mobility domain association) are to
be retained or removed when generating EAPOL-Key msg 2/4.

wpa_supplicant has replaced the PMKID List contents from (Re)Association
Request frame with PMKR1Name when generating EAPOL-Key msg 2/4 for FT.
Allow it to be configured (ft_prepend_pmkid=1) to prepend the PMKR1Name
without removing the PMKIDs from (Re)Association Request frame.

Signed-off-by: Jouni Malinen <j@w1.fi>
13 files changed:
src/ap/ieee802_11.c
src/ap/wpa_auth.c
src/common/wpa_common.c
src/common/wpa_common.h
src/rsn_supp/wpa.c
src/rsn_supp/wpa.h
src/rsn_supp/wpa_i.h
wlantest/rx_mgmt.c
wpa_supplicant/config.c
wpa_supplicant/config.h
wpa_supplicant/config_file.c
wpa_supplicant/sme.c
wpa_supplicant/wpa_supplicant.c

index bf8a331661a52177c6dd8f95da21a89f0f7de573..7fb49a4b429e9edfaf54740dc16bac51cb95256f 100644 (file)
@@ -2028,7 +2028,7 @@ prepare_auth_resp_fils(struct hostapd_data *hapd,
                }
 
                os_memcpy(ie_buf, ie, ielen);
-               if (wpa_insert_pmkid(ie_buf, &ielen, pmksa->pmkid) < 0) {
+               if (wpa_insert_pmkid(ie_buf, &ielen, pmksa->pmkid, true) < 0) {
                        *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
                        goto fail;
                }
index 0bb8b4872478a5138ba34c512892778bd91619de..afb0208e78b81521415a6f50a32018f3f9a64caa 100644 (file)
@@ -4448,7 +4448,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
                size_t elen;
 
                elen = pos - kde;
-               res = wpa_insert_pmkid(kde, &elen, sm->pmk_r1_name);
+               res = wpa_insert_pmkid(kde, &elen, sm->pmk_r1_name, true);
                if (res < 0) {
                        wpa_printf(MSG_ERROR,
                                   "FT: Failed to insert PMKR1Name into RSN IE in EAPOL-Key data");
@@ -6577,7 +6577,7 @@ int wpa_auth_resend_m3(struct wpa_state_machine *sm,
                size_t elen;
 
                elen = pos - kde;
-               res = wpa_insert_pmkid(kde, &elen, sm->pmk_r1_name);
+               res = wpa_insert_pmkid(kde, &elen, sm->pmk_r1_name, true);
                if (res < 0) {
                        wpa_printf(MSG_ERROR,
                                   "FT: Failed to insert PMKR1Name into RSN IE in EAPOL-Key data");
index e4930a2913d34d328120888c19dace9a6c9565b2..c82fd0e5d47988232db236be2d57f8234806cb1e 100644 (file)
@@ -2893,7 +2893,7 @@ int wpa_compare_rsn_ie(int ft_initial_assoc,
 }
 
 
-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, bool replace)
 {
        u8 *start, *end, *rpos, *rend;
        int added = 0;
@@ -2956,12 +2956,12 @@ int wpa_insert_pmkid(u8 *ies, size_t *ies_len, const u8 *pmkid)
                if (rend - rpos < 2)
                        return -1;
                num_pmkid = WPA_GET_LE16(rpos);
+               if (num_pmkid * PMKID_LEN > rend - rpos - 2)
+                       return -1;
                /* PMKID-Count was included; use it */
-               if (num_pmkid != 0) {
+               if (replace && 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
@@ -2974,8 +2974,9 @@ int wpa_insert_pmkid(u8 *ies, size_t *ies_len, const u8 *pmkid)
                        os_memmove(rpos + 2, after, end - after);
                        start[1] -= num_pmkid * PMKID_LEN;
                        added -= num_pmkid * PMKID_LEN;
+                       num_pmkid = 0;
                }
-               WPA_PUT_LE16(rpos, 1);
+               WPA_PUT_LE16(rpos, num_pmkid + 1);
                rpos += 2;
                os_memmove(rpos + PMKID_LEN, rpos, end + added - rpos);
                os_memcpy(rpos, pmkid, PMKID_LEN);
index 1269bf95d1504065da935908086736685fe0aa29..a2c7033c9fbc9da5bd63fdb60e99bc3c0b09cf35 100644 (file)
@@ -555,7 +555,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, bool replace);
 
 #define MAX_NUM_MLO_LINKS 15
 
index 1d20b5e2bf451c34c3968fdcebf29add0a5e8f2a..2109552c0c83133f6ffb63531315cb403f464cc2 100644 (file)
@@ -559,7 +559,7 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
                        return -1;
                os_memcpy(rsn_ie_buf, wpa_ie, wpa_ie_len);
                res = wpa_insert_pmkid(rsn_ie_buf, &wpa_ie_len,
-                                      sm->pmk_r1_name);
+                                      sm->pmk_r1_name, !sm->ft_prepend_pmkid);
                if (res < 0) {
                        os_free(rsn_ie_buf);
                        return -1;
@@ -4695,6 +4695,9 @@ int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param,
        case WPA_PARAM_WMM_ENABLED:
                sm->wmm_enabled = value;
                break;
+       case WPA_PARAM_FT_PREPEND_PMKID:
+               sm->ft_prepend_pmkid = value;
+               break;
        default:
                break;
        }
index 3d2c2812e3e31b2f7b219590ec9d568d6251f7f1..ba5c3e1b4390ec3cc19ed5cd6d97040124c06229 100644 (file)
@@ -134,6 +134,7 @@ enum wpa_sm_conf_params {
        WPA_PARAM_DISABLE_EAPOL_G2_TX,
        WPA_PARAM_ENCRYPT_EAPOL_M2,
        WPA_PARAM_ENCRYPT_EAPOL_M4,
+       WPA_PARAM_FT_PREPEND_PMKID,
 };
 
 struct rsn_supp_config {
index f326f43e9b27c0be831529336f10876f6b0e8596..ca97c12937cf62d414b7817ba2aea3680cb67bfe 100644 (file)
@@ -227,6 +227,7 @@ struct wpa_sm {
 
        bool wmm_enabled;
        bool driver_bss_selection;
+       bool ft_prepend_pmkid;
 };
 
 
index ac7ea6abc4ac46d56bcefe1647274893d7fc8c8c..93263258fb83c21770433b4cd3fd1b71cc0f33f4 100644 (file)
@@ -2207,7 +2207,8 @@ static void rx_mgmt_reassoc_resp(struct wlantest *wt, const u8 *data,
 
                                os_memcpy(rsne_buf, l_bss->rsnie, rsne_len);
                                if (wpa_insert_pmkid(rsne_buf, &rsne_len,
-                                                    sta->pmk_r1_name) < 0) {
+                                                    sta->pmk_r1_name,
+                                                    true) < 0) {
                                        wpa_printf(MSG_DEBUG,
                                                   "FT: Could not insert PMKR1Name into AP RSNE for link ID %u ",
                                                   link_id);
index fca4320a19f2a163841b75df327c373fc3fd2561..f400b50cfc1407b6be833246b22ce949e873d803 100644 (file)
@@ -5545,6 +5545,7 @@ static const struct global_parse_data global_fields[] = {
        { INT_RANGE(mld_connect_band_pref, 0, MLD_CONNECT_BAND_PREF_MAX), 0 },
        { FUNC(mld_connect_bssid_pref), 0 },
 #endif /* CONFIG_TESTING_OPTIONS */
+       { INT_RANGE(ft_prepend_pmkid, 0, 1), CFG_CHANGED_FT_PREPEND_PMKID },
        /* NOTE: When adding new parameters here, add_interface() in
         * wpa_supplicant/dbus_new_introspect.c may need to be modified to
         * increase the size of the iface->xml buffer. */
index 02139e6b2c090b30d55fed81aca7c4f9e6fd6d94..8981305c2a7ae884473d7ea6985bd6e0762d7f12 100644 (file)
@@ -439,6 +439,7 @@ struct wpa_cred {
 #define CFG_CHANGED_WOWLAN_TRIGGERS BIT(18)
 #define CFG_CHANGED_DISABLE_BTM BIT(19)
 #define CFG_CHANGED_BGSCAN BIT(20)
+#define CFG_CHANGED_FT_PREPEND_PMKID BIT(21)
 
 /**
  * struct wpa_config - wpa_supplicant configuration data
@@ -712,6 +713,14 @@ struct wpa_config {
         */
        unsigned int dot11RSNAConfigSATimeout;
 
+       /**
+        * ft_prepend_pmkid - Whether to prepend PMKR1Name with PMKIDs
+        *
+        * This control whether PMKR1Name is prepended to the PMKID list
+        * insread of replacing the full list when constructing RSNE for
+        * EAPOL-Key msg 2/4 for FT cases. */
+       bool ft_prepend_pmkid;
+
        /**
         * update_config - Is wpa_supplicant allowed to update configuration
         *
index 4db85f9c07e1ba3de9d0fdb8a8d66309bfef58a6..ac1414ae2957290c52f3478d3e6cde884ed36b84 100644 (file)
@@ -1622,6 +1622,8 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
                fprintf(f, "mld_connect_bssid_pref=" MACSTR "\n",
                        MAC2STR(config->mld_connect_bssid_pref));
 #endif /* CONFIG_TESTING_OPTIONS */
+       if (config->ft_prepend_pmkid)
+               fprintf(f, "ft_prepend_pmkid=%d", config->ft_prepend_pmkid);
 }
 
 #endif /* CONFIG_NO_CONFIG_WRITE */
index 706310b6129edbce145be28f7fbca49a09b01072..00e1117d55ebd19241ea4683c72e6ab2762e5735 100644 (file)
@@ -1901,7 +1901,7 @@ static int sme_sae_set_pmk(struct wpa_supplicant *wpa_s, const u8 *bssid)
                }
                if (wpa_insert_pmkid(wpa_s->sme.assoc_req_ie,
                                     &wpa_s->sme.assoc_req_ie_len,
-                                    wpa_s->sme.sae.pmkid) < 0)
+                                    wpa_s->sme.sae.pmkid, true) < 0)
                        return -1;
                wpa_hexdump(MSG_DEBUG,
                            "SME: Updated Association Request IEs",
index b820773b88adca9f0cba6eba627ab9f1aedc3b1a..172a863cbb1fcfb3b5c141bdd01a575c4fdd5117 100644 (file)
@@ -7192,6 +7192,9 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
                return -1;
        }
 
+       wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_FT_PREPEND_PMKID,
+                        wpa_s->conf->ft_prepend_pmkid);
+
        wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
                                                      &wpa_s->hw.num_modes,
                                                      &wpa_s->hw.flags,
@@ -8151,6 +8154,10 @@ void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
        if (wpa_s->conf->changed_parameters & CFG_CHANGED_DISABLE_BTM)
                wpa_supplicant_set_default_scan_ies(wpa_s);
 
+       if (wpa_s->conf->changed_parameters & CFG_CHANGED_FT_PREPEND_PMKID)
+               wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_FT_PREPEND_PMKID,
+                                wpa_s->conf->ft_prepend_pmkid);
+
 #ifdef CONFIG_BGSCAN
        /*
         * We default to global bgscan parameters only when per-network bgscan