[PATCH 1/1] hostapd: Support 4way handshake offload for AP/P2P GO

Vinayak Yadawad vinayak.yadawad at broadcom.com
Wed Nov 8 04:56:09 PST 2023


This patch adds support for AP/P2P GO 4way HS support.
For drivers supporting the AP PSK offload, supplicant/hostapd
would pass down the PSK for driver to handle 4way handshake.
The driver is expected to indicate PORT authorized event to
indicate that the 4way handshake is completed successfully.

Signed-off-by: Vinayak Yadawad <vinayak.yadawad at broadcom.com>
---
 src/ap/beacon.c                    | 13 ++++++++++++-
 src/ap/drv_callbacks.c             | 10 ++++++++++
 src/ap/hostapd.c                   |  7 ++++++-
 src/drivers/driver.h               | 14 +++++++++++++-
 src/drivers/driver_nl80211.c       |  5 +++++
 src/drivers/driver_nl80211_capa.c  |  5 +++++
 src/drivers/driver_nl80211_event.c |  9 ++++++++-
 wpa_supplicant/ap.c                |  1 +
 wpa_supplicant/events.c            | 16 +++++++++++++++-
 9 files changed, 75 insertions(+), 5 deletions(-)

diff --git a/src/ap/beacon.c b/src/ap/beacon.c
index b88aeb03c..9a311c5d3 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -32,7 +32,7 @@
 #include "dfs.h"
 #include "taxonomy.h"
 #include "ieee802_11_auth.h"
-
+#include "crypto/sha1.h"
 
 #ifdef NEED_AP_MLME
 
@@ -2026,6 +2026,17 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
 	resp = hostapd_probe_resp_offloads(hapd, &resp_len);
 #endif /* NEED_AP_MLME */
 
+	/* If key mgmt offload is enabled, configure PSK  */
+	if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) &&
+	    (hapd->iface->drv_flags2 & WPA_DRIVER_FLAGS2_4WAY_HANDSHAKE_AP_PSK)) {
+		if (hapd->conf->ssid.wpa_psk && hapd->conf->ssid.wpa_psk_set) {
+			os_memcpy(params->psk, hapd->conf->ssid.wpa_psk->psk, PMK_LEN);
+		} else if (hapd->conf->ssid.wpa_passphrase) {
+			pbkdf2_sha1(hapd->conf->ssid.wpa_passphrase, hapd->conf->ssid.ssid,
+				hapd->conf->ssid.ssid_len, 4096, params->psk, PMK_LEN);
+		}
+	}
+
 	params->head = (u8 *) head;
 	params->head_len = head_len;
 	params->tail = tail;
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index bc575e260..2cd7b5a58 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -2186,6 +2186,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
 			  union wpa_event_data *data)
 {
 	struct hostapd_data *hapd = ctx;
+	struct sta_info *sta = NULL;
 #ifndef CONFIG_NO_STDOUT_DEBUG
 	int level = MSG_DEBUG;
 
@@ -2305,6 +2306,15 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
 				    data->assoc_info.link_addr,
 				    data->assoc_info.reassoc);
 		break;
+	case EVENT_PORT_AUTHORIZED:
+		/* Port auth event from associated STA */
+		sta = ap_get_sta(hapd, data->port_authorized.sta_addr);
+		if (sta)
+			ap_sta_set_authorized(hapd, sta, 1);
+		else
+			wpa_printf(MSG_DEBUG, "sta info not found");
+		break;
+
 #ifdef CONFIG_OWE
 	case EVENT_UPDATE_DH:
 		if (!data)
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 966030d57..7b5050f32 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -3573,8 +3573,13 @@ void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
 		    sta->auth_alg != WLAN_AUTH_FILS_PK &&
 		    !(sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS)))
 			wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH);
-	} else
+	} else if (!(hapd->iface->drv_flags2 &
+	    WPA_DRIVER_FLAGS2_4WAY_HANDSHAKE_AP_PSK)) {
+		/* 4way HS offloaded STA will have this handled from port auth
+		 * event
+		 */
 		wpa_auth_sta_associated(hapd->wpa_auth, sta->wpa_sm);
+	}
 
 	if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_WIRED) {
 		if (eloop_cancel_timeout(ap_handle_timer, hapd, sta) > 0) {
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 24016b344..c5ffe44a1 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -1809,6 +1809,11 @@ struct wpa_driver_ap_params {
 	 * mld_link_id - Link id for MLD BSS's
 	 */
 	u8 mld_link_id;
+
+	/**
+	 * psk - PSK passed to driver for 4-way HS offload
+	 */
+	u8 psk[PMK_LEN];
 };
 
 struct wpa_driver_mesh_bss_params {
@@ -2281,6 +2286,8 @@ struct wpa_driver_capa {
 #define WPA_DRIVER_FLAGS2_SCAN_MIN_PREQ         0x0000000000008000ULL
 /** Driver supports SAE authentication offload in STA mode */
 #define WPA_DRIVER_FLAGS2_SAE_OFFLOAD_STA	0x0000000000010000ULL
+/** Driver support AP_PSK authentication offload */
+#define WPA_DRIVER_FLAGS2_4WAY_HANDSHAKE_AP_PSK	0x0000000000020000ULL
 	u64 flags2;
 
 #define FULL_AP_CLIENT_STATE_SUPP(drv_flags) \
@@ -6668,11 +6675,16 @@ union wpa_event_data {
 	struct pasn_auth pasn_auth;
 
 	/**
-	 * struct port_authorized - Data for EVENT_PORT_AUTHORIZED
+	 * struct port_authorized - Data for EVENT_PORT_AUTHORIZED for STA or AP
+	 * to indicate that port is authorized and open for data.
+	 * td_bitmap, td_bitmap_len: STA event would indicate td_bitmap if peer AP
+	 * notifies the same in EAPOL 3/4.
+	 * sta_addr: For AP, this would be the associated STA's macaddr.
 	 */
 	struct port_authorized {
 		const u8 *td_bitmap;
 		size_t td_bitmap_len;
+		u8 sta_addr[ETH_ALEN];
 	} port_authorized;
 
 	/**
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 8b72d74c5..b7b123d24 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -5110,6 +5110,11 @@ static int wpa_driver_nl80211_set_ap(void *priv,
 			 suites))
 		goto fail;
 
+	if ((params->key_mgmt_suites & WPA_KEY_MGMT_PSK) &&
+	    (drv->capa.flags & WPA_DRIVER_FLAGS2_4WAY_HANDSHAKE_AP_PSK) &&
+	    (nla_put(msg, NL80211_ATTR_PMK, 32, params->psk)))
+		goto fail;
+
 	if (params->key_mgmt_suites & WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
 	    (!params->pairwise_ciphers ||
 	     params->pairwise_ciphers & (WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40)) &&
diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
index b7d914140..6faeaa5f3 100644
--- a/src/drivers/driver_nl80211_capa.c
+++ b/src/drivers/driver_nl80211_capa.c
@@ -705,6 +705,11 @@ static void wiphy_info_ext_feature_flags(struct wiphy_info_data *info,
 	if (ext_feature_isset(ext_features, len,
 			      NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT))
 		capa->flags2 |= WPA_DRIVER_FLAGS2_SCAN_MIN_PREQ;
+
+	if (ext_feature_isset(ext_features, len,
+			      NL80211_EXT_FEATURE_4WAY_HANDSHAKE_AP_PSK))
+		capa->flags2 |= WPA_DRIVER_FLAGS2_4WAY_HANDSHAKE_AP_PSK;
+
 }
 
 
diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
index 0297bffeb..1c56b81fd 100644
--- a/src/drivers/driver_nl80211_event.c
+++ b/src/drivers/driver_nl80211_event.c
@@ -3506,7 +3506,14 @@ static void nl80211_port_authorized(struct wpa_driver_nl80211_data *drv,
 	}
 
 	addr = nla_data(tb[NL80211_ATTR_MAC]);
-	if (os_memcmp(addr, drv->bssid, ETH_ALEN) != 0) {
+	if (is_ap_interface(drv->nlmode) && drv->device_ap_sme) {
+		/* Update STA assoc address */
+		os_memcpy(event.port_authorized.sta_addr, addr, ETH_ALEN);
+		wpa_printf(MSG_DEBUG,
+			"nl80211: Port authorized for STA addr "  MACSTR,
+			MAC2STR(addr));
+	} else if (is_sta_interface(drv->nlmode) &&
+	    os_memcmp(addr, drv->bssid, ETH_ALEN) != 0) {
 		wpa_printf(MSG_DEBUG,
 			   "nl80211: Ignore port authorized event for " MACSTR
 			   " (not the currently connected BSSID " MACSTR ")",
diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
index 2fc9f453b..b6e666a7d 100644
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -1058,6 +1058,7 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s,
 		return -1;
 	hapd_iface->owner = wpa_s;
 	hapd_iface->drv_flags = wpa_s->drv_flags;
+	hapd_iface->drv_flags2 = wpa_s->drv_flags2;
 	hapd_iface->probe_resp_offloads = wpa_s->probe_resp_offloads;
 	hapd_iface->extended_capa = wpa_s->extended_capa;
 	hapd_iface->extended_capa_mask = wpa_s->extended_capa_mask;
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 1f186eb67..63f6a4730 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -22,6 +22,7 @@
 #include "common/wpa_ctrl.h"
 #include "eap_peer/eap.h"
 #include "ap/hostapd.h"
+#include "ap/sta_info.h"
 #include "p2p/p2p.h"
 #include "fst/fst.h"
 #include "wnm_sta.h"
@@ -6416,7 +6417,20 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
 				wpa_s, data->port_authorized.td_bitmap[0]);
 		}
 #endif /* CONFIG_NO_WPA */
-		wpa_supplicant_event_port_authorized(wpa_s);
+		if (wpa_s->ap_iface && wpa_s->ap_iface->bss[0]) {
+			/* ap/p2p_go authorizing sta/p2p_gc */
+			struct sta_info *sta = NULL;
+
+			sta = ap_get_sta(wpa_s->ap_iface->bss[0],
+				data->port_authorized.sta_addr);
+			if (sta)
+				ap_sta_set_authorized(wpa_s->ap_iface->bss[0], sta, 1);
+			else
+				wpa_printf(MSG_ERROR, "sta info not found");
+		} else {
+			/* sta/p2p gc port authorized event handling */
+			wpa_supplicant_event_port_authorized(wpa_s);
+		}
 		break;
 	case EVENT_STATION_OPMODE_CHANGED:
 #ifdef CONFIG_AP
-- 
2.32.0

-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 4218 bytes
Desc: S/MIME Cryptographic Signature
URL: <http://lists.infradead.org/pipermail/hostap/attachments/20231108/3f003ece/attachment.p7s>


More information about the Hostap mailing list