All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 1/3] eapol: add PMK installer support
@ 2021-04-09 16:14 James Prestwood
  2021-04-09 16:14 ` [PATCH v2 2/3] netdev: add CONNECTION_TYPE_8021X_OFFLOAD James Prestwood
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: James Prestwood @ 2021-04-09 16:14 UTC (permalink / raw)
  To: iwd

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

802.1x offloading needs a way to call SET_PMK after EAP finishes.
In the same manor as set_tk/gtk/igtk a new 'install_pmk' function
was added which eapol can call into after EAP completes.
---
 src/eapol.c | 10 ++++++++++
 src/eapol.h |  5 +++++
 2 files changed, 15 insertions(+)

diff --git a/src/eapol.c b/src/eapol.c
index 23aaf530..3823f854 100644
--- a/src/eapol.c
+++ b/src/eapol.c
@@ -52,6 +52,7 @@ static uint32_t eapol_4way_handshake_time = 2;
 static eapol_rekey_offload_func_t rekey_offload = NULL;
 
 static eapol_tx_packet_func_t tx_packet = NULL;
+static eapol_install_pmk_func_t install_pmk = NULL;
 static void *tx_user_data;
 
 #define VERIFY_IS_ZERO(field)						\
@@ -2162,6 +2163,10 @@ static void eapol_eap_complete_cb(enum eap_result result, void *user_data)
 		sm->eap = NULL;
 		handshake_failed(sm, MMPDU_REASON_CODE_IEEE8021X_FAILED);
 		return;
+	} else {
+		if (install_pmk)
+			install_pmk(sm->handshake, sm->handshake->pmk,
+					sm->handshake->pmk_len);
 	}
 
 	eap_reset(sm->eap);
@@ -2470,6 +2475,11 @@ void __eapol_set_rekey_offload_func(eapol_rekey_offload_func_t func)
 	rekey_offload = func;
 }
 
+void __eapol_set_install_pmk_func(eapol_install_pmk_func_t func)
+{
+	install_pmk = func;
+}
+
 void eapol_register(struct eapol_sm *sm)
 {
 	eapol_frame_watch_func_t rx_handler = sm->handshake->authenticator ?
diff --git a/src/eapol.h b/src/eapol.h
index 0f9a6917..a948c018 100644
--- a/src/eapol.h
+++ b/src/eapol.h
@@ -51,6 +51,9 @@ typedef void (*eapol_frame_watch_func_t)(uint16_t proto, const uint8_t *from,
 						const struct eapol_frame *frame,
 						bool noencrypt,
 						void *user_data);
+typedef void (*eapol_install_pmk_func_t)(struct handshake_state *hs,
+						const uint8_t *pmk,
+						size_t pmk_len);
 
 bool eapol_calculate_mic(enum ie_rsn_akm_suite akm, const uint8_t *kck,
 				const struct eapol_key *frame, uint8_t *mic,
@@ -102,6 +105,8 @@ void __eapol_tx_packet(uint32_t ifindex, const uint8_t *dst, uint16_t proto,
 void __eapol_set_tx_packet_func(eapol_tx_packet_func_t func);
 void __eapol_set_tx_user_data(void *user_data);
 
+void __eapol_set_install_pmk_func(eapol_install_pmk_func_t func);
+
 void __eapol_set_rekey_offload_func(eapol_rekey_offload_func_t func);
 void __eapol_update_replay_counter(uint32_t ifindex, const uint8_t *spa,
 				const uint8_t *aa, uint64_t replay_counter);
-- 
2.26.2

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

* [PATCH v2 2/3] netdev: add CONNECTION_TYPE_8021X_OFFLOAD
  2021-04-09 16:14 [PATCH v2 1/3] eapol: add PMK installer support James Prestwood
@ 2021-04-09 16:14 ` James Prestwood
  2021-04-09 16:14 ` [PATCH v2 3/3] netdev: implement netdev_set_pmk James Prestwood
  2021-04-09 16:34 ` [PATCH v2 1/3] eapol: add PMK installer support Denis Kenzior
  2 siblings, 0 replies; 4+ messages in thread
From: James Prestwood @ 2021-04-09 16:14 UTC (permalink / raw)
  To: iwd

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

This adds a new type for 8021x offload as well as support in
building CMD_CONNECT.

As described in the comment, 8021x offloading is not particularly
similar to PSK as far as the code flow in IWD is concerned. There
still needs to be an eapol_sm due to EAP being done in userspace.
This throws somewhat of a wrench into our 'is_offload' cases. And
as such this connection type is handled specially.
---
 src/netdev.c | 32 ++++++++++++++++++++++++++++++--
 1 file changed, 30 insertions(+), 2 deletions(-)

diff --git a/src/netdev.c b/src/netdev.c
index d8703ed2..f41cd2c9 100644
--- a/src/netdev.c
+++ b/src/netdev.c
@@ -72,6 +72,7 @@ enum connection_type {
 	CONNECTION_TYPE_FULLMAC,
 	CONNECTION_TYPE_SAE_OFFLOAD,
 	CONNECTION_TYPE_PSK_OFFLOAD,
+	CONNECTION_TYPE_8021X_OFFLOAD,
 };
 
 static uint32_t unicast_watch;
