mirror of
				https://git.kernel.org/pub/scm/network/wireless/iwd.git
				synced 2025-11-04 08:57:29 +01:00 
			
		
		
		
	eapol: More strictly validate key_descriptor_version
This commit is contained in:
		
							parent
							
								
									7f2aa40bba
								
							
						
					
					
						commit
						b85b92b3ee
					
				
							
								
								
									
										40
									
								
								src/eapol.c
									
									
									
									
									
								
							
							
						
						
									
										40
									
								
								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;
 | 
			
		||||
 | 
			
		||||
	/* Further Descriptor Type check */
 | 
			
		||||
	if (!sm->handshake->wpa_ie &&
 | 
			
		||||
			ek->descriptor_type != EAPOL_DESCRIPTOR_TYPE_80211)
 | 
			
		||||
	if (L_WARN_ON(eapol_key_descriptor_version_from_akm(hs->akm_suite,
 | 
			
		||||
				hs->pairwise_cipher,
 | 
			
		||||
				&expected_key_descriptor_version) < 0))
 | 
			
		||||
		return;
 | 
			
		||||
	else if (sm->handshake->wpa_ie &&
 | 
			
		||||
 | 
			
		||||
	if (L_WARN_ON(expected_key_descriptor_version !=
 | 
			
		||||
				ek->key_descriptor_version))
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	/* Further Descriptor Type check */
 | 
			
		||||
	if (!hs->wpa_ie && ek->descriptor_type != EAPOL_DESCRIPTOR_TYPE_80211)
 | 
			
		||||
		return;
 | 
			
		||||
	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)
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user