mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2025-01-03 19:02:34 +01:00
eapol: Send / Validate RSNXE in STA mode
This commit is contained in:
parent
1a7c5786f6
commit
636c6eb645
105
src/eapol.c
105
src/eapol.c
@ -1098,6 +1098,15 @@ static void eapol_ptk_1_of_4_retry(struct l_timeout *timeout, void *user_data)
|
|||||||
eapol_set_key_timeout(sm, eapol_ptk_1_of_4_retry);
|
eapol_set_key_timeout(sm, eapol_ptk_1_of_4_retry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline size_t append_ie(uint8_t *ies, const uint8_t *ie)
|
||||||
|
{
|
||||||
|
if (!ie)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
memcpy(ies, ie, ie[1] + 2);
|
||||||
|
return ie[1] + 2;
|
||||||
|
}
|
||||||
|
|
||||||
static void eapol_handle_ptk_1_of_4(struct eapol_sm *sm,
|
static void eapol_handle_ptk_1_of_4(struct eapol_sm *sm,
|
||||||
const struct eapol_key *ek,
|
const struct eapol_key *ek,
|
||||||
bool unencrypted)
|
bool unencrypted)
|
||||||
@ -1105,7 +1114,7 @@ static void eapol_handle_ptk_1_of_4(struct eapol_sm *sm,
|
|||||||
const uint8_t *kck;
|
const uint8_t *kck;
|
||||||
struct eapol_key *step2;
|
struct eapol_key *step2;
|
||||||
uint8_t mic[MIC_MAXLEN];
|
uint8_t mic[MIC_MAXLEN];
|
||||||
uint8_t ies[512];
|
uint8_t ies[1024];
|
||||||
size_t ies_len;
|
size_t ies_len;
|
||||||
const uint8_t *own_ie = sm->handshake->supplicant_ie;
|
const uint8_t *own_ie = sm->handshake->supplicant_ie;
|
||||||
const uint8_t *pmkid;
|
const uint8_t *pmkid;
|
||||||
@ -1210,9 +1219,6 @@ static void eapol_handle_ptk_1_of_4(struct eapol_sm *sm,
|
|||||||
(IE_RSN_AKM_SUITE_FT_OVER_8021X |
|
(IE_RSN_AKM_SUITE_FT_OVER_8021X |
|
||||||
IE_RSN_AKM_SUITE_FT_USING_PSK |
|
IE_RSN_AKM_SUITE_FT_USING_PSK |
|
||||||
IE_RSN_AKM_SUITE_FT_OVER_SAE_SHA256)) {
|
IE_RSN_AKM_SUITE_FT_OVER_SAE_SHA256)) {
|
||||||
const uint8_t *mde = sm->handshake->mde;
|
|
||||||
const uint8_t *fte = sm->handshake->fte;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Rebuild the RSNE to include the PMKR1Name and append
|
* Rebuild the RSNE to include the PMKR1Name and append
|
||||||
* MDE + FTE.
|
* MDE + FTE.
|
||||||
@ -1223,14 +1229,10 @@ static void eapol_handle_ptk_1_of_4(struct eapol_sm *sm,
|
|||||||
ie_build_rsne(&rsn_info, ies);
|
ie_build_rsne(&rsn_info, ies);
|
||||||
ies_len = ies[1] + 2;
|
ies_len = ies[1] + 2;
|
||||||
|
|
||||||
memcpy(ies + ies_len, mde, mde[1] + 2);
|
ies_len += append_ie(ies + ies_len, sm->handshake->mde);
|
||||||
ies_len += mde[1] + 2;
|
ies_len += append_ie(ies + ies_len, sm->handshake->fte);
|
||||||
|
|
||||||
memcpy(ies + ies_len, fte, fte[1] + 2);
|
|
||||||
ies_len += fte[1] + 2;
|
|
||||||
} else {
|
} else {
|
||||||
ies_len = own_ie[1] + 2;
|
ies_len = append_ie(ies, own_ie);
|
||||||
memcpy(ies, own_ie, ies_len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sm->handshake->support_ip_allocation) {
|
if (sm->handshake->support_ip_allocation) {
|
||||||
@ -1242,6 +1244,14 @@ static void eapol_handle_ptk_1_of_4(struct eapol_sm *sm,
|
|||||||
ies[ies_len++] = 0x01;
|
ies[ies_len++] = 0x01;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 802.11-2020, Section 12.7.6.3:
|
||||||
|
* "The RSNXE that the Supplicant sent in its (Re)Association Request
|
||||||
|
* frame, if this element is present in the (Re)Association Request
|
||||||
|
* frame that the Supplicant sent."
|
||||||
|
*/
|
||||||
|
ies_len += append_ie(ies + ies_len, sm->handshake->supplicant_rsnxe);
|
||||||
|
|
||||||
step2 = eapol_create_ptk_2_of_4(sm->protocol_version,
|
step2 = eapol_create_ptk_2_of_4(sm->protocol_version,
|
||||||
ek->key_descriptor_version,
|
ek->key_descriptor_version,
|
||||||
L_BE64_TO_CPU(ek->key_replay_counter),
|
L_BE64_TO_CPU(ek->key_replay_counter),
|
||||||
@ -1552,6 +1562,33 @@ static bool eapol_check_ip_mask(const uint8_t *mask,
|
|||||||
(uint32_t) (mask_uint << __builtin_popcountl(mask_uint)) == 0;
|
(uint32_t) (mask_uint << __builtin_popcountl(mask_uint)) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int eapol_ie_matches(const void *ies, size_t ies_len,
|
||||||
|
enum ie_type type, uint8_t *target_ie)
|
||||||
|
{
|
||||||
|
struct ie_tlv_iter iter;
|
||||||
|
|
||||||
|
ie_tlv_iter_init(&iter, ies, ies_len);
|
||||||
|
|
||||||
|
while (ie_tlv_iter_next(&iter)) {
|
||||||
|
if (ie_tlv_iter_get_tag(&iter) != type)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!target_ie)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (memcmp(ie_tlv_iter_get_data(&iter) - 2,
|
||||||
|
target_ie, target_ie[1] + 2))
|
||||||
|
return -EBADMSG;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!target_ie)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
static void eapol_handle_ptk_3_of_4(struct eapol_sm *sm,
|
static void eapol_handle_ptk_3_of_4(struct eapol_sm *sm,
|
||||||
const struct eapol_key *ek,
|
const struct eapol_key *ek,
|
||||||
const uint8_t *decrypted_key_data,
|
const uint8_t *decrypted_key_data,
|
||||||
@ -1618,10 +1655,7 @@ static void eapol_handle_ptk_3_of_4(struct eapol_sm *sm,
|
|||||||
(IE_RSN_AKM_SUITE_FT_OVER_8021X |
|
(IE_RSN_AKM_SUITE_FT_OVER_8021X |
|
||||||
IE_RSN_AKM_SUITE_FT_USING_PSK |
|
IE_RSN_AKM_SUITE_FT_USING_PSK |
|
||||||
IE_RSN_AKM_SUITE_FT_OVER_SAE_SHA256)) {
|
IE_RSN_AKM_SUITE_FT_OVER_SAE_SHA256)) {
|
||||||
struct ie_tlv_iter iter;
|
|
||||||
struct ie_rsn_info ie_info;
|
struct ie_rsn_info ie_info;
|
||||||
const uint8_t *mde = hs->mde;
|
|
||||||
const uint8_t *fte = hs->fte;
|
|
||||||
|
|
||||||
if (ie_parse_rsne_from_data(rsne, rsne[1] + 2, &ie_info) < 0)
|
if (ie_parse_rsne_from_data(rsne, rsne[1] + 2, &ie_info) < 0)
|
||||||
goto error_ie_different;
|
goto error_ie_different;
|
||||||
@ -1630,27 +1664,34 @@ static void eapol_handle_ptk_3_of_4(struct eapol_sm *sm,
|
|||||||
hs->pmk_r1_name, 16))
|
hs->pmk_r1_name, 16))
|
||||||
goto error_ie_different;
|
goto error_ie_different;
|
||||||
|
|
||||||
ie_tlv_iter_init(&iter, decrypted_key_data,
|
if (eapol_ie_matches(decrypted_key_data,
|
||||||
decrypted_key_data_size);
|
decrypted_key_data_size,
|
||||||
|
IE_TYPE_MOBILITY_DOMAIN,
|
||||||
|
hs->mde) < 0)
|
||||||
|
goto error_ie_different;
|
||||||
|
|
||||||
while (ie_tlv_iter_next(&iter))
|
if (eapol_ie_matches(decrypted_key_data,
|
||||||
switch (ie_tlv_iter_get_tag(&iter)) {
|
decrypted_key_data_size,
|
||||||
case IE_TYPE_MOBILITY_DOMAIN:
|
IE_TYPE_FAST_BSS_TRANSITION,
|
||||||
if (memcmp(ie_tlv_iter_get_data(&iter) - 2,
|
hs->fte) < 0)
|
||||||
mde, mde[1] + 2))
|
goto error_ie_different;
|
||||||
goto error_ie_different;
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case IE_TYPE_FAST_BSS_TRANSITION:
|
|
||||||
if (memcmp(ie_tlv_iter_get_data(&iter) - 2,
|
|
||||||
fte, fte[1] + 2))
|
|
||||||
goto error_ie_different;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 802.11-2020, Section 12.7.6.4:
|
||||||
|
* "If the RSNXE is present, the Supplicant verifies that the RSNXE is
|
||||||
|
* identical to that the STA received in the Beacon or Probe Response
|
||||||
|
* frame."
|
||||||
|
*
|
||||||
|
* Verify only if RSN is used
|
||||||
|
*/
|
||||||
|
if (!hs->osen_ie && !hs->wpa_ie &&
|
||||||
|
eapol_ie_matches(decrypted_key_data,
|
||||||
|
decrypted_key_data_size,
|
||||||
|
IE_TYPE_RSNX,
|
||||||
|
hs->authenticator_rsnxe) < 0)
|
||||||
|
goto error_ie_different;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If ptk_complete is set, then we are receiving Message 3 again.
|
* If ptk_complete is set, then we are receiving Message 3 again.
|
||||||
* It must be a retransmission, otherwise the anonce wouldn't match
|
* It must be a retransmission, otherwise the anonce wouldn't match
|
||||||
|
Loading…
Reference in New Issue
Block a user