Merge "Merge commit 'dda10c2afb8378747491ea5d329a1de635d6d58e' into merge"
diff --git a/hostapd/Android.mk b/hostapd/Android.mk
index 123d2c9..85ac8c5 100644
--- a/hostapd/Android.mk
+++ b/hostapd/Android.mk
@@ -557,17 +557,6 @@
 CONFIG_INTERNAL_DH_GROUP5=y
 endif
 
-ifeq ($(CONFIG_TLS), schannel)
-ifdef TLS_FUNCS
-OBJS += src/crypto/tls_schannel.c
-endif
-OBJS += src/crypto/crypto_cryptoapi.c
-OBJS_p += src/crypto/crypto_cryptoapi.c
-CONFIG_INTERNAL_SHA256=y
-CONFIG_INTERNAL_RC4=y
-CONFIG_INTERNAL_DH_GROUP5=y
-endif
-
 ifeq ($(CONFIG_TLS), internal)
 ifndef CONFIG_CRYPTO
 CONFIG_CRYPTO=internal
@@ -805,8 +794,10 @@
 HOBJS += src/crypto/random.c
 HOBJS += src/utils/eloop.c
 HOBJS += $(SHA1OBJS)
+ifneq ($(CONFIG_TLS), openssl)
 HOBJS += src/crypto/md5.c
 endif
+endif
 
 ifdef CONFIG_RADIUS_SERVER
 L_CFLAGS += -DRADIUS_SERVER
diff --git a/hostapd/Makefile b/hostapd/Makefile
index eace68c..d718c15 100644
--- a/hostapd/Makefile
+++ b/hostapd/Makefile
@@ -553,17 +553,6 @@
 CONFIG_INTERNAL_DH_GROUP5=y
 endif
 
-ifeq ($(CONFIG_TLS), schannel)
-ifdef TLS_FUNCS
-OBJS += ../src/crypto/tls_schannel.o
-endif
-OBJS += ../src/crypto/crypto_cryptoapi.o
-OBJS_p += ../src/crypto/crypto_cryptoapi.o
-CONFIG_INTERNAL_SHA256=y
-CONFIG_INTERNAL_RC4=y
-CONFIG_INTERNAL_DH_GROUP5=y
-endif
-
 ifeq ($(CONFIG_TLS), internal)
 ifndef CONFIG_CRYPTO
 CONFIG_CRYPTO=internal
@@ -803,8 +792,10 @@
 HOBJS += ../src/crypto/random.o
 HOBJS += ../src/utils/eloop.o
 HOBJS += $(SHA1OBJS)
+ifneq ($(CONFIG_TLS), openssl)
 HOBJS += ../src/crypto/md5.o
 endif
+endif
 
 ifdef CONFIG_RADIUS_SERVER
 CFLAGS += -DRADIUS_SERVER
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 53143f7..cae9fd3 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -775,6 +775,24 @@
 }
 
 
+static int hostapd_parse_chanlist(struct hostapd_config *conf, char *val)
+{
+	char *pos;
+
+	/* for backwards compatibility, translate ' ' in conf str to ',' */
+	pos = val;
+	while (pos) {
+		pos = os_strchr(pos, ' ');
+		if (pos)
+			*pos++ = ',';
+	}
+	if (freq_range_list_parse(&conf->acs_ch_list, val))
+		return -1;
+
+	return 0;
+}
+
+
 static int hostapd_parse_intlist(int **int_list, char *val)
 {
 	int *list;
@@ -2542,12 +2560,15 @@
 				   line);
 			return 1;
 #else /* CONFIG_ACS */
+			conf->acs = 1;
 			conf->channel = 0;
 #endif /* CONFIG_ACS */
-		} else
+		} else {
 			conf->channel = atoi(pos);
+			conf->acs = conf->channel == 0;
+		}
 	} else if (os_strcmp(buf, "chanlist") == 0) {
-		if (hostapd_parse_intlist(&conf->chanlist, pos)) {
+		if (hostapd_parse_chanlist(conf, pos)) {
 			wpa_printf(MSG_ERROR, "Line %d: invalid channel list",
 				   line);
 			return 1;
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index 9e81e9e..90d1523 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -170,8 +170,11 @@
 
 # Channel list restriction. This option allows hostapd to select one of the
 # provided channels when a channel should be automatically selected.
-# Default: not set (allow any enabled channel to be selected)
+# Channel list can be provided as range using hyphen ('-') or individual
+# channels can be specified by space (' ') seperated values
+# Default: all channels allowed in selected hw_mode
 #chanlist=100 104 108 112 116
+#chanlist=1 6 11-13
 
 # Beacon interval in kus (1.024 ms) (default: 100; range 15..65535)
 beacon_int=100
diff --git a/src/ap/acs.c b/src/ap/acs.c
index ae7f6c3..652d020 100644
--- a/src/ap/acs.c
+++ b/src/ap/acs.c
@@ -479,16 +479,10 @@
 static int is_in_chanlist(struct hostapd_iface *iface,
 			  struct hostapd_channel_data *chan)
 {
-	int *entry;
-
-	if (!iface->conf->chanlist)
+	if (!iface->conf->acs_ch_list.num)
 		return 1;
 
-	for (entry = iface->conf->chanlist; *entry != -1; entry++) {
-		if (*entry == chan->chan)
-			return 1;
-	}
-	return 0;
+	return freq_range_list_includes(&iface->conf->acs_ch_list, chan->chan);
 }
 
 
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index 76011dc..cccbfab 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -181,6 +181,8 @@
 	conf->corrupt_gtk_rekey_mic_probability = 0.0;
 #endif /* CONFIG_TESTING_OPTIONS */
 
+	conf->acs = 0;
+	conf->acs_ch_list.num = 0;
 #ifdef CONFIG_ACS
 	conf->acs_num_scans = 5;
 #endif /* CONFIG_ACS */
@@ -579,7 +581,7 @@
 	os_free(conf->bss);
 	os_free(conf->supported_rates);
 	os_free(conf->basic_rates);
-	os_free(conf->chanlist);
+	os_free(conf->acs_ch_list.range);
 	os_free(conf->driver_params);
 #ifdef CONFIG_ACS
 	os_free(conf->acs_chan_bias);
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index 961d2dd..b9d6832 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -568,7 +568,8 @@
 	int fragm_threshold;
 	u8 send_probe_response;
 	u8 channel;
-	int *chanlist;
+	u8 acs;
+	struct wpa_freq_range_list acs_ch_list;
 	enum hostapd_hw_mode hw_mode; /* HOSTAPD_MODE_IEEE80211A, .. */
 	enum {
 		LONG_PREAMBLE = 0,
diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
index e16306c..9ee88b4 100644
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -217,6 +217,15 @@
 }
 
 
+int hostapd_reset_ap_wps_ie(struct hostapd_data *hapd)
+{
+	if (hapd->driver == NULL || hapd->driver->set_ap_wps_ie == NULL)
+		return 0;
+
+	return hapd->driver->set_ap_wps_ie(hapd->drv_priv, NULL, NULL, NULL);
+}
+
+
 int hostapd_set_ap_wps_ie(struct hostapd_data *hapd)
 {
 	struct wpabuf *beacon, *proberesp, *assocresp;
@@ -715,13 +724,66 @@
 int hostapd_drv_do_acs(struct hostapd_data *hapd)
 {
 	struct drv_acs_params params;
+	int ret, i, acs_ch_list_all = 0;
+	u8 *channels = NULL;
+	unsigned int num_channels = 0;
+	struct hostapd_hw_modes *mode;
 
 	if (hapd->driver == NULL || hapd->driver->do_acs == NULL)
 		return 0;
+
 	os_memset(&params, 0, sizeof(params));
 	params.hw_mode = hapd->iface->conf->hw_mode;
+
+	/*
+	 * If no chanlist config parameter is provided, include all enabled
+	 * channels of the selected hw_mode.
+	 */
+	if (!hapd->iface->conf->acs_ch_list.num)
+		acs_ch_list_all = 1;
+
+	mode = hapd->iface->current_mode;
+	if (mode == NULL)
+		return -1;
+	channels = os_malloc(mode->num_channels);
+	if (channels == NULL)
+		return -1;
+
+	for (i = 0; i < mode->num_channels; i++) {
+		struct hostapd_channel_data *chan = &mode->channels[i];
+		if (!acs_ch_list_all &&
+		    !freq_range_list_includes(&hapd->iface->conf->acs_ch_list,
+					      chan->chan))
+			continue;
+		if (!(chan->flag & HOSTAPD_CHAN_DISABLED))
+			channels[num_channels++] = chan->chan;
+	}
+
+	params.ch_list = channels;
+	params.ch_list_len = num_channels;
+
 	params.ht_enabled = !!(hapd->iface->conf->ieee80211n);
 	params.ht40_enabled = !!(hapd->iface->conf->ht_capab &
 				 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET);
-	return hapd->driver->do_acs(hapd->drv_priv, &params);
+	params.vht_enabled = !!(hapd->iface->conf->ieee80211ac);
+	params.ch_width = 20;
+	if (hapd->iface->conf->ieee80211n && params.ht40_enabled)
+		params.ch_width = 40;
+
+	/* Note: VHT20 is defined by combination of ht_capab & vht_oper_chwidth
+	 */
+	if (hapd->iface->conf->ieee80211ac && params.ht40_enabled) {
+		if (hapd->iface->conf->vht_oper_chwidth == VHT_CHANWIDTH_80MHZ)
+			params.ch_width = 80;
+		else if (hapd->iface->conf->vht_oper_chwidth ==
+			 VHT_CHANWIDTH_160MHZ ||
+			 hapd->iface->conf->vht_oper_chwidth ==
+			 VHT_CHANWIDTH_80P80MHZ)
+			params.ch_width = 160;
+	}
+
+	ret = hapd->driver->do_acs(hapd->drv_priv, &params);
+	os_free(channels);
+
+	return ret;
 }
diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
index 5d07e71..82eaf3f 100644
--- a/src/ap/ap_drv_ops.h
+++ b/src/ap/ap_drv_ops.h
@@ -24,6 +24,7 @@
 void hostapd_free_ap_extra_ies(struct hostapd_data *hapd, struct wpabuf *beacon,
 			       struct wpabuf *proberesp,
 			       struct wpabuf *assocresp);
+int hostapd_reset_ap_wps_ie(struct hostapd_data *hapd);
 int hostapd_set_ap_wps_ie(struct hostapd_data *hapd);
 int hostapd_set_authorized(struct hostapd_data *hapd,
 			   struct sta_info *sta, int authorized);
diff --git a/src/ap/dfs.c b/src/ap/dfs.c
index da6fd46..715f19b 100644
--- a/src/ap/dfs.c
+++ b/src/ap/dfs.c
@@ -122,6 +122,20 @@
 }
 
 
+static struct hostapd_channel_data *
+dfs_get_chan_data(struct hostapd_hw_modes *mode, int freq, int first_chan_idx)
+{
+	int i;
+
+	for (i = first_chan_idx; i < mode->num_channels; i++) {
+		if (mode->channels[i].freq == freq)
+			return &mode->channels[i];
+	}
+
+	return NULL;
+}
+
+
 static int dfs_chan_range_available(struct hostapd_hw_modes *mode,
 				    int first_chan_idx, int num_chans,
 				    int skip_radar)
@@ -129,15 +143,15 @@
 	struct hostapd_channel_data *first_chan, *chan;
 	int i;
 
-	if (first_chan_idx + num_chans >= mode->num_channels)
+	if (first_chan_idx + num_chans > mode->num_channels)
 		return 0;
 
 	first_chan = &mode->channels[first_chan_idx];
 
 	for (i = 0; i < num_chans; i++) {
-		chan = &mode->channels[first_chan_idx + i];
-
-		if (first_chan->freq + i * 20 != chan->freq)
+		chan = dfs_get_chan_data(mode, first_chan->freq + i * 20,
+					 first_chan_idx);
+		if (!chan)
 			return 0;
 
 		if (!dfs_channel_available(chan, skip_radar))
@@ -151,16 +165,10 @@
 static int is_in_chanlist(struct hostapd_iface *iface,
 			  struct hostapd_channel_data *chan)
 {
-	int *entry;
-
-	if (!iface->conf->chanlist)
+	if (!iface->conf->acs_ch_list.num)
 		return 1;
 
-	for (entry = iface->conf->chanlist; *entry != -1; entry++) {
-		if (*entry == chan->chan)
-			return 1;
-	}
-	return 0;
+	return freq_range_list_includes(&iface->conf->acs_ch_list, chan->chan);
 }
 
 
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index a0adc67..507053e 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -532,9 +532,8 @@
 
 #ifdef CONFIG_ACS
 static void hostapd_acs_channel_selected(struct hostapd_data *hapd,
-					 u8 pri_channel, u8 sec_channel)
+					 struct acs_selected_channels *acs_res)
 {
-	int channel;
 	int ret;
 
 	if (hapd->iconf->channel) {
@@ -543,29 +542,55 @@
 		return;
 	}
 
-	hapd->iface->freq = hostapd_hw_get_freq(hapd, pri_channel);
+	hapd->iface->freq = hostapd_hw_get_freq(hapd, acs_res->pri_channel);
 
-	channel = pri_channel;
-	if (!channel) {
+	if (!acs_res->pri_channel) {
 		hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
 			       HOSTAPD_LEVEL_WARNING,
 			       "driver switched to bad channel");
 		return;
 	}
 
-	hapd->iconf->channel = channel;
+	hapd->iconf->channel = acs_res->pri_channel;
+	hapd->iconf->acs = 1;
 
-	if (sec_channel == 0)
+	if (acs_res->sec_channel == 0)
 		hapd->iconf->secondary_channel = 0;
-	else if (sec_channel < pri_channel)
+	else if (acs_res->sec_channel < acs_res->pri_channel)
 		hapd->iconf->secondary_channel = -1;
-	else if (sec_channel > pri_channel)
+	else if (acs_res->sec_channel > acs_res->pri_channel)
 		hapd->iconf->secondary_channel = 1;
 	else {
 		wpa_printf(MSG_ERROR, "Invalid secondary channel!");
 		return;
 	}
 
+	if (hapd->iface->conf->ieee80211ac) {
+		/* set defaults for backwards compatibility */
+		hapd->iconf->vht_oper_centr_freq_seg1_idx = 0;
+		hapd->iconf->vht_oper_centr_freq_seg0_idx = 0;
+		hapd->iconf->vht_oper_chwidth = VHT_CHANWIDTH_USE_HT;
+		if (acs_res->ch_width == 80) {
+			hapd->iconf->vht_oper_centr_freq_seg0_idx =
+				acs_res->vht_seg0_center_ch;
+			hapd->iconf->vht_oper_chwidth = VHT_CHANWIDTH_80MHZ;
+		} else if (acs_res->ch_width == 160) {
+			if (acs_res->vht_seg1_center_ch == 0) {
+				hapd->iconf->vht_oper_centr_freq_seg0_idx =
+					acs_res->vht_seg0_center_ch;
+				hapd->iconf->vht_oper_chwidth =
+					VHT_CHANWIDTH_160MHZ;
+			} else {
+				hapd->iconf->vht_oper_centr_freq_seg0_idx =
+					acs_res->vht_seg0_center_ch;
+				hapd->iconf->vht_oper_centr_freq_seg1_idx =
+					acs_res->vht_seg1_center_ch;
+				hapd->iconf->vht_oper_chwidth =
+					VHT_CHANWIDTH_80P80MHZ;
+			}
+		}
+	}
+
 	ret = hostapd_acs_completed(hapd->iface, 0);
 	if (ret) {
 		wpa_printf(MSG_ERROR,
@@ -1248,9 +1273,8 @@
 		break;
 #ifdef CONFIG_ACS
 	case EVENT_ACS_CHANNEL_SELECTED:
-		hostapd_acs_channel_selected(
-			hapd, data->acs_selected_channels.pri_channel,
-			data->acs_selected_channels.sec_channel);
+		hostapd_acs_channel_selected(hapd,
+					     &data->acs_selected_channels);
 		break;
 #endif /* CONFIG_ACS */
 	default:
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 3e4e16b..6cdb6d3 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -179,6 +179,7 @@
 		hapd = iface->bss[j];
 		hapd->iconf = newconf;
 		hapd->iconf->channel = oldconf->channel;
+		hapd->iconf->acs = oldconf->acs;
 		hapd->iconf->secondary_channel = oldconf->secondary_channel;
 		hapd->iconf->ieee80211n = oldconf->ieee80211n;
 		hapd->iconf->ieee80211ac = oldconf->ieee80211ac;
diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c
index 05431d3..96744c4 100644
--- a/src/ap/hw_features.c
+++ b/src/ap/hw_features.c
@@ -510,7 +510,11 @@
 		return 0;
 	}
 
-	if ((conf & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) &&
+	/*
+	 * Driver ACS chosen channel may not be HT40 due to internal driver
+	 * restrictions.
+	 */
+	if (!iface->conf->acs && (conf & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) &&
 	    !(hw & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) {
 		wpa_printf(MSG_ERROR, "Driver does not support configured "
 			   "HT capability [HT40*]");
diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
index 9c5f609..b83b460 100644
--- a/src/ap/wpa_auth.c
+++ b/src/ap/wpa_auth.c
@@ -67,6 +67,14 @@
 }
 
 
+static inline void wpa_auth_psk_failure_report(
+	struct wpa_authenticator *wpa_auth, const u8 *addr)
+{
+	if (wpa_auth->cb.psk_failure_report)
+		wpa_auth->cb.psk_failure_report(wpa_auth->cb.ctx, addr);
+}
+
+
 static inline void wpa_auth_set_eapol(struct wpa_authenticator *wpa_auth,
 				      const u8 *addr, wpa_eapol_variable var,
 				      int value)
@@ -1985,7 +1993,7 @@
 SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
 {
 	struct wpa_ptk PTK;
-	int ok = 0;
+	int ok = 0, psk_found = 0;
 	const u8 *pmk = NULL;
 
 	SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING, wpa_ptk);
@@ -2001,6 +2009,7 @@
 					       sm->p2p_dev_addr, pmk);
 			if (pmk == NULL)
 				break;
+			psk_found = 1;
 		} else
 			pmk = sm->PMK;
 
@@ -2020,6 +2029,8 @@
 	if (!ok) {
 		wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
 				"invalid MIC in msg 2/4 of 4-Way Handshake");
+		if (psk_found)
+			wpa_auth_psk_failure_report(sm->wpa_auth, sm->addr);
 		return;
 	}
 
diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
index 2788e65..11e745e 100644
--- a/src/ap/wpa_auth.h
+++ b/src/ap/wpa_auth.h
@@ -189,6 +189,7 @@
 		       const char *txt);
 	void (*disconnect)(void *ctx, const u8 *addr, u16 reason);
 	int (*mic_failure_report)(void *ctx, const u8 *addr);
+	void (*psk_failure_report)(void *ctx, const u8 *addr);
 	void (*set_eapol)(void *ctx, const u8 *addr, wpa_eapol_variable var,
 			  int value);
 	int (*get_eapol)(void *ctx, const u8 *addr, wpa_eapol_variable var);
diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c
index 7f83207..d417a72 100644
--- a/src/ap/wpa_auth_glue.c
+++ b/src/ap/wpa_auth_glue.c
@@ -11,6 +11,7 @@
 #include "utils/common.h"
 #include "common/ieee802_11_defs.h"
 #include "common/sae.h"
+#include "common/wpa_ctrl.h"
 #include "eapol_auth/eapol_auth_sm.h"
 #include "eapol_auth/eapol_auth_sm_i.h"
 #include "eap_server/eap.h"
@@ -144,6 +145,14 @@
 }
 
 
+static void hostapd_wpa_auth_psk_failure_report(void *ctx, const u8 *addr)
+{
+	struct hostapd_data *hapd = ctx;
+	wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_POSSIBLE_PSK_MISMATCH MACSTR,
+		MAC2STR(addr));
+}
+
+
 static void hostapd_wpa_auth_set_eapol(void *ctx, const u8 *addr,
 				       wpa_eapol_variable var, int value)
 {
@@ -579,6 +588,7 @@
 	cb.logger = hostapd_wpa_auth_logger;
 	cb.disconnect = hostapd_wpa_auth_disconnect;
 	cb.mic_failure_report = hostapd_wpa_auth_mic_failure_report;
+	cb.psk_failure_report = hostapd_wpa_auth_psk_failure_report;
 	cb.set_eapol = hostapd_wpa_auth_set_eapol;
 	cb.get_eapol = hostapd_wpa_auth_get_eapol;
 	cb.get_psk = hostapd_wpa_auth_get_psk;
diff --git a/src/ap/wps_hostapd.c b/src/ap/wps_hostapd.c
index b0e8b0b..7e74829 100644
--- a/src/ap/wps_hostapd.c
+++ b/src/ap/wps_hostapd.c
@@ -856,8 +856,10 @@
 	wpabuf_free(hapd->wps_probe_resp_ie);
 	hapd->wps_probe_resp_ie = NULL;
 
-	if (deinit_only)
+	if (deinit_only) {
+		hostapd_reset_ap_wps_ie(hapd);
 		return;
+	}
 
 	hostapd_set_ap_wps_ie(hapd);
 }
diff --git a/src/common/hw_features_common.c b/src/common/hw_features_common.c
index 309215e..8d83de6 100644
--- a/src/common/hw_features_common.c
+++ b/src/common/hw_features_common.c
@@ -363,8 +363,6 @@
 			    int vht_oper_chwidth, int center_segment0,
 			    int center_segment1, u32 vht_caps)
 {
-	int tmp;
-
 	os_memset(data, 0, sizeof(*data));
 	data->mode = mode;
 	data->freq = freq;
@@ -404,13 +402,34 @@
 			return -1;
 		if (!sec_channel_offset)
 			return -1;
-		/* primary 40 part must match the HT configuration */
-		tmp = (30 + freq - 5000 - center_segment0 * 5) / 20;
-		tmp /= 2;
-		if (data->center_freq1 != 5000 +
-		    center_segment0 * 5 - 20 + 40 * tmp)
-			return -1;
-		data->center_freq1 = 5000 + center_segment0 * 5;
+		if (!center_segment0) {
+			if (channel <= 48)
+				center_segment0 = 42;
+			else if (channel <= 64)
+				center_segment0 = 58;
+			else if (channel <= 112)
+				center_segment0 = 106;
+			else if (channel <= 128)
+				center_segment0 = 122;
+			else if (channel <= 144)
+				center_segment0 = 138;
+			else if (channel <= 161)
+				center_segment0 = 155;
+			data->center_freq1 = 5000 + center_segment0 * 5;
+		} else {
+			/*
+			 * Note: HT/VHT config and params are coupled. Check if
+			 * HT40 channel band is in VHT80 Pri channel band
+			 * configuration.
+			 */
+			if (center_segment0 == channel + 6 ||
+			    center_segment0 == channel + 2 ||
+			    center_segment0 == channel - 2 ||
+			    center_segment0 == channel - 6)
+				data->center_freq1 = 5000 + center_segment0 * 5;
+			else
+				return -1;
+		}
 		break;
 	case VHT_CHANWIDTH_160MHZ:
 		data->bandwidth = 160;
@@ -424,13 +443,21 @@
 			return -1;
 		if (!sec_channel_offset)
 			return -1;
-		/* primary 40 part must match the HT configuration */
-		tmp = (70 + freq - 5000 - center_segment0 * 5) / 20;
-		tmp /= 2;
-		if (data->center_freq1 != 5000 +
-		    center_segment0 * 5 - 60 + 40 * tmp)
+		/*
+		 * Note: HT/VHT config and params are coupled. Check if
+		 * HT40 channel band is in VHT160 channel band configuration.
+		 */
+		if (center_segment0 == channel + 14 ||
+		    center_segment0 == channel + 10 ||
+		    center_segment0 == channel + 6 ||
+		    center_segment0 == channel + 2 ||
+		    center_segment0 == channel - 2 ||
+		    center_segment0 == channel - 6 ||
+		    center_segment0 == channel - 10 ||
+		    center_segment0 == channel - 14)
+			data->center_freq1 = 5000 + center_segment0 * 5;
+		else
 			return -1;
-		data->center_freq1 = 5000 + center_segment0 * 5;
 		break;
 	}
 
diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h
index 2117ee7..5ff6817 100644
--- a/src/common/qca-vendor.h
+++ b/src/common/qca-vendor.h
@@ -195,6 +195,11 @@
 	QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
 	QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED,
 	QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED,
+	QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED,
+	QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
+	QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST,
+	QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
+	QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
 	/* keep last */
 	QCA_WLAN_VENDOR_ATTR_ACS_AFTER_LAST,
 	QCA_WLAN_VENDOR_ATTR_ACS_MAX =
diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h
index 1d19fc5..e3a816f 100644
--- a/src/common/wpa_ctrl.h
+++ b/src/common/wpa_ctrl.h
@@ -227,6 +227,7 @@
 #define WPS_EVENT_AP_PIN_DISABLED "WPS-AP-PIN-DISABLED "
 #define AP_STA_CONNECTED "AP-STA-CONNECTED "
 #define AP_STA_DISCONNECTED "AP-STA-DISCONNECTED "
+#define AP_STA_POSSIBLE_PSK_MISMATCH "AP-STA-POSSIBLE-PSK-MISMATCH "
 
 #define AP_REJECTED_MAX_STA "AP-REJECTED-MAX-STA "
 #define AP_REJECTED_BLOCKED_STA "AP-REJECTED-BLOCKED-STA "
