From de94be0acde87f727ab8482761127d24fae71a73 Mon Sep 17 00:00:00 2001
From: Jouni Malinen <j@w1.fi>
Date: Sat, 4 May 2019 19:17:45 +0300
Subject: [PATCH] Enforce that IEEE 802.1X EAPOL-Key Replay Counter increases

While this should not happen in practical use cases,
wpa_get_ntp_timestamp() could return the same value when called twice in
a row quickly. Work around that case by enforcing a new Replay Counter
value based on stored last value.

Signed-off-by: Jouni Malinen <j@w1.fi>
---
 src/ap/hostapd.h    |  2 ++
 src/ap/ieee802_1x.c | 15 +++++++++++++++
 2 files changed, 17 insertions(+)

diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index 594699f3c..f573717d1 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -384,6 +384,8 @@ struct hostapd_data {
 	unsigned int num_backlogged_sta;
 	unsigned int airtime_weight;
 #endif /* CONFIG_AIRTIME_POLICY */
+
+	u8 last_1x_eapol_key_replay_counter[8];
 };
 
 
diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c
index 97f503f75..09ec16b8b 100644
--- a/src/ap/ieee802_1x.c
+++ b/src/ap/ieee802_1x.c
@@ -157,6 +157,21 @@ static void ieee802_1x_tx_key_one(struct hostapd_data *hapd,
 	key->type = EAPOL_KEY_TYPE_RC4;
 	WPA_PUT_BE16(key->key_length, key_len);
 	wpa_get_ntp_timestamp(key->replay_counter);
+	if (os_memcmp(key->replay_counter,
+		      hapd->last_1x_eapol_key_replay_counter,
+		      IEEE8021X_REPLAY_COUNTER_LEN) <= 0) {
+		/* NTP timestamp did not increment from last EAPOL-Key frame;
+		 * use previously used value + 1 instead. */
+		inc_byte_array(hapd->last_1x_eapol_key_replay_counter,
+			       IEEE8021X_REPLAY_COUNTER_LEN);
+		os_memcpy(key->replay_counter,
+			  hapd->last_1x_eapol_key_replay_counter,
+			  IEEE8021X_REPLAY_COUNTER_LEN);
+	} else {
+		os_memcpy(hapd->last_1x_eapol_key_replay_counter,
+			  key->replay_counter,
+			  IEEE8021X_REPLAY_COUNTER_LEN);
+	}
 
 	if (random_get_bytes(key->key_iv, sizeof(key->key_iv))) {
 		wpa_printf(MSG_ERROR, "Could not get random numbers");