SAE H2E: RSNXE override in EAPOL-Key msg 3/4

This new hostapd configuration parameter rsnxe_override_eapol=<hexdump>
can be used to override RSNXE value in EAPOL-Key msg 3/4 for testing
purposes.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
This commit is contained in:
Jouni Malinen 2019-12-07 16:53:08 +02:00 committed by Jouni Malinen
parent 49ac2466c3
commit f2c4b44b40
6 changed files with 54 additions and 11 deletions

View file

@ -4156,6 +4156,9 @@ static int hostapd_config_fill(struct hostapd_config *conf,
} else if (os_strcmp(buf, "sae_commit_override") == 0) { } else if (os_strcmp(buf, "sae_commit_override") == 0) {
wpabuf_free(bss->sae_commit_override); wpabuf_free(bss->sae_commit_override);
bss->sae_commit_override = wpabuf_parse_bin(pos); 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 */ #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

@ -880,6 +880,7 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
#ifdef CONFIG_TESTING_OPTIONS #ifdef CONFIG_TESTING_OPTIONS
wpabuf_free(conf->own_ie_override); wpabuf_free(conf->own_ie_override);
wpabuf_free(conf->sae_commit_override); wpabuf_free(conf->sae_commit_override);
wpabuf_free(conf->rsnxe_override_eapol);
#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

@ -664,6 +664,7 @@ struct hostapd_bss_config {
struct wpabuf *own_ie_override; struct wpabuf *own_ie_override;
int sae_reflection_attack; int sae_reflection_attack;
struct wpabuf *sae_commit_override; struct wpabuf *sae_commit_override;
struct wpabuf *rsnxe_override_eapol;
#endif /* CONFIG_TESTING_OPTIONS */ #endif /* CONFIG_TESTING_OPTIONS */
#define MESH_ENABLED BIT(0) #define MESH_ENABLED BIT(0)

View file

@ -3139,11 +3139,12 @@ static int ocv_oci_add(struct wpa_state_machine *sm, u8 **argpos)
SM_STATE(WPA_PTK, PTKINITNEGOTIATING) 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; size_t gtk_len, kde_len;
struct wpa_group *gsm = sm->group; struct wpa_group *gsm = sm->group;
u8 *wpa_ie; u8 *wpa_ie;
int wpa_ie_len, secure, gtkidx, encr = 0; int wpa_ie_len, secure, gtkidx, encr = 0;
u8 *wpa_ie_buf = NULL;
SM_ENTRY_MA(WPA_PTK, PTKINITNEGOTIATING, wpa_ptk); SM_ENTRY_MA(WPA_PTK, PTKINITNEGOTIATING, wpa_ptk);
sm->TimeoutEvt = FALSE; sm->TimeoutEvt = FALSE;
@ -3177,6 +3178,35 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
wpa_ie = wpa_ie + wpa_ie[1] + 2; wpa_ie = wpa_ie + wpa_ie[1] + 2;
wpa_ie_len = 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, wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
"sending 3/4 msg of 4-Way Handshake"); "sending 3/4 msg of 4-Way Handshake");
if (sm->wpa == WPA_VERSION_WPA2) { if (sm->wpa == WPA_VERSION_WPA2) {
@ -3191,7 +3221,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
* of GTK in the BSS. * of GTK in the BSS.
*/ */
if (random_get_bytes(dummy_gtk, gtk_len) < 0) if (random_get_bytes(dummy_gtk, gtk_len) < 0)
return; goto done;
gtk = dummy_gtk; gtk = dummy_gtk;
} }
gtkidx = gsm->GN; gtkidx = gsm->GN;
@ -3234,7 +3264,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
#endif /* CONFIG_P2P */ #endif /* CONFIG_P2P */
kde = os_malloc(kde_len); kde = os_malloc(kde_len);
if (kde == NULL) if (kde == NULL)
return; goto done;
pos = kde; pos = kde;
os_memcpy(pos, wpa_ie, wpa_ie_len); os_memcpy(pos, wpa_ie, wpa_ie_len);
@ -3249,8 +3279,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
if (res < 0) { if (res < 0) {
wpa_printf(MSG_ERROR, "FT: Failed to insert " wpa_printf(MSG_ERROR, "FT: Failed to insert "
"PMKR1Name into RSN IE in EAPOL-Key data"); "PMKR1Name into RSN IE in EAPOL-Key data");
os_free(kde); goto done;
return;
} }
pos -= wpa_ie_len; pos -= wpa_ie_len;
pos += elen; pos += elen;
@ -3264,10 +3293,8 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
gtk, gtk_len); gtk, gtk_len);
} }
pos = ieee80211w_kde_add(sm, pos); pos = ieee80211w_kde_add(sm, pos);
if (ocv_oci_add(sm, &pos) < 0) { if (ocv_oci_add(sm, &pos) < 0)
os_free(kde); goto done;
return;
}
#ifdef CONFIG_IEEE80211R_AP #ifdef CONFIG_IEEE80211R_AP
if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
@ -3293,8 +3320,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
if (res < 0) { if (res < 0) {
wpa_printf(MSG_ERROR, "FT: Failed to insert FTIE " wpa_printf(MSG_ERROR, "FT: Failed to insert FTIE "
"into EAPOL-Key Key Data"); "into EAPOL-Key Key Data");
os_free(kde); goto done;
return;
} }
pos += res; pos += res;
@ -3331,7 +3357,9 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL | WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL |
WPA_KEY_INFO_KEY_TYPE, WPA_KEY_INFO_KEY_TYPE,
_rsc, sm->ANonce, kde, pos - kde, 0, encr); _rsc, sm->ANonce, kde, pos - kde, 0, encr);
done:
os_free(kde); os_free(kde);
os_free(wpa_ie_buf);
} }

View file

@ -219,6 +219,8 @@ struct wpa_auth_config {
double corrupt_gtk_rekey_mic_probability; double corrupt_gtk_rekey_mic_probability;
u8 own_ie_override[MAX_OWN_IE_OVERRIDE]; u8 own_ie_override[MAX_OWN_IE_OVERRIDE];
size_t own_ie_override_len; size_t own_ie_override_len;
u8 rsnxe_override_eapol[MAX_OWN_IE_OVERRIDE];
size_t rsnxe_override_eapol_len;
#endif /* CONFIG_TESTING_OPTIONS */ #endif /* CONFIG_TESTING_OPTIONS */
#ifdef CONFIG_P2P #ifdef CONFIG_P2P
u8 ip_addr_go[4]; u8 ip_addr_go[4];

View file

@ -118,6 +118,14 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
wpabuf_head(conf->own_ie_override), wpabuf_head(conf->own_ie_override),
wconf->own_ie_override_len); 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 */ #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);