diff mbox series

[3/4] netdev: implement PMKSA for fullmac drivers

Message ID 20250212162401.130792-4-prestwoj@gmail.com (mailing list archive)
State New
Headers show
Series PMKSA support for fullmac drivers | expand

Checks

Context Check Description
tedd_an/pre-ci_am success Success
prestwoj/iwd-ci-gitlint success GitLint

Commit Message

James Prestwood Feb. 12, 2025, 4:24 p.m. UTC
Supporting PMKSA on fullmac drivers requires that we set the PMKSA
into the kernel as well as remove it. Since station has a removal
path netdev_remove_pmksa needed to be added which station will
call. This will handle both removing IWD's PMKSA cache as well as
in the kernels.

On addition its similar, we add to both IWDs cache and the kernels.
---
 src/netdev.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/netdev.h |  2 ++
 2 files changed, 70 insertions(+)

Comments

James Prestwood Feb. 12, 2025, 4:27 p.m. UTC | #1
On 2/12/25 8:24 AM, James Prestwood wrote:
> Supporting PMKSA on fullmac drivers requires that we set the PMKSA
> into the kernel as well as remove it. Since station has a removal
> path netdev_remove_pmksa needed to be added which station will
> call. This will handle both removing IWD's PMKSA cache as well as
> in the kernels.
>
> On addition its similar, we add to both IWDs cache and the kernels.
> ---
>   src/netdev.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>   src/netdev.h |  2 ++
>   2 files changed, 70 insertions(+)
>
> diff --git a/src/netdev.c b/src/netdev.c
> index 06282c2a..42fb6a4b 100644
> --- a/src/netdev.c
> +++ b/src/netdev.c
> @@ -1498,6 +1498,52 @@ static void netdev_setting_keys_failed(struct netdev_handshake_state *nhs,
>   	handshake_event(&nhs->super, HANDSHAKE_EVENT_SETTING_KEYS_FAILED, &err);
>   }
>   
> +static void netdev_set_pmksa(struct handshake_state *hs)
> +{
> +	struct l_genl_msg *msg;
> +	uint32_t expiration = (uint32_t)hs->expiration;
> +
> +	if (!hs->have_pmkid)
> +		return;
> +
> +	msg = l_genl_msg_new(NL80211_CMD_SET_PMKSA);
> +
> +	l_genl_msg_append_attr(msg, NL80211_ATTR_IFINDEX, 4, &hs->ifindex);
> +	l_genl_msg_append_attr(msg, NL80211_ATTR_PMKID, 16, hs->pmkid);
> +	l_genl_msg_append_attr(msg, NL80211_ATTR_MAC, ETH_ALEN, hs->aa);
> +	l_genl_msg_append_attr(msg, NL80211_ATTR_SSID, hs->ssid_len, hs->ssid);
> +	l_genl_msg_append_attr(msg, NL80211_ATTR_PMK_LIFETIME, 4, &expiration);
> +	l_genl_msg_append_attr(msg, NL80211_ATTR_PMK, hs->pmk_len, hs->pmk);
> +
> +	if (!l_genl_family_send(nl80211, msg, NULL, NULL, NULL))
> +		l_error("error sending SET_PMKSA");
> +}
> +
> +void netdev_remove_pmksa(struct netdev *netdev)
> +{
> +	struct l_genl_msg *msg;
> +	struct handshake_state *hs = netdev->handshake;
> +	struct netdev_handshake_state *nhs = l_container_of(hs,
> +					struct netdev_handshake_state, super);
> +
> +	handshake_state_remove_pmksa(netdev->handshake);
> +
> +	if (nhs->type != CONNECTION_TYPE_FULLMAC)
> +		return;
> +
> +	/* Fullmac cards need to set/remove the PMKSA within the kernel */
> +
> +	msg = l_genl_msg_new(NL80211_CMD_DEL_PMKSA);
> +
> +	l_genl_msg_append_attr(msg, NL80211_ATTR_IFINDEX, 4, &netdev->index);
> +	l_genl_msg_append_attr(msg, NL80211_ATTR_PMKID, 16, hs->pmkid);
> +	l_genl_msg_append_attr(msg, NL80211_ATTR_MAC, ETH_ALEN, hs->aa);
> +	l_genl_msg_append_attr(msg, NL80211_ATTR_SSID, hs->ssid_len, hs->ssid);
> +
> +	if (!l_genl_family_send(nl80211, msg, NULL, NULL, NULL))
> +		l_error("error sending DEL_PMKSA");
> +}
> +
>   static void try_handshake_complete(struct netdev_handshake_state *nhs)
>   {
>   	l_debug("ptk_installed: %u, gtk_installed: %u, igtk_installed: %u",
> @@ -1518,6 +1564,9 @@ static void try_handshake_complete(struct netdev_handshake_state *nhs)
>   
>   		l_debug("Invoking handshake_event()");
>   
> +		if (nhs->type == CONNECTION_TYPE_FULLMAC)
> +			netdev_set_pmksa(&nhs->super);
> +
>   		handshake_state_cache_pmksa(&nhs->super);
>   
>   		if (handshake_event(&nhs->super, HANDSHAKE_EVENT_COMPLETE))
> @@ -6469,6 +6518,23 @@ static void netdev_get_link(struct netdev *netdev)
>   	L_WARN_ON(netdev->get_link_cmd_id == 0);
>   }
>   
> +static void netdev_flush_pmksa(struct netdev *netdev)
> +{
> +	struct l_genl_msg *msg = l_genl_msg_new(NL80211_CMD_FLUSH_PMKSA);
Just noticed this is leaking memory. I'll fix after reviews.
> +
> +	/*
> +	 * We only utilize the kernel's PMKSA cache for fullmac cards, so no
> +	 * need to flush if this is a softmac
> +	 */
> +	if (wiphy_supports_cmds_auth_assoc(netdev->wiphy))
> +		return;
> +
> +	l_genl_msg_append_attr(msg, NL80211_ATTR_IFINDEX, 4, &netdev->index);
> +
> +	if (!l_genl_family_send(nl80211, msg, NULL, NULL, NULL))
> +		l_error("Failed to flush PMKSA");
> +}
> +
>   struct netdev *netdev_create_from_genl(struct l_genl_msg *msg,
>   					const uint8_t *set_mac)
>   {
> @@ -6544,6 +6610,8 @@ struct netdev *netdev_create_from_genl(struct l_genl_msg *msg,
>   
>   	netdev_get_link(netdev);
>   
> +	netdev_flush_pmksa(netdev);
> +
>   	return netdev;
>   }
>   
> diff --git a/src/netdev.h b/src/netdev.h
> index 6299934e..0c7d7550 100644
> --- a/src/netdev.h
> +++ b/src/netdev.h
> @@ -218,6 +218,8 @@ int netdev_get_all_stations(struct netdev *netdev, netdev_get_station_cb_t cb,
>   
>   void netdev_handshake_failed(struct handshake_state *hs, uint16_t reason_code);
>   
> +void netdev_remove_pmksa(struct netdev *netdev);
> +
>   struct netdev *netdev_find(int ifindex);
>   
>   uint32_t netdev_watch_add(netdev_watch_func_t func,
diff mbox series

Patch

diff --git a/src/netdev.c b/src/netdev.c
index 06282c2a..42fb6a4b 100644
--- a/src/netdev.c
+++ b/src/netdev.c
@@ -1498,6 +1498,52 @@  static void netdev_setting_keys_failed(struct netdev_handshake_state *nhs,
 	handshake_event(&nhs->super, HANDSHAKE_EVENT_SETTING_KEYS_FAILED, &err);
 }
 
+static void netdev_set_pmksa(struct handshake_state *hs)
+{
+	struct l_genl_msg *msg;
+	uint32_t expiration = (uint32_t)hs->expiration;
+
+	if (!hs->have_pmkid)
+		return;
+
+	msg = l_genl_msg_new(NL80211_CMD_SET_PMKSA);
+
+	l_genl_msg_append_attr(msg, NL80211_ATTR_IFINDEX, 4, &hs->ifindex);
+	l_genl_msg_append_attr(msg, NL80211_ATTR_PMKID, 16, hs->pmkid);
+	l_genl_msg_append_attr(msg, NL80211_ATTR_MAC, ETH_ALEN, hs->aa);
+	l_genl_msg_append_attr(msg, NL80211_ATTR_SSID, hs->ssid_len, hs->ssid);
+	l_genl_msg_append_attr(msg, NL80211_ATTR_PMK_LIFETIME, 4, &expiration);
+	l_genl_msg_append_attr(msg, NL80211_ATTR_PMK, hs->pmk_len, hs->pmk);
+
+	if (!l_genl_family_send(nl80211, msg, NULL, NULL, NULL))
+		l_error("error sending SET_PMKSA");
+}
+
+void netdev_remove_pmksa(struct netdev *netdev)
+{
+	struct l_genl_msg *msg;
+	struct handshake_state *hs = netdev->handshake;
+	struct netdev_handshake_state *nhs = l_container_of(hs,
+					struct netdev_handshake_state, super);
+
+	handshake_state_remove_pmksa(netdev->handshake);
+
+	if (nhs->type != CONNECTION_TYPE_FULLMAC)
+		return;
+
+	/* Fullmac cards need to set/remove the PMKSA within the kernel */
+
+	msg = l_genl_msg_new(NL80211_CMD_DEL_PMKSA);
+
+	l_genl_msg_append_attr(msg, NL80211_ATTR_IFINDEX, 4, &netdev->index);
+	l_genl_msg_append_attr(msg, NL80211_ATTR_PMKID, 16, hs->pmkid);
+	l_genl_msg_append_attr(msg, NL80211_ATTR_MAC, ETH_ALEN, hs->aa);
+	l_genl_msg_append_attr(msg, NL80211_ATTR_SSID, hs->ssid_len, hs->ssid);
+
+	if (!l_genl_family_send(nl80211, msg, NULL, NULL, NULL))
+		l_error("error sending DEL_PMKSA");
+}
+
 static void try_handshake_complete(struct netdev_handshake_state *nhs)
 {
 	l_debug("ptk_installed: %u, gtk_installed: %u, igtk_installed: %u",
@@ -1518,6 +1564,9 @@  static void try_handshake_complete(struct netdev_handshake_state *nhs)
 
 		l_debug("Invoking handshake_event()");
 
+		if (nhs->type == CONNECTION_TYPE_FULLMAC)
+			netdev_set_pmksa(&nhs->super);
+
 		handshake_state_cache_pmksa(&nhs->super);
 
 		if (handshake_event(&nhs->super, HANDSHAKE_EVENT_COMPLETE))
@@ -6469,6 +6518,23 @@  static void netdev_get_link(struct netdev *netdev)
 	L_WARN_ON(netdev->get_link_cmd_id == 0);
 }
 
+static void netdev_flush_pmksa(struct netdev *netdev)
+{
+	struct l_genl_msg *msg = l_genl_msg_new(NL80211_CMD_FLUSH_PMKSA);
+
+	/*
+	 * We only utilize the kernel's PMKSA cache for fullmac cards, so no
+	 * need to flush if this is a softmac
+	 */
+	if (wiphy_supports_cmds_auth_assoc(netdev->wiphy))
+		return;
+
+	l_genl_msg_append_attr(msg, NL80211_ATTR_IFINDEX, 4, &netdev->index);
+
+	if (!l_genl_family_send(nl80211, msg, NULL, NULL, NULL))
+		l_error("Failed to flush PMKSA");
+}
+
 struct netdev *netdev_create_from_genl(struct l_genl_msg *msg,
 					const uint8_t *set_mac)
 {
@@ -6544,6 +6610,8 @@  struct netdev *netdev_create_from_genl(struct l_genl_msg *msg,
 
 	netdev_get_link(netdev);
 
+	netdev_flush_pmksa(netdev);
+
 	return netdev;
 }
 
diff --git a/src/netdev.h b/src/netdev.h
index 6299934e..0c7d7550 100644
--- a/src/netdev.h
+++ b/src/netdev.h
@@ -218,6 +218,8 @@  int netdev_get_all_stations(struct netdev *netdev, netdev_get_station_cb_t cb,
 
 void netdev_handshake_failed(struct handshake_state *hs, uint16_t reason_code);
 
+void netdev_remove_pmksa(struct netdev *netdev);
+
 struct netdev *netdev_find(int ifindex);
 
 uint32_t netdev_watch_add(netdev_watch_func_t func,