WMM: Advertise support for 16 PTKSA replay counters for non-AP STA

In theory, each device that supports WMM (or the IEEE 802.11 QoS for
that matter) is expected to advertise how many replay counters it
supports and the peer device is supposed to use that information to
restrict the total number of different MSDU priorities (AC/UP) that
might be used. In practice, this is not really done in deployed devices
and instead, it is just assumed that everyone supports the eight
different replay counters so that there is no need to restrict which
MSDU priorities can be used.

hostapd implementation of WMM has advertised support for 16 PTKSA replay
counters from the beginning while wpa_supplicant has not had any code
for setting the supported replay counter fields in RSNE, i.e., has left
the value to 0 which implies that only a single replay counter is
supported. While this does not really result in any real issues with
deployed devices, this is not really correct behavior based on the
current IEEE 802.11 standard and the WMM specification.

Update wpa_supplicant to use similar design to the hostapd RSNE
generation by setting the number of supported PTKSA replay counters to
16 whenever WMM is enabled. For now, this is done based on the
association being for HT/VHT/HE/EHT and also based on the AP supporting
WMM since it is much more likely for the local device to support WMM and
eight replay counters (which can be indicated only with the value that
implies support for 16 counters since there is no separate value for 8).

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
This commit is contained in:
Jouni Malinen 2023-04-12 18:46:53 +03:00 committed by Jouni Malinen
parent ac54b61273
commit 07a7bcd7ea
8 changed files with 32 additions and 5 deletions

View file

@ -4560,6 +4560,9 @@ int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param,
sm->dpp_pfs = value; sm->dpp_pfs = value;
break; break;
#endif /* CONFIG_DPP2 */ #endif /* CONFIG_DPP2 */
case WPA_PARAM_WMM_ENABLED:
sm->wmm_enabled = value;
break;
default: default:
break; break;
} }

View file

@ -123,6 +123,7 @@ enum wpa_sm_conf_params {
WPA_PARAM_USE_EXT_KEY_ID, WPA_PARAM_USE_EXT_KEY_ID,
WPA_PARAM_FT_RSNXE_USED, WPA_PARAM_FT_RSNXE_USED,
WPA_PARAM_DPP_PFS, WPA_PARAM_DPP_PFS,
WPA_PARAM_WMM_ENABLED,
WPA_PARAM_OCI_FREQ_EAPOL, WPA_PARAM_OCI_FREQ_EAPOL,
WPA_PARAM_OCI_FREQ_EAPOL_G2, WPA_PARAM_OCI_FREQ_EAPOL_G2,
WPA_PARAM_OCI_FREQ_FT_ASSOC, WPA_PARAM_OCI_FREQ_FT_ASSOC,

View file

@ -220,6 +220,8 @@ struct wpa_sm {
int dpp_pfs; int dpp_pfs;
#endif /* CONFIG_DPP2 */ #endif /* CONFIG_DPP2 */
struct wpa_sm_mlo mlo; struct wpa_sm_mlo mlo;
bool wmm_enabled;
}; };

View file

