Cumulative patch from commit 0f3bf6135d9e5d5e50de46c4755de0864f6c66

0f3bf61 AP: Fix checking if DFS is required
d41cc8c Allow HT 40 MHz intolerant flag to be set for association
6d99bd8 nl80211: Debug print HT/VHT capability override information
f777fd1 Fix writing of provisioning_sp cred parameter
d2c33b9 Reduce the amount of time PTK/TPTK/GTK is kept in memory
a7ca6da Fix P2P redirection of global ctrl_iface SET command
d6b818e Remove SAVE_CONFIG redirect from global control interface
128cc37 eap_proxy: Use unique Makefile names for Android and non-Android
e83e15e P2P: Fix interface remove to terminate all P2P groups
e47ee24 l2_packet: Fix l2_packet_none (hostapd default)

Change-Id: Ib336ce383695ce9ce662465d91c6bc82496db153
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/ap/dfs.c b/src/ap/dfs.c
index 3fb1881..c30f6d6 100644
--- a/src/ap/dfs.c
+++ b/src/ap/dfs.c
@@ -916,8 +916,9 @@
 {
 	int n_chans, start_chan_idx;
 
-	if (!iface->current_mode)
-		return -1;
+	if (!iface->conf->ieee80211h || !iface->current_mode ||
+	    iface->current_mode->mode != HOSTAPD_MODE_IEEE80211A)
+		return 0;
 
 	/* Get start (first) channel for current configuration */
 	start_chan_idx = dfs_get_start_chan_idx(iface);
diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h
index 0e292e6..cea4701 100644
--- a/src/common/qca-vendor.h
+++ b/src/common/qca-vendor.h
@@ -19,13 +19,6 @@
 #define OUI_QCA 0x001374
 
 /**
- * enum qca_radiotap_vendor_ids - QCA radiotap vendor namespace IDs
- */
-enum qca_radiotap_vendor_ids {
-	QCA_RADIOTAP_VID_WLANTEST = 0,
-};
-
-/**
  * enum qca_nl80211_vendor_subcmds - QCA nl80211 vendor command identifiers
  *
  * @QCA_NL80211_VENDOR_SUBCMD_UNSPEC: Reserved value 0
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 7e3de51..1300703 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -8663,7 +8663,10 @@
 
 	if (params->htcaps && params->htcaps_mask) {
 		int sz = sizeof(struct ieee80211_ht_capabilities);
+		wpa_hexdump(MSG_DEBUG, "  * htcaps", params->htcaps, sz);
 		NLA_PUT(msg, NL80211_ATTR_HT_CAPABILITY, sz, params->htcaps);
+		wpa_hexdump(MSG_DEBUG, "  * htcaps_mask",
+			    params->htcaps_mask, sz);
 		NLA_PUT(msg, NL80211_ATTR_HT_CAPABILITY_MASK, sz,
 			params->htcaps_mask);
 	}
@@ -8676,7 +8679,10 @@
 
 	if (params->vhtcaps && params->vhtcaps_mask) {
 		int sz = sizeof(struct ieee80211_vht_capabilities);
+		wpa_hexdump(MSG_DEBUG, "  * vhtcaps", params->vhtcaps, sz);
 		NLA_PUT(msg, NL80211_ATTR_VHT_CAPABILITY, sz, params->vhtcaps);
+		wpa_hexdump(MSG_DEBUG, "  * vhtcaps_mask",
+			    params->vhtcaps_mask, sz);
 		NLA_PUT(msg, NL80211_ATTR_VHT_CAPABILITY_MASK, sz,
 			params->vhtcaps_mask);
 	}
diff --git a/src/l2_packet/l2_packet_none.c b/src/l2_packet/l2_packet_none.c
index b01e830..6896c4e 100644
--- a/src/l2_packet/l2_packet_none.c
+++ b/src/l2_packet/l2_packet_none.c
@@ -84,7 +84,8 @@
 	 * TODO: open connection for receiving frames
 	 */
 	l2->fd = -1;
-	eloop_register_read_sock(l2->fd, l2_packet_receive, l2, NULL);
+	if (l2->fd >= 0)
+		eloop_register_read_sock(l2->fd, l2_packet_receive, l2, NULL);
 
 	return l2;
 }
diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
index 5c00726..d45f5dc 100644
--- a/src/rsn_supp/wpa.c
+++ b/src/rsn_supp/wpa.c
@@ -383,7 +383,6 @@
 {
 	struct wpa_eapol_ie_parse ie;
 	struct wpa_ptk *ptk;
-	u8 buf[8];
 	int res;
 	u8 *kde, *kde_buf = NULL;
 	size_t kde_len;
@@ -438,10 +437,12 @@
 	ptk = &sm->tptk;
 	wpa_derive_ptk(sm, src_addr, key, ptk);
 	if (sm->pairwise_cipher == WPA_CIPHER_TKIP) {
+		u8 buf[8];
 		/* Supplicant: swap tx/rx Mic keys */
 		os_memcpy(buf, ptk->u.auth.tx_mic_key, 8);
 		os_memcpy(ptk->u.auth.tx_mic_key, ptk->u.auth.rx_mic_key, 8);
 		os_memcpy(ptk->u.auth.rx_mic_key, buf, 8);
+		os_memset(buf, 0, sizeof(buf));
 	}
 	sm->tptk_set = 1;
 
@@ -657,6 +658,7 @@
 			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
 				"WPA: Failed to set GTK to the driver "
 				"(Group only)");
+			os_memset(gtk_buf, 0, sizeof(gtk_buf));
 			return -1;
 		}
 	} else if (wpa_sm_set_key(sm, gd->alg, broadcast_ether_addr,
@@ -666,8 +668,10 @@
 			"WPA: Failed to set GTK to "
 			"the driver (alg=%d keylen=%d keyidx=%d)",
 			gd->alg, gd->gtk_len, gd->keyidx);
+		os_memset(gtk_buf, 0, sizeof(gtk_buf));
 		return -1;
 	}
+	os_memset(gtk_buf, 0, sizeof(gtk_buf));
 
 	return 0;
 }
@@ -729,8 +733,10 @@
 	     wpa_supplicant_install_gtk(sm, &gd, key->key_rsc))) {
 		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
 			"RSN: Failed to install GTK");
+		os_memset(&gd, 0, sizeof(gd));
 		return -1;
 	}
+	os_memset(&gd, 0, sizeof(gd));
 
 	wpa_supplicant_key_neg_complete(sm, sm->bssid,
 					key_info & WPA_KEY_INFO_SECURE);
@@ -1237,7 +1243,6 @@
 					     struct wpa_gtk_data *gd)
 {
 	size_t maxkeylen;
-	u8 ek[32];
 
 	gd->gtk_len = WPA_GET_BE16(key->key_length);
 	maxkeylen = keydatalen;
@@ -1266,20 +1271,23 @@
 	gd->keyidx = (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >>
 		WPA_KEY_INFO_KEY_INDEX_SHIFT;
 	if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4) {
-		os_memcpy(ek, key->key_iv, 16);
-		os_memcpy(ek + 16, sm->ptk.kek, 16);
+		u8 ek[32];
 		if (keydatalen > sizeof(gd->gtk)) {
 			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
 				"WPA: RC4 key data too long (%lu)",
 				(unsigned long) keydatalen);
 			return -1;
 		}
+		os_memcpy(ek, key->key_iv, 16);
+		os_memcpy(ek + 16, sm->ptk.kek, 16);
 		os_memcpy(gd->gtk, key + 1, keydatalen);
 		if (rc4_skip(ek, 32, 256, gd->gtk, keydatalen)) {
+			os_memset(ek, 0, sizeof(ek));
 			wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
 				"WPA: RC4 failed");
 			return -1;
 		}
+		os_memset(ek, 0, sizeof(ek));
 	} else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
 		if (keydatalen % 8) {
 			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
@@ -1430,6 +1438,7 @@
 			sm->tptk_set = 0;
 			sm->ptk_set = 1;
 			os_memcpy(&sm->ptk, &sm->tptk, sizeof(sm->ptk));
+			os_memset(&sm->tptk, 0, sizeof(sm->tptk));
 		}
 	}
 
@@ -1482,10 +1491,12 @@
 		os_memcpy(ek, key->key_iv, 16);
 		os_memcpy(ek + 16, sm->ptk.kek, 16);
 		if (rc4_skip(ek, 32, 256, (u8 *) (key + 1), keydatalen)) {
+			os_memset(ek, 0, sizeof(ek));
 			wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
 				"WPA: RC4 failed");
 			return -1;
 		}
+		os_memset(ek, 0, sizeof(ek));
 	} else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
 		   ver == WPA_KEY_INFO_TYPE_AES_128_CMAC ||
 		   sm->key_mgmt == WPA_KEY_MGMT_OSEN) {
@@ -2133,7 +2144,9 @@
 		 */
 		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Clear old PTK");
 		sm->ptk_set = 0;
+		os_memset(&sm->ptk, 0, sizeof(sm->ptk));
 		sm->tptk_set = 0;
+		os_memset(&sm->tptk, 0, sizeof(sm->tptk));
 	}
 
 #ifdef CONFIG_TDLS
@@ -2663,29 +2676,22 @@
 #ifdef CONFIG_WNM
 int wpa_wnmsleep_install_key(struct wpa_sm *sm, u8 subelem_id, u8 *buf)
 {
-	struct wpa_gtk_data gd;
-#ifdef CONFIG_IEEE80211W
-	struct wpa_igtk_kde igd;
-	u16 keyidx;
-#endif /* CONFIG_IEEE80211W */
 	u16 keyinfo;
 	u8 keylen;  /* plaintext key len */
 	u8 *key_rsc;
 
-	os_memset(&gd, 0, sizeof(gd));
-#ifdef CONFIG_IEEE80211W
-	os_memset(&igd, 0, sizeof(igd));
-#endif /* CONFIG_IEEE80211W */
-
-	keylen = wpa_cipher_key_len(sm->group_cipher);
-	gd.key_rsc_len = wpa_cipher_rsc_len(sm->group_cipher);
-	gd.alg = wpa_cipher_to_alg(sm->group_cipher);
-	if (gd.alg == WPA_ALG_NONE) {
-		wpa_printf(MSG_DEBUG, "Unsupported group cipher suite");
-		return -1;
-	}
-
 	if (subelem_id == WNM_SLEEP_SUBELEM_GTK) {
+		struct wpa_gtk_data gd;
+
+		os_memset(&gd, 0, sizeof(gd));
+		keylen = wpa_cipher_key_len(sm->group_cipher);
+		gd.key_rsc_len = wpa_cipher_rsc_len(sm->group_cipher);
+		gd.alg = wpa_cipher_to_alg(sm->group_cipher);
+		if (gd.alg == WPA_ALG_NONE) {
+			wpa_printf(MSG_DEBUG, "Unsupported group cipher suite");
+			return -1;
+		}
+
 		key_rsc = buf + 5;
 		keyinfo = WPA_GET_LE16(buf + 2);
 		gd.gtk_len = keylen;
@@ -2703,12 +2709,18 @@
 		wpa_hexdump_key(MSG_DEBUG, "Install GTK (WNM SLEEP)",
 				gd.gtk, gd.gtk_len);
 		if (wpa_supplicant_install_gtk(sm, &gd, key_rsc)) {
+			os_memset(&gd, 0, sizeof(gd));
 			wpa_printf(MSG_DEBUG, "Failed to install the GTK in "
 				   "WNM mode");
 			return -1;
 		}
+		os_memset(&gd, 0, sizeof(gd));
 #ifdef CONFIG_IEEE80211W
 	} else if (subelem_id == WNM_SLEEP_SUBELEM_IGTK) {
+		struct wpa_igtk_kde igd;
+		u16 keyidx;
+
+		os_memset(&igd, 0, sizeof(igd));
 		keylen = wpa_cipher_key_len(sm->mgmt_group_cipher);
 		os_memcpy(igd.keyid, buf + 2, 2);
 		os_memcpy(igd.pn, buf + 4, 6);
@@ -2724,8 +2736,10 @@
 				   igd.igtk, keylen) < 0) {
 			wpa_printf(MSG_DEBUG, "Failed to install the IGTK in "
 				   "WNM mode");
+			os_memset(&igd, 0, sizeof(igd));
 			return -1;
 		}
+		os_memset(&igd, 0, sizeof(igd));
 #endif /* CONFIG_IEEE80211W */
 	} else {
 		wpa_printf(MSG_DEBUG, "Unknown element id");
diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile
index 19dae70..f74d516 100644
--- a/wpa_supplicant/Makefile
+++ b/wpa_supplicant/Makefile
@@ -515,7 +515,7 @@
 ifdef CONFIG_EAP_PROXY
 CFLAGS += -DCONFIG_EAP_PROXY
 OBJS += ../src/eap_peer/eap_proxy_$(CONFIG_EAP_PROXY).o
-include eap_proxy_$(CONFIG_EAP_PROXY).mk
+include eap_proxy_$(CONFIG_EAP_PROXY).mak
 CONFIG_IEEE8021X_EAPOL=y
 endif
 
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index 74283eb..b4ee1f5 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -1702,6 +1702,7 @@
 	{ INT_RANGE(disable_ht40, -1, 1) },
 	{ INT_RANGE(disable_sgi, 0, 1) },
 	{ INT_RANGE(disable_ldpc, 0, 1) },
+	{ INT_RANGE(ht40_intolerant, 0, 1) },
 	{ INT_RANGE(disable_max_amsdu, -1, 1) },
 	{ INT_RANGE(ampdu_factor, -1, 3) },
 	{ INT_RANGE(ampdu_density, -1, 7) },
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index 505d405..8f0561a 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -809,7 +809,7 @@
 		fprintf(f, "\tupdate_identifier=%d\n", cred->update_identifier);
 
 	if (cred->provisioning_sp)
-		fprintf(f, "\tprovisioning_sp=%s\n", cred->provisioning_sp);
+		fprintf(f, "\tprovisioning_sp=\"%s\"\n", cred->provisioning_sp);
 	if (cred->sp_priority)
 		fprintf(f, "\tsp_priority=%d\n", cred->sp_priority);
 
diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h
index 71829ef..a458990 100644
--- a/wpa_supplicant/config_ssid.h
+++ b/wpa_supplicant/config_ssid.h
@@ -534,6 +534,11 @@
 	int disable_ldpc;
 
 	/**
+	 * ht40_intolerant - Indicate 40 MHz intolerant for this network
+	 */
+	int ht40_intolerant;
+
+	/**
 	 * disable_max_amsdu - Disable MAX A-MSDU
 	 *
 	 * A-MDSU will be 3839 bytes when disabled, or 7935
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index abffaae..b8b6d95 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -6802,7 +6802,6 @@
 #ifdef CONFIG_P2P
 	static const char * cmd[] = {
 		"LIST_NETWORKS",
-		"SAVE_CONFIG",
 		"P2P_FIND",
 		"P2P_STOP_FIND",
 		"P2P_LISTEN",
@@ -6822,7 +6821,6 @@
 #endif /* ANDROID */
 		"GET_NETWORK ",
 		"REMOVE_NETWORK ",
-		"SET ",
 		"P2P_FIND ",
 		"P2P_CONNECT ",
 		"P2P_LISTEN ",
@@ -6922,6 +6920,9 @@
 	}
 #endif /* CONFIG_WIFI_DISPLAY */
 
