All the mail mirrored from lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 1/9] frame-xchg: add type to frame_xchg_prefix
@ 2022-08-24 22:55 James Prestwood
  2022-08-24 22:55 ` [PATCH v2 2/9] station: don't set OCVC for FT AKMs James Prestwood
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: James Prestwood @ 2022-08-24 22:55 UTC (permalink / raw
  To: iwd; +Cc: James Prestwood

All uses of frame-xchg were for action frames, and the frame type
was hard coded. Soon other frame types will be needed so the type
must now be specified in the frame_xchg_prefix structure.
---
 src/anqp.c       | 1 +
 src/frame-xchg.c | 2 +-
 src/frame-xchg.h | 1 +
 src/p2p.c        | 4 ++++
 4 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/src/anqp.c b/src/anqp.c
index 8febdf91..a3c3d7ed 100644
--- a/src/anqp.c
+++ b/src/anqp.c
@@ -156,6 +156,7 @@ static bool anqp_response_frame_event(const struct mmpdu_header *hdr,
 }
 
 static const struct frame_xchg_prefix anqp_frame_prefix = {
+	.frame_type = 0x00d0,
 	.data = (uint8_t []) {
 		0x04, 0x0b,
 	},
diff --git a/src/frame-xchg.c b/src/frame-xchg.c
index 5ba36081..158befd0 100644
--- a/src/frame-xchg.c
+++ b/src/frame-xchg.c
@@ -1193,7 +1193,7 @@ uint32_t frame_xchg_startv(uint64_t wdev_id, struct iovec *frame, uint32_t freq,
 		watch = l_new(struct frame_xchg_watch_data, 1);
 		watch->prefix = prefix;
 		watch->cb = va_arg(resp_args, void *);
-		frame_watch_add(wdev_id, group_id, 0x00d0,
+		frame_watch_add(wdev_id, group_id, prefix->frame_type,
 				prefix->data, prefix->len,
 				frame_xchg_resp_cb, fx, NULL);
 
diff --git a/src/frame-xchg.h b/src/frame-xchg.h
index e3748538..360bb4d4 100644
--- a/src/frame-xchg.h
+++ b/src/frame-xchg.h
@@ -32,6 +32,7 @@ typedef void (*frame_xchg_cb_t)(int err, void *user_data);
 typedef void (*frame_xchg_destroy_func_t)(void *user_data);
 
 struct frame_xchg_prefix {
+	uint16_t frame_type;
 	const uint8_t *data;
 	size_t len;
 };
diff --git a/src/p2p.c b/src/p2p.c
index ff3b8e45..45a1b70b 100644
--- a/src/p2p.c
+++ b/src/p2p.c
@@ -820,6 +820,7 @@ static void p2p_peer_frame_xchg(struct p2p_peer *peer, struct iovec *tx_body,
 
 static const struct frame_xchg_prefix p2p_frame_go_neg_req = {
 	/* Management -> Public Action -> P2P -> GO Negotiation Request */
+	.frame_type = 0x00d0,
 	.data = (uint8_t []) {
 		0x04, 0x09, 0x50, 0x6f, 0x9a, 0x09,
 		P2P_ACTION_GO_NEGOTIATION_REQ
@@ -829,6 +830,7 @@ static const struct frame_xchg_prefix p2p_frame_go_neg_req = {
 
 static const struct frame_xchg_prefix p2p_frame_go_neg_resp = {
 	/* Management -> Public Action -> P2P -> GO Negotiation Response */
+	.frame_type = 0x00d0,
 	.data = (uint8_t []) {
 		0x04, 0x09, 0x50, 0x6f, 0x9a, 0x09,
 		P2P_ACTION_GO_NEGOTIATION_RESP
@@ -838,6 +840,7 @@ static const struct frame_xchg_prefix p2p_frame_go_neg_resp = {
 
 static const struct frame_xchg_prefix p2p_frame_go_neg_confirm = {
 	/* Management -> Public Action -> P2P -> GO Negotiation Confirm */
+	.frame_type = 0x00d0,
 	.data = (uint8_t []) {
 		0x04, 0x09, 0x50, 0x6f, 0x9a, 0x09,
 		P2P_ACTION_GO_NEGOTIATION_CONFIRM
@@ -847,6 +850,7 @@ static const struct frame_xchg_prefix p2p_frame_go_neg_confirm = {
 
 static const struct frame_xchg_prefix p2p_frame_pd_resp = {
 	/* Management -> Public Action -> P2P -> Provision Discovery Response */
+	.frame_type = 0x00d0,
 	.data = (uint8_t []) {
 		0x04, 0x09, 0x50, 0x6f, 0x9a, 0x09,
 		P2P_ACTION_PROVISION_DISCOVERY_RESP
-- 
2.34.3


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

* [PATCH v2 2/9] station: don't set OCVC for FT AKMs
  2022-08-24 22:55 [PATCH v2 1/9] frame-xchg: add type to frame_xchg_prefix James Prestwood
@ 2022-08-24 22:55 ` James Prestwood
  2022-08-24 22:55 ` [PATCH v2 3/9] ft: remove OCI element from auth/assoc James Prestwood
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: James Prestwood @ 2022-08-24 22:55 UTC (permalink / raw
  To: iwd; +Cc: James Prestwood

Using OCV in FT is now disabled, so if the AKM is FT don't set the
capability or AP's may reject FT attempts.
---
 src/station.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/src/station.c b/src/station.c
index 66b296b8..cdc31127 100644
--- a/src/station.c
+++ b/src/station.c
@@ -1110,9 +1110,15 @@ build_ie:
 	 * seen that they do not include the OCI in the 4-way handshake yet
 	 * still advertise the capability. Because of this OCV is disabled if
 	 * any offload features are detected (since IWD prefers to use offload).
+	 *
+	 * TODO: For now OCV is disabled if the network is FT capable. This is
+	 *       being done until support in the kernel is added to
+	 *       automatically include the OCI element for the association
+	 *       request.
 	 */
 	info.ocvc = !disable_ocv && bss_info.ocvc && info.mfpc &&
-			!wiphy_can_offload(wiphy);
+			!wiphy_can_offload(wiphy) &&
+			!IE_AKM_IS_FT(info.akm_suites);
 
 	/*
 	 * IEEE 802.11-2020 9.4.2.24.4 states extended key IDs can only be used
-- 
2.34.3


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

* [PATCH v2 3/9] ft: remove OCI element from auth/assoc
  2022-08-24 22:55 [PATCH v2 1/9] frame-xchg: add type to frame_xchg_prefix James Prestwood
  2022-08-24 22:55 ` [PATCH v2 2/9] station: don't set OCVC for FT AKMs James Prestwood
@ 2022-08-24 22:55 ` James Prestwood
  2022-08-24 22:55 ` [PATCH v2 4/9] frame-xchg: create global group enum James Prestwood
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: James Prestwood @ 2022-08-24 22:55 UTC (permalink / raw
  To: iwd; +Cc: James Prestwood

FT is moving to authentication via CMD_FRAME which breaks the ability
to get the OCI from the kernel (since its now an offchannel operation).
Using OCI during FT isn't that useful anyways, so its being removed.
---
 src/ft.c     | 26 ++------------------------
 src/ft.h     |  2 +-
 src/netdev.c |  3 +--
 3 files changed, 4 insertions(+), 27 deletions(-)

diff --git a/src/ft.c b/src/ft.c
index 2285a86f..7ae78476 100644
--- a/src/ft.c
+++ b/src/ft.c
@@ -233,10 +233,6 @@ static int ft_tx_reassociate(struct ft_sm *ft)
 		rsn_info.num_pmkids = 1;
 		rsn_info.pmkids = hs->pmk_r1_name;
 
-		/* Always set OCVC false for FT-over-DS */
-		if (ft->over_ds)
-			rsn_info.ocvc = false;
-
 		rsne = alloca(256);
 		ie_build_rsne(&rsn_info, rsne);
 
@@ -276,22 +272,6 @@ static int ft_tx_reassociate(struct ft_sm *ft)
 		memcpy(ft_info.anonce, hs->anonce, 32);
 		memcpy(ft_info.snonce, hs->snonce, 32);
 
-		/*
-		 * IEEE 802.11-2020 Section 13.7.1 FT reassociation in an RSN
-		 *
-		 * "If dot11RSNAOperatingChannelValidationActivated is true and
-		 *  the FTO indicates OCVC capability, the target AP shall
-		 *  ensure that OCI subelement of the FTE matches by ensuring
-		 *  that all of the following are true:
-		 *      - OCI subelement is present
-		 *      - Channel information in the OCI matches current
-		 *        operating channel parameters (see 12.2.9)"
-		 */
-		if (hs->supplicant_ocvc && hs->chandef) {
-			oci_from_chandef(hs->chandef, ft_info.oci);
-			ft_info.oci_present = true;
-		}
-
 		fte = alloca(256);
 		ie_build_fast_bss_transition(&ft_info, kck_len, fte);
 
@@ -812,7 +792,7 @@ static bool ft_over_ds_start(struct auth_proto *ap)
 	return ft_tx_reassociate(ft) == 0;
 }
 
