From 086ccdc598a0a3fecec77751a5d4147b4ce98e5e Mon Sep 17 00:00:00 2001 From: Vinay Gannevaram Date: Sun, 18 Sep 2022 19:13:45 +0530 Subject: [PATCH] PASN: Remove wpa_s dependency for the functions processing RX frames Remove wpa_s dependency for processing PASN M2 frame and preparing M3 frame. To hold the context of wpa_s when transmitting M3 frame, add cb ctx. Signed-off-by: Jouni Malinen --- wpa_supplicant/pasn_supplicant.c | 128 ++++++++++++++++++------------ wpa_supplicant/wpa_supplicant_i.h | 1 + 2 files changed, 78 insertions(+), 51 deletions(-) diff --git a/wpa_supplicant/pasn_supplicant.c b/wpa_supplicant/pasn_supplicant.c index cad5b0469..c0731382b 100644 --- a/wpa_supplicant/pasn_supplicant.c +++ b/wpa_supplicant/pasn_supplicant.c @@ -839,10 +839,8 @@ static int wpas_pasn_wd_fils_rx(struct wpas_pasn *pasn, struct wpabuf *wd) #endif /* CONFIG_FILS */ -static struct wpabuf * wpas_pasn_get_wrapped_data(struct wpa_supplicant *wpa_s) +static struct wpabuf * wpas_pasn_get_wrapped_data(struct wpas_pasn *pasn) { - struct wpas_pasn *pasn = &wpa_s->pasn; - if (pasn->using_pmksa) return NULL; @@ -974,7 +972,7 @@ static struct wpabuf * wpas_pasn_build_auth_1(struct wpa_supplicant *wpa_s, * Note: Even when PMKSA is available, also add wrapped data as * it is possible that the PMKID is no longer valid at the AP. */ - wrapped_data_buf = wpas_pasn_get_wrapped_data(wpa_s); + wrapped_data_buf = wpas_pasn_get_wrapped_data(pasn); } if (wpa_pasn_add_rsne(buf, pmkid, pasn->akmp, pasn->cipher) < 0) @@ -1025,9 +1023,8 @@ fail: } -static struct wpabuf * wpas_pasn_build_auth_3(struct wpa_supplicant *wpa_s) +static struct wpabuf * wpas_pasn_build_auth_3(struct wpas_pasn *pasn) { - struct wpas_pasn *pasn = &wpa_s->pasn; struct wpabuf *buf, *wrapped_data_buf = NULL; u8 mic[WPA_PASN_MAX_MIC_LEN]; u8 mic_len, data_len; @@ -1051,7 +1048,7 @@ static struct wpabuf * wpas_pasn_build_auth_3(struct wpa_supplicant *wpa_s) pasn->own_addr, pasn->bssid, pasn->trans_seq + 1, WLAN_STATUS_SUCCESS); - wrapped_data_buf = wpas_pasn_get_wrapped_data(wpa_s); + wrapped_data_buf = wpas_pasn_get_wrapped_data(pasn); if (!wrapped_data_buf) wrapped_data = WPA_PASN_WRAPPED_DATA_NO; @@ -1164,13 +1161,12 @@ static void wpas_pasn_reset(struct wpa_supplicant *wpa_s) } -static int wpas_pasn_set_pmk(struct wpa_supplicant *wpa_s, +static int wpas_pasn_set_pmk(struct wpas_pasn *pasn, struct wpa_ie_data *rsn_data, struct wpa_pasn_params_data *pasn_data, struct wpabuf *wrapped_data) { static const u8 pasn_default_pmk[] = {'P', 'M', 'K', 'z'}; - struct wpas_pasn *pasn = &wpa_s->pasn; os_memset(pasn->pmk, 0, sizeof(pasn->pmk)); pasn->pmk_len = 0; @@ -1200,9 +1196,8 @@ static int wpas_pasn_set_pmk(struct wpa_supplicant *wpa_s, if (rsn_data->num_pmkid) { struct rsn_pmksa_cache_entry *pmksa; - pmksa = wpa_sm_pmksa_cache_get(wpa_s->wpa, pasn->bssid, - rsn_data->pmkid, NULL, - pasn->akmp); + pmksa = pmksa_cache_get(pasn->pmksa, pasn->bssid, + rsn_data->pmkid, NULL, pasn->akmp); if (pmksa) { wpa_printf(MSG_DEBUG, "PASN: Using PMKSA"); @@ -1659,13 +1654,14 @@ static void wpas_pasn_deauth_cb(struct ptksa_cache_entry *entry) } -int wpas_pasn_auth_rx(struct wpa_supplicant *wpa_s, - const struct ieee80211_mgmt *mgmt, size_t len) +static int wpa_pasn_auth_rx(struct wpas_pasn *pasn, const u8 *data, size_t len, + struct wpa_pasn_params_data *pasn_params) + { - struct wpas_pasn *pasn = &wpa_s->pasn; struct ieee802_11_elems elems; struct wpa_ie_data rsn_data; - struct wpa_pasn_params_data pasn_params; + const struct ieee80211_mgmt *mgmt = + (const struct ieee80211_mgmt *) data; struct wpabuf *wrapped_data = NULL, *secret = NULL, *frame = NULL; u8 mic[WPA_PASN_MAX_MIC_LEN], out_mic[WPA_PASN_MAX_MIC_LEN]; u8 mic_len; @@ -1674,7 +1670,7 @@ int wpas_pasn_auth_rx(struct wpa_supplicant *wpa_s, u16 fc = host_to_le16((WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_AUTH << 4)); - if (!wpa_s->pasn_auth_work || !mgmt || + if (!mgmt || len < offsetof(struct ieee80211_mgmt, u.auth.variable)) return -2; @@ -1698,7 +1694,7 @@ int wpas_pasn_auth_rx(struct wpa_supplicant *wpa_s, "PASN: RX: Invalid transaction sequence: (%u != %u)", le_to_host16(mgmt->u.auth.auth_transaction), pasn->trans_seq + 1); - return -1; + return -3; } status = le_to_host16(mgmt->u.auth.status_code); @@ -1741,9 +1737,14 @@ int wpas_pasn_auth_rx(struct wpa_supplicant *wpa_s, goto fail; } + if (!pasn_params) { + wpa_printf(MSG_DEBUG, "PASN: pasn_params == NULL"); + goto fail; + } + ret = wpa_pasn_parse_parameter_ie(elems.pasn_params - 3, elems.pasn_params_len + 3, - true, &pasn_params); + true, pasn_params); if (ret) { wpa_printf(MSG_DEBUG, "PASN: Failed validation PASN of Parameters IE"); @@ -1754,19 +1755,19 @@ int wpas_pasn_auth_rx(struct wpa_supplicant *wpa_s, wpa_printf(MSG_DEBUG, "PASN: Authentication temporarily rejected"); - if (pasn_params.comeback && pasn_params.comeback_len) { + if (pasn_params->comeback && pasn_params->comeback_len) { wpa_printf(MSG_DEBUG, "PASN: Comeback token available. After=%u", - pasn_params.after); + pasn_params->after); - if (!pasn_params.after) - return wpas_pasn_immediate_retry(wpa_s, pasn, - &pasn_params); + if (!pasn_params->after) + return 1; pasn->comeback = wpabuf_alloc_copy( - pasn_params.comeback, pasn_params.comeback_len); + pasn_params->comeback, + pasn_params->comeback_len); if (pasn->comeback) - pasn->comeback_after = pasn_params.after; + pasn->comeback_after = pasn_params->after; } pasn->status = status; @@ -1792,38 +1793,38 @@ int wpas_pasn_auth_rx(struct wpa_supplicant *wpa_s, goto fail; } - if (pasn->group != pasn_params.group) { + if (pasn->group != pasn_params->group) { wpa_printf(MSG_DEBUG, "PASN: Mismatch in group"); goto fail; } - if (!pasn_params.pubkey || !pasn_params.pubkey_len) { + if (!pasn_params->pubkey || !pasn_params->pubkey_len) { wpa_printf(MSG_DEBUG, "PASN: Invalid public key"); goto fail; } - if (pasn_params.pubkey[0] == WPA_PASN_PUBKEY_UNCOMPRESSED) { + if (pasn_params->pubkey[0] == WPA_PASN_PUBKEY_UNCOMPRESSED) { inc_y = 1; - } else if (pasn_params.pubkey[0] == WPA_PASN_PUBKEY_COMPRESSED_0 || - pasn_params.pubkey[0] == WPA_PASN_PUBKEY_COMPRESSED_1) { + } else if (pasn_params->pubkey[0] == WPA_PASN_PUBKEY_COMPRESSED_0 || + pasn_params->pubkey[0] == WPA_PASN_PUBKEY_COMPRESSED_1) { inc_y = 0; } else { wpa_printf(MSG_DEBUG, "PASN: Invalid first octet in pubkey=0x%x", - pasn_params.pubkey[0]); + pasn_params->pubkey[0]); goto fail; } secret = crypto_ecdh_set_peerkey(pasn->ecdh, inc_y, - pasn_params.pubkey + 1, - pasn_params.pubkey_len - 1); + pasn_params->pubkey + 1, + pasn_params->pubkey_len - 1); if (!secret) { wpa_printf(MSG_DEBUG, "PASN: Failed to derive shared secret"); goto fail; } - if (pasn_params.wrapped_data_format != WPA_PASN_WRAPPED_DATA_NO) { + if (pasn_params->wrapped_data_format != WPA_PASN_WRAPPED_DATA_NO) { wrapped_data = ieee802_11_defrag(&elems, WLAN_EID_EXTENSION, WLAN_EID_EXT_WRAPPED_DATA); @@ -1834,7 +1835,7 @@ int wpas_pasn_auth_rx(struct wpa_supplicant *wpa_s, } } - ret = wpas_pasn_set_pmk(wpa_s, &rsn_data, &pasn_params, wrapped_data); + ret = wpas_pasn_set_pmk(pasn, &rsn_data, pasn_params, wrapped_data); if (ret) { wpa_printf(MSG_DEBUG, "PASN: Failed to set PMK"); goto fail; @@ -1883,13 +1884,14 @@ int wpas_pasn_auth_rx(struct wpa_supplicant *wpa_s, wpa_printf(MSG_DEBUG, "PASN: Success verifying Authentication frame"); - frame = wpas_pasn_build_auth_3(wpa_s); + frame = wpas_pasn_build_auth_3(pasn); if (!frame) { wpa_printf(MSG_DEBUG, "PASN: Failed building 3rd auth frame"); goto fail; } - ret = wpa_drv_send_mlme(wpa_s, wpabuf_head(frame), wpabuf_len(frame), 0, + ret = wpa_drv_send_mlme(pasn->cb_ctx, + wpabuf_head(frame), wpabuf_len(frame), 0, pasn->freq, 100); wpabuf_free(frame); if (ret) { @@ -1899,18 +1901,8 @@ int wpas_pasn_auth_rx(struct wpa_supplicant *wpa_s, wpa_printf(MSG_DEBUG, "PASN: Success sending last frame. Store PTK"); - ptksa_cache_add(wpa_s->ptksa, pasn->own_addr, pasn->bssid, - pasn->cipher, dot11RSNAConfigPMKLifetime, &pasn->ptk, - wpa_s->pasn_params ? wpas_pasn_deauth_cb : NULL, - wpa_s->pasn_params ? wpa_s : NULL); - - forced_memzero(&pasn->ptk, sizeof(pasn->ptk)); - pasn->status = WLAN_STATUS_SUCCESS; - if (pasn->pmksa_entry) - wpa_sm_set_cur_pmksa(wpa_s->wpa, pasn->pmksa_entry); - return 0; fail: wpa_printf(MSG_DEBUG, "PASN: Failed RX processing - terminating"); @@ -1927,13 +1919,47 @@ fail: else pasn->status = status; - wpas_pasn_auth_stop(wpa_s); - - wpas_pasn_auth_work_done(wpa_s, PASN_STATUS_FAILURE); return -1; } +int wpas_pasn_auth_rx(struct wpa_supplicant *wpa_s, + const struct ieee80211_mgmt *mgmt, size_t len) +{ + struct wpas_pasn *pasn = &wpa_s->pasn; + struct wpa_pasn_params_data pasn_data; + int ret; + + if (!wpa_s->pasn_auth_work) + return -2; + + pasn->cb_ctx = wpa_s; + ret = wpa_pasn_auth_rx(pasn, (const u8 *) mgmt, len, &pasn_data); + if (ret == 0) { + ptksa_cache_add(wpa_s->ptksa, pasn->own_addr, pasn->bssid, + pasn->cipher, dot11RSNAConfigPMKLifetime, + &pasn->ptk, + wpa_s->pasn_params ? wpas_pasn_deauth_cb : NULL, + wpa_s->pasn_params ? wpa_s : NULL); + + if (pasn->pmksa_entry) + wpa_sm_set_cur_pmksa(wpa_s->wpa, pasn->pmksa_entry); + } + + forced_memzero(&pasn->ptk, sizeof(pasn->ptk)); + + if (ret == -1) { + wpas_pasn_auth_stop(wpa_s); + wpas_pasn_auth_work_done(wpa_s, PASN_STATUS_FAILURE); + } + + if (ret == 1) + ret = wpas_pasn_immediate_retry(wpa_s, pasn, &pasn_data); + + return ret; +} + + void wpas_pasn_auth_trigger(struct wpa_supplicant *wpa_s, struct pasn_auth *pasn_auth) { diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index ad3539ab7..a7cdc930e 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -598,6 +598,7 @@ struct wpas_pasn { #ifdef CONFIG_TESTING_OPTIONS int corrupt_mic; #endif /* CONFIG_TESTING_OPTIONS */ + void *cb_ctx; }; #endif /* CONFIG_PASN */