From: Peddolla Harshavardhan Reddy Date: Sat, 14 Jun 2025 08:17:14 +0000 (+0530) Subject: PASN: Support comeback data X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9345b2c65d07ec2535cf57788e45795a06904bce;p=thirdparty%2Fhostap.git PASN: Support comeback data Allow PASN Authentication with a comeback request after the AP's requested comeback time, as indicated in the status report of the PASN handshake. Also enable the comeback mechanism by including comeback time and cookie in the status report to extend PASN Authentication with comeback. Signed-off-by: Peddolla Harshavardhan Reddy --- diff --git a/src/drivers/driver.h b/src/drivers/driver.h index f4d6e4289..0a0532353 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -3056,6 +3056,11 @@ enum pasn_status { * @temporary_network: Indicates if a temporary network was created to perform * PASN authentication. * @password: Password of user requested network. + * @comeback_len: Length of the comeback cookie data. + * @comeback: Comeback cookie data that may be present in case a temporary + * rejection is received from the AP. + * @comeback_after: The time after which the STA can try for PASN handshake in + * case of temporary rejection. * @ltf_keyseed_required: Indicates whether LTF keyseed generation is required * @status: PASN response status, %PASN_STATUS_SUCCESS for successful * authentication, use %PASN_STATUS_FAILURE if PASN authentication @@ -3071,6 +3076,9 @@ struct pasn_peer { int group; bool temporary_network; char *password; + size_t comeback_len; + u8 *comeback; + u16 comeback_after; bool ltf_keyseed_required; enum pasn_status status; }; diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index ce86b72c4..0cc5b4b0e 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -13673,6 +13673,17 @@ static int nl80211_send_pasn_resp(void *priv, struct pasn_auth *params) wpa_cipher_to_cipher_suite(cipher))) goto fail; + if (params->peer[i].comeback_after && + params->peer[i].comeback_len && + params->peer[i].comeback && + (nla_put_u16(msg, + QCA_WLAN_VENDOR_ATTR_PASN_PEER_COMEBACK_AFTER, + params->peer[i].comeback_after) || + nla_put(msg, QCA_WLAN_VENDOR_ATTR_PASN_PEER_COOKIE, + params->peer[i].comeback_len, + params->peer[i].comeback))) + goto fail; + wpa_printf(MSG_DEBUG, "nl80211: Own address[%u]: " MACSTR " Peer address[%u]: " MACSTR diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c index 3bba2af8c..bcf6ff895 100644 --- a/src/drivers/driver_nl80211_event.c +++ b/src/drivers/driver_nl80211_event.c @@ -3415,6 +3415,12 @@ static void qca_nl80211_pasn_auth(struct i802_bss *bss, u8 *data, size_t len) os_memcpy(pw[idx], password, password_len); event.pasn_auth.peer[idx].password = pw[idx]; } + if (cfg[QCA_WLAN_VENDOR_ATTR_PASN_PEER_COOKIE]) { + event.pasn_auth.peer[idx].comeback_len = + nla_len(cfg[QCA_WLAN_VENDOR_ATTR_PASN_PEER_COOKIE]); + event.pasn_auth.peer[idx].comeback = + nla_data(cfg[QCA_WLAN_VENDOR_ATTR_PASN_PEER_COOKIE]); + } wpa_printf(MSG_DEBUG, "nl80211: PASN auth action: peer addr " MACSTR " AKMP 0x%x cipher 0x%x", diff --git a/wpa_supplicant/pasn_supplicant.c b/wpa_supplicant/pasn_supplicant.c index 89a8f17e7..0158aadf1 100644 --- a/wpa_supplicant/pasn_supplicant.c +++ b/wpa_supplicant/pasn_supplicant.c @@ -390,8 +390,6 @@ static void wpas_pasn_configure_next_peer(struct wpa_supplicant *wpa_s, struct pasn_auth *pasn_params) { struct pasn_peer *peer; - u8 comeback_len = 0; - const u8 *comeback = NULL; struct wpa_ssid *ssid; if (!pasn_params) @@ -456,7 +454,7 @@ static void wpas_pasn_configure_next_peer(struct wpa_supplicant *wpa_s, peer->peer_addr, peer->akmp, peer->cipher, peer->group, peer->network_id, - comeback, comeback_len)) { + peer->comeback, peer->comeback_len)) { peer->status = PASN_STATUS_FAILURE; wpa_msg(wpa_s, MSG_INFO, PASN_AUTH_STATUS MACSTR " akmp=%s, status=%u", @@ -465,7 +463,9 @@ static void wpas_pasn_configure_next_peer(struct wpa_supplicant *wpa_s, peer->status); wpa_s->pasn_count++; str_clear_free(peer->password); + os_free(peer->comeback); peer->password = NULL; + peer->comeback = NULL; continue; } wpa_printf(MSG_DEBUG, "PASN: Sent PASN auth start for " MACSTR, @@ -481,6 +481,7 @@ static void wpas_pasn_configure_next_peer(struct wpa_supplicant *wpa_s, for (i = 0; i < pasn_params->num_peers; i++) { peer = &pasn_params->peer[i]; str_clear_free(peer->password); + os_free(peer->comeback); if (peer->temporary_network) { ssid = wpa_config_get_network(wpa_s->conf, @@ -910,6 +911,33 @@ static void wpas_pasn_deauth_cb(struct ptksa_cache_entry *entry) } +static void wpas_pasn_store_comeback_data(struct wpa_supplicant *wpa_s, + const struct wpabuf *comeback, + u16 comeback_after) +{ + struct pasn_peer *peer; + + if (!wpa_s->pasn_params) + return; + + peer = &wpa_s->pasn_params->peer[wpa_s->pasn_count]; + if (!peer) + return; + + os_free(peer->comeback); + peer->comeback = os_zalloc(wpabuf_len(comeback)); + if (!peer->comeback) { + wpa_printf(MSG_ERROR, + "PASN: Mem alloc failed for comeback data"); + return; + } + + peer->comeback_len = wpabuf_len(comeback); + os_memcpy(peer->comeback, wpabuf_head_u8(comeback), peer->comeback_len); + peer->comeback_after = comeback_after; +} + + int wpas_pasn_auth_rx(struct wpa_supplicant *wpa_s, const struct ieee80211_mgmt *mgmt, size_t len) { @@ -941,6 +969,10 @@ int wpas_pasn_auth_rx(struct wpa_supplicant *wpa_s, forced_memzero(pasn_get_ptk(pasn), sizeof(pasn->ptk)); if (ret == -1) { + if (pasn->status == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY && + pasn->comeback && wpabuf_len(pasn->comeback)) + wpas_pasn_store_comeback_data(wpa_s, pasn->comeback, + pasn->comeback_after); wpas_pasn_auth_stop(wpa_s); wpas_pasn_auth_work_done(wpa_s, PASN_STATUS_FAILURE); } @@ -997,6 +1029,16 @@ void wpas_pasn_auth_trigger(struct wpa_supplicant *wpa_s, return; } } + if (src->comeback_len && src->comeback) { + dst->comeback = os_memdup(src->comeback, + src->comeback_len); + if (!dst->comeback) { + wpa_printf(MSG_DEBUG, + "PASN: Mem alloc failed for comeback cookie"); + return; + } + dst->comeback_len = src->comeback_len; + } if (!is_zero_ether_addr(src->own_addr)) { os_memcpy(dst->own_addr, src->own_addr, ETH_ALEN);