mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2025-01-03 19:02:34 +01:00
eapol: Tighten up replay counter handling
This commit is contained in:
parent
5b6c18fadd
commit
c1a0e844b0
70
src/eapol.c
70
src/eapol.c
@ -991,7 +991,7 @@ static void eapol_handle_ptk_1_of_4(struct eapol_sm *sm,
|
||||
|
||||
step2 = eapol_create_ptk_2_of_4(sm->protocol_version,
|
||||
ek->key_descriptor_version,
|
||||
sm->replay_counter,
|
||||
L_BE64_TO_CPU(ek->key_replay_counter),
|
||||
sm->handshake->snonce, ies_len, ies,
|
||||
sm->handshake->wpa_ie);
|
||||
|
||||
@ -1086,9 +1086,11 @@ static void eapol_handle_ptk_3_of_4(struct eapol_sm *sm,
|
||||
}
|
||||
|
||||
/*
|
||||
* 11.6.6.4: "On reception of Message 3, the Supplicant silently
|
||||
* discards the message if ... or if the ANonce value in Message 3
|
||||
* differs from the ANonce value in Message 1"
|
||||
* 802.11-2016, Section 12.7.6.4:
|
||||
* "On reception of message 3, the Supplicant silently discards the
|
||||
* message if the Key Replay Counter field value has already been used
|
||||
* or if the ANonce value in message 3 differs from the ANonce value
|
||||
* in message 1."
|
||||
*/
|
||||
if (memcmp(sm->handshake->anonce, ek->key_nonce, sizeof(ek->key_nonce)))
|
||||
return;
|
||||
@ -1239,6 +1241,18 @@ static void eapol_handle_ptk_3_of_4(struct eapol_sm *sm,
|
||||
} else
|
||||
igtk = NULL;
|
||||
|
||||
/*
|
||||
* 802.11-2016, Section 12.7.6.4:
|
||||
* "b) Verifies the message 3 MIC. If the calculated MIC does not match
|
||||
* the MIC that the Authenticator included in the EAPOL-Key frame, the
|
||||
* Supplicant silently discards message 3."
|
||||
* "c) Updates the last-seen value of the Key Replay Counter field."
|
||||
*
|
||||
* Note that part b was done in eapol_key_handle
|
||||
*/
|
||||
sm->replay_counter = L_BE64_TO_CPU(ek->key_replay_counter);
|
||||
sm->have_replay = true;
|
||||
|
||||
step4 = eapol_create_ptk_4_of_4(sm->protocol_version,
|
||||
ek->key_descriptor_version,
|
||||
sm->replay_counter,
|
||||
@ -1330,6 +1344,24 @@ static void eapol_handle_gtk_1_of_2(struct eapol_sm *sm,
|
||||
} else
|
||||
igtk = NULL;
|
||||
|
||||
/*
|
||||
* 802.11-2016, Section 12.7.7.2:
|
||||
* "
|
||||
* a) Verifies that the Key Replay Counter field value has not yet been
|
||||
* seen before, i.e., its value is strictly larger than that in any
|
||||
* other EAPOL-Key frame received thus far during this session.
|
||||
* b) Verifies that the MIC is valid, i.e., it uses the KCK that is
|
||||
* part of the PTK to verify that there is no data integrity error.
|
||||
* c) Uses the MLME-SETKEYS.request primitive to configure the temporal
|
||||
* GTK and, when present, IGTK into its IEEE 802.11 MAC.
|
||||
* d) Responds by creating and sending message 2 of the group key
|
||||
* handshake to the Authenticator and incrementing the replay counter.
|
||||
* "
|
||||
* Note: steps a & b are performed in eapol_key_handle
|
||||
*/
|
||||
sm->replay_counter = L_BE64_TO_CPU(ek->key_replay_counter);
|
||||
sm->have_replay = true;
|
||||
|
||||
step2 = eapol_create_gtk_2_of_2(sm->protocol_version,
|
||||
ek->key_descriptor_version,
|
||||
sm->replay_counter,
|
||||
@ -1406,20 +1438,32 @@ static void eapol_key_handle(struct eapol_sm *sm,
|
||||
replay_counter = L_BE64_TO_CPU(ek->key_replay_counter);
|
||||
|
||||
/*
|
||||
* 11.6.6.2: "If the Key Replay Counter field value is less than or
|
||||
* equal to the current local value, the Supplicant discards the
|
||||
* message.
|
||||
* 802.11-2016, Section 12.7.2:
|
||||
* "The Supplicant and Authenticator shall track the key replay counter
|
||||
* per security association. The key replay counter shall be
|
||||
* initialized to 0 on (re)association. The Authenticator shall
|
||||
* increment the key replay counter on each successive EAPOL-Key frame."
|
||||
*
|
||||
* 11.6.6.4: "On reception of Message 3, the Supplicant silently
|
||||
* discards the message if the Key Replay Counter field value has
|
||||
* already been used...
|
||||
* and
|
||||
*
|
||||
* "The Supplicant should also use the key replay counter and ignore
|
||||
* EAPOL-Key frames with a Key Replay Counter field value smaller than
|
||||
* or equal to any received in a valid message. The local Key Replay
|
||||
* Counter field should not be updated until after the EAPOL-Key MIC is
|
||||
* checked and is found to be valid. In other words, the Supplicant
|
||||
* never updates the Key Replay Counter field for message 1 in the
|
||||
* 4-way handshake, as it includes no MIC. This implies the Supplicant
|
||||
* needs to allow for retransmission of message 1 when checking for
|
||||
* the key replay counter of message 3."
|
||||
*
|
||||
* Note: The latter condition implies that Message 1 and Message 3
|
||||
* can have the same replay counter, though other parts of the spec
|
||||
* mandate that the Authenticator has to increment the replay counter
|
||||
* for each frame sent. Contradictory.
|
||||
*/
|
||||
if (sm->have_replay && sm->replay_counter >= replay_counter)
|
||||
return;
|
||||
|
||||
sm->replay_counter = replay_counter;
|
||||
sm->have_replay = true;
|
||||
|
||||
ptk = handshake_state_get_ptk(sm->handshake);
|
||||
|
||||
if (ek->key_mic) {
|
||||
|
Loading…
Reference in New Issue
Block a user