[PATCH v2 04/33] FT: add support for wildcard R0KH / R1KH

M. Braun michael-dev at fami-braun.de
Sat Sep 24 14:07:48 PDT 2016


From: Michael Braun <michael-dev at fami-braun.de>

This enables using FT RRB without configuring each other AP locally.
Instead, broadcast messages are exchanged.

Signed-off-by: Michael Braun <michael-dev at fami-braun.de>
---
 hostapd/hostapd.conf   |  4 ++++
 src/ap/wpa_auth.h      |  3 +++
 src/ap/wpa_auth_ft.c   | 47 ++++++++++++++++++++++++++++++++++++++++-------
 src/ap/wpa_auth_glue.c |  9 +++++++--
 4 files changed, 54 insertions(+), 9 deletions(-)

diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index dab4a4e..26546de 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -1306,6 +1306,8 @@ own_ip_addr=127.0.0.1
 #r0kh=02:01:02:03:04:05 r0kh-1.example.com 000102030405060708090a0b0c0d0e0f
 #r0kh=02:01:02:03:04:06 r0kh-2.example.com 00112233445566778899aabbccddeeff
 # And so on.. One line per R0KH.
+# Wildcard entry:
+#r0kh=ff:ff:ff:ff:ff:ff * 00112233445566778899aabbccddeeff
 
 # List of R1KHs in the same Mobility Domain
 # format: <MAC address> <R1KH-ID> <128-bit key as hex string>
@@ -1315,6 +1317,8 @@ own_ip_addr=127.0.0.1
 #r1kh=02:01:02:03:04:05 02:11:22:33:44:55 000102030405060708090a0b0c0d0e0f
 #r1kh=02:01:02:03:04:06 02:11:22:33:44:66 00112233445566778899aabbccddeeff
 # And so on.. One line per R1KH.
+# Wildcard entry:
+#r1kh=00:00:00:00:00:00 00:00:00:00:00:00 00112233445566778899aabbccddeeff
 
 # Whether PMK-R1 push is enabled at R0KH
 # 0 = do not push PMK-R1 to all configured R1KHs (default)
diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
index 5712884..39a1afd 100644
--- a/src/ap/wpa_auth.h
+++ b/src/ap/wpa_auth.h
@@ -44,6 +44,7 @@ struct ft_rrb_frame {
 
 #define FT_R0KH_R1KH_PULL_NONCE_LEN 16
 #define FT_R0KH_R1KH_PULL_DATA_LEN (FT_R0KH_R1KH_PULL_NONCE_LEN + \
+				    FT_R0KH_ID_MAX_LEN + 1 + \
 				    WPA_PMK_NAME_LEN + FT_R1KH_ID_LEN + \
 				    ETH_ALEN)
 #define FT_R0KH_R1KH_PULL_PAD_LEN ((8 - FT_R0KH_R1KH_PULL_DATA_LEN % 8) % 8)
