[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