diff --git a/src/crypto/crypto_cryptoapi.c b/src/crypto/crypto_cryptoapi.c
deleted file mode 100644
index 55a069b..0000000
--- a/src/crypto/crypto_cryptoapi.c
+++ /dev/null
@@ -1,783 +0,0 @@
-/*
- * Crypto wrapper for Microsoft CryptoAPI
- * Copyright (c) 2005-2009, Jouni Malinen <j@w1.fi>
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#include "includes.h"
-#include <windows.h>
-#include <wincrypt.h>
-
-#include "common.h"
-#include "crypto.h"
-
-#ifndef MS_ENH_RSA_AES_PROV
-#ifdef UNICODE
-#define MS_ENH_RSA_AES_PROV \
-L"Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)"
-#else
-#define MS_ENH_RSA_AES_PROV \
-"Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)"
-#endif
-#endif /* MS_ENH_RSA_AES_PROV */
-
-#ifndef CALG_HMAC
-#define CALG_HMAC (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_HMAC)
-#endif
-
-#ifdef __MINGW32_VERSION
-/*
- * MinGW does not yet include all the needed definitions for CryptoAPI, so
- * define here whatever extra is needed.
- */
-
-static BOOL WINAPI
-(*CryptImportPublicKeyInfo)(HCRYPTPROV hCryptProv, DWORD dwCertEncodingType,
-			    PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey)
-= NULL; /* to be loaded from crypt32.dll */
-
-
-static int mingw_load_crypto_func(void)
-{
-	HINSTANCE dll;
-
-	/* MinGW does not yet have full CryptoAPI support, so load the needed
-	 * function here. */
-
-	if (CryptImportPublicKeyInfo)
-		return 0;
-
-	dll = LoadLibrary("crypt32");
-	if (dll == NULL) {
-		wpa_printf(MSG_DEBUG, "CryptoAPI: Could not load crypt32 "
-			   "library");
-		return -1;
-	}
-
-	CryptImportPublicKeyInfo = GetProcAddress(
-		dll, "CryptImportPublicKeyInfo");
-	if (CryptImportPublicKeyInfo == NULL) {
-		wpa_printf(MSG_DEBUG, "CryptoAPI: Could not get "
-			   "CryptImportPublicKeyInfo() address from "
-			   "crypt32 library");
-		return -1;
-	}
-
-	return 0;
-}
-
-#else /* __MINGW32_VERSION */
-
-static int mingw_load_crypto_func(void)
-{
-	return 0;
-}
-
-#endif /* __MINGW32_VERSION */
-
-
-static void cryptoapi_report_error(const char *msg)
-{
-	char *s, *pos;
-	DWORD err = GetLastError();
-
-	if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
-			  FORMAT_MESSAGE_FROM_SYSTEM,
-			  NULL, err, 0, (LPTSTR) &s, 0, NULL) == 0) {
- 		wpa_printf(MSG_DEBUG, "CryptoAPI: %s: %d", msg, (int) err);
-	}
-
-	pos = s;
-	while (*pos) {
-		if (*pos == '\n' || *pos == '\r') {
-			*pos = '\0';
-			break;
-		}
-		pos++;
-	}
-
-	wpa_printf(MSG_DEBUG, "CryptoAPI: %s: %d: (%s)", msg, (int) err, s);
-	LocalFree(s);
-}
-
-
-int cryptoapi_hash_vector(ALG_ID alg, size_t hash_len, size_t num_elem,
-			  const u8 *addr[], const size_t *len, u8 *mac)
-{
-	HCRYPTPROV prov;
-	HCRYPTHASH hash;
-	size_t i;
-	DWORD hlen;
-	int ret = 0;
-
-	if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, 0)) {
-		cryptoapi_report_error("CryptAcquireContext");
-		return -1;
-	}
-
-	if (!CryptCreateHash(prov, alg, 0, 0, &hash)) {
-		cryptoapi_report_error("CryptCreateHash");
-		CryptReleaseContext(prov, 0);
-		return -1;
-	}
-
-	for (i = 0; i < num_elem; i++) {
-		if (!CryptHashData(hash, (BYTE *) addr[i], len[i], 0)) {
-			cryptoapi_report_error("CryptHashData");
-			CryptDestroyHash(hash);
-			CryptReleaseContext(prov, 0);
-		}
-	}
-
-	hlen = hash_len;
-	if (!CryptGetHashParam(hash, HP_HASHVAL, mac, &hlen, 0)) {
-		cryptoapi_report_error("CryptGetHashParam");
-		ret = -1;
-	}
-
-	CryptDestroyHash(hash);
-	CryptReleaseContext(prov, 0);
-
-	return ret;
-}
-
-
-int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
-{
-	return cryptoapi_hash_vector(CALG_MD4, 16, num_elem, addr, len, mac);
-}
-
-
-void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
-{
-	u8 next, tmp;
-	int i;
-	HCRYPTPROV prov;
-	HCRYPTKEY ckey;
-	DWORD dlen;
-	struct {
-		BLOBHEADER hdr;
-		DWORD len;
-		BYTE key[8];
-	} key_blob;
-	DWORD mode = CRYPT_MODE_ECB;
-
-	key_blob.hdr.bType = PLAINTEXTKEYBLOB;
-	key_blob.hdr.bVersion = CUR_BLOB_VERSION;
-	key_blob.hdr.reserved = 0;
-	key_blob.hdr.aiKeyAlg = CALG_DES;
-	key_blob.len = 8;
-
-	/* Add parity bits to the key */
-	next = 0;
-	for (i = 0; i < 7; i++) {
-		tmp = key[i];
-		key_blob.key[i] = (tmp >> i) | next | 1;
-		next = tmp << (7 - i);
-	}
-	key_blob.key[i] = next | 1;
-
-	if (!CryptAcquireContext(&prov, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL,
-				 CRYPT_VERIFYCONTEXT)) {
- 		wpa_printf(MSG_DEBUG, "CryptoAPI: CryptAcquireContext failed: "
-			   "%d", (int) GetLastError());
-		return;
-	}
-
-	if (!CryptImportKey(prov, (BYTE *) &key_blob, sizeof(key_blob), 0, 0,
-			    &ckey)) {
- 		wpa_printf(MSG_DEBUG, "CryptoAPI: CryptImportKey failed: %d",
-			   (int) GetLastError());
-		CryptReleaseContext(prov, 0);
-		return;
-	}
-
-	if (!CryptSetKeyParam(ckey, KP_MODE, (BYTE *) &mode, 0)) {
- 		wpa_printf(MSG_DEBUG, "CryptoAPI: CryptSetKeyParam(KP_MODE) "
-			   "failed: %d", (int) GetLastError());
-		CryptDestroyKey(ckey);
-		CryptReleaseContext(prov, 0);
-		return;
-	}
-
-	os_memcpy(cypher, clear, 8);
-	dlen = 8;
-	if (!CryptEncrypt(ckey, 0, FALSE, 0, cypher, &dlen, 8)) {
-		wpa_printf(MSG_DEBUG, "CryptoAPI: CryptEncrypt failed: %d",
-			   (int) GetLastError());
-		os_memset(cypher, 0, 8);
-	}
-
-	CryptDestroyKey(ckey);
-	CryptReleaseContext(prov, 0);
-}
-
-
-int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
-{
-	return cryptoapi_hash_vector(CALG_MD5, 16, num_elem, addr, len, mac);
-}
-
-
-int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
-{
-	return cryptoapi_hash_vector(CALG_SHA, 20, num_elem, addr, len, mac);
-}
-
-
-struct aes_context {
-	HCRYPTPROV prov;
-	HCRYPTKEY ckey;
-};
-
-
-void * aes_encrypt_init(const u8 *key, size_t len)
-{
-	struct aes_context *akey;
-	struct {
-		BLOBHEADER hdr;
-		DWORD len;
-		BYTE key[16];
-	} key_blob;
-	DWORD mode = CRYPT_MODE_ECB;
-
-	if (len != 16)
-		return NULL;
-
-	key_blob.hdr.bType = PLAINTEXTKEYBLOB;
-	key_blob.hdr.bVersion = CUR_BLOB_VERSION;
-	key_blob.hdr.reserved = 0;
-	key_blob.hdr.aiKeyAlg = CALG_AES_128;
-	key_blob.len = len;
-	os_memcpy(key_blob.key, key, len);
-
-	akey = os_zalloc(sizeof(*akey));
-	if (akey == NULL)
-		return NULL;
-
-	if (!CryptAcquireContext(&akey->prov, NULL,
-				 MS_ENH_RSA_AES_PROV, PROV_RSA_AES,
-				 CRYPT_VERIFYCONTEXT)) {
- 		wpa_printf(MSG_DEBUG, "CryptoAPI: CryptAcquireContext failed: "
-			   "%d", (int) GetLastError());
-		os_free(akey);
-		return NULL;
-	}
-
-	if (!CryptImportKey(akey->prov, (BYTE *) &key_blob, sizeof(key_blob),
-			    0, 0, &akey->ckey)) {
- 		wpa_printf(MSG_DEBUG, "CryptoAPI: CryptImportKey failed: %d",
-			   (int) GetLastError());
-		CryptReleaseContext(akey->prov, 0);
-		os_free(akey);
-		return NULL;
-	}
-
-	if (!CryptSetKeyParam(akey->ckey, KP_MODE, (BYTE *) &mode, 0)) {
- 		wpa_printf(MSG_DEBUG, "CryptoAPI: CryptSetKeyParam(KP_MODE) "
-			   "failed: %d", (int) GetLastError());
-		CryptDestroyKey(akey->ckey);
-		CryptReleaseContext(akey->prov, 0);
-		os_free(akey);
-		return NULL;
-	}
-
-	return akey;
-}
-
-
-void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
-{
-	struct aes_context *akey = ctx;
-	DWORD dlen;
-
-	os_memcpy(crypt, plain, 16);
-	dlen = 16;
-	if (!CryptEncrypt(akey->ckey, 0, FALSE, 0, crypt, &dlen, 16)) {
-		wpa_printf(MSG_DEBUG, "CryptoAPI: CryptEncrypt failed: %d",
-			   (int) GetLastError());
-		os_memset(crypt, 0, 16);
-	}
-}
-
-
-void aes_encrypt_deinit(void *ctx)
-{
-	struct aes_context *akey = ctx;
-	if (akey) {
-		CryptDestroyKey(akey->ckey);
-		CryptReleaseContext(akey->prov, 0);
-		os_free(akey);
-	}
-}
-
-
-void * aes_decrypt_init(const u8 *key, size_t len)
-{
-	return aes_encrypt_init(key, len);
-}
-
-
-void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
-{
-	struct aes_context *akey = ctx;
-	DWORD dlen;
-
-	os_memcpy(plain, crypt, 16);
-	dlen = 16;
-
-	if (!CryptDecrypt(akey->ckey, 0, FALSE, 0, plain, &dlen)) {
-		wpa_printf(MSG_DEBUG, "CryptoAPI: CryptDecrypt failed: %d",
-			   (int) GetLastError());
-	}
-}
-
-
-void aes_decrypt_deinit(void *ctx)
-{
-	aes_encrypt_deinit(ctx);
-}
-
-
-struct crypto_hash {
-	enum crypto_hash_alg alg;
-	int error;
-	HCRYPTPROV prov;
-	HCRYPTHASH hash;
-	HCRYPTKEY key;
-};
-
-struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
-				      size_t key_len)
-{
-	struct crypto_hash *ctx;
-	ALG_ID calg;
-	struct {
-		BLOBHEADER hdr;
-		DWORD len;
-		BYTE key[32];
-	} key_blob;
-
-	os_memset(&key_blob, 0, sizeof(key_blob));
-	switch (alg) {
-	case CRYPTO_HASH_ALG_MD5:
-		calg = CALG_MD5;
-		break;
-	case CRYPTO_HASH_ALG_SHA1:
-		calg = CALG_SHA;
-		break;
-	case CRYPTO_HASH_ALG_HMAC_MD5:
-	case CRYPTO_HASH_ALG_HMAC_SHA1:
-		calg = CALG_HMAC;
-		key_blob.hdr.bType = PLAINTEXTKEYBLOB;
-		key_blob.hdr.bVersion = CUR_BLOB_VERSION;
-		key_blob.hdr.reserved = 0;
-		/*
-		 * Note: RC2 is not really used, but that can be used to
-		 * import HMAC keys of up to 16 byte long.
-		 * CRYPT_IPSEC_HMAC_KEY flag for CryptImportKey() is needed to
-		 * be able to import longer keys (HMAC-SHA1 uses 20-byte key).
-		 */
-		key_blob.hdr.aiKeyAlg = CALG_RC2;
-		key_blob.len = key_len;
-		if (key_len > sizeof(key_blob.key))
-			return NULL;
-		os_memcpy(key_blob.key, key, key_len);
-		break;
-	default:
-		return NULL;
-	}
-
-	ctx = os_zalloc(sizeof(*ctx));
-	if (ctx == NULL)
-		return NULL;
-
-	ctx->alg = alg;
-
-	if (!CryptAcquireContext(&ctx->prov, NULL, NULL, PROV_RSA_FULL, 0)) {
-		cryptoapi_report_error("CryptAcquireContext");
-		os_free(ctx);
-		return NULL;
-	}
-
-	if (calg == CALG_HMAC) {
-#ifndef CRYPT_IPSEC_HMAC_KEY
-#define CRYPT_IPSEC_HMAC_KEY 0x00000100
-#endif
-		if (!CryptImportKey(ctx->prov, (BYTE *) &key_blob,
-				    sizeof(key_blob), 0, CRYPT_IPSEC_HMAC_KEY,
-				    &ctx->key)) {
-			cryptoapi_report_error("CryptImportKey");
-			CryptReleaseContext(ctx->prov, 0);
-			os_free(ctx);
-			return NULL;
-		}
-	}
-
-	if (!CryptCreateHash(ctx->prov, calg, ctx->key, 0, &ctx->hash)) {
-		cryptoapi_report_error("CryptCreateHash");
-		CryptReleaseContext(ctx->prov, 0);
-		os_free(ctx);
-		return NULL;
-	}
-
-	if (calg == CALG_HMAC) {
-		HMAC_INFO info;
-		os_memset(&info, 0, sizeof(info));
-		switch (alg) {
-		case CRYPTO_HASH_ALG_HMAC_MD5:
-			info.HashAlgid = CALG_MD5;
-			break;
-		case CRYPTO_HASH_ALG_HMAC_SHA1:
-			info.HashAlgid = CALG_SHA;
-			break;
-		default:
-			/* unreachable */
-			break;
-		}
-
-		if (!CryptSetHashParam(ctx->hash, HP_HMAC_INFO, (BYTE *) &info,
-				       0)) {
-			cryptoapi_report_error("CryptSetHashParam");
-			CryptDestroyHash(ctx->hash);
-			CryptReleaseContext(ctx->prov, 0);
-			os_free(ctx);
-			return NULL;
-		}
-	}
-
-	return ctx;
-}
-
-
-void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
-{
-	if (ctx == NULL || ctx->error)
-		return;
-
-	if (!CryptHashData(ctx->hash, (BYTE *) data, len, 0)) {
-		cryptoapi_report_error("CryptHashData");
-		ctx->error = 1;
-	}
-}
-
-
-int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
-{
-	int ret = 0;
-	DWORD hlen;
-
-	if (ctx == NULL)
-		return -2;
-
-	if (mac == NULL || len == NULL)
-		goto done;
-
-	if (ctx->error) {
-		ret = -2;
-		goto done;
-	}
-
-	hlen = *len;
-	if (!CryptGetHashParam(ctx->hash, HP_HASHVAL, mac, &hlen, 0)) {
-		cryptoapi_report_error("CryptGetHashParam");
-		ret = -2;
-	}
-	*len = hlen;
-
-done:
-	if (ctx->alg == CRYPTO_HASH_ALG_HMAC_SHA1 ||
-	    ctx->alg == CRYPTO_HASH_ALG_HMAC_MD5)
-		CryptDestroyKey(ctx->key);
-
-	os_free(ctx);
-
-	return ret;
-}
-
-
-struct crypto_cipher {
-	HCRYPTPROV prov;
-	HCRYPTKEY key;
-};
-
-
-struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
-					  const u8 *iv, const u8 *key,
-					  size_t key_len)
-{	
-	struct crypto_cipher *ctx;
-	struct {
-		BLOBHEADER hdr;
-		DWORD len;
-		BYTE key[32];
-	} key_blob;
-	DWORD mode = CRYPT_MODE_CBC;
-
-	key_blob.hdr.bType = PLAINTEXTKEYBLOB;
-	key_blob.hdr.bVersion = CUR_BLOB_VERSION;
-	key_blob.hdr.reserved = 0;
-	key_blob.len = key_len;
-	if (key_len > sizeof(key_blob.key))
-		return NULL;
-	os_memcpy(key_blob.key, key, key_len);
-
-	switch (alg) {
-	case CRYPTO_CIPHER_ALG_AES:
-		if (key_len == 32)
-			key_blob.hdr.aiKeyAlg = CALG_AES_256;
-		else if (key_len == 24)
-			key_blob.hdr.aiKeyAlg = CALG_AES_192;
-		else
-			key_blob.hdr.aiKeyAlg = CALG_AES_128;
-		break;
-	case CRYPTO_CIPHER_ALG_3DES:
-		key_blob.hdr.aiKeyAlg = CALG_3DES;
-		break;
-	case CRYPTO_CIPHER_ALG_DES:
-		key_blob.hdr.aiKeyAlg = CALG_DES;
-		break;
-	case CRYPTO_CIPHER_ALG_RC2:
-		key_blob.hdr.aiKeyAlg = CALG_RC2;
-		break;
-	case CRYPTO_CIPHER_ALG_RC4:
-		key_blob.hdr.aiKeyAlg = CALG_RC4;
-		break;
-	default:
-		return NULL;
-	}
-
-	ctx = os_zalloc(sizeof(*ctx));
-	if (ctx == NULL)
-		return NULL;
-
-	if (!CryptAcquireContext(&ctx->prov, NULL, MS_ENH_RSA_AES_PROV,
-				 PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) {
-		cryptoapi_report_error("CryptAcquireContext");
-		goto fail1;
-	}
-
-	if (!CryptImportKey(ctx->prov, (BYTE *) &key_blob,
-			    sizeof(key_blob), 0, 0, &ctx->key)) {
- 		cryptoapi_report_error("CryptImportKey");
-		goto fail2;
-	}
-
-	if (!CryptSetKeyParam(ctx->key, KP_MODE, (BYTE *) &mode, 0)) {
- 		cryptoapi_report_error("CryptSetKeyParam(KP_MODE)");
-		goto fail3;
-	}
-
-	if (iv && !CryptSetKeyParam(ctx->key, KP_IV, (BYTE *) iv, 0)) {
- 		cryptoapi_report_error("CryptSetKeyParam(KP_IV)");
-		goto fail3;
-	}
-
-	return ctx;
-
-fail3:
-	CryptDestroyKey(ctx->key);
-fail2:
-	CryptReleaseContext(ctx->prov, 0);
-fail1:
-	os_free(ctx);
-	return NULL;
-}
-
-
-int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
-			  u8 *crypt, size_t len)
-{
-	DWORD dlen;
-
-	os_memcpy(crypt, plain, len);
-	dlen = len;
-	if (!CryptEncrypt(ctx->key, 0, FALSE, 0, crypt, &dlen, len)) {
- 		cryptoapi_report_error("CryptEncrypt");
-		os_memset(crypt, 0, len);
-		return -1;
-	}
-
-	return 0;
-}
-
-
-int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
-			  u8 *plain, size_t len)
-{
-	DWORD dlen;
-
-	os_memcpy(plain, crypt, len);
-	dlen = len;
-	if (!CryptDecrypt(ctx->key, 0, FALSE, 0, plain, &dlen)) {
- 		cryptoapi_report_error("CryptDecrypt");
-		return -1;
-	}
-
-	return 0;
-}
-
-
-void crypto_cipher_deinit(struct crypto_cipher *ctx)
-{
-	CryptDestroyKey(ctx->key);
-	CryptReleaseContext(ctx->prov, 0);
-	os_free(ctx);
-}
-
-
-struct crypto_public_key {
-	HCRYPTPROV prov;
-	HCRYPTKEY rsa;
-};
-
-struct crypto_private_key {
-	HCRYPTPROV prov;
-	HCRYPTKEY rsa;
-};
-
-
-struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len)
-{
-	/* Use crypto_public_key_from_cert() instead. */
-	return NULL;
-}
-
-
-struct crypto_private_key * crypto_private_key_import(const u8 *key,
-						      size_t len,
-						      const char *passwd)
-{
-	/* TODO */
-	return NULL;
-}
-
-
-struct crypto_public_key * crypto_public_key_from_cert(const u8 *buf,
-						       size_t len)
-{
-	struct crypto_public_key *pk;
-	PCCERT_CONTEXT cc;
-
-	pk = os_zalloc(sizeof(*pk));
-	if (pk == NULL)
-		return NULL;
-
-	cc = CertCreateCertificateContext(X509_ASN_ENCODING |
-					  PKCS_7_ASN_ENCODING, buf, len);
-	if (!cc) {
- 		cryptoapi_report_error("CryptCreateCertificateContext");
-		os_free(pk);
-		return NULL;
-	}
-
-	if (!CryptAcquireContext(&pk->prov, NULL, MS_DEF_PROV, PROV_RSA_FULL,
-				 0)) {
- 		cryptoapi_report_error("CryptAcquireContext");
-		os_free(pk);
-		CertFreeCertificateContext(cc);
-		return NULL;
-	}
-
-	if (!CryptImportPublicKeyInfo(pk->prov, X509_ASN_ENCODING |
-				      PKCS_7_ASN_ENCODING,
-				      &cc->pCertInfo->SubjectPublicKeyInfo,
-				      &pk->rsa)) {
- 		cryptoapi_report_error("CryptImportPublicKeyInfo");
-		CryptReleaseContext(pk->prov, 0);
-		os_free(pk);
-		CertFreeCertificateContext(cc);
-		return NULL;
-	}
-
-	CertFreeCertificateContext(cc);
-
-	return pk;
-}
-
-
-int crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key *key,
-					const u8 *in, size_t inlen,
-					u8 *out, size_t *outlen)
-{
-	DWORD clen;
-	u8 *tmp;
-	size_t i;
-
-	if (*outlen < inlen)
-		return -1;
-	tmp = malloc(*outlen);
-	if (tmp == NULL)
-		return -1;
-
-	os_memcpy(tmp, in, inlen);
-	clen = inlen;
-	if (!CryptEncrypt(key->rsa, 0, TRUE, 0, tmp, &clen, *outlen)) {
-		wpa_printf(MSG_DEBUG, "CryptoAPI: Failed to encrypt using "
-			   "public key: %d", (int) GetLastError());
-		os_free(tmp);
-		return -1;
-	}
-
-	*outlen = clen;
-
-	/* Reverse the output */
-	for (i = 0; i < *outlen; i++)
-		out[i] = tmp[*outlen - 1 - i];
-
-	os_free(tmp);
-
-	return 0;
-}
-
-
-int crypto_private_key_sign_pkcs1(struct crypto_private_key *key,
-				  const u8 *in, size_t inlen,
-				  u8 *out, size_t *outlen)
-{
-	/* TODO */
-	return -1;
-}
-
-
-void crypto_public_key_free(struct crypto_public_key *key)
-{
-	if (key) {
-		CryptDestroyKey(key->rsa);
-		CryptReleaseContext(key->prov, 0);
-		os_free(key);
-	}
-}
-
-
-void crypto_private_key_free(struct crypto_private_key *key)
-{
-	if (key) {
-		CryptDestroyKey(key->rsa);
-		CryptReleaseContext(key->prov, 0);
-		os_free(key);
-	}
-}
-
-
-int crypto_global_init(void)
-{
-	return mingw_load_crypto_func();
-}
-
-
-void crypto_global_deinit(void)
-{
-}
-
-
-int crypto_mod_exp(const u8 *base, size_t base_len,
-		   const u8 *power, size_t power_len,
-		   const u8 *modulus, size_t modulus_len,
-		   u8 *result, size_t *result_len)
-{
-	/* TODO */
-	return -1;
-}
diff --git a/src/crypto/tls_schannel.c b/src/crypto/tls_schannel.c
deleted file mode 100644
index 31a2c94..0000000
--- a/src/crypto/tls_schannel.c
+++ /dev/null
@@ -1,763 +0,0 @@
-/*
- * SSL/TLS interface functions for Microsoft Schannel
- * Copyright (c) 2005-2009, Jouni Malinen <j@w1.fi>
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-/*
- * FIX: Go through all SSPI functions and verify what needs to be freed
- * FIX: session resumption
- * TODO: add support for server cert chain validation
- * TODO: add support for CA cert validation
- * TODO: add support for EAP-TLS (client cert/key conf)
- */
-
-#include "includes.h"
-#include <windows.h>
-#include <wincrypt.h>
-#include <schannel.h>
-#define SECURITY_WIN32
-#include <security.h>
-#include <sspi.h>
-
-#include "common.h"
-#include "tls.h"
-
-
-struct tls_global {
-	HMODULE hsecurity;
-	PSecurityFunctionTable sspi;
-	HCERTSTORE my_cert_store;
-};
-
-struct tls_connection {
-	int established, start;
-	int failed, read_alerts, write_alerts;
-
-	SCHANNEL_CRED schannel_cred;
-	CredHandle creds;
-	CtxtHandle context;
-
-	u8 eap_tls_prf[128];
-	int eap_tls_prf_set;
-};
-
-
-static int schannel_load_lib(struct tls_global *global)
-{
-	INIT_SECURITY_INTERFACE pInitSecurityInterface;
-
-	global->hsecurity = LoadLibrary(TEXT("Secur32.dll"));
-	if (global->hsecurity == NULL) {
-		wpa_printf(MSG_ERROR, "%s: Could not load Secur32.dll - 0x%x",
-			   __func__, (unsigned int) GetLastError());
-		return -1;
-	}
-
-	pInitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress(
-		global->hsecurity, "InitSecurityInterfaceA");
-	if (pInitSecurityInterface == NULL) {
-		wpa_printf(MSG_ERROR, "%s: Could not find "
-			   "InitSecurityInterfaceA from Secur32.dll",
-			   __func__);
-		FreeLibrary(global->hsecurity);
-		global->hsecurity = NULL;
-		return -1;
-	}
-
-	global->sspi = pInitSecurityInterface();
-	if (global->sspi == NULL) {
-		wpa_printf(MSG_ERROR, "%s: Could not read security "
-			   "interface - 0x%x",
-			   __func__, (unsigned int) GetLastError());
-		FreeLibrary(global->hsecurity);
-		global->hsecurity = NULL;
-		return -1;
-	}
-
-	return 0;
-}
-
-
-void * tls_init(const struct tls_config *conf)
-{
-	struct tls_global *global;
-
-	global = os_zalloc(sizeof(*global));
-	if (global == NULL)
-		return NULL;
-	if (schannel_load_lib(global)) {
-		os_free(global);
-		return NULL;
-	}
-	return global;
-}
-
-
-void tls_deinit(void *ssl_ctx)
-{
-	struct tls_global *global = ssl_ctx;
-
-	if (global->my_cert_store)
-		CertCloseStore(global->my_cert_store, 0);
-	FreeLibrary(global->hsecurity);
-	os_free(global);
-}
-
-
-int tls_get_errors(void *ssl_ctx)
-{
-	return 0;
-}
-
-
-struct tls_connection * tls_connection_init(void *ssl_ctx)
-{
-	struct tls_connection *conn;
-
-	conn = os_zalloc(sizeof(*conn));
-	if (conn == NULL)
-		return NULL;
-	conn->start = 1;
-
-	return conn;
-}
-
-
-void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn)
-{
-	if (conn == NULL)
-		return;
-
-	os_free(conn);
-}
-
-
-int tls_connection_established(void *ssl_ctx, struct tls_connection *conn)
-{
-	return conn ? conn->established : 0;
-}
-
-
-int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn)
-{
-	struct tls_global *global = ssl_ctx;
-	if (conn == NULL)
-		return -1;
-
-	conn->eap_tls_prf_set = 0;
-	conn->established = conn->failed = 0;
-	conn->read_alerts = conn->write_alerts = 0;
-	global->sspi->DeleteSecurityContext(&conn->context);
-	/* FIX: what else needs to be reseted? */
-
-	return 0;
-}
-
-
-int tls_global_set_params(void *tls_ctx,
-			  const struct tls_connection_params *params)
-{
-	return -1;
-}
-
-
-int tls_global_set_verify(void *ssl_ctx, int check_crl)
-{
-	return -1;
-}
-
-
-int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn,
-			      int verify_peer)
-{
-	return -1;
-}
-
-
-int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn,
-			    struct tls_keys *keys)
-{
-	/* Schannel does not export master secret or client/server random. */
-	return -1;
-}
-
-
-int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
-		       const char *label, int server_random_first,
-		       u8 *out, size_t out_len)
-{
-	/*
-	 * Cannot get master_key from Schannel, but EapKeyBlock can be used to
-	 * generate session keys for EAP-TLS and EAP-PEAPv0. EAP-PEAPv2 and
-	 * EAP-TTLS cannot use this, though, since they are using different
-	 * labels. The only option could be to implement TLSv1 completely here
-	 * and just use Schannel or CryptoAPI for low-level crypto
-	 * functionality..
-	 */
-
-	if (conn == NULL || !conn->eap_tls_prf_set || server_random_first ||
-	    os_strcmp(label, "client EAP encryption") != 0 ||
-	    out_len > sizeof(conn->eap_tls_prf))
-		return -1;
-
-	os_memcpy(out, conn->eap_tls_prf, out_len);
-
-	return 0;
-}
-
-
-static struct wpabuf * tls_conn_hs_clienthello(struct tls_global *global,
-					       struct tls_connection *conn)
-{
-	DWORD sspi_flags, sspi_flags_out;
-	SecBufferDesc outbuf;
-	SecBuffer outbufs[1];
-	SECURITY_STATUS status;
-	TimeStamp ts_expiry;
-
-	sspi_flags = ISC_REQ_REPLAY_DETECT |
-		ISC_REQ_CONFIDENTIALITY |
-		ISC_RET_EXTENDED_ERROR |
-		ISC_REQ_ALLOCATE_MEMORY |
-		ISC_REQ_MANUAL_CRED_VALIDATION;
-
-	wpa_printf(MSG_DEBUG, "%s: Generating ClientHello", __func__);
-
-	outbufs[0].pvBuffer = NULL;
-	outbufs[0].BufferType = SECBUFFER_TOKEN;
-	outbufs[0].cbBuffer = 0;
-
-	outbuf.cBuffers = 1;
-	outbuf.pBuffers = outbufs;
-	outbuf.ulVersion = SECBUFFER_VERSION;
-
-#ifdef UNICODE
-	status = global->sspi->InitializeSecurityContextW(
-		&conn->creds, NULL, NULL /* server name */, sspi_flags, 0,
-		SECURITY_NATIVE_DREP, NULL, 0, &conn->context,
-		&outbuf, &sspi_flags_out, &ts_expiry);
-#else /* UNICODE */
-	status = global->sspi->InitializeSecurityContextA(
-		&conn->creds, NULL, NULL /* server name */, sspi_flags, 0,
-		SECURITY_NATIVE_DREP, NULL, 0, &conn->context,
-		&outbuf, &sspi_flags_out, &ts_expiry);
-#endif /* UNICODE */
-	if (status != SEC_I_CONTINUE_NEEDED) {
-		wpa_printf(MSG_ERROR, "%s: InitializeSecurityContextA "
-			   "failed - 0x%x",
-			   __func__, (unsigned int) status);
-		return NULL;
-	}
-
-	if (outbufs[0].cbBuffer != 0 && outbufs[0].pvBuffer) {
-		struct wpabuf *buf;
-		wpa_hexdump(MSG_MSGDUMP, "SChannel - ClientHello",
-			    outbufs[0].pvBuffer, outbufs[0].cbBuffer);
-		conn->start = 0;
-		buf = wpabuf_alloc_copy(outbufs[0].pvBuffer,
-					outbufs[0].cbBuffer);
-		if (buf == NULL)
-			return NULL;
-		global->sspi->FreeContextBuffer(outbufs[0].pvBuffer);
-		return buf;
-	}
-
-	wpa_printf(MSG_ERROR, "SChannel: Failed to generate ClientHello");
-
-	return NULL;
-}
-
-
-#ifndef SECPKG_ATTR_EAP_KEY_BLOCK
-#define SECPKG_ATTR_EAP_KEY_BLOCK 0x5b
-
-typedef struct _SecPkgContext_EapKeyBlock {
-	BYTE rgbKeys[128];
-	BYTE rgbIVs[64];
-} SecPkgContext_EapKeyBlock, *PSecPkgContext_EapKeyBlock;
-#endif /* !SECPKG_ATTR_EAP_KEY_BLOCK */
-
-static int tls_get_eap(struct tls_global *global, struct tls_connection *conn)
-{
-	SECURITY_STATUS status;
-	SecPkgContext_EapKeyBlock kb;
-
-	/* Note: Windows NT and Windows Me/98/95 do not support getting
-	 * EapKeyBlock */
-
-	status = global->sspi->QueryContextAttributes(
-		&conn->context, SECPKG_ATTR_EAP_KEY_BLOCK, &kb);
-	if (status != SEC_E_OK) {
-		wpa_printf(MSG_DEBUG, "%s: QueryContextAttributes("
-			   "SECPKG_ATTR_EAP_KEY_BLOCK) failed (%d)",
-			   __func__, (int) status);
-		return -1;
-	}
-
-	wpa_hexdump_key(MSG_MSGDUMP, "Schannel - EapKeyBlock - rgbKeys",
-			kb.rgbKeys, sizeof(kb.rgbKeys));
-	wpa_hexdump_key(MSG_MSGDUMP, "Schannel - EapKeyBlock - rgbIVs",
-			kb.rgbIVs, sizeof(kb.rgbIVs));
-
-	os_memcpy(conn->eap_tls_prf, kb.rgbKeys, sizeof(kb.rgbKeys));
-	conn->eap_tls_prf_set = 1;
-	return 0;
-}
-
-
-struct wpabuf * tls_connection_handshake(void *tls_ctx,
-					 struct tls_connection *conn,
-					 const struct wpabuf *in_data,
-					 struct wpabuf **appl_data)
-{
-	struct tls_global *global = tls_ctx;
-	DWORD sspi_flags, sspi_flags_out;
-	SecBufferDesc inbuf, outbuf;
-	SecBuffer inbufs[2], outbufs[1];
-	SECURITY_STATUS status;
-	TimeStamp ts_expiry;
-	struct wpabuf *out_buf = NULL;
-
-	if (appl_data)
-		*appl_data = NULL;
-
-	if (conn->start)
-		return tls_conn_hs_clienthello(global, conn);
-
-	wpa_printf(MSG_DEBUG, "SChannel: %d bytes handshake data to process",
-		   (int) wpabuf_len(in_data));
-
-	sspi_flags = ISC_REQ_REPLAY_DETECT |
-		ISC_REQ_CONFIDENTIALITY |
-		ISC_RET_EXTENDED_ERROR |
-		ISC_REQ_ALLOCATE_MEMORY |
-		ISC_REQ_MANUAL_CRED_VALIDATION;
-
-	/* Input buffer for Schannel */
-	inbufs[0].pvBuffer = (u8 *) wpabuf_head(in_data);
-	inbufs[0].cbBuffer = wpabuf_len(in_data);
-	inbufs[0].BufferType = SECBUFFER_TOKEN;
-
-	/* Place for leftover data from Schannel */
-	inbufs[1].pvBuffer = NULL;
-	inbufs[1].cbBuffer = 0;
-	inbufs[1].BufferType = SECBUFFER_EMPTY;
-
-	inbuf.cBuffers = 2;
-	inbuf.pBuffers = inbufs;
-	inbuf.ulVersion = SECBUFFER_VERSION;
-
-	/* Output buffer for Schannel */
-	outbufs[0].pvBuffer = NULL;
-	outbufs[0].cbBuffer = 0;
-	outbufs[0].BufferType = SECBUFFER_TOKEN;
-
-	outbuf.cBuffers = 1;
-	outbuf.pBuffers = outbufs;
-	outbuf.ulVersion = SECBUFFER_VERSION;
-
-#ifdef UNICODE
-	status = global->sspi->InitializeSecurityContextW(
-		&conn->creds, &conn->context, NULL, sspi_flags, 0,
-		SECURITY_NATIVE_DREP, &inbuf, 0, NULL,
-		&outbuf, &sspi_flags_out, &ts_expiry);
-#else /* UNICODE */
-	status = global->sspi->InitializeSecurityContextA(
-		&conn->creds, &conn->context, NULL, sspi_flags, 0,
-		SECURITY_NATIVE_DREP, &inbuf, 0, NULL,
-		&outbuf, &sspi_flags_out, &ts_expiry);
-#endif /* UNICODE */
-
-	wpa_printf(MSG_MSGDUMP, "Schannel: InitializeSecurityContext -> "
-		   "status=%d inlen[0]=%d intype[0]=%d inlen[1]=%d "
-		   "intype[1]=%d outlen[0]=%d",
-		   (int) status, (int) inbufs[0].cbBuffer,
-		   (int) inbufs[0].BufferType, (int) inbufs[1].cbBuffer,
-		   (int) inbufs[1].BufferType,
-		   (int) outbufs[0].cbBuffer);
-	if (status == SEC_E_OK || status == SEC_I_CONTINUE_NEEDED ||
-	    (FAILED(status) && (sspi_flags_out & ISC_RET_EXTENDED_ERROR))) {
-		if (outbufs[0].cbBuffer != 0 && outbufs[0].pvBuffer) {
-			wpa_hexdump(MSG_MSGDUMP, "SChannel - output",
-				    outbufs[0].pvBuffer, outbufs[0].cbBuffer);
-			out_buf = wpabuf_alloc_copy(outbufs[0].pvBuffer,
-						    outbufs[0].cbBuffer);
-			global->sspi->FreeContextBuffer(outbufs[0].pvBuffer);
-			outbufs[0].pvBuffer = NULL;
-			if (out_buf == NULL)
-				return NULL;
-		}
-	}
-
-	switch (status) {
-	case SEC_E_INCOMPLETE_MESSAGE:
-		wpa_printf(MSG_DEBUG, "Schannel: SEC_E_INCOMPLETE_MESSAGE");
-		break;
-	case SEC_I_CONTINUE_NEEDED:
-		wpa_printf(MSG_DEBUG, "Schannel: SEC_I_CONTINUE_NEEDED");
-		break;
-	case SEC_E_OK:
-		/* TODO: verify server certificate chain */
-		wpa_printf(MSG_DEBUG, "Schannel: SEC_E_OK - Handshake "
-			   "completed successfully");
-		conn->established = 1;
-		tls_get_eap(global, conn);
-
-		/* Need to return something to get final TLS ACK. */
-		if (out_buf == NULL)
-			out_buf = wpabuf_alloc(0);
-
-		if (inbufs[1].BufferType == SECBUFFER_EXTRA) {
-			wpa_hexdump(MSG_MSGDUMP, "SChannel - Encrypted "
-				    "application data",
-				    inbufs[1].pvBuffer, inbufs[1].cbBuffer);
-			if (appl_data) {
-				*appl_data = wpabuf_alloc_copy(
-					outbufs[1].pvBuffer,
-					outbufs[1].cbBuffer);
-			}
-			global->sspi->FreeContextBuffer(inbufs[1].pvBuffer);
-			inbufs[1].pvBuffer = NULL;
-		}
-		break;
-	case SEC_I_INCOMPLETE_CREDENTIALS:
-		wpa_printf(MSG_DEBUG,
-			   "Schannel: SEC_I_INCOMPLETE_CREDENTIALS");
-		break;
-	case SEC_E_WRONG_PRINCIPAL:
-		wpa_printf(MSG_DEBUG, "Schannel: SEC_E_WRONG_PRINCIPAL");
-		break;
-	case SEC_E_INTERNAL_ERROR:
-		wpa_printf(MSG_DEBUG, "Schannel: SEC_E_INTERNAL_ERROR");
-		break;
-	}
-
-	if (FAILED(status)) {
-		wpa_printf(MSG_DEBUG, "Schannel: Handshake failed "
-			   "(out_buf=%p)", out_buf);
-		conn->failed++;
-		global->sspi->DeleteSecurityContext(&conn->context);
-		return out_buf;
-	}
-
-	if (inbufs[1].BufferType == SECBUFFER_EXTRA) {
-		/* TODO: Can this happen? What to do with this data? */
-		wpa_hexdump(MSG_MSGDUMP, "SChannel - Leftover data",
-			    inbufs[1].pvBuffer, inbufs[1].cbBuffer);
-		global->sspi->FreeContextBuffer(inbufs[1].pvBuffer);
-		inbufs[1].pvBuffer = NULL;
-	}
-
-	return out_buf;
-}
-
-
-struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
-						struct tls_connection *conn,
-						const struct wpabuf *in_data,
-						struct wpabuf **appl_data)
-{
-	return NULL;
-}
-
-
-struct wpabuf * tls_connection_encrypt(void *tls_ctx,
-				       struct tls_connection *conn,
-				       const struct wpabuf *in_data)
-{
-	struct tls_global *global = tls_ctx;
-	SECURITY_STATUS status;
-	SecBufferDesc buf;
-	SecBuffer bufs[4];
-	SecPkgContext_StreamSizes sizes;
-	int i;
-	struct wpabuf *out;
-
-	status = global->sspi->QueryContextAttributes(&conn->context,
-						      SECPKG_ATTR_STREAM_SIZES,
-						      &sizes);
-	if (status != SEC_E_OK) {
-		wpa_printf(MSG_DEBUG, "%s: QueryContextAttributes failed",
-			   __func__);
-		return NULL;
-	}
-	wpa_printf(MSG_DEBUG, "%s: Stream sizes: header=%u trailer=%u",
-		   __func__,
-		   (unsigned int) sizes.cbHeader,
-		   (unsigned int) sizes.cbTrailer);
-
-	out = wpabuf_alloc(sizes.cbHeader + wpabuf_len(in_data) +
-			   sizes.cbTrailer);
-
-	os_memset(&bufs, 0, sizeof(bufs));
-	bufs[0].pvBuffer = wpabuf_put(out, sizes.cbHeader);
-	bufs[0].cbBuffer = sizes.cbHeader;
-	bufs[0].BufferType = SECBUFFER_STREAM_HEADER;
-
-	bufs[1].pvBuffer = wpabuf_put(out, 0);
-	wpabuf_put_buf(out, in_data);
-	bufs[1].cbBuffer = wpabuf_len(in_data);
-	bufs[1].BufferType = SECBUFFER_DATA;
-
-	bufs[2].pvBuffer = wpabuf_put(out, sizes.cbTrailer);
-	bufs[2].cbBuffer = sizes.cbTrailer;
-	bufs[2].BufferType = SECBUFFER_STREAM_TRAILER;
-
-	buf.ulVersion = SECBUFFER_VERSION;
-	buf.cBuffers = 3;
-	buf.pBuffers = bufs;
-
-	status = global->sspi->EncryptMessage(&conn->context, 0, &buf, 0);
-
-	wpa_printf(MSG_MSGDUMP, "Schannel: EncryptMessage -> "
-		   "status=%d len[0]=%d type[0]=%d len[1]=%d type[1]=%d "
-		   "len[2]=%d type[2]=%d",
-		   (int) status,
-		   (int) bufs[0].cbBuffer, (int) bufs[0].BufferType,
-		   (int) bufs[1].cbBuffer, (int) bufs[1].BufferType,
-		   (int) bufs[2].cbBuffer, (int) bufs[2].BufferType);
-	wpa_printf(MSG_MSGDUMP, "Schannel: EncryptMessage pointers: "
-		   "out_data=%p bufs %p %p %p",
-		   wpabuf_head(out), bufs[0].pvBuffer, bufs[1].pvBuffer,
-		   bufs[2].pvBuffer);
-
-	for (i = 0; i < 3; i++) {
-		if (bufs[i].pvBuffer && bufs[i].BufferType != SECBUFFER_EMPTY)
-		{
-			wpa_hexdump(MSG_MSGDUMP, "SChannel: bufs",
-				    bufs[i].pvBuffer, bufs[i].cbBuffer);
-		}
-	}
-
-	if (status == SEC_E_OK) {
-		wpa_printf(MSG_DEBUG, "%s: SEC_E_OK", __func__);
-		wpa_hexdump_buf_key(MSG_MSGDUMP, "Schannel: Encrypted data "
-				    "from EncryptMessage", out);
-		return out;
-	}
-
-	wpa_printf(MSG_DEBUG, "%s: Failed - status=%d",
-		   __func__, (int) status);
-	wpabuf_free(out);
-	return NULL;
-}
-
-
-struct wpabuf * tls_connection_decrypt(void *tls_ctx,
-				       struct tls_connection *conn,
-				       const struct wpabuf *in_data)
-{
-	struct tls_global *global = tls_ctx;
-	SECURITY_STATUS status;
-	SecBufferDesc buf;
-	SecBuffer bufs[4];
-	int i;
-	struct wpabuf *out, *tmp;
-
-	wpa_hexdump_buf(MSG_MSGDUMP,
-			"Schannel: Encrypted data to DecryptMessage", in_data);
-	os_memset(&bufs, 0, sizeof(bufs));
-	tmp = wpabuf_dup(in_data);
-	if (tmp == NULL)
-		return NULL;
-	bufs[0].pvBuffer = wpabuf_mhead(tmp);
-	bufs[0].cbBuffer = wpabuf_len(in_data);
-	bufs[0].BufferType = SECBUFFER_DATA;
-
-	bufs[1].BufferType = SECBUFFER_EMPTY;
-	bufs[2].BufferType = SECBUFFER_EMPTY;
-	bufs[3].BufferType = SECBUFFER_EMPTY;
-
-	buf.ulVersion = SECBUFFER_VERSION;
-	buf.cBuffers = 4;
-	buf.pBuffers = bufs;
-
-	status = global->sspi->DecryptMessage(&conn->context, &buf, 0,
-						    NULL);
-	wpa_printf(MSG_MSGDUMP, "Schannel: DecryptMessage -> "
-		   "status=%d len[0]=%d type[0]=%d len[1]=%d type[1]=%d "
-		   "len[2]=%d type[2]=%d len[3]=%d type[3]=%d",
-		   (int) status,
-		   (int) bufs[0].cbBuffer, (int) bufs[0].BufferType,
-		   (int) bufs[1].cbBuffer, (int) bufs[1].BufferType,
-		   (int) bufs[2].cbBuffer, (int) bufs[2].BufferType,
-		   (int) bufs[3].cbBuffer, (int) bufs[3].BufferType);
-	wpa_printf(MSG_MSGDUMP, "Schannel: DecryptMessage pointers: "
-		   "out_data=%p bufs %p %p %p %p",
-		   wpabuf_head(tmp), bufs[0].pvBuffer, bufs[1].pvBuffer,
-		   bufs[2].pvBuffer, bufs[3].pvBuffer);
-
-	switch (status) {
-	case SEC_E_INCOMPLETE_MESSAGE:
-		wpa_printf(MSG_DEBUG, "%s: SEC_E_INCOMPLETE_MESSAGE",
-			   __func__);
-		break;
-	case SEC_E_OK:
-		wpa_printf(MSG_DEBUG, "%s: SEC_E_OK", __func__);
-		for (i = 0; i < 4; i++) {
-			if (bufs[i].BufferType == SECBUFFER_DATA)
-				break;
-		}
-		if (i == 4) {
-			wpa_printf(MSG_DEBUG, "%s: No output data from "
-				   "DecryptMessage", __func__);
-			wpabuf_free(tmp);
-			return NULL;
-		}
-		wpa_hexdump_key(MSG_MSGDUMP, "Schannel: Decrypted data from "
-				"DecryptMessage",
-				bufs[i].pvBuffer, bufs[i].cbBuffer);
-		out = wpabuf_alloc_copy(bufs[i].pvBuffer, bufs[i].cbBuffer);
-		wpabuf_free(tmp);
-		return out;
-	}
-
-	wpa_printf(MSG_DEBUG, "%s: Failed - status=%d",
-		   __func__, (int) status);
-	wpabuf_free(tmp);
-	return NULL;
-}
-
-
-int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn)
-{
-	return 0;
-}
-
-
-int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
-				   u8 *ciphers)
-{
-	return -1;
-}
-
-
-int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn,
-		   char *buf, size_t buflen)
-{
-	return -1;
-}
-
-
-int tls_connection_enable_workaround(void *ssl_ctx,
-				     struct tls_connection *conn)
-{
-	return 0;
-}
-
-
-int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn,
-				    int ext_type, const u8 *data,
-				    size_t data_len)
-{
-	return -1;
-}
-
-
-int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn)
-{
-	if (conn == NULL)
-		return -1;
-	return conn->failed;
-}
-
-
-int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn)
-{
-	if (conn == NULL)
-		return -1;
-	return conn->read_alerts;
-}
-
-
-int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn)
-{
-	if (conn == NULL)
-		return -1;
-	return conn->write_alerts;
-}
-
-
-int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
-			      const struct tls_connection_params *params)
-{
-	struct tls_global *global = tls_ctx;
-	ALG_ID algs[1];
-	SECURITY_STATUS status;
-	TimeStamp ts_expiry;
-
-	if (conn == NULL)
-		return -1;
-
-	if (params->subject_match) {
-		wpa_printf(MSG_INFO, "TLS: subject_match not supported");
-		return -1;
-	}
-
-	if (params->altsubject_match) {
-		wpa_printf(MSG_INFO, "TLS: altsubject_match not supported");
-		return -1;
-	}
-
-	if (params->suffix_match) {
-		wpa_printf(MSG_INFO, "TLS: suffix_match not supported");
-		return -1;
-	}
-
-	if (params->domain_match) {
-		wpa_printf(MSG_INFO, "TLS: domain_match not supported");
-		return -1;
-	}
-
-	if (params->openssl_ciphers) {
-		wpa_printf(MSG_INFO, "GnuTLS: openssl_ciphers not supported");
-		return -1;
-	}
-
-	if (global->my_cert_store == NULL &&
-	    (global->my_cert_store = CertOpenSystemStore(0, TEXT("MY"))) ==
-	    NULL) {
-		wpa_printf(MSG_ERROR, "%s: CertOpenSystemStore failed - 0x%x",
-			   __func__, (unsigned int) GetLastError());
-		return -1;
-	}
-
-	os_memset(&conn->schannel_cred, 0, sizeof(conn->schannel_cred));
-	conn->schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
-	conn->schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1;
-	algs[0] = CALG_RSA_KEYX;
-	conn->schannel_cred.cSupportedAlgs = 1;
-	conn->schannel_cred.palgSupportedAlgs = algs;
-	conn->schannel_cred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS;
-#ifdef UNICODE
-	status = global->sspi->AcquireCredentialsHandleW(
-		NULL, UNISP_NAME_W, SECPKG_CRED_OUTBOUND, NULL,
-		&conn->schannel_cred, NULL, NULL, &conn->creds, &ts_expiry);
-#else /* UNICODE */
-	status = global->sspi->AcquireCredentialsHandleA(
-		NULL, UNISP_NAME_A, SECPKG_CRED_OUTBOUND, NULL,
-		&conn->schannel_cred, NULL, NULL, &conn->creds, &ts_expiry);
-#endif /* UNICODE */
-	if (status != SEC_E_OK) {
-		wpa_printf(MSG_DEBUG, "%s: AcquireCredentialsHandleA failed - "
-			   "0x%x", __func__, (unsigned int) status);
-		return -1;
-	}
-
-	return 0;
-}
-
-
-unsigned int tls_capabilities(void *tls_ctx)
-{
-	return 0;
-}
-
-
-int tls_get_library_version(char *buf, size_t buf_len)
-{
-	return os_snprintf(buf, buf_len, "schannel");
-}
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 4074b87..6a9cd74 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -1588,6 +1588,16 @@
 
 	/* Indicates whether HT40 is enabled */
 	int ht40_enabled;
