} 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
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;
}
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;
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",
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);
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");
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);
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
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);
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);
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);
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 */
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);
*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;
}
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;
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;
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 &&
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) {
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) {
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 ||
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,
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 ||
{
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;
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)) {
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) {
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 &&
!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
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);
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;
}
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;
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)
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;
* 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;
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)
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) */
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 */
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 */
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;
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);
#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;
&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;
}
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);
sm->assoc_resp_ies, sm->assoc_resp_ies_len);
}
+ wpa_ft_parse_ies_free(&ft);
return 0;
}
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);
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;
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) {
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 ||
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 ||
{
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);
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;
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);
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 */
}
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
os_memcpy(sm->bssid, target_ap, ETH_ALEN);
}
- return 0;
+ ret = 0;
+fail:
+ wpa_ft_parse_ies_free(&parse);
+ return ret;
}
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) {
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;
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 &&
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) {
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) {
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 ||
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 ||
{
wpa_printf(MSG_DEBUG, "FT: No matching PMKR1Name (PMKID) in "
"RSNIE (pmkid=%d)", !!parse.rsn_pmkid);
- return -1;
+ goto fail;
}
count = 3;
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)) {
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) {
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) {
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");
"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) &&
"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
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,
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 */
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;
}
wpa_printf(MSG_DEBUG, "FT: Completed successfully");
- return 0;
+ ret = 0;
+fail:
+ wpa_ft_parse_ies_free(&parse);
+ return ret;
}
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. */
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;
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 ||
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);
}
}
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) {
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,
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;
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;
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;
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) {
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);
add_note(wt, MSG_INFO,
"FT: No matching PMKR1Name (PMKID) in RSNE (pmkid=%d)",
!!parse.rsn_pmkid);
- return;
+ goto out;
}
count = 3;
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)) {
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,
mic) < 0) {
wpabuf_free(extra);
add_note(wt, MSG_INFO, "FT: Failed to calculate MIC");
- return;
+ goto out;
}
wpabuf_free(extra);
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);
}
}
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,
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;
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;
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;
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) {
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 ||
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,
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)) {
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) {
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");
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) {
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);
}
if (!bss) {
add_note(wt, MSG_INFO, "No BSS entry for Target AP");
- return;
+ goto out;
}
if (parse.r1kh_id)
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,
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);
}