Authenticator side testing functionality for EAPOL-Key Key Data field

Allow additional elements and KDEs to be added to EAPOL-Key msg 1/4 and
3/4 and allow EAPOL-Key msg 3/4 Key Data field to be not encrypted.
These are for testing purposes to enable a convenient mechanism for
testing supplicant behavior with either potential future extensions or
incorrect Authenticator behavior.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
This commit is contained in:
Jouni Malinen 2024-01-16 13:04:59 +02:00 committed by Jouni Malinen
parent 2a61071182
commit 3547ed403d
6 changed files with 78 additions and 1 deletions

View file

@ -4355,6 +4355,14 @@ static int hostapd_config_fill(struct hostapd_config *conf,
bss->eap_skip_prot_success = atoi(pos); bss->eap_skip_prot_success = atoi(pos);
} else if (os_strcmp(buf, "delay_eapol_tx") == 0) { } else if (os_strcmp(buf, "delay_eapol_tx") == 0) {
conf->delay_eapol_tx = atoi(pos); conf->delay_eapol_tx = atoi(pos);
} else if (os_strcmp(buf, "eapol_m1_elements") == 0) {
if (parse_wpabuf_hex(line, buf, &bss->eapol_m1_elements, pos))
return 1;
} else if (os_strcmp(buf, "eapol_m3_elements") == 0) {
if (parse_wpabuf_hex(line, buf, &bss->eapol_m3_elements, pos))
return 1;
} else if (os_strcmp(buf, "eapol_m3_no_encrypt") == 0) {
bss->eapol_m3_no_encrypt = 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

@ -948,6 +948,8 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
wpabuf_free(conf->rsnxe_override_ft); wpabuf_free(conf->rsnxe_override_ft);
wpabuf_free(conf->gtk_rsc_override); wpabuf_free(conf->gtk_rsc_override);
wpabuf_free(conf->igtk_rsc_override); wpabuf_free(conf->igtk_rsc_override);
wpabuf_free(conf->eapol_m1_elements);
wpabuf_free(conf->eapol_m3_elements);
#endif /* CONFIG_TESTING_OPTIONS */ #endif /* CONFIG_TESTING_OPTIONS */
os_free(conf->no_probe_resp_if_seen_on); os_free(conf->no_probe_resp_if_seen_on);

View file

@ -704,6 +704,9 @@ struct hostapd_bss_config {
unsigned int oci_freq_override_ft_assoc; unsigned int oci_freq_override_ft_assoc;
unsigned int oci_freq_override_fils_assoc; unsigned int oci_freq_override_fils_assoc;
unsigned int oci_freq_override_wnm_sleep; unsigned int oci_freq_override_wnm_sleep;
struct wpabuf *eapol_m1_elements;
struct wpabuf *eapol_m3_elements;
bool eapol_m3_no_encrypt;
#ifdef CONFIG_IEEE80211BE #ifdef CONFIG_IEEE80211BE
u16 eht_oper_puncturing_override; u16 eht_oper_puncturing_override;

View file

@ -623,6 +623,17 @@ int wpa_init_keys(struct wpa_authenticator *wpa_auth)
} }
static void wpa_auth_free_conf(struct wpa_auth_config *conf)
{
#ifdef CONFIG_TESTING_OPTIONS
wpabuf_free(conf->eapol_m1_elements);
conf->eapol_m1_elements = NULL;
wpabuf_free(conf->eapol_m3_elements);
conf->eapol_m3_elements = NULL;
#endif /* CONFIG_TESTING_OPTIONS */
}
/** /**
* wpa_deinit - Deinitialize WPA authenticator * wpa_deinit - Deinitialize WPA authenticator
* @wpa_auth: Pointer to WPA authenticator data from wpa_init() * @wpa_auth: Pointer to WPA authenticator data from wpa_init()
@ -656,6 +667,7 @@ void wpa_deinit(struct wpa_authenticator *wpa_auth)
bin_clear_free(prev, sizeof(*prev)); bin_clear_free(prev, sizeof(*prev));
} }
wpa_auth_free_conf(&wpa_auth->conf);
os_free(wpa_auth); os_free(wpa_auth);
} }
@ -673,6 +685,7 @@ int wpa_reconfig(struct wpa_authenticator *wpa_auth,
if (!wpa_auth) if (!wpa_auth)
return 0; return 0;
wpa_auth_free_conf(&wpa_auth->conf);
os_memcpy(&wpa_auth->conf, conf, sizeof(*conf)); os_memcpy(&wpa_auth->conf, conf, sizeof(*conf));
if (wpa_auth_gen_wpa_ie(wpa_auth)) { if (wpa_auth_gen_wpa_ie(wpa_auth)) {
wpa_printf(MSG_ERROR, "Could not generate WPA IE."); wpa_printf(MSG_ERROR, "Could not generate WPA IE.");
@ -2332,10 +2345,14 @@ SM_STATE(WPA_PTK, INITPSK)
SM_STATE(WPA_PTK, PTKSTART) SM_STATE(WPA_PTK, PTKSTART)
{ {
u8 buf[2 * (2 + RSN_SELECTOR_LEN) + PMKID_LEN + ETH_ALEN]; u8 *buf;
size_t buf_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN;
u8 *pmkid = NULL; u8 *pmkid = NULL;
size_t kde_len = 0; size_t kde_len = 0;
u16 key_info; u16 key_info;
#ifdef CONFIG_TESTING_OPTIONS
struct wpa_auth_config *conf = &sm->wpa_auth->conf;
#endif /* CONFIG_TESTING_OPTIONS */
SM_ENTRY_MA(WPA_PTK, PTKSTART, wpa_ptk); SM_ENTRY_MA(WPA_PTK, PTKSTART, wpa_ptk);
sm->PTKRequest = false; sm->PTKRequest = false;
@ -2350,6 +2367,19 @@ SM_STATE(WPA_PTK, PTKSTART)
return; return;
} }
#ifdef CONFIG_IEEE80211BE
if (sm->mld_assoc_link_id >= 0)
buf_len += 2 + RSN_SELECTOR_LEN + ETH_ALEN;
#endif /* CONFIG_IEEE80211BE */
#ifdef CONFIG_TESTING_OPTIONS
if (conf->eapol_m1_elements)
buf_len += wpabuf_len(conf->eapol_m1_elements);
#endif /* CONFIG_TESTING_OPTIONS */
buf = os_zalloc(buf_len);
if (!buf)
return;
wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG, wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
"sending 1/4 msg of 4-Way Handshake"); "sending 1/4 msg of 4-Way Handshake");
/* /*
@ -2453,11 +2483,20 @@ SM_STATE(WPA_PTK, PTKSTART)
} }
#endif /* CONFIG_IEEE80211BE */ #endif /* CONFIG_IEEE80211BE */
#ifdef CONFIG_TESTING_OPTIONS
if (conf->eapol_m1_elements) {
os_memcpy(buf + kde_len, wpabuf_head(conf->eapol_m1_elements),
wpabuf_len(conf->eapol_m1_elements));
kde_len += wpabuf_len(conf->eapol_m1_elements);
}
#endif /* CONFIG_TESTING_OPTIONS */
key_info = WPA_KEY_INFO_ACK | WPA_KEY_INFO_KEY_TYPE; key_info = WPA_KEY_INFO_ACK | WPA_KEY_INFO_KEY_TYPE;
if (sm->pairwise_set && sm->wpa != WPA_VERSION_WPA) if (sm->pairwise_set && sm->wpa != WPA_VERSION_WPA)
key_info |= WPA_KEY_INFO_SECURE; key_info |= WPA_KEY_INFO_SECURE;
wpa_send_eapol(sm->wpa_auth, sm, key_info, NULL, wpa_send_eapol(sm->wpa_auth, sm, key_info, NULL,
sm->ANonce, kde_len ? buf : NULL, kde_len, 0, 0); sm->ANonce, kde_len ? buf : NULL, kde_len, 0, 0);
os_free(buf);
} }
@ -4260,6 +4299,11 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
kde_len += wpa_auth_ml_kdes_len(sm); kde_len += wpa_auth_ml_kdes_len(sm);
#ifdef CONFIG_TESTING_OPTIONS
if (conf->eapol_m3_elements)
kde_len += wpabuf_len(conf->eapol_m3_elements);
#endif /* CONFIG_TESTING_OPTIONS */
kde = os_malloc(kde_len); kde = os_malloc(kde_len);
if (!kde) if (!kde)
goto done; goto done;
@ -4374,6 +4418,17 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
pos = wpa_auth_ml_kdes(sm, pos); pos = wpa_auth_ml_kdes(sm, pos);
#ifdef CONFIG_TESTING_OPTIONS
if (conf->eapol_m3_elements) {
os_memcpy(pos, wpabuf_head(conf->eapol_m3_elements),
wpabuf_len(conf->eapol_m3_elements));
pos += wpabuf_len(conf->eapol_m3_elements);
}
if (conf->eapol_m3_no_encrypt)
encr = 0;
#endif /* CONFIG_TESTING_OPTIONS */
wpa_send_eapol(sm->wpa_auth, sm, wpa_send_eapol(sm->wpa_auth, sm,
(secure ? WPA_KEY_INFO_SECURE : 0) | (secure ? WPA_KEY_INFO_SECURE : 0) |
(wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ? (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ?

View file

@ -242,6 +242,9 @@ struct wpa_auth_config {
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; bool delay_eapol_tx;
struct wpabuf *eapol_m1_elements;
struct wpabuf *eapol_m3_elements;
bool eapol_m3_no_encrypt;
#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

@ -183,6 +183,12 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
wconf->oci_freq_override_ft_assoc = conf->oci_freq_override_ft_assoc; wconf->oci_freq_override_ft_assoc = conf->oci_freq_override_ft_assoc;
wconf->oci_freq_override_fils_assoc = wconf->oci_freq_override_fils_assoc =
conf->oci_freq_override_fils_assoc; conf->oci_freq_override_fils_assoc;
if (conf->eapol_m1_elements)
wconf->eapol_m1_elements = wpabuf_dup(conf->eapol_m1_elements);
if (conf->eapol_m3_elements)
wconf->eapol_m3_elements = wpabuf_dup(conf->eapol_m3_elements);
wconf->eapol_m3_no_encrypt = conf->eapol_m3_no_encrypt;
#endif /* CONFIG_TESTING_OPTIONS */ #endif /* CONFIG_TESTING_OPTIONS */
#ifdef CONFIG_P2P #ifdef CONFIG_P2P
os_memcpy(wconf->ip_addr_go, conf->ip_addr_go, 4); os_memcpy(wconf->ip_addr_go, conf->ip_addr_go, 4);