iwd.lists.linux.dev archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/3] netdev: factor out scan_bss from CMD_CONNECT builder
@ 2021-09-01 23:36 James Prestwood
  2021-09-01 23:36 ` [PATCH 2/3] wsc: set ssid in handshake James Prestwood
  2021-09-01 23:36 ` [PATCH 3/3] owe: netdev: refactor to remove OWE as an auth-proto James Prestwood
  0 siblings, 2 replies; 3+ messages in thread
From: James Prestwood @ 2021-09-01 23:36 UTC (permalink / raw)
  To: iwd

[-- Attachment #1: Type: text/plain, Size: 3767 bytes --]

In order to support OWE in the CMD_CONNECT path the scan_bss parameter
needs to be removed since this is lost after netdev_connect returns.
Nearly everything needed is also stored in the handshake except the
privacy capability which is now being mirrored in the netdev object
itself.
---
 src/netdev.c | 23 ++++++++++++-----------
 1 file changed, 12 insertions(+), 11 deletions(-)

diff --git a/src/netdev.c b/src/netdev.c
index a5d1b8ed..8592685c 100644
--- a/src/netdev.c
+++ b/src/netdev.c
@@ -181,6 +181,7 @@ struct netdev {
 	bool events_ready : 1;
 	bool retry_auth : 1;
 	bool in_reassoc : 1;
+	bool privacy : 1;
 };
 
 struct netdev_preauth_state {
@@ -788,6 +789,7 @@ static void netdev_connect_free(struct netdev *netdev)
 	netdev->ignore_connect_event = false;
 	netdev->expect_connect_failure = false;
 	netdev->cur_rssi_low = false;
+	netdev->privacy = false;
 
 	if (netdev->connect_cmd) {
 		l_genl_msg_unref(netdev->connect_cmd);
@@ -2901,7 +2903,6 @@ static void netdev_fils_tx_associate(struct iovec *fils_iov, size_t n_fils_iov,
 }
 
 static struct l_genl_msg *netdev_build_cmd_connect(struct netdev *netdev,
-						struct scan_bss *bss,
 						struct handshake_state *hs,
 						const uint8_t *prev_bssid,
 						const struct iovec *vendor_ies,
@@ -2924,10 +2925,9 @@ static struct l_genl_msg *netdev_build_cmd_connect(struct netdev *netdev,
 	msg = l_genl_msg_new_sized(NL80211_CMD_CONNECT, 512);
 	l_genl_msg_append_attr(msg, NL80211_ATTR_IFINDEX, 4, &netdev->index);
 	l_genl_msg_append_attr(msg, NL80211_ATTR_WIPHY_FREQ,
-						4, &bss->frequency);
-	l_genl_msg_append_attr(msg, NL80211_ATTR_MAC, ETH_ALEN, bss->addr);
-	l_genl_msg_append_attr(msg, NL80211_ATTR_SSID,
-						bss->ssid_len, bss->ssid);
+							4, &netdev->frequency);
+	l_genl_msg_append_attr(msg, NL80211_ATTR_MAC, ETH_ALEN, hs->aa);
+	l_genl_msg_append_attr(msg, NL80211_ATTR_SSID, hs->ssid_len, hs->ssid);
 	l_genl_msg_append_attr(msg, NL80211_ATTR_AUTH_TYPE, 4, &auth_type);
 
 	switch (nhs->type) {
@@ -2950,7 +2950,7 @@ static struct l_genl_msg *netdev_build_cmd_connect(struct netdev *netdev,
 		l_genl_msg_append_attr(msg, NL80211_ATTR_PREV_BSSID, ETH_ALEN,
 						prev_bssid);
 
-	if (bss->capability & IE_BSS_CAP_PRIVACY)
+	if (netdev->privacy)
 		l_genl_msg_append_attr(msg, NL80211_ATTR_PRIVACY, 0, NULL);
 
 	l_genl_msg_append_attr(msg, NL80211_ATTR_SOCKET_OWNER, 0, NULL);
@@ -3476,6 +3476,10 @@ static void netdev_connect_common(struct netdev *netdev,
 	bool is_rsn = hs->supplicant_ie != NULL;
 	const uint8_t *prev_bssid = prev_bss ? prev_bss->addr : NULL;
 
+	netdev->frequency = bss->frequency;
+	netdev->privacy = bss->capability & IE_BSS_CAP_PRIVACY;
+	handshake_state_set_authenticator_address(hs, bss->addr);
+
 	if (!is_rsn)
 		goto build_cmd_connect;
 
@@ -3519,8 +3523,8 @@ static void netdev_connect_common(struct netdev *netdev,
 		break;
 	default:
 build_cmd_connect:
-		cmd_connect = netdev_build_cmd_connect(netdev, bss, hs,
-					prev_bssid, vendor_ies, num_vendor_ies);
+		cmd_connect = netdev_build_cmd_connect(netdev, hs, prev_bssid,
+						vendor_ies, num_vendor_ies);
 
 		if (!is_offload(hs) && (is_rsn || hs->settings_8021x)) {
 			sm = eapol_sm_new(hs);
@@ -3536,13 +3540,10 @@ build_cmd_connect:
 	netdev->user_data = user_data;
 	netdev->handshake = hs;
 	netdev->sm = sm;
-	netdev->frequency = bss->frequency;
 	netdev->cur_rssi = bss->signal_strength / 100;
 	netdev_rssi_level_init(netdev);
 	netdev_cqm_rssi_update(netdev);
 
-	handshake_state_set_authenticator_address(hs, bss->addr);
-
 	if (!wiphy_has_ext_feature(netdev->wiphy,
 					NL80211_EXT_FEATURE_CAN_REPLACE_PTK0))
 		handshake_state_set_no_rekey(hs, true);
-- 
2.31.1

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH 2/3] wsc: set ssid in handshake
  2021-09-01 23:36 [PATCH 1/3] netdev: factor out scan_bss from CMD_CONNECT builder James Prestwood
@ 2021-09-01 23:36 ` James Prestwood
  2021-09-01 23:36 ` [PATCH 3/3] owe: netdev: refactor to remove OWE as an auth-proto James Prestwood
  1 sibling, 0 replies; 3+ messages in thread
From: James Prestwood @ 2021-09-01 23:36 UTC (permalink / raw)
  To: iwd

[-- Attachment #1: Type: text/plain, Size: 694 bytes --]

netdev now assumes the SSID was set in the handshake (normally via
network_handshake_setup) but WSC calls netdev_connect directly so
it also should set the SSID.
---
 src/wsc.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/wsc.c b/src/wsc.c
index 4ab497d4..2618497a 100644
--- a/src/wsc.c
+++ b/src/wsc.c
@@ -356,6 +356,7 @@ static int wsc_enrollee_connect(struct wsc_enrollee *wsce, struct scan_bss *bss,
 
 	handshake_state_set_event_func(hs, wsc_enrollee_handshake_event, wsce);
 	handshake_state_set_8021x_config(hs, settings);
+	handshake_state_set_ssid(hs, bss->ssid, bss->ssid_len);
 	wsce->eap_settings = settings;
 
 	request.version2 = true;
-- 
2.31.1

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH 3/3] owe: netdev: refactor to remove OWE as an auth-proto
  2021-09-01 23:36 [PATCH 1/3] netdev: factor out scan_bss from CMD_CONNECT builder James Prestwood
  2021-09-01 23:36 ` [PATCH 2/3] wsc: set ssid in handshake James Prestwood
@ 2021-09-01 23:36 ` James Prestwood
  1 sibling, 0 replies; 3+ messages in thread
From: James Prestwood @ 2021-09-01 23:36 UTC (permalink / raw)
  To: iwd

[-- Attachment #1: Type: text/plain, Size: 27369 bytes --]

---
 src/netdev.c | 550 +++++++++++++++++++++++++++------------------------
 src/netdev.h |   1 +
 src/owe.c    | 148 ++------------
 src/owe.h    |  12 +-
 4 files changed, 317 insertions(+), 394 deletions(-)

diff --git a/src/netdev.c b/src/netdev.c
index 8592685c..bf19bf7a 100644
--- a/src/netdev.c
+++ b/src/netdev.c
@@ -119,6 +119,7 @@ struct netdev {
 	void *user_data;
 	struct eapol_sm *sm;
 	struct auth_proto *ap;
+	struct owe_sm *owe_sm;
 	struct handshake_state *handshake;
 	uint32_t connect_cmd_id;
 	uint32_t disconnect_cmd_id;
@@ -752,6 +753,11 @@ static void netdev_connect_free(struct netdev *netdev)
 		netdev->ap = NULL;
 	}
 
+	if (netdev->owe_sm) {
+		owe_sm_free(netdev->owe_sm);
+		netdev->owe_sm = NULL;
+	}
+
 	eapol_preauth_cancel(netdev->index);
 
 	if (netdev->handshake) {
@@ -2094,6 +2100,228 @@ static void netdev_driver_connected(struct netdev *netdev)
 		eapol_register(netdev->sm);
 }
 
+static unsigned int ie_rsn_akm_suite_to_nl80211(enum ie_rsn_akm_suite akm)
+{
+	switch (akm) {
+	case IE_RSN_AKM_SUITE_8021X:
+		return CRYPTO_AKM_8021X;
+	case IE_RSN_AKM_SUITE_PSK:
+		return CRYPTO_AKM_PSK;
+	case IE_RSN_AKM_SUITE_FT_OVER_8021X:
+		return CRYPTO_AKM_FT_OVER_8021X;
+	case IE_RSN_AKM_SUITE_FT_USING_PSK:
+		return CRYPTO_AKM_FT_USING_PSK;
+	case IE_RSN_AKM_SUITE_8021X_SHA256:
+		return CRYPTO_AKM_8021X_SHA256;
+	case IE_RSN_AKM_SUITE_PSK_SHA256:
+		return CRYPTO_AKM_PSK_SHA256;
+	case IE_RSN_AKM_SUITE_TDLS:
+		return CRYPTO_AKM_TDLS;
+	case IE_RSN_AKM_SUITE_SAE_SHA256:
+		return CRYPTO_AKM_SAE_SHA256;
+	case IE_RSN_AKM_SUITE_FT_OVER_SAE_SHA256:
+		return CRYPTO_AKM_FT_OVER_SAE_SHA256;
+	case IE_RSN_AKM_SUITE_AP_PEER_KEY_SHA256:
+		return CRYPTO_AKM_AP_PEER_KEY_SHA256;
+	case IE_RSN_AKM_SUITE_8021X_SUITE_B_SHA256:
+		return CRYPTO_AKM_8021X_SUITE_B_SHA256;
+	case IE_RSN_AKM_SUITE_8021X_SUITE_B_SHA384:
+		return CRYPTO_AKM_8021X_SUITE_B_SHA384;
+	case IE_RSN_AKM_SUITE_FT_OVER_8021X_SHA384:
+		return CRYPTO_AKM_FT_OVER_8021X_SHA384;
+	case IE_RSN_AKM_SUITE_FILS_SHA256:
+		return CRYPTO_AKM_FILS_SHA256;
+	case IE_RSN_AKM_SUITE_FILS_SHA384:
+		return CRYPTO_AKM_FILS_SHA384;
+	case IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA256:
+		return CRYPTO_AKM_FT_OVER_FILS_SHA256;
+	case IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA384:
+		return CRYPTO_AKM_FT_OVER_FILS_SHA384;
+	case IE_RSN_AKM_SUITE_OWE:
+		return CRYPTO_AKM_OWE;
+	case IE_RSN_AKM_SUITE_OSEN:
+		return CRYPTO_AKM_OSEN;
+	}
+
+	return 0;
+}
+
+static struct l_genl_msg *netdev_build_cmd_connect(struct netdev *netdev,
+						struct handshake_state *hs,
+						const uint8_t *prev_bssid,
+						const struct iovec *vendor_ies,
+						size_t num_vendor_ies)
+{
+	struct netdev_handshake_state *nhs =
+		l_container_of(hs, struct netdev_handshake_state, super);
+	uint32_t auth_type = IE_AKM_IS_SAE(hs->akm_suite) ?
+					NL80211_AUTHTYPE_SAE :
+					NL80211_AUTHTYPE_OPEN_SYSTEM;
+	enum mpdu_management_subtype subtype = prev_bssid ?
+				MPDU_MANAGEMENT_SUBTYPE_REASSOCIATION_REQUEST :
+				MPDU_MANAGEMENT_SUBTYPE_ASSOCIATION_REQUEST;
+	struct l_genl_msg *msg;
+	struct iovec iov[64];
+	unsigned int n_iov = L_ARRAY_SIZE(iov);
+	unsigned int c_iov = 0;
+	bool is_rsn = hs->supplicant_ie != NULL;
+	uint8_t owe_dh_ie[5 + L_ECC_SCALAR_MAX_BYTES];
+	size_t dh_ie_len;
+
+	msg = l_genl_msg_new_sized(NL80211_CMD_CONNECT, 512);
+	l_genl_msg_append_attr(msg, NL80211_ATTR_IFINDEX, 4, &netdev->index);
+	l_genl_msg_append_attr(msg, NL80211_ATTR_WIPHY_FREQ,
+							4, &netdev->frequency);
+	l_genl_msg_append_attr(msg, NL80211_ATTR_MAC, ETH_ALEN, hs->aa);
+	l_genl_msg_append_attr(msg, NL80211_ATTR_SSID, hs->ssid_len, hs->ssid);
+	l_genl_msg_append_attr(msg, NL80211_ATTR_AUTH_TYPE, 4, &auth_type);
+
+	switch (nhs->type) {
+	case CONNECTION_TYPE_SOFTMAC:
+	case CONNECTION_TYPE_FULLMAC:
+		break;
+	case CONNECTION_TYPE_SAE_OFFLOAD:
+		l_genl_msg_append_attr(msg, NL80211_ATTR_SAE_PASSWORD,
+					strlen(hs->passphrase), hs->passphrase);
+		break;
+	case CONNECTION_TYPE_PSK_OFFLOAD:
+		l_genl_msg_append_attr(msg, NL80211_ATTR_PMK, 32, hs->pmk);
+		break;
+	case CONNECTION_TYPE_8021X_OFFLOAD:
+		l_genl_msg_append_attr(msg, NL80211_ATTR_WANT_1X_4WAY_HS,
+					0, NULL);
+	}
+
+	if (prev_bssid)
+		l_genl_msg_append_attr(msg, NL80211_ATTR_PREV_BSSID, ETH_ALEN,
+						prev_bssid);
+
+	if (netdev->privacy)
+		l_genl_msg_append_attr(msg, NL80211_ATTR_PRIVACY, 0, NULL);
+
+	l_genl_msg_append_attr(msg, NL80211_ATTR_SOCKET_OWNER, 0, NULL);
+
+	if (is_rsn) {
+		uint32_t nl_cipher;
+		uint32_t nl_akm;
+		uint32_t wpa_version;
+
+		if (hs->pairwise_cipher == IE_RSN_CIPHER_SUITE_CCMP)
+			nl_cipher = CRYPTO_CIPHER_CCMP;
+		else
+			nl_cipher = CRYPTO_CIPHER_TKIP;
+
+		l_genl_msg_append_attr(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE,
+					4, &nl_cipher);
+
+		if (hs->group_cipher == IE_RSN_CIPHER_SUITE_CCMP)
+			nl_cipher = CRYPTO_CIPHER_CCMP;
+		else
+			nl_cipher = CRYPTO_CIPHER_TKIP;
+
+		l_genl_msg_append_attr(msg, NL80211_ATTR_CIPHER_SUITE_GROUP,
+					4, &nl_cipher);
+
+		if (hs->mfp) {
+			uint32_t use_mfp = NL80211_MFP_REQUIRED;
+			l_genl_msg_append_attr(msg, NL80211_ATTR_USE_MFP,
+								4, &use_mfp);
+		}
+
+		nl_akm = ie_rsn_akm_suite_to_nl80211(hs->akm_suite);
+		if (nl_akm)
+			l_genl_msg_append_attr(msg, NL80211_ATTR_AKM_SUITES,
+							4, &nl_akm);
+
+		if (IE_AKM_IS_SAE(hs->akm_suite))
+			wpa_version = NL80211_WPA_VERSION_3;
+		else if (hs->wpa_ie)
+			wpa_version = NL80211_WPA_VERSION_1;
+		else
+			wpa_version = NL80211_WPA_VERSION_2;
+
+		l_genl_msg_append_attr(msg, NL80211_ATTR_WPA_VERSIONS,
+						4, &wpa_version);
+
+		l_genl_msg_append_attr(msg, NL80211_ATTR_CONTROL_PORT, 0, NULL);
+		c_iov = iov_ie_append(iov, n_iov, c_iov, hs->supplicant_ie);
+	}
+
+	if (netdev->owe_sm) {
+		owe_build_dh_ie(netdev->owe_sm, owe_dh_ie, &dh_ie_len);
+		c_iov = iov_ie_append(iov, n_iov, c_iov, owe_dh_ie);
+	}
+
+	if (netdev->pae_over_nl80211)
+		l_genl_msg_append_attr(msg,
+				NL80211_ATTR_CONTROL_PORT_OVER_NL80211,
+				0, NULL);
+
+	c_iov = iov_ie_append(iov, n_iov, c_iov, hs->mde);
+	c_iov = netdev_populate_common_ies(netdev, hs, msg, iov, n_iov, c_iov);
+
+	mpdu_sort_ies(subtype, iov, c_iov);
+
+	if (vendor_ies && !L_WARN_ON(n_iov - c_iov < num_vendor_ies)) {
+		memcpy(iov + c_iov, vendor_ies,
+					sizeof(*vendor_ies) * num_vendor_ies);
+		c_iov += num_vendor_ies;
+	}
+
+	if (c_iov)
+		l_genl_msg_append_attrv(msg, NL80211_ATTR_IE, iov, c_iov);
+
+	return msg;
+}
+
+static void netdev_cmd_connect_cb(struct l_genl_msg *msg, void *user_data)
+{
+	struct netdev *netdev = user_data;
+
+	netdev->connect_cmd_id = 0;
+
+	if (l_genl_msg_get_error(msg) >= 0) {
+		/*
+		 * connected should be false if the connect event hasn't come
+		 * in yet.  i.e. the CMD_CONNECT ack arrived first (typical).
+		 * Mark the connection as 'connected'
+		 */
+		if (!netdev->connected)
+			netdev_driver_connected(netdev);
+
+		return;
+	}
+
+	netdev_connect_failed(netdev, NETDEV_RESULT_ASSOCIATION_FAILED,
+				MMPDU_STATUS_CODE_UNSPECIFIED);
+}
+
+static bool netdev_retry_owe(struct netdev *netdev)
+{
+	struct iovec iov;
+
+	if (!owe_next_group(netdev->owe_sm))
+		return false;
+
+	iov.iov_base = netdev->handshake->vendor_ies;
+	iov.iov_len = netdev->handshake->vendor_ies_len;
+
+	netdev->connect_cmd = netdev_build_cmd_connect(netdev,
+					netdev->handshake, NULL, &iov, 1);
+
+	netdev->connect_cmd_id = l_genl_family_send(nl80211,
+						netdev->connect_cmd,
+						netdev_cmd_connect_cb, netdev,
+						NULL);
+
+	if (!netdev->connect_cmd_id)
+		return false;
+
+	netdev->connect_cmd = NULL;
+
+	return true;
+}
+
 static void netdev_connect_event(struct l_genl_msg *msg, struct netdev *netdev)
 {
 	struct l_genl_attr attr;
@@ -2162,6 +2390,14 @@ static void netdev_connect_event(struct l_genl_msg *msg, struct netdev *netdev)
 			goto error;
 	}
 
+	if (netdev->owe_sm && status_code && *status_code ==
+				MMPDU_STATUS_CODE_UNSUPP_FINITE_CYCLIC_GROUP) {
+		if (!netdev_retry_owe(netdev))
+			goto error;
+
+		return;
+	}
+
 	/* AP Rejected the authenticate / associate */
 	if (!status_code || *status_code != 0)
 		goto error;
@@ -2175,8 +2411,12 @@ process_resp_ies:
 	if (resp_ies) {
 		const uint8_t *fte = NULL;
 		const uint8_t *qos_set = NULL;
+		const uint8_t *owe_dh = NULL;
+		size_t owe_dh_len = 0;
 		size_t qos_len = 0;
 		struct ie_ft_info ft_info;
+		struct ie_rsn_info info;
+		bool owe_akm_found = false;
 
 		ie_tlv_iter_init(&iter, resp_ies, resp_ies_len);
 
@@ -2203,9 +2443,58 @@ process_resp_ies:
 					data - 3,
 					ie_tlv_iter_get_length(&iter) + 3);
 				break;
+			case IE_TYPE_OWE_DH_PARAM:
+				if (!netdev->owe_sm)
+					continue;
+
+				owe_dh = data;
+				owe_dh_len = len;
+
+				break;
+
+			case IE_TYPE_RSN:
+				if (!netdev->owe_sm)
+					continue;
+
+				if (ie_parse_rsne(&iter, &info) < 0) {
+					l_error("could not parse RSN IE");
+					goto error;
+				}
+
+				/*
+				 * RFC 8110 Section 4.2
+				 * An AP agreeing to do OWE MUST include the OWE AKM in
+				 * the RSN element portion of the 802.11 association
+				 * response.
+				 */
+				if (info.akm_suites != IE_RSN_AKM_SUITE_OWE) {
+					l_error("OWE AKM not included");
+					goto error;
+				}
+
+				owe_akm_found = true;
+
+				break;
 			}
 		}
 
+		if (netdev->owe_sm) {
+			if (!owe_dh || !owe_akm_found) {
+				l_error("OWE DH element/RSN not found");
+				goto error;
+			}
+
+			if (owe_process_dh_ie(netdev->owe_sm, owe_dh,
+						owe_dh_len) != 0)
+				goto error;
+
+			owe_sm_free(netdev->owe_sm);
+			netdev->owe_sm = NULL;
+
+			netdev->sm = eapol_sm_new(netdev->handshake);
+			eapol_register(netdev->sm);
+		}
+
 		/* FILS handles its own FT key derivation */
 		if (fte && !(netdev->handshake->akm_suite &
 				(IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA256 |
@@ -2271,52 +2560,6 @@ deauth:
 							netdev, NULL);
 }
 
-static unsigned int ie_rsn_akm_suite_to_nl80211(enum ie_rsn_akm_suite akm)
-{
-	switch (akm) {
-	case IE_RSN_AKM_SUITE_8021X:
-		return CRYPTO_AKM_8021X;
-	case IE_RSN_AKM_SUITE_PSK:
-		return CRYPTO_AKM_PSK;
-	case IE_RSN_AKM_SUITE_FT_OVER_8021X:
-		return CRYPTO_AKM_FT_OVER_8021X;
-	case IE_RSN_AKM_SUITE_FT_USING_PSK:
-		return CRYPTO_AKM_FT_USING_PSK;
-	case IE_RSN_AKM_SUITE_8021X_SHA256:
-		return CRYPTO_AKM_8021X_SHA256;
-	case IE_RSN_AKM_SUITE_PSK_SHA256:
-		return CRYPTO_AKM_PSK_SHA256;
-	case IE_RSN_AKM_SUITE_TDLS:
-		return CRYPTO_AKM_TDLS;
-	case IE_RSN_AKM_SUITE_SAE_SHA256:
-		return CRYPTO_AKM_SAE_SHA256;
-	case IE_RSN_AKM_SUITE_FT_OVER_SAE_SHA256:
-		return CRYPTO_AKM_FT_OVER_SAE_SHA256;
-	case IE_RSN_AKM_SUITE_AP_PEER_KEY_SHA256:
-		return CRYPTO_AKM_AP_PEER_KEY_SHA256;
-	case IE_RSN_AKM_SUITE_8021X_SUITE_B_SHA256:
-		return CRYPTO_AKM_8021X_SUITE_B_SHA256;
-	case IE_RSN_AKM_SUITE_8021X_SUITE_B_SHA384:
-		return CRYPTO_AKM_8021X_SUITE_B_SHA384;
-	case IE_RSN_AKM_SUITE_FT_OVER_8021X_SHA384:
-		return CRYPTO_AKM_FT_OVER_8021X_SHA384;
-	case IE_RSN_AKM_SUITE_FILS_SHA256:
-		return CRYPTO_AKM_FILS_SHA256;
-	case IE_RSN_AKM_SUITE_FILS_SHA384:
-		return CRYPTO_AKM_FILS_SHA384;
-	case IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA256:
-		return CRYPTO_AKM_FT_OVER_FILS_SHA256;
-	case IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA384:
-		return CRYPTO_AKM_FT_OVER_FILS_SHA384;
-	case IE_RSN_AKM_SUITE_OWE:
-		return CRYPTO_AKM_OWE;
-	case IE_RSN_AKM_SUITE_OSEN:
-		return CRYPTO_AKM_OSEN;
-	}
-
-	return 0;
-}
-
 static struct l_genl_msg *netdev_build_cmd_associate_common(
 							struct netdev *netdev)
 {
@@ -2602,28 +2845,6 @@ assoc_failed:
 	netdev->expect_connect_failure = true;
 }
 
-static void netdev_cmd_connect_cb(struct l_genl_msg *msg, void *user_data)
-{
-	struct netdev *netdev = user_data;
-
-	netdev->connect_cmd_id = 0;
-
-	if (l_genl_msg_get_error(msg) >= 0) {
-		/*
-		 * connected should be false if the connect event hasn't come
-		 * in yet.  i.e. the CMD_CONNECT ack arrived first (typical).
-		 * Mark the connection as 'connected'
-		 */
-		if (!netdev->connected)
-			netdev_driver_connected(netdev);
-
-		return;
-	}
-
-	netdev_connect_failed(netdev, NETDEV_RESULT_ASSOCIATION_FAILED,
-				MMPDU_STATUS_CODE_UNSPECIFIED);
-}
-
 static struct l_genl_msg *netdev_build_cmd_authenticate(struct netdev *netdev,
 							uint32_t auth_type)
 {
@@ -2777,64 +2998,6 @@ static void netdev_sae_tx_associate(void *user_data)
 	}
 }
 
-static void netdev_owe_tx_authenticate(void *user_data)
-{
-	struct netdev *netdev = user_data;
-	struct l_genl_msg *msg;
-
-	msg = netdev_build_cmd_authenticate(netdev,
-						NL80211_AUTHTYPE_OPEN_SYSTEM);
-
-	if (!l_genl_family_send(nl80211, msg, netdev_auth_cb,
-							netdev, NULL)) {
-		l_genl_msg_unref(msg);
-		netdev_connect_failed(netdev,
-					NETDEV_RESULT_AUTHENTICATION_FAILED,
-					MMPDU_STATUS_CODE_UNSPECIFIED);
-		return;
-	}
-
-	netdev->auth_cmd = l_genl_msg_ref(msg);
-}
-
-static void netdev_owe_tx_associate(struct iovec *owe_iov, size_t n_owe_iov,
-					void *user_data)
-{
-	struct netdev *netdev = user_data;
-	struct handshake_state *hs = netdev->handshake;
-	struct l_genl_msg *msg;
-	struct iovec iov[64];
-	unsigned int n_iov = L_ARRAY_SIZE(iov);
-	unsigned int c_iov = 0;
-	enum mpdu_management_subtype subtype =
-				MPDU_MANAGEMENT_SUBTYPE_ASSOCIATION_REQUEST;
-
-	msg = netdev_build_cmd_associate_common(netdev);
-
-	c_iov = netdev_populate_common_ies(netdev, hs, msg, iov, n_iov, c_iov);
-
-	if (!L_WARN_ON(n_iov - c_iov < n_owe_iov)) {
-		memcpy(iov + c_iov, owe_iov, sizeof(*owe_iov) * n_owe_iov);
-		c_iov += n_owe_iov;
-	}
-
-	mpdu_sort_ies(subtype, iov, c_iov);
-
-	l_genl_msg_append_attrv(msg, NL80211_ATTR_IE, iov, c_iov);
-
-	/* If doing a non-FT Reassociation */
-	if (netdev->in_reassoc)
-		l_genl_msg_append_attr(msg, NL80211_ATTR_PREV_BSSID, 6,
-					netdev->ap->prev_bssid);
-
-	if (!l_genl_family_send(nl80211, msg, netdev_assoc_cb,
-							netdev, NULL)) {
-		l_genl_msg_unref(msg);
-		netdev_connect_failed(netdev, NETDEV_RESULT_ASSOCIATION_FAILED,
-					MMPDU_STATUS_CODE_UNSPECIFIED);
-	}
-}
-
 static void netdev_fils_tx_authenticate(const uint8_t *body,
 					size_t body_len,
 					void *user_data)
@@ -2902,127 +3065,6 @@ static void netdev_fils_tx_associate(struct iovec *fils_iov, size_t n_fils_iov,
 	}
 }
 
-static struct l_genl_msg *netdev_build_cmd_connect(struct netdev *netdev,
-						struct handshake_state *hs,
-						const uint8_t *prev_bssid,
-						const struct iovec *vendor_ies,
-						size_t num_vendor_ies)
-{
-	struct netdev_handshake_state *nhs =
-		l_container_of(hs, struct netdev_handshake_state, super);
-	uint32_t auth_type = IE_AKM_IS_SAE(hs->akm_suite) ?
-					NL80211_AUTHTYPE_SAE :
-					NL80211_AUTHTYPE_OPEN_SYSTEM;
-	enum mpdu_management_subtype subtype = prev_bssid ?
-				MPDU_MANAGEMENT_SUBTYPE_REASSOCIATION_REQUEST :
-				MPDU_MANAGEMENT_SUBTYPE_ASSOCIATION_REQUEST;
-	struct l_genl_msg *msg;
-	struct iovec iov[64];
-	unsigned int n_iov = L_ARRAY_SIZE(iov);
-	unsigned int c_iov = 0;
-	bool is_rsn = hs->supplicant_ie != NULL;
-
-	msg = l_genl_msg_new_sized(NL80211_CMD_CONNECT, 512);
-	l_genl_msg_append_attr(msg, NL80211_ATTR_IFINDEX, 4, &netdev->index);
-	l_genl_msg_append_attr(msg, NL80211_ATTR_WIPHY_FREQ,
-							4, &netdev->frequency);
-	l_genl_msg_append_attr(msg, NL80211_ATTR_MAC, ETH_ALEN, hs->aa);
-	l_genl_msg_append_attr(msg, NL80211_ATTR_SSID, hs->ssid_len, hs->ssid);
-	l_genl_msg_append_attr(msg, NL80211_ATTR_AUTH_TYPE, 4, &auth_type);
-
-	switch (nhs->type) {
-	case CONNECTION_TYPE_SOFTMAC:
-	case CONNECTION_TYPE_FULLMAC:
-		break;
-	case CONNECTION_TYPE_SAE_OFFLOAD:
-		l_genl_msg_append_attr(msg, NL80211_ATTR_SAE_PASSWORD,
-					strlen(hs->passphrase), hs->passphrase);
-		break;
-	case CONNECTION_TYPE_PSK_OFFLOAD:
-		l_genl_msg_append_attr(msg, NL80211_ATTR_PMK, 32, hs->pmk);
-		break;
-	case CONNECTION_TYPE_8021X_OFFLOAD:
-		l_genl_msg_append_attr(msg, NL80211_ATTR_WANT_1X_4WAY_HS,
-					0, NULL);
-	}
-
-	if (prev_bssid)
-		l_genl_msg_append_attr(msg, NL80211_ATTR_PREV_BSSID, ETH_ALEN,
-						prev_bssid);
-
-	if (netdev->privacy)
-		l_genl_msg_append_attr(msg, NL80211_ATTR_PRIVACY, 0, NULL);
-
-	l_genl_msg_append_attr(msg, NL80211_ATTR_SOCKET_OWNER, 0, NULL);
-
-	if (is_rsn) {
-		uint32_t nl_cipher;
-		uint32_t nl_akm;
-		uint32_t wpa_version;
-
-		if (hs->pairwise_cipher == IE_RSN_CIPHER_SUITE_CCMP)
-			nl_cipher = CRYPTO_CIPHER_CCMP;
-		else
-			nl_cipher = CRYPTO_CIPHER_TKIP;
-
-		l_genl_msg_append_attr(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE,
-					4, &nl_cipher);
-
-		if (hs->group_cipher == IE_RSN_CIPHER_SUITE_CCMP)
-			nl_cipher = CRYPTO_CIPHER_CCMP;
-		else
-			nl_cipher = CRYPTO_CIPHER_TKIP;
-
-		l_genl_msg_append_attr(msg, NL80211_ATTR_CIPHER_SUITE_GROUP,
-					4, &nl_cipher);
-
-		if (hs->mfp) {
-			uint32_t use_mfp = NL80211_MFP_REQUIRED;
-			l_genl_msg_append_attr(msg, NL80211_ATTR_USE_MFP,
-								4, &use_mfp);
-		}
-
-		nl_akm = ie_rsn_akm_suite_to_nl80211(hs->akm_suite);
-		if (nl_akm)
-			l_genl_msg_append_attr(msg, NL80211_ATTR_AKM_SUITES,
-							4, &nl_akm);
-
-		if (IE_AKM_IS_SAE(hs->akm_suite))
-			wpa_version = NL80211_WPA_VERSION_3;
-		else if (hs->wpa_ie)
-			wpa_version = NL80211_WPA_VERSION_1;
-		else
-			wpa_version = NL80211_WPA_VERSION_2;
-
-		l_genl_msg_append_attr(msg, NL80211_ATTR_WPA_VERSIONS,
-						4, &wpa_version);
-
-		l_genl_msg_append_attr(msg, NL80211_ATTR_CONTROL_PORT, 0, NULL);
-		c_iov = iov_ie_append(iov, n_iov, c_iov, hs->supplicant_ie);
-	}
-
-	if (netdev->pae_over_nl80211)
-		l_genl_msg_append_attr(msg,
-				NL80211_ATTR_CONTROL_PORT_OVER_NL80211,
-				0, NULL);
-
-	c_iov = iov_ie_append(iov, n_iov, c_iov, hs->mde);
-	c_iov = netdev_populate_common_ies(netdev, hs, msg, iov, n_iov, c_iov);
-
-	mpdu_sort_ies(subtype, iov, c_iov);
-
-	if (vendor_ies && !L_WARN_ON(n_iov - c_iov < num_vendor_ies)) {
-		memcpy(iov + c_iov, vendor_ies,
-					sizeof(*vendor_ies) * num_vendor_ies);
-		c_iov += num_vendor_ies;
-	}
-
-	if (c_iov)
-		l_genl_msg_append_attrv(msg, NL80211_ATTR_IE, iov, c_iov);
-
-	return msg;
-}
-
 struct rtnl_data {
 	struct netdev *netdev;
 	uint8_t addr[ETH_ALEN];
@@ -3393,6 +3435,7 @@ static int netdev_handshake_state_setup_connection_type(
 	case IE_RSN_AKM_SUITE_PSK:
 	case IE_RSN_AKM_SUITE_FT_USING_PSK:
 	case IE_RSN_AKM_SUITE_PSK_SHA256:
+	case IE_RSN_AKM_SUITE_OWE:
 		if (wiphy_has_ext_feature(wiphy,
 				NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK))
 			goto psk_offload;
@@ -3425,12 +3468,11 @@ static int netdev_handshake_state_setup_connection_type(
 			goto softmac;
 
 		return -EINVAL;
-	case IE_RSN_AKM_SUITE_OWE:
 	case IE_RSN_AKM_SUITE_FILS_SHA256:
 	case IE_RSN_AKM_SUITE_FILS_SHA384:
 	case IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA256:
 	case IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA384:
-		/* FILS and OWE have no offload in any upstream driver */
+		/* FILS has no offload in any upstream driver */
 		if (softmac)
 			goto softmac;
 
@@ -3509,10 +3551,9 @@ static void netdev_connect_common(struct netdev *netdev,
 
 		break;
 	case IE_RSN_AKM_SUITE_OWE:
-		netdev->ap = owe_sm_new(hs, netdev_owe_tx_authenticate,
-						netdev_owe_tx_associate,
-						netdev);
-		break;
+		netdev->owe_sm = owe_sm_new(hs);
+
+		goto build_cmd_connect;
 	case IE_RSN_AKM_SUITE_FILS_SHA256:
 	case IE_RSN_AKM_SUITE_FILS_SHA384:
 	case IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA256:
@@ -3526,7 +3567,8 @@ build_cmd_connect:
 		cmd_connect = netdev_build_cmd_connect(netdev, hs, prev_bssid,
 						vendor_ies, num_vendor_ies);
 
-		if (!is_offload(hs) && (is_rsn || hs->settings_8021x)) {
+		if (!netdev->owe_sm && !is_offload(hs) &&
+					(is_rsn || hs->settings_8021x)) {
 			sm = eapol_sm_new(hs);
 
 			if (nhs->type == CONNECTION_TYPE_8021X_OFFLOAD)
diff --git a/src/netdev.h b/src/netdev.h
index 0094d5f9..e5698894 100644
--- a/src/netdev.h
+++ b/src/netdev.h
@@ -28,6 +28,7 @@ struct handshake_state;
 struct eapol_sm;
 struct mmpdu_header;
 struct diagnostic_station_info;
+struct owe_sm;
 
 enum netdev_result {
 	NETDEV_RESULT_OK,
diff --git a/src/owe.c b/src/owe.c
index b1eea025..eed3e266 100644
--- a/src/owe.c
+++ b/src/owe.c
@@ -34,7 +34,6 @@
 #include "src/auth-proto.h"
 
 struct owe_sm {
-	struct auth_proto ap;
 	struct handshake_state *hs;
 	const struct l_ecc_curve *curve;
 	struct l_ecc_scalar *private;
@@ -42,10 +41,6 @@ struct owe_sm {
 	uint8_t retry;
 	uint16_t group;
 	const unsigned int *ecc_groups;
-
-	owe_tx_authenticate_func_t auth_tx;
-	owe_tx_associate_func_t assoc_tx;
-	void *user_data;
 };
 
 static bool owe_reset(struct owe_sm *owe)
@@ -72,62 +67,28 @@ static bool owe_reset(struct owe_sm *owe)
 	return true;
 }
 
-static void owe_free(struct auth_proto *ap)
+void owe_sm_free(struct owe_sm *owe)
 {
-	struct owe_sm *owe = l_container_of(ap, struct owe_sm, ap);
-
 	l_ecc_scalar_free(owe->private);
 	l_ecc_point_free(owe->public_key);
 
 	l_free(owe);
 }
 
-static bool owe_start(struct auth_proto *ap)
+void owe_build_dh_ie(struct owe_sm *owe, uint8_t *buf, size_t *len_out)
 {
-	struct owe_sm *owe = l_container_of(ap, struct owe_sm, ap);
-
-	owe->auth_tx(owe->user_data);
-
-	return true;
-}
-
-static int owe_rx_authenticate(struct auth_proto *ap, const uint8_t *frame,
-				size_t frame_len)
-{
-	struct owe_sm *owe = l_container_of(ap, struct owe_sm, ap);
-
-	uint8_t buf[5 + L_ECC_SCALAR_MAX_BYTES];
-	struct iovec iov[3];
-	int iov_elems = 0;
-	size_t len;
-
-	/*
-	 * RFC 8110 Section 4.3
-	 * A client wishing to do OWE MUST indicate the OWE AKM in the RSN
-	 * element portion of the 802.11 association request ...
-	 */
-	iov[iov_elems].iov_base = owe->hs->supplicant_ie;
-	iov[iov_elems].iov_len = owe->hs->supplicant_ie[1] + 2;
-	iov_elems++;
-
 	/*
-	 * ... and MUST include a Diffie-Hellman Parameter element to its
-	 * 802.11 association request.
+	 * A client wishing to do OWE ... MUST include a Diffie-Hellman
+	 * Parameter element to its 802.11 association request.
 	 */
 	buf[0] = IE_TYPE_EXTENSION;
 	buf[2] = IE_TYPE_OWE_DH_PARAM - 256;
 	l_put_le16(owe->group, buf + 3); /* group */
-	len = l_ecc_point_get_x(owe->public_key, buf + 5,
+	*len_out = l_ecc_point_get_x(owe->public_key, buf + 5,
 					L_ECC_SCALAR_MAX_BYTES);
-	buf[1] = 3 + len; /* length */
-
-	iov[iov_elems].iov_base = (void *) buf;
-	iov[iov_elems].iov_len = buf[1] + 2;
-	iov_elems++;
+	buf[1] = 3 + *len_out; /* length */
 
-	owe->assoc_tx(iov, iov_elems, owe->user_data);
-
-	return 0;
+	*len_out += 5;
 }
 
 /*
@@ -220,7 +181,7 @@ failed:
 	return false;
 }
 
-static bool owe_retry(struct owe_sm *owe)
+bool owe_next_group(struct owe_sm *owe)
 {
 	/* retry with another group, if possible */
 	owe->retry++;
@@ -228,88 +189,23 @@ static bool owe_retry(struct owe_sm *owe)
 	if (!owe_reset(owe))
 		return false;
 
-	l_debug("OWE retrying with group %u", owe->group);
-
-	owe_rx_authenticate(&owe->ap, NULL, 0);
-
 	return true;
 }
 
-static int owe_rx_associate(struct auth_proto *ap, const uint8_t *frame,
-				size_t len)
+int owe_process_dh_ie(struct owe_sm *owe, const uint8_t *dh, size_t len)
 {
-	struct owe_sm *owe = l_container_of(ap, struct owe_sm, ap);
-
-	const struct mmpdu_header *mpdu = (const struct mmpdu_header *) frame;
-	const struct mmpdu_association_response *body = mmpdu_body(mpdu);
-	struct ie_tlv_iter iter;
-	size_t owe_dh_len = 0;
-	const uint8_t *owe_dh = NULL;
-	struct ie_rsn_info info;
-	bool akm_found = false;
-	const void *data;
-
-	if (L_LE16_TO_CPU(body->status_code) ==
-				MMPDU_STATUS_CODE_UNSUPP_FINITE_CYCLIC_GROUP) {
-		if (!owe_retry(owe))
-			goto owe_bad_status;
-
-		return -EAGAIN;
-	} else if (body->status_code)
-		goto owe_bad_status;
-
-	ie_tlv_iter_init(&iter, body->ies, (const uint8_t *) mpdu + len -
-				body->ies);
-
-	while (ie_tlv_iter_next(&iter)) {
-		uint16_t tag = ie_tlv_iter_get_tag(&iter);
-
-		data = ie_tlv_iter_get_data(&iter);
-		len = ie_tlv_iter_get_length(&iter);
-
-		switch (tag) {
-		case IE_TYPE_OWE_DH_PARAM:
-			owe_dh = data;
-			owe_dh_len = len;
-
-			break;
-		case IE_TYPE_RSN:
-			if (ie_parse_rsne(&iter, &info) < 0) {
-				l_error("could not parse RSN IE");
-				goto invalid_ies;
-			}
-
-			/*
-			 * RFC 8110 Section 4.2
-			 * An AP agreeing to do OWE MUST include the OWE AKM in
-			 * the RSN element portion of the 802.11 association
-			 * response.
-			 */
-			if (info.akm_suites != IE_RSN_AKM_SUITE_OWE) {
-				l_error("OWE AKM not included");
-				goto invalid_ies;
-			}
-
-			akm_found = true;
-
-			break;
-		default:
-			continue;
-		}
-	}
-
-	if (!owe_dh || owe_dh_len < 34 || !akm_found) {
+	if (!dh || len < 34) {
 		l_error("associate response did not include proper OWE IE's");
 		goto invalid_ies;
 	}
 
-	if (l_get_le16(owe_dh) != owe->group) {
+	if (l_get_le16(dh) != owe->group) {
 		l_error("associate response contained unsupported group %u",
-				l_get_le16(owe_dh));
+				l_get_le16(dh));
 		return -EBADMSG;
 	}
 
-	if (!owe_compute_keys(owe, owe_dh + 2, owe_dh_len - 2)) {
+	if (!owe_compute_keys(owe, dh + 2, len - 2)) {
 		l_error("could not compute OWE keys");
 		return -EBADMSG;
 	}
@@ -318,33 +214,19 @@ static int owe_rx_associate(struct auth_proto *ap, const uint8_t *frame,
 
 invalid_ies:
 	return MMPDU_STATUS_CODE_INVALID_ELEMENT;
-
-owe_bad_status:
-	return L_LE16_TO_CPU(body->status_code);
 }
 
-struct auth_proto *owe_sm_new(struct handshake_state *hs,
-				owe_tx_authenticate_func_t auth,
-				owe_tx_associate_func_t assoc,
-				void *user_data)
+struct owe_sm *owe_sm_new(struct handshake_state *hs)
 {
 	struct owe_sm *owe = l_new(struct owe_sm, 1);
 
 	owe->hs = hs;
-	owe->auth_tx = auth;
-	owe->assoc_tx = assoc;
-	owe->user_data = user_data;
 	owe->ecc_groups = l_ecc_supported_ike_groups();
 
-	owe->ap.start = owe_start;
-	owe->ap.free = owe_free;
-	owe->ap.rx_authenticate = owe_rx_authenticate;
-	owe->ap.rx_associate = owe_rx_associate;
-
 	if (!owe_reset(owe)) {
 		l_free(owe);
 		return NULL;
 	}
 
-	return &owe->ap;
+	return owe;
 }
diff --git a/src/owe.h b/src/owe.h
index 9a21505f..8a734a00 100644
--- a/src/owe.h
+++ b/src/owe.h
@@ -23,11 +23,9 @@
 struct owe_sm;
 struct handshake_state;
 
-typedef void (*owe_tx_authenticate_func_t)(void *user_data);
-typedef void (*owe_tx_associate_func_t)(struct iovec *ie_iov, size_t iov_len,
-					void *user_data);
+struct owe_sm *owe_sm_new(struct handshake_state *hs);
+void owe_sm_free(struct owe_sm *sm);
 
-struct auth_proto *owe_sm_new(struct handshake_state *hs,
-				owe_tx_authenticate_func_t auth,
-				owe_tx_associate_func_t assoc,
-				void *user_data);
+void owe_build_dh_ie(struct owe_sm *sm, uint8_t *buf, size_t *len_out);
+int owe_process_dh_ie(struct owe_sm *sm, const uint8_t *dh, size_t len);
+bool owe_next_group(struct owe_sm *sm);
-- 
2.31.1

^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2021-09-01 23:36 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-01 23:36 [PATCH 1/3] netdev: factor out scan_bss from CMD_CONNECT builder James Prestwood
2021-09-01 23:36 ` [PATCH 2/3] wsc: set ssid in handshake James Prestwood
2021-09-01 23:36 ` [PATCH 3/3] owe: netdev: refactor to remove OWE as an auth-proto James Prestwood

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).