public inbox for iwd@lists.linux.dev
 help / color / mirror / Atom feed
From: James Prestwood <prestwoj@gmail.com>
To: iwd@lists.linux.dev
Cc: James Prestwood <prestwoj@gmail.com>
Subject: [PATCH 13/15] station: support PMKSA connections
Date: Fri, 22 Nov 2024 07:15:49 -0800	[thread overview]
Message-ID: <20241122151551.286355-14-prestwoj@gmail.com> (raw)
In-Reply-To: <20241122151551.286355-1-prestwoj@gmail.com>

The actual connection piece of this is very minimal, and only
requires station to check if there is a PMKSA cached, and if so
include the PMKID in the RSNE. Netdev then takes care of the rest.

The remainder of this patch is the error handling if a PMKSA
connection fails with INVALID_PMKID. In this case IWD should retry
the same BSS without PMKSA.

An option was also added to disable PMKSA if a user wants to do
that. In theory PMKSA is actually less secure compared to SAE so
it could be something a user wants to disable. Going forward though
it will be enabled by default as its a requirement from the WiFi
alliance for WPA3 certification.
---
 src/station.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 53 insertions(+), 1 deletion(-)

diff --git a/src/station.c b/src/station.c
index 09193eed..5403c332 100644
--- a/src/station.c
+++ b/src/station.c
@@ -63,6 +63,7 @@
 #include "src/eap.h"
 #include "src/eap-tls-common.h"
 #include "src/storage.h"
+#include "src/pmksa.h"
 
 #define STATION_RECENT_NETWORK_LIMIT	5
 #define STATION_RECENT_FREQS_LIMIT	5
@@ -78,6 +79,7 @@ static bool supports_drop_gratuitous_arp;
 static bool supports_drop_unsolicited_na;
 static bool supports_ipv4_drop_unicast_in_l2_multicast;
 static bool supports_ipv6_drop_unicast_in_l2_multicast;
+static bool pmksa_disabled;
 static struct watchlist event_watches;
 static uint32_t known_networks_watch;
 static uint32_t allowed_bands;