@@ -203,6 +204,15 @@ static inline bool is_offload(struct handshake_state *hs)
 	switch (nhs->type) {
 	case CONNECTION_TYPE_SOFTMAC:
 	case CONNECTION_TYPE_FULLMAC:
+	/*
+	 * 8021x offload does not quite fit into the same category of PSK
+	 * offload. First the netdev_connect_event comes prior to EAP meaning
+	 * the handshake is not done at this point. In addition it still
+	 * requires EAP take place in userspace meaning IWD needs an eapol_sm.
+	 * Because of this, and our prior use of 'is_offload', it does not fit
+	 * into the same category and will need to be handled specially.
+	 */
+	case CONNECTION_TYPE_8021X_OFFLOAD:
 		return false;
 	case CONNECTION_TYPE_SAE_OFFLOAD:
 	case CONNECTION_TYPE_PSK_OFFLOAD:
@@ -2666,6 +2676,9 @@ static struct l_genl_msg *netdev_build_cmd_connect(struct netdev *netdev,
 	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)
@@ -3045,13 +3058,21 @@ static int netdev_handshake_state_setup_connection_type(
 		if (wiphy_has_ext_feature(wiphy,
 				NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK))
 			goto psk_offload;
-		/* fall through */
+
+		if (softmac)
+			goto softmac;
+
+		goto fullmac;
 	case IE_RSN_AKM_SUITE_8021X:
 	case IE_RSN_AKM_SUITE_FT_OVER_8021X:
 	case IE_RSN_AKM_SUITE_8021X_SHA256:
 	case IE_RSN_AKM_SUITE_8021X_SUITE_B_SHA256:
 	case IE_RSN_AKM_SUITE_8021X_SUITE_B_SHA384:
 	case IE_RSN_AKM_SUITE_FT_OVER_8021X_SHA384:
+		if (wiphy_has_ext_feature(wiphy,
+				NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X))
+			goto offload_1x;
+
 		if (softmac)
 			goto softmac;
 
@@ -3096,6 +3117,9 @@ sae_offload:
 psk_offload:
 	nhs->type = CONNECTION_TYPE_PSK_OFFLOAD;
 	return 0;
+offload_1x:
+	nhs->type = CONNECTION_TYPE_8021X_OFFLOAD;
+	return 0;
 }
 
 static int netdev_connect_common(struct netdev *netdev,
@@ -3181,8 +3205,12 @@ build_cmd_connect:
 		if (!cmd_connect)
 			return -EINVAL;
 
-		if (!is_offload(hs) && (is_rsn || hs->settings_8021x))
+		if (!is_offload(hs) && (is_rsn || hs->settings_8021x)) {
 			sm = eapol_sm_new(hs);
+
+			if (nhs->type == CONNECTION_TYPE_8021X_OFFLOAD)
+				eapol_sm_set_require_handshake(sm, false);
+		}
 	}
 
 	return netdev_connect_common(netdev, cmd_connect, bss, hs, sm,
-- 
2.26.2

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

* [PATCH v2 3/3] netdev: implement netdev_set_pmk
  2021-04-09 16:14 [PATCH v2 1/3] eapol: add PMK installer support James Prestwood
  2021-04-09 16:14 ` [PATCH v2 2/3] netdev: add CONNECTION_TYPE_8021X_OFFLOAD James Prestwood
@ 2021-04-09 16:14 ` James Prestwood
  2021-04-09 16:34 ` [PATCH v2 1/3] eapol: add PMK installer support Denis Kenzior
  2 siblings, 0 replies; 4+ messages in thread
From: James Prestwood @ 2021-04-09 16:14 UTC (permalink / raw)
  To: iwd

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

The 8021x offloading procedure still does EAP in userspace which
negotiates the PMK. The kernel then expects to obtain this PMK
from userspace by calling SET_PMK. This then allows the firmware
to begin the 4-way handshake.

Using __eapol_install_set_pmk_func to install netdev_set_pmk,
netdev now gets called into once EAP finishes and can begin
the final userspace actions prior to the firmware starting
the 4-way handshake:

 - SET_PMK using PMK negotiated with EAP
 - Emit SETTING_KEYS event
 - netdev_connect_ok

One thing to note is that the kernel provides no way of knowing if
the 4-way handshake completed. Assuming SET_PMK/SET_STATION come
back with no errors, IWD assumes the PMK was valid. If not, or
due to some other issue in the 4-way, the kernel will send a
disconnect.
---
 src/netdev.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 55 insertions(+)

v2:
 * used new __eapol_set_install_pmk_func
 * Removed SET_STATION call. After testing it appears this is
   not needed.
diff --git a/src/netdev.c b/src/netdev.c
index f41cd2c9..b3357068 100644
--- a/src/netdev.c
+++ b/src/netdev.c
@@ -83,6 +83,7 @@ struct netdev_handshake_state {
 	uint32_t group_new_key_cmd_id;
 	uint32_t group_management_new_key_cmd_id;
 	uint32_t set_station_cmd_id;
+	uint32_t set_pmk_cmd_id;
 	bool ptk_installed;
 	bool gtk_installed;
 	bool igtk_installed;
@@ -252,6 +253,11 @@ static void netdev_handshake_state_cancel_all(
 		l_genl_family_cancel(nl80211, nhs->set_station_cmd_id);
 		nhs->set_station_cmd_id = 0;
 	}
+
+	if (nhs->set_pmk_cmd_id) {
+		l_genl_family_cancel(nl80211, nhs->set_pmk_cmd_id);
+		nhs->set_pmk_cmd_id = 0;
+	}
 }
 
 static void netdev_handshake_state_free(struct handshake_state *hs)
@@ -1705,6 +1711,54 @@ invalid_key:
 	netdev_setting_keys_failed(nhs, err);
 }
 
+static void netdev_set_pmk_cb(struct l_genl_msg *msg, void *user_data)
+{
+	struct netdev_handshake_state *nhs = user_data;
+	struct netdev *netdev = nhs->netdev;
+	int err = l_genl_msg_get_error(msg);
+
+	nhs->set_pmk_cmd_id = 0;
+
+	if (err < 0) {
+		l_error("Error with SET_PMK/SET_STATION");
+		netdev_setting_keys_failed(nhs, err);
+		return;
+	}
+
+	handshake_event(netdev->handshake, HANDSHAKE_EVENT_SETTING_KEYS);
+	netdev_connect_ok(netdev);
+}
+
+static void netdev_set_pmk(struct handshake_state *hs, const uint8_t *pmk,
+				size_t pmk_len)
+{
+	struct l_genl_msg *msg;
+	struct netdev_handshake_state *nhs = l_container_of(hs,
+				struct netdev_handshake_state, super);
+	struct netdev *netdev = nhs->netdev;
+
+	/* Only relevent for 8021x offload */
+	if (nhs->type != CONNECTION_TYPE_8021X_OFFLOAD)
+		return;
+
+	msg = l_genl_msg_new(NL80211_CMD_SET_PMK);
+
+	l_genl_msg_append_attr(msg, NL80211_ATTR_IFINDEX, 4, &netdev->index);
+	l_genl_msg_append_attr(msg, NL80211_ATTR_MAC, 6, netdev->handshake->aa);
+	l_genl_msg_append_attr(msg, NL80211_ATTR_PMK,
+				netdev->handshake->pmk_len,
+				netdev->handshake->pmk);
+
+	nhs->set_pmk_cmd_id = l_genl_family_send(nl80211, msg,
+							netdev_set_pmk_cb,
+							nhs, NULL);
+	if (!nhs->set_pmk_cmd_id) {
+		l_error("Failed to set SET_PMK");
+		netdev_setting_keys_failed(nhs, -EIO);
+		return;
+	}
+}
+
 void netdev_handshake_failed(struct handshake_state *hs, uint16_t reason_code)
 {
 	struct netdev_handshake_state *nhs =
@@ -5566,6 +5620,7 @@ static int netdev_init(void)
 
 	__eapol_set_rekey_offload_func(netdev_set_rekey_offload);
 	__eapol_set_tx_packet_func(netdev_control_port_frame);
+	__eapol_set_install_pmk_func(netdev_set_pmk);
 
 	unicast_watch = l_genl_add_unicast_watch(genl, NL80211_GENL_NAME,
 						netdev_unicast_notify,
-- 
2.26.2

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

* Re: [PATCH v2 1/3] eapol: add PMK installer support
  2021-04-09 16:14 [PATCH v2 1/3] eapol: add PMK installer support James Prestwood
  2021-04-09 16:14 ` [PATCH v2 2/3] netdev: add CONNECTION_TYPE_8021X_OFFLOAD James Prestwood
  2021-04-09 16:14 ` [PATCH v2 3/3] netdev: implement netdev_set_pmk James Prestwood
@ 2021-04-09 16:34 ` Denis Kenzior
  2 siblings, 0 replies; 4+ messages in thread
From: Denis Kenzior @ 2021-04-09 16:34 UTC (permalink / raw)
  To: iwd

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

Hi James,

On 4/9/21 11:14 AM, James Prestwood wrote:
> 802.1x offloading needs a way to call SET_PMK after EAP finishes.
> In the same manor as set_tk/gtk/igtk a new 'install_pmk' function
> was added which eapol can call into after EAP completes.
> ---
>   src/eapol.c | 10 ++++++++++
>   src/eapol.h |  5 +++++
>   2 files changed, 15 insertions(+)
> 

All applied, thanks.

Regards,
-Denis

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

end of thread, other threads:[~2021-04-09 16:34 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-04-09 16:14 [PATCH v2 1/3] eapol: add PMK installer support James Prestwood
2021-04-09 16:14 ` [PATCH v2 2/3] netdev: add CONNECTION_TYPE_8021X_OFFLOAD James Prestwood
2021-04-09 16:14 ` [PATCH v2 3/3] netdev: implement netdev_set_pmk James Prestwood
2021-04-09 16:34 ` [PATCH v2 1/3] eapol: add PMK installer support Denis Kenzior

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.