tests: EAPOL-Key fuzzing tool

Add test-eapol program that can be used for fuzzing the EAPOL-Key
Supplicant and Authenticator implementations. This tool can write
Supplicant or Authenticator messages into a file as an initialization
step and for the fuzzing step, that file (with potential modifications)
can be used to replace the internally generated message contents.

The TEST_FUZZ=y build parameter is used to make a special build where a
hardcoded random number generator and hardcoded timestamp are used to
force deterministic behavior for the EAPOL-Key operations. This will
also make the implementation ignore Key MIC and AES keywrap errors to
allow processing of modified messages to continue further.

Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2019-02-10 17:02:49 +02:00
parent 02a0a23939
commit 525923b1d7
4 changed files with 709 additions and 0 deletions

View file

@ -345,6 +345,10 @@ static int wpa_group_init_gmk_and_counter(struct wpa_authenticator *wpa_auth,
wpa_get_ntp_timestamp(buf + ETH_ALEN);
ptr = (unsigned long) group;
os_memcpy(buf + ETH_ALEN + 8, &ptr, sizeof(ptr));
#ifdef TEST_FUZZ
os_memset(buf + ETH_ALEN, 0xab, 8);
os_memset(buf + ETH_ALEN + 8, 0xcd, sizeof(ptr));
#endif /* TEST_FUZZ */
if (random_get_bytes(rkey, sizeof(rkey)) < 0)
return -1;
@ -1217,6 +1221,11 @@ continue_processing:
wpa_try_alt_snonce(sm, data, data_len))) {
wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
"received EAPOL-Key with invalid MIC");
#ifdef TEST_FUZZ
wpa_printf(MSG_INFO,
"TEST: Ignore Key MIC failure for fuzz testing");
goto continue_fuzz;
#endif /* TEST_FUZZ */
return;
}
#ifdef CONFIG_FILS
@ -1225,9 +1234,17 @@ continue_processing:
&key_data_length) < 0) {
wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
"received EAPOL-Key with invalid MIC");
#ifdef TEST_FUZZ
wpa_printf(MSG_INFO,
"TEST: Ignore Key MIC failure for fuzz testing");
goto continue_fuzz;
#endif /* TEST_FUZZ */
return;
}
#endif /* CONFIG_FILS */
#ifdef TEST_FUZZ
continue_fuzz:
#endif /* TEST_FUZZ */
sm->MICVerified = TRUE;
eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm);
sm->pending_1_of_4_timeout = 0;
@ -1332,6 +1349,9 @@ static int wpa_gmk_to_gtk(const u8 *gmk, const char *label, const u8 *addr,
os_memcpy(data + ETH_ALEN, gnonce, WPA_NONCE_LEN);
pos = data + ETH_ALEN + WPA_NONCE_LEN;
wpa_get_ntp_timestamp(pos);
#ifdef TEST_FUZZ
os_memset(pos, 0xef, 8);
#endif /* TEST_FUZZ */
pos += 8;
if (random_get_bytes(pos, gtk_len) < 0)
ret = -1;
@ -1611,6 +1631,9 @@ static void wpa_send_eapol(struct wpa_authenticator *wpa_auth,
timeout_ms = eapol_key_timeout_no_retrans;
if (pairwise && ctr == 1 && !(key_info & WPA_KEY_INFO_MIC))
sm->pending_1_of_4_timeout = 1;
#ifdef TEST_FUZZ
timeout_ms = 1;
#endif /* TEST_FUZZ */
wpa_printf(MSG_DEBUG, "WPA: Use EAPOL-Key timeout of %u ms (retry "
"counter %u)", timeout_ms, ctr);
eloop_register_timeout(timeout_ms / 1000, (timeout_ms % 1000) * 1000,

View file

@ -1852,7 +1852,15 @@ static int wpa_supplicant_verify_eapol_key_mic(struct wpa_sm *sm,
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
"WPA: Invalid EAPOL-Key MIC "
"when using TPTK - ignoring TPTK");
#ifdef TEST_FUZZ
wpa_printf(MSG_INFO,
"TEST: Ignore Key MIC failure for fuzz testing");
goto continue_fuzz;
#endif /* TEST_FUZZ */
} else {
#ifdef TEST_FUZZ
continue_fuzz:
#endif /* TEST_FUZZ */
ok = 1;
sm->tptk_set = 0;
sm->ptk_set = 1;
@ -1878,8 +1886,16 @@ static int wpa_supplicant_verify_eapol_key_mic(struct wpa_sm *sm,
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
"WPA: Invalid EAPOL-Key MIC - "
"dropping packet");
#ifdef TEST_FUZZ
wpa_printf(MSG_INFO,
"TEST: Ignore Key MIC failure for fuzz testing");
goto continue_fuzz2;
#endif /* TEST_FUZZ */
return -1;
}
#ifdef TEST_FUZZ
continue_fuzz2:
#endif /* TEST_FUZZ */
ok = 1;
}
@ -1954,14 +1970,25 @@ static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm,
"WPA: No memory for AES-UNWRAP buffer");
return -1;
}
#ifdef TEST_FUZZ
os_memset(buf, 0x11, *key_data_len);
#endif /* TEST_FUZZ */
if (aes_unwrap(sm->ptk.kek, sm->ptk.kek_len, *key_data_len / 8,
key_data, buf)) {
#ifdef TEST_FUZZ
wpa_printf(MSG_INFO,
"TEST: Ignore AES unwrap failure for fuzz testing");
goto continue_fuzz;
#endif /* TEST_FUZZ */
bin_clear_free(buf, *key_data_len);
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
"WPA: AES unwrap failed - "
"could not decrypt EAPOL-Key key data");
return -1;
}
#ifdef TEST_FUZZ
continue_fuzz:
#endif /* TEST_FUZZ */
os_memcpy(key_data, buf, *key_data_len);
bin_clear_free(buf, *key_data_len);
WPA_PUT_BE16(((u8 *) (key + 1)) + mic_len, *key_data_len);