[PATCH v2 33/33] FT: do not change ANonce during re-sent auth request

Michael Braun michael-dev at fami-braun.de
Sat Sep 24 13:54:14 PDT 2016


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 at fami-braun.de>
---
 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




More information about the Hostap mailing list