[PATCH 1/1] hostapd: Add support for SAE offload for STA/AP interface

Vinayak Yadawad vinayak.yadawad at broadcom.com
Thu Oct 12 02:29:29 PDT 2023


In the current change we enable support for SAE offload by
1. Adding support of 4-way HS offload for AP interface
2. Adding support for SAE authentication offload
The changes basically involve handling of necessary parameter
plumbing to the driver in the connect path for STA interface.
Also the changes involve AP parameter plumbing in AP bringup
path and Port authorized event handling.

Signed-off-by: Vinayak Yadawad <vinayak.yadawad at broadcom.com>
---
 src/ap/beacon.c                    | 31 ++++++++++++++++++++++++++++++
 src/ap/drv_callbacks.c             |  6 ++++++
 src/ap/hostapd.c                   |  7 +++++--
 src/ap/wpa_auth_glue.c             |  6 ++++++
 src/ap/wpa_auth_glue.h             |  1 +
 src/ap/wpa_auth_ie.c               |  6 ++++--
 src/drivers/driver.h               | 24 +++++++++++++++++++++++
 src/drivers/driver_nl80211.c       | 22 +++++++++++++++++++++
 src/drivers/driver_nl80211_capa.c  | 12 ++++++++++++
 src/drivers/driver_nl80211_event.c |  9 ++++++++-
 wpa_supplicant/wpa_supplicant.c    | 15 +++++++++++++++
 11 files changed, 134 insertions(+), 5 deletions(-)

diff --git a/src/ap/beacon.c b/src/ap/beacon.c
index 1d3b96ac7..a844f4169 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -32,6 +32,7 @@
 #include "dfs.h"
 #include "taxonomy.h"
 #include "ieee802_11_auth.h"
+#include "crypto/sha1.h"
 
 
 #ifdef NEED_AP_MLME
@@ -2011,6 +2012,36 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
 	resp = hostapd_probe_resp_offloads(hapd, &resp_len);
 #endif /* NEED_AP_MLME */
 
+	/* If SAE offload is enabled, provide passphrase to lower layer for
+	 * PMK generation
+	 */
+	if ((wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt)) &&
+	    (hapd->iface->drv_flags2 & WPA_DRIVER_FLAGS2_SAE_OFFLOAD_AP)) {
+		if (hapd->conf->ssid.wpa_passphrase) {
+			params->sae_passphrase_len =
+				os_strlen(hapd->conf->ssid.wpa_passphrase);
+			if (params->sae_passphrase_len) {
+				os_memcpy(params->sae_passphrase,
+					hapd->conf->ssid.wpa_passphrase,
+					params->sae_passphrase_len);
+			}
+		}
+		if (hapd->conf->sae_pwe) {
+			params->sae_pwe = hapd->conf->sae_pwe;
+		}
+	}
+
+	/* 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 0516213f4..42419f523 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -2188,6 +2188,8 @@ 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;
 
@@ -2482,6 +2484,10 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
 		hostapd_cleanup_cca_params(hapd);
 		break;
 #endif /* CONFIG_IEEE80211AX */
+	case EVENT_PORT_AUTHORIZED:
+		sta = ap_get_sta(hapd, data->port_authorized.sta_addr);
+		ap_sta_set_authorized(hapd, sta, 1);
+		break;
 	default:
 		wpa_printf(MSG_DEBUG, "Unknown event %d", event);
 		break;
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 966030d57..961524b31 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -3573,8 +3573,11 @@ 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
-		wpa_auth_sta_associated(hapd->wpa_auth, sta->wpa_sm);
+	} else {
+		if (!(hapd->iface->drv_flags2 &
+		    WPA_DRIVER_FLAGS2_4WAY_HANDSHAKE_AP_PSK))
+			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/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c
index 30a72b126..35b56b9df 100644
--- a/src/ap/wpa_auth_glue.c
+++ b/src/ap/wpa_auth_glue.c
@@ -1757,6 +1757,12 @@ int hostapd_setup_wpa(struct hostapd_data *hapd)
 
 }
 
+bool hostapd_wpa_auth_is_sae_offload_enabled(void *ctx)
+{
+	struct hostapd_data *hapd = ctx;
+
+	return	!!(hapd->iface->drv_flags2 & WPA_DRIVER_FLAGS2_SAE_OFFLOAD_AP);
+}
 
 void hostapd_reconfig_wpa(struct hostapd_data *hapd)
 {
diff --git a/src/ap/wpa_auth_glue.h b/src/ap/wpa_auth_glue.h
index 1b13ae7be..7a7cb966b 100644
--- a/src/ap/wpa_auth_glue.h
+++ b/src/ap/wpa_auth_glue.h
@@ -12,5 +12,6 @@
 int hostapd_setup_wpa(struct hostapd_data *hapd);
 void hostapd_reconfig_wpa(struct hostapd_data *hapd);
 void hostapd_deinit_wpa(struct hostapd_data *hapd);
+bool hostapd_wpa_auth_is_sae_offload_enabled(void *ctx);
 
 #endif /* WPA_AUTH_GLUE_H */
diff --git a/src/ap/wpa_auth_ie.c b/src/ap/wpa_auth_ie.c
index 43ccec9be..3d33ac934 100644
--- a/src/ap/wpa_auth_ie.c
+++ b/src/ap/wpa_auth_ie.c
@@ -17,6 +17,7 @@
 #include "pmksa_cache_auth.h"
 #include "wpa_auth_ie.h"
 #include "wpa_auth_i.h"
+#include "wpa_auth_glue.h"
 
 
 #ifdef CONFIG_RSN_TESTING
@@ -998,8 +999,9 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
 	}
 
 #ifdef CONFIG_SAE
-	if (sm->wpa_key_mgmt == WPA_KEY_MGMT_SAE && data.num_pmkid &&
-	    !sm->pmksa) {
+	if (sm->wpa_key_mgmt == WPA_KEY_MGMT_SAE &&
+	    !(hostapd_wpa_auth_is_sae_offload_enabled(wpa_auth->cb_ctx)) &&
+	    data.num_pmkid && !sm->pmksa) {
 		wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
 				 "No PMKSA cache entry found for SAE");
 		return WPA_INVALID_PMKID;
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index dbe2ad5e4..96fe56787 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -69,6 +69,8 @@ enum hostapd_chan_width_attr {
 #define HOSTAPD_DFS_REGION_ETSI	2
 #define HOSTAPD_DFS_REGION_JP	3
 
+#define MAX_PASSPHRASE_LEN 63
+
 /**
  * enum reg_change_initiator - Regulatory change initiator
  */
@@ -1785,6 +1787,21 @@ struct wpa_driver_ap_params {
 	 * mld_link_id - Link id for MLD BSS's
 	 */
 	u8 mld_link_id;
+
+	/**
+	 * sae_passphrase - sae passphrase for SAE offload
+	 */
+	u8 sae_passphrase[MAX_PASSPHRASE_LEN];
+
+	/**
+	 * sae_passphrase_len - sae passphrase length for SAE offload
+	 */
+	u8 sae_passphrase_len;
+
+	/**
+	 * psk - PSK passed to driver for 4-way HS offload
+	 */
+	u8 psk[PMK_LEN];
 };
 
 struct wpa_driver_mesh_bss_params {
@@ -2253,6 +2270,12 @@ struct wpa_driver_capa {
 #define WPA_DRIVER_FLAGS2_PROT_RANGE_NEG_STA	0x0000000000002000ULL
 /** Driver supports MLO in station/AP mode */
 #define WPA_DRIVER_FLAGS2_MLO			0x0000000000004000ULL
+/** Driver support AP_PSK authentication offload */
+#define WPA_DRIVER_FLAGS2_4WAY_HANDSHAKE_AP_PSK	0x0000000000008000ULL
+/** Driver support SAE STA authentication offload */
+#define WPA_DRIVER_FLAGS2_SAE_OFFLOAD		0x0000000000010000ULL
+/** Driver support SAE AP authentication offload */
+#define WPA_DRIVER_FLAGS2_SAE_OFFLOAD_AP	0x0000000000020000ULL
 	u64 flags2;
 
 #define FULL_AP_CLIENT_STATE_SUPP(drv_flags) \
@@ -6645,6 +6668,7 @@ union wpa_event_data {
 	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 9bd6a58e0..817bc084f 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -5109,6 +5109,17 @@ 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 (wpa_key_mgmt_sae(params->key_mgmt_suites) &&
+	    (drv->capa.flags2 & WPA_DRIVER_FLAGS2_SAE_OFFLOAD_AP) &&
+	    (nla_put(msg, NL80211_ATTR_SAE_PASSWORD, params->sae_passphrase_len,
+	    params->sae_passphrase)))
+		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)) &&
@@ -6926,6 +6937,17 @@ static int nl80211_connect_common(struct wpa_driver_nl80211_data *drv,
 			return -1;
 	}
 
+	/* Add SAE passphrase in case of SAE offload */
+	if (wpa_key_mgmt_sae(params->key_mgmt_suite) &&
+	    (drv->capa.flags2 & WPA_DRIVER_FLAGS2_SAE_OFFLOAD) &&
+	    params->passphrase) {
+		wpa_hexdump_key(MSG_DEBUG, "  * SAE passphrase",
+			params->passphrase, os_strlen(params->passphrase));
+		if (nla_put(msg, NL80211_ATTR_SAE_PASSWORD,
+		    os_strlen(params->passphrase), params->passphrase))
+			return -1;
+	}
+
 	if (nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT))
 		return -1;
 
diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
index 5e6406885..c17957381 100644
--- a/src/drivers/driver_nl80211_capa.c
+++ b/src/drivers/driver_nl80211_capa.c
@@ -697,6 +697,18 @@ static void wiphy_info_ext_feature_flags(struct wiphy_info_data *info,
 		capa->flags2 |= WPA_DRIVER_FLAGS2_PROT_RANGE_NEG_STA;
 		capa->flags2 |= WPA_DRIVER_FLAGS2_PROT_RANGE_NEG_AP;
 	}
+
+	if (ext_feature_isset(ext_features, len,
+			      NL80211_EXT_FEATURE_4WAY_HANDSHAKE_AP_PSK))
+		capa->flags2 |= WPA_DRIVER_FLAGS2_4WAY_HANDSHAKE_AP_PSK;
+
+	if (ext_feature_isset(ext_features, len,
+			      NL80211_EXT_FEATURE_SAE_OFFLOAD_AP))
+		capa->flags2 |= WPA_DRIVER_FLAGS2_SAE_OFFLOAD_AP;
+
+	if (ext_feature_isset(ext_features, len,
+			      NL80211_EXT_FEATURE_SAE_OFFLOAD))
+		capa->flags2 |= WPA_DRIVER_FLAGS2_SAE_OFFLOAD;
 }
 
 
diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
index 9d39703e0..d1473e8f9 100644
--- a/src/drivers/driver_nl80211_event.c
+++ b/src/drivers/driver_nl80211_event.c
@@ -3505,7 +3505,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 BSSID "  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/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 69f228919..961411596 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -4269,6 +4269,21 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
 	     params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192))
 		params.req_handshake_offload = 1;
 
+	params.sae_pwe = wpa_s->conf->sae_pwe;
+	if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE) &&
+	    (wpa_key_mgmt_sae(params.key_mgmt_suite))) {
+		if (ssid->sae_password) {
+			wpa_printf(MSG_DEBUG, "sae enabled join..Using sae_password");
+			params.passphrase = ssid->sae_password;
+		} else if (ssid->passphrase) {
+			wpa_printf(MSG_DEBUG, "sae enabled join..Using passphrase");
+			params.passphrase = ssid->passphrase;
+		} else {
+			wpa_printf(MSG_ERROR, "sae enabled join.."
+				"But neither sae_password nor passphrase set");
+		}
+	}
+
 	if (wpa_s->conf->key_mgmt_offload) {
 		if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
 		    params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
-- 
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/20231012/63f0c119/attachment.p7s>


More information about the Hostap mailing list