-bool ft_build_authenticate_ies(struct handshake_state *hs, bool ocvc,
+bool ft_build_authenticate_ies(struct handshake_state *hs,
 				const uint8_t *new_snonce, uint8_t *buf,
 				size_t *len)
 {
@@ -841,7 +821,6 @@ bool ft_build_authenticate_ies(struct handshake_state *hs, bool ocvc,
 
 		rsn_info.num_pmkids = 1;
 		rsn_info.pmkids = hs->pmk_r0_name;
-		rsn_info.ocvc = ocvc;
 
 		ie_build_rsne(&rsn_info, ptr);
 		ptr += ptr[1] + 2;
@@ -892,8 +871,7 @@ static bool ft_start(struct auth_proto *ap)
 	uint8_t buf[512];
 	size_t len;
 
-	if (!ft_build_authenticate_ies(hs, hs->supplicant_ocvc, hs->snonce,
-					buf, &len))
+	if (!ft_build_authenticate_ies(hs, hs->snonce, buf, &len))
 		return false;
 
 	iov.iov_base = buf;
diff --git a/src/ft.h b/src/ft.h
index f90fc1b2..dd56da23 100644
--- a/src/ft.h
+++ b/src/ft.h
@@ -45,7 +45,7 @@ struct ft_ds_info {
 
 void ft_ds_info_free(struct ft_ds_info *info);
 
-bool ft_build_authenticate_ies(struct handshake_state *hs, bool ocvc,
+bool ft_build_authenticate_ies(struct handshake_state *hs,
 				const uint8_t *new_snonce, uint8_t *buf,
 				size_t *len);
 
diff --git a/src/netdev.c b/src/netdev.c
index 3cc34fcd..36e9fc26 100644
--- a/src/netdev.c
+++ b/src/netdev.c
@@ -4759,8 +4759,7 @@ int netdev_fast_transition_over_ds_action(struct netdev *netdev,
 	iovs[0].iov_base = ft_req;
 	iovs[0].iov_len = sizeof(ft_req);
 
-	if (!ft_build_authenticate_ies(hs, false, info->super.snonce,
-						buf, &len))
+	if (!ft_build_authenticate_ies(hs, info->super.snonce, buf, &len))
 		goto failed;
 
 	iovs[1].iov_base = buf;
-- 
2.34.3


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

* [PATCH v2 4/9] frame-xchg: create global group enum
  2022-08-24 22:55 [PATCH v2 1/9] frame-xchg: add type to frame_xchg_prefix James Prestwood
  2022-08-24 22:55 ` [PATCH v2 2/9] station: don't set OCVC for FT AKMs James Prestwood
  2022-08-24 22:55 ` [PATCH v2 3/9] ft: remove OCI element from auth/assoc James Prestwood
@ 2022-08-24 22:55 ` James Prestwood
  2022-08-24 22:55 ` [PATCH v2 5/9] ft: netdev: prep for FT isolation into ft.c James Prestwood
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: James Prestwood @ 2022-08-24 22:55 UTC (permalink / raw
  To: iwd; +Cc: James Prestwood

Only P2P utilizes groups for now but to avoid conflicts in group
numbers for other modules create a global list which can be added
to as needed.
---
 src/frame-xchg.h |  7 +++++++
 src/p2p.c        | 24 +++++++++---------------
 2 files changed, 16 insertions(+), 15 deletions(-)

diff --git a/src/frame-xchg.h b/src/frame-xchg.h
index 360bb4d4..5b55ded8 100644
--- a/src/frame-xchg.h
+++ b/src/frame-xchg.h
@@ -37,6 +37,13 @@ struct frame_xchg_prefix {
 	size_t len;
 };
 
+enum frame_xchg_group {
+	FRAME_GROUP_DEFAULT = 0,
+	FRAME_GROUP_P2P_LISTEN,
+	FRAME_GROUP_P2P_CONNECT,
+	FRAME_GROUP_FT,
+};
+
 bool frame_watch_add(uint64_t wdev_id, uint32_t group, uint16_t frame_type,
 			const uint8_t *prefix, size_t prefix_len,
 			frame_watch_cb_t handler, void *user_data,
diff --git a/src/p2p.c b/src/p2p.c
index 45a1b70b..cfd8560a 100644
--- a/src/p2p.c
+++ b/src/p2p.c
@@ -190,12 +190,6 @@ static const int channels_scan_2_4_other[] = { 2, 3, 4, 5, 7, 8, 9, 10 };
  */
 #define P2P_GO_INTENT 2
 
-enum {
-	FRAME_GROUP_DEFAULT = 0,
-	FRAME_GROUP_LISTEN,
-	FRAME_GROUP_CONNECT,
-};
-
 static bool p2p_device_match(const void *a, const void *b)
 {
 	const struct p2p_device *dev = a;
@@ -718,7 +712,7 @@ static void p2p_connection_reset(struct p2p_device *dev)
 
 	netdev_watch_remove(dev->conn_netdev_watch_id);
 
-	frame_watch_group_remove(dev->wdev_id, FRAME_GROUP_CONNECT);
+	frame_watch_group_remove(dev->wdev_id, FRAME_GROUP_P2P_CONNECT);
 	frame_xchg_stop_wdev(dev->wdev_id);
 
 	if (!dev->enabled || (dev->enabled && dev->start_stop_cmd_id)) {
@@ -2527,13 +2521,13 @@ respond:
 
 	if (status == P2P_STATUS_SUCCESS)
 		p2p_peer_frame_xchg(peer, iov, dev->addr, 0, 600, 0, true,
-					FRAME_GROUP_CONNECT,
+					FRAME_GROUP_P2P_CONNECT,
 					p2p_go_negotiation_resp_done,
 					&p2p_frame_go_neg_confirm,
 					p2p_go_negotiation_confirm_cb, NULL);
 	else
 		p2p_peer_frame_xchg(peer, iov, dev->addr, 0, 0, 0, true,
-					FRAME_GROUP_CONNECT,
+					FRAME_GROUP_P2P_CONNECT,
 					p2p_go_negotiation_resp_err_done, NULL);
 
 	l_debug("GO Negotiation Response sent with status %i", status);
@@ -2804,7 +2798,7 @@ static bool p2p_go_negotiation_resp_cb(const struct mmpdu_header *mpdu,
 	iov[iov_len].iov_base = NULL;
 
 	p2p_peer_frame_xchg(dev->conn_peer, iov, dev->conn_peer->device_addr,
-				0, 0, 0, false, FRAME_GROUP_CONNECT,
+				0, 0, 0, false, FRAME_GROUP_P2P_CONNECT,
 				p2p_go_negotiation_confirm_done, NULL);
 	l_free(confirm_body);
 
@@ -2893,7 +2887,7 @@ static void p2p_start_go_negotiation(struct p2p_device *dev)
 
 	p2p_peer_frame_xchg(dev->conn_peer, iov, dev->conn_peer->device_addr,
 				100, resp_timeout, 256, false,
-				FRAME_GROUP_CONNECT,
+				FRAME_GROUP_P2P_CONNECT,
 				p2p_go_negotiation_req_done,
 				&p2p_frame_go_neg_resp,
 				p2p_go_negotiation_resp_cb, NULL);
@@ -3035,7 +3029,7 @@ static void p2p_start_provision_discovery(struct p2p_device *dev)
 	 * sent to the P2P Device Address of the P2P Group Owner"
 	 */
 	p2p_peer_frame_xchg(dev->conn_peer, iov, dev->conn_peer->device_addr,
-				200, 600, 8, false, FRAME_GROUP_CONNECT,
+				200, 600, 8, false, FRAME_GROUP_P2P_CONNECT,
 				p2p_provision_disc_req_done,
 				&p2p_frame_pd_resp, p2p_provision_disc_resp_cb,
 				NULL);
@@ -4167,9 +4161,9 @@ static void p2p_device_discovery_start(struct p2p_device *dev)
 		dev->listen_channel = channels_social[l_getrandom_uint32() %
 						L_ARRAY_SIZE(channels_social)];
 
-	frame_watch_add(dev->wdev_id, FRAME_GROUP_LISTEN, 0x0040,
+	frame_watch_add(dev->wdev_id, FRAME_GROUP_P2P_LISTEN, 0x0040,
 			(uint8_t *) "", 0, p2p_device_probe_cb, dev, NULL);
-	frame_watch_add(dev->wdev_id, FRAME_GROUP_LISTEN, 0x00d0,
+	frame_watch_add(dev->wdev_id, FRAME_GROUP_P2P_LISTEN, 0x00d0,
 			p2p_frame_go_neg_req.data, p2p_frame_go_neg_req.len,
 			p2p_device_go_negotiation_req_cb, dev, NULL);
 
@@ -4187,7 +4181,7 @@ static void p2p_device_discovery_stop(struct p2p_device *dev)
 		l_timeout_remove(dev->scan_timeout);
 
 	p2p_device_roc_cancel(dev);
-	frame_watch_group_remove(dev->wdev_id, FRAME_GROUP_LISTEN);
+	frame_watch_group_remove(dev->wdev_id, FRAME_GROUP_P2P_LISTEN);
 }
 
 static void p2p_device_enable_cb(struct l_genl_msg *msg, void *user_data)
-- 
2.34.3


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

* [PATCH v2 5/9] ft: netdev: prep for FT isolation into ft.c
  2022-08-24 22:55 [PATCH v2 1/9] frame-xchg: add type to frame_xchg_prefix James Prestwood
                   ` (2 preceding siblings ...)
  2022-08-24 22:55 ` [PATCH v2 4/9] frame-xchg: create global group enum James Prestwood
@ 2022-08-24 22:55 ` James Prestwood
  2022-08-24 22:55 ` [PATCH v2 6/9] netdev: use new ft_sm for over-DS James Prestwood
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: James Prestwood @ 2022-08-24 22:55 UTC (permalink / raw
  To: iwd; +Cc: James Prestwood

Currently netdev handles caching FT auth information and uses FT
parsers/auth-proto to manage the protocol. This sets up to remove
this state machine from netdev and isolate it into ft.c.

This does not break the existing auth-proto (hence the slight
modifications, which will be removed soon).

Eventually the auth-proto will be removed from FT entirely, replaced
just by an FT state machine, similar to how EAPoL works (netdev hooks
to TX/RX frames).
---
 src/ft.c     | 337 +++++++++++++++++++++++++++++++++++++++++++++++++--
 src/ft.h     |  20 ++-
 src/netdev.c |  47 ++++---
 3 files changed, 377 insertions(+), 27 deletions(-)

diff --git a/src/ft.c b/src/ft.c
index 7ae78476..2c9c92e6 100644
--- a/src/ft.c
+++ b/src/ft.c
@@ -33,6 +33,33 @@
 #include "src/mpdu.h"
 #include "src/auth-proto.h"
 #include "src/band.h"
+#include "src/scan.h"
+#include "src/frame-xchg.h"
+#include "src/util.h"
+#include "src/netdev.h"
+#include "src/module.h"
+
+static ft_tx_action_func_t tx_action = NULL;
+static ft_tx_associate_func_t tx_assoc = NULL;
+static struct l_queue *sm_list = NULL;
+
+struct ft_info {
+	uint8_t spa[6];
+	uint8_t aa[6];
+	uint8_t snonce[32];
+	uint8_t mde[3];
+	uint8_t *fte;
+	uint8_t *authenticator_ie;
+
+	struct ie_ft_info ft_info;
+
+	bool parsed : 1;
+};
+
+struct ft_info_finder {
+	const uint8_t *spa;
+	const uint8_t *aa;
+};
 
 struct ft_sm {
 	struct auth_proto ap;
@@ -45,8 +72,24 @@ struct ft_sm {
 	void *user_data;
 
 	bool over_ds : 1;
+
+	uint8_t prev_bssid[6];
+	struct l_queue *ft_auths;
 };
 
+static bool match_ifindex(const void *a, const void *data)
+{
+	const struct ft_sm *sm = a;
+	uint32_t ifindex = L_PTR_TO_UINT(data);
+
+	return sm->hs->ifindex == ifindex;
+}
+
+static struct ft_sm *ft_sm_find(uint32_t ifindex)
+{
+	return l_queue_find(sm_list, match_ifindex, L_UINT_TO_PTR(ifindex));
+}
+
 /*
  * Calculate the MIC field of the FTE and write it directly to that FTE,
  * assuming it was all zeros before.  See 12.8.4 and 12.8.5.
@@ -286,7 +329,7 @@ static int ft_tx_reassociate(struct ft_sm *ft)
 		iov_elems += 1;
 	}
 
-	return ft->tx_assoc(iov, iov_elems, ft->user_data);
+	return tx_assoc(ft->hs->ifindex, ft->prev_bssid, iov, iov_elems);
 
 error:
 	return -EINVAL;
@@ -328,7 +371,7 @@ static bool ft_verify_rsne(const uint8_t *rsne, const uint8_t *pmk_r0_name,
 	return true;
 }
 
-static int ft_parse_ies(struct handshake_state *hs,
+static int parse_ies(struct handshake_state *hs,
 			const uint8_t *authenticator_ie,
 			const uint8_t *ies, size_t ies_len,
 			const uint8_t **mde_out,
@@ -460,7 +503,7 @@ bool ft_over_ds_parse_action_ies(struct ft_ds_info *info,
 	const uint8_t *fte = NULL;
 	bool is_rsn = hs->supplicant_ie != NULL;
 
-	if (ft_parse_ies(hs, info->authenticator_ie, ies, ies_len,
+	if (parse_ies(hs, info->authenticator_ie, ies, ies_len,
 				&mde, &fte) < 0)
 		return false;
 
@@ -492,7 +535,7 @@ static int ft_process_ies(struct handshake_state *hs, const uint8_t *ies,
 	if (!ies)
 		goto ft_error;
 
-	if (ft_parse_ies(hs, hs->authenticator_ie, ies, ies_len,
+	if (parse_ies(hs, hs->authenticator_ie, ies, ies_len,
 				&mde, &fte) < 0)
 		goto ft_error;
 
@@ -634,10 +677,9 @@ auth_error:
 	return (int)status_code;
 }
 
-static int ft_rx_associate(struct auth_proto *ap, const uint8_t *frame,
-				size_t frame_len)
+int __ft_rx_associate(uint32_t ifindex, const uint8_t *frame, size_t frame_len)
 {
-	struct ft_sm *ft = l_container_of(ap, struct ft_sm, ap);
+	struct ft_sm *ft = ft_sm_find(ifindex);
 	struct handshake_state *hs = ft->hs;
 	uint32_t kck_len = handshake_state_get_kck_len(hs);
 	const uint8_t *rsne = NULL;
@@ -651,6 +693,9 @@ static int ft_rx_associate(struct auth_proto *ap, const uint8_t *frame,
 					&mde, &fte))
 		return -EBADMSG;
 
+	if (out_status != 0)
+		return (int)out_status;
+
 	/*
 	 * During a transition in an RSN, check for an RSNE containing the
 	 * PMK-R1-Name and the remaining fields same as in the advertised
@@ -771,6 +816,14 @@ static int ft_rx_associate(struct auth_proto *ap, const uint8_t *frame,
 	return 0;
 }
 
+static int ft_rx_associate(struct auth_proto *ap, const uint8_t *frame,
+				size_t frame_len)
+{
+	struct ft_sm *sm = l_container_of(ap, struct ft_sm, ap);
+
+	return __ft_rx_associate(sm->hs->ifindex, frame, frame_len);
+}
+
 static int ft_rx_oci(struct auth_proto *ap)
 {
 	struct ft_sm *ft = l_container_of(ap, struct ft_sm, ap);
@@ -778,10 +831,12 @@ static int ft_rx_oci(struct auth_proto *ap)
 	return ft_tx_reassociate(ft);
 }
 
-static void ft_sm_free(struct auth_proto *ap)
+static void ft_auth_proto_free(struct auth_proto *ap)
 {
 	struct ft_sm *ft = l_container_of(ap, struct ft_sm, ap);
 
+	l_queue_remove(sm_list, ft);
+
 	l_free(ft);
 }
 
@@ -899,9 +954,13 @@ struct auth_proto *ft_over_air_sm_new(struct handshake_state *hs,
 	ft->ap.rx_authenticate = ft_rx_authenticate;
 	ft->ap.rx_associate = ft_rx_associate;
 	ft->ap.start = ft_start;
-	ft->ap.free = ft_sm_free;
+	ft->ap.free = ft_auth_proto_free;
 	ft->ap.rx_oci = ft_rx_oci;
 
+	memcpy(ft->prev_bssid, hs->aa, 6);
+
+	l_queue_push_tail(sm_list, ft);
+
 	return &ft->ap;
 }
 
@@ -918,7 +977,265 @@ struct auth_proto *ft_over_ds_sm_new(struct handshake_state *hs,
 
 	ft->ap.rx_associate = ft_rx_associate;
 	ft->ap.start = ft_over_ds_start;
-	ft->ap.free = ft_sm_free;
+	ft->ap.free = ft_auth_proto_free;
+
+	memcpy(ft->prev_bssid, hs->aa, 6);
+
+	l_queue_push_tail(sm_list, ft);
 
 	return &ft->ap;
 }
+
+void __ft_set_tx_action_func(ft_tx_action_func_t func)
+{
+	tx_action = func;
+}
+
+void __ft_set_tx_associate_func(ft_tx_associate_func_t func)
+{
+	tx_assoc = func;
+}
+
+static bool match_ft_info(const void *a, const void *b)
+{
+	const struct ft_info *info = a;
+	const struct ft_info_finder *finder = b;
+
+	if (memcmp(info->spa, finder->spa, 6))
+		return false;
+	if (memcmp(info->aa, finder->aa, 6))
+		return false;
+
+	return true;
+}
+
+static bool ft_parse_ies(struct ft_info *info, struct handshake_state *hs,
+			const uint8_t *ies, size_t ies_len)
+{
+	const uint8_t *mde = NULL;
+	const uint8_t *fte = NULL;
+	bool is_rsn = hs->supplicant_ie != NULL;
+
+	if (parse_ies(hs, info->authenticator_ie, ies, ies_len,
+				&mde, &fte) < 0)
+		return false;
+
+	if (!mde_equal(info->mde, mde))
+		goto ft_error;
+
+	if (is_rsn) {
+		if (!ft_parse_fte(hs, info->snonce, fte, &info->ft_info))
+			goto ft_error;
+
+		info->fte = l_memdup(fte, fte[1] + 2);
+	} else if (fte)
+		goto ft_error;
+
+	return true;
+
+ft_error:
+	return false;
+}
+
+static void ft_action_response_cb(const struct mmpdu_header *hdr,
+					const void *body, size_t body_len,
+					int rssi, void *user_data)
+{
+	struct ft_sm *sm = user_data;
+	struct ft_info *info;
+	int ret;
+	const uint8_t *aa;
+	const uint8_t *spa;
+	const uint8_t *ies;
+	size_t ies_len;
+	struct ft_info_finder finder;
+
+	ret = ft_over_ds_parse_action_response(body, body_len, &spa, &aa,
+						&ies, &ies_len);
+	if (ret != 0)
+		return;
+
+	finder.spa = spa;
+	finder.aa = aa;
+
+	info = l_queue_find(sm->ft_auths, match_ft_info, &finder);
+	if (!info)
+		return;
+
+	if (!ft_parse_ies(info, sm->hs, ies, ies_len))
+		goto ft_error;
+
+	info->parsed = true;
+
+	return;
+
+ft_error:
+	l_debug("FT-over-DS authenticate to "MAC" failed", MAC_STR(info->aa));
+}
+
+static struct ft_info *ft_info_new(struct handshake_state *hs,
+					const struct scan_bss *target_bss)
+{
+	struct ft_info *info = l_new(struct ft_info, 1);
+
+	memcpy(info->spa, hs->spa, 6);
+	memcpy(info->aa, target_bss->addr, 6);
+	memcpy(info->mde, target_bss->mde, sizeof(info->mde));
+
+	if (target_bss->rsne)
+		info->authenticator_ie = l_memdup(target_bss->rsne,
+						target_bss->rsne[1] + 2);
+
+	l_getrandom(info->snonce, 32);
+
+	return info;
+}
+
+static void ft_info_destroy(void *data)
+{
+	struct ft_info *info = data;
+
+	if (info->fte)
+		l_free(info->fte);
+
+	if (info->authenticator_ie)
+		l_free(info->authenticator_ie);
+
+	l_free(info);
+}
+
+static void ft_prepare_handshake(struct ft_info *info,
+					struct handshake_state *hs)
+{
+	if (!hs->supplicant_ie)
+		return;
+
+	memcpy(hs->snonce, info->snonce, sizeof(hs->snonce));
+
+	handshake_state_set_fte(hs, info->fte);
+
+	handshake_state_set_anonce(hs, info->ft_info.anonce);
+
+	handshake_state_set_kh_ids(hs, info->ft_info.r0khid,
+						info->ft_info.r0khid_len,
+						info->ft_info.r1khid);
+
+	handshake_state_derive_ptk(hs);
+}
+
+static const uint8_t action_ft_response_prefix[] =  { 0x06, 0x02 };
+
+struct ft_sm *ft_sm_new(struct handshake_state *hs)
+{
+	struct ft_sm *sm = l_new(struct ft_sm, 1);
+	struct netdev *netdev = netdev_find(hs->ifindex);
+
+	sm->hs = hs;
+	sm->ft_auths = l_queue_new();
+	sm->over_ds = hs->mde[4] & 1;
+	memcpy(sm->prev_bssid, hs->aa, 6);
+
+	if (sm->over_ds)
+		frame_watch_add(netdev_get_wdev_id(netdev), FRAME_GROUP_FT,
+			0x00d0, action_ft_response_prefix,
+			sizeof(action_ft_response_prefix),
+			ft_action_response_cb, sm, NULL);
+
+	l_queue_push_tail(sm_list, sm);
+
+	return sm;
+}
+
+void ft_sm_free(struct ft_sm *sm)
+{
+	struct netdev *netdev = netdev_find(sm->hs->ifindex);
+
+	if (sm->over_ds)
+		frame_watch_group_remove(netdev_get_wdev_id(netdev),
+					FRAME_GROUP_FT);
+
+	l_queue_destroy(sm->ft_auths, ft_info_destroy);
+
+	l_queue_remove(sm_list, sm);
+
+	l_free(sm);
+}
+
+int ft_action(struct ft_sm *sm, const struct scan_bss *target)
+{
+	struct ft_info *info;
+	uint8_t ft_req[14];
+	struct iovec iov[5];
+	uint8_t ies[512];
+	size_t len;
+	int ret = -EINVAL;
+
+	info = ft_info_new(sm->hs, target);
+
+	ft_req[0] = 6; /* FT category */
+	ft_req[1] = 1; /* FT Request action */
+	memcpy(ft_req + 2, info->spa, 6);
+	memcpy(ft_req + 8, info->aa, 6);
+
+	if (!ft_build_authenticate_ies(sm->hs, info->snonce, ies, &len))
+		goto failed;
+
+	iov[0].iov_base = ft_req;
+	iov[0].iov_len = sizeof(ft_req);
+
+	iov[1].iov_base = ies;
+	iov[1].iov_len = len;
+
+	ret = tx_action(sm->hs->ifindex, sm->hs->aa, iov, 2);
+	if (ret < 0)
+		goto failed;
+
+	l_queue_push_tail(sm->ft_auths, info);
+
+	return 0;
+
+failed:
+	l_free(info);
+	return ret;
+}
+
+int ft_associate(struct ft_sm *sm, const uint8_t *addr)
+{
+	struct ft_info *info;
+	struct ft_info_finder finder;
+
+	finder.spa = sm->hs->spa;
+	finder.aa = addr;
+
+	info = l_queue_find(sm->ft_auths, match_ft_info, &finder);
+	/*
+	 * TODO: Since FT-over-DS is done early, before the time of roaming, it
+	 *       may end up that a completely new BSS is the best candidate and
+	 *       we haven't yet authenticated. We could actually authenticate
+	 *       at this point, but for now just assume the caller will choose
+	 *       a different BSS.
+	 */
+	if (!info)
+		return -ENOENT;
+
+	ft_prepare_handshake(info, sm->hs);
+
+	return ft_tx_reassociate(sm);
+}
+
+static int ft_init(void)
+{
+	sm_list = l_queue_new();
+
+	return 0;
+}
+
+static void ft_exit(void)
+{
+	if (!l_queue_isempty(sm_list))
+		l_warn("stale FT state machines found!");
+
+	l_queue_destroy(sm_list, (l_queue_destroy_func_t)ft_sm_free);
+}
+
+IWD_MODULE(ft, ft_init, ft_exit);
diff --git a/src/ft.h b/src/ft.h
index dd56da23..6e0f4271 100644
--- a/src/ft.h
+++ b/src/ft.h
@@ -21,11 +21,16 @@
  */
 
 struct handshake_state;
+struct scan_bss;
+
+typedef int (*ft_tx_action_func_t)(uint32_t ifindex, const uint8_t *dest,
+					struct iovec *iov, size_t iov_len);
 
 typedef void (*ft_tx_authenticate_func_t)(struct iovec *iov, size_t iov_len,
 					void *user_data);
-typedef int (*ft_tx_associate_func_t)(struct iovec *ie_iov, size_t iov_len,
-					void *user_data);
+typedef int (*ft_tx_associate_func_t)(uint32_t ifindex,
+					const uint8_t *prev_bssid,
+					struct iovec *ie_iov, size_t iov_len);
 typedef int (*ft_get_oci)(void *user_data);
 
 typedef void (*ft_ds_free_func_t)(void *user_data);
@@ -71,3 +76,14 @@ struct auth_proto *ft_over_ds_sm_new(struct handshake_state *hs,
 
 bool ft_over_ds_prepare_handshake(struct ft_ds_info *info,
 					struct handshake_state *hs);
+
+void __ft_set_tx_action_func(ft_tx_action_func_t func);
+void __ft_set_tx_associate_func(ft_tx_associate_func_t func);
+int __ft_rx_associate(uint32_t ifindex, const uint8_t *frame,
+			size_t frame_len);
+
+struct ft_sm *ft_sm_new(struct handshake_state *hs);
+void ft_sm_free(struct ft_sm *sm);
+
+int ft_action(struct ft_sm *sm, const struct scan_bss *target);
+int ft_associate(struct ft_sm *sm, const uint8_t *addr);
diff --git a/src/netdev.c b/src/netdev.c
index 36e9fc26..7a1dbc0f 100644
--- a/src/netdev.c
+++ b/src/netdev.c
@@ -4360,6 +4360,25 @@ static uint32_t netdev_send_action_frame(struct netdev *netdev,
 						user_data);
 }
 
+static void netdev_ft_action_cb(struct l_genl_msg *msg, void *user_data)
+{
+	if (l_genl_msg_get_error(msg) < 0)
+		l_debug("Failed to send FT-Action");
+}
+
+static int netdev_tx_ft_action_frame(uint32_t ifindex, const uint8_t *dest,
+					struct iovec *iov, size_t iov_len)
+{
+	struct netdev *netdev = netdev_find(ifindex);
+
+	if (!netdev_send_action_framev(netdev, dest, iov, iov_len,
+					netdev->frequency,
+					netdev_ft_action_cb, NULL))
+		return -EIO;
+
+	return 0;
+}
+
 static void netdev_cmd_authenticate_ft_cb(struct l_genl_msg *msg,
 						void *user_data)
 {
@@ -4402,11 +4421,10 @@ restore_snonce:
 					MMPDU_STATUS_CODE_UNSPECIFIED);
 }
 
-static int netdev_ft_tx_associate(struct iovec *ft_iov, size_t n_ft_iov,
-					void *user_data)
+static int netdev_ft_tx_associate(uint32_t ifindex, const uint8_t *prev_bssid,
+					struct iovec *ft_iov, size_t n_ft_iov)
 {
-	struct netdev *netdev = user_data;
-	struct auth_proto *ap = netdev->ap;
+	struct netdev *netdev = netdev_find(ifindex);
 	struct handshake_state *hs = netdev->handshake;
 	struct l_genl_msg *msg;
 	struct iovec iov[64];
@@ -4427,7 +4445,7 @@ static int netdev_ft_tx_associate(struct iovec *ft_iov, size_t n_ft_iov,
 	mpdu_sort_ies(subtype, iov, c_iov);
 
 	l_genl_msg_append_attr(msg, NL80211_ATTR_PREV_BSSID, ETH_ALEN,
-				ap->prev_bssid);
+				prev_bssid);
 	l_genl_msg_append_attrv(msg, NL80211_ATTR_IE, iov, c_iov);
 
 	netdev->connect_cmd_id = l_genl_family_send(nl80211, msg,
@@ -4639,17 +4657,15 @@ int netdev_fast_transition(struct netdev *netdev,
 			l_get_le16(target_bss->mde))
 		return -EINVAL;
 
-	prepare_ft(netdev, target_bss);
-
-	handshake_state_new_snonce(netdev->handshake);
-
 	netdev->connect_cb = cb;
 
 	netdev->ap = ft_over_air_sm_new(netdev->handshake,
 					netdev_ft_tx_authenticate,
 					netdev_ft_tx_associate,
 					netdev_get_oci, netdev);
-	memcpy(netdev->ap->prev_bssid, orig_bss->addr, ETH_ALEN);
+	prepare_ft(netdev, target_bss);
+
+	handshake_state_new_snonce(netdev->handshake);
 
 	wiphy_radio_work_insert(netdev->wiphy, &netdev->work,
 				WIPHY_WORK_PRIORITY_CONNECT, &ft_work_ops);
@@ -4681,16 +4697,14 @@ int netdev_fast_transition_over_ds(struct netdev *netdev,
 	if (!info || !info->parsed)
 		return -ENOENT;
 
-	prepare_ft(netdev, target_bss);
-
-	ft_over_ds_prepare_handshake(&info->super, netdev->handshake);
-
 	netdev->connect_cb = cb;
 
 	netdev->ap = ft_over_ds_sm_new(netdev->handshake,
 					netdev_ft_tx_associate,
 					netdev);
-	memcpy(netdev->ap->prev_bssid, orig_bss->addr, ETH_ALEN);
+	prepare_ft(netdev, target_bss);
+
+	ft_over_ds_prepare_handshake(&info->super, netdev->handshake);
 
 	wiphy_radio_work_insert(netdev->wiphy, &netdev->work,
 				WIPHY_WORK_PRIORITY_CONNECT, &ft_work_ops);
@@ -6635,6 +6649,9 @@ static int netdev_init(void)
 	__eapol_set_tx_packet_func(netdev_control_port_frame);
 	__eapol_set_install_pmk_func(netdev_set_pmk);
 
+	__ft_set_tx_action_func(netdev_tx_ft_action_frame);
+	__ft_set_tx_associate_func(netdev_ft_tx_associate);
+
 	unicast_watch = l_genl_add_unicast_watch(genl, NL80211_GENL_NAME,
 						netdev_unicast_notify,
 						NULL, NULL);
-- 
2.34.3


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

* [PATCH v2 6/9] netdev: use new ft_sm for over-DS
  2022-08-24 22:55 [PATCH v2 1/9] frame-xchg: add type to frame_xchg_prefix James Prestwood
                   ` (3 preceding siblings ...)
  2022-08-24 22:55 ` [PATCH v2 5/9] ft: netdev: prep for FT isolation into ft.c James Prestwood
@ 2022-08-24 22:55 ` James Prestwood
  2022-08-24 22:55 ` [PATCH v2 7/9] ft: implement offchannel authentication James Prestwood
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: James Prestwood @ 2022-08-24 22:55 UTC (permalink / raw
  To: iwd; +Cc: James Prestwood

FT-over-DS auth entries are now stored in ft.c itself, and a few APIs
are exposed to send the action/associate frames. This is duplicated
in netdev, which can now be removed. Currently FT-over-Air still
uses the auth-proto which has been left in place for now.

The basic flow remains the same, station initiates action frames to
possible roam candidates. Authentication takes place and the IEs
are stored in ft.c. Then, when a roam is required, association may
begin using one of the cached authentications.
---
 src/netdev.c | 255 +++++++++------------------------------------------
 1 file changed, 43 insertions(+), 212 deletions(-)

diff --git a/src/netdev.c b/src/netdev.c
index 7a1dbc0f..334e10ab 100644
--- a/src/netdev.c
+++ b/src/netdev.c
@@ -96,13 +96,6 @@ struct netdev_handshake_state {
 	enum connection_type type;
 };
 
-struct netdev_ft_over_ds_info {
-	struct ft_ds_info super;
-	struct netdev *netdev;
-
-	bool parsed : 1;
-};
-
 struct netdev_ext_key_info {
 	uint16_t proto;
 	bool noencrypt;
@@ -128,6 +121,7 @@ struct netdev {
 	struct eapol_sm *sm;
 	struct auth_proto *ap;
 	struct owe_sm *owe_sm;
+	struct ft_sm *ft_sm;
 	struct handshake_state *handshake;
 	uint32_t connect_cmd_id;
 	uint32_t disconnect_cmd_id;
@@ -176,8 +170,6 @@ struct netdev {
 	struct l_genl_msg *auth_cmd;
 	struct wiphy_radio_work_item work;
 
-	struct l_queue *ft_ds_list;
-
 	struct netdev_ext_key_info *ext_key_info;
 
 	bool connected : 1;
@@ -752,13 +744,6 @@ static void netdev_preauth_destroy(void *data)
 	l_free(state);
 }
 
-static void netdev_ft_ds_entry_free(void *data)
-{
-	struct netdev_ft_over_ds_info *info = data;
-
-	ft_ds_info_free(&info->super);
-}
-
 static void netdev_connect_free(struct netdev *netdev)
 {
 	if (netdev->work.id)
@@ -779,6 +764,11 @@ static void netdev_connect_free(struct netdev *netdev)
 		netdev->owe_sm = NULL;
 	}
 
+	if (netdev->ft_sm) {
+		ft_sm_free(netdev->ft_sm);
+		netdev->ft_sm = NULL;
+	}
+
 	eapol_preauth_cancel(netdev->index);
 
 	if (netdev->handshake) {
@@ -847,11 +837,6 @@ static void netdev_connect_free(struct netdev *netdev)
 		l_genl_family_cancel(nl80211, netdev->get_oci_cmd_id);
 		netdev->get_oci_cmd_id = 0;
 	}
-
-	if (netdev->ft_ds_list) {
-		l_queue_destroy(netdev->ft_ds_list, netdev_ft_ds_entry_free);
-		netdev->ft_ds_list = NULL;
-	}
 }
 
 static void netdev_connect_failed(struct netdev *netdev,
@@ -962,11 +947,6 @@ static void netdev_free(void *data)
 	if (netdev->fw_roam_bss)
 		scan_bss_free(netdev->fw_roam_bss);
 
-	if (netdev->ft_ds_list) {
-		l_queue_destroy(netdev->ft_ds_list, netdev_ft_ds_entry_free);
-		netdev->ft_ds_list = NULL;
-	}
-
 	scan_wdev_remove(netdev->wdev_id);
 
 	watchlist_destroy(&netdev->station_watches);
@@ -1415,9 +1395,12 @@ static void netdev_connect_ok(struct netdev *netdev)
 		netdev->fw_roam_bss = NULL;
 	}
 
-	if (netdev->ft_ds_list) {
-		l_queue_destroy(netdev->ft_ds_list, netdev_ft_ds_entry_free);
-		netdev->ft_ds_list = NULL;
+	/* TODO: Create only for over-DS. Over-air still uses auth-proto */
+	if (netdev->handshake->mde && (netdev->handshake->mde[4] & 1)) {
+		if (netdev->ft_sm)
+			ft_sm_free(netdev->ft_sm);
+
+		netdev->ft_sm = ft_sm_new(netdev->handshake);
 	}
 
 	if (netdev->connect_cb) {
@@ -3198,7 +3181,7 @@ static void netdev_associate_event(struct l_genl_msg *msg,
 	if (!netdev->connected || netdev->aborting)
 		return;
 
-	if (!netdev->ap) {
+	if (!netdev->ap && !netdev->ft_sm) {
 		netdev->associated = true;
 		netdev->in_reassoc = false;
 		return;
@@ -3238,7 +3221,7 @@ static void netdev_associate_event(struct l_genl_msg *msg,
 	if (L_WARN_ON(!frame))
 		goto assoc_failed;
 
-	if (netdev->ap) {
+	if (netdev->ap || netdev->ft_sm) {
 		const struct mmpdu_header *hdr;
 		const struct mmpdu_association_response *assoc;
 
@@ -3249,7 +3232,12 @@ static void netdev_associate_event(struct l_genl_msg *msg,
 		assoc = mmpdu_body(hdr);
 		status_code = L_CPU_TO_LE16(assoc->status_code);
 
-		ret = auth_proto_rx_associate(netdev->ap, frame, frame_len);
+		if (netdev->ap)
+			ret = auth_proto_rx_associate(netdev->ap, frame,
+							frame_len);
+		else
+			ret = __ft_rx_associate(netdev->index, frame,
+							frame_len);
 		if (ret == 0) {
 			bool fils = !!(netdev->handshake->akm_suite &
 					(IE_RSN_AKM_SUITE_FILS_SHA256 |
@@ -3257,8 +3245,10 @@ static void netdev_associate_event(struct l_genl_msg *msg,
 					 IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA384 |
 					 IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA256));
 
-			auth_proto_free(netdev->ap);
-			netdev->ap = NULL;
+			if (netdev->ap) {
+				auth_proto_free(netdev->ap);
+				netdev->ap = NULL;
+			}
 
 			netdev->sm = eapol_sm_new(netdev->handshake);
 			eapol_register(netdev->sm);
@@ -4527,81 +4517,6 @@ static void prepare_ft(struct netdev *netdev, const struct scan_bss *target_bss)
 	}
 }
 
-static void netdev_ft_over_ds_auth_failed(struct netdev_ft_over_ds_info *info,
-						uint16_t status)
-{
-	l_queue_remove(info->netdev->ft_ds_list, info);
-	ft_ds_info_free(&info->super);
-}
-
-struct ft_ds_finder {
-	const uint8_t *spa;
-	const uint8_t *aa;
-};
-
-static bool match_ft_ds_info(const void *a, const void *b)
-{
-	const struct netdev_ft_over_ds_info *info = a;
-	const struct ft_ds_finder *finder = b;
-
-	if (memcmp(info->super.spa, finder->spa, 6))
-		return false;
-	if (memcmp(info->super.aa, finder->aa, 6))
-		return false;
-
-	return true;
-}
-
-static void netdev_ft_response_frame_event(const struct mmpdu_header *hdr,
-					const void *body, size_t body_len,
-					int rssi, void *user_data)
-{
-	struct netdev *netdev = user_data;
-	struct netdev_ft_over_ds_info *info;
-	int ret;
-	uint16_t status_code = MMPDU_STATUS_CODE_UNSPECIFIED;
-	const uint8_t *aa;
-	const uint8_t *spa;
-	const uint8_t *ies;
-	size_t ies_len;
-	struct ft_ds_finder finder;
-
-	if (!netdev->connected)
-		return;
-
-	ret = ft_over_ds_parse_action_response(body, body_len, &spa, &aa,
-						&ies, &ies_len);
-	if (ret < 0)
-		return;
-
-	finder.spa = spa;
-	finder.aa = aa;
-
-	info = l_queue_find(netdev->ft_ds_list, match_ft_ds_info, &finder);
-	if (!info)
-		return;
-
-	/* Lookup successful, now check the status code */
-	if (ret > 0) {
-		status_code = (uint16_t)ret;
-		goto ft_error;
-	}
-
-	if (!ft_over_ds_parse_action_ies(&info->super, netdev->handshake,
-						ies, ies_len))
-		goto ft_error;
-
-	info->parsed = true;
-
-	return;
-
-ft_error:
-	l_debug("FT-over-DS to "MAC" failed (%d)", MAC_STR(info->super.aa),
-			status_code);
-
-	netdev_ft_over_ds_auth_failed(info, status_code);
-}
-
 static void netdev_qos_map_frame_event(const struct mmpdu_header *hdr,
 					const void *body, size_t body_len,
 					int rssi, void *user_data)
@@ -4628,16 +4543,23 @@ static bool netdev_ft_work_ready(struct wiphy_radio_work_item *item)
 {
 	struct netdev *netdev = l_container_of(item, struct netdev, work);
 
-	if (!auth_proto_start(netdev->ap)) {
-		/* Restore original nonce */
-		memcpy(netdev->handshake->snonce, netdev->prev_snonce, 32);
+	if (netdev->ft_sm) {
+		if (ft_associate(netdev->ft_sm, netdev->handshake->aa))
+			goto assoc_failed;
 
-		netdev_connect_failed(netdev, NETDEV_RESULT_ABORTED,
-						MMPDU_STATUS_CODE_UNSPECIFIED);
-		return true;
+		return false;
 	}
 
-	return false;
+	if (auth_proto_start(netdev->ap))
+		return false;
+
+assoc_failed:
+	/* Restore original nonce */
+	memcpy(netdev->handshake->snonce, netdev->prev_snonce, 32);
+
+	netdev_connect_failed(netdev, NETDEV_RESULT_ABORTED,
+						MMPDU_STATUS_CODE_UNSPECIFIED);
+	return true;
 }
 
 static const struct wiphy_radio_work_item_ops ft_work_ops = {
@@ -4678,124 +4600,38 @@ int netdev_fast_transition_over_ds(struct netdev *netdev,
 					const struct scan_bss *orig_bss,
 					netdev_connect_cb_t cb)
 {
-	struct netdev_ft_over_ds_info *info;
-	struct ft_ds_finder finder;
-
 	if (!netdev->operational)
 		return -ENOTCONN;
 
-	if (!netdev->handshake->mde || !target_bss->mde_present ||
+	if (!netdev->ft_sm || !netdev->handshake->mde ||
+			!target_bss->mde_present ||
 			l_get_le16(netdev->handshake->mde + 2) !=
 			l_get_le16(target_bss->mde))
 		return -EINVAL;
 
-	finder.spa = netdev->addr;
-	finder.aa = target_bss->addr;
-
-	info = l_queue_find(netdev->ft_ds_list, match_ft_ds_info, &finder);
-
-	if (!info || !info->parsed)
-		return -ENOENT;
-
 	netdev->connect_cb = cb;
 
-	netdev->ap = ft_over_ds_sm_new(netdev->handshake,
-					netdev_ft_tx_associate,
-					netdev);
 	prepare_ft(netdev, target_bss);
 
-	ft_over_ds_prepare_handshake(&info->super, netdev->handshake);
-
 	wiphy_radio_work_insert(netdev->wiphy, &netdev->work,
 				WIPHY_WORK_PRIORITY_CONNECT, &ft_work_ops);
 
 	return 0;
 }
 
-static void netdev_ft_request_cb(struct l_genl_msg *msg, void *user_data)
-{
-	struct netdev_ft_over_ds_info *info = user_data;
-
-	if (l_genl_msg_get_error(msg) < 0) {
-		l_error("Could not send CMD_FRAME for FT-over-DS");
-		netdev_ft_over_ds_auth_failed(info,
-					MMPDU_STATUS_CODE_UNSPECIFIED);
-	}
-}
-
-static void netdev_ft_ds_info_free(struct ft_ds_info *ft)
-{
-	struct netdev_ft_over_ds_info *info = l_container_of(ft,
-					struct netdev_ft_over_ds_info, super);
-
-	l_free(info);
-}
-
 int netdev_fast_transition_over_ds_action(struct netdev *netdev,
 					const struct scan_bss *target_bss)
 {
-	struct netdev_ft_over_ds_info *info;
-	uint8_t ft_req[14];
-	struct handshake_state *hs = netdev->handshake;
-	struct iovec iovs[5];
-	uint8_t buf[512];
-	size_t len;
-
 	if (!netdev->operational)
 		return -ENOTCONN;
 
-	if (!netdev->handshake->mde || !target_bss->mde_present ||
+	if (!netdev->ft_sm || !netdev->handshake->mde ||
+			!target_bss->mde_present ||
 			l_get_le16(netdev->handshake->mde + 2) !=
 			l_get_le16(target_bss->mde))
 		return -EINVAL;
 
-	l_debug("");
-
-	info = l_new(struct netdev_ft_over_ds_info, 1);
-	info->netdev = netdev;
-
-	memcpy(info->super.spa, hs->spa, ETH_ALEN);
-	memcpy(info->super.aa, target_bss->addr, ETH_ALEN);
-	memcpy(info->super.mde, target_bss->mde, sizeof(info->super.mde));
-
-	if (target_bss->rsne)
-		info->super.authenticator_ie = l_memdup(target_bss->rsne,
-						target_bss->rsne[1] + 2);
-
-	l_getrandom(info->super.snonce, 32);
-	info->super.free = netdev_ft_ds_info_free;
-
-	ft_req[0] = 6; /* FT category */
-	ft_req[1] = 1; /* FT Request action */
-	memcpy(ft_req + 2, netdev->addr, 6);
-	memcpy(ft_req + 8, info->super.aa, 6);
-
-	iovs[0].iov_base = ft_req;
-	iovs[0].iov_len = sizeof(ft_req);
-
-	if (!ft_build_authenticate_ies(hs, info->super.snonce, buf, &len))
-		goto failed;
-
-	iovs[1].iov_base = buf;
-	iovs[1].iov_len = len;
-
-	iovs[2].iov_base = NULL;
-
-	if (!netdev->ft_ds_list)
-		netdev->ft_ds_list = l_queue_new();
-
-	l_queue_push_head(netdev->ft_ds_list, info);
-
-	netdev_send_action_framev(netdev, netdev->handshake->aa, iovs, 2,
-					netdev->frequency,
-					netdev_ft_request_cb,
-					info);
-
-	return 0;
-
-failed:
-	l_free(info);
-	return -EIO;
+	return ft_action(netdev->ft_sm, target_bss);
 }
 
 static void netdev_preauth_cb(const uint8_t *pmk, void *user_data)
@@ -5823,7 +5659,6 @@ static void netdev_add_station_frame_watches(struct netdev *netdev)
 	static const uint8_t action_neighbor_report_prefix[2] = { 0x05, 0x05 };
 	static const uint8_t action_sa_query_resp_prefix[2] = { 0x08, 0x01 };
 	static const uint8_t action_sa_query_req_prefix[2] = { 0x08, 0x00 };
-	static const uint8_t action_ft_response_prefix[] =  { 0x06, 0x02 };
 	static const uint8_t action_qos_map_prefix[] = { 0x01, 0x04 };
 	uint64_t wdev = netdev->wdev_id;
 
@@ -5840,10 +5675,6 @@ static void netdev_add_station_frame_watches(struct netdev *netdev)
 			sizeof(action_sa_query_req_prefix),
 			netdev_sa_query_req_frame_event, netdev, NULL);
 
-	frame_watch_add(wdev, 0, 0x00d0, action_ft_response_prefix,
-			sizeof(action_ft_response_prefix),
-			netdev_ft_response_frame_event, netdev, NULL);
-
 	if (wiphy_supports_qos_set_map(netdev->wiphy))
 		frame_watch_add(wdev, 0, 0x00d0, action_qos_map_prefix,
 				sizeof(action_qos_map_prefix),
-- 
2.34.3


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

* [PATCH v2 7/9] ft: implement offchannel authentication
  2022-08-24 22:55 [PATCH v2 1/9] frame-xchg: add type to frame_xchg_prefix James Prestwood
                   ` (4 preceding siblings ...)
  2022-08-24 22:55 ` [PATCH v2 6/9] netdev: use new ft_sm for over-DS James Prestwood
@ 2022-08-24 22:55 ` James Prestwood
  2022-08-24 22:55 ` [PATCH v2 8/9] netdev: update FT-over-Air to use ft_authenticate() James Prestwood
  2022-08-24 22:55 ` [PATCH v2 9/9] ft: remove unused code after refactor James Prestwood
  7 siblings, 0 replies; 9+ messages in thread
From: James Prestwood @ 2022-08-24 22:55 UTC (permalink / raw
  To: iwd; +Cc: James Prestwood

A new API was added, ft_authenticate, which will send an
authentication frame offchannel via CMD_FRAME. This bypasses
the kernel's authentication state allowing multiple auth
attempts to take place without disconnecting.
---
 src/ft.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/ft.h |   5 +++
 2 files changed, 137 insertions(+)

diff --git a/src/ft.c b/src/ft.c
index 2c9c92e6..ce57020b 100644
--- a/src/ft.c
+++ b/src/ft.c
@@ -50,6 +50,7 @@ struct ft_info {
 	uint8_t mde[3];
 	uint8_t *fte;
 	uint8_t *authenticator_ie;
+	uint32_t frequency;
 
 	struct ie_ft_info ft_info;
 
@@ -69,6 +70,7 @@ struct ft_sm {
 	ft_tx_associate_func_t tx_assoc;
 	ft_get_oci get_oci;
 
+	ft_authenticate_cb_t auth_cb;
 	void *user_data;
 
 	bool over_ds : 1;
@@ -1082,6 +1084,8 @@ static struct ft_info *ft_info_new(struct handshake_state *hs,
 	memcpy(info->aa, target_bss->addr, 6);
 	memcpy(info->mde, target_bss->mde, sizeof(info->mde));
 
+	info->frequency = target_bss->frequency;
+
 	if (target_bss->rsne)
 		info->authenticator_ie = l_memdup(target_bss->rsne,
 						target_bss->rsne[1] + 2);
@@ -1199,6 +1203,134 @@ failed:
 	return ret;
 }
 
+static void ft_authenticate_cb(int err, void *user_data)
+{
+	if (err < 0)
+		l_debug("Failed to send FT-Authenticate");
+}
+
+static void ft_authenticate_destroy(void *user_data)
+{
+	struct ft_sm *sm = user_data;
+	struct ft_info *info = l_queue_peek_head(sm->ft_auths);
+
+	if (L_WARN_ON(!info))
+		return;
+
+	if (!info->parsed)
+		goto failed;
+
+	sm->auth_cb(0, info->aa, info->frequency, sm->user_data);
+
+	return;
+
+failed:
+	l_queue_pop_head(sm->ft_auths);
+	ft_info_destroy(info);
+
+	sm->auth_cb(-EINVAL, info->aa, info->frequency, sm->user_data);
+}
+
+static void ft_authenticate_response_cb(const struct mmpdu_header *hdr,
+					const void *body, size_t body_len,
+					int rssi, void *user_data)
+{
+	struct ft_sm *sm = user_data;
+	struct ft_info *info = l_queue_peek_head(sm->ft_auths);
+	uint16_t status;
+	const uint8_t *ies;
+	size_t ies_len;
+
+	if (!ft_parse_authentication_resp_frame((const uint8_t *)hdr,
+					mmpdu_header_len(hdr) + body_len,
+					info->spa, info->aa, info->aa, 2,
+					&status, &ies, &ies_len))
+		return;
+
+	if (status != 0)
+		return;
+
+	if (!ft_parse_ies(info, sm->hs, ies, ies_len))
+		return;
+
+	info->parsed = true;
+
+	return;
+}
+
+static const struct frame_xchg_prefix ft_prefix = {
+	.frame_type = 0x0000 | (MPDU_MANAGEMENT_SUBTYPE_AUTHENTICATION << 4),
+	.data = (uint8_t []) { 0x02, 0x00 },
+	.len = 2,
+};
+
+static bool ft_send_authenticate(struct ft_sm *sm, struct ft_info *info)
+{
+	uint64_t wdev_id = netdev_get_wdev_id(netdev_find(sm->hs->ifindex));
+	uint8_t header[28 + sizeof(struct mmpdu_authentication)];
+	uint8_t ies[256];
+	size_t len;
+	struct iovec iov[3];
+	struct mmpdu_header *mpdu = (struct mmpdu_header *) header;
+	struct mmpdu_authentication *auth;
+	struct handshake_state *hs = sm->hs;
+
+	memset(mpdu, 0, sizeof(*mpdu));
+
+	/* Header */
+	mpdu->fc.protocol_version = 0;
+	mpdu->fc.type = MPDU_TYPE_MANAGEMENT;
+	mpdu->fc.subtype = MPDU_MANAGEMENT_SUBTYPE_AUTHENTICATION;
+	memcpy(mpdu->address_1, info->aa, 6);
+	memcpy(mpdu->address_2, info->spa, 6);
+	memcpy(mpdu->address_3, info->aa, 6);
+
+	/* Authentication body */
+	auth = (void *) mmpdu_body(mpdu);
+	auth->algorithm = L_CPU_TO_LE16(MMPDU_AUTH_ALGO_FT);
+	auth->transaction_sequence = L_CPU_TO_LE16(1);
+	auth->status = L_CPU_TO_LE16(0);
+
+	iov[0].iov_base = mpdu;
+	iov[0].iov_len = mmpdu_header_len(mpdu) +
+				sizeof(struct mmpdu_authentication);
+
+	if (!ft_build_authenticate_ies(hs, info->snonce, ies, &len))
+		return false;
+
+	iov[1].iov_base = ies;
+	iov[1].iov_len = len;
+
+	iov[2].iov_base = NULL;
+
+	return frame_xchg_start(wdev_id, iov, info->frequency, FRAME_GROUP_FT,
+				100, 0, 0,
+				ft_authenticate_cb, sm,
+				ft_authenticate_destroy, &ft_prefix,
+				ft_authenticate_response_cb, NULL) != 0;
+}
+
+int ft_authenticate(struct ft_sm *sm, const struct scan_bss *target,
+			ft_authenticate_cb_t cb, void *user_data)
+{
+	struct ft_info *info = ft_info_new(sm->hs, target);
+	int ret = -EINVAL;
+
+	if (!ft_send_authenticate(sm, info))
+		goto failed;
+
+	sm->auth_cb = cb;
+	sm->user_data = user_data;
+
+	l_queue_push_tail(sm->ft_auths, info);
+
+	return 0;
+
+failed:
+	l_free(info);
+	return ret;
+}
+
 int ft_associate(struct ft_sm *sm, const uint8_t *addr)
 {
 	struct ft_info *info;
diff --git a/src/ft.h b/src/ft.h
index 6e0f4271..9839128a 100644
--- a/src/ft.h
+++ b/src/ft.h
@@ -35,6 +35,9 @@ typedef int (*ft_get_oci)(void *user_data);
 
 typedef void (*ft_ds_free_func_t)(void *user_data);
 
+typedef void (*ft_authenticate_cb_t)(int err, const uint8_t *addr,
+					uint32_t freq, void *user_data);
+
 struct ft_ds_info {
 	uint8_t spa[6];
 	uint8_t aa[6];
@@ -87,3 +90,5 @@ void ft_sm_free(struct ft_sm *sm);
 
 int ft_action(struct ft_sm *sm, const struct scan_bss *target);
 int ft_associate(struct ft_sm *sm, const uint8_t *addr);
+int ft_authenticate(struct ft_sm *sm, const struct scan_bss *target,
+			ft_authenticate_cb_t cb, void *user_data);
-- 
2.34.3


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

* [PATCH v2 8/9] netdev: update FT-over-Air to use ft_authenticate()
  2022-08-24 22:55 [PATCH v2 1/9] frame-xchg: add type to frame_xchg_prefix James Prestwood
                   ` (5 preceding siblings ...)
  2022-08-24 22:55 ` [PATCH v2 7/9] ft: implement offchannel authentication James Prestwood
@ 2022-08-24 22:55 ` James Prestwood
  2022-08-24 22:55 ` [PATCH v2 9/9] ft: remove unused code after refactor James Prestwood
  7 siblings, 0 replies; 9+ messages in thread
From: James Prestwood @ 2022-08-24 22:55 UTC (permalink / raw
  To: iwd; +Cc: James Prestwood

This removes the FT auth-proto entirely from FT-over-Air, and
instead requires using ft_authenticate/ft_associate along with
the new ft_sm state machine.

The authentication phase is now done off-channel which allows
failures to be non-fatal (eventually). Currently the behavior
isn't changed, and failing to authenticate to a BSS will result
in a disconnect.
---
 src/ft.c     |   6 +++
 src/netdev.c | 113 +++++++++++++++++----------------------------------
 2 files changed, 44 insertions(+), 75 deletions(-)

diff --git a/src/ft.c b/src/ft.c
index ce57020b..47e98c05 100644
--- a/src/ft.c
+++ b/src/ft.c
@@ -1114,6 +1114,12 @@ static void ft_prepare_handshake(struct ft_info *info,
 	if (!hs->supplicant_ie)
 		return;
 
+	if (info->authenticator_ie)
+		handshake_state_set_authenticator_ie(hs,
+						info->authenticator_ie);
+
+	memcpy(hs->mde + 2, info->mde, 3);
+
 	memcpy(hs->snonce, info->snonce, sizeof(hs->snonce));
 
 	handshake_state_set_fte(hs, info->fte);
diff --git a/src/netdev.c b/src/netdev.c
index 334e10ab..5bd2954f 100644
--- a/src/netdev.c
+++ b/src/netdev.c
@@ -1395,8 +1395,7 @@ static void netdev_connect_ok(struct netdev *netdev)
 		netdev->fw_roam_bss = NULL;
 	}
 
-	/* TODO: Create only for over-DS. Over-air still uses auth-proto */
-	if (netdev->handshake->mde && (netdev->handshake->mde[4] & 1)) {
+	if (netdev->handshake->mde) {
 		if (netdev->ft_sm)
 			ft_sm_free(netdev->ft_sm);
 
@@ -4369,48 +4368,6 @@ static int netdev_tx_ft_action_frame(uint32_t ifindex, const uint8_t *dest,
 	return 0;
 }
 
-static void netdev_cmd_authenticate_ft_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)
-		netdev_connect_failed(netdev,
-					NETDEV_RESULT_AUTHENTICATION_FAILED,
-					MMPDU_STATUS_CODE_UNSPECIFIED);
-}
-
-static void netdev_ft_tx_authenticate(struct iovec *iov,
-					size_t iov_len, void *user_data)
-{
-	struct netdev *netdev = user_data;
-	struct l_genl_msg *cmd_authenticate;
-
-	cmd_authenticate = netdev_build_cmd_authenticate(netdev,
-							NL80211_AUTHTYPE_FT);
-	l_genl_msg_append_attrv(cmd_authenticate, NL80211_ATTR_IE, iov,
-					iov_len);
-
-	netdev->connect_cmd_id = l_genl_family_send(nl80211,
-						cmd_authenticate,
-						netdev_cmd_authenticate_ft_cb,
-						netdev, NULL);
-	if (!netdev->connect_cmd_id) {
-		l_genl_msg_unref(cmd_authenticate);
-		goto restore_snonce;
-	}
-
-	return;
-
-restore_snonce:
-	memcpy(netdev->handshake->snonce, netdev->prev_snonce, 32);
-
-	netdev_connect_failed(netdev, NETDEV_RESULT_AUTHENTICATION_FAILED,
-					MMPDU_STATUS_CODE_UNSPECIFIED);
-}
-
 static int netdev_ft_tx_associate(uint32_t ifindex, const uint8_t *prev_bssid,
 					struct iovec *ft_iov, size_t n_ft_iov)
 {
@@ -4450,7 +4407,8 @@ static int netdev_ft_tx_associate(uint32_t ifindex, const uint8_t *prev_bssid,
 	return 0;
 }
 
-static void prepare_ft(struct netdev *netdev, const struct scan_bss *target_bss)
+static void prepare_ft(struct netdev *netdev, const uint8_t *addr,
+			uint32_t frequency)
 {
 	struct netdev_handshake_state *nhs;
 
@@ -4461,15 +4419,9 @@ static void prepare_ft(struct netdev *netdev, const struct scan_bss *target_bss)
 	 */
 	memcpy(netdev->prev_snonce, netdev->handshake->snonce, 32);
 
-	netdev->frequency = target_bss->frequency;
-
-	handshake_state_set_authenticator_address(netdev->handshake,
-							target_bss->addr);
+	handshake_state_set_authenticator_address(netdev->handshake, addr);
 
-	if (target_bss->rsne)
-		handshake_state_set_authenticator_ie(netdev->handshake,
-							target_bss->rsne);
-	memcpy(netdev->handshake->mde + 2, target_bss->mde, 3);
+	netdev->frequency = frequency;
 
 	netdev->handshake->active_tk_index = 0;
 	netdev->associated = false;
@@ -4543,15 +4495,10 @@ static bool netdev_ft_work_ready(struct wiphy_radio_work_item *item)
 {
 	struct netdev *netdev = l_container_of(item, struct netdev, work);
 
-	if (netdev->ft_sm) {
-		if (ft_associate(netdev->ft_sm, netdev->handshake->aa))
-			goto assoc_failed;
-
-		return false;
-	}
+	if (ft_associate(netdev->ft_sm, netdev->handshake->aa))
+		goto assoc_failed;
 
-	if (auth_proto_start(netdev->ap))
-		return false;
+	return false;
 
 assoc_failed:
 	/* Restore original nonce */
@@ -4566,6 +4513,27 @@ static const struct wiphy_radio_work_item_ops ft_work_ops = {
 	.do_work = netdev_ft_work_ready,
 };
 
+static void netdev_ft_authenticate_cb(int err, const uint8_t *addr,
+					uint32_t frequency,
+					void *user_data)
+{
+	struct netdev *netdev = user_data;
+
+	if (err < 0)
+		goto ft_failed;
+
+	prepare_ft(netdev, addr, frequency);
+
+	wiphy_radio_work_insert(netdev->wiphy, &netdev->work,
+				WIPHY_WORK_PRIORITY_CONNECT, &ft_work_ops);
+
+	return;
+
+ft_failed:
+	netdev_connect_failed(netdev, NETDEV_RESULT_AUTHENTICATION_FAILED,
+					MMPDU_STATUS_CODE_UNSPECIFIED);
+}
+
 int netdev_fast_transition(struct netdev *netdev,
 				const struct scan_bss *target_bss,
 				const struct scan_bss *orig_bss,
@@ -4574,25 +4542,20 @@ int netdev_fast_transition(struct netdev *netdev,
 	if (!netdev->operational)
 		return -ENOTCONN;
 
-	if (!netdev->handshake->mde || !target_bss->mde_present ||
+	if (!netdev->ft_sm || !netdev->handshake->mde ||
+			!target_bss->mde_present ||
 			l_get_le16(netdev->handshake->mde + 2) !=
 			l_get_le16(target_bss->mde))
 		return -EINVAL;
 
 	netdev->connect_cb = cb;
 
-	netdev->ap = ft_over_air_sm_new(netdev->handshake,
-					netdev_ft_tx_authenticate,
-					netdev_ft_tx_associate,
-					netdev_get_oci, netdev);
-	prepare_ft(netdev, target_bss);
-
-	handshake_state_new_snonce(netdev->handshake);
-
-	wiphy_radio_work_insert(netdev->wiphy, &netdev->work,
-				WIPHY_WORK_PRIORITY_CONNECT, &ft_work_ops);
-
-	return 0;
+	/*
+	 * ft_authenticate uses offchannel so we cant start a wiphy work item
+	 * until that completes
+	 */
+	return ft_authenticate(netdev->ft_sm, target_bss,
+				netdev_ft_authenticate_cb, netdev);
 }
 
 int netdev_fast_transition_over_ds(struct netdev *netdev,
@@ -4611,7 +4574,7 @@ int netdev_fast_transition_over_ds(struct netdev *netdev,
 
 	netdev->connect_cb = cb;
 
-	prepare_ft(netdev, target_bss);
+	prepare_ft(netdev, target_bss->addr, target_bss->frequency);
 
 	wiphy_radio_work_insert(netdev->wiphy, &netdev->work,
 				WIPHY_WORK_PRIORITY_CONNECT, &ft_work_ops);
-- 
2.34.3


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

* [PATCH v2 9/9] ft: remove unused code after refactor
  2022-08-24 22:55 [PATCH v2 1/9] frame-xchg: add type to frame_xchg_prefix James Prestwood
                   ` (6 preceding siblings ...)
  2022-08-24 22:55 ` [PATCH v2 8/9] netdev: update FT-over-Air to use ft_authenticate() James Prestwood
@ 2022-08-24 22:55 ` James Prestwood
  7 siblings, 0 replies; 9+ messages in thread
From: James Prestwood @ 2022-08-24 22:55 UTC (permalink / raw
  To: iwd; +Cc: James Prestwood

Removes unused code as well as makes a few functions static which
are no longer used externally.
---
 src/ft.c | 254 ++-----------------------------------------------------
 src/ft.h |  47 ----------
 2 files changed, 5 insertions(+), 296 deletions(-)

diff --git a/src/ft.c b/src/ft.c
index 47e98c05..32d7ee27 100644
--- a/src/ft.c
+++ b/src/ft.c
@@ -24,6 +24,8 @@
 #include <config.h>
 #endif
 
+#include <errno.h>
+
 #include <ell/ell.h>
 
 #include "src/ie.h"
@@ -31,8 +33,6 @@
 #include "src/crypto.h"
 #include "src/ft.h"
 #include "src/mpdu.h"
-#include "src/auth-proto.h"
-#include "src/band.h"
 #include "src/scan.h"
 #include "src/frame-xchg.h"
 #include "src/util.h"
@@ -63,13 +63,8 @@ struct ft_info_finder {
 };
 
 struct ft_sm {
-	struct auth_proto ap;
 	struct handshake_state *hs;
 
-	ft_tx_authenticate_func_t tx_auth;
-	ft_tx_associate_func_t tx_assoc;
-	ft_get_oci get_oci;
-
 	ft_authenticate_cb_t auth_cb;
 	void *user_data;
 
@@ -496,79 +491,8 @@ static bool mde_equal(const uint8_t *mde1, const uint8_t *mde2)
 	return memcmp(mde1, mde1, mde1[1] + 2) == 0;
 }
 
-bool ft_over_ds_parse_action_ies(struct ft_ds_info *info,
-					struct handshake_state *hs,
-					const uint8_t *ies,
-					size_t ies_len)
-{
-	const uint8_t *mde = NULL;
-	const uint8_t *fte = NULL;
-	bool is_rsn = hs->supplicant_ie != NULL;
-
-	if (parse_ies(hs, info->authenticator_ie, ies, ies_len,
-				&mde, &fte) < 0)
-		return false;
-
-	if (!mde_equal(info->mde, mde))
-		goto ft_error;
-
-	if (is_rsn) {
-		if (!ft_parse_fte(hs, info->snonce, fte, &info->ft_info))
-			goto ft_error;
-
-		info->fte = l_memdup(fte, fte[1] + 2);
-	} else if (fte)
-		goto ft_error;
-
-	return true;
-
-ft_error:
-	return false;
-}
-
-static int ft_process_ies(struct handshake_state *hs, const uint8_t *ies,
-			size_t ies_len)
-{
-	const uint8_t *mde = NULL;
-	const uint8_t *fte = NULL;
-	bool is_rsn = hs->supplicant_ie != NULL;
-
-	/* Check 802.11r IEs */
-	if (!ies)
-		goto ft_error;
-
-	if (parse_ies(hs, hs->authenticator_ie, ies, ies_len,
-				&mde, &fte) < 0)
-		goto ft_error;
-
-	if (!mde_equal(hs->mde, mde))
-		goto ft_error;
-
-	if (is_rsn) {
-		struct ie_ft_info ft_info;
-
-		if (!ft_parse_fte(hs, hs->snonce, fte, &ft_info))
-			goto ft_error;
-
-		handshake_state_set_fte(hs, fte);
-
-		handshake_state_set_anonce(hs, ft_info.anonce);
-
-		handshake_state_set_kh_ids(hs, ft_info.r0khid,
-						ft_info.r0khid_len,
-						ft_info.r1khid);
-
-		handshake_state_derive_ptk(hs);
-	} else if (fte)
-		goto ft_error;
-
-	return 0;
-
-ft_error:
-	return -EBADMSG;
-}
-
-int ft_over_ds_parse_action_response(const uint8_t *frame, size_t frame_len,
+static int ft_over_ds_parse_action_response(const uint8_t *frame,
+					size_t frame_len,
 					const uint8_t **spa_out,
 					const uint8_t **aa_out,
 					const uint8_t **ies_out,
@@ -610,75 +534,6 @@ int ft_over_ds_parse_action_response(const uint8_t *frame, size_t frame_len,
 	return 0;
 }
 
-bool ft_over_ds_prepare_handshake(struct ft_ds_info *info,
-					struct handshake_state *hs)
-{
-	if (!hs->supplicant_ie)
-		return true;
-
-	memcpy(hs->snonce, info->snonce, sizeof(hs->snonce));
-
-	handshake_state_set_fte(hs, info->fte);
-
-	handshake_state_set_anonce(hs, info->ft_info.anonce);
-
-	handshake_state_set_kh_ids(hs, info->ft_info.r0khid,
-						info->ft_info.r0khid_len,
-						info->ft_info.r1khid);
-
-	handshake_state_derive_ptk(hs);
-
-	return true;
-}
-
-void ft_ds_info_free(struct ft_ds_info *info)
-{
-	__typeof__(info->free) destroy = info->free;
-
-	if (info->fte)
-		l_free(info->fte);
-
-	if (info->authenticator_ie)
-		l_free(info->authenticator_ie);
-
-	if (destroy)
-		destroy(info);
-}
-
-static int ft_rx_authenticate(struct auth_proto *ap, const uint8_t *frame,
-				size_t frame_len)
-{
-	struct ft_sm *ft = l_container_of(ap, struct ft_sm, ap);
-	uint16_t status_code = MMPDU_STATUS_CODE_UNSPECIFIED;
-	const uint8_t *ies = NULL;
-	size_t ies_len;
-	int ret;
-
-	/*
-	 * Parse the Authentication Response and validate the contents
-	 * according to 12.5.2 / 12.5.4: RSN or non-RSN Over-the-air
-	 * FT Protocol.
-	 */
-	if (!ft_parse_authentication_resp_frame(frame, frame_len, ft->hs->spa,
-						ft->hs->aa, ft->hs->aa,
-						2, &status_code,
-						&ies, &ies_len))
-		goto auth_error;
-
-	/* AP Rejected the authenticate / associate */
-	if (status_code != 0)
-		goto auth_error;
-
-	ret = ft_process_ies(ft->hs, ies, ies_len);
-	if (ret < 0)
-		goto auth_error;
-
-	return ft->get_oci(ft->user_data);
-
-auth_error:
-	return (int)status_code;
-}
-
 int __ft_rx_associate(uint32_t ifindex, const uint8_t *frame, size_t frame_len)
 {
 	struct ft_sm *ft = ft_sm_find(ifindex);
@@ -818,38 +673,7 @@ int __ft_rx_associate(uint32_t ifindex, const uint8_t *frame, size_t frame_len)
 	return 0;
 }
 
-static int ft_rx_associate(struct auth_proto *ap, const uint8_t *frame,
-				size_t frame_len)
-{
-	struct ft_sm *sm = l_container_of(ap, struct ft_sm, ap);
-
-	return __ft_rx_associate(sm->hs->ifindex, frame, frame_len);
-}
-
-static int ft_rx_oci(struct auth_proto *ap)
-{
-	struct ft_sm *ft = l_container_of(ap, struct ft_sm, ap);
-
-	return ft_tx_reassociate(ft);
-}
-
-static void ft_auth_proto_free(struct auth_proto *ap)
-{
-	struct ft_sm *ft = l_container_of(ap, struct ft_sm, ap);
-
-	l_queue_remove(sm_list, ft);
-
-	l_free(ft);
-}
-
-static bool ft_over_ds_start(struct auth_proto *ap)
-{
-	struct ft_sm *ft = l_container_of(ap, struct ft_sm, ap);
-
-	return ft_tx_reassociate(ft) == 0;
-}
-
-bool ft_build_authenticate_ies(struct handshake_state *hs,
+static bool ft_build_authenticate_ies(struct handshake_state *hs,
 				const uint8_t *new_snonce, uint8_t *buf,
 				size_t *len)
 {
@@ -920,74 +744,6 @@ bool ft_build_authenticate_ies(struct handshake_state *hs,
 	return true;
 }
 
-static bool ft_start(struct auth_proto *ap)
-{
-	struct ft_sm *ft = l_container_of(ap, struct ft_sm, ap);
-	struct handshake_state *hs = ft->hs;
-	struct iovec iov;
-	uint8_t buf[512];
-	size_t len;
-
-	if (!ft_build_authenticate_ies(hs, hs->snonce, buf, &len))
-		return false;
-
-	iov.iov_base = buf;
-	iov.iov_len = len;
-
-	ft->tx_auth(&iov, 1, ft->user_data);
-
-	return true;
-}
-
-struct auth_proto *ft_over_air_sm_new(struct handshake_state *hs,
-				ft_tx_authenticate_func_t tx_auth,
-				ft_tx_associate_func_t tx_assoc,
-				ft_get_oci get_oci,
-				void *user_data)
-{
-	struct ft_sm *ft = l_new(struct ft_sm, 1);
-
-	ft->tx_auth = tx_auth;
-	ft->tx_assoc = tx_assoc;
-	ft->get_oci = get_oci;
-	ft->hs = hs;
-	ft->user_data = user_data;
-
-	ft->ap.rx_authenticate = ft_rx_authenticate;
-	ft->ap.rx_associate = ft_rx_associate;
-	ft->ap.start = ft_start;
-	ft->ap.free = ft_auth_proto_free;
-	ft->ap.rx_oci = ft_rx_oci;
-
-	memcpy(ft->prev_bssid, hs->aa, 6);
-
-	l_queue_push_tail(sm_list, ft);
-
-	return &ft->ap;
-}
-
-struct auth_proto *ft_over_ds_sm_new(struct handshake_state *hs,
-				ft_tx_associate_func_t tx_assoc,
-				void *user_data)
-{
-	struct ft_sm *ft = l_new(struct ft_sm, 1);
-
-	ft->tx_assoc = tx_assoc;
-	ft->hs = hs;
-	ft->user_data = user_data;
-	ft->over_ds = true;
-
-	ft->ap.rx_associate = ft_rx_associate;
-	ft->ap.start = ft_over_ds_start;
-	ft->ap.free = ft_auth_proto_free;
-
-	memcpy(ft->prev_bssid, hs->aa, 6);
-
-	l_queue_push_tail(sm_list, ft);
-
-	return &ft->ap;
-}
-
 void __ft_set_tx_action_func(ft_tx_action_func_t func)
 {
 	tx_action = func;
diff --git a/src/ft.h b/src/ft.h
index 9839128a..1a18cd0e 100644
--- a/src/ft.h
+++ b/src/ft.h
@@ -26,60 +26,13 @@ struct scan_bss;
 typedef int (*ft_tx_action_func_t)(uint32_t ifindex, const uint8_t *dest,
 					struct iovec *iov, size_t iov_len);
 
-typedef void (*ft_tx_authenticate_func_t)(struct iovec *iov, size_t iov_len,
-					void *user_data);
 typedef int (*ft_tx_associate_func_t)(uint32_t ifindex,
 					const uint8_t *prev_bssid,
 					struct iovec *ie_iov, size_t iov_len);
-typedef int (*ft_get_oci)(void *user_data);
-
-typedef void (*ft_ds_free_func_t)(void *user_data);
 
 typedef void (*ft_authenticate_cb_t)(int err, const uint8_t *addr,
 					uint32_t freq, void *user_data);
 
-struct ft_ds_info {
-	uint8_t spa[6];
-	uint8_t aa[6];
-	uint8_t snonce[32];
-	uint8_t mde[3];
-	uint8_t *fte;
-	uint8_t *authenticator_ie;
-
-	struct ie_ft_info ft_info;
-
-	void (*free)(struct ft_ds_info *s);
-};
-
-void ft_ds_info_free(struct ft_ds_info *info);
-
-bool ft_build_authenticate_ies(struct handshake_state *hs,
-				const uint8_t *new_snonce, uint8_t *buf,
-				size_t *len);
-
-int ft_over_ds_parse_action_response(const uint8_t *frame, size_t frame_len,
-					const uint8_t **spa_out,
-					const uint8_t **aa_out,
-					const uint8_t **ies_out,
-					size_t *ies_len);
-bool ft_over_ds_parse_action_ies(struct ft_ds_info *info,
-					struct handshake_state *hs,
-					const uint8_t *ies,
-					size_t ies_len);
-
-struct auth_proto *ft_over_air_sm_new(struct handshake_state *hs,
-				ft_tx_authenticate_func_t tx_auth,
-				ft_tx_associate_func_t tx_assoc,
-				ft_get_oci get_oci,
-				void *user_data);
-
-struct auth_proto *ft_over_ds_sm_new(struct handshake_state *hs,
-				ft_tx_associate_func_t tx_assoc,
-				void *user_data);
-
-bool ft_over_ds_prepare_handshake(struct ft_ds_info *info,
-					struct handshake_state *hs);
-
 void __ft_set_tx_action_func(ft_tx_action_func_t func);
 void __ft_set_tx_associate_func(ft_tx_associate_func_t func);
 int __ft_rx_associate(uint32_t ifindex, const uint8_t *frame,
-- 
2.34.3


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

end of thread, other threads:[~2022-08-24 22:55 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-08-24 22:55 [PATCH v2 1/9] frame-xchg: add type to frame_xchg_prefix James Prestwood
2022-08-24 22:55 ` [PATCH v2 2/9] station: don't set OCVC for FT AKMs James Prestwood
2022-08-24 22:55 ` [PATCH v2 3/9] ft: remove OCI element from auth/assoc James Prestwood
2022-08-24 22:55 ` [PATCH v2 4/9] frame-xchg: create global group enum James Prestwood
2022-08-24 22:55 ` [PATCH v2 5/9] ft: netdev: prep for FT isolation into ft.c James Prestwood
2022-08-24 22:55 ` [PATCH v2 6/9] netdev: use new ft_sm for over-DS James Prestwood
2022-08-24 22:55 ` [PATCH v2 7/9] ft: implement offchannel authentication James Prestwood
2022-08-24 22:55 ` [PATCH v2 8/9] netdev: update FT-over-Air to use ft_authenticate() James Prestwood
2022-08-24 22:55 ` [PATCH v2 9/9] ft: remove unused code after refactor James Prestwood

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.