+
+	/* Indicates whether VHT is enabled */
+	int vht_enabled;
+
+	/* Configured ACS channel width */
+	u16 ch_width;
+
+	/* ACS channel list info */
+	unsigned int ch_list_len;
+	const u8 *ch_list;
 };
 
 
@@ -2657,18 +2667,6 @@
 			  int encrypt);
 
 	/**
-	 * shared_freq - Get operating frequency of shared interface(s)
-	 * @priv: Private driver interface data
-	 * Returns: Operating frequency in MHz, 0 if no shared operation in
-	 * use, or -1 on failure
-	 *
-	 * This command can be used to request the current operating frequency
-	 * of any virtual interface that shares the same radio to provide
-	 * information for channel selection for other virtual interfaces.
-	 */
-	int (*shared_freq)(void *priv);
-
-	/**
 	 * get_noa - Get current Notice of Absence attribute payload
 	 * @priv: Private driver interface data
 	 * @buf: Buffer for returning NoA
@@ -4558,10 +4556,18 @@
 	 * struct acs_selected_channels - Data for EVENT_ACS_CHANNEL_SELECTED
 	 * @pri_channel: Selected primary channel
 	 * @sec_channel: Selected secondary channel
+	 * @vht_seg0_center_ch: VHT mode Segment0 center channel
+	 * @vht_seg1_center_ch: VHT mode Segment1 center channel
+	 * @ch_width: Selected Channel width by driver. Driver may choose to
+	 *	change hostapd configured ACS channel width due driver internal
+	 *	channel restrictions.
 	 */
 	struct acs_selected_channels {
 		u8 pri_channel;
 		u8 sec_channel;
+		u8 vht_seg0_center_ch;
+		u8 vht_seg1_center_ch;
+		u16 ch_width;
 	} acs_selected_channels;
 };
 
diff --git a/src/drivers/driver_atheros.c b/src/drivers/driver_atheros.c
index f464421..b8e7864 100644
--- a/src/drivers/driver_atheros.c
+++ b/src/drivers/driver_atheros.c
@@ -1694,6 +1694,13 @@
 	struct atheros_driver_data *drv = priv;
 
 	atheros_reset_appfilter(drv);
+
+	if (drv->wpa_ie || drv->wps_beacon_ie || drv->wps_probe_resp_ie) {
+		wpabuf_free(drv->wpa_ie);
+		wpabuf_free(drv->wps_beacon_ie);
+		wpabuf_free(drv->wps_probe_resp_ie);
+		atheros_set_opt_ie(priv, NULL, 0);
+	}
 	netlink_deinit(drv->netlink);
 	(void) linux_set_iface_flags(drv->ioctl_sock, drv->iface, 0);
 	if (drv->ioctl_sock >= 0)
@@ -1704,9 +1711,6 @@
 		l2_packet_deinit(drv->sock_xmit);
 	if (drv->sock_raw)
 		l2_packet_deinit(drv->sock_raw);
-	wpabuf_free(drv->wpa_ie);
-	wpabuf_free(drv->wps_beacon_ie);
-	wpabuf_free(drv->wps_probe_resp_ie);
 	free(drv);
 }
 
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index aaff9ab..7b3dc51 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -6522,47 +6522,6 @@
 }
 
 
-static int wpa_driver_nl80211_shared_freq(void *priv)
-{
-	struct i802_bss *bss = priv;
-	struct wpa_driver_nl80211_data *drv = bss->drv;
-	struct wpa_driver_nl80211_data *driver;
-	int freq = 0;
-
-	/*
-	 * If the same PHY is in connected state with some other interface,
-	 * then retrieve the assoc freq.
-	 */
-	wpa_printf(MSG_DEBUG, "nl80211: Get shared freq for PHY %s",
-		   drv->phyname);
-
-	dl_list_for_each(driver, &drv->global->interfaces,
-			 struct wpa_driver_nl80211_data, list) {
-		if (drv == driver ||
-		    os_strcmp(drv->phyname, driver->phyname) != 0 ||
-		    !driver->associated)
-			continue;
-
-		wpa_printf(MSG_DEBUG, "nl80211: Found a match for PHY %s - %s "
-			   MACSTR,
-			   driver->phyname, driver->first_bss->ifname,
-			   MAC2STR(driver->first_bss->addr));
-		if (is_ap_interface(driver->nlmode))
-			freq = driver->first_bss->freq;
-		else
-			freq = nl80211_get_assoc_freq(driver);
-		wpa_printf(MSG_DEBUG, "nl80211: Shared freq for PHY %s: %d",
-			   drv->phyname, freq);
-	}
-
-	if (!freq)
-		wpa_printf(MSG_DEBUG, "nl80211: No shared interface for "
-			   "PHY (%s) in associated state", drv->phyname);
-
-	return freq;
-}
-
-
 static int nl80211_send_frame(void *priv, const u8 *data, size_t data_len,
 			      int encrypt)
 {
@@ -8423,12 +8382,24 @@
 	    (params->ht_enabled &&
 	     nla_put_flag(msg, QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED)) ||
 	    (params->ht40_enabled &&
-	     nla_put_flag(msg, QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED))) {
+	     nla_put_flag(msg, QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED)) ||
+	    (params->vht_enabled &&
+	     nla_put_flag(msg, QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED)) ||
+	    nla_put_u16(msg, QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
+			params->ch_width) ||
+	    (params->ch_list_len &&
+	     nla_put(msg, QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST, params->ch_list_len,
+		     params->ch_list))) {
 		nlmsg_free(msg);
 		return -ENOBUFS;
 	}
 	nla_nest_end(msg, data);
 
