}
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;
}
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");
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");
}
-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;
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
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);
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
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;
case WPA_PARAM_WMM_ENABLED:
sm->wmm_enabled = value;
break;
+ case WPA_PARAM_FT_PREPEND_PMKID:
+ sm->ft_prepend_pmkid = value;
+ break;
default:
break;
}
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 {
bool wmm_enabled;
bool driver_bss_selection;
+ bool ft_prepend_pmkid;
};
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);
{ 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. */
#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
*/
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
*
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 */
}
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",
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,
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