diff mbox series

[2/3,v2] handshake: split handshake_state_get_pmkid into separate APIs

Message ID 20230620172533.727504-3-prestwoj@gmail.com (mailing list archive)
State Accepted, archived
Headers show
Series PMKID changes | expand

Commit Message

James Prestwood June 20, 2023, 5:25 p.m. UTC
The PMKID derivation has gotten messy due to the spec
updating/clarifying the hash size for the FT-8021X AKM. This
has led to hostapd updating the derivation which leaves older
hostapd versions using SHA1 and newer versions using SHA256.

To support this the checksum type is being fed to
handshake_state_get_pmkid so the caller can decide what sha to
use. In addition handshake_state_pmkid_matches is being added
which uses get_pmkid() but handles sorting out the hash type
automatically.

This lets preauthentication use handshake_state_get_pmkid where
there is the potential that a new PMKID is derived and eapol
can use handshake_state_pmkid_matches which only derives the
PMKID to compare against the peers.
---
 src/eapol.c     |  7 +------
 src/handshake.c | 26 +++++++++++++++-----------
 src/handshake.h |  6 ++++--
 src/station.c   | 10 +++++++++-
 4 files changed, 29 insertions(+), 20 deletions(-)
diff mbox series

Patch

diff --git a/src/eapol.c b/src/eapol.c
index f290f40a..6fb2f306 100644
--- a/src/eapol.c
+++ b/src/eapol.c
@@ -1234,12 +1234,7 @@  static void eapol_handle_ptk_1_of_4(struct eapol_sm *sm,
 		if (!found)
 			goto error_unspecified;
 	} else if (pmkid) {
-		uint8_t own_pmkid[16];
-
-		if (!handshake_state_get_pmkid(sm->handshake, own_pmkid))
-			goto error_unspecified;
-
-		if (l_secure_memcmp(pmkid, own_pmkid, 16)) {
+		if (!handshake_state_pmkid_matches(sm->handshake, pmkid)) {
 			l_debug("Authenticator sent a PMKID that didn't match");
 
 			/*
diff --git a/src/handshake.c b/src/handshake.c
index ac5bda51..46755841 100644
--- a/src/handshake.c
+++ b/src/handshake.c
@@ -734,10 +734,9 @@  void handshake_state_set_pmkid(struct handshake_state *s, const uint8_t *pmkid)
 	s->have_pmkid = true;
 }
 
-bool handshake_state_get_pmkid(struct handshake_state *s, uint8_t *out_pmkid)
+bool handshake_state_get_pmkid(struct handshake_state *s, uint8_t *out_pmkid,
+				enum l_checksum_type sha)
 {
-	enum l_checksum_type sha;
-
 	/* SAE exports pmkid */
 	if (s->have_pmkid) {
 		memcpy(out_pmkid, s->pmkid, 16);
@@ -747,13 +746,15 @@  bool handshake_state_get_pmkid(struct handshake_state *s, uint8_t *out_pmkid)
 	if (!s->have_pmk)
 		return false;
 
-	/*
-	 * Note 802.11 section 11.6.1.3:
-	 * "When the PMKID is calculated for the PMKSA as part of RSN
-	 * preauthentication, the AKM has not yet been negotiated. In this
-	 * case, the HMAC-SHA1-128 based derivation is used for the PMKID
-	 * calculation."
-	 */
+	return crypto_derive_pmkid(s->pmk, 32, s->spa, s->aa, out_pmkid,
+					sha);
+}
+
+bool handshake_state_pmkid_matches(struct handshake_state *s,
+					const uint8_t *check)
+{
+	uint8_t own_pmkid[16];
+	enum l_checksum_type sha;
 
 	if (s->akm_suite & (IE_RSN_AKM_SUITE_8021X_SHA256 |
 			IE_RSN_AKM_SUITE_PSK_SHA256))
@@ -761,7 +762,10 @@  bool handshake_state_get_pmkid(struct handshake_state *s, uint8_t *out_pmkid)
 	else
 		sha = L_CHECKSUM_SHA1;
 
-	return crypto_derive_pmkid(s->pmk, 32, s->spa, s->aa, out_pmkid, sha);
+	if (!handshake_state_get_pmkid(s, own_pmkid, sha))
+		return false;
+
+	return l_secure_memcmp(own_pmkid, check, 16) == 0;
 }
 
 void handshake_state_set_gtk(struct handshake_state *s, const uint8_t *key,
diff --git a/src/handshake.h b/src/handshake.h
index 863ffac7..7200c361 100644
--- a/src/handshake.h
+++ b/src/handshake.h
@@ -269,8 +269,10 @@  void handshake_state_install_igtk(struct handshake_state *s,
 void handshake_state_override_pairwise_cipher(struct handshake_state *s,
 					enum ie_rsn_cipher_suite pairwise);
 
-bool handshake_state_get_pmkid(struct handshake_state *s, uint8_t *out_pmkid);
-
+bool handshake_state_get_pmkid(struct handshake_state *s, uint8_t *out_pmkid,
+				enum l_checksum_type sha);
+bool handshake_state_pmkid_matches(struct handshake_state *s,
+					const uint8_t *check);
 bool handshake_decode_fte_key(struct handshake_state *s, const uint8_t *wrapped,
 				size_t key_len, uint8_t *key_out);
 
diff --git a/src/station.c b/src/station.c
index f830ab7a..2473de2a 100644
--- a/src/station.c
+++ b/src/station.c
@@ -2236,7 +2236,15 @@  static void station_preauthenticate_cb(struct netdev *netdev,
 					new_hs->supplicant_ie[1] + 2,
 					&rsn_info);
 
-		handshake_state_get_pmkid(new_hs, pmkid);
+		/*
+		 * IEEE 802.11 Section 12.7.1.3:
+		 *
+		 * "When the PMKID is calculated for the PMKSA as part of
+		 * preauthentication, the AKM has not yet been negotiated.
+		 * In this case, the HMAC-SHA-1 based derivation is used for
+		 * the PMKID calculation."
+		 */
+		handshake_state_get_pmkid(new_hs, pmkid, L_CHECKSUM_SHA1);
 
 		rsn_info.num_pmkids = 1;
 		rsn_info.pmkids = pmkid;