+	wpa_printf(MSG_DEBUG,
+		   "nl80211: ACS Params: HW_MODE: %d HT: %d HT40: %d VHT: %d BW: %d CH_LIST_LEN: %u",
+		   params->hw_mode, params->ht_enabled, params->ht40_enabled,
+		   params->vht_enabled, params->ch_width, params->ch_list_len);
+
 	ret = send_and_recv_msgs(drv, msg, NULL, NULL);
 	if (ret) {
 		wpa_printf(MSG_DEBUG,
@@ -8498,7 +8469,6 @@
 	.signal_monitor = nl80211_signal_monitor,
 	.signal_poll = nl80211_signal_poll,
 	.send_frame = nl80211_send_frame,
-	.shared_freq = wpa_driver_nl80211_shared_freq,
 	.set_param = nl80211_set_param,
 	.get_radio_name = nl80211_get_radio_name,
 	.add_pmkid = nl80211_add_pmkid,
diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
index 802589a..64c4665 100644
--- a/src/drivers/driver_nl80211.h
+++ b/src/drivers/driver_nl80211.h
@@ -270,5 +270,6 @@
 int wpa_driver_nl80211_stop_sched_scan(void *priv);
 struct wpa_scan_results * wpa_driver_nl80211_get_scan_results(void *priv);
 void nl80211_dump_scan(struct wpa_driver_nl80211_data *drv);
+const u8 * nl80211_get_ie(const u8 *ies, size_t ies_len, u8 ie);
 
 #endif /* DRIVER_NL80211_H */
diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
index 13c446f..ba1e240 100644
--- a/src/drivers/driver_nl80211_capa.c
+++ b/src/drivers/driver_nl80211_capa.c
@@ -575,22 +575,25 @@
 				continue;
 			}
 			vinfo = nla_data(nl);
-			switch (vinfo->subcmd) {
-			case QCA_NL80211_VENDOR_SUBCMD_TEST:
-				drv->vendor_cmd_test_avail = 1;
-				break;
-			case QCA_NL80211_VENDOR_SUBCMD_ROAMING:
-				drv->roaming_vendor_cmd_avail = 1;
-				break;
-			case QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY:
-				drv->dfs_vendor_cmd_avail = 1;
-				break;
-			case QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES:
-				drv->get_features_vendor_cmd_avail = 1;
-				break;
-			case QCA_NL80211_VENDOR_SUBCMD_DO_ACS:
-				drv->capa.flags |= WPA_DRIVER_FLAGS_ACS_OFFLOAD;
-				break;
+			if (vinfo->vendor_id == OUI_QCA) {
+				switch (vinfo->subcmd) {
+				case QCA_NL80211_VENDOR_SUBCMD_TEST:
+					drv->vendor_cmd_test_avail = 1;
+					break;
+				case QCA_NL80211_VENDOR_SUBCMD_ROAMING:
+					drv->roaming_vendor_cmd_avail = 1;
+					break;
+				case QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY:
+					drv->dfs_vendor_cmd_avail = 1;
+					break;
+				case QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES:
+					drv->get_features_vendor_cmd_avail = 1;
+					break;
+				case QCA_NL80211_VENDOR_SUBCMD_DO_ACS:
+					drv->capa.flags |=
+						WPA_DRIVER_FLAGS_ACS_OFFLOAD;
+					break;
+				}
 			}
 
 			wpa_printf(MSG_DEBUG, "nl80211: Supported vendor command: vendor_id=0x%x subcmd=%u",
diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
index 87e412d..8cebfb2 100644
--- a/src/drivers/driver_nl80211_event.c
+++ b/src/drivers/driver_nl80211_event.c
@@ -271,6 +271,7 @@
 			       struct nlattr *ptk_kek)
 {
 	union wpa_event_data event;
+	const u8 *ssid;
 	u16 status_code;
 
 	if (drv->capa.flags & WPA_DRIVER_FLAGS_SME) {
@@ -331,6 +332,16 @@
 	if (req_ie) {
 		event.assoc_info.req_ies = nla_data(req_ie);
 		event.assoc_info.req_ies_len = nla_len(req_ie);
+
+		if (cmd == NL80211_CMD_ROAM) {
+			ssid = nl80211_get_ie(event.assoc_info.req_ies,
+					      event.assoc_info.req_ies_len,
+					      WLAN_EID_SSID);
+			if (ssid && ssid[1] > 0 && ssid[1] <= 32) {
+				drv->ssid_len = ssid[1];
+				os_memcpy(drv->ssid, ssid + 2, ssid[1]);
+			}
+		}
 	}
 	if (resp_ie) {
 		event.assoc_info.resp_ies = nla_data(resp_ie);
@@ -1500,6 +1511,25 @@
 		nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL]);
 	event.acs_selected_channels.sec_channel =
 		nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL]);
+	if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL])
+		event.acs_selected_channels.vht_seg0_center_ch =
+			nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL]);
+	if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL])
+		event.acs_selected_channels.vht_seg1_center_ch =
+			nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL]);
+	if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH])
+		event.acs_selected_channels.ch_width =
+			nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
+
+	wpa_printf(MSG_INFO,
+		   "nl80211: ACS Results: PCH: %d SCH: %d BW: %d VHT0: %d VHT1: %d",
+		   event.acs_selected_channels.pri_channel,
+		   event.acs_selected_channels.sec_channel,
+		   event.acs_selected_channels.ch_width,
+		   event.acs_selected_channels.vht_seg0_center_ch,
+		   event.acs_selected_channels.vht_seg1_center_ch);
+
+	/* Ignore ACS channel list check for backwards compatibility */
 
 	wpa_supplicant_event(drv->ctx, EVENT_ACS_CHANNEL_SELECTED, &event);
 }
diff --git a/src/drivers/driver_nl80211_scan.c b/src/drivers/driver_nl80211_scan.c
index 3911f48..9cd3162 100644
--- a/src/drivers/driver_nl80211_scan.c
+++ b/src/drivers/driver_nl80211_scan.c
@@ -433,7 +433,7 @@
 }
 
 
-static const u8 * nl80211_get_ie(const u8 *ies, size_t ies_len, u8 ie)
+const u8 * nl80211_get_ie(const u8 *ies, size_t ies_len, u8 ie)
 {
 	const u8 *end, *pos;
 
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index 6adb3dc..f584fae 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -2730,6 +2730,25 @@
 }
 
 
+void p2p_service_flush_asp(struct p2p_data *p2p)
+{
+	struct p2ps_advertisement *adv, *prev;
+
+	if (!p2p)
+		return;
+
+	adv = p2p->p2ps_adv_list;
+	while (adv) {
+		prev = adv;
+		adv = adv->next;
+		os_free(prev);
+	}
+
+	p2p->p2ps_adv_list = NULL;
+	p2p_dbg(p2p, "All ASP advertisements flushed");
+}
+
+
 int p2p_parse_dev_addr_in_p2p_ie(struct wpabuf *p2p_ie, u8 *dev_addr)
 {
 	struct p2p_message msg;
@@ -2878,8 +2897,6 @@
 
 void p2p_deinit(struct p2p_data *p2p)
 {
-	struct p2ps_advertisement *adv, *prev;
-
 #ifdef CONFIG_WIFI_DISPLAY
 	wpabuf_free(p2p->wfd_ie_beacon);
 	wpabuf_free(p2p->wfd_ie_probe_req);
@@ -2913,13 +2930,7 @@
 	os_free(p2p->after_scan_tx);
 	p2p_remove_wps_vendor_extensions(p2p);
 	os_free(p2p->no_go_freq.range);
-
-	adv = p2p->p2ps_adv_list;
-	while (adv) {
-		prev = adv;
-		adv = adv->next;
-		os_free(prev);
-	}
+	p2p_service_flush_asp(p2p);
 
 	os_free(p2p);
 }
diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h
index 2402db6..2e5c3dc 100644
--- a/src/p2p/p2p.h
+++ b/src/p2p/p2p.h
@@ -2242,6 +2242,7 @@
 			const char *adv_str, u8 svc_state,
 			u16 config_methods, const char *svc_info);
 int p2p_service_del_asp(struct p2p_data *p2p, u32 adv_id);
+void p2p_service_flush_asp(struct p2p_data *p2p);
 struct p2ps_advertisement * p2p_get_p2ps_adv_list(struct p2p_data *p2p);
 
 #endif /* P2P_H */
diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk
index 322104b..ee40d30 100644
--- a/wpa_supplicant/Android.mk
+++ b/wpa_supplicant/Android.mk
@@ -374,7 +374,7 @@
 ifdef CONFIG_EAP_UNAUTH_TLS
 # EAP-UNAUTH-TLS
 L_CFLAGS += -DEAP_UNAUTH_TLS
-ifndef CONFIG_EAP_UNAUTH_TLS
+ifndef CONFIG_EAP_TLS
 OBJS += src/eap_peer/eap_tls.c
 OBJS_h += src/eap_server/eap_server_tls.c
 TLS_FUNCS=y
@@ -995,21 +995,6 @@
 CONFIG_INTERNAL_DH_GROUP5=y
 endif
 
-ifeq ($(CONFIG_TLS), schannel)
-ifdef TLS_FUNCS
-OBJS += src/crypto/tls_schannel.c
-endif
-OBJS += src/crypto/crypto_cryptoapi.c
-OBJS_p += src/crypto/crypto_cryptoapi.c
-ifdef NEED_FIPS186_2_PRF
-OBJS += src/crypto/fips_prf_internal.c
-OBJS += src/crypto/sha1-internal.c
-endif
-CONFIG_INTERNAL_SHA256=y
-CONFIG_INTERNAL_RC4=y
-CONFIG_INTERNAL_DH_GROUP5=y
-endif
-
 ifeq ($(CONFIG_TLS), internal)
 ifndef CONFIG_CRYPTO
 CONFIG_CRYPTO=internal
diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile
index 976b984..d086eeb 100644
--- a/wpa_supplicant/Makefile
+++ b/wpa_supplicant/Makefile
@@ -379,7 +379,7 @@
 ifdef CONFIG_EAP_UNAUTH_TLS
 # EAP-UNAUTH-TLS
 CFLAGS += -DEAP_UNAUTH_TLS
-ifndef CONFIG_EAP_UNAUTH_TLS
+ifndef CONFIG_EAP_TLS
 OBJS += ../src/eap_peer/eap_tls.o
 OBJS_h += ../src/eap_server/eap_server_tls.o
 TLS_FUNCS=y
@@ -1013,21 +1013,6 @@
 CONFIG_INTERNAL_DH_GROUP5=y
 endif
 
-ifeq ($(CONFIG_TLS), schannel)
-ifdef TLS_FUNCS
-OBJS += ../src/crypto/tls_schannel.o
-endif
-OBJS += ../src/crypto/crypto_cryptoapi.o
-OBJS_p += ../src/crypto/crypto_cryptoapi.o
-ifdef NEED_FIPS186_2_PRF
-OBJS += ../src/crypto/fips_prf_internal.o
-SHA1OBJS += ../src/crypto/sha1-internal.o
-endif
-CONFIG_INTERNAL_SHA256=y
-CONFIG_INTERNAL_RC4=y
-CONFIG_INTERNAL_DH_GROUP5=y
-endif
-
 ifeq ($(CONFIG_TLS), internal)
 ifndef CONFIG_CRYPTO
 CONFIG_CRYPTO=internal
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index 4ebc3a1..53d2d01 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -5299,6 +5299,11 @@
 {
 	u32 adv_id;
 
+	if (os_strcmp(cmd, "all") == 0) {
+		wpas_p2p_service_flush_asp(wpa_s);
+		return 0;
+	}
+
 	if (sscanf(cmd, "%x", &adv_id) != 1)
 		return -1;
 
@@ -6697,6 +6702,8 @@
 			   MAC2STR(wpa_s->bssid),
 			   MAC2STR(wpa_s->pending_bssid));
 	}
+
+	eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
 }
 
 
@@ -6943,6 +6950,15 @@
 		return;
 	}
 
+#ifdef CONFIG_INTERWORKING
+	if (wpa_s->fetch_anqp_in_progress || wpa_s->network_select) {
+		wpa_printf(MSG_DEBUG,
+			   "Interworking select in progress - reject new scan");
+		*reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n");
+		return;
+	}
+#endif /* CONFIG_INTERWORKING */
+
 	if (params) {
 		if (os_strncasecmp(params, "TYPE=ONLY", 9) == 0)
 			scan_only = 1;
@@ -8248,6 +8264,7 @@
 		wpa_supplicant_cancel_scan(wpa_s);
 		wpa_supplicant_deauthenticate(wpa_s,
 					      WLAN_REASON_DEAUTH_LEAVING);
+		eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
 	} else if (os_strcmp(buf, "SCAN") == 0) {
 		wpas_ctrl_scan(wpa_s, NULL, reply, reply_size, &reply_len);
 	} else if (os_strncmp(buf, "SCAN ", 5) == 0) {
diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h
index 65b430d..ffee1f7 100644
--- a/wpa_supplicant/driver_i.h
+++ b/wpa_supplicant/driver_i.h
@@ -503,13 +503,6 @@
 					    proberesp, assocresp);
 }
 
-static inline int wpa_drv_shared_freq(struct wpa_supplicant *wpa_s)
-{
-	if (!wpa_s->driver->shared_freq)
-		return -1;
-	return wpa_s->driver->shared_freq(wpa_s->drv_priv);
-}
-
 static inline int wpa_drv_get_noa(struct wpa_supplicant *wpa_s,
 				  u8 *buf, size_t buf_len)
 {
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 1f55e0f..6ed2549 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -71,6 +71,59 @@
 }
 
 
+/**
+ * wpas_reenabled_network_time - Time until first network is re-enabled
+ * @wpa_s: Pointer to wpa_supplicant data
+ * Returns: If all enabled networks are temporarily disabled, returns the time
+ *	(in sec) until the first network is re-enabled. Otherwise returns 0.
+ *
+ * This function is used in case all enabled networks are temporarily disabled,
+ * in which case it returns the time (in sec) that the first network will be
+ * re-enabled. The function assumes that at least one network is enabled.
+ */
+static int wpas_reenabled_network_time(struct wpa_supplicant *wpa_s)
+{
+	struct wpa_ssid *ssid;
+	int disabled_for, res = 0;
+
+#ifdef CONFIG_INTERWORKING
+	if (wpa_s->conf->auto_interworking && wpa_s->conf->interworking &&
+	    wpa_s->conf->cred)
+		return 0;
+#endif /* CONFIG_INTERWORKING */
+
+	for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
+		if (ssid->disabled)
+			continue;
+
+		disabled_for = wpas_temp_disabled(wpa_s, ssid);
+		if (!disabled_for)
+			return 0;
+
+		if (!res || disabled_for < res)
+			res = disabled_for;
+	}
+
+	return res;
+}
+
+
+void wpas_network_reenabled(void *eloop_ctx, void *timeout_ctx)
+{
+	struct wpa_supplicant *wpa_s = eloop_ctx;
+
+	if (wpa_s->disconnected || wpa_s->wpa_state != WPA_SCANNING)
+		return;
+
+	wpa_dbg(wpa_s, MSG_DEBUG,
+		"Try to associate due to network getting re-enabled");
+	if (wpa_supplicant_fast_associate(wpa_s) != 1) {
+		wpa_supplicant_cancel_sched_scan(wpa_s);
+		wpa_supplicant_req_scan(wpa_s, 0, 0);
+	}
+}
+
+
 static struct wpa_bss * wpa_supplicant_get_new_bss(
 	struct wpa_supplicant *wpa_s, const u8 *bssid)
 {
@@ -105,11 +158,32 @@
 static int wpa_supplicant_select_config(struct wpa_supplicant *wpa_s)
 {
 	struct wpa_ssid *ssid, *old_ssid;
+	u8 drv_ssid[MAX_SSID_LEN];
+	size_t drv_ssid_len;
 	int res;
 
 	if (wpa_s->conf->ap_scan == 1 && wpa_s->current_ssid) {
 		wpa_supplicant_update_current_bss(wpa_s);
-		return 0;
+
+		if (wpa_s->current_ssid->ssid_len == 0)
+			return 0; /* current profile still in use */
+		res = wpa_drv_get_ssid(wpa_s, drv_ssid);
+		if (res < 0) {
+			wpa_msg(wpa_s, MSG_INFO,
+				"Failed to read SSID from driver");
+			return 0; /* try to use current profile */
+		}
+		drv_ssid_len = res;
+
+		if (drv_ssid_len == wpa_s->current_ssid->ssid_len &&
+		    os_memcmp(drv_ssid, wpa_s->current_ssid->ssid,
+			      drv_ssid_len) == 0)
+			return 0; /* current profile still in use */
+
+		wpa_msg(wpa_s, MSG_DEBUG,
+			"Driver-initiated BSS selection changed the SSID to %s",
+			wpa_ssid_txt(drv_ssid, drv_ssid_len));
+		/* continue selecting a new network profile */
 	}
 
 	wpa_dbg(wpa_s, MSG_DEBUG, "Select network based on association "
@@ -1421,6 +1495,17 @@
 {
 	struct wpa_bss *selected;
 	struct wpa_ssid *ssid = NULL;
+	int time_to_reenable = wpas_reenabled_network_time(wpa_s);
+
+	if (time_to_reenable > 0) {
+		wpa_dbg(wpa_s, MSG_DEBUG,
+			"Postpone network selection by %d seconds since all networks are disabled",
+			time_to_reenable);
+		eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
+		eloop_register_timeout(time_to_reenable, 0,
+				       wpas_network_reenabled, wpa_s, NULL);
+		return 0;
+	}
 
 	if (wpa_s->p2p_mgmt)
 		return 0; /* no normal connection on p2p_mgmt interface */
@@ -1946,6 +2031,8 @@
 	}
 #endif /* CONFIG_AP */
 
+	eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
+
 	ft_completed = wpa_ft_is_completed(wpa_s->wpa);
 	if (data && wpa_supplicant_event_associnfo(wpa_s, data) < 0)
 		return;
@@ -2868,6 +2955,14 @@
 				ifs, &ifs->hw.num_modes, &ifs->hw.flags);
 		}
 	}
+
+	/* Restart sched_scan with updated channel list */
+	if (wpa_s->sched_scanning) {
+		wpa_dbg(wpa_s, MSG_DEBUG,
+			"Channel list changed restart sched scan.");
+		wpa_supplicant_cancel_sched_scan(wpa_s);
+		wpa_supplicant_req_scan(wpa_s, 0, 0);
+	}
 }
 
 
diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h
index 1d3c67b..0b9ebc0 100644
--- a/wpa_supplicant/p2p_supplicant.h
+++ b/wpa_supplicant/p2p_supplicant.h
@@ -93,6 +93,7 @@
 			     u32 adv_id, const char *adv_str, u8 svc_state,
 			     u16 config_methods, const char *svc_info);
 int wpas_p2p_service_del_asp(struct wpa_supplicant *wpa_s, u32 adv_id);
+void wpas_p2p_service_flush_asp(struct wpa_supplicant *wpa_s);
 int wpas_p2p_service_p2ps_id_exists(struct wpa_supplicant *wpa_s, u32 adv_id);
 void wpas_sd_request(void *ctx, int freq, const u8 *sa, u8 dialog_token,
 		     u16 update_indic, const u8 *tlvs, size_t tlvs_len);
diff --git a/wpa_supplicant/p2p_supplicant_sd.c b/wpa_supplicant/p2p_supplicant_sd.c
index cb68c03..f4aa3e0 100644
--- a/wpa_supplicant/p2p_supplicant_sd.c
+++ b/wpa_supplicant/p2p_supplicant_sd.c
@@ -671,6 +671,21 @@
 }
 
 
+static void wpas_sd_all_asp(struct wpa_supplicant *wpa_s,
+			    struct wpabuf *resp, u8 srv_trans_id)
+{
+	/* Query data to add all P2PS advertisements:
+	 *  - Service name length: 1
+	 *  - Service name: '*'
+	 *  - Service Information Request Length: 0
+	 */
+	const u8 q[] = { 1, (const u8) '*', 0 };
+
+	if (p2p_get_p2ps_adv_list(wpa_s->global->p2p))
+		wpas_sd_req_asp(wpa_s, resp, srv_trans_id, q, sizeof(q));
+}
+
+
 void wpas_sd_request(void *ctx, int freq, const u8 *sa, u8 dialog_token,
 		     u16 update_indic, const u8 *tlvs, size_t tlvs_len)
 {
@@ -735,6 +750,7 @@
 				   "response");
 			wpas_sd_all_bonjour(wpa_s, resp, srv_trans_id);
 			wpas_sd_all_upnp(wpa_s, resp, srv_trans_id);
+			wpas_sd_all_asp(wpa_s, resp, srv_trans_id);
 			goto done;
 		}
 
@@ -743,7 +759,8 @@
 			wpa_printf(MSG_DEBUG, "P2P: Service Discovery Request "
 				   "for all services");
 			if (dl_list_empty(&wpa_s->global->p2p_srv_upnp) &&
-			    dl_list_empty(&wpa_s->global->p2p_srv_bonjour)) {
+			    dl_list_empty(&wpa_s->global->p2p_srv_bonjour) &&
+			    !p2p_get_p2ps_adv_list(wpa_s->global->p2p)) {
 				wpa_printf(MSG_DEBUG, "P2P: No service "
 					   "discovery protocols available");
 				wpas_sd_add_proto_not_avail(
@@ -753,6 +770,7 @@
 			}
 			wpas_sd_all_bonjour(wpa_s, resp, srv_trans_id);
 			wpas_sd_all_upnp(wpa_s, resp, srv_trans_id);
+			wpas_sd_all_asp(wpa_s, resp, srv_trans_id);
 			break;
 		case P2P_SERV_BONJOUR:
 			wpas_sd_req_bonjour(wpa_s, resp, srv_trans_id,
@@ -1136,6 +1154,7 @@
 			      struct p2p_srv_upnp, list)
 		wpas_p2p_srv_upnp_free(usrv);
 
+	wpas_p2p_service_flush_asp(wpa_s);
 	wpas_p2p_sd_service_update(wpa_s);
 }
 
@@ -1154,7 +1173,12 @@
 
 int wpas_p2p_service_del_asp(struct wpa_supplicant *wpa_s, u32 adv_id)
 {
-	return p2p_service_del_asp(wpa_s->global->p2p, adv_id);
+	int ret;
+
+	ret = p2p_service_del_asp(wpa_s->global->p2p, adv_id);
+	if (ret == 0)
+		wpas_p2p_sd_service_update(wpa_s);
+	return ret;
 }
 
 
@@ -1163,9 +1187,20 @@
 			     const char *adv_str, u8 svc_state,
 			     u16 config_methods, const char *svc_info)
 {
-	return p2p_service_add_asp(wpa_s->global->p2p, auto_accept, adv_id,
-				   adv_str, svc_state, config_methods,
-				   svc_info);
+	int ret;
+
+	ret = p2p_service_add_asp(wpa_s->global->p2p, auto_accept, adv_id,
+				  adv_str, svc_state, config_methods,
+				  svc_info);
+	if (ret == 0)
+		wpas_p2p_sd_service_update(wpa_s);
+	return ret;
+}
+
+
+void wpas_p2p_service_flush_asp(struct wpa_supplicant *wpa_s)
+{
+	p2p_service_flush_asp(wpa_s->global->p2p);
 }
 
 
diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index 805891a..3c6b2c7 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -418,22 +418,6 @@
 static void wpas_add_interworking_elements(struct wpa_supplicant *wpa_s,
 					   struct wpabuf *buf)
 {
-	if (wpa_s->conf->interworking == 0)
-		return;
-
-	wpabuf_put_u8(buf, WLAN_EID_EXT_CAPAB);
-	wpabuf_put_u8(buf, 6);
-	wpabuf_put_u8(buf, 0x00);
-	wpabuf_put_u8(buf, 0x00);
-	wpabuf_put_u8(buf, 0x00);
-	wpabuf_put_u8(buf, 0x80); /* Bit 31 - Interworking */
-	wpabuf_put_u8(buf, 0x00);
-#ifdef CONFIG_HS20
-	wpabuf_put_u8(buf, 0x40); /* Bit 46 - WNM-Notification */
-#else /* CONFIG_HS20 */
-	wpabuf_put_u8(buf, 0x00);
-#endif /* CONFIG_HS20 */
-
 	wpabuf_put_u8(buf, WLAN_EID_INTERWORKING);
 	wpabuf_put_u8(buf, is_zero_ether_addr(wpa_s->conf->hessid) ? 1 :
 		      1 + ETH_ALEN);
@@ -448,11 +432,19 @@
 static struct wpabuf * wpa_supplicant_extra_ies(struct wpa_supplicant *wpa_s)
 {
 	struct wpabuf *extra_ie = NULL;
+	u8 ext_capab[18];
+	int ext_capab_len;
 #ifdef CONFIG_WPS
 	int wps = 0;
 	enum wps_request_type req_type = WPS_REQ_ENROLLEE_INFO;
 #endif /* CONFIG_WPS */
 
+	ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
+					     sizeof(ext_capab));
+	if (ext_capab_len > 0 &&
+	    wpabuf_resize(&extra_ie, ext_capab_len) == 0)
+		wpabuf_put_data(extra_ie, ext_capab, ext_capab_len);
+
 #ifdef CONFIG_INTERWORKING
 	if (wpa_s->conf->interworking &&
 	    wpabuf_resize(&extra_ie, 100) == 0)
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 19fb890..6f5fbad 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -456,6 +456,8 @@
 			     wpa_s, NULL);
 #endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
 
+	eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
+
 	wpas_wps_deinit(wpa_s);
 
 	wpabuf_free(wpa_s->pending_eapol_rx);
@@ -2625,6 +2627,13 @@
 		eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
 		wpa_s->connect_without_scan =
 			(ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
+
+		/*
+		 * Don't optimize next scan freqs since a new ESS has been
+		 * selected.
+		 */
+		os_free(wpa_s->next_scan_freqs);
+		wpa_s->next_scan_freqs = NULL;
 	} else {
 		wpa_s->connect_without_scan = NULL;
 	}
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 26ff216..0ec102f 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -1140,4 +1140,5 @@
 int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
 			   int *freq_array, unsigned int len);
 
+void wpas_network_reenabled(void *eloop_ctx, void *timeout_ctx);
 #endif /* WPA_SUPPLICANT_I_H */