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,