From 9479c31a72a82e1605c9af527e98d395cc8c14e9 Mon Sep 17 00:00:00 2001 From: James Prestwood Date: Tue, 20 Jun 2023 10:25:33 -0700 Subject: [PATCH] handshake: add FT_OVER_8021X AKM for SHA256 PMKID derivation Hostapd commit b6d3fd05e3 changed the PMKID derivation in accordance with 802.11-2020 which then breaks PMKID validation in IWD. This breaks the FT-8021x AKM in IWD if the AP uses this hostapd version since the PMKID doesn't validate during EAPoL. This updates the PMKID derivation to use the correct SHA hash for this AKM and adds SHA1 based PMKID checking for interoperability with older hostapd versions. --- src/handshake.c | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/src/handshake.c b/src/handshake.c index 46755841..6b93774a 100644 --- a/src/handshake.c +++ b/src/handshake.c @@ -756,8 +756,26 @@ bool handshake_state_pmkid_matches(struct handshake_state *s, uint8_t own_pmkid[16]; enum l_checksum_type sha; + /* + * 802.11-2020 Table 9-151 defines the hashing algorithm to use + * for various AKM's. Note some AKMs are omitted here because they + * export the PMKID individually (SAE/FILS/FT-PSK) + * + * SHA1: + * 00-0F-AC:1 (8021X) + * 00-0F-AC:2 (PSK) + * + * SHA256: + * 00-0F-AC:3 (FT-8021X) + * 00-0F-AC:5 (8021X-SHA256) + * 00-0F-AC:6 (PSK-SHA256) + * + * SHA384: + * 00-0F-AC:13 (FT-8021X-SHA384) + */ if (s->akm_suite & (IE_RSN_AKM_SUITE_8021X_SHA256 | - IE_RSN_AKM_SUITE_PSK_SHA256)) + IE_RSN_AKM_SUITE_PSK_SHA256 | + IE_RSN_AKM_SUITE_FT_OVER_8021X)) sha = L_CHECKSUM_SHA256; else sha = L_CHECKSUM_SHA1; @@ -765,7 +783,19 @@ bool handshake_state_pmkid_matches(struct handshake_state *s, if (!handshake_state_get_pmkid(s, own_pmkid, sha)) return false; - return l_secure_memcmp(own_pmkid, check, 16) == 0; + if (l_secure_memcmp(own_pmkid, check, 16)) { + if (s->akm_suite != IE_RSN_AKM_SUITE_FT_OVER_8021X) + return false; + + l_debug("PMKID did not match, trying SHA1 derivation"); + + if (!handshake_state_get_pmkid(s, own_pmkid, L_CHECKSUM_SHA1)) + return false; + + return l_secure_memcmp(own_pmkid, check, 16) == 0; + } + + return true; } void handshake_state_set_gtk(struct handshake_state *s, const uint8_t *key,