[PATCH 2/2] SAE: implement retransmission timer

Bob Copeland me
Tue Jan 6 22:10:57 PST 2015


Add the t0 retransmission timer as specified by 802.11-2012 11.3.8.4.
This makes SAE much more likely to succeed in the case of lost frames.

Signed-off-by: Bob Copeland <me at bobcopeland.com>
---
 src/ap/ieee802_11.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 src/common/sae.h    |  1 +
 2 files changed, 83 insertions(+), 1 deletion(-)

diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 015cfe0..f896bdc 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -328,6 +328,10 @@ static void handle_auth_ft_finish(void *ctx, const u8 *dst, const u8 *bssid,
 
 #ifdef CONFIG_SAE
 
+#define dot11RSNASAERetransPeriod 40	/* msec */
+#define dot11RSNASAESync 5		/* attempts */
+
+
 static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd,
 					     struct sta_info *sta, int update)
 {
@@ -483,6 +487,43 @@ static struct wpabuf * auth_build_token_req(struct hostapd_data *hapd,
 }
 
 
+static int sae_check_big_sync(struct sta_info *sta)
+{
+	if (sta->sae->sync > dot11RSNASAESync) {
+		sta->sae->state = SAE_NOTHING;
+		sta->sae->sync = 0;
+		return -1;
+	}
+	return 0;
+}
+
+
+static void auth_sae_retransmit_timer(void *eloop_ctx, void *eloop_data)
+{
+	struct hostapd_data *hapd = eloop_ctx;
+	struct sta_info *sta = eloop_data;
+
+	if (sae_check_big_sync(sta))
+		return;
+	sta->sae->sync++;
+
+	switch (sta->sae->state) {
+	case SAE_COMMITTED:
+		auth_sae_send_commit(hapd, sta, hapd->own_addr, 0);
+		eloop_register_timeout(0, dot11RSNASAERetransPeriod * 1000,
+				       auth_sae_retransmit_timer, hapd, sta);
+		break;
+	case SAE_CONFIRMED:
+		auth_sae_send_confirm(hapd, sta, hapd->own_addr);
+		eloop_register_timeout(0, dot11RSNASAERetransPeriod * 1000,
+				       auth_sae_retransmit_timer, hapd, sta);
+		break;
+	default:
+		break;
+	}
+}
+
+
 static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
 		       const u8 *bssid, u8 auth_transaction)
 {
@@ -530,6 +571,10 @@ static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
 				 * when receiving Confirm from STA.
 				 */
 			}
+			sta->sae->sync = 0;
+			eloop_register_timeout(0, dot11RSNASAERetransPeriod * 1000,
+					       auth_sae_retransmit_timer,
+					       hapd, sta);
 		} else {
 			hostapd_logger(hapd, sta->addr,
 				       HOSTAPD_MODULE_IEEE80211,
@@ -538,6 +583,7 @@ static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
 		}
 		break;
 	case SAE_COMMITTED:
+		eloop_cancel_timeout(auth_sae_retransmit_timer, hapd, sta);
 		if (auth_transaction == 1) {
 			if (sae_process_commit(sta->sae) < 0)
 				return WLAN_STATUS_UNSPECIFIED_FAILURE;
@@ -546,14 +592,26 @@ static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
 			if (ret)
 				return ret;
 			sta->sae->state = SAE_CONFIRMED;
+			sta->sae->sync = 0;
+			eloop_register_timeout(0, dot11RSNASAERetransPeriod * 1000,
+					       auth_sae_retransmit_timer,
+					       hapd, sta);
 		} else if (hapd->conf->mesh & MESH_ENABLED) {
 			/*
 			 * In mesh case, follow SAE finite state machine and
-			 * send Commit now.
+			 * send Commit now, if sync count allows.
 			 */
+			if (sae_check_big_sync(sta))
+				return WLAN_STATUS_SUCCESS;
+			sta->sae->sync++;
+
 			ret = auth_sae_send_commit(hapd, sta, bssid, 1);
 			if (ret)
 				return ret;
+
+			eloop_register_timeout(0, dot11RSNASAERetransPeriod * 1000,
+					       auth_sae_retransmit_timer,
+					       hapd, sta);
 		} else {
 			/*
 			 * For instructure BSS, send the postponed Confirm from
@@ -575,7 +633,12 @@ static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
 		}
 		break;
 	case SAE_CONFIRMED:
+		eloop_cancel_timeout(auth_sae_retransmit_timer, hapd, sta);
 		if (auth_transaction == 1) {
+			if (sae_check_big_sync(sta))
+				return WLAN_STATUS_SUCCESS;
+			sta->sae->sync++;
+
 			ret = auth_sae_send_commit(hapd, sta, bssid, 1);
 			if (ret)
 				return ret;
@@ -586,6 +649,10 @@ static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
 			ret = auth_sae_send_confirm(hapd, sta, bssid);
 			if (ret)
 				return ret;
+
+			eloop_register_timeout(0, dot11RSNASAERetransPeriod * 1000,
+					       auth_sae_retransmit_timer,
+					       hapd, sta);
 		} else {
 			sta->flags |= WLAN_STA_AUTH;
 			sta->auth_alg = WLAN_AUTH_SAE;
@@ -603,6 +670,10 @@ static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
 				   MAC2STR(sta->addr));
 			ap_free_sta(hapd, sta);
 		} else {
+			if (sae_check_big_sync(sta))
+				return WLAN_STATUS_SUCCESS;
+			sta->sae->sync++;
+
 			ret = auth_sae_send_confirm(hapd, sta, bssid);
 			sae_clear_temp_data(sta->sae);
 			if (ret)
@@ -632,6 +703,7 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
 		if (sta->sae == NULL)
 			return;
 		sta->sae->state = SAE_NOTHING;
+		sta->sae->sync = 0;
 	}
 
 	if (auth_transaction == 1) {
@@ -685,6 +757,12 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
 				return;
 			}
 			sta->sae->state = SAE_COMMITTED;
+			eloop_cancel_timeout(auth_sae_retransmit_timer,
+					     hapd, sta);
+			sta->sae->sync = 0;
+			eloop_register_timeout(0, dot11RSNASAERetransPeriod * 1000,
+					       auth_sae_retransmit_timer,
+					       hapd, sta);
 			return;
 		}
 
@@ -782,6 +860,9 @@ int auth_sae_init_committed(struct hostapd_data *hapd, struct sta_info *sta)
 		return -1;
 
 	sta->sae->state = SAE_COMMITTED;
+	sta->sae->sync = 0;
+	eloop_register_timeout(0, dot11RSNASAERetransPeriod * 1000,
+			       auth_sae_retransmit_timer, hapd, sta);
 
 	return 0;
 }
diff --git a/src/common/sae.h b/src/common/sae.h
index 89d74ab..3ebf40c 100644
--- a/src/common/sae.h
+++ b/src/common/sae.h
@@ -44,6 +44,7 @@ struct sae_data {
 	u8 pmk[SAE_PMK_LEN];
 	struct crypto_bignum *peer_commit_scalar;
 	int group;
+	int sync;
 	struct sae_temporary_data *tmp;
 };
 
-- 
2.1.4




More information about the Hostap mailing list