diff mbox series

[01/26] eapol: More strictly validate key_descriptor_version

Message ID 20221021191307.31492-1-denkenz@gmail.com (mailing list archive)
State New
Headers show
Series [01/26] eapol: More strictly validate key_descriptor_version | expand

Checks

Context Check Description
tedd_an/pre-ci_am success Success
prestwoj/iwd-alpine-ci-fetch success Fetch PR
prestwoj/iwd-ci-fetch success Fetch PR
prestwoj/iwd-ci-gitlint success GitLint
prestwoj/iwd-ci-build success Build - Configure
prestwoj/iwd-alpine-ci-makedistcheck success Make Distcheck
prestwoj/iwd-alpine-ci-build success Build - Configure
prestwoj/iwd-ci-clang success clang PASS
prestwoj/iwd-ci-makecheckvalgrind success Make Check w/Valgrind
prestwoj/iwd-ci-makecheck success Make Check
prestwoj/iwd-alpine-ci-makecheckvalgrind success Make Check w/Valgrind
prestwoj/iwd-alpine-ci-makecheck success Make Check
prestwoj/iwd-ci-testrunner fail test-runner - FAIL: testP2P
prestwoj/iwd-ci-incremental_build success Incremental Build with patches
prestwoj/iwd-ci-makedistcheck success Make Distcheck
prestwoj/iwd-alpine-ci-incremental_build success Incremental Build with patches

Commit Message

Denis Kenzior Oct. 21, 2022, 7:12 p.m. UTC
---
 src/eapol.c     | 38 +++++++++++++++++++++++---------------
 src/eapolutil.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
 src/eapolutil.h |  6 ++++++
 3 files changed, 73 insertions(+), 15 deletions(-)

Comments

Denis Kenzior Oct. 26, 2022, 7:53 p.m. UTC | #1
All 26 applied.

Regards,
-Denis
diff mbox series

Patch

diff --git a/src/eapol.c b/src/eapol.c
index e8bd5cdbf64b..c6439bb1302d 100644
--- a/src/eapol.c
+++ b/src/eapol.c
@@ -2238,12 +2238,14 @@  static void eapol_key_handle(struct eapol_sm *sm,
 				const struct eapol_frame *frame,
 				bool unencrypted)
 {
+	struct handshake_state *hs = sm->handshake;
 	const struct eapol_key *ek;
 	const uint8_t *kck;
 	const uint8_t *kek;
 	uint8_t *decrypted_key_data = NULL;
 	size_t key_data_len = 0;
 	uint64_t replay_counter;
+	uint8_t expected_key_descriptor_version;
 
 	ek = eapol_key_validate((const uint8_t *) frame,
 				sizeof(struct eapol_header) +
@@ -2256,11 +2258,19 @@  static void eapol_key_handle(struct eapol_sm *sm,
 	if (!ek->key_ack)
 		return;
 
+	if (L_WARN_ON(eapol_key_descriptor_version_from_akm(hs->akm_suite,
+				hs->pairwise_cipher,
+				&expected_key_descriptor_version) < 0))
+		return;
+
+	if (L_WARN_ON(expected_key_descriptor_version !=
+				ek->key_descriptor_version))
+		return;
+
 	/* Further Descriptor Type check */
-	if (!sm->handshake->wpa_ie &&
-			ek->descriptor_type != EAPOL_DESCRIPTOR_TYPE_80211)
+	if (!hs->wpa_ie && ek->descriptor_type != EAPOL_DESCRIPTOR_TYPE_80211)
 		return;
-	else if (sm->handshake->wpa_ie &&
+	else if (hs->wpa_ie &&
 			ek->descriptor_type != EAPOL_DESCRIPTOR_TYPE_WPA)
 		return;
 
@@ -2293,31 +2303,30 @@  static void eapol_key_handle(struct eapol_sm *sm,
 	if (sm->have_replay && sm->replay_counter >= replay_counter)
 		return;
 
-	kck = handshake_state_get_kck(sm->handshake);
+	kck = handshake_state_get_kck(hs);
 
 	if (ek->key_mic) {
 		/* Haven't received step 1 yet, so no ptk */
-		if (!sm->handshake->have_snonce)
+		if (!hs->have_snonce)
 			return;
 
-		if (!eapol_verify_mic(sm->handshake->akm_suite, kck, ek,
-					sm->mic_len))
+		if (!eapol_verify_mic(hs->akm_suite, kck, ek, sm->mic_len))
 			return;
 	}
 
-	if ((ek->encrypted_key_data && !sm->handshake->wpa_ie) ||
-			(ek->key_type == 0 && sm->handshake->wpa_ie)) {
+	if ((ek->encrypted_key_data && !hs->wpa_ie) ||
+			(ek->key_type == 0 && hs->wpa_ie)) {
 		/*
 		 * If using a MIC (non-FILS) but haven't received step 1 yet
 		 * we disregard since there will be no ptk
 		 */
-		if (sm->mic_len && !sm->handshake->have_snonce)
+		if (sm->mic_len && !hs->have_snonce)
 			return;
 
-		kek = handshake_state_get_kek(sm->handshake);
+		kek = handshake_state_get_kek(hs);
 
 		decrypted_key_data = eapol_decrypt_key_data(
-					sm->handshake->akm_suite, kek,
+					hs->akm_suite, kek,
 					ek, &key_data_len, sm->mic_len);
 		if (!decrypted_key_data)
 			return;
@@ -2326,11 +2335,10 @@  static void eapol_key_handle(struct eapol_sm *sm,
 
 	if (ek->key_type == 0) {
 		/* GTK handshake allowed only after PTK handshake complete */
-		if (!sm->handshake->ptk_complete)
+		if (!hs->ptk_complete)
 			goto done;
 
-		if (sm->handshake->group_cipher ==
-				IE_RSN_CIPHER_SUITE_NO_GROUP_TRAFFIC)
+		if (hs->group_cipher == IE_RSN_CIPHER_SUITE_NO_GROUP_TRAFFIC)
 			goto done;
 
 		if (!decrypted_key_data)
diff --git a/src/eapolutil.c b/src/eapolutil.c
index e2a41c2e823f..3a0ef26e62bc 100644
--- a/src/eapolutil.c
+++ b/src/eapolutil.c
@@ -25,9 +25,11 @@ 
 #endif
 
 #include <stdio.h>
+#include <errno.h>
 #include <ell/ell.h>
 
 #include "src/eapolutil.h"
+#include "src/ie.h"
 
 const struct eapol_key *eapol_key_validate(const uint8_t *frame, size_t len,
 						size_t mic_len)
@@ -80,3 +82,45 @@  const struct eapol_key *eapol_key_validate(const uint8_t *frame, size_t len,
 
 	return ek;
 }
+
+int eapol_key_descriptor_version_from_akm(enum ie_rsn_akm_suite akm,
+					enum ie_rsn_cipher_suite pairwise,
+					uint8_t *outv)
+{
+	/* 802.11-2020 Section 12.7.2 */
+	switch (akm) {
+	case IE_RSN_AKM_SUITE_8021X:
+	case IE_RSN_AKM_SUITE_PSK:
+		if (pairwise == IE_RSN_CIPHER_SUITE_USE_GROUP_CIPHER ||
+				pairwise == IE_RSN_CIPHER_SUITE_TKIP)
+			*outv = EAPOL_KEY_DESCRIPTOR_VERSION_HMAC_MD5_ARC4;
+		else
+			*outv = EAPOL_KEY_DESCRIPTOR_VERSION_HMAC_SHA1_AES;
+
+		return 0;
+	case IE_RSN_AKM_SUITE_FT_OVER_8021X:
+	case IE_RSN_AKM_SUITE_FT_USING_PSK:
+	case IE_RSN_AKM_SUITE_8021X_SHA256:
+	case IE_RSN_AKM_SUITE_PSK_SHA256:
+		*outv = EAPOL_KEY_DESCRIPTOR_VERSION_AES_128_CMAC_AES;
+		return 0;
+	case IE_RSN_AKM_SUITE_SAE_SHA256:
+	case IE_RSN_AKM_SUITE_FT_OVER_SAE_SHA256:
+	case IE_RSN_AKM_SUITE_8021X_SUITE_B_SHA256:
+	case IE_RSN_AKM_SUITE_8021X_SUITE_B_SHA384:
+	case IE_RSN_AKM_SUITE_FT_OVER_8021X_SHA384:
+	case IE_RSN_AKM_SUITE_FILS_SHA256:
+	case IE_RSN_AKM_SUITE_FILS_SHA384:
+	case IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA256:
+	case IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA384:
+	case IE_RSN_AKM_SUITE_OWE:
+	case IE_RSN_AKM_SUITE_OSEN:
+		*outv = EAPOL_KEY_DESCRIPTOR_VERSION_AKM_DEFINED;
+		return 0;
+	case IE_RSN_AKM_SUITE_TDLS:
+	case IE_RSN_AKM_SUITE_AP_PEER_KEY_SHA256:
+		break;
+	}
+
+	return -ENOTSUP;
+};
diff --git a/src/eapolutil.h b/src/eapolutil.h
index 1f15872eb2d7..7451f69bedd8 100644
--- a/src/eapolutil.h
+++ b/src/eapolutil.h
@@ -25,6 +25,9 @@ 
 #include <asm/byteorder.h>
 #include <linux/types.h>
 
+enum ie_rsn_akm_suite;
+enum ie_rsn_cipher_suite;
+
 enum eapol_protocol_version {
 	EAPOL_PROTOCOL_VERSION_2001	= 1,
 	EAPOL_PROTOCOL_VERSION_2004	= 2,
@@ -116,3 +119,6 @@  struct eapol_key {
 
 const struct eapol_key *eapol_key_validate(const uint8_t *frame, size_t len,
 						size_t mic_len);
+int eapol_key_descriptor_version_from_akm(enum ie_rsn_akm_suite akm,
+					enum ie_rsn_cipher_suite pairwise,
+					uint8_t *out_version);