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 <quic_jouni@quicinc.com>
This commit is contained in:
Vinay Gannevaram 2022-09-18 19:13:45 +05:30 committed by Jouni Malinen
parent e2e87b90bf
commit 086ccdc598
2 changed files with 78 additions and 51 deletions

View file

@ -839,10 +839,8 @@ static int wpas_pasn_wd_fils_rx(struct wpas_pasn *pasn, struct wpabuf *wd)
#endif /* CONFIG_FILS */ #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) if (pasn->using_pmksa)
return NULL; 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 * Note: Even when PMKSA is available, also add wrapped data as
* it is possible that the PMKID is no longer valid at the AP. * 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) 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; struct wpabuf *buf, *wrapped_data_buf = NULL;
u8 mic[WPA_PASN_MAX_MIC_LEN]; u8 mic[WPA_PASN_MAX_MIC_LEN];
u8 mic_len, data_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->own_addr, pasn->bssid,
pasn->trans_seq + 1, WLAN_STATUS_SUCCESS); 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) if (!wrapped_data_buf)
wrapped_data = WPA_PASN_WRAPPED_DATA_NO; 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_ie_data *rsn_data,
struct wpa_pasn_params_data *pasn_data, struct wpa_pasn_params_data *pasn_data,
struct wpabuf *wrapped_data) struct wpabuf *wrapped_data)
{ {
static const u8 pasn_default_pmk[] = {'P', 'M', 'K', 'z'}; 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)); os_memset(pasn->pmk, 0, sizeof(pasn->pmk));
pasn->pmk_len = 0; pasn->pmk_len = 0;
@ -1200,9 +1196,8 @@ static int wpas_pasn_set_pmk(struct wpa_supplicant *wpa_s,
if (rsn_data->num_pmkid) { if (rsn_data->num_pmkid) {
struct rsn_pmksa_cache_entry *pmksa; struct rsn_pmksa_cache_entry *pmksa;
pmksa = wpa_sm_pmksa_cache_get(wpa_s->wpa, pasn->bssid, pmksa = pmksa_cache_get(pasn->pmksa, pasn->bssid,
rsn_data->pmkid, NULL, rsn_data->pmkid, NULL, pasn->akmp);
pasn->akmp);
if (pmksa) { if (pmksa) {
wpa_printf(MSG_DEBUG, "PASN: Using 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, static int wpa_pasn_auth_rx(struct wpas_pasn *pasn, const u8 *data, size_t len,
const struct ieee80211_mgmt *mgmt, size_t len) struct wpa_pasn_params_data *pasn_params)
{ {
struct wpas_pasn *pasn = &wpa_s->pasn;
struct ieee802_11_elems elems; struct ieee802_11_elems elems;
struct wpa_ie_data rsn_data; 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; 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[WPA_PASN_MAX_MIC_LEN], out_mic[WPA_PASN_MAX_MIC_LEN];
u8 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) | u16 fc = host_to_le16((WLAN_FC_TYPE_MGMT << 2) |
(WLAN_FC_STYPE_AUTH << 4)); (WLAN_FC_STYPE_AUTH << 4));
if (!wpa_s->pasn_auth_work || !mgmt || if (!mgmt ||
len < offsetof(struct ieee80211_mgmt, u.auth.variable)) len < offsetof(struct ieee80211_mgmt, u.auth.variable))
return -2; return -2;
@ -1698,7 +1694,7 @@ int wpas_pasn_auth_rx(struct wpa_supplicant *wpa_s,
"PASN: RX: Invalid transaction sequence: (%u != %u)", "PASN: RX: Invalid transaction sequence: (%u != %u)",
le_to_host16(mgmt->u.auth.auth_transaction), le_to_host16(mgmt->u.auth.auth_transaction),
pasn->trans_seq + 1); pasn->trans_seq + 1);
return -1; return -3;
} }
status = le_to_host16(mgmt->u.auth.status_code); 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; 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, ret = wpa_pasn_parse_parameter_ie(elems.pasn_params - 3,
elems.pasn_params_len + 3, elems.pasn_params_len + 3,
true, &pasn_params); true, pasn_params);
if (ret) { if (ret) {
wpa_printf(MSG_DEBUG, wpa_printf(MSG_DEBUG,
"PASN: Failed validation PASN of Parameters IE"); "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, wpa_printf(MSG_DEBUG,
"PASN: Authentication temporarily rejected"); "PASN: Authentication temporarily rejected");
if (pasn_params.comeback && pasn_params.comeback_len) { if (pasn_params->comeback && pasn_params->comeback_len) {
wpa_printf(MSG_DEBUG, wpa_printf(MSG_DEBUG,
"PASN: Comeback token available. After=%u", "PASN: Comeback token available. After=%u",
pasn_params.after); pasn_params->after);
if (!pasn_params.after) if (!pasn_params->after)
return wpas_pasn_immediate_retry(wpa_s, pasn, return 1;
&pasn_params);
pasn->comeback = wpabuf_alloc_copy( pasn->comeback = wpabuf_alloc_copy(
pasn_params.comeback, pasn_params.comeback_len); pasn_params->comeback,
pasn_params->comeback_len);
if (pasn->comeback) if (pasn->comeback)
pasn->comeback_after = pasn_params.after; pasn->comeback_after = pasn_params->after;
} }
pasn->status = status; pasn->status = status;
@ -1792,38 +1793,38 @@ int wpas_pasn_auth_rx(struct wpa_supplicant *wpa_s,
goto fail; goto fail;
} }
if (pasn->group != pasn_params.group) { if (pasn->group != pasn_params->group) {
wpa_printf(MSG_DEBUG, "PASN: Mismatch in group"); wpa_printf(MSG_DEBUG, "PASN: Mismatch in group");
goto fail; 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"); wpa_printf(MSG_DEBUG, "PASN: Invalid public key");
goto fail; goto fail;
} }
if (pasn_params.pubkey[0] == WPA_PASN_PUBKEY_UNCOMPRESSED) { if (pasn_params->pubkey[0] == WPA_PASN_PUBKEY_UNCOMPRESSED) {
inc_y = 1; inc_y = 1;
} else if (pasn_params.pubkey[0] == WPA_PASN_PUBKEY_COMPRESSED_0 || } else if (pasn_params->pubkey[0] == WPA_PASN_PUBKEY_COMPRESSED_0 ||
pasn_params.pubkey[0] == WPA_PASN_PUBKEY_COMPRESSED_1) { pasn_params->pubkey[0] == WPA_PASN_PUBKEY_COMPRESSED_1) {
inc_y = 0; inc_y = 0;
} else { } else {
wpa_printf(MSG_DEBUG, wpa_printf(MSG_DEBUG,
"PASN: Invalid first octet in pubkey=0x%x", "PASN: Invalid first octet in pubkey=0x%x",
pasn_params.pubkey[0]); pasn_params->pubkey[0]);
goto fail; goto fail;
} }
secret = crypto_ecdh_set_peerkey(pasn->ecdh, inc_y, secret = crypto_ecdh_set_peerkey(pasn->ecdh, inc_y,
pasn_params.pubkey + 1, pasn_params->pubkey + 1,
pasn_params.pubkey_len - 1); pasn_params->pubkey_len - 1);
if (!secret) { if (!secret) {
wpa_printf(MSG_DEBUG, "PASN: Failed to derive shared secret"); wpa_printf(MSG_DEBUG, "PASN: Failed to derive shared secret");
goto fail; 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, wrapped_data = ieee802_11_defrag(&elems,
WLAN_EID_EXTENSION, WLAN_EID_EXTENSION,
WLAN_EID_EXT_WRAPPED_DATA); 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) { if (ret) {
wpa_printf(MSG_DEBUG, "PASN: Failed to set PMK"); wpa_printf(MSG_DEBUG, "PASN: Failed to set PMK");
goto fail; 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"); 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) { if (!frame) {
wpa_printf(MSG_DEBUG, "PASN: Failed building 3rd auth frame"); wpa_printf(MSG_DEBUG, "PASN: Failed building 3rd auth frame");
goto fail; 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); pasn->freq, 100);
wpabuf_free(frame); wpabuf_free(frame);
if (ret) { 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"); 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; pasn->status = WLAN_STATUS_SUCCESS;
if (pasn->pmksa_entry)
wpa_sm_set_cur_pmksa(wpa_s->wpa, pasn->pmksa_entry);
return 0; return 0;
fail: fail:
wpa_printf(MSG_DEBUG, "PASN: Failed RX processing - terminating"); wpa_printf(MSG_DEBUG, "PASN: Failed RX processing - terminating");
@ -1927,13 +1919,47 @@ fail:
else else
pasn->status = status; pasn->status = status;
wpas_pasn_auth_stop(wpa_s);
wpas_pasn_auth_work_done(wpa_s, PASN_STATUS_FAILURE);
return -1; 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, void wpas_pasn_auth_trigger(struct wpa_supplicant *wpa_s,
struct pasn_auth *pasn_auth) struct pasn_auth *pasn_auth)
{ {

View file

@ -598,6 +598,7 @@ struct wpas_pasn {
#ifdef CONFIG_TESTING_OPTIONS #ifdef CONFIG_TESTING_OPTIONS
int corrupt_mic; int corrupt_mic;
#endif /* CONFIG_TESTING_OPTIONS */ #endif /* CONFIG_TESTING_OPTIONS */
void *cb_ctx;
}; };
#endif /* CONFIG_PASN */ #endif /* CONFIG_PASN */