+	/* Restore cmd to its original value to allow redirection */
+	value[-1] = ' ';
+
 	return -1;
 }
 
@@ -6929,7 +6930,7 @@
 #ifndef CONFIG_NO_CONFIG_WRITE
 static int wpas_global_ctrl_iface_save_config(struct wpa_global *global)
 {
-	int ret = 0;
+	int ret = 0, saved = 0;
 	struct wpa_supplicant *wpa_s;
 
 	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
@@ -6943,9 +6944,16 @@
 			ret = 1;
 		} else {
 			wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration updated");
+			saved++;
 		}
 	}
 
+	if (!saved && !ret) {
+		wpa_dbg(wpa_s, MSG_DEBUG,
+			"CTRL_IFACE: SAVE_CONFIG - No configuration files could be updated");
+		ret = 1;
+	}
+
 	return ret;
 }
 #endif /* CONFIG_NO_CONFIG_WRITE */
@@ -7058,8 +7066,19 @@
 	} else if (os_strcmp(buf, "RESUME") == 0) {
 		wpas_notify_resume(global);
 	} else if (os_strncmp(buf, "SET ", 4) == 0) {
-		if (wpas_global_ctrl_iface_set(global, buf + 4))
+		if (wpas_global_ctrl_iface_set(global, buf + 4)) {
+#ifdef CONFIG_P2P
+			if (global->p2p_init_wpa_s) {
+				os_free(reply);
+				/* Check if P2P redirection would work for this
+				 * command. */
+				return wpa_supplicant_ctrl_iface_process(
+					global->p2p_init_wpa_s,
+					buf, resp_len);
+			}
+#endif /* CONFIG_P2P */
 			reply_len = -1;
+		}
 #ifndef CONFIG_NO_CONFIG_WRITE
 	} else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
 		if (wpas_global_ctrl_iface_save_config(global))
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index a9fbf00..5d9cbf7 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -2967,6 +2967,12 @@
 	wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
 	wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
 	wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
+
+	if (ssid->ht40_intolerant) {
+		u16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
+		htcaps->ht_capabilities_info |= bit;
+		htcaps_mask->ht_capabilities_info |= bit;
+	}
 }
 
 #endif /* CONFIG_HT_OVERRIDES */
@@ -3679,6 +3685,8 @@
 	wpa_supplicant_cleanup(wpa_s);
 
 #ifdef CONFIG_P2P
+	if (wpa_s == wpa_s->parent)
+		wpas_p2p_group_remove(wpa_s, "*");
 	if (wpa_s == wpa_s->global->p2p_init_wpa_s && wpa_s->global->p2p) {
 		wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Disable P2P since removing "
 			"the management interface is being removed");
diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf
index 629d886..86a4621 100644
--- a/wpa_supplicant/wpa_supplicant.conf
+++ b/wpa_supplicant/wpa_supplicant.conf
@@ -951,6 +951,10 @@
 # 0 = LDPC enabled (if AP supports it)
 # 1 = LDPC disabled
 #
+# ht40_intolerant: Whether 40 MHz intolerant should be indicated.
+# 0 = 40 MHz tolerant (default)
+# 1 = 40 MHz intolerant
+#
 # ht_mcs:  Configure allowed MCS rates.
 #  Parsed as an array of bytes, in base-16 (ascii-hex)
 # ht_mcs=""                                   // Use all available (default)