From 89d2f8b07c948cc5fbe8767948128f487eae2ed5 Mon Sep 17 00:00:00 2001
From: Chung-Hsien Hsu <stanley.hsu@cypress.com>
Date: Tue, 10 Dec 2019 14:05:16 -0600
Subject: [PATCH 10/49] nl80211: Support SAE authentication offload in AP mode

If driver advertises support for SAE authentication offload, pass SAE
password in NL80211_CMD_NEW_BEACON command for AP mode.

Signed-off-by: Chung-Hsien Hsu <chung-hsien.hsu@infineon.com>
---
 src/drivers/driver.h              | 12 +++++++++++-
 src/drivers/driver_nl80211.c      | 28 +++++++++++++++++++++++++++-
 src/drivers/driver_nl80211_capa.c |  4 ++++
 3 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index a42ec5e1f..45260e8c5 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -1611,6 +1611,14 @@ struct wpa_driver_ap_params {
 	 * should be prepared to handle %NULL value as an error.
 	 */
 	const u8 *psk;
+
+	/**
+	 * sae_password - Password for SAE authentication
+	 *
+	 * This value is made available only for WPA3-Personal (SAE) and only
+	 * for drivers that set WPA_DRIVER_FLAGS2_SAE_OFFLOAD_AP.
+	 */
+	const char *sae_password;
 };
 
 struct wpa_driver_mesh_bss_params {
@@ -2057,10 +2065,12 @@ struct wpa_driver_capa {
 #define WPA_DRIVER_FLAGS2_OCV			0x0000000000000080ULL
 /** Driver expects user space implementation of SME in AP mode */
 #define WPA_DRIVER_FLAGS2_AP_SME		0x0000000000000100ULL
-/** Driver supports SAE authentication offload */
+/** Driver supports SAE authentication offload in station mode */
 #define WPA_DRIVER_FLAGS2_SAE_OFFLOAD		0x0000000000000200ULL
 /** Driver supports 4-way handshake offload for WPA-Personal in AP mode */
 #define WPA_DRIVER_FLAGS2_4WAY_HANDSHAKE_AP_PSK	0x0000000000000400ULL
+/** Driver supports SAE authentication offload in AP mode */
+#define WPA_DRIVER_FLAGS2_SAE_OFFLOAD_AP	0x0000000000000800ULL
 	u64 flags2;
 
 #define FULL_AP_CLIENT_STATE_SUPP(drv_flags) \
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index f228a0715..b6afc6e7a 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -4630,8 +4630,13 @@ static int wpa_driver_nl80211_set_ap(void *priv,
 	ver = 0;
 	if (params->wpa_version & WPA_PROTO_WPA)
 		ver |= NL80211_WPA_VERSION_1;
-	if (params->wpa_version & WPA_PROTO_RSN)
+	if (params->wpa_version & WPA_PROTO_RSN) {
 		ver |= NL80211_WPA_VERSION_2;
+#ifdef CONFIG_SAE
+		if (params->key_mgmt_suites & WPA_KEY_MGMT_SAE)
+			ver |= NL80211_WPA_VERSION_3;
+#endif /* CONFIG_SAE */
+	}
 	if (ver &&
 	    nla_put_u32(msg, NL80211_ATTR_WPA_VERSIONS, ver))
 		goto fail;
@@ -4685,6 +4690,27 @@ static int wpa_driver_nl80211_set_ap(void *priv,
 			goto fail;
 	}
 
+#ifdef CONFIG_SAE
+	/* Add SAE password in case of SAE authentication offload */
+	if ((params->sae_password || params->passphrase) &&
+	    (params->key_mgmt_suites & WPA_KEY_MGMT_SAE) &&
+	    (drv->capa.flags2 & WPA_DRIVER_FLAGS2_SAE_OFFLOAD_AP)) {
+		const char *password;
+		size_t pwd_len;
+
+		if (params->sae_password)
+			password = params->sae_password;
+		else
+			password = params->passphrase;
+
+		pwd_len = os_strlen(password);
+		wpa_hexdump_ascii_key(MSG_DEBUG, "nl80211: SAE password",
+				      (u8 *) password, pwd_len);
+		if (nla_put(msg, NL80211_ATTR_SAE_PASSWORD, pwd_len, password))
+			goto fail;
+	}
+#endif /* CONFIG_SAE */
+
 	if (params->beacon_ies) {
 		wpa_hexdump_buf(MSG_DEBUG, "nl80211: beacon_ies",
 				params->beacon_ies);
diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
index dc4988c7c..ae6029a92 100644
--- a/src/drivers/driver_nl80211_capa.c
+++ b/src/drivers/driver_nl80211_capa.c
@@ -602,6 +602,10 @@ static void wiphy_info_ext_feature_flags(struct wiphy_info_data *info,
 			      NL80211_EXT_FEATURE_SAE_OFFLOAD))
 		capa->flags2 |= WPA_DRIVER_FLAGS2_SAE_OFFLOAD;
 
+	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_MFP_OPTIONAL))
 		capa->flags |= WPA_DRIVER_FLAGS_MFP_OPTIONAL;
-- 
2.17.1

