@@ -65,6 +65,7 @@
#include "src/frame-xchg.h"
#include "src/diagnostic.h"
#include "src/band.h"
+#include "src/pmksa.h"
#ifndef ENOTSUPP
#define ENOTSUPP 524
@@ -1517,6 +1518,8 @@ static void try_handshake_complete(struct netdev_handshake_state *nhs)
l_debug("Invoking handshake_event()");
+ handshake_state_cache_pmksa(&nhs->super);
+
if (handshake_event(&nhs->super, HANDSHAKE_EVENT_COMPLETE))
return;
@@ -2458,7 +2461,19 @@ static struct l_genl_msg *netdev_build_cmd_connect(struct netdev *netdev,
{
struct netdev_handshake_state *nhs =
l_container_of(hs, struct netdev_handshake_state, super);
- uint32_t auth_type = IE_AKM_IS_SAE(hs->akm_suite) ?
+ /*
+ * Choose Open system auth type if PMKSA caching is used for an SAE AKM:
+ *
+ * IEEE 802.11-2020 Table 9-151
+ * - SAE authentication:
+ * 3 (SAE) for SAE Authentication
+ * 0 (open) for PMKSA caching
+ * - FT authentication over SAE:
+ * 3 (SAE) for FT Initial Mobility Domain Association
+ * 0 (open) for FT Initial Mobility Domain Association over
+ * PMKSA caching
+ */
+ uint32_t auth_type = IE_AKM_IS_SAE(hs->akm_suite) && !hs->have_pmksa ?
NL80211_AUTHTYPE_SAE :
NL80211_AUTHTYPE_OPEN_SYSTEM;
enum mpdu_management_subtype subtype = prev_bssid ?
@@ -4027,6 +4042,15 @@ static void netdev_connect_common(struct netdev *netdev,
goto done;
}
+ /*
+ * If SAE, and we have a valid PMKSA cache we can skip the entire SAE
+ * protocol and authenticate using the cached keys.
+ */
+ if (IE_AKM_IS_SAE(hs->akm_suite) && hs->have_pmksa) {
+ l_debug("Skipping SAE by using PMKSA cache");
+ goto build_cmd_connect;
+ }
+
if (!IE_AKM_IS_SAE(hs->akm_suite) ||
nhs->type == CONNECTION_TYPE_SAE_OFFLOAD)
goto build_cmd_connect;