mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-11-25 17:59:25 +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,
|
const struct eapol_frame *frame,
|
||||||
bool unencrypted)
|
bool unencrypted)
|
||||||
{
|
{
|
||||||
|
struct handshake_state *hs = sm->handshake;
|
||||||
const struct eapol_key *ek;
|
const struct eapol_key *ek;
|
||||||
const uint8_t *kck;
|
const uint8_t *kck;
|
||||||
const uint8_t *kek;
|
const uint8_t *kek;
|
||||||
uint8_t *decrypted_key_data = NULL;
|
uint8_t *decrypted_key_data = NULL;
|
||||||
size_t key_data_len = 0;
|
size_t key_data_len = 0;
|
||||||
uint64_t replay_counter;
|
uint64_t replay_counter;
|
||||||
|
uint8_t expected_key_descriptor_version;
|
||||||
|
|
||||||
ek = eapol_key_validate((const uint8_t *) frame,
|
ek = eapol_key_validate((const uint8_t *) frame,
|
||||||
sizeof(struct eapol_header) +
|
sizeof(struct eapol_header) +
|
||||||
@ -2256,11 +2258,19 @@ static void eapol_key_handle(struct eapol_sm *sm,
|
|||||||
if (!ek->key_ack)
|
if (!ek->key_ack)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Further Descriptor Type check */
|
if (L_WARN_ON(eapol_key_descriptor_version_from_akm(hs->akm_suite,
|
||||||
if (!sm->handshake->wpa_ie &&
|
hs->pairwise_cipher,
|
||||||
ek->descriptor_type != EAPOL_DESCRIPTOR_TYPE_80211)
|
&expected_key_descriptor_version) < 0))
|
||||||
return;
|
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)
|
ek->descriptor_type != EAPOL_DESCRIPTOR_TYPE_WPA)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -2293,31 +2303,30 @@ static void eapol_key_handle(struct eapol_sm *sm,
|
|||||||
if (sm->have_replay && sm->replay_counter >= replay_counter)
|
if (sm->have_replay && sm->replay_counter >= replay_counter)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
kck = handshake_state_get_kck(sm->handshake);
|
kck = handshake_state_get_kck(hs);
|
||||||
|
|
||||||
if (ek->key_mic) {
|
if (ek->key_mic) {
|
||||||
/* Haven't received step 1 yet, so no ptk */
|
/* Haven't received step 1 yet, so no ptk */
|
||||||
if (!sm->handshake->have_snonce)
|
if (!hs->have_snonce)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!eapol_verify_mic(sm->handshake->akm_suite, kck, ek,
|
if (!eapol_verify_mic(hs->akm_suite, kck, ek, sm->mic_len))
|
||||||
sm->mic_len))
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ek->encrypted_key_data && !sm->handshake->wpa_ie) ||
|
if ((ek->encrypted_key_data && !hs->wpa_ie) ||
|
||||||
(ek->key_type == 0 && sm->handshake->wpa_ie)) {
|
(ek->key_type == 0 && hs->wpa_ie)) {
|
||||||
/*
|
/*
|
||||||
* If using a MIC (non-FILS) but haven't received step 1 yet
|
* If using a MIC (non-FILS) but haven't received step 1 yet
|
||||||
* we disregard since there will be no ptk
|
* we disregard since there will be no ptk
|
||||||
*/
|
*/
|
||||||
if (sm->mic_len && !sm->handshake->have_snonce)
|
if (sm->mic_len && !hs->have_snonce)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
kek = handshake_state_get_kek(sm->handshake);
|
kek = handshake_state_get_kek(hs);
|
||||||
|
|
||||||
decrypted_key_data = eapol_decrypt_key_data(
|
decrypted_key_data = eapol_decrypt_key_data(
|
||||||
sm->handshake->akm_suite, kek,
|
hs->akm_suite, kek,
|
||||||
ek, &key_data_len, sm->mic_len);
|
ek, &key_data_len, sm->mic_len);
|
||||||
if (!decrypted_key_data)
|
if (!decrypted_key_data)
|
||||||
return;
|
return;
|
||||||
@ -2326,11 +2335,10 @@ static void eapol_key_handle(struct eapol_sm *sm,
|
|||||||
|
|
||||||
if (ek->key_type == 0) {
|
if (ek->key_type == 0) {
|
||||||
/* GTK handshake allowed only after PTK handshake complete */
|
/* GTK handshake allowed only after PTK handshake complete */
|
||||||
if (!sm->handshake->ptk_complete)
|
if (!hs->ptk_complete)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
if (sm->handshake->group_cipher ==
|
if (hs->group_cipher == IE_RSN_CIPHER_SUITE_NO_GROUP_TRAFFIC)
|
||||||
IE_RSN_CIPHER_SUITE_NO_GROUP_TRAFFIC)
|
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
if (!decrypted_key_data)
|
if (!decrypted_key_data)
|
||||||
|
@ -25,9 +25,11 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <ell/ell.h>
|
#include <ell/ell.h>
|
||||||
|
|
||||||
#include "src/eapolutil.h"
|
#include "src/eapolutil.h"
|
||||||
|
#include "src/ie.h"
|
||||||
|
|
||||||
const struct eapol_key *eapol_key_validate(const uint8_t *frame, size_t len,
|
const struct eapol_key *eapol_key_validate(const uint8_t *frame, size_t len,
|
||||||
size_t mic_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;
|
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 <asm/byteorder.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
|
||||||
|
enum ie_rsn_akm_suite;
|
||||||
|
enum ie_rsn_cipher_suite;
|
||||||
|
|
||||||
enum eapol_protocol_version {
|
enum eapol_protocol_version {
|
||||||
EAPOL_PROTOCOL_VERSION_2001 = 1,
|
EAPOL_PROTOCOL_VERSION_2001 = 1,
|
||||||
EAPOL_PROTOCOL_VERSION_2004 = 2,
|
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,
|
const struct eapol_key *eapol_key_validate(const uint8_t *frame, size_t len,
|
||||||
size_t mic_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…
Reference in New Issue
Block a user