@@ -1157,6 +1159,7 @@ static int station_build_handshake_rsn(struct handshake_state *hs,
 					struct network *network,
 					struct scan_bss *bss)
 {
+	struct netdev *netdev = netdev_find(hs->ifindex);
 	const struct l_settings *settings = iwd_get_config();
 	enum security security = network_get_security(network);
 	bool add_mde = false;
@@ -1167,6 +1170,7 @@ static int station_build_handshake_rsn(struct handshake_state *hs,
 	uint8_t *ap_ie;
 	bool disable_ocv;
 	enum band_freq band;
+	struct pmksa *pmksa;
 
 	memset(&info, 0, sizeof(info));
 
@@ -1300,6 +1304,17 @@ build_ie:
 			IE_CIPHER_IS_GCMP_CCMP(info.pairwise_ciphers))
 		info.extended_key_id = true;
 
+	if (IE_AKM_IS_SAE(info.akm_suites) && !pmksa_disabled) {
+		pmksa = pmksa_cache_get(netdev_get_address(netdev), bss->addr,
+					bss->ssid, bss->ssid_len,
+					info.akm_suites);
+		if (pmksa) {
+			handshake_state_set_pmksa(hs, pmksa);
+			info.num_pmkids = 1;
+			info.pmkids = hs->pmksa->pmkid;
+		}
+	}
+
 	/* RSN takes priority */
 	if (bss->rsne) {
 		ap_ie = bss->rsne;
@@ -3391,6 +3406,39 @@ try_next:
 	return station_try_next_bss(station);
 }
 
+static bool station_pmksa_fallback(struct station *station, uint16_t status)
+{
+	/*
+	 * IEEE 802.11-2020 12.6.10.3 Cached PMKSAs and RSNA key management
+	 *
+	 * "If the Authenticator does not have a PMKSA for the PMKIDs in the
+	 * (re)association request or the AKM does not match, its behavior
+	 * depends on how the PMKSA was established. If SAE authentication was
+	 * used to establish the PMKSA, then the AP shall reject (re)association
+	 * by sending a (Re)Association Response frame with status code
+	 * STATUS_INVALID_PMKID. Note that this allows the non-AP STA to fall
+	 * back to full SAE authentication to establish another PMKSA"
+	 */
+	if (status != MMPDU_STATUS_CODE_INVALID_PMKID)
+		return false;
+
+	if (L_WARN_ON(!station->hs))
+		return false;
+
+	if (!IE_AKM_IS_SAE(station->hs->akm_suite) || !station->hs->have_pmksa)
+		return false;
+
+	/*
+	 * Remove the PMKSA from the handshake and return true to re-try the
+	 * same BSS without PMKSA.
+	 */
+	handshake_state_remove_pmksa(station->hs);
+
+	station_debug_event(station, "pmksa-invalid-pmkid");
+
+	return true;
+}
+
 /* A bit more concise for trying to fit these into 80 characters */
 #define IS_TEMPORARY_STATUS(code) \
 	((code) == MMPDU_STATUS_CODE_DENIED_UNSUFFICIENT_BANDWIDTH || \
@@ -3414,7 +3462,7 @@ static bool station_retry_with_status(struct station *station,
 	if (IS_TEMPORARY_STATUS(status_code))
 		network_blacklist_add(station->connected_network,
 						station->connected_bss);
-	else
+	else if (!station_pmksa_fallback(station, status_code))
 		blacklist_add_bss(station->connected_bss->addr);
 
 	iwd_notice(IWD_NOTICE_CONNECT_FAILED, "status: %u", status_code);
@@ -5830,6 +5878,10 @@ static int station_init(void)
 				&anqp_disabled))
 		anqp_disabled = true;
 
+	if (!l_settings_get_bool(iwd_get_config(), "General", "DisablePMKSA",
+				&pmksa_disabled))
+		pmksa_disabled = false;
+
 	if (!netconfig_enabled())
 		l_info("station: Network configuration is disabled.");
 
-- 
2.34.1


  parent reply	other threads:[~2024-11-22 15:16 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-11-22 15:15 [PATCH 00/15] PMKSA support (SAE only) James Prestwood
2024-11-22 15:15 ` [PATCH 01/15] handshake: add ref counting to handshake_state James Prestwood
2024-11-22 15:15 ` [PATCH 02/15] unit: update use of handshake_state with ref/unref James Prestwood
2024-11-22 15:15 ` [PATCH 03/15] auto-t: always initialize StationDebug in Device class James Prestwood
2024-11-22 15:15 ` [PATCH 04/15] auto-t: add pmksa_flush() to hostapd module James Prestwood
2024-11-22 15:15 ` [PATCH 05/15] auto-t: update testSAE to disable PMKSA James Prestwood
2024-11-22 15:15 ` [PATCH 06/15] pmksa: Add skeleton James Prestwood
2024-11-22 15:15 ` [PATCH 07/15] unit: Add basic pmksa test James Prestwood
2024-11-22 15:15 ` [PATCH 08/15] pmksa: Add debugging James Prestwood
2024-11-22 15:15 ` [PATCH 09/15] handshake: Add pmksa setter & stealer James Prestwood
2024-11-25 14:56   ` Denis Kenzior
2024-11-25 15:01     ` James Prestwood
2024-11-25 19:25       ` Bryce Johnson
2024-11-25 19:49         ` James Prestwood
2024-11-25 20:18           ` Bryce Johnson
2024-11-22 15:15 ` [PATCH 10/15] handshake: add handshake_state_remove_pmksa James Prestwood
2024-11-22 15:15 ` [PATCH 11/15] netdev: add support to use PMKSA over SAE if available James Prestwood
2024-11-22 15:15 ` [PATCH 12/15] station: hold reference to handshake object James Prestwood
2024-11-22 15:15 ` James Prestwood [this message]
2024-11-22 15:15 ` [PATCH 14/15] auto-t: add PMKSA tests James Prestwood
2024-11-22 15:15 ` [PATCH 15/15] doc: document DisablePMKSA option James Prestwood

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=20241122151551.286355-14-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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox