[PATCH] supplicant: Allow corrupting EAPOL message responses.
greearb at candelatech.com
greearb at candelatech.com
Wed Jan 25 07:44:00 PST 2017
From: Ben Greear <greearb at candelatech.com>
Good for testing the peer's state machine logic.
Signed-off-by: Ben Greear <greearb at candelatech.com>
---
src/rsn_supp/peerkey.c | 10 ++++----
src/rsn_supp/wpa.c | 50 ++++++++++++++++++++++++++++++++++----
src/rsn_supp/wpa.h | 23 ++++++++++++++++--
src/rsn_supp/wpa_i.h | 7 +++++-
wpa_supplicant/config.c | 9 +++++++
wpa_supplicant/config.h | 6 +++++
wpa_supplicant/wpa_supplicant.c | 1 -
wpa_supplicant/wpa_supplicant.conf | 6 +++++
wpa_supplicant/wpas_glue.c | 9 +++++++
9 files changed, 107 insertions(+), 14 deletions(-)
diff --git a/src/rsn_supp/peerkey.c b/src/rsn_supp/peerkey.c
index ce338f8..f674213 100644
--- a/src/rsn_supp/peerkey.c
+++ b/src/rsn_supp/peerkey.c
@@ -114,7 +114,7 @@ static int wpa_supplicant_send_smk_error(struct wpa_sm *sm, const u8 *dst,
}
wpa_eapol_key_send(sm, &sm->ptk, ver, dst, ETH_P_EAPOL, rbuf, rlen,
- mic);
+ mic, EAPOL_MSG_TYPE_SMK_ERROR);
return 0;
}
@@ -167,7 +167,7 @@ static int wpa_supplicant_send_smk_m3(struct wpa_sm *sm,
wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK M3");
wpa_eapol_key_send(sm, &sm->ptk, ver, src_addr, ETH_P_EAPOL, rbuf, rlen,
- mic);
+ mic, EAPOL_MSG_TYPE_SMK_M3);
return 0;
}
@@ -371,7 +371,7 @@ static void wpa_supplicant_send_stk_1_of_4(struct wpa_sm *sm,
wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key STK 1/4 to " MACSTR,
MAC2STR(peerkey->addr));
wpa_eapol_key_send(sm, NULL, ver, peerkey->addr, ETH_P_EAPOL,
- mbuf, mlen, NULL);
+ mbuf, mlen, NULL, EAPOL_MSG_TYPE_STK_1_OF_4);
}
@@ -427,7 +427,7 @@ static void wpa_supplicant_send_stk_3_of_4(struct wpa_sm *sm,
wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key STK 3/4 to " MACSTR,
MAC2STR(peerkey->addr));
wpa_eapol_key_send(sm, &peerkey->stk, ver, peerkey->addr, ETH_P_EAPOL,
- mbuf, mlen, mic);
+ mbuf, mlen, mic, EAPOL_MSG_TYPE_STK_3_OF_4);
}
@@ -1094,7 +1094,7 @@ int wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer)
wpa_printf(MSG_INFO, "RSN: Sending EAPOL-Key SMK M1 Request (peer "
MACSTR ")", MAC2STR(peer));
wpa_eapol_key_send(sm, &sm->ptk, ver, bssid, ETH_P_EAPOL, rbuf, rlen,
- mic);
+ mic, EAPOL_MSG_TYPE_SMK_M1);
peerkey->next = sm->peerkey;
sm->peerkey = peerkey;
diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
index 4d68998..ccd7f30 100644
--- a/src/rsn_supp/wpa.c
+++ b/src/rsn_supp/wpa.c
@@ -29,6 +29,27 @@
static const u8 null_rsc[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+#ifdef CONFIG_TESTING_OPTIONS
+const char* eapol_msg_type_str(enum eapol_key_msg_type t)
+{
+ static const char* types_str[EAPOL_MSG_TYPE_MAX] =
+ {"UNKNOWN", "1/4", "2/4", "3/4", "4/4", "1/2", "2/2", "KEY-REQ",
+ "SMK-ERROR", "SMK-M1", "SMK-M3", "STK-1/4", "STK-3/4" };
+ if (t >= 0 && t < EAPOL_MSG_TYPE_MAX)
+ return types_str[t];
+ return types_str[EAPOL_MSG_TYPE_UNKNOWN];
+}
+
+void wpa_apply_corruptions(struct wpa_sm *sm, u16 corrupt_eapol_2_of_4,
+ u16 corrupt_eapol_4_of_4, u16 corrupt_eapol_2_of_2,
+ u16 corrupt_eapol_key_req)
+{
+ sm->corrupt_eapol_2_of_4 = corrupt_eapol_2_of_4;
+ sm->corrupt_eapol_4_of_4 = corrupt_eapol_4_of_4;
+ sm->corrupt_eapol_2_of_2 = corrupt_eapol_2_of_2;
+ sm->corrupt_eapol_key_req = corrupt_eapol_key_req;
+}
+#endif
/**
* wpa_eapol_key_send - Send WPA/RSN EAPOL-Key message
@@ -44,7 +65,8 @@ static const u8 null_rsc[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
*/
int wpa_eapol_key_send(struct wpa_sm *sm, struct wpa_ptk *ptk,
int ver, const u8 *dest, u16 proto,
- u8 *msg, size_t msg_len, u8 *key_mic)
+ u8 *msg, size_t msg_len, u8 *key_mic,
+ enum eapol_key_msg_type eapol_type)
{
int ret = -1;
size_t mic_len = wpa_mic_len(sm->key_mgmt);
@@ -149,6 +171,24 @@ int wpa_eapol_key_send(struct wpa_sm *sm, struct wpa_ptk *ptk,
#endif /* CONFIG_FILS */
}
+#ifdef CONFIG_TESTING_OPTIONS
+ /* Purposefully corrupt the frame for testing purposes? */
+ if (((sm->corrupt_eapol_2_of_4 && eapol_type == EAPOL_MSG_TYPE_2_OF_4) &&
+ (os_random() % 65535) < sm->corrupt_eapol_2_of_4) ||
+ ((sm->corrupt_eapol_4_of_4 && eapol_type == EAPOL_MSG_TYPE_4_OF_4) &&
+ (os_random() % 65535) < sm->corrupt_eapol_4_of_4) ||
+ ((sm->corrupt_eapol_key_req && eapol_type == EAPOL_MSG_TYPE_KEY_REQUEST) &&
+ (os_random() % 65535) < sm->corrupt_eapol_key_req) ||
+ ((sm->corrupt_eapol_2_of_2 && eapol_type == EAPOL_MSG_TYPE_GROUP_2_OF_2) &&
+ (os_random() % 65535) < sm->corrupt_eapol_2_of_2)) {
+ /* Corrupt a random byte, maybe more?? */
+ int idx = os_random() % msg_len;
+ msg[idx] = os_random();
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+ "WPA: Corrupting EAPOL message type: %s, idx: %d value: 0x%x\n",
+ eapol_msg_type_str(eapol_type), idx, msg[idx]);
+ }
+#endif
wpa_hexdump(MSG_MSGDUMP, "WPA: TX EAPOL-Key", msg, msg_len);
ret = wpa_sm_ether_send(sm, dest, proto, msg, msg_len);
eapol_sm_notify_tx_eapol_key(sm->eapol);
@@ -229,7 +269,7 @@ void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise)
"pairwise=%d ptk_set=%d len=%lu)",
error, pairwise, sm->ptk_set, (unsigned long) rlen);
wpa_eapol_key_send(sm, &sm->ptk, ver, bssid, ETH_P_EAPOL, rbuf, rlen,
- key_mic);
+ key_mic, EAPOL_MSG_TYPE_KEY_REQUEST);
}
@@ -493,7 +533,7 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 2/4");
return wpa_eapol_key_send(sm, ptk, ver, dst, ETH_P_EAPOL, rbuf, rlen,
- key_mic);
+ key_mic, EAPOL_MSG_TYPE_2_OF_4);
}
@@ -1249,7 +1289,7 @@ int wpa_supplicant_send_4_of_4(struct wpa_sm *sm, const unsigned char *dst,
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 4/4");
return wpa_eapol_key_send(sm, ptk, ver, dst, ETH_P_EAPOL, rbuf, rlen,
- key_mic);
+ key_mic, EAPOL_MSG_TYPE_4_OF_4);
}
@@ -1555,7 +1595,7 @@ static int wpa_supplicant_send_2_of_2(struct wpa_sm *sm,
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 2/2");
return wpa_eapol_key_send(sm, &sm->ptk, ver, sm->bssid, ETH_P_EAPOL,
- rbuf, rlen, key_mic);
+ rbuf, rlen, key_mic, EAPOL_MSG_TYPE_GROUP_2_OF_2);
}
diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h
index 29b2f33..c1009f3 100644
--- a/src/rsn_supp/wpa.h
+++ b/src/rsn_supp/wpa.h
@@ -117,6 +117,13 @@ enum eapol_key_msg_type {
EAPOL_MSG_TYPE_4_OF_4, /* sent by sta */
EAPOL_MSG_TYPE_GROUP_1_OF_2, /* rx by sta */
EAPOL_MSG_TYPE_GROUP_2_OF_2, /* sent by sta */
+ EAPOL_MSG_TYPE_KEY_REQUEST,
+ EAPOL_MSG_TYPE_SMK_ERROR,
+ EAPOL_MSG_TYPE_SMK_M1,
+ EAPOL_MSG_TYPE_SMK_M3,
+ EAPOL_MSG_TYPE_STK_1_OF_4,
+ EAPOL_MSG_TYPE_STK_3_OF_4,
+ EAPOL_MSG_TYPE_MAX,
};
@@ -124,6 +131,10 @@ enum eapol_key_msg_type {
#ifdef CONFIG_TESTING_OPTIONS
enum eapol_key_msg_type wpa_eapol_key_type(struct wpa_sm *sm, const u8 *buf, size_t len);
+const char* eapol_msg_type_str(enum eapol_key_msg_type t);
+void wpa_apply_corruptions(struct wpa_sm* wpa_sm, u16 corrupt_eapol_2_of_4,
+ u16 corrupt_eapol_4_of_4, u16 corrupt_eapol_2_of_2,
+ u16 corrupt_eapol_key_req);
#endif
@@ -186,10 +197,18 @@ void wpa_sm_set_ptk_kck_kek(struct wpa_sm *sm,
#else /* CONFIG_NO_WPA */
#ifdef CONFIG_TESTING_OPTIONS
-enum eapol_key_msg_type wpa_eapol_key_type(struct wpa_sm *sm, const u8 *src_addr,
- const u8 *buf, size_t len) {
+static inline enum eapol_key_msg_type
+wpa_eapol_key_type(struct wpa_sm *sm, const u8 *src_addr,
+ const u8 *buf, size_t len)
+{
return EAPOL_MSG_TYPE_UNKNOWN;
}
+
+static inline void wpa_apply_corruptions(struct wpa_sm *sm, u16 corrupt_eapol_2_of_4,
+ u16 corrupt_eapol_4_of_4, u16 corrupt_eapol_2_of_2,
+ u16 corrupt_eapol_key_req)
+{
+}
#endif
static inline struct wpa_sm * wpa_sm_init(struct wpa_sm_ctx *ctx)
diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h
index 180d468..61662fb 100644
--- a/src/rsn_supp/wpa_i.h
+++ b/src/rsn_supp/wpa_i.h
@@ -137,6 +137,11 @@ struct wpa_sm {
#ifdef CONFIG_TESTING_OPTIONS
struct wpabuf *test_assoc_ie;
+
+ u16 corrupt_eapol_2_of_4;
+ u16 corrupt_eapol_4_of_4;
+ u16 corrupt_eapol_2_of_2;
+ u16 corrupt_eapol_key_req;
#endif /* CONFIG_TESTING_OPTIONS */
#ifdef CONFIG_FILS
@@ -365,7 +370,7 @@ static inline int wpa_sm_key_mgmt_set_pmk(struct wpa_sm *sm,
int wpa_eapol_key_send(struct wpa_sm *sm, struct wpa_ptk *ptk,
int ver, const u8 *dest, u16 proto,
- u8 *msg, size_t msg_len, u8 *key_mic);
+ u8 *msg, size_t msg_len, u8 *key_mic, enum eapol_key_msg_type eapol_type);
int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
const struct wpa_eapol_key *key,
int ver, const u8 *nonce,
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index 2bff8e7..d56b6da 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -3838,6 +3838,11 @@ struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface,
config->ignore_eapol_1_of_4 = DEFAULT_IGNORE_AUTH_RESP;
config->ignore_eapol_3_of_4 = DEFAULT_IGNORE_AUTH_RESP;
config->ignore_eapol_1_of_2 = DEFAULT_IGNORE_AUTH_RESP;
+
+ config->corrupt_eapol_2_of_4 = DEFAULT_IGNORE_AUTH_RESP;
+ config->corrupt_eapol_4_of_4 = DEFAULT_IGNORE_AUTH_RESP;
+ config->corrupt_eapol_2_of_2 = DEFAULT_IGNORE_AUTH_RESP;
+ config->corrupt_eapol_key_req = DEFAULT_IGNORE_AUTH_RESP;
#endif
return config;
@@ -4563,6 +4568,10 @@ static const struct global_parse_data global_fields[] = {
{ INT(ignore_eapol_1_of_4), 0 },
{ INT(ignore_eapol_3_of_4), 0 },
{ INT(ignore_eapol_1_of_2), 0 },
+ { INT(corrupt_eapol_2_of_4), 0 },
+ { INT(corrupt_eapol_4_of_4), 0 },
+ { INT(corrupt_eapol_2_of_2), 0 },
+ { INT(corrupt_eapol_key_req), 0 },
#endif
{ INT(accept_external_scan_results), 0 },
{ STR(wowlan_triggers), 0 },
diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h
index f93ca78..1e31255 100644
--- a/wpa_supplicant/config.h
+++ b/wpa_supplicant/config.h
@@ -891,6 +891,12 @@ struct wpa_config {
unsigned short ignore_eapol_1_of_4;
unsigned short ignore_eapol_3_of_4;
unsigned short ignore_eapol_1_of_2;
+
+ unsigned short corrupt_eapol_2_of_4;
+ unsigned short corrupt_eapol_4_of_4;
+ unsigned short corrupt_eapol_2_of_2;
+ unsigned short corrupt_eapol_key_req;
+
#endif
/**
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 52a986a..7c2ebd3 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -3516,7 +3516,6 @@ void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
return;
}
-
/* Check for dropping specific eapol frames */
emt = wpa_eapol_key_type(wpa_s->wpa, buf, len);
if (emt == EAPOL_MSG_TYPE_1_OF_4) {
diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf
index 27985a3..500d575 100644
--- a/wpa_supplicant/wpa_supplicant.conf
+++ b/wpa_supplicant/wpa_supplicant.conf
@@ -1379,6 +1379,12 @@ fast_reauth=1
#ignore_eapol_3_of_4=1000
#ignore_eapol_1_of_2=1000
+# Randomly set a byte in the message to a different value
+#corrupt_eapol_2_of_4=1000
+#corrupt_eapol_4_of_4=1000
+#corrupt_eapol_2_of_2=1000
+#corrupt_eapol_key_req=1000
+
# Example blocks:
diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
index 16ffc7f..06de244 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -1170,6 +1170,15 @@ int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s)
os_free(ctx);
return -1;
}
+
+#ifdef CONFIG_TESTING_OPTIONS
+ wpa_apply_corruptions(wpa_s->wpa,
+ wpa_s->conf->corrupt_eapol_2_of_4,
+ wpa_s->conf->corrupt_eapol_4_of_4,
+ wpa_s->conf->corrupt_eapol_2_of_2,
+ wpa_s->conf->corrupt_eapol_key_req);
+#endif
+
#endif /* CONFIG_NO_WPA */
return 0;
--
1.9.3
More information about the Hostap
mailing list