From b85b92b3eebce28219d60eb54f383699daef958d Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Wed, 19 Oct 2022 15:30:28 -0500 Subject: [PATCH] eapol: More strictly validate key_descriptor_version --- src/eapol.c | 40 ++++++++++++++++++++++++---------------- src/eapolutil.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ src/eapolutil.h | 6 ++++++ 3 files changed, 74 insertions(+), 16 deletions(-) diff --git a/src/eapol.c b/src/eapol.c index e8bd5cdb..c6439bb1 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; - /* 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) diff --git a/src/eapolutil.c b/src/eapolutil.c index e2a41c2e..3a0ef26e 100644 --- a/src/eapolutil.c +++ b/src/eapolutil.c @@ -25,9 +25,11 @@ #endif #include +#include #include #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 1f15872e..7451f69b 100644 --- a/src/eapolutil.h +++ b/src/eapolutil.h @@ -25,6 +25,9 @@ #include #include +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);