From 7fad6590bdc52b7810f24d4fdad85b54df853678 Mon Sep 17 00:00:00 2001 From: James Prestwood Date: Fri, 24 Jun 2022 16:07:40 -0700 Subject: [PATCH] eapol: allow 'secure' to be set on rekeys About a month ago hostapd was changed to set the secure bit on eapol frames during rekeys (bc36991791). The spec is ambiguous about this and has conflicting info depending on the sections you read (12.7.2 vs 12.7.6). According to the hostapd commit log TGme is trying to clarify this and wants to set secure=1 in the case of rekeys. Because of this, IWD is completely broken with rekeys since its disallows secure=1 on PTK 1/4 and 2/4. Now, a bool is passed to the verify functions which signifies if the PTK has been negotiated already. If secure differs from this the key frame is not verified. --- src/eapol.c | 14 ++++++++------ src/eapol.h | 5 +++-- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/eapol.c b/src/eapol.c index 9f885d02..e8bd5cdb 100644 --- a/src/eapol.c +++ b/src/eapol.c @@ -443,7 +443,8 @@ static void eapol_key_data_append(struct eapol_key *ek, if (ek->error) \ return false \ -bool eapol_verify_ptk_1_of_4(const struct eapol_key *ek, size_t mic_len) +bool eapol_verify_ptk_1_of_4(const struct eapol_key *ek, size_t mic_len, + bool ptk_complete) { /* Verify according to 802.11, Section 11.6.6.2 */ VERIFY_PTK_COMMON(ek); @@ -457,7 +458,7 @@ bool eapol_verify_ptk_1_of_4(const struct eapol_key *ek, size_t mic_len) if (ek->key_mic) return false; - if (ek->secure) + if (ek->secure != ptk_complete) return false; if (ek->encrypted_key_data) @@ -475,7 +476,7 @@ bool eapol_verify_ptk_1_of_4(const struct eapol_key *ek, size_t mic_len) return true; } -bool eapol_verify_ptk_2_of_4(const struct eapol_key *ek) +bool eapol_verify_ptk_2_of_4(const struct eapol_key *ek, bool ptk_complete) { uint16_t key_len; @@ -491,7 +492,7 @@ bool eapol_verify_ptk_2_of_4(const struct eapol_key *ek) if (!ek->key_mic) return false; - if (ek->secure) + if (ek->secure != ptk_complete) return false; if (ek->encrypted_key_data) @@ -1151,7 +1152,8 @@ static void eapol_handle_ptk_1_of_4(struct eapol_sm *sm, l_debug("ifindex=%u", sm->handshake->ifindex); - if (!eapol_verify_ptk_1_of_4(ek, sm->mic_len)) + if (!eapol_verify_ptk_1_of_4(ek, sm->mic_len, + sm->handshake->ptk_complete)) return; if (sm->handshake->ptk_complete && unencrypted) { @@ -1523,7 +1525,7 @@ static void eapol_handle_ptk_2_of_4(struct eapol_sm *sm, l_debug("ifindex=%u", sm->handshake->ifindex); - if (!eapol_verify_ptk_2_of_4(ek)) + if (!eapol_verify_ptk_2_of_4(ek, sm->handshake->ptk_complete)) return; if (L_BE64_TO_CPU(ek->key_replay_counter) != sm->replay_counter) diff --git a/src/eapol.h b/src/eapol.h index 53ae6e8f..8d8d5252 100644 --- a/src/eapol.h +++ b/src/eapol.h @@ -65,8 +65,9 @@ uint8_t *eapol_decrypt_key_data(enum ie_rsn_akm_suite akm, const uint8_t *kek, const struct eapol_key *frame, size_t *decrypted_size, size_t mic_len); -bool eapol_verify_ptk_1_of_4(const struct eapol_key *ek, size_t mic_len); -bool eapol_verify_ptk_2_of_4(const struct eapol_key *ek); +bool eapol_verify_ptk_1_of_4(const struct eapol_key *ek, size_t mic_len, + bool ptk_complete); +bool eapol_verify_ptk_2_of_4(const struct eapol_key *ek, bool ptk_complete); bool eapol_verify_ptk_3_of_4(const struct eapol_key *ek, bool is_wpa, size_t mic_len); bool eapol_verify_ptk_4_of_4(const struct eapol_key *ek, bool is_wpa);