The A-Nonce generation is in the authentication request processing that has strict timing requirements on client side and mac80211 will automatically resend the request if the AP does not answer within time. Generating the reply might involve querying RADIUS and PMK-R0-Holder using RRB as well as FT key derivation and vlan_add_dynamic. This might take longer than the client expects and thus trigger authentication request resend. If the client resends the authentication request not while hostapd is waiting for RADIUS or RRB pull reply but while it is processing RRB reply (or shortly blocked for other reasons while RRB reply is already in receive buffer), hostapd will process the second request after it has send out the first authentication reply. For me, this has only happened with address sanitizer enabled. Processing the second authentication request will overwrite the first A-Nonce, though the client (wpa_supplicant) will the the first A-Nonce. Signed-off-by: Michael Braun <michael-dev@xxxxxxxxxxxxx> --- src/ap/wpa_auth.h | 1 + src/ap/wpa_auth_ft.c | 30 ++++++++++++++++++++++++++++-- src/ap/wpa_auth_i.h | 1 + 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index 5ec0343..15994bf 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -16,6 +16,7 @@ #include "vlan.h" #define MAX_OWN_IE_OVERRIDE 256 +#define FT_ANONCE_TIMEOUT 5 #ifdef _MSC_VER #pragma pack(push, 1) diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c index 409cbc6..9d85eb0 100644 --- a/src/ap/wpa_auth_ft.c +++ b/src/ap/wpa_auth_ft.c @@ -1809,6 +1809,7 @@ static int wpa_ft_process_auth_req(struct wpa_state_machine *sm, struct vlan_description vlan; const u8 *identity, *radius_cui; size_t identity_len = 0, radius_cui_len = 0; + struct os_reltime now; *resp_ies = NULL; *resp_ies_len = 0; @@ -1839,6 +1840,9 @@ static int wpa_ft_process_auth_req(struct wpa_state_machine *sm, return WLAN_STATUS_INVALID_FTIE; } + if (os_memcmp(ftie->snonce, sm->SNonce, WPA_NONCE_LEN) != 0) + /* do not reuse A-Nonce if S-Nonce differs */ + sm->ANonceTimestamp = 0; os_memcpy(sm->SNonce, ftie->snonce, WPA_NONCE_LEN); if (parse.r0kh_id == NULL) { @@ -1891,17 +1895,36 @@ static int wpa_ft_process_auth_req(struct wpa_state_machine *sm, sm->pmk_r1_name_valid = 1; os_memcpy(sm->pmk_r1_name, pmk_r1_name, WPA_PMK_NAME_LEN); + /* if the second authentication requests comes in very very quickly, + * it might be a client resend. Do not touch A-Nonce then. + */ + + os_get_reltime(&now); + if (sm->ANonceTimestamp && + sm->ANonceTimestamp < now.sec - FT_ANONCE_TIMEOUT) + sm->ANonceTimestamp = 0; + + if (sm->ANonceTimestamp) { + wpa_hexdump(MSG_DEBUG, "FT: Reuse ANonce", + sm->ANonce, WPA_NONCE_LEN); + goto skip_anonce; + } + if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) { wpa_printf(MSG_DEBUG, "FT: Failed to get random data for " "ANonce"); return WLAN_STATUS_UNSPECIFIED_FAILURE; } - wpa_hexdump(MSG_DEBUG, "FT: Received SNonce", - sm->SNonce, WPA_NONCE_LEN); wpa_hexdump(MSG_DEBUG, "FT: Generated ANonce", sm->ANonce, WPA_NONCE_LEN); + sm->ANonceTimestamp = now.sec; +skip_anonce: + + wpa_hexdump(MSG_DEBUG, "FT: Received SNonce", + sm->SNonce, WPA_NONCE_LEN); + if (wpa_pmk_r1_to_ptk(pmk_r1, sm->SNonce, sm->ANonce, sm->addr, sm->wpa_auth->addr, pmk_r1_name, &sm->PTK, ptk_name, sm->wpa_key_mgmt, @@ -2018,6 +2041,9 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, if (sm == NULL) return WLAN_STATUS_UNSPECIFIED_FAILURE; + /* station entered ASSOC state, so next AUTH will get new ANonce */ + sm->ANonceTimestamp = 0; + wpa_hexdump(MSG_DEBUG, "FT: Reassoc Req IEs", ies, ies_len); if (wpa_ft_parse_ies(ies, ies_len, &parse) < 0) { diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h index eb5d03e..53268ab 100644 --- a/src/ap/wpa_auth_i.h +++ b/src/ap/wpa_auth_i.h @@ -57,6 +57,7 @@ struct wpa_state_machine { Boolean MICVerified; Boolean GUpdateStationKeys; u8 ANonce[WPA_NONCE_LEN]; + int ANonceTimestamp; u8 SNonce[WPA_NONCE_LEN]; u8 alt_SNonce[WPA_NONCE_LEN]; u8 alt_replay_counter[WPA_REPLAY_COUNTER_LEN]; -- 2.1.4 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap