All of lore.kernel.org
 help / color / mirror / Atom feed
From: James Prestwood <prestwoj@gmail.com>
To: iwd@lists.linux.dev
Cc: James Prestwood <prestwoj@gmail.com>
Subject: [PATCH v3 06/14] netdev: use new ft_sm for over-DS
Date: Thu, 15 Sep 2022 15:07:33 -0700	[thread overview]
Message-ID: <20220915220741.1128728-6-prestwoj@gmail.com> (raw)
In-Reply-To: <20220915220741.1128728-1-prestwoj@gmail.com>

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 03b384bb..2519feda 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);
@@ -4533,81 +4523,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)
@@ -4634,16 +4549,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 = {
@@ -4684,124 +4606,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)
@@ -5829,7 +5665,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;
 
@@ -5846,10 +5681,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


  parent reply	other threads:[~2022-09-15 22:07 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-09-15 22:07 [PATCH v3 01/14] frame-xchg: add type to frame_xchg_prefix James Prestwood
2022-09-15 22:07 ` [PATCH v3 02/14] station: don't set OCVC for FT AKMs James Prestwood
2022-09-15 22:07 ` [PATCH v3 03/14] ft: remove OCI element from auth/assoc James Prestwood
2022-09-16 16:05   ` Denis Kenzior
2022-09-16 16:18     ` James Prestwood
2022-09-15 22:07 ` [PATCH v3 04/14] frame-xchg: create global group enum James Prestwood
2022-09-16 16:06   ` Denis Kenzior
2022-09-16 16:28     ` James Prestwood
2022-09-15 22:07 ` [PATCH v3 05/14] ft: netdev: prep for FT isolation into ft.c James Prestwood
2022-09-15 22:07 ` James Prestwood [this message]
2022-09-15 22:07 ` [PATCH v3 07/14] ft: implement offchannel authentication James Prestwood
2022-09-15 22:07 ` [PATCH v3 08/14] netdev: update FT-over-Air to use ft_authenticate() James Prestwood
2022-09-15 22:07 ` [PATCH v3 09/14] ft: remove unused code after refactor James Prestwood
2022-09-15 22:07 ` [PATCH v3 10/14] ft: add ft_sm_can_associate James Prestwood
2022-09-15 22:07 ` [PATCH v3 11/14] netdev: check for authentication for FT-over-DS James Prestwood
2022-09-15 22:07 ` [PATCH v3 12/14] station: create list of roam candidates James Prestwood
2022-09-15 22:07 ` [PATCH v3 13/14] station: try multiple " James Prestwood
2022-09-15 22:07 ` [PATCH v3 14/14] netdev: add NETDEV_EVENT_FT_AUTHENTICATE, handle in station James Prestwood
2022-09-16 16:04 ` [PATCH v3 01/14] frame-xchg: add type to frame_xchg_prefix Denis Kenzior

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220915220741.1128728-6-prestwoj@gmail.com \
    --to=prestwoj@gmail.com \
    --cc=iwd@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.