FT: Allow wpa_supplicant to be configured to prepend PMKR1Name

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>
This commit is contained in:
Jouni Malinen 2024-02-03 20:13:46 +02:00
parent 9929426b92
commit 8fa52a7974
13 changed files with 38 additions and 12 deletions

View 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;
}

View 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");

View 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);

View 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

View 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;
}

View 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 {

View file

@ -227,6 +227,7 @@ struct wpa_sm {
bool wmm_enabled;
bool driver_bss_selection;
bool ft_prepend_pmkid;
};

View 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);

View 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. */

View 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
*

View 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 */

View 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",

View 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