AP: Add testing option to delay EAPOL Tx

Add a testing option to delay EAPOL-Key messages 1/4 and 3/4. By setting
delay_eapol_tx=1, the actual EAPOL Tx will occur on the last possible
attempt (wpa_pairwise_update_count) thus all previous attempts will fail
on timeout which is the wanted delay.

In addition, add an hwsim test that uses this testing option to verify
that non protected Robust Action frames are dropped prior to keys
installation in MFP.

Signed-off-by: Daniel Gabay <daniel.gabay@intel.com>
Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
This commit is contained in:
Daniel Gabay 2022-12-01 18:54:35 +02:00 committed by Jouni Malinen
parent 1897abad94
commit bb67d5b52b
7 changed files with 70 additions and 1 deletions

View file

@ -4271,6 +4271,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
bss->oci_freq_override_wnm_sleep = atoi(pos); bss->oci_freq_override_wnm_sleep = atoi(pos);
} else if (os_strcmp(buf, "eap_skip_prot_success") == 0) { } else if (os_strcmp(buf, "eap_skip_prot_success") == 0) {
bss->eap_skip_prot_success = atoi(pos); bss->eap_skip_prot_success = atoi(pos);
} else if (os_strcmp(buf, "delay_eapol_tx") == 0) {
conf->delay_eapol_tx = atoi(pos);
#endif /* CONFIG_TESTING_OPTIONS */ #endif /* CONFIG_TESTING_OPTIONS */
#ifdef CONFIG_SAE #ifdef CONFIG_SAE
} else if (os_strcmp(buf, "sae_password") == 0) { } else if (os_strcmp(buf, "sae_password") == 0) {

View file

@ -3086,6 +3086,11 @@ own_ip_addr=127.0.0.1
# Include only ECSA IE without CSA IE where possible # Include only ECSA IE without CSA IE where possible
# (channel switch operating class is needed) # (channel switch operating class is needed)
#ecsa_ie_only=0 #ecsa_ie_only=0
#
# Delay EAPOL-Key messages 1/4 and 3/4 by not sending the frame until the last
# attempt (wpa_pairwise_update_count). This will trigger a timeout on all
# previous attempts and thus delays the frame. (testing only)
#delay_eapol_tx=0
##### Multiple BSSID support ################################################## ##### Multiple BSSID support ##################################################
# #

View file

@ -1076,6 +1076,7 @@ struct hostapd_config {
double ignore_reassoc_probability; double ignore_reassoc_probability;
double corrupt_gtk_rekey_mic_probability; double corrupt_gtk_rekey_mic_probability;
int ecsa_ie_only; int ecsa_ie_only;
bool delay_eapol_tx;
#endif /* CONFIG_TESTING_OPTIONS */ #endif /* CONFIG_TESTING_OPTIONS */
#ifdef CONFIG_ACS #ifdef CONFIG_ACS

View file

@ -1736,10 +1736,25 @@ static void wpa_send_eapol(struct wpa_authenticator *wpa_auth,
if (!sm) if (!sm)
return; return;
ctr = pairwise ? sm->TimeoutCtr : sm->GTimeoutCtr;
#ifdef CONFIG_TESTING_OPTIONS
/* When delay_eapol_tx is true, delay the EAPOL-Key transmission by
* sending it only on the last attempt after all timeouts for the prior
* skipped attemps. */
if (wpa_auth->conf.delay_eapol_tx &&
ctr != wpa_auth->conf.wpa_pairwise_update_count) {
wpa_msg(sm->wpa_auth->conf.msg_ctx, MSG_INFO,
"DELAY-EAPOL-TX-%d", ctr);
goto skip_tx;
}
#endif /* CONFIG_TESTING_OPTIONS */
__wpa_send_eapol(wpa_auth, sm, key_info, key_rsc, nonce, kde, kde_len, __wpa_send_eapol(wpa_auth, sm, key_info, key_rsc, nonce, kde, kde_len,
keyidx, encr, 0); keyidx, encr, 0);
#ifdef CONFIG_TESTING_OPTIONS
skip_tx:
#endif /* CONFIG_TESTING_OPTIONS */
ctr = pairwise ? sm->TimeoutCtr : sm->GTimeoutCtr;
if (ctr == 1 && wpa_auth->conf.tx_status) if (ctr == 1 && wpa_auth->conf.tx_status)
timeout_ms = pairwise ? eapol_key_timeout_first : timeout_ms = pairwise ? eapol_key_timeout_first :
eapol_key_timeout_first_group; eapol_key_timeout_first_group;

View file

@ -240,6 +240,7 @@ struct wpa_auth_config {
unsigned int gtk_rsc_override_set:1; unsigned int gtk_rsc_override_set:1;
unsigned int igtk_rsc_override_set:1; unsigned int igtk_rsc_override_set:1;
int ft_rsnxe_used; int ft_rsnxe_used;
bool delay_eapol_tx;
#endif /* CONFIG_TESTING_OPTIONS */ #endif /* CONFIG_TESTING_OPTIONS */
unsigned int oci_freq_override_eapol_m3; unsigned int oci_freq_override_eapol_m3;
unsigned int oci_freq_override_eapol_g1; unsigned int oci_freq_override_eapol_g1;

View file

@ -117,6 +117,7 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
#ifdef CONFIG_TESTING_OPTIONS #ifdef CONFIG_TESTING_OPTIONS
wconf->corrupt_gtk_rekey_mic_probability = wconf->corrupt_gtk_rekey_mic_probability =
iconf->corrupt_gtk_rekey_mic_probability; iconf->corrupt_gtk_rekey_mic_probability;
wconf->delay_eapol_tx = iconf->delay_eapol_tx;
if (conf->own_ie_override && if (conf->own_ie_override &&
wpabuf_len(conf->own_ie_override) <= MAX_OWN_IE_OVERRIDE) { wpabuf_len(conf->own_ie_override) <= MAX_OWN_IE_OVERRIDE) {
wconf->own_ie_override_len = wpabuf_len(conf->own_ie_override); wconf->own_ie_override_len = wpabuf_len(conf->own_ie_override);

View file

@ -1470,3 +1470,47 @@ def test_ap_pmf_sta_global_require2(dev, apdev):
raise Exception("Unexpected connection") raise Exception("Unexpected connection")
finally: finally:
dev[0].set("pmf", "0") dev[0].set("pmf", "0")
def test_ap_pmf_drop_robust_mgmt_prior_to_keys_installation(dev, apdev):
"""Drop non protected Robust Action frames prior to keys installation"""
ssid = "test-pmf-required"
passphrase = '12345678'
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
params['delay_eapol_tx'] = '1'
params['ieee80211w'] = '2'
params['wpa_pairwise_update_count'] = '5'
hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
# Spectrum management with Channel Switch element
msg = {'fc': 0x00d0,
'sa': hapd.own_addr(),
'da': dev[0].own_addr(),
'bssid': hapd.own_addr(),
'payload': binascii.unhexlify('00042503000608')
}
dev[0].connect(ssid, psk=passphrase, scan_freq='2412', ieee80211w='1',
wait_connect=False)
# wait for the first delay before sending the frame
ev = hapd.wait_event(['DELAY-EAPOL-TX-1'], timeout=10)
if ev is None:
raise Exception("EAPOL is not delayed")
# send the Action frame while connecting (prior to keys installation)
hapd.mgmt_tx(msg)
dev[0].wait_connected(timeout=10, error="Timeout on connection")
hapd.wait_sta()
hwsim_utils.test_connectivity(dev[0], hapd)
# Verify no channel switch event
ev = dev[0].wait_event(['CTRL-EVENT-STARTED-CHANNEL-SWITCH'], timeout=5)
if ev is not None:
raise Exception("Unexpected CSA prior to keys installation")
# Send the frame after keys installation and verify channel switch event
hapd.mgmt_tx(msg)
ev = dev[0].wait_event(['CTRL-EVENT-STARTED-CHANNEL-SWITCH'], timeout=5)
if ev is None:
raise Exception("Expected CSA handling after keys installation")