aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--wpa_supplicant/ChangeLog4
-rw-r--r--wpa_supplicant/Makefile4
-rw-r--r--wpa_supplicant/defconfig4
-rw-r--r--wpa_supplicant/events.c75
-rw-r--r--wpa_supplicant/wpa_supplicant_i.h4
-rw-r--r--wpa_supplicant/wpas_glue.c7
6 files changed, 94 insertions, 4 deletions
diff --git a/wpa_supplicant/ChangeLog b/wpa_supplicant/ChangeLog
index c41d2e8..1f7d8d6 100644
--- a/wpa_supplicant/ChangeLog
+++ b/wpa_supplicant/ChangeLog
@@ -8,6 +8,10 @@ ChangeLog for wpa_supplicant
* added a new network configuration option, wpa_ptk_rekey, that can be
used to enforce frequent PTK rekeying, e.g., to mitigate some attacks
against TKIP deficiencies
+ * added an optional mitigation mechanism for certain attacks against
+ TKIP by delaying Michael MIC error reports by a random amount of time
+ between 0 and 60 seconds; this can be enabled with a build option
+ CONFIG_DELAYED_MIC_ERROR_REPORT=y in .config
* fixed EAP-AKA to use RES Length field in AT_RES as length in bits,
not bytes
diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile
index badda34..277894c 100644
--- a/wpa_supplicant/Makefile
+++ b/wpa_supplicant/Makefile
@@ -951,6 +951,10 @@ ifdef CONFIG_DEBUG_FILE
CFLAGS += -DCONFIG_DEBUG_FILE
endif
+ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
+CFLAGS += -DCONFIG_DELAYED_MIC_ERROR_REPORT
+endif
+
OBJS += ../src/drivers/scan_helpers.o
OBJS_wpa_rm := ctrl_iface.o mlme.o ctrl_iface_unix.o
diff --git a/wpa_supplicant/defconfig b/wpa_supplicant/defconfig
index 38435cd..2653654 100644
--- a/wpa_supplicant/defconfig
+++ b/wpa_supplicant/defconfig
@@ -364,3 +364,7 @@ CONFIG_PEERKEY=y
# Enable privilege separation (see README 'Privilege separation' for details)
#CONFIG_PRIVSEP=y
+
+# Enable mitigation against certain attacks against TKIP by delaying Michael
+# MIC error reports by a random amount of time between 0 and 60 seconds
+#CONFIG_DELAYED_MIC_ERROR_REPORT=y
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 45b5ac3..27dfd55 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -862,6 +862,22 @@ static void wpa_supplicant_event_disassoc(struct wpa_supplicant *wpa_s)
}
+#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
+static void wpa_supplicant_delayed_mic_error_report(void *eloop_ctx,
+ void *sock_ctx)
+{
+ struct wpa_supplicant *wpa_s = eloop_ctx;
+
+ if (!wpa_s->pending_mic_error_report)
+ return;
+
+ wpa_printf(MSG_DEBUG, "WPA: Sending pending MIC error report");
+ wpa_sm_key_request(wpa_s->wpa, 1, wpa_s->pending_mic_error_pairwise);
+ wpa_s->pending_mic_error_report = 0;
+}
+#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
+
+
static void
wpa_supplicant_event_michael_mic_failure(struct wpa_supplicant *wpa_s,
union wpa_event_data *data)
@@ -871,10 +887,25 @@ wpa_supplicant_event_michael_mic_failure(struct wpa_supplicant *wpa_s,
wpa_msg(wpa_s, MSG_WARNING, "Michael MIC failure detected");
pairwise = (data && data->michael_mic_failure.unicast);
- wpa_sm_key_request(wpa_s->wpa, 1, pairwise);
os_get_time(&t);
- if (wpa_s->last_michael_mic_error &&
- t.sec - wpa_s->last_michael_mic_error <= 60) {
+ if ((wpa_s->last_michael_mic_error &&
+ t.sec - wpa_s->last_michael_mic_error <= 60) ||
+ wpa_s->pending_mic_error_report) {
+ if (wpa_s->pending_mic_error_report) {
+ /*
+ * Send the pending MIC error report immediately since
+ * we are going to start countermeasures and AP better
+ * do the same.
+ */
+ wpa_sm_key_request(wpa_s->wpa, 1,
+ wpa_s->pending_mic_error_pairwise);
+ }
+
+ /* Send the new MIC error report immediately since we are going
+ * to start countermeasures and AP better do the same.
+ */
+ wpa_sm_key_request(wpa_s->wpa, 1, pairwise);
+
/* initialize countermeasures */
wpa_s->countermeasures = 1;
wpa_msg(wpa_s, MSG_WARNING, "TKIP countermeasures started");
@@ -895,8 +926,46 @@ wpa_supplicant_event_michael_mic_failure(struct wpa_supplicant *wpa_s,
wpa_s, NULL);
/* TODO: mark the AP rejected for 60 second. STA is
* allowed to associate with another AP.. */
+ } else {
+#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
+ if (wpa_s->mic_errors_seen) {
+ /*
+ * Reduce the effectiveness of Michael MIC error
+ * reports as a means for attacking against TKIP if
+ * more than one MIC failure is noticed with the same
+ * PTK. We delay the transmission of the reports by a
+ * random time between 0 and 60 seconds in order to
+ * force the attacker wait 60 seconds before getting
+ * the information on whether a frame resulted in a MIC
+ * failure.
+ */
+ u8 rval[4];
+ int sec;
+
+ if (os_get_random(rval, sizeof(rval)) < 0)
+ sec = os_random() % 60;
+ else
+ sec = WPA_GET_BE32(rval) % 60;
+ wpa_printf(MSG_DEBUG, "WPA: Delay MIC error report %d "
+ "seconds", sec);
+ wpa_s->pending_mic_error_report = 1;
+ wpa_s->pending_mic_error_pairwise = pairwise;
+ eloop_cancel_timeout(
+ wpa_supplicant_delayed_mic_error_report,
+ wpa_s, NULL);
+ eloop_register_timeout(
+ sec, os_random() % 1000000,
+ wpa_supplicant_delayed_mic_error_report,
+ wpa_s, NULL);
+ } else {
+ wpa_sm_key_request(wpa_s->wpa, 1, pairwise);
+ }
+#else /* CONFIG_DELAYED_MIC_ERROR_REPORT */
+ wpa_sm_key_request(wpa_s->wpa, 1, pairwise);
+#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
}
wpa_s->last_michael_mic_error = t.sec;
+ wpa_s->mic_errors_seen++;
}
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 9afae2a..a8fb6d2 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -334,6 +334,10 @@ struct wpa_supplicant {
struct wpa_client_mlme mlme;
int use_client_mlme;
int driver_4way_handshake;
+
+ int pending_mic_error_report;
+ int pending_mic_error_pairwise;
+ int mic_errors_seen; /* Michael MIC errors with the current PTK */
};
diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
index d5e31eb..e1e2cd6 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -427,11 +427,16 @@ static int wpa_supplicant_get_bssid(void *ctx, u8 *bssid)
}
-static int wpa_supplicant_set_key(void *wpa_s, wpa_alg alg,
+static int wpa_supplicant_set_key(void *_wpa_s, wpa_alg alg,
const u8 *addr, int key_idx, int set_tx,
const u8 *seq, size_t seq_len,
const u8 *key, size_t key_len)
{
+ struct wpa_supplicant *wpa_s = _wpa_s;
+ if (alg == WPA_ALG_TKIP && key_idx == 0 && key_len == 32) {
+ /* Clear the MIC error counter when setting a new PTK. */
+ wpa_s->mic_errors_seen = 0;
+ }
return wpa_drv_set_key(wpa_s, alg, addr, key_idx, set_tx, seq, seq_len,
key, key_len);
}