@ -109,6 +109,10 @@ u16 rsn_supp_capab(struct wpa_sm *sm)
{ {
u16 capab = 0; u16 capab = 0;
if (sm->wmm_enabled) {
/* Advertise 16 PTKSA replay counters when using WMM */
capab |= RSN_NUM_REPLAY_COUNTERS_16 << 2;
}
if (sm->mfp) if (sm->mfp)
capab |= WPA_CAPABILITY_MFPC; capab |= WPA_CAPABILITY_MFPC;
if (sm->mfp == 2) if (sm->mfp == 2)

View file

@ -1533,7 +1533,7 @@ def eapol_test(apdev, dev, wpa2=True, ieee80211w=0):
if ieee80211w == 2: if ieee80211w == 2:
rsne = binascii.unhexlify('30140100000fac040100000fac040100000fac02cc00') rsne = binascii.unhexlify('30140100000fac040100000fac040100000fac02cc00')
else: else:
rsne = binascii.unhexlify('30140100000fac040100000fac040100000fac020000') rsne = binascii.unhexlify('30140100000fac040100000fac040100000fac020c00')
else: else:
rsne = binascii.unhexlify('dd160050f20101000050f20201000050f20201000050f202') rsne = binascii.unhexlify('dd160050f20101000050f20201000050f20201000050f202')
snonce = binascii.unhexlify('1111111111111111111111111111111111111111111111111111111111111111') snonce = binascii.unhexlify('1111111111111111111111111111111111111111111111111111111111111111')

View file

@ -388,9 +388,9 @@ class APConnection:
pmk = binascii.unhexlify("c2c6c255af836bed1b3f2f1ded98e052f5ad618bb554e2836757b55854a0eab7") pmk = binascii.unhexlify("c2c6c255af836bed1b3f2f1ded98e052f5ad618bb554e2836757b55854a0eab7")
if sta_ocv != "0": if sta_ocv != "0":
self.rsne = binascii.unhexlify("301a0100000fac040100000fac040100000fac0280400000000fac06") self.rsne = binascii.unhexlify("301a0100000fac040100000fac040100000fac028c400000000fac06")
else: else:
self.rsne = binascii.unhexlify("301a0100000fac040100000fac040100000fac0280000000000fac06") self.rsne = binascii.unhexlify("301a0100000fac040100000fac040100000fac028c000000000fac06")
self.snonce = binascii.unhexlify('1111111111111111111111111111111111111111111111111111111111111111') self.snonce = binascii.unhexlify('1111111111111111111111111111111111111111111111111111111111111111')
dev.connect(self.ssid, raw_psk=self.psk, scan_freq=freq, ocv=sta_ocv, dev.connect(self.ssid, raw_psk=self.psk, scan_freq=freq, ocv=sta_ocv,

View file

@ -2370,7 +2370,7 @@ def test_sae_rsne_mismatch(dev, apdev):
# First, test with matching RSNE to confirm testing capability # First, test with matching RSNE to confirm testing capability
dev[0].set("rsne_override_eapol", dev[0].set("rsne_override_eapol",
"30140100000fac040100000fac040100000fac080000") "30140100000fac040100000fac040100000fac080c00")
dev[0].connect("sae-pwe", psk="12345678", key_mgmt="SAE", dev[0].connect("sae-pwe", psk="12345678", key_mgmt="SAE",
scan_freq="2412") scan_freq="2412")
dev[0].request("REMOVE_NETWORK all") dev[0].request("REMOVE_NETWORK all")
@ -2378,7 +2378,7 @@ def test_sae_rsne_mismatch(dev, apdev):
dev[0].dump_monitor() dev[0].dump_monitor()
# Then, test with modified RSNE # Then, test with modified RSNE
tests = ["30140100000fac040100000fac040100000fac080010", "0000"] tests = ["30140100000fac040100000fac040100000fac080c10", "0000"]
for ie in tests: for ie in tests:
dev[0].set("rsne_override_eapol", ie) dev[0].set("rsne_override_eapol", ie)
dev[0].connect("sae-pwe", psk="12345678", key_mgmt="SAE", dev[0].connect("sae-pwe", psk="12345678", key_mgmt="SAE",

View file

@ -1582,6 +1582,7 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
int sel, proto; int sel, proto;
enum sae_pwe sae_pwe; enum sae_pwe sae_pwe;
const u8 *bss_wpa, *bss_rsn, *bss_rsnx, *bss_osen; const u8 *bss_wpa, *bss_rsn, *bss_rsnx, *bss_osen;
bool wmm;
if (bss) { if (bss) {
bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
@ -1978,6 +1979,22 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID, 0); wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID, 0);
} }
/* Mark WMM enabled for any HT/VHT/HE/EHT association to get more
* appropriate advertisement of the supported number of PTKSA receive
* counters. In theory, this could be based on a driver capability, but
* in practice all cases using WMM support at least eight replay
* counters, so use a hardcoded value for now since there is no explicit
* driver capability indication for this.
*
* In addition, claim WMM to be enabled if the AP supports it since it
* is far more likely for any current device to support WMM. */
wmm = wpa_s->connection_set &&
(wpa_s->connection_ht || wpa_s->connection_vht ||
wpa_s->connection_he || wpa_s->connection_eht);
if (!wmm && bss)
wmm = wpa_bss_get_vendor_ie(bss, WMM_IE_VENDOR_TYPE);
wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_WMM_ENABLED, wmm);
if (!skip_default_rsne) { if (!skip_default_rsne) {
if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie,
wpa_ie_len)) { wpa_ie_len)) {