From aa08d9d76803f871bb90535e8eaf90e0b6b08870 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 25 Aug 2023 19:34:44 +0300 Subject: [PATCH] Fix use of defragmented FTE information The FTE parser itself used valid data, but the reassembled buffer was available only during the parser run. That buffer will be needed for the caller as well since most of the parsed data is used as pointers instead of copied data. Store the reassembled buffer in struct wpa_ft_ies and require wpa_ft_parse_ies() callers to use wpa_ft_parse_ies_free() to free any possibly allocated temporary data after wpa_ft_parse_ies() calls that return success (0). Fixes: 43b5f11d969a ("Defragmentation of FTE") Signed-off-by: Jouni Malinen --- src/ap/wpa_auth_ft.c | 130 ++++++++++++++++++++++++++-------------- src/common/wpa_common.c | 46 +++++++++----- src/common/wpa_common.h | 3 + src/rsn_supp/wpa.c | 13 +++- src/rsn_supp/wpa_ft.c | 100 ++++++++++++++++++------------- wlantest/rx_mgmt.c | 86 ++++++++++++++------------ 6 files changed, 235 insertions(+), 143 deletions(-) diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c index 70e73df16..4b16f62df 100644 --- a/src/ap/wpa_auth_ft.c +++ b/src/ap/wpa_auth_ft.c @@ -2821,8 +2821,10 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, } else { res = wpa_write_rsnxe(&sm->wpa_auth->conf, rsnxe, sizeof(rsnxe_buf)); - if (res < 0) - return NULL; + if (res < 0) { + pos = NULL; + goto fail; + } rsnxe_len = res; } #ifdef CONFIG_TESTING_OPTIONS @@ -2854,15 +2856,20 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, NULL, fte_mic) < 0) { wpa_printf(MSG_DEBUG, "FT: Failed to calculate MIC"); - return NULL; + pos = NULL; + goto fail; } os_free(sm->assoc_resp_ftie); sm->assoc_resp_ftie = os_malloc(ftie_len); - if (!sm->assoc_resp_ftie) - return NULL; + if (!sm->assoc_resp_ftie) { + pos = NULL; + goto fail; + } os_memcpy(sm->assoc_resp_ftie, ftie, ftie_len); +fail: + wpa_ft_parse_ies_free(&parse); return pos; } @@ -3174,6 +3181,7 @@ static int wpa_ft_process_auth_req(struct wpa_state_machine *sm, const u8 *identity, *radius_cui; size_t identity_len = 0, radius_cui_len = 0; size_t pmk_r1_len, kdk_len, len; + int retval = WLAN_STATUS_UNSPECIFIED_FAILURE; *resp_ies = NULL; *resp_ies_len = 0; @@ -3195,17 +3203,20 @@ static int wpa_ft_process_auth_req(struct wpa_state_machine *sm, sm->wpa_auth->conf.mobility_domain, MOBILITY_DOMAIN_ID_LEN) != 0) { wpa_printf(MSG_DEBUG, "FT: Invalid MDIE"); - return WLAN_STATUS_INVALID_MDIE; + retval = WLAN_STATUS_INVALID_MDIE; + goto out; } if (!parse.ftie || parse.ftie_len < sizeof(struct rsn_ftie)) { wpa_printf(MSG_DEBUG, "FT: Invalid FTIE"); - return WLAN_STATUS_INVALID_FTIE; + retval = WLAN_STATUS_INVALID_FTIE; + goto out; } if (parse.r0kh_id == NULL) { wpa_printf(MSG_DEBUG, "FT: Invalid FTIE - no R0KH-ID"); - return WLAN_STATUS_INVALID_FTIE; + retval = WLAN_STATUS_INVALID_FTIE; + goto out; } wpa_hexdump(MSG_DEBUG, "FT: STA R0KH-ID", @@ -3215,11 +3226,12 @@ static int wpa_ft_process_auth_req(struct wpa_state_machine *sm, if (parse.rsn_pmkid == NULL) { wpa_printf(MSG_DEBUG, "FT: No PMKID in RSNIE"); - return WLAN_STATUS_INVALID_PMKID; + retval = WLAN_STATUS_INVALID_PMKID; + goto out; } if (wpa_ft_set_key_mgmt(sm, &parse) < 0) - return WLAN_STATUS_UNSPECIFIED_FAILURE; + goto out; wpa_hexdump(MSG_DEBUG, "FT: Requested PMKR0Name", parse.rsn_pmkid, WPA_PMK_NAME_LEN); @@ -3229,12 +3241,14 @@ static int wpa_ft_process_auth_req(struct wpa_state_machine *sm, if (wpa_derive_pmk_r1_name(parse.rsn_pmkid, sm->wpa_auth->conf.r1_key_holder, sm->addr, pmk_r1_name, PMK_LEN) < 0) - return WLAN_STATUS_UNSPECIFIED_FAILURE; + goto out; if (wpa_ft_psk_pmk_r1(sm, pmk_r1_name, pmk_r1, &pairwise, &vlan, &identity, &identity_len, &radius_cui, &radius_cui_len, - &session_timeout) < 0) - return WLAN_STATUS_INVALID_PMKID; + &session_timeout) < 0) { + retval = WLAN_STATUS_INVALID_PMKID; + goto out; + } pmk_r1_len = PMK_LEN; wpa_printf(MSG_DEBUG, "FT: Generated PMK-R1 for FT-PSK locally"); @@ -3285,10 +3299,12 @@ static int wpa_ft_process_auth_req(struct wpa_state_machine *sm, if (wpa_ft_pull_pmk_r1(sm, ies, ies_len, parse.rsn_pmkid) < 0) { wpa_printf(MSG_DEBUG, "FT: Did not have matching PMK-R1 and either unknown or blocked R0KH-ID or NAK from R0KH"); - return WLAN_STATUS_INVALID_PMKID; + retval = WLAN_STATUS_INVALID_PMKID; + goto out; } - return -1; /* Status pending */ + retval = -1; /* Status pending */ + goto out; pmk_r1_derived: wpa_hexdump_key(MSG_DEBUG, "FT: Selected PMK-R1", pmk_r1, pmk_r1_len); @@ -3300,7 +3316,7 @@ pmk_r1_derived: if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) { wpa_printf(MSG_DEBUG, "FT: Failed to get random data for " "ANonce"); - return WLAN_STATUS_UNSPECIFIED_FAILURE; + goto out; } /* Now that we know the correct PMK-R1 length and as such, the length @@ -3311,7 +3327,8 @@ pmk_r1_derived: ftie = (const struct rsn_ftie_sha512 *) parse.ftie; if (!ftie || parse.ftie_len < sizeof(*ftie)) { wpa_printf(MSG_DEBUG, "FT: Invalid FTIE"); - return WLAN_STATUS_INVALID_FTIE; + retval = WLAN_STATUS_INVALID_FTIE; + goto out; } os_memcpy(sm->SNonce, ftie->snonce, WPA_NONCE_LEN); @@ -3321,7 +3338,8 @@ pmk_r1_derived: ftie = (const struct rsn_ftie_sha384 *) parse.ftie; if (!ftie || parse.ftie_len < sizeof(*ftie)) { wpa_printf(MSG_DEBUG, "FT: Invalid FTIE"); - return WLAN_STATUS_INVALID_FTIE; + retval = WLAN_STATUS_INVALID_FTIE; + goto out; } os_memcpy(sm->SNonce, ftie->snonce, WPA_NONCE_LEN); @@ -3331,7 +3349,8 @@ pmk_r1_derived: ftie = (const struct rsn_ftie *) parse.ftie; if (!ftie || parse.ftie_len < sizeof(*ftie)) { wpa_printf(MSG_DEBUG, "FT: Invalid FTIE"); - return WLAN_STATUS_INVALID_FTIE; + retval = WLAN_STATUS_INVALID_FTIE; + goto out; } os_memcpy(sm->SNonce, ftie->snonce, WPA_NONCE_LEN); @@ -3353,14 +3372,14 @@ pmk_r1_derived: sm->addr, sm->wpa_auth->addr, pmk_r1_name, &sm->PTK, ptk_name, parse.key_mgmt, pairwise, kdk_len) < 0) - return WLAN_STATUS_UNSPECIFIED_FAILURE; + goto out; #ifdef CONFIG_PASN if (sm->wpa_auth->conf.secure_ltf && ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF) && wpa_ltf_keyseed(&sm->PTK, parse.key_mgmt, pairwise)) { wpa_printf(MSG_DEBUG, "FT: Failed to derive LTF keyseed"); - return WLAN_STATUS_UNSPECIFIED_FAILURE; + goto out; } #endif /* CONFIG_PASN */ @@ -3371,14 +3390,14 @@ pmk_r1_derived: if (wpa_ft_set_vlan(sm->wpa_auth, sm->addr, &vlan) < 0) { wpa_printf(MSG_DEBUG, "FT: Failed to configure VLAN"); - return WLAN_STATUS_UNSPECIFIED_FAILURE; + goto out; } if (wpa_ft_set_identity(sm->wpa_auth, sm->addr, identity, identity_len) < 0 || wpa_ft_set_radius_cui(sm->wpa_auth, sm->addr, radius_cui, radius_cui_len) < 0) { wpa_printf(MSG_DEBUG, "FT: Failed to configure identity/CUI"); - return WLAN_STATUS_UNSPECIFIED_FAILURE; + goto out; } wpa_ft_set_session_timeout(sm->wpa_auth, sm->addr, session_timeout); @@ -3411,11 +3430,14 @@ pmk_r1_derived: *resp_ies_len = pos - *resp_ies; - return WLAN_STATUS_SUCCESS; + retval = WLAN_STATUS_SUCCESS; + goto out; fail: os_free(*resp_ies); *resp_ies = NULL; - return WLAN_STATUS_UNSPECIFIED_FAILURE; +out: + wpa_ft_parse_ies_free(&parse); + return retval; } @@ -3474,6 +3496,7 @@ int wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, const u8 *kck; size_t kck_len; struct wpa_auth_config *conf; + int retval = WLAN_STATUS_UNSPECIFIED_FAILURE; if (sm == NULL) return WLAN_STATUS_UNSPECIFIED_FAILURE; @@ -3490,19 +3513,21 @@ int wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, if (parse.rsn == NULL) { wpa_printf(MSG_DEBUG, "FT: No RSNIE in Reassoc Req"); - return WLAN_STATUS_UNSPECIFIED_FAILURE; + goto out; } if (parse.rsn_pmkid == NULL) { wpa_printf(MSG_DEBUG, "FT: No PMKID in RSNIE"); - return WLAN_STATUS_INVALID_PMKID; + retval = WLAN_STATUS_INVALID_PMKID; + goto out; } if (os_memcmp_const(parse.rsn_pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN) != 0) { wpa_printf(MSG_DEBUG, "FT: PMKID in Reassoc Req did not match " "with the PMKR1Name derived from auth request"); - return WLAN_STATUS_INVALID_PMKID; + retval = WLAN_STATUS_INVALID_PMKID; + goto out; } mdie = (struct rsn_mdie *) parse.mdie; @@ -3510,7 +3535,8 @@ int wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, os_memcmp(mdie->mobility_domain, conf->mobility_domain, MOBILITY_DOMAIN_ID_LEN) != 0) { wpa_printf(MSG_DEBUG, "FT: Invalid MDIE"); - return WLAN_STATUS_INVALID_MDIE; + retval = WLAN_STATUS_INVALID_MDIE; + goto out; } if (sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_SAE_EXT_KEY && @@ -3528,7 +3554,8 @@ int wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, wpa_printf(MSG_DEBUG, "FT: Invalid FTE (fte_mic_len=%zu mic_len=%zu)", parse.fte_mic_len, mic_len); - return WLAN_STATUS_INVALID_FTIE; + retval = WLAN_STATUS_INVALID_FTIE; + goto out; } if (os_memcmp(parse.fte_snonce, sm->SNonce, WPA_NONCE_LEN) != 0) { @@ -3537,7 +3564,8 @@ int wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, parse.fte_snonce, WPA_NONCE_LEN); wpa_hexdump(MSG_DEBUG, "FT: Expected SNonce", sm->SNonce, WPA_NONCE_LEN); - return WLAN_STATUS_INVALID_FTIE; + retval = WLAN_STATUS_INVALID_FTIE; + goto out; } if (os_memcmp(parse.fte_anonce, sm->ANonce, WPA_NONCE_LEN) != 0) { @@ -3546,12 +3574,14 @@ int wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, parse.fte_anonce, WPA_NONCE_LEN); wpa_hexdump(MSG_DEBUG, "FT: Expected ANonce", sm->ANonce, WPA_NONCE_LEN); - return WLAN_STATUS_INVALID_FTIE; + retval = WLAN_STATUS_INVALID_FTIE; + goto out; } if (parse.r0kh_id == NULL) { wpa_printf(MSG_DEBUG, "FT: No R0KH-ID subelem in FTIE"); - return WLAN_STATUS_INVALID_FTIE; + retval = WLAN_STATUS_INVALID_FTIE; + goto out; } if (parse.r0kh_id_len != sm->r0kh_id_len || @@ -3563,12 +3593,14 @@ int wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, parse.r0kh_id, parse.r0kh_id_len); wpa_hexdump(MSG_DEBUG, "FT: The current R0KH-ID", sm->r0kh_id, sm->r0kh_id_len); - return WLAN_STATUS_INVALID_FTIE; + retval = WLAN_STATUS_INVALID_FTIE; + goto out; } if (parse.r1kh_id == NULL) { wpa_printf(MSG_DEBUG, "FT: No R1KH-ID subelem in FTIE"); - return WLAN_STATUS_INVALID_FTIE; + retval = WLAN_STATUS_INVALID_FTIE; + goto out; } if (os_memcmp_const(parse.r1kh_id, conf->r1_key_holder, @@ -3579,7 +3611,8 @@ int wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, parse.r1kh_id, FT_R1KH_ID_LEN); wpa_hexdump(MSG_DEBUG, "FT: Expected R1KH-ID", conf->r1_key_holder, FT_R1KH_ID_LEN); - return WLAN_STATUS_INVALID_FTIE; + retval = WLAN_STATUS_INVALID_FTIE; + goto out; } if (parse.rsn_pmkid == NULL || @@ -3587,7 +3620,8 @@ int wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, { wpa_printf(MSG_DEBUG, "FT: No matching PMKR1Name (PMKID) in " "RSNIE (pmkid=%d)", !!parse.rsn_pmkid); - return WLAN_STATUS_INVALID_PMKID; + retval = WLAN_STATUS_INVALID_PMKID; + goto out; } count = 3; @@ -3599,7 +3633,7 @@ int wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, wpa_printf(MSG_DEBUG, "FT: Unexpected IE count in MIC " "Control: received %u expected %u", parse.fte_elem_count, count); - return WLAN_STATUS_UNSPECIFIED_FAILURE; + goto out; } if (wpa_key_mgmt_fils(sm->wpa_key_mgmt)) { @@ -3620,7 +3654,7 @@ int wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, NULL, mic) < 0) { wpa_printf(MSG_DEBUG, "FT: Failed to calculate MIC"); - return WLAN_STATUS_UNSPECIFIED_FAILURE; + goto out; } if (os_memcmp_const(mic, parse.fte_mic, mic_len) != 0) { @@ -3639,7 +3673,8 @@ int wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, wpa_hexdump(MSG_MSGDUMP, "FT: RSNXE", parse.rsnxe ? parse.rsnxe - 2 : NULL, parse.rsnxe ? parse.rsnxe_len + 2 : 0); - return WLAN_STATUS_INVALID_FTIE; + retval = WLAN_STATUS_INVALID_FTIE; + goto out; } if (parse.fte_rsnxe_used && @@ -3648,7 +3683,8 @@ int wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, !parse.rsnxe) { wpa_printf(MSG_INFO, "FT: FTE indicated that STA uses RSNXE, but RSNXE was not included"); - return -1; /* discard request */ + retval = -1; /* discard request */ + goto out; } #ifdef CONFIG_OCV @@ -3661,14 +3697,14 @@ int wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, if (wpa_channel_info(sm->wpa_auth, &ci) != 0) { wpa_printf(MSG_WARNING, "Failed to get channel info to validate received OCI in (Re)Assoc Request"); - return WLAN_STATUS_UNSPECIFIED_FAILURE; + goto out; } if (get_sta_tx_parameters(sm, channel_width_to_int(ci.chanwidth), ci.seg1_idx, &tx_chanwidth, &tx_seg1_idx) < 0) - return WLAN_STATUS_UNSPECIFIED_FAILURE; + goto out; res = ocv_verify_tx_params(parse.oci, parse.oci_len, &ci, tx_chanwidth, tx_seg1_idx); @@ -3684,12 +3720,16 @@ int wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, OCV_FAILURE "addr=" MACSTR " frame=ft-reassoc-req error=%s", MAC2STR(sm->addr), ocv_errorstr); - return WLAN_STATUS_INVALID_FTIE; + retval = WLAN_STATUS_INVALID_FTIE; + goto out; } } #endif /* CONFIG_OCV */ - return WLAN_STATUS_SUCCESS; + retval = WLAN_STATUS_SUCCESS; +out: + wpa_ft_parse_ies_free(&parse); + return retval; } diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c index c11b461eb..1e7a2bd1a 100644 --- a/src/common/wpa_common.c +++ b/src/common/wpa_common.c @@ -1222,7 +1222,7 @@ int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse, if (ieee802_11_parse_elems(ies, ies_len, &elems, 0) == ParseFailed) { wpa_printf(MSG_DEBUG, "FT: Failed to parse elements"); - return -1; + goto fail; } pos = ies; @@ -1250,7 +1250,7 @@ int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse, if (ret < 0) { wpa_printf(MSG_DEBUG, "FT: Failed to parse " "RSN IE: %d", ret); - return -1; + goto fail; } parse->rsn_capab = data.capabilities; if (data.num_pmkid == 1 && data.pmkid) @@ -1270,7 +1270,7 @@ int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse, case WLAN_EID_MOBILITY_DOMAIN: wpa_hexdump(MSG_DEBUG, "FT: MDE", pos, len); if (len < sizeof(struct rsn_mdie)) - return -1; + goto fail; parse->mdie = pos; parse->mdie_len = len; break; @@ -1284,7 +1284,7 @@ int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse, * using the struct rsn_ftie* definitions. */ if (len < 2) - return -1; + goto fail; prot_ie_count = pos[1]; /* Element Count field in * MIC Control */ is_fte = true; @@ -1321,17 +1321,17 @@ int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse, if (fte_len < 255) { res = wpa_ft_parse_fte(key_mgmt, fte, fte_len, parse); } else { - struct wpabuf *buf; - - buf = ieee802_11_defrag_data(fte, fte_len, false); - if (!buf) - return -1; - res = wpa_ft_parse_fte(key_mgmt, wpabuf_head(buf), - wpabuf_len(buf), parse); - wpabuf_free(buf); + parse->fte_buf = ieee802_11_defrag_data(fte, fte_len, + false); + if (!parse->fte_buf) + goto fail; + res = wpa_ft_parse_fte(key_mgmt, + wpabuf_head(parse->fte_buf), + wpabuf_len(parse->fte_buf), + parse); } if (res < 0) - return -1; + goto fail; } if (prot_ie_count == 0) @@ -1367,13 +1367,13 @@ int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse, if (prot_ie_count < 0) { wpa_printf(MSG_DEBUG, "FT: Some required IEs not included in " "the protected IE count"); - return -1; + goto fail; } if (prot_ie_count == 0 && parse->ric) { wpa_printf(MSG_DEBUG, "FT: RIC IE(s) in the frame, but not " "included in protected IE count"); - return -1; + goto fail; } /* Determine the end of the RIC IE(s) */ @@ -1389,11 +1389,25 @@ int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse, if (prot_ie_count) { wpa_printf(MSG_DEBUG, "FT: %d protected IEs missing from " "frame", (int) prot_ie_count); - return -1; + goto fail; } return 0; + +fail: + wpa_ft_parse_ies_free(parse); + return -1; } + + +void wpa_ft_parse_ies_free(struct wpa_ft_ies *parse) +{ + if (!parse) + return; + wpabuf_free(parse->fte_buf); + parse->fte_buf = NULL; +} + #endif /* CONFIG_IEEE80211R */ diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h index bfcd71781..80c7d324f 100644 --- a/src/common/wpa_common.h +++ b/src/common/wpa_common.h @@ -604,6 +604,8 @@ struct wpa_ft_ies { u16 valid_mlo_bigtks; /* bitmap of valid link BIGTK subelements */ const u8 *mlo_bigtk[MAX_NUM_MLO_LINKS]; size_t mlo_bigtk_len[MAX_NUM_MLO_LINKS]; + + struct wpabuf *fte_buf; }; /* IEEE P802.11az/D2.6 - 9.4.2.303 PASN Parameters element */ @@ -640,6 +642,7 @@ struct wpa_pasn_params_data { int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse, int key_mgmt, bool reassoc_resp); +void wpa_ft_parse_ies_free(struct wpa_ft_ies *parse); struct wpa_eapol_ie_parse { const u8 *wpa_ie; diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index fcd8ede3b..7294a15bc 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -5372,6 +5372,11 @@ int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data, const u8 *g_ap = NULL; size_t g_ap_len = 0, kdk_len; struct wpabuf *pub = NULL; +#ifdef CONFIG_IEEE80211R + struct wpa_ft_ies parse; + + os_memset(&parse, 0, sizeof(parse)); +#endif /* CONFIG_IEEE80211R */ os_memcpy(sm->bssid, bssid, ETH_ALEN); @@ -5450,8 +5455,6 @@ int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data, #ifdef CONFIG_IEEE80211R if (wpa_key_mgmt_ft(sm->key_mgmt)) { - struct wpa_ft_ies parse; - if (!elems.mdie || !elems.ftie) { wpa_printf(MSG_DEBUG, "FILS+FT: No MDE or FTE"); goto fail; @@ -5662,10 +5665,16 @@ int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data, &sm->fils_key_auth_len); wpabuf_free(pub); forced_memzero(ick, sizeof(ick)); +#ifdef CONFIG_IEEE80211R + wpa_ft_parse_ies_free(&parse); +#endif /* CONFIG_IEEE80211R */ return res; fail: wpabuf_free(pub); wpabuf_clear_free(dh_ss); +#ifdef CONFIG_IEEE80211R + wpa_ft_parse_ies_free(&parse); +#endif /* CONFIG_IEEE80211R */ return -1; } diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c index b88f1d2c6..69de046c0 100644 --- a/src/rsn_supp/wpa_ft.c +++ b/src/rsn_supp/wpa_ft.c @@ -130,8 +130,10 @@ int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *ies, size_t ies_len) if (wpa_ft_parse_ies(ies, ies_len, &ft, sm->key_mgmt, false) < 0) return -1; - if (ft.mdie_len < MOBILITY_DOMAIN_ID_LEN + 1) + if (ft.mdie_len < MOBILITY_DOMAIN_ID_LEN + 1) { + wpa_ft_parse_ies_free(&ft); return -1; + } wpa_hexdump(MSG_DEBUG, "FT: Mobility domain", ft.mdie, MOBILITY_DOMAIN_ID_LEN); @@ -179,6 +181,7 @@ int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *ies, size_t ies_len) sm->assoc_resp_ies, sm->assoc_resp_ies_len); } + wpa_ft_parse_ies_free(&ft); return 0; } @@ -587,11 +590,13 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len, struct wpa_ft_ies parse; struct rsn_mdie *mdie; u8 ptk_name[WPA_PMK_NAME_LEN]; - int ret; + int ret = -1, res; const u8 *bssid; const u8 *kck; size_t kck_len, kdk_len; + os_memset(&parse, 0, sizeof(parse)); + wpa_hexdump(MSG_DEBUG, "FT: Response IEs", ies, ies_len); wpa_hexdump(MSG_DEBUG, "FT: RIC IEs", ric_ies, ric_ies_len); @@ -599,27 +604,27 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len, if (!sm->over_the_ds_in_progress) { wpa_printf(MSG_DEBUG, "FT: No over-the-DS in progress " "- drop FT Action Response"); - return -1; + goto fail; } if (os_memcmp(target_ap, sm->target_ap, ETH_ALEN) != 0) { wpa_printf(MSG_DEBUG, "FT: No over-the-DS in progress " "with this Target AP - drop FT Action " "Response"); - return -1; + goto fail; } } if (!wpa_key_mgmt_ft(sm->key_mgmt)) { wpa_printf(MSG_DEBUG, "FT: Reject FT IEs since FT is not " "enabled for this connection"); - return -1; + goto fail; } if (wpa_ft_parse_ies(ies, ies_len, &parse, sm->key_mgmt, !ft_action) < 0) { wpa_printf(MSG_DEBUG, "FT: Failed to parse IEs"); - return -1; + goto fail; } mdie = (struct rsn_mdie *) parse.mdie; @@ -627,12 +632,12 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len, os_memcmp(mdie->mobility_domain, sm->mobility_domain, MOBILITY_DOMAIN_ID_LEN) != 0) { wpa_printf(MSG_DEBUG, "FT: Invalid MDIE"); - return -1; + goto fail; } if (!parse.ftie || !parse.fte_anonce || !parse.fte_snonce) { wpa_printf(MSG_DEBUG, "FT: Invalid FTE"); - return -1; + goto fail; } if (os_memcmp(parse.fte_snonce, sm->snonce, WPA_NONCE_LEN) != 0) { @@ -641,12 +646,12 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len, parse.fte_snonce, WPA_NONCE_LEN); wpa_hexdump(MSG_DEBUG, "FT: Expected SNonce", sm->snonce, WPA_NONCE_LEN); - return -1; + goto fail; } if (parse.r0kh_id == NULL) { wpa_printf(MSG_DEBUG, "FT: No R0KH-ID subelem in FTIE"); - return -1; + goto fail; } if (parse.r0kh_id_len != sm->r0kh_id_len || @@ -658,12 +663,12 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len, parse.r0kh_id, parse.r0kh_id_len); wpa_hexdump(MSG_DEBUG, "FT: The current R0KH-ID", sm->r0kh_id, sm->r0kh_id_len); - return -1; + goto fail; } if (parse.r1kh_id == NULL) { wpa_printf(MSG_DEBUG, "FT: No R1KH-ID subelem in FTIE"); - return -1; + goto fail; } if (parse.rsn_pmkid == NULL || @@ -671,13 +676,13 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len, { wpa_printf(MSG_DEBUG, "FT: No matching PMKR0Name (PMKID) in " "RSNIE"); - return -1; + goto fail; } if (sm->mfp == 2 && !(parse.rsn_capab & WPA_CAPABILITY_MFPC)) { wpa_printf(MSG_INFO, "FT: Target AP does not support PMF, but local configuration requires that"); - return -1; + goto fail; } os_memcpy(sm->r1kh_id, parse.r1kh_id, FT_R1KH_ID_LEN); @@ -688,7 +693,7 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len, if (wpa_derive_pmk_r1(sm->pmk_r0, sm->pmk_r0_len, sm->pmk_r0_name, sm->r1kh_id, sm->own_addr, sm->pmk_r1, sm->pmk_r1_name) < 0) - return -1; + goto fail; sm->pmk_r1_len = sm->pmk_r0_len; bssid = target_ap; @@ -708,7 +713,7 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len, sm->pmk_r1_name, &sm->ptk, ptk_name, sm->key_mgmt, sm->pairwise_cipher, kdk_len) < 0) - return -1; + goto fail; os_memcpy(sm->key_mobility_domain, sm->mobility_domain, MOBILITY_DOMAIN_ID_LEN); @@ -718,7 +723,7 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len, ieee802_11_rsnx_capab(sm->ap_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF) && wpa_ltf_keyseed(&sm->ptk, sm->key_mgmt, sm->pairwise_cipher)) { wpa_printf(MSG_DEBUG, "FT: Failed to derive LTF keyseed"); - return -1; + goto fail; } #endif /* CONFIG_PASN */ @@ -742,8 +747,8 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len, } wpa_sm_mark_authenticated(sm, bssid); - ret = wpa_ft_install_ptk(sm, bssid); - if (ret) { + res = wpa_ft_install_ptk(sm, bssid); + if (res) { /* * Some drivers do not support key configuration when we are * not associated with the target AP. Work around this by @@ -765,7 +770,10 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len, os_memcpy(sm->bssid, target_ap, ETH_ALEN); } - return 0; + ret = 0; +fail: + wpa_ft_parse_ies_free(&parse); + return ret; } @@ -1021,13 +1029,16 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, size_t kck_len; int own_rsnxe_used; size_t mic_len; + int ret = -1; + + os_memset(&parse, 0, sizeof(parse)); wpa_hexdump(MSG_DEBUG, "FT: Response IEs", ies, ies_len); if (!wpa_key_mgmt_ft(sm->key_mgmt)) { wpa_printf(MSG_DEBUG, "FT: Reject FT IEs since FT is not " "enabled for this connection"); - return -1; + goto fail; } if (sm->ft_reassoc_completed) { @@ -1037,7 +1048,7 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, if (wpa_ft_parse_ies(ies, ies_len, &parse, sm->key_mgmt, true) < 0) { wpa_printf(MSG_DEBUG, "FT: Failed to parse IEs"); - return -1; + goto fail; } mdie = (struct rsn_mdie *) parse.mdie; @@ -1045,7 +1056,7 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, os_memcmp(mdie->mobility_domain, sm->mobility_domain, MOBILITY_DOMAIN_ID_LEN) != 0) { wpa_printf(MSG_DEBUG, "FT: Invalid MDIE"); - return -1; + goto fail; } if (sm->key_mgmt == WPA_KEY_MGMT_FT_SAE_EXT_KEY && @@ -1063,7 +1074,7 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, wpa_printf(MSG_DEBUG, "FT: Invalid FTE (fte_mic_len=%zu mic_len=%zu)", parse.fte_mic_len, mic_len); - return -1; + goto fail; } if (os_memcmp(parse.fte_snonce, sm->snonce, WPA_NONCE_LEN) != 0) { @@ -1072,7 +1083,7 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, parse.fte_snonce, WPA_NONCE_LEN); wpa_hexdump(MSG_DEBUG, "FT: Expected SNonce", sm->snonce, WPA_NONCE_LEN); - return -1; + goto fail; } if (os_memcmp(parse.fte_anonce, sm->anonce, WPA_NONCE_LEN) != 0) { @@ -1081,12 +1092,12 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, parse.fte_anonce, WPA_NONCE_LEN); wpa_hexdump(MSG_DEBUG, "FT: Expected ANonce", sm->anonce, WPA_NONCE_LEN); - return -1; + goto fail; } if (parse.r0kh_id == NULL) { wpa_printf(MSG_DEBUG, "FT: No R0KH-ID subelem in FTIE"); - return -1; + goto fail; } if (parse.r0kh_id_len != sm->r0kh_id_len || @@ -1098,18 +1109,18 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, parse.r0kh_id, parse.r0kh_id_len); wpa_hexdump(MSG_DEBUG, "FT: The current R0KH-ID", sm->r0kh_id, sm->r0kh_id_len); - return -1; + goto fail; } if (parse.r1kh_id == NULL) { wpa_printf(MSG_DEBUG, "FT: No R1KH-ID subelem in FTIE"); - return -1; + goto fail; } if (os_memcmp_const(parse.r1kh_id, sm->r1kh_id, FT_R1KH_ID_LEN) != 0) { wpa_printf(MSG_DEBUG, "FT: Unknown R1KH-ID used in " "ReassocResp"); - return -1; + goto fail; } if (parse.rsn_pmkid == NULL || @@ -1117,7 +1128,7 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, { wpa_printf(MSG_DEBUG, "FT: No matching PMKR1Name (PMKID) in " "RSNIE (pmkid=%d)", !!parse.rsn_pmkid); - return -1; + goto fail; } count = 3; @@ -1129,7 +1140,7 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, wpa_printf(MSG_DEBUG, "FT: Unexpected IE count in MIC " "Control: received %u expected %u", parse.fte_elem_count, count); - return -1; + goto fail; } if (wpa_key_mgmt_fils(sm->key_mgmt)) { @@ -1150,7 +1161,7 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, NULL, mic) < 0) { wpa_printf(MSG_DEBUG, "FT: Failed to calculate MIC"); - return -1; + goto fail; } if (os_memcmp_const(mic, parse.fte_mic, mic_len) != 0) { @@ -1158,13 +1169,13 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, wpa_hexdump(MSG_MSGDUMP, "FT: Received MIC", parse.fte_mic, mic_len); wpa_hexdump(MSG_MSGDUMP, "FT: Calculated MIC", mic, mic_len); - return -1; + goto fail; } if (parse.fte_rsnxe_used && !sm->ap_rsnxe) { wpa_printf(MSG_INFO, "FT: FTE indicated that AP uses RSNXE, but RSNXE was not included in Beacon/Probe Response frames"); - return -1; + goto fail; } if (!sm->ap_rsn_ie) { @@ -1173,7 +1184,7 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, if (wpa_sm_get_beacon_ie(sm) < 0) { wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "FT: Could not find AP from the scan results"); - return -1; + goto fail; } wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: Found the current AP from updated scan results"); @@ -1191,7 +1202,7 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, "RSNE in FT protocol Reassociation Response frame", parse.rsn ? parse.rsn - 2 : NULL, parse.rsn ? parse.rsn_len + 2 : 0); - return -1; + goto fail; } own_rsnxe_used = wpa_key_mgmt_sae(sm->key_mgmt) && @@ -1211,7 +1222,7 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, "RSNXE in FT protocol Reassociation Response frame", parse.rsnxe ? parse.rsnxe - 2 : NULL, parse.rsnxe ? parse.rsnxe_len + 2 : 0); - return -1; + goto fail; } #ifdef CONFIG_OCV @@ -1221,7 +1232,7 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, if (wpa_sm_channel_info(sm, &ci) != 0) { wpa_printf(MSG_WARNING, "Failed to get channel info to validate received OCI in (Re)Assoc Response"); - return -1; + goto fail; } if (ocv_verify_tx_params(parse.oci, parse.oci_len, &ci, @@ -1230,7 +1241,7 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, wpa_msg(sm->ctx->msg_ctx, MSG_INFO, OCV_FAILURE "addr=" MACSTR " frame=ft-assoc error=%s", MAC2STR(src_addr), ocv_errorstr); - return -1; + goto fail; } } #endif /* CONFIG_OCV */ @@ -1240,13 +1251,13 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, if (wpa_ft_process_gtk_subelem(sm, parse.gtk, parse.gtk_len) < 0 || wpa_ft_process_igtk_subelem(sm, parse.igtk, parse.igtk_len) < 0 || wpa_ft_process_bigtk_subelem(sm, parse.bigtk, parse.bigtk_len) < 0) - return -1; + goto fail; if (sm->set_ptk_after_assoc) { wpa_printf(MSG_DEBUG, "FT: Try to set PTK again now that we " "are associated"); if (wpa_ft_install_ptk(sm, src_addr) < 0) - return -1; + goto fail; sm->set_ptk_after_assoc = 0; } @@ -1259,7 +1270,10 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, wpa_printf(MSG_DEBUG, "FT: Completed successfully"); - return 0; + ret = 0; +fail: + wpa_ft_parse_ies_free(&parse); + return ret; } diff --git a/wlantest/rx_mgmt.c b/wlantest/rx_mgmt.c index 461679e5e..137ff89b2 100644 --- a/wlantest/rx_mgmt.c +++ b/wlantest/rx_mgmt.c @@ -537,11 +537,11 @@ static void process_ft_auth(struct wlantest *wt, struct wlantest_bss *bss, if (trans == 1) { sta->key_mgmt = parse.key_mgmt; sta->pairwise_cipher = parse.pairwise_cipher; - return; + goto out; } if (trans != 2) - return; + goto out; /* TODO: Should find the latest updated PMK-R0 value here instead * copying the one from the first found matching old STA entry. */ @@ -553,7 +553,7 @@ static void process_ft_auth(struct wlantest *wt, struct wlantest_bss *bss, break; } if (!old_sta) - return; + goto out; os_memcpy(sta->pmk_r0, old_sta->pmk_r0, old_sta->pmk_r0_len); sta->pmk_r0_len = old_sta->pmk_r0_len; @@ -566,7 +566,7 @@ static void process_ft_auth(struct wlantest *wt, struct wlantest_bss *bss, if (wpa_derive_pmk_r1(sta->pmk_r0, sta->pmk_r0_len, sta->pmk_r0_name, bss->r1kh_id, sta->addr, sta->pmk_r1, sta->pmk_r1_name) < 0) - return; + goto out; sta->pmk_r1_len = sta->pmk_r0_len; if (!parse.fte_anonce || !parse.fte_snonce || @@ -574,9 +574,11 @@ static void process_ft_auth(struct wlantest *wt, struct wlantest_bss *bss, parse.fte_anonce, sta->addr, bss->bssid, sta->pmk_r1_name, &ptk, ptk_name, sta->key_mgmt, sta->pairwise_cipher, 0) < 0) - return; + goto out; sta_new_ptk(wt, sta, &ptk); +out: + wpa_ft_parse_ies_free(&parse); } @@ -1143,6 +1145,7 @@ static void rx_mgmt_assoc_resp(struct wlantest *wt, const u8 *data, size_t len) } if (parse.r1kh_id) os_memcpy(bss->r1kh_id, parse.r1kh_id, FT_R1KH_ID_LEN); + wpa_ft_parse_ies_free(&parse); } if (elems.owe_dh && elems.owe_dh_len >= 2) { @@ -1310,12 +1313,12 @@ static void rx_mgmt_reassoc_req(struct wlantest *wt, const u8 *data, if (!parse.rsn) { add_note(wt, MSG_INFO, "FT: No RSNE in Reassoc Req"); - return; + goto out; } if (!parse.rsn_pmkid) { add_note(wt, MSG_INFO, "FT: No PMKID in RSNE"); - return; + goto out; } if (os_memcmp_const(parse.rsn_pmkid, sta->pmk_r1_name, @@ -1328,7 +1331,7 @@ static void rx_mgmt_reassoc_req(struct wlantest *wt, const u8 *data, wpa_hexdump(MSG_DEBUG, "FT: Previously derived PMKR1Name", sta->pmk_r1_name, WPA_PMK_NAME_LEN); - return; + goto out; } mde = (struct rsn_mdie *) parse.mdie; @@ -1344,7 +1347,7 @@ static void rx_mgmt_reassoc_req(struct wlantest *wt, const u8 *data, fte = (struct rsn_ftie_sha384 *) parse.ftie; if (!fte || parse.ftie_len < sizeof(*fte)) { add_note(wt, MSG_INFO, "FT: Invalid FTE"); - return; + goto out; } anonce = fte->anonce; @@ -1357,7 +1360,7 @@ static void rx_mgmt_reassoc_req(struct wlantest *wt, const u8 *data, fte = (struct rsn_ftie *) parse.ftie; if (!fte || parse.ftie_len < sizeof(*fte)) { add_note(wt, MSG_INFO, "FT: Invalid FTIE"); - return; + goto out; } anonce = fte->anonce; @@ -1372,7 +1375,7 @@ static void rx_mgmt_reassoc_req(struct wlantest *wt, const u8 *data, snonce, WPA_NONCE_LEN); wpa_hexdump(MSG_DEBUG, "FT: Expected SNonce", sta->snonce, WPA_NONCE_LEN); - return; + goto out; } if (os_memcmp(anonce, sta->anonce, WPA_NONCE_LEN) != 0) { @@ -1381,19 +1384,19 @@ static void rx_mgmt_reassoc_req(struct wlantest *wt, const u8 *data, anonce, WPA_NONCE_LEN); wpa_hexdump(MSG_DEBUG, "FT: Expected ANonce", sta->anonce, WPA_NONCE_LEN); - return; + goto out; } if (!parse.r0kh_id) { add_note(wt, MSG_INFO, "FT: No R0KH-ID subelem in FTE"); - return; + goto out; } os_memcpy(bss->r0kh_id, parse.r0kh_id, parse.r0kh_id_len); bss->r0kh_id_len = parse.r0kh_id_len; if (!parse.r1kh_id) { add_note(wt, MSG_INFO, "FT: No R1KH-ID subelem in FTE"); - return; + goto out; } os_memcpy(bss->r1kh_id, parse.r1kh_id, FT_R1KH_ID_LEN); @@ -1404,7 +1407,7 @@ static void rx_mgmt_reassoc_req(struct wlantest *wt, const u8 *data, add_note(wt, MSG_INFO, "FT: No matching PMKR1Name (PMKID) in RSNE (pmkid=%d)", !!parse.rsn_pmkid); - return; + goto out; } count = 3; @@ -1416,7 +1419,7 @@ static void rx_mgmt_reassoc_req(struct wlantest *wt, const u8 *data, add_note(wt, MSG_INFO, "FT: Unexpected IE count in MIC Control: received %u expected %u", fte_elem_count, count); - return; + goto out; } if (wpa_key_mgmt_fils(sta->key_mgmt)) { @@ -1432,7 +1435,7 @@ static void rx_mgmt_reassoc_req(struct wlantest *wt, const u8 *data, extra = wpabuf_alloc(MAX_NUM_MLO_LINKS * ETH_ALEN); if (!extra) - return; + goto out; for (i = 0; i < MAX_NUM_MLO_LINKS; i++) { if (!is_zero_ether_addr(sta->link_addr[i])) wpabuf_put_data(extra, @@ -1453,7 +1456,7 @@ static void rx_mgmt_reassoc_req(struct wlantest *wt, const u8 *data, mic) < 0) { wpabuf_free(extra); add_note(wt, MSG_INFO, "FT: Failed to calculate MIC"); - return; + goto out; } wpabuf_free(extra); @@ -1486,10 +1489,12 @@ static void rx_mgmt_reassoc_req(struct wlantest *wt, const u8 *data, link_id, MAC2STR(sta->link_addr[link_id])); } - return; + goto out; } add_note(wt, MSG_INFO, "FT: Valid FTE MIC"); + out: + wpa_ft_parse_ies_free(&parse); } } @@ -1839,12 +1844,12 @@ static void rx_mgmt_reassoc_resp(struct wlantest *wt, const u8 *data, if (!parse.rsn) { add_note(wt, MSG_INFO, "FT: No RSNE in Reassoc Resp"); - return; + goto out; } if (!parse.rsn_pmkid) { add_note(wt, MSG_INFO, "FT: No PMKID in RSNE"); - return; + goto out; } if (os_memcmp_const(parse.rsn_pmkid, sta->pmk_r1_name, @@ -1857,7 +1862,7 @@ static void rx_mgmt_reassoc_resp(struct wlantest *wt, const u8 *data, wpa_hexdump(MSG_DEBUG, "FT: Previously derived PMKR1Name", sta->pmk_r1_name, WPA_PMK_NAME_LEN); - return; + goto out; } mde = (struct rsn_mdie *) parse.mdie; @@ -1873,7 +1878,7 @@ static void rx_mgmt_reassoc_resp(struct wlantest *wt, const u8 *data, fte = (struct rsn_ftie_sha384 *) parse.ftie; if (!fte || parse.ftie_len < sizeof(*fte)) { add_note(wt, MSG_INFO, "FT: Invalid FTE"); - return; + goto out; } anonce = fte->anonce; @@ -1886,7 +1891,7 @@ static void rx_mgmt_reassoc_resp(struct wlantest *wt, const u8 *data, fte = (struct rsn_ftie *) parse.ftie; if (!fte || parse.ftie_len < sizeof(*fte)) { add_note(wt, MSG_INFO, "FT: Invalid FTIE"); - return; + goto out; } anonce = fte->anonce; @@ -1901,7 +1906,7 @@ static void rx_mgmt_reassoc_resp(struct wlantest *wt, const u8 *data, snonce, WPA_NONCE_LEN); wpa_hexdump(MSG_DEBUG, "FT: Expected SNonce", sta->snonce, WPA_NONCE_LEN); - return; + goto out; } if (os_memcmp(anonce, sta->anonce, WPA_NONCE_LEN) != 0) { @@ -1910,12 +1915,12 @@ static void rx_mgmt_reassoc_resp(struct wlantest *wt, const u8 *data, anonce, WPA_NONCE_LEN); wpa_hexdump(MSG_DEBUG, "FT: Expected ANonce", sta->anonce, WPA_NONCE_LEN); - return; + goto out; } if (!parse.r0kh_id) { add_note(wt, MSG_INFO, "FT: No R0KH-ID subelem in FTE"); - return; + goto out; } if (parse.r0kh_id_len != bss->r0kh_id_len || @@ -1934,7 +1939,7 @@ static void rx_mgmt_reassoc_resp(struct wlantest *wt, const u8 *data, if (!parse.r1kh_id) { add_note(wt, MSG_INFO, "FT: No R1KH-ID subelem in FTE"); - return; + goto out; } if (os_memcmp_const(parse.r1kh_id, bss->r1kh_id, @@ -1953,7 +1958,7 @@ static void rx_mgmt_reassoc_resp(struct wlantest *wt, const u8 *data, add_note(wt, MSG_INFO, "FT: Unexpected IE count in MIC Control: received %u expected %u", fte_elem_count, count); - return; + goto out; } if (wpa_key_mgmt_fils(sta->key_mgmt)) { @@ -1978,7 +1983,7 @@ static void rx_mgmt_reassoc_resp(struct wlantest *wt, const u8 *data, NULL, mic) < 0) { add_note(wt, MSG_INFO, "FT: Failed to calculate MIC"); - return; + goto out; } if (os_memcmp_const(mic, fte_mic, mic_len) != 0) { @@ -2000,7 +2005,7 @@ static void rx_mgmt_reassoc_resp(struct wlantest *wt, const u8 *data, wpa_hexdump(MSG_MSGDUMP, "FT: RSNXE", parse.rsnxe ? parse.rsnxe - 2 : NULL, parse.rsnxe ? parse.rsnxe_len + 2 : 0); - return; + goto out; } add_note(wt, MSG_INFO, "FT: Valid FTE MIC"); @@ -2024,6 +2029,9 @@ static void rx_mgmt_reassoc_resp(struct wlantest *wt, const u8 *data, parse.igtk, parse.igtk_len); process_bigtk_subelem(wt, bss, sta, kek, kek_len, parse.bigtk, parse.bigtk_len); + + out: + wpa_ft_parse_ies_free(&parse); } if (elems.owe_dh && elems.owe_dh_len >= 2) { @@ -2165,18 +2173,20 @@ static void rx_mgmt_action_ft_request(struct wlantest *wt, bss = bss_get(wt, aa); if (!bss) { add_note(wt, MSG_INFO, "No BSS entry for Target AP"); - return; + goto out; } sta = sta_find_mlo(wt, bss, spa); if (!sta) sta = sta_get(bss, spa); if (!sta) - return; + goto out; sta->ft_over_ds = true; sta->key_mgmt = parse.key_mgmt; sta->pairwise_cipher = parse.pairwise_cipher; +out: + wpa_ft_parse_ies_free(&parse); } @@ -2227,7 +2237,7 @@ static void rx_mgmt_action_ft_response(struct wlantest *wt, if (!bss) { add_note(wt, MSG_INFO, "No BSS entry for Target AP"); - return; + goto out; } if (parse.r1kh_id) @@ -2236,14 +2246,14 @@ static void rx_mgmt_action_ft_response(struct wlantest *wt, if (wpa_derive_pmk_r1(sta->pmk_r0, sta->pmk_r0_len, sta->pmk_r0_name, bss->r1kh_id, spa, sta->pmk_r1, sta->pmk_r1_name) < 0) - return; + goto out; sta->pmk_r1_len = sta->pmk_r0_len; new_sta = sta_find_mlo(wt, bss, spa); if (!new_sta) new_sta = sta_get(bss, spa); if (!new_sta) - return; + goto out; os_memcpy(new_sta->pmk_r0, sta->pmk_r0, sta->pmk_r0_len); new_sta->pmk_r0_len = sta->pmk_r0_len; os_memcpy(new_sta->pmk_r0_name, sta->pmk_r0_name, @@ -2258,11 +2268,13 @@ static void rx_mgmt_action_ft_response(struct wlantest *wt, sta->pmk_r1_name, &ptk, ptk_name, new_sta->key_mgmt, new_sta->pairwise_cipher, 0) < 0) - return; + goto out; sta_new_ptk(wt, new_sta, &ptk); os_memcpy(new_sta->snonce, parse.fte_snonce, WPA_NONCE_LEN); os_memcpy(new_sta->anonce, parse.fte_anonce, WPA_NONCE_LEN); +out: + wpa_ft_parse_ies_free(&parse); }