aboutsummaryrefslogtreecommitdiffstats
path: root/hostapd
diff options
context:
space:
mode:
Diffstat (limited to 'hostapd')
-rw-r--r--hostapd/wpa.c52
-rw-r--r--hostapd/wpa_auth_i.h9
2 files changed, 48 insertions, 13 deletions
diff --git a/hostapd/wpa.c b/hostapd/wpa.c
index 946552c..4f56354 100644
--- a/hostapd/wpa.c
+++ b/hostapd/wpa.c
@@ -498,7 +498,7 @@ void wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth,
#endif /* CONFIG_IEEE80211R */
if (sm->started) {
- os_memset(sm->key_replay_counter, 0, WPA_REPLAY_COUNTER_LEN);
+ os_memset(&sm->key_replay, 0, sizeof(sm->key_replay));
sm->ReAuthenticationRequest = TRUE;
wpa_sm_step(sm);
return;
@@ -574,6 +574,21 @@ static void wpa_request_new_ptk(struct wpa_state_machine *sm)
}
+static int wpa_replay_counter_valid(struct wpa_state_machine *sm,
+ const u8 *replay_counter)
+{
+ int i;
+ for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) {
+ if (!sm->key_replay[i].valid)
+ break;
+ if (os_memcmp(replay_counter, sm->key_replay[i].counter,
+ WPA_REPLAY_COUNTER_LEN) == 0)
+ return 1;
+ }
+ return 0;
+}
+
+
void wpa_receive(struct wpa_authenticator *wpa_auth,
struct wpa_state_machine *sm,
u8 *data, size_t data_len)
@@ -672,14 +687,18 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
}
if (!(key_info & WPA_KEY_INFO_REQUEST) &&
- (!sm->key_replay_counter_valid ||
- os_memcmp(key->replay_counter, sm->key_replay_counter,
- WPA_REPLAY_COUNTER_LEN) != 0)) {
+ !wpa_replay_counter_valid(sm, key->replay_counter)) {
+ int i;
wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
"received EAPOL-Key %s with unexpected "
"replay counter", msgtxt);
- wpa_hexdump(MSG_DEBUG, "expected replay counter",
- sm->key_replay_counter, WPA_REPLAY_COUNTER_LEN);
+ for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) {
+ if (!sm->key_replay[i].valid)
+ break;
+ wpa_hexdump(MSG_DEBUG, "pending replay counter",
+ sm->key_replay[i].counter,
+ WPA_REPLAY_COUNTER_LEN);
+ }
wpa_hexdump(MSG_DEBUG, "received replay counter",
key->replay_counter, WPA_REPLAY_COUNTER_LEN);
return;
@@ -842,8 +861,12 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
wpa_rekey_gtk(wpa_auth, NULL);
}
} else {
- /* Do not allow the same key replay counter to be reused. */
- sm->key_replay_counter_valid = FALSE;
+ /* Do not allow the same key replay counter to be reused. This
+ * does also invalidate all other pending replay counters if
+ * retransmissions were used, i.e., we will only process one of
+ * the pending replies and ignore rest if more than one is
+ * received. */
+ sm->key_replay[0].valid = FALSE;
}
#ifdef CONFIG_PEERKEY
@@ -914,6 +937,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
int key_data_len, pad_len = 0;
u8 *buf, *pos;
int version, pairwise;
+ int i;
len = sizeof(struct ieee802_1x_hdr) + sizeof(struct wpa_eapol_key);
@@ -986,10 +1010,16 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
WPA_PUT_BE16(key->key_length, 0);
/* FIX: STSL: what to use as key_replay_counter? */
- inc_byte_array(sm->key_replay_counter, WPA_REPLAY_COUNTER_LEN);
- os_memcpy(key->replay_counter, sm->key_replay_counter,
+ for (i = RSNA_MAX_EAPOL_RETRIES - 1; i > 0; i--) {
+ sm->key_replay[i].valid = sm->key_replay[i - 1].valid;
+ os_memcpy(sm->key_replay[i].counter,
+ sm->key_replay[i - 1].counter,
+ WPA_REPLAY_COUNTER_LEN);
+ }
+ inc_byte_array(sm->key_replay[0].counter, WPA_REPLAY_COUNTER_LEN);
+ os_memcpy(key->replay_counter, sm->key_replay[0].counter,
WPA_REPLAY_COUNTER_LEN);
- sm->key_replay_counter_valid = TRUE;
+ sm->key_replay[0].valid = TRUE;
if (nonce)
os_memcpy(key->key_nonce, nonce, WPA_NONCE_LEN);
diff --git a/hostapd/wpa_auth_i.h b/hostapd/wpa_auth_i.h
index 7770d17..3ee6548 100644
--- a/hostapd/wpa_auth_i.h
+++ b/hostapd/wpa_auth_i.h
@@ -15,6 +15,9 @@
#ifndef WPA_AUTH_I_H
#define WPA_AUTH_I_H
+/* max(dot11RSNAConfigGroupUpdateCount,dot11RSNAConfigPairwiseUpdateCount) */
+#define RSNA_MAX_EAPOL_RETRIES 3
+
struct wpa_group;
struct wpa_stsl_negotiation {
@@ -66,8 +69,10 @@ struct wpa_state_machine {
Boolean pairwise_set;
int keycount;
Boolean Pair;
- u8 key_replay_counter[WPA_REPLAY_COUNTER_LEN];
- Boolean key_replay_counter_valid;
+ struct {
+ u8 counter[WPA_REPLAY_COUNTER_LEN];
+ Boolean valid;
+ } key_replay[RSNA_MAX_EAPOL_RETRIES];
Boolean PInitAKeys; /* WPA only, not in IEEE 802.11i */
Boolean PTKRequest; /* not in IEEE 802.11i state machine */
Boolean has_GTK;