diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 15aaca924..0c0137b4f 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -4355,6 +4355,14 @@ static int hostapd_config_fill(struct hostapd_config *conf, bss->eap_skip_prot_success = atoi(pos); } else if (os_strcmp(buf, "delay_eapol_tx") == 0) { 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 */ #ifdef CONFIG_SAE } else if (os_strcmp(buf, "sae_password") == 0) { diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c index 040f39e7f..429879189 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -948,6 +948,8 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf) wpabuf_free(conf->rsnxe_override_ft); wpabuf_free(conf->gtk_rsc_override); wpabuf_free(conf->igtk_rsc_override); + wpabuf_free(conf->eapol_m1_elements); + wpabuf_free(conf->eapol_m3_elements); #endif /* CONFIG_TESTING_OPTIONS */ os_free(conf->no_probe_resp_if_seen_on); diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index 1d3949559..7e7c340cd 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -704,6 +704,9 @@ struct hostapd_bss_config { unsigned int oci_freq_override_ft_assoc; unsigned int oci_freq_override_fils_assoc; 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 u16 eht_oper_puncturing_override; diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 74925a4ff..1b2a89a80 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -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_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)); } + wpa_auth_free_conf(&wpa_auth->conf); os_free(wpa_auth); } @@ -673,6 +685,7 @@ int wpa_reconfig(struct wpa_authenticator *wpa_auth, if (!wpa_auth) return 0; + wpa_auth_free_conf(&wpa_auth->conf); os_memcpy(&wpa_auth->conf, conf, sizeof(*conf)); if (wpa_auth_gen_wpa_ie(wpa_auth)) { wpa_printf(MSG_ERROR, "Could not generate WPA IE."); @@ -2332,10 +2345,14 @@ SM_STATE(WPA_PTK, INITPSK) 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; size_t kde_len = 0; 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->PTKRequest = false; @@ -2350,6 +2367,19 @@ SM_STATE(WPA_PTK, PTKSTART) 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, "sending 1/4 msg of 4-Way Handshake"); /* @@ -2453,11 +2483,20 @@ SM_STATE(WPA_PTK, PTKSTART) } #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; if (sm->pairwise_set && sm->wpa != WPA_VERSION_WPA) key_info |= WPA_KEY_INFO_SECURE; wpa_send_eapol(sm->wpa_auth, sm, key_info, NULL, 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); +#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); if (!kde) goto done; @@ -4374,6 +4418,17 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) 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, (secure ? WPA_KEY_INFO_SECURE : 0) | (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ? diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index 058d99902..c74862307 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -242,6 +242,9 @@ struct wpa_auth_config { unsigned int igtk_rsc_override_set:1; int ft_rsnxe_used; bool delay_eapol_tx; + struct wpabuf *eapol_m1_elements; + struct wpabuf *eapol_m3_elements; + bool eapol_m3_no_encrypt; #endif /* CONFIG_TESTING_OPTIONS */ unsigned int oci_freq_override_eapol_m3; unsigned int oci_freq_override_eapol_g1; diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c index 76e854156..5737ab8dc 100644 --- a/src/ap/wpa_auth_glue.c +++ b/src/ap/wpa_auth_glue.c @@ -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_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 */ #ifdef CONFIG_P2P os_memcpy(wconf->ip_addr_go, conf->ip_addr_go, 4);