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 if multiple Michael MIC failures are detected with the same PTK (i.e., the Authenticator does not rekey PTK on first failure report). This is disabled by default and can be enabled with a build option CONFIG_DELAYED_MIC_ERROR_REPORT=y in .config. This may help in making a chopchop attack take much longer time by forcing the attacker to wait 60 seconds before knowing whether a modified frame resulted in a MIC failure.
This commit is contained in:
parent
6982784e20
commit
46690a3b9b
6 changed files with 94 additions and 4 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue