From f2c4b44b40c29d52d9b398500f1f55015e56a857 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 7 Dec 2019 16:53:08 +0200 Subject: [PATCH] SAE H2E: RSNXE override in EAPOL-Key msg 3/4 This new hostapd configuration parameter rsnxe_override_eapol= can be used to override RSNXE value in EAPOL-Key msg 3/4 for testing purposes. Signed-off-by: Jouni Malinen --- hostapd/config_file.c | 3 +++ src/ap/ap_config.c | 1 + src/ap/ap_config.h | 1 + src/ap/wpa_auth.c | 50 ++++++++++++++++++++++++++++++++---------- src/ap/wpa_auth.h | 2 ++ src/ap/wpa_auth_glue.c | 8 +++++++ 6 files changed, 54 insertions(+), 11 deletions(-) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 40066add3..25dc1fade 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -4156,6 +4156,9 @@ static int hostapd_config_fill(struct hostapd_config *conf, } else if (os_strcmp(buf, "sae_commit_override") == 0) { wpabuf_free(bss->sae_commit_override); bss->sae_commit_override = wpabuf_parse_bin(pos); + } else if (os_strcmp(buf, "rsnxe_override_eapol") == 0) { + wpabuf_free(bss->rsnxe_override_eapol); + bss->rsnxe_override_eapol = wpabuf_parse_bin(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 d4a340484..70829679d 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -880,6 +880,7 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf) #ifdef CONFIG_TESTING_OPTIONS wpabuf_free(conf->own_ie_override); wpabuf_free(conf->sae_commit_override); + wpabuf_free(conf->rsnxe_override_eapol); #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 2a0c984a3..23416c6eb 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -664,6 +664,7 @@ struct hostapd_bss_config { struct wpabuf *own_ie_override; int sae_reflection_attack; struct wpabuf *sae_commit_override; + struct wpabuf *rsnxe_override_eapol; #endif /* CONFIG_TESTING_OPTIONS */ #define MESH_ENABLED BIT(0) diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 7b690d730..891cdd22a 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -3139,11 +3139,12 @@ static int ocv_oci_add(struct wpa_state_machine *sm, u8 **argpos) SM_STATE(WPA_PTK, PTKINITNEGOTIATING) { - u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde, *pos, dummy_gtk[32]; + u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde = NULL, *pos, dummy_gtk[32]; size_t gtk_len, kde_len; struct wpa_group *gsm = sm->group; u8 *wpa_ie; int wpa_ie_len, secure, gtkidx, encr = 0; + u8 *wpa_ie_buf = NULL; SM_ENTRY_MA(WPA_PTK, PTKINITNEGOTIATING, wpa_ptk); sm->TimeoutEvt = FALSE; @@ -3177,6 +3178,35 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) wpa_ie = wpa_ie + wpa_ie[1] + 2; wpa_ie_len = wpa_ie[1] + 2; } +#ifdef CONFIG_TESTING_OPTIONS + if (sm->wpa_auth->conf.rsnxe_override_eapol_len) { + u8 *obuf = sm->wpa_auth->conf.rsnxe_override_eapol; + size_t olen = sm->wpa_auth->conf.rsnxe_override_eapol_len; + const u8 *rsnxe; + + wpa_hexdump(MSG_DEBUG, + "TESTING: wpa_ie before RSNXE EAPOL override", + wpa_ie, wpa_ie_len); + wpa_ie_buf = os_malloc(wpa_ie_len + olen); + if (!wpa_ie_buf) + return; + os_memcpy(wpa_ie_buf, wpa_ie, wpa_ie_len); + wpa_ie = wpa_ie_buf; + rsnxe = get_ie(wpa_ie, wpa_ie_len, WLAN_EID_RSNX); + if (rsnxe) { + u8 rsnxe_len = 2 + rsnxe[1]; + + os_memmove((void *) rsnxe, rsnxe + rsnxe_len, + wpa_ie_len - (rsnxe - wpa_ie) - rsnxe_len); + wpa_ie_len -= rsnxe_len; + } + os_memcpy(wpa_ie + wpa_ie_len, obuf, olen); + wpa_ie_len += olen; + wpa_hexdump(MSG_DEBUG, + "TESTING: wpa_ie after RSNXE EAPOL override", + wpa_ie, wpa_ie_len); + } +#endif /* CONFIG_TESTING_OPTIONS */ wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, "sending 3/4 msg of 4-Way Handshake"); if (sm->wpa == WPA_VERSION_WPA2) { @@ -3191,7 +3221,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) * of GTK in the BSS. */ if (random_get_bytes(dummy_gtk, gtk_len) < 0) - return; + goto done; gtk = dummy_gtk; } gtkidx = gsm->GN; @@ -3234,7 +3264,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) #endif /* CONFIG_P2P */ kde = os_malloc(kde_len); if (kde == NULL) - return; + goto done; pos = kde; os_memcpy(pos, wpa_ie, wpa_ie_len); @@ -3249,8 +3279,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) if (res < 0) { wpa_printf(MSG_ERROR, "FT: Failed to insert " "PMKR1Name into RSN IE in EAPOL-Key data"); - os_free(kde); - return; + goto done; } pos -= wpa_ie_len; pos += elen; @@ -3264,10 +3293,8 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) gtk, gtk_len); } pos = ieee80211w_kde_add(sm, pos); - if (ocv_oci_add(sm, &pos) < 0) { - os_free(kde); - return; - } + if (ocv_oci_add(sm, &pos) < 0) + goto done; #ifdef CONFIG_IEEE80211R_AP if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { @@ -3293,8 +3320,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) if (res < 0) { wpa_printf(MSG_ERROR, "FT: Failed to insert FTIE " "into EAPOL-Key Key Data"); - os_free(kde); - return; + goto done; } pos += res; @@ -3331,7 +3357,9 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL | WPA_KEY_INFO_KEY_TYPE, _rsc, sm->ANonce, kde, pos - kde, 0, encr); +done: os_free(kde); + os_free(wpa_ie_buf); } diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index f62783812..933a4b8ed 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -219,6 +219,8 @@ struct wpa_auth_config { double corrupt_gtk_rekey_mic_probability; u8 own_ie_override[MAX_OWN_IE_OVERRIDE]; size_t own_ie_override_len; + u8 rsnxe_override_eapol[MAX_OWN_IE_OVERRIDE]; + size_t rsnxe_override_eapol_len; #endif /* CONFIG_TESTING_OPTIONS */ #ifdef CONFIG_P2P u8 ip_addr_go[4]; diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c index ddab95040..7fb0923e4 100644 --- a/src/ap/wpa_auth_glue.c +++ b/src/ap/wpa_auth_glue.c @@ -118,6 +118,14 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf, wpabuf_head(conf->own_ie_override), wconf->own_ie_override_len); } + if (conf->rsnxe_override_eapol && + wpabuf_len(conf->rsnxe_override_eapol) <= MAX_OWN_IE_OVERRIDE) { + wconf->rsnxe_override_eapol_len = + wpabuf_len(conf->rsnxe_override_eapol); + os_memcpy(wconf->rsnxe_override_eapol, + wpabuf_head(conf->rsnxe_override_eapol), + wconf->rsnxe_override_eapol_len); + } #endif /* CONFIG_TESTING_OPTIONS */ #ifdef CONFIG_P2P os_memcpy(wconf->ip_addr_go, conf->ip_addr_go, 4);