diff mbox

[2/3] FT: disable encryption

Message ID 1474794548-326-3-git-send-email-michael-dev@fami-braun.de
State Deferred
Headers show

Commit Message

michael-dev Sept. 25, 2016, 9:09 a.m. UTC
For example when ft_iface points to some already encrypted VPN interface, there
is no advantage in hostapd encrypting the RRB messages.

This change adds an option to disable encryption with FT RRB messages.

Signed-off-by: Michael Braun <michael-dev@fami-braun.de>
---
 hostapd/config_file.c  |   2 +
 hostapd/hostapd.conf   |   4 ++
 src/ap/ap_config.c     |   1 +
 src/ap/ap_config.h     |   1 +
 src/ap/wpa_auth.h      |   1 +
 src/ap/wpa_auth_ft.c   | 106 +++++++++++++++++++++++++++++++++++++++----------
 src/ap/wpa_auth_glue.c |   1 +
 7 files changed, 96 insertions(+), 20 deletions(-)

Comments

Johannes Berg Sept. 26, 2016, 7:13 a.m. UTC | #1
On Sun, 2016-09-25 at 11:09 +0200, Michael Braun wrote:
> For example when ft_iface points to some already encrypted VPN
> interface, there
> is no advantage in hostapd encrypting the RRB messages.
> 
What's the advantage of disabling it though? Seems it just adds
complexity.

johannes
diff mbox

Patch

diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 9e706ac..cea5329 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -2556,6 +2556,8 @@  static int hostapd_config_fill(struct hostapd_config *conf,
 		bss->r1_max_key_lifetime = atoi(pos);
 	} else if (os_strcmp(buf, "reassociation_deadline") == 0) {
 		bss->reassociation_deadline = atoi(pos);
+	} else if (os_strcmp(buf, "rkh_disable_encryption") == 0) {
+		bss->rkh_disable_encryption = atoi(pos);
 	} else if (os_strcmp(buf, "rkh_pos_timeout") == 0) {
 		bss->rkh_pos_timeout = atoi(pos);
 	} else if (os_strcmp(buf, "rkh_neg_timeout") == 0) {
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index 1617200..eceb8f1 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -1371,6 +1371,10 @@  own_ip_addr=127.0.0.1
 #                 list, so subsequent requests won't be broadcasted.
 #r1kh=00:00:00:00:00:00 00:00:00:00:00:00 00112233445566778899aabbccddeeff
 
+# Disable encryption of FT RRB messages
+# default: 0 (disabled)
+#rkh_disable_encryption = 1
+
 # Timeout (seconds) for newly discovered R0KH/R1KH (see wildcard entries above)
 # Special values: 0 -> do not cache; -1 -> do not expire
 #rkh_pos_timeout = 86400 (default = 1d)
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index f019da9..ebd1a67 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -92,6 +92,7 @@  void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
 
 #ifdef CONFIG_IEEE80211R
 	bss->ft_over_ds = 1;
+	bss->rkh_disable_encryption = 0;
 	bss->rkh_pos_timeout = 86400;
 	bss->rkh_neg_timeout = 60;
 	bss->rkh_pull_timeout = 1000;
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index aaed2ce..8721e72 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -346,6 +346,7 @@  struct hostapd_bss_config {
 	u8 mobility_domain[MOBILITY_DOMAIN_ID_LEN];
 	u8 r1_key_holder[FT_R1KH_ID_LEN];
 	u32 r0_key_lifetime;
+	int rkh_disable_encryption:1;
 	int rkh_pos_timeout;
 	int rkh_neg_timeout;
 	int rkh_pull_timeout; /* ms */
diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
index 650cad2..4815cf5 100644
--- a/src/ap/wpa_auth.h
+++ b/src/ap/wpa_auth.h
@@ -167,6 +167,7 @@  struct wpa_auth_config {
 	size_t r0_key_holder_len;
 	u8 r1_key_holder[FT_R1KH_ID_LEN];
 	u32 r0_key_lifetime;
+	int rkh_disable_encryption:1;
 	int rkh_pos_timeout;
 	int rkh_neg_timeout;
 	int rkh_pull_timeout; /* ms */
diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c
index 8d125af..9717694 100644
--- a/src/ap/wpa_auth_ft.c
+++ b/src/ap/wpa_auth_ft.c
@@ -62,8 +62,13 @@  static int wpa_ft_rrb_decrypt(const u8 *kek, size_t kek_len,
 	f = (struct ft_rrb_frame *) data;
 
 	alen = le_to_host16(f->action_length); /* plaintext length */
-	blen = alen + ((8 - (alen % 8)) % 8); /* round up to full block size */
-	clen = blen + 8; /* extra space for keywrap */
+	if (kek) {
+		blen = alen + ((8 - (alen % 8)) % 8); /* round up to block */
+		clen = blen + 8; /* extra space for keywrap */
+	} else { /* not encrypted */
+		blen = alen;
+		clen = alen;
+	}
 
 	/* ciphertext (packet) long enough for given plaintext length? */
 	if (data_len - sizeof(*f) < clen)
@@ -74,7 +79,11 @@  static int wpa_ft_rrb_decrypt(const u8 *kek, size_t kek_len,
 	if (!*plain)
 		return -1;
 
-	if (!aes_unwrap(kek, kek_len, blen / 8, crypt, *plain)) {
+	if (kek && !aes_unwrap(kek, kek_len, blen / 8, crypt, *plain)) {
+		*plain_size = alen;
+		return 0;
+	} else if (!kek) {
+		os_memcpy(*plain, crypt, alen);
 		*plain_size = alen;
 		return 0;
 	}
@@ -361,7 +370,10 @@  static int wpa_ft_rrb_build(const u8 *kek, size_t kek_len,
 	tlv_len += wpa_ft_tlv_len(tlvs1);
 	tlv_len += wpa_ft_tlv_len(tlvs2);
 	tlv_len += wpa_ft_vlan_len(vlan);
-	pad_len = (8 - (tlv_len % 8)) % 8;
+	if (kek)
+		pad_len = (8 - (tlv_len % 8)) % 8;
+	else
+		pad_len = 0;
 
 	plain  = os_zalloc(tlv_len + pad_len);
 	if (plain == NULL)
@@ -380,7 +392,10 @@  static int wpa_ft_rrb_build(const u8 *kek, size_t kek_len,
 		return -1;
 	}
 
-	*packet_len = sizeof(*frame) + tlv_len + pad_len + 8;
+	if (kek)
+		*packet_len = sizeof(*frame) + tlv_len + pad_len + 8;
+	else
+		*packet_len = sizeof(*frame) + tlv_len + pad_len;
 	*packet = os_zalloc(*packet_len);
 	if (*packet == NULL) {
 		*packet_len = 0;
@@ -394,7 +409,11 @@  static int wpa_ft_rrb_build(const u8 *kek, size_t kek_len,
 
 	crypt = *packet + sizeof(*frame);
 
-	if (!aes_wrap(kek, kek_len, (tlv_len + 7) / 8, plain, crypt)) {
+	if (kek && !aes_wrap(kek, kek_len, (tlv_len + 7) / 8, plain, crypt)) {
+		os_free(plain);
+		return 0;
+	} else if (!kek) {
+		os_memcpy(crypt, plain, tlv_len);
 		os_free(plain);
 		return 0;
 	}
@@ -1133,6 +1152,8 @@  static int wpa_ft_pull_pmk_r1(struct wpa_state_machine *sm,
 	size_t packet_len;
 	int tsecs, tusecs, first;
 	struct wpabuf *ft_pending_req_ies;
+	const u8 *kek;
+	size_t kek_len;
 
 	if (sm->ft_pending_pull_left_retries <= 0)
 		return -1;
@@ -1166,6 +1187,14 @@  static int wpa_ft_pull_pmk_r1(struct wpa_state_machine *sm,
 			    sm->r0kh_id, sm->r0kh_id_len);
 		return -1;
 	}
+	if (!sm->wpa_auth->conf.rkh_disable_encryption) {
+		kek = r0kh->key;
+		kek_len = sizeof(r0kh->key);
+	} else {
+		kek = NULL;
+		kek_len = 0;
+	}
+
 
 	wpa_printf(MSG_DEBUG, "FT: Send PMK-R1 pull request to remote R0KH "
 		   "address " MACSTR, MAC2STR(r0kh->addr));
@@ -1196,8 +1225,8 @@  static int wpa_ft_pull_pmk_r1(struct wpa_state_machine *sm,
 		{ .type = FT_RRB_LAST_EMPTY, .len = 0, .data = NULL },
 	};
 
-	if (wpa_ft_rrb_build(r0kh->key, sizeof(r0kh->key), &req_hdr,
-			     req_tlv, NULL, NULL, &packet, &packet_len) < 0) {
+	if (wpa_ft_rrb_build(kek, kek_len, &req_hdr, req_tlv, NULL, NULL,
+			     &packet, &packet_len) < 0) {
 		return -1;
 	}
 
@@ -2483,6 +2512,8 @@  static int wpa_ft_rrb_rx_pull(struct wpa_authenticator *wpa_auth,
 	size_t f_pmk_r0_name_len;
 	const struct wpa_ft_pmk_r0_sa *r0;
 	const u8 *mdid = wpa_auth->conf.mobility_domain;
+	const u8 *kek;
+	size_t kek_len;
 
 	wpa_printf(MSG_DEBUG, "FT: Received PMK-R1 pull request");
 
@@ -2508,9 +2539,16 @@  static int wpa_ft_rrb_rx_pull(struct wpa_authenticator *wpa_auth,
 			   MAC2STR(src_addr));
 		return -1;
 	}
+	if (!wpa_auth->conf.rkh_disable_encryption) {
+		kek = r1kh->key;
+		kek_len = sizeof(r1kh->key);
+	} else {
+		kek = NULL;
+		kek_len = 0;
+	}
 
-	if (wpa_ft_rrb_decrypt(r1kh->key, sizeof(r1kh->key),
-			       data, data_len, &plain, &plain_len) < 0) {
+	if (wpa_ft_rrb_decrypt(kek, kek_len, data, data_len, &plain,
+			       &plain_len) < 0) {
 		wpa_printf(MSG_DEBUG, "FT: Failed to decrypt PMK-R1 pull "
 			   "request from " MACSTR, MAC2STR(src_addr));
 		return -1;
@@ -2562,9 +2600,8 @@  static int wpa_ft_rrb_rx_pull(struct wpa_authenticator *wpa_auth,
 		wpa_printf(MSG_DEBUG, "FT: No matching PMK-R0-Name found for "
 			   "PMK-R1 pull request");
 
-	ret = wpa_ft_rrb_build_r0(r1kh->key, sizeof(r1kh->key), &resp_hdr,
-				  resp_tlv, r0, f_r1kh_id, f_s1kh_id,
-				  &packet, &packet_len);
+	ret = wpa_ft_rrb_build_r0(kek, kek_len, &resp_hdr, resp_tlv, r0,
+				  f_r1kh_id, f_s1kh_id, &packet, &packet_len);
 
 	if (!ret)
 		wpa_ft_rrb_send(wpa_auth, src_addr, packet, packet_len);
@@ -2796,6 +2833,8 @@  static int wpa_ft_rrb_rx_resp(struct wpa_authenticator *wpa_auth,
 	struct ft_pull_resp_cb_ctx ctx;
 	const u8 *f_nonce, *f_s1kh_id;
 	size_t f_nonce_len, f_s1kh_id_len;
+	const u8 *kek;
+	size_t kek_len;
 
 	wpa_printf(MSG_DEBUG, "FT: Received PMK-R1 pull response");
 
@@ -2820,9 +2859,17 @@  static int wpa_ft_rrb_rx_resp(struct wpa_authenticator *wpa_auth,
 			   MAC2STR(src_addr));
 		return -1;
 	}
+	if (!wpa_auth->conf.rkh_disable_encryption) {
+		kek = r0kh->key;
+		kek_len = sizeof(r0kh->key);
+	} else {
+		kek = NULL;
+		kek_len = 0;
+	}
 
-	if (wpa_ft_rrb_decrypt(r0kh->key, sizeof(r0kh->key),
-			       data, data_len, &plain, &plain_len) < 0) {
+
+	if (wpa_ft_rrb_decrypt(kek, kek_len, data, data_len, &plain,
+			       &plain_len) < 0) {
 		wpa_printf(MSG_DEBUG, "FT: Failed to decrypt PMK-R1 pull "
 			   "response from " MACSTR, MAC2STR(src_addr));
 		return -1;
@@ -2880,6 +2927,8 @@  static int wpa_ft_rrb_rx_push(struct wpa_authenticator *wpa_auth,
 	os_time_t tsend;
 	const u8 *f_timestamp;
 	size_t f_timestamp_len;
+	const u8 *kek;
+	size_t kek_len;
 
 	wpa_printf(MSG_DEBUG, "FT: Received PMK-R1 push");
 
@@ -2903,9 +2952,17 @@  static int wpa_ft_rrb_rx_push(struct wpa_authenticator *wpa_auth,
 			   MAC2STR(src_addr));
 		return -1;
 	}
+	if (!wpa_auth->conf.rkh_disable_encryption) {
+		kek = r0kh->key;
+		kek_len = sizeof(r0kh->key);
+	} else {
+		kek = NULL;
+		kek_len = 0;
+	}
+
 
-	if (wpa_ft_rrb_decrypt(r0kh->key, sizeof(r0kh->key),
-			       data, data_len, &plain, &plain_len) < 0) {
+	if (wpa_ft_rrb_decrypt(kek, kek_len, data, data_len, &plain,
+			       &plain_len) < 0) {
 		wpa_printf(MSG_DEBUG, "FT: Failed to decrypt PMK-R1 push from "
 			   MACSTR, MAC2STR(src_addr));
 		return -1;
@@ -3073,6 +3130,16 @@  static void wpa_ft_generate_pmk_r1(struct wpa_authenticator *wpa_auth,
 	size_t packet_len;
 	u8 f_timestamp[sizeof(le32)];
 	const u8 *mdid = wpa_auth->conf.mobility_domain;
+	const u8 *kek;
+	size_t kek_len;
+
+	if (!wpa_auth->conf.rkh_disable_encryption) {
+		kek = r1kh->key;
+		kek_len = sizeof(r1kh->key);
+	} else {
+		kek = NULL;
+		kek_len = 0;
+	}
 
 	os_memset(&push_hdr, 0, sizeof(push_hdr));
 	push_hdr.frame_type = RSN_REMOTE_FRAME_TYPE_FT_RRB;
@@ -3097,9 +3164,8 @@  static void wpa_ft_generate_pmk_r1(struct wpa_authenticator *wpa_auth,
 		{ .type = FT_RRB_LAST_EMPTY, .len = 0, .data = NULL },
 	};
 
-	if (wpa_ft_rrb_build_r0(r1kh->key, sizeof(r1kh->key), &push_hdr,
-				push_tlv, pmk_r0, r1kh->id, s1kh_id,
-				&packet, &packet_len) < 0)
+	if (wpa_ft_rrb_build_r0(kek, kek_len, &push_hdr, push_tlv, pmk_r0,
+				r1kh->id, s1kh_id, &packet, &packet_len) < 0)
 		return;
 
 	wpa_ft_rrb_send(wpa_auth, r1kh->addr, packet, packet_len);
diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c
index fbd5f6d..2d80714 100644
--- a/src/ap/wpa_auth_glue.c
+++ b/src/ap/wpa_auth_glue.c
@@ -78,6 +78,7 @@  static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
 	wconf->r0_key_lifetime = conf->r0_key_lifetime;
 	wconf->r1_max_key_lifetime = conf->r1_max_key_lifetime;
 	wconf->reassociation_deadline = conf->reassociation_deadline;
+	wconf->rkh_disable_encryption = conf->rkh_disable_encryption;
 	wconf->rkh_pos_timeout = conf->rkh_pos_timeout;
 	wconf->rkh_neg_timeout = conf->rkh_neg_timeout;
 	wconf->rkh_pull_timeout = conf->rkh_pull_timeout;