From d3516cad7a8fc6893650bf32580c13fbd96eabf8 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 18 Oct 2019 00:11:24 +0300 Subject: [PATCH] Store a copy of Association Request RSNXE in AP mode for later use This is needed to be able to compare the received RSNXE to a protected version in EAPOL-Key msg 2/4. Signed-off-by: Jouni Malinen --- src/ap/drv_callbacks.c | 2 ++ src/ap/ieee802_11.c | 6 +++++- src/ap/wpa_auth.c | 1 + src/ap/wpa_auth.h | 1 + src/ap/wpa_auth_i.h | 2 ++ src/ap/wpa_auth_ie.c | 16 ++++++++++++++++ tests/fuzzing/eapol-key-auth/eapol-key-auth.c | 3 ++- tests/test-eapol.c | 2 +- wpa_supplicant/ibss_rsn.c | 2 +- 9 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index 57c14347d..f863c9869 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -319,6 +319,8 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr, res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm, hapd->iface->freq, ie, ielen, + elems.rsnxe ? elems.rsnxe - 2 : NULL, + elems.rsnxe ? elems.rsnxe_len + 2 : 0, elems.mdie, elems.mdie_len, elems.owe_dh, elems.owe_dh_len); if (res != WPA_IE_OK) { diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 401f907f4..7cd00624f 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -1654,6 +1654,8 @@ void handle_auth_fils(struct hostapd_data *hapd, struct sta_info *sta, res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm, hapd->iface->freq, elems.rsn_ie - 2, elems.rsn_ie_len + 2, + elems.rsnxe ? elems.rsnxe - 2 : NULL, + elems.rsnxe ? elems.rsnxe_len + 2 : 0, elems.mdie, elems.mdie_len, NULL, 0); resp = wpa_res_to_status_code(res); if (resp != WLAN_STATUS_SUCCESS) @@ -2965,7 +2967,7 @@ u16 owe_process_rsn_ie(struct hostapd_data *hapd, rsn_ie_len += 2; res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm, hapd->iface->freq, rsn_ie, rsn_ie_len, - NULL, 0, owe_dh, owe_dh_len); + NULL, 0, NULL, 0, owe_dh, owe_dh_len); status = wpa_res_to_status_code(res); if (status != WLAN_STATUS_SUCCESS) goto end; @@ -3173,6 +3175,8 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm, hapd->iface->freq, wpa_ie, wpa_ie_len, + elems.rsnxe ? elems.rsnxe - 2 : NULL, + elems.rsnxe ? elems.rsnxe_len + 2 : 0, elems.mdie, elems.mdie_len, elems.owe_dh, elems.owe_dh_len); resp = wpa_res_to_status_code(res); diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 1c82ccf62..aaea5841f 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -708,6 +708,7 @@ static void wpa_free_sta_sm(struct wpa_state_machine *sm) #endif /* CONFIG_IEEE80211R_AP */ os_free(sm->last_rx_eapol_key); os_free(sm->wpa_ie); + os_free(sm->rsnxe); wpa_group_put(sm->wpa_auth, sm->group); #ifdef CONFIG_DPP2 wpabuf_clear_free(sm->dpp_z); diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index f0f03aa52..f62783812 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -319,6 +319,7 @@ enum { int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, struct wpa_state_machine *sm, int freq, const u8 *wpa_ie, size_t wpa_ie_len, + const u8 *rsnxe, size_t rsnxe_len, const u8 *mdie, size_t mdie_len, const u8 *owe_dh, size_t owe_dh_len); int wpa_validate_osen(struct wpa_authenticator *wpa_auth, diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h index f568a90c8..a993f5008 100644 --- a/src/ap/wpa_auth_i.h +++ b/src/ap/wpa_auth_i.h @@ -102,6 +102,8 @@ struct wpa_state_machine { u8 *wpa_ie; size_t wpa_ie_len; + u8 *rsnxe; + size_t rsnxe_len; enum { WPA_VERSION_NO_WPA = 0 /* WPA not used */, diff --git a/src/ap/wpa_auth_ie.c b/src/ap/wpa_auth_ie.c index 4b0e279dc..c0f57aa7f 100644 --- a/src/ap/wpa_auth_ie.c +++ b/src/ap/wpa_auth_ie.c @@ -549,6 +549,7 @@ static int wpa_auth_okc_iter(struct wpa_authenticator *a, void *ctx) int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, struct wpa_state_machine *sm, int freq, const u8 *wpa_ie, size_t wpa_ie_len, + const u8 *rsnxe, size_t rsnxe_len, const u8 *mdie, size_t mdie_len, const u8 *owe_dh, size_t owe_dh_len) { @@ -952,6 +953,21 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, os_memcpy(sm->wpa_ie, wpa_ie, wpa_ie_len); sm->wpa_ie_len = wpa_ie_len; + if (rsnxe && rsnxe_len) { + if (!sm->rsnxe || sm->rsnxe_len < rsnxe_len) { + os_free(sm->rsnxe); + sm->rsnxe = os_malloc(rsnxe_len); + if (!sm->rsnxe) + return WPA_ALLOC_FAIL; + } + os_memcpy(sm->rsnxe, rsnxe, rsnxe_len); + sm->rsnxe_len = rsnxe_len; + } else { + os_free(sm->rsnxe); + sm->rsnxe = NULL; + sm->rsnxe_len = 0; + } + return WPA_IE_OK; } diff --git a/tests/fuzzing/eapol-key-auth/eapol-key-auth.c b/tests/fuzzing/eapol-key-auth/eapol-key-auth.c index 0fffa783f..a909114a4 100644 --- a/tests/fuzzing/eapol-key-auth/eapol-key-auth.c +++ b/tests/fuzzing/eapol-key-auth/eapol-key-auth.c @@ -261,7 +261,8 @@ static int auth_init(struct wpa *wpa) } if (wpa_validate_wpa_ie(wpa->auth_group, wpa->auth, 2412, supp_ie, - supp_ie_len, NULL, 0, NULL, 0) != WPA_IE_OK) { + supp_ie_len, NULL, 0, NULL, 0, NULL, 0) != + WPA_IE_OK) { wpa_printf(MSG_DEBUG, "AUTH: wpa_validate_wpa_ie() failed"); return -1; } diff --git a/tests/test-eapol.c b/tests/test-eapol.c index 0dd65e489..944e4cfb9 100644 --- a/tests/test-eapol.c +++ b/tests/test-eapol.c @@ -504,7 +504,7 @@ static int auth_init(struct wpa *wpa) } if (wpa_validate_wpa_ie(wpa->auth_group, wpa->auth, 2412, wpa->supp_ie, - wpa->supp_ie_len, NULL, 0, NULL, 0) != + wpa->supp_ie_len, NULL, 0, NULL, 0, NULL, 0) != WPA_IE_OK) { wpa_printf(MSG_DEBUG, "AUTH: wpa_validate_wpa_ie() failed"); return -1; diff --git a/wpa_supplicant/ibss_rsn.c b/wpa_supplicant/ibss_rsn.c index 2bf51c626..36c0aff17 100644 --- a/wpa_supplicant/ibss_rsn.c +++ b/wpa_supplicant/ibss_rsn.c @@ -465,7 +465,7 @@ static int ibss_rsn_auth_init(struct ibss_rsn *ibss_rsn, "\x00\x0f\xac\x04" "\x01\x00\x00\x0f\xac\x04" "\x01\x00\x00\x0f\xac\x02" - "\x00\x00", 22, NULL, 0, NULL, 0) != + "\x00\x00", 22, NULL, 0, NULL, 0, NULL, 0) != WPA_IE_OK) { wpa_printf(MSG_DEBUG, "AUTH: wpa_validate_wpa_ie() failed"); return -1;