@@ -55,6 +56,8 @@ struct ft_r0kh_r1kh_pull_frame {
 	u8 ap_address[ETH_ALEN];
 
 	u8 nonce[FT_R0KH_R1KH_PULL_NONCE_LEN];
+	u8 r0kh_id[FT_R0KH_ID_MAX_LEN];
+	u8 r0kh_id_len;
 	u8 pmk_r0_name[WPA_PMK_NAME_LEN];
 	u8 r1kh_id[FT_R1KH_ID_LEN];
 	u8 s1kh_id[ETH_ALEN];
diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c
index e0e0740..04e9bf8 100644
--- a/src/ap/wpa_auth_ft.c
+++ b/src/ap/wpa_auth_ft.c
@@ -316,7 +316,7 @@ static int wpa_ft_pull_pmk_r1(struct wpa_state_machine *sm,
 			      const u8 *ies, size_t ies_len,
 			      const u8 *pmk_r0_name)
 {
-	struct ft_remote_r0kh *r0kh;
+	struct ft_remote_r0kh *r0kh, *r0kh_wildcard = NULL;
 	struct ft_r0kh_r1kh_pull_frame frame, f;
 
 	r0kh = sm->wpa_auth->conf.r0kh_list;
@@ -325,8 +325,14 @@ static int wpa_ft_pull_pmk_r1(struct wpa_state_machine *sm,
 		    os_memcmp_const(r0kh->id, sm->r0kh_id, sm->r0kh_id_len) ==
 		    0)
 			break;
+		if (r0kh->id_len == 1 && r0kh->id[0] == '*')
+			r0kh_wildcard = r0kh;
 		r0kh = r0kh->next;
 	}
+	if (r0kh == NULL && r0kh_wildcard != NULL) {
+		wpa_printf(MSG_DEBUG, "FT: Using wildcard R0KH-ID");
+		r0kh = r0kh_wildcard;
+	}
 	if (r0kh == NULL) {
 		wpa_hexdump(MSG_DEBUG, "FT: Did not find R0KH-ID",
 			    sm->r0kh_id, sm->r0kh_id_len);
@@ -351,6 +357,8 @@ static int wpa_ft_pull_pmk_r1(struct wpa_state_machine *sm,
 	}
 	os_memcpy(sm->ft_pending_pull_nonce, f.nonce,
 		  FT_R0KH_R1KH_PULL_NONCE_LEN);
+	os_memcpy(f.r0kh_id, sm->r0kh_id, FT_R0KH_ID_MAX_LEN);
+	f.r0kh_id_len = sm->r0kh_id_len;
 	os_memcpy(f.pmk_r0_name, pmk_r0_name, WPA_PMK_NAME_LEN);
 	os_memcpy(f.r1kh_id, sm->wpa_auth->conf.r1_key_holder, FT_R1KH_ID_LEN);
 	os_memcpy(f.s1kh_id, sm->addr, ETH_ALEN);
@@ -1423,7 +1431,7 @@ static int wpa_ft_rrb_rx_pull(struct wpa_authenticator *wpa_auth,
 	struct ft_r0kh_r1kh_pull_frame f;
 	const u8 *crypt;
 	u8 *plain;
-	struct ft_remote_r1kh *r1kh;
+	struct ft_remote_r1kh *r1kh, *r1kh_wildcard = NULL;
 	struct ft_r0kh_r1kh_resp_frame resp, r;
 	u8 pmk_r0[PMK_LEN];
 	int pairwise;
@@ -1437,8 +1445,15 @@ static int wpa_ft_rrb_rx_pull(struct wpa_authenticator *wpa_auth,
 	while (r1kh) {
 		if (os_memcmp(r1kh->addr, src_addr, ETH_ALEN) == 0)
 			break;
+		if (is_zero_ether_addr(r1kh->addr) &&
+		    is_zero_ether_addr(r1kh->id))
+			r1kh_wildcard = r1kh;
 		r1kh = r1kh->next;
 	}
+	if (r1kh == NULL && r1kh_wildcard != NULL) {
+		wpa_printf(MSG_DEBUG, "FT: Using wildcard R1KH-ID");
+		r1kh = r1kh_wildcard;
+	}
 	if (r1kh == NULL) {
 		wpa_printf(MSG_DEBUG, "FT: No matching R1KH address found for "
 			   "PMK-R1 pull source address " MACSTR,
@@ -1459,6 +1474,11 @@ static int wpa_ft_rrb_rx_pull(struct wpa_authenticator *wpa_auth,
 		return -1;
 	}
 
+	if (f.r0kh_id_len != wpa_auth->conf.r0_key_holder_len ||
+	    os_memcmp_const(f.r0kh_id, wpa_auth->conf.r0_key_holder,
+			    f.r0kh_id_len) != 0)
+		return -1;
+
 	wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - nonce",
 		    f.nonce, sizeof(f.nonce));
 	wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - PMKR0Name",
@@ -1559,7 +1579,7 @@ static int wpa_ft_rrb_rx_resp(struct wpa_authenticator *wpa_auth,
 	struct ft_r0kh_r1kh_resp_frame f;
 	const u8 *crypt;
 	u8 *plain;
-	struct ft_remote_r0kh *r0kh;
+	struct ft_remote_r0kh *r0kh, *r0kh_wildcard = NULL;
 	int pairwise, res;
 
 	wpa_printf(MSG_DEBUG, "FT: Received PMK-R1 pull response");
@@ -1571,8 +1591,14 @@ static int wpa_ft_rrb_rx_resp(struct wpa_authenticator *wpa_auth,
 	while (r0kh) {
 		if (os_memcmp(r0kh->addr, src_addr, ETH_ALEN) == 0)
 			break;
+		if (r0kh->id_len == 1 && r0kh->id[0] == '*')
+			r0kh_wildcard = r0kh;
 		r0kh = r0kh->next;
 	}
+	if (r0kh == NULL && r0kh_wildcard != NULL) {
+		wpa_printf(MSG_DEBUG, "FT: Using wildcard R0KH-ID");
+		r0kh = r0kh_wildcard;
+	}
 	if (r0kh == NULL) {
 		wpa_printf(MSG_DEBUG, "FT: No matching R0KH address found for "
 			   "PMK-R0 pull response source address " MACSTR,
@@ -1628,7 +1654,7 @@ static int wpa_ft_rrb_rx_push(struct wpa_authenticator *wpa_auth,
 	struct ft_r0kh_r1kh_push_frame f;
 	const u8 *crypt;
 	u8 *plain;
-	struct ft_remote_r0kh *r0kh;
+	struct ft_remote_r0kh *r0kh, *r0kh_wildcard = NULL;
 	struct os_time now;
 	os_time_t tsend;
 	int pairwise;
@@ -1642,8 +1668,14 @@ static int wpa_ft_rrb_rx_push(struct wpa_authenticator *wpa_auth,
 	while (r0kh) {
 		if (os_memcmp(r0kh->addr, src_addr, ETH_ALEN) == 0)
 			break;
+		if (r0kh->id_len == 1 && r0kh->id[0] == '*')
+			r0kh_wildcard = r0kh;
 		r0kh = r0kh->next;
 	}
+	if (r0kh == NULL && r0kh_wildcard != NULL) {
+		wpa_printf(MSG_DEBUG, "FT: Using wildcard R0KH-ID");
+		r0kh = r0kh_wildcard;
+	}
 	if (r0kh == NULL) {
 		wpa_printf(MSG_DEBUG, "FT: No matching R0KH address found for "
 			   "PMK-R0 push source address " MACSTR,
@@ -1892,10 +1924,11 @@ void wpa_ft_push_pmk_r1(struct wpa_authenticator *wpa_auth, const u8 *addr)
 	wpa_printf(MSG_DEBUG, "FT: Deriving and pushing PMK-R1 keys to R1KHs "
 		   "for STA " MACSTR, MAC2STR(addr));
 
-	r1kh = wpa_auth->conf.r1kh_list;
-	while (r1kh) {
+	for (r1kh = wpa_auth->conf.r1kh_list; r1kh; r1kh = r1kh->next) {
+		if (is_zero_ether_addr(r1kh->addr) ||
+		    is_zero_ether_addr(r1kh->id))
+			continue;
 		wpa_ft_generate_pmk_r1(wpa_auth, r0, r1kh, addr, r0->pairwise);
-		r1kh = r1kh->next;
 	}
 }
 
diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c
index 2a5a940..12b9ccc 100644
--- a/src/ap/wpa_auth_glue.c
+++ b/src/ap/wpa_auth_glue.c
@@ -417,6 +417,9 @@ static int hostapd_wpa_auth_ft_iter(struct hostapd_iface *iface, void *ctx)
 	struct wpa_auth_ft_iface_iter_data *idata = ctx;
 	struct hostapd_data *hapd;
 	size_t j;
+	int multicast;
+
+	multicast = is_multicast_ether_addr(idata->dst);
 
 	for (j = 0; j < iface->num_bss; j++) {
 		hapd = iface->bss[j];
@@ -424,7 +427,8 @@ static int hostapd_wpa_auth_ft_iter(struct hostapd_iface *iface, void *ctx)
 			continue;
 		if (!hapd->wpa_auth)
 			continue;
-		if (os_memcmp(hapd->own_addr, idata->dst, ETH_ALEN) == 0) {
+		if (os_memcmp(hapd->own_addr, idata->dst, ETH_ALEN) == 0 ||
+		    multicast) {
 			wpa_printf(MSG_DEBUG, "FT: Send RRB data directly to "
 				   "locally managed BSS " MACSTR "@%s -> "
 				   MACSTR "@%s",
@@ -434,7 +438,8 @@ static int hostapd_wpa_auth_ft_iter(struct hostapd_iface *iface, void *ctx)
 			wpa_ft_rrb_rx(hapd->wpa_auth,
 				      idata->src_hapd->own_addr,
 				      idata->data, idata->data_len);
-			return 1;
+			if (!multicast)
+				return 1;
 		}
 	}
 
-- 
2.1.4




More information about the Hostap mailing list