From 29818cbd2d4fc8aee50d632335a31028b614ae1a Mon Sep 17 00:00:00 2001 From: Sowmiya Sree Elavalagan Date: Thu, 10 Feb 2022 12:30:25 +0530 Subject: [PATCH] hostapd:Fix race condition in four way handshake When there is multiple delayed m2 from the station, after ap has tried m3 multiple times, ap tends to send m3 again for the later received m2 incrementing the replay counter. Here station replies with m4 only for the first m3, but replay counter would have advanced to higher number due to multiple m3 retries. Due to replay counter mismatch m4 is discarded and station association fails. Added a flag to stop processing m2 if state machine has already advanced to m3 state, this prevent m3 triggered in response for m2 there by preventing the race condition with respect to replay counter Signed-off-by: Sowmiya Sree Elavalagan --- src/ap/wpa_auth.c | 3 ++- src/ap/wpa_auth_i.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -1150,7 +1150,7 @@ void wpa_receive(struct wpa_authenticato !wpa_replay_counter_valid(sm->key_replay, key->replay_counter)) { int i; - if (msg == PAIRWISE_2 && + if (msg == PAIRWISE_2 && !sm->m3_retried && wpa_replay_counter_valid(sm->prev_key_replay, key->replay_counter) && sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING && @@ -3753,6 +3753,7 @@ SM_STEP(WPA_PTK) } break; case WPA_PTK_INITPSK: + sm->m3_retried = 0; if (wpa_auth_get_psk(wpa_auth, sm->addr, sm->p2p_dev_addr, NULL, NULL, NULL)) { SM_ENTER(WPA_PTK, PTKSTART); @@ -3811,8 +3812,10 @@ SM_STEP(WPA_PTK) sm->disconnect_reason = WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT; SM_ENTER(WPA_PTK, DISCONNECT); - } else if (sm->TimeoutEvt) + } else if (sm->TimeoutEvt) { + sm->m3_retried = 1; SM_ENTER(WPA_PTK, PTKINITNEGOTIATING); + } break; case WPA_PTK_PTKINITDONE: break; --- a/src/ap/wpa_auth_i.h +++ b/src/ap/wpa_auth_i.h @@ -95,6 +95,7 @@ struct wpa_state_machine { #endif /* CONFIG_IEEE80211R_AP */ unsigned int is_wnmsleep:1; unsigned int pmkid_set:1; + unsigned int m3_retried:1; #ifdef CONFIG_OCV int ocv_enabled;