Cumulative patch from commit 21cb63fffd1e766c8b989125394ed0bfb05e5a4b

21cb63f OpenSSL: Fix client certificate chain building after PKCS#12 use
12a81b6 ACS: Remove unreachable case from a debug print
896607d Remove a pointer check that can never be true
a95cc47 ACS: Be more consistent with iface->current_mode checks
6014e59 P2P: Print find_start in debug log when ignoring old scan results
64845c1 l2_packet: Extend bridge workaround RX processing to cover two frames
4a539ab l2_packet: Improve bridge workaround RX processing
7a36f11 EAP-PAX: Check hmac_sha1_vector() return value
1d20c66 P2P: Clear groups first on FLUSH command
27446e4 mesh: Do not force another peering exchange on driver event
cc64fe7 mesh: Do not clear link state on driver event if exchange was started
b5f5c32 mesh: Add some more details to MPM debug messages
7d41907 nl80211: Add a missing space to a debug message
6174de6 mesh: Connection and group started/removed events into debug log
2da4a56 Add more hostapd.conf documentation for hw_mode with HT/VHT
acc3943 EAP-PEAP peer: Cryptobinding in fast-reconnect case with inner EAP
cba9ebf P2P: Try SD Query with each non-ACK peer only once per search iteration
e9ccfc3 Clear wpa_supplicant state to DISCONNECTED on FLUSH command
aeb408f HS 2.0: Add some documentation for OSEN and network block use
4f6cd3f Fix wpa_supplicant AP mode P2P IE handling if P2P is disabled
92acb40 Fix wpa_supplicant build with CONFIG_L2_PACKET=pcap
15c5606 Update copyright notices for the new year 2016
6e379c6 WPS: Testing mechanism to force auth/encr type flags
ea31912 WPS: Add a workaround for WPA2PSK missing from Enrollee auth flags
db671e0 WPS: Do not build Credential with unsupported encr combination on AP
d7c3347 HS 2.0: Postpone WNM-Notification sending by 100 ms
750f5d9 EAP-FAST: Enable AES256-based TLS cipher suites with OpenSSL
1ebb24b OpenSSL: Share a single openssl_tls_prf() implementation
dea2051 OpenSSL: Clean up function to fetch client/server random
9a42d85 OpenSSL: Drop support for OpenSSL 1.0.0
de213e8 OpenSSL: Drop support for OpenSSL 0.9.8
e79eb0c P2P: Fix P2P_FIND while waiting for listen ROC to start in the driver
944f693 P2P: Stop offchannel TX wait on P2P_STOP_FIND/P2P_LISTEN
8edd9f1 P2P: Add an option to specify group SSID in P2P_CONNECT join case
70e0cb3 P2P: Provide group SSID, if specified, to P2P Client join step
438be60 P2P: Do not accept any GO BSS entry if SSID is specified for join
35510d5 P2P: Use join SSID in the skip-PD cases
8b8d4f4 P2P: Do not accept any BSS entry for join if SSID is already known
b875276 P2P: Use group SSID, if known, for join operation even if no BSS entry
aa256cb P2PS: Add group SSID, if known, to the P2PS-PROV-DONE event
071e3bf FST: Fix handling of Rx FST Setup Request when session already exists

Change-Id: Ia48764e8663232291160fb24153fa367b9ed3015
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/ap/acs.c b/src/ap/acs.c
index 03d797f..5e83805 100644
--- a/src/ap/acs.c
+++ b/src/ap/acs.c
@@ -599,8 +599,7 @@
 	wpa_printf(MSG_DEBUG, "ACS: Survey analysis for selected bandwidth %d MHz",
 		   n_chans == 1 ? 20 :
 		   n_chans == 2 ? 40 :
-		   n_chans == 4 ? 80 :
-		   -1);
+		   80);
 
 	for (i = 0; i < iface->current_mode->num_channels; i++) {
 		double total_weight;
@@ -933,6 +932,9 @@
 		return HOSTAPD_CHAN_ACS;
 	}
 
+	if (!iface->current_mode)
+		return HOSTAPD_CHAN_INVALID;
+
 	acs_cleanup(iface);
 
 	err = acs_request_scan(iface);
diff --git a/src/ap/beacon.c b/src/ap/beacon.c
index 9490e21..3276d12 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -731,7 +731,7 @@
 	}
 
 #ifdef CONFIG_P2P
-	if (hapd->p2p && elems.wps_ie) {
+	if (hapd->p2p && hapd->p2p_group && elems.wps_ie) {
 		struct wpabuf *wps;
 		wps = ieee802_11_vendor_ie_concat(ie, ie_len, WPS_DEV_OUI_WFA);
 		if (wps && !p2p_group_match_dev_type(hapd->p2p_group, wps)) {
@@ -744,7 +744,7 @@
 		wpabuf_free(wps);
 	}
 
-	if (hapd->p2p && elems.p2p) {
+	if (hapd->p2p && hapd->p2p_group && elems.p2p) {
 		struct wpabuf *p2p;
 		p2p = ieee802_11_vendor_ie_concat(ie, ie_len, P2P_IE_VENDOR_TYPE);
 		if (p2p && !p2p_group_match_dev_id(hapd->p2p_group, p2p)) {
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index aad0d81..9f53660 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -956,8 +956,6 @@
 
 	for (i = 0; i < iface->current_mode->num_channels; i++) {
 		chan = &iface->current_mode->channels[i];
-		if (!chan)
-			return NULL;
 		if ((unsigned int) chan->freq == freq)
 			return chan;
 	}
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 01b514e..ec6f8a7 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -1737,7 +1737,7 @@
 #endif /* CONFIG_WPS */
 
 #ifdef CONFIG_P2P
-	if (sta->p2p_ie) {
+	if (sta->p2p_ie && hapd->p2p_group) {
 		struct wpabuf *p2p_resp_ie;
 		enum p2p_status_code status;
 		switch (status_code) {
@@ -2010,7 +2010,7 @@
 	/* Stop Accounting and IEEE 802.1X sessions, but leave the STA
 	 * authenticated. */
 	accounting_sta_stop(hapd, sta);
-	ieee802_1x_free_station(sta);
+	ieee802_1x_free_station(hapd, sta);
 	if (sta->ipaddr)
 		hostapd_drv_br_delete_ip_neigh(hapd, 4, (u8 *) &sta->ipaddr);
 	ap_sta_ip6addr_del(hapd, sta);
diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c
index e3b3d94..607f941 100644
--- a/src/ap/ieee802_1x.c
+++ b/src/ap/ieee802_1x.c
@@ -34,6 +34,9 @@
 #include "ieee802_1x.h"
 
 
+#ifdef CONFIG_HS20
+static void ieee802_1x_wnm_notif_send(void *eloop_ctx, void *timeout_ctx);
+#endif /* CONFIG_HS20 */
 static void ieee802_1x_finished(struct hostapd_data *hapd,
 				struct sta_info *sta, int success,
 				int remediation);
@@ -1048,7 +1051,7 @@
 		 * Clear any possible EAPOL authenticator state to support
 		 * reassociation change from WPS to PSK.
 		 */
-		ieee802_1x_free_station(sta);
+		ieee802_1x_free_station(hapd, sta);
 		return;
 	}
 
@@ -1059,7 +1062,7 @@
 		 * Clear any possible EAPOL authenticator state to support
 		 * reassociation change from WPA-EAP to PSK.
 		 */
-		ieee802_1x_free_station(sta);
+		ieee802_1x_free_station(hapd, sta);
 		return;
 	}
 
@@ -1146,10 +1149,14 @@
 }
 
 
-void ieee802_1x_free_station(struct sta_info *sta)
+void ieee802_1x_free_station(struct hostapd_data *hapd, struct sta_info *sta)
 {
 	struct eapol_state_machine *sm = sta->eapol_sm;
 
+#ifdef CONFIG_HS20
+	eloop_cancel_timeout(ieee802_1x_wnm_notif_send, hapd, sta);
+#endif /* CONFIG_HS20 */
+
 	if (sm == NULL)
 		return;
 
@@ -2528,6 +2535,34 @@
 }
 
 
+#ifdef CONFIG_HS20
+static void ieee802_1x_wnm_notif_send(void *eloop_ctx, void *timeout_ctx)
+{
+	struct hostapd_data *hapd = eloop_ctx;
+	struct sta_info *sta = timeout_ctx;
+
+	if (sta->remediation) {
+		wpa_printf(MSG_DEBUG, "HS 2.0: Send WNM-Notification to "
+			   MACSTR " to indicate Subscription Remediation",
+			   MAC2STR(sta->addr));
+		hs20_send_wnm_notification(hapd, sta->addr,
+					   sta->remediation_method,
+					   sta->remediation_url);
+		os_free(sta->remediation_url);
+		sta->remediation_url = NULL;
+	}
+
+	if (sta->hs20_deauth_req) {
+		wpa_printf(MSG_DEBUG, "HS 2.0: Send WNM-Notification to "
+			   MACSTR " to indicate imminent deauthentication",
+			   MAC2STR(sta->addr));
+		hs20_send_wnm_notification_deauth_req(hapd, sta->addr,
+						      sta->hs20_deauth_req);
+	}
+}
+#endif /* CONFIG_HS20 */
+
+
 static void ieee802_1x_finished(struct hostapd_data *hapd,
 				struct sta_info *sta, int success,
 				int remediation)
@@ -2547,26 +2582,12 @@
 		sta->remediation_method = 1; /* SOAP-XML SPP */
 	}
 
-	if (success) {
-		if (sta->remediation) {
-			wpa_printf(MSG_DEBUG, "HS 2.0: Send WNM-Notification "
-				   "to " MACSTR " to indicate Subscription "
-				   "Remediation",
-				   MAC2STR(sta->addr));
-			hs20_send_wnm_notification(hapd, sta->addr,
-						   sta->remediation_method,
-						   sta->remediation_url);
-			os_free(sta->remediation_url);
-			sta->remediation_url = NULL;
-		}
-
-		if (sta->hs20_deauth_req) {
-			wpa_printf(MSG_DEBUG, "HS 2.0: Send WNM-Notification "
-				   "to " MACSTR " to indicate imminent "
-				   "deauthentication", MAC2STR(sta->addr));
-			hs20_send_wnm_notification_deauth_req(
-				hapd, sta->addr, sta->hs20_deauth_req);
-		}
+	if (success && (sta->remediation || sta->hs20_deauth_req)) {
+		wpa_printf(MSG_DEBUG, "HS 2.0: Schedule WNM-Notification to "
+			   MACSTR " in 100 ms", MAC2STR(sta->addr));
+		eloop_cancel_timeout(ieee802_1x_wnm_notif_send, hapd, sta);
+		eloop_register_timeout(0, 100000, ieee802_1x_wnm_notif_send,
+				       hapd, sta);
 	}
 #endif /* CONFIG_HS20 */
 
diff --git a/src/ap/ieee802_1x.h b/src/ap/ieee802_1x.h
index 14d6955..ec80199 100644
--- a/src/ap/ieee802_1x.h
+++ b/src/ap/ieee802_1x.h
@@ -21,7 +21,7 @@
 void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
 			size_t len);
 void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta);
-void ieee802_1x_free_station(struct sta_info *sta);
+void ieee802_1x_free_station(struct hostapd_data *hapd, struct sta_info *sta);
 
 void ieee802_1x_abort_auth(struct hostapd_data *hapd, struct sta_info *sta);
 void ieee802_1x_set_sta_authorized(struct hostapd_data *hapd,
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index 500beff..68fff4c 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -253,7 +253,7 @@
 	eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta);
 	sae_clear_retransmit_timer(hapd, sta);
 
-	ieee802_1x_free_station(sta);
+	ieee802_1x_free_station(hapd, sta);
 	wpa_auth_sta_deinit(sta->wpa_sm);
 	rsn_preauth_free_station(hapd, sta);
 #ifndef CONFIG_NO_RADIUS
@@ -487,7 +487,7 @@
 			sta->acct_terminate_cause =
 				RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT;
 		accounting_sta_stop(hapd, sta);
-		ieee802_1x_free_station(sta);
+		ieee802_1x_free_station(hapd, sta);
 		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
 			       HOSTAPD_LEVEL_INFO, "disassociated due to "
 			       "inactivity");
@@ -722,7 +722,7 @@
 	eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DISASSOC, 0,
 			       ap_handle_timer, hapd, sta);
 	accounting_sta_stop(hapd, sta);
-	ieee802_1x_free_station(sta);
+	ieee802_1x_free_station(hapd, sta);
 
 	sta->disassoc_reason = reason;
 	sta->flags |= WLAN_STA_PENDING_DISASSOC_CB;
@@ -761,7 +761,7 @@
 	eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DEAUTH, 0,
 			       ap_handle_timer, hapd, sta);
 	accounting_sta_stop(hapd, sta);
-	ieee802_1x_free_station(sta);
+	ieee802_1x_free_station(hapd, sta);
 
 	sta->deauth_reason = reason;
 	sta->flags |= WLAN_STA_PENDING_DEAUTH_CB;
diff --git a/src/ap/wps_hostapd.c b/src/ap/wps_hostapd.c
index 66a43eb..ba58f3e 100644
--- a/src/ap/wps_hostapd.c
+++ b/src/ap/wps_hostapd.c
@@ -1,6 +1,6 @@
 /*
  * hostapd / WPS integration
- * Copyright (c) 2008-2012, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2008-2016, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -445,6 +445,8 @@
 	os_memcpy(hapd->wps->ssid, cred->ssid, cred->ssid_len);
 	hapd->wps->ssid_len = cred->ssid_len;
 	hapd->wps->encr_types = cred->encr_type;
+	hapd->wps->encr_types_rsn = cred->encr_type;
+	hapd->wps->encr_types_wpa = cred->encr_type;
 	hapd->wps->auth_types = cred->auth_type;
 	hapd->wps->ap_encr_type = cred->encr_type;
 	hapd->wps->ap_auth_type = cred->auth_type;
@@ -1068,10 +1070,14 @@
 		if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X)
 			wps->auth_types |= WPS_AUTH_WPA2;
 
-		if (conf->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP))
+		if (conf->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP)) {
 			wps->encr_types |= WPS_ENCR_AES;
-		if (conf->rsn_pairwise & WPA_CIPHER_TKIP)
+			wps->encr_types_rsn |= WPS_ENCR_AES;
+		}
+		if (conf->rsn_pairwise & WPA_CIPHER_TKIP) {
 			wps->encr_types |= WPS_ENCR_TKIP;
+			wps->encr_types_rsn |= WPS_ENCR_TKIP;
+		}
 	}
 
 	if (conf->wpa & WPA_PROTO_WPA) {
@@ -1080,10 +1086,14 @@
 		if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X)
 			wps->auth_types |= WPS_AUTH_WPA;
 
-		if (conf->wpa_pairwise & WPA_CIPHER_CCMP)
+		if (conf->wpa_pairwise & WPA_CIPHER_CCMP) {
 			wps->encr_types |= WPS_ENCR_AES;
-		if (conf->wpa_pairwise & WPA_CIPHER_TKIP)
+			wps->encr_types_wpa |= WPS_ENCR_AES;
+		}
+		if (conf->wpa_pairwise & WPA_CIPHER_TKIP) {
 			wps->encr_types |= WPS_ENCR_TKIP;
+			wps->encr_types_wpa |= WPS_ENCR_TKIP;
+		}
 	}
 
 	if (conf->ssid.security_policy == SECURITY_PLAINTEXT) {
@@ -1123,6 +1133,8 @@
 		/* Override parameters to enable security by default */
 		wps->auth_types = WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK;
 		wps->encr_types = WPS_ENCR_AES | WPS_ENCR_TKIP;
+		wps->encr_types_rsn = WPS_ENCR_AES | WPS_ENCR_TKIP;
+		wps->encr_types_wpa = WPS_ENCR_AES | WPS_ENCR_TKIP;
 	}
 
 	wps->ap_settings = conf->ap_settings;
diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c
index b53bc4a..73b547d 100644
--- a/src/crypto/crypto_openssl.c
+++ b/src/crypto/crypto_openssl.c
@@ -772,14 +772,10 @@
 #else
 	HMAC_CTX_init(&ctx->ctx);
 
-#if OPENSSL_VERSION_NUMBER < 0x00909000
-	HMAC_Init_ex(&ctx->ctx, key, key_len, md, NULL);
-#else /* openssl < 0.9.9 */
 	if (HMAC_Init_ex(&ctx->ctx, key, key_len, md, NULL) != 1) {
 		bin_clear_free(ctx, sizeof(*ctx));
 		return NULL;
 	}
-#endif /* openssl < 0.9.9 */
 #endif
 
 	return ctx;
@@ -819,12 +815,7 @@
 	res = HMAC_Final(ctx->ctx, mac, &mdlen);
 	HMAC_CTX_free(ctx->ctx);
 #else
-#if OPENSSL_VERSION_NUMBER < 0x00909000
-	HMAC_Final(&ctx->ctx, mac, &mdlen);
-	res = 1;
-#else /* openssl < 0.9.9 */
 	res = HMAC_Final(&ctx->ctx, mac, &mdlen);
-#endif /* openssl < 0.9.9 */
 	HMAC_CTX_cleanup(&ctx->ctx);
 #endif
 	bin_clear_free(ctx, sizeof(*ctx));
@@ -875,22 +866,13 @@
 		return -1;
 
 	HMAC_CTX_init(&ctx);
-#if OPENSSL_VERSION_NUMBER < 0x00909000
-	HMAC_Init_ex(&ctx, key, key_len, type, NULL);
-#else /* openssl < 0.9.9 */
 	if (HMAC_Init_ex(&ctx, key, key_len, type, NULL) != 1)
 		return -1;
-#endif /* openssl < 0.9.9 */
 
 	for (i = 0; i < num_elem; i++)
 		HMAC_Update(&ctx, addr[i], len[i]);
 
-#if OPENSSL_VERSION_NUMBER < 0x00909000
-	HMAC_Final(&ctx, mac, &mdlen);
-	res = 1;
-#else /* openssl < 0.9.9 */
 	res = HMAC_Final(&ctx, mac, &mdlen);
-#endif /* openssl < 0.9.9 */
 	HMAC_CTX_cleanup(&ctx);
 
 	return res == 1 ? 0 : -1;
diff --git a/src/crypto/tls.h b/src/crypto/tls.h
index 453b4de..15a3bcf 100644
--- a/src/crypto/tls.h
+++ b/src/crypto/tls.h
@@ -461,7 +461,9 @@
 	TLS_CIPHER_RC4_SHA /* 0x0005 */,
 	TLS_CIPHER_AES128_SHA /* 0x002f */,
 	TLS_CIPHER_RSA_DHE_AES128_SHA /* 0x0031 */,
-	TLS_CIPHER_ANON_DH_AES128_SHA /* 0x0034 */
+	TLS_CIPHER_ANON_DH_AES128_SHA /* 0x0034 */,
+	TLS_CIPHER_RSA_DHE_AES256_SHA /* 0x0039 */,
+	TLS_CIPHER_AES256_SHA /* 0x0035 */,
 };
 
 /**
diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c
index 62277c4..22d6dc4 100644
--- a/src/crypto/tls_openssl.c
+++ b/src/crypto/tls_openssl.c
@@ -37,13 +37,6 @@
 #include "tls.h"
 #include "tls_openssl.h"
 
-#if OPENSSL_VERSION_NUMBER < 0x10000000L
-/* ERR_remove_thread_state replaces ERR_remove_state and the latter is
- * deprecated. However, OpenSSL 0.9.8 doesn't include
- * ERR_remove_thread_state. */
-#define ERR_remove_thread_state(tid) ERR_remove_state(0)
-#endif
-
 #if defined(OPENSSL_IS_BORINGSSL)
 /* stack_index_t is the return type of OpenSSL's sk_XXX_num() functions. */
 typedef size_t stack_index_t;
@@ -58,6 +51,46 @@
 #endif /* OPENSSL_NO_TLSEXT */
 #endif /* SSL_set_tlsext_status_type */
 
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+/*
+ * SSL_get_client_random() and SSL_get_server_random() were added in OpenSSL
+ * 1.1.0. Provide compatibility wrappers for older versions.
+ */
+
+static size_t SSL_get_client_random(const SSL *ssl, unsigned char *out,
+				    size_t outlen)
+{
+	if (!ssl->s3 || outlen < SSL3_RANDOM_SIZE)
+		return 0;
+	os_memcpy(out, ssl->s3->client_random, SSL3_RANDOM_SIZE);
+	return SSL3_RANDOM_SIZE;
+}
+
+
+static size_t SSL_get_server_random(const SSL *ssl, unsigned char *out,
+				    size_t outlen)
+{
+	if (!ssl->s3 || outlen < SSL3_RANDOM_SIZE)
+		return 0;
+	os_memcpy(out, ssl->s3->server_random, SSL3_RANDOM_SIZE);
+	return SSL3_RANDOM_SIZE;
+}
+
+
+static size_t SSL_SESSION_get_master_key(const SSL_SESSION *session,
+					 unsigned char *out, size_t outlen)
+{
+	if (!session || session->master_key_length < 0 ||
+	    (size_t) session->master_key_length > outlen)
+		return 0;
+	if ((size_t) session->master_key_length < outlen)
+		outlen = session->master_key_length;
+	os_memcpy(out, session->master_key, outlen);
+	return outlen;
+}
+
+#endif
+
 #ifdef ANDROID
 #include <openssl/pem.h>
 #include <keystore/keystore_get.h>
@@ -126,10 +159,8 @@
 	X509 *peer_issuer;
 	X509 *peer_issuer_issuer;
 
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L
 	unsigned char client_random[SSL3_RANDOM_SIZE];
 	unsigned char server_random[SSL3_RANDOM_SIZE];
-#endif
 };
 
 
@@ -2203,6 +2234,17 @@
 	if (client_cert == NULL && client_cert_blob == NULL)
 		return 0;
 
+#ifdef PKCS12_FUNCS
+#if OPENSSL_VERSION_NUMBER < 0x10002000L
+	/*
+	 * Clear previously set extra chain certificates, if any, from PKCS#12
+	 * processing in tls_parse_pkcs12() to allow OpenSSL to build a new
+	 * chain properly.
+	 */
+	SSL_CTX_clear_extra_chain_certs(conn->ssl_ctx);
+#endif /* OPENSSL_VERSION_NUMBER < 0x10002000L */
+#endif /* PKCS12_FUNCS */
+
 	if (client_cert_blob &&
 	    SSL_use_certificate_ASN1(conn->ssl, (u8 *) client_cert_blob,
 				     client_cert_blob_len) == 1) {
@@ -2386,9 +2428,7 @@
 		 */
 		res = 0;
 #else /* OPENSSL_VERSION_NUMBER >= 0x10002000L */
-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
 		SSL_CTX_clear_extra_chain_certs(data->ssl);
-#endif /* OPENSSL_VERSION_NUMBER >= 0x10001000L */
 		while ((cert = sk_X509_pop(certs)) != NULL) {
 			X509_NAME_oneline(X509_get_subject_name(cert), buf,
 					  sizeof(buf));
@@ -2933,16 +2973,6 @@
 	if (conn == NULL || keys == NULL)
 		return -1;
 	ssl = conn->ssl;
-#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
-	if (ssl == NULL || ssl->s3 == NULL || ssl->session == NULL)
-		return -1;
-
-	os_memset(keys, 0, sizeof(*keys));
-	keys->client_random = ssl->s3->client_random;
-	keys->client_random_len = SSL3_RANDOM_SIZE;
-	keys->server_random = ssl->s3->server_random;
-	keys->server_random_len = SSL3_RANDOM_SIZE;
-#else
 	if (ssl == NULL)
 		return -1;
 
@@ -2953,7 +2983,6 @@
 	keys->server_random = conn->server_random;
 	keys->server_random_len = SSL_get_server_random(
 		ssl, conn->server_random, sizeof(conn->server_random));
-#endif
 
 	return 0;
 }
@@ -2972,17 +3001,11 @@
 		return -1;
 
 	c = ssl->enc_read_ctx->cipher;
-#if OPENSSL_VERSION_NUMBER >= 0x00909000L
 	h = EVP_MD_CTX_md(ssl->read_hash);
-#else
-	h = ssl->read_hash;
-#endif
 	if (h)
 		md_size = EVP_MD_size(h);
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
 	else if (ssl->s3)
 		md_size = ssl->s3->tmp.new_mac_secret_size;
-#endif
 	else
 		return -1;
 
@@ -3032,74 +3055,6 @@
 		   "mode");
 	return -1;
 #else /* CONFIG_FIPS */
-#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
-	SSL *ssl;
-	u8 *rnd;
-	int ret = -1;
-	int skip = 0;
-	u8 *tmp_out = NULL;
-	u8 *_out = out;
-	const char *ver;
-
-	/*
-	 * TLS library did not support key generation, so get the needed TLS
-	 * session parameters and use an internal implementation of TLS PRF to
-	 * derive the key.
-	 */
-
-	if (conn == NULL)
-		return -1;
-	ssl = conn->ssl;
-	if (ssl == NULL || ssl->s3 == NULL || ssl->session == NULL ||
-	    ssl->session->master_key_length <= 0)
-		return -1;
-	ver = SSL_get_version(ssl);
-
-	if (skip_keyblock) {
-		skip = openssl_get_keyblock_size(ssl);
-		if (skip < 0)
-			return -1;
-		tmp_out = os_malloc(skip + out_len);
-		if (!tmp_out)
-			return -1;
-		_out = tmp_out;
-	}
-
-	rnd = os_malloc(2 * SSL3_RANDOM_SIZE);
-	if (!rnd) {
-		os_free(tmp_out);
-		return -1;
-	}
-
-	if (server_random_first) {
-		os_memcpy(rnd, ssl->s3->server_random, SSL3_RANDOM_SIZE);
-		os_memcpy(rnd + SSL3_RANDOM_SIZE, ssl->s3->client_random,
-			SSL3_RANDOM_SIZE);
-	} else {
-		os_memcpy(rnd, ssl->s3->client_random, SSL3_RANDOM_SIZE);
-		os_memcpy(rnd + SSL3_RANDOM_SIZE, ssl->s3->server_random,
-			SSL3_RANDOM_SIZE);
-	}
-
-	if (os_strcmp(ver, "TLSv1.2") == 0) {
-		tls_prf_sha256(ssl->session->master_key,
-			       ssl->session->master_key_length,
-			       label, rnd, 2 * SSL3_RANDOM_SIZE,
-			       _out, skip + out_len);
-		ret = 0;
-	} else if (tls_prf_sha1_md5(ssl->session->master_key,
-				    ssl->session->master_key_length,
-				    label, rnd, 2 * SSL3_RANDOM_SIZE,
-				    _out, skip + out_len) == 0) {
-		ret = 0;
-	}
-	os_free(rnd);
-	if (ret == 0 && skip_keyblock)
-		os_memcpy(out, _out + skip, out_len);
-	bin_clear_free(tmp_out, skip);
-
-	return ret;
-#else
 	SSL *ssl;
 	SSL_SESSION *sess;
 	u8 *rnd;
@@ -3177,7 +3132,6 @@
 	bin_clear_free(tmp_out, skip);
 
 	return ret;
-#endif
 #endif /* CONFIG_FIPS */
 }
 
@@ -3186,21 +3140,17 @@
 		       const char *label, int server_random_first,
 		       int skip_keyblock, u8 *out, size_t out_len)
 {
-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
-	SSL *ssl;
 	if (conn == NULL)
 		return -1;
 	if (server_random_first || skip_keyblock)
 		return openssl_tls_prf(conn, label,
 				       server_random_first, skip_keyblock,
 				       out, out_len);
-	ssl = conn->ssl;
-	if (SSL_export_keying_material(ssl, out, out_len, label,
+	if (SSL_export_keying_material(conn->ssl, out, out_len, label,
 				       os_strlen(label), NULL, 0, 0) == 1) {
 		wpa_printf(MSG_DEBUG, "OpenSSL: Using internal PRF");
 		return 0;
 	}
-#endif
 	return openssl_tls_prf(conn, label, server_random_first,
 			       skip_keyblock, out, out_len);
 }
@@ -3461,18 +3411,14 @@
 
 int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn)
 {
-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
 	return conn ? SSL_cache_hit(conn->ssl) : 0;
-#else
-	return conn ? conn->ssl->hit : 0;
-#endif
 }
 
 
 int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
 				   u8 *ciphers)
 {
-	char buf[100], *pos, *end;
+	char buf[500], *pos, *end;
 	u8 *c;
 	int ret;
 
@@ -3500,6 +3446,12 @@
 		case TLS_CIPHER_ANON_DH_AES128_SHA:
 			suite = "ADH-AES128-SHA";
 			break;
+		case TLS_CIPHER_RSA_DHE_AES256_SHA:
+			suite = "DHE-RSA-AES256-SHA";
+			break;
+		case TLS_CIPHER_AES256_SHA:
+			suite = "AES256-SHA";
+			break;
 		default:
 			wpa_printf(MSG_DEBUG, "TLS: Unsupported "
 				   "cipher selection: %d", *c);
diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
index 4d7ac47..d5b5a87 100644
--- a/src/drivers/driver_nl80211_event.c
+++ b/src/drivers/driver_nl80211_event.c
@@ -1136,7 +1136,7 @@
 		return;
 
 	addr = nla_data(tb[NL80211_ATTR_MAC]);
-	wpa_printf(MSG_DEBUG, "nl80211: New peer candidate" MACSTR,
+	wpa_printf(MSG_DEBUG, "nl80211: New peer candidate " MACSTR,
 		   MAC2STR(addr));
 
 	os_memset(&data, 0, sizeof(data));
diff --git a/src/eap_common/eap_pax_common.c b/src/eap_common/eap_pax_common.c
index 0e80ef5..a11bce8 100644
--- a/src/eap_common/eap_pax_common.c
+++ b/src/eap_common/eap_pax_common.c
@@ -57,7 +57,8 @@
 	left = output_len;
 	for (counter = 1; counter <= (u8) num_blocks; counter++) {
 		size_t clen = left > EAP_PAX_MAC_LEN ? EAP_PAX_MAC_LEN : left;
-		hmac_sha1_vector(key, key_len, 3, addr, len, mac);
+		if (hmac_sha1_vector(key, key_len, 3, addr, len, mac) < 0)
+			return -1;
 		os_memcpy(pos, mac, clen);
 		pos += clen;
 		left -= clen;
@@ -106,7 +107,8 @@
 	len[2] = data3_len;
 
 	count = (data1 ? 1 : 0) + (data2 ? 1 : 0) + (data3 ? 1 : 0);
-	hmac_sha1_vector(key, key_len, count, addr, len, hash);
+	if (hmac_sha1_vector(key, key_len, count, addr, len, hash) < 0)
+		return -1;
 	os_memcpy(mac, hash, EAP_PAX_MAC_LEN);
 
 	return 0;
diff --git a/src/eap_peer/eap_fast.c b/src/eap_peer/eap_fast.c
index a7f6bef..57390ae 100644
--- a/src/eap_peer/eap_fast.c
+++ b/src/eap_peer/eap_fast.c
@@ -1446,7 +1446,7 @@
 static int eap_fast_set_provisioning_ciphers(struct eap_sm *sm,
 					     struct eap_fast_data *data)
 {
-	u8 ciphers[5];
+	u8 ciphers[7];
 	int count = 0;
 
 	if (data->provisioning_allowed & EAP_FAST_PROV_UNAUTH) {
@@ -1458,7 +1458,9 @@
 	if (data->provisioning_allowed & EAP_FAST_PROV_AUTH) {
 		wpa_printf(MSG_DEBUG, "EAP-FAST: Enabling authenticated "
 			   "provisioning TLS cipher suites");
+		ciphers[count++] = TLS_CIPHER_RSA_DHE_AES256_SHA;
 		ciphers[count++] = TLS_CIPHER_RSA_DHE_AES128_SHA;
+		ciphers[count++] = TLS_CIPHER_AES256_SHA;
 		ciphers[count++] = TLS_CIPHER_AES128_SHA;
 		ciphers[count++] = TLS_CIPHER_RC4_SHA;
 	}
diff --git a/src/eap_peer/eap_pax.c b/src/eap_peer/eap_pax.c
index c920bcd..2b87a64 100644
--- a/src/eap_peer/eap_pax.c
+++ b/src/eap_peer/eap_pax.c
@@ -276,10 +276,10 @@
 	left -= 2;
 	wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: MAC_CK(B, CID)",
 		    pos, EAP_PAX_MAC_LEN);
-	eap_pax_mac(data->mac_id, data->ck, EAP_PAX_CK_LEN,
-		    data->rand.r.y, EAP_PAX_RAND_LEN,
-		    (u8 *) data->cid, data->cid_len, NULL, 0, mac);
-	if (os_memcmp_const(pos, mac, EAP_PAX_MAC_LEN) != 0) {
+	if (eap_pax_mac(data->mac_id, data->ck, EAP_PAX_CK_LEN,
+			data->rand.r.y, EAP_PAX_RAND_LEN,
+			(u8 *) data->cid, data->cid_len, NULL, 0, mac) < 0 ||
+	    os_memcmp_const(pos, mac, EAP_PAX_MAC_LEN) != 0) {
 		wpa_printf(MSG_INFO, "EAP-PAX: Invalid MAC_CK(B, CID) "
 			   "received");
 		wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: expected MAC_CK(B, CID)",
@@ -306,9 +306,12 @@
 	/* Optional ADE could be added here, if needed */
 
 	rpos = wpabuf_put(resp, EAP_PAX_ICV_LEN);
-	eap_pax_mac(data->mac_id, data->ick, EAP_PAX_ICK_LEN,
-		    wpabuf_head(resp), wpabuf_len(resp) - EAP_PAX_ICV_LEN,
-		    NULL, 0, NULL, 0, rpos);
+	if (eap_pax_mac(data->mac_id, data->ick, EAP_PAX_ICK_LEN,
+			wpabuf_head(resp), wpabuf_len(resp) - EAP_PAX_ICV_LEN,
+			NULL, 0, NULL, 0, rpos) < 0) {
+		wpabuf_free(resp);
+		return NULL;
+	}
 	wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", rpos, EAP_PAX_ICV_LEN);
 
 	data->state = PAX_DONE;
@@ -472,9 +475,13 @@
 		return NULL;
 
 	*len = EAP_MSK_LEN;
-	eap_pax_kdf(data->mac_id, data->mk, EAP_PAX_MK_LEN,
-		    "Master Session Key", data->rand.e, 2 * EAP_PAX_RAND_LEN,
-		    EAP_MSK_LEN, key);
+	if (eap_pax_kdf(data->mac_id, data->mk, EAP_PAX_MK_LEN,
+			"Master Session Key",
+			data->rand.e, 2 * EAP_PAX_RAND_LEN,
+			EAP_MSK_LEN, key) < 0) {
+		os_free(key);
+		return NULL;
+	}
 
 	return key;
 }
@@ -493,10 +500,13 @@
 		return NULL;
 
 	*len = EAP_EMSK_LEN;
-	eap_pax_kdf(data->mac_id, data->mk, EAP_PAX_MK_LEN,
-		    "Extended Master Session Key",
-		    data->rand.e, 2 * EAP_PAX_RAND_LEN,
-		    EAP_EMSK_LEN, key);
+	if (eap_pax_kdf(data->mac_id, data->mk, EAP_PAX_MK_LEN,
+			"Extended Master Session Key",
+			data->rand.e, 2 * EAP_PAX_RAND_LEN,
+			EAP_EMSK_LEN, key) < 0) {
+		os_free(key);
+		return NULL;
+	}
 
 	return key;
 }
diff --git a/src/eap_peer/eap_peap.c b/src/eap_peer/eap_peap.c
index 503d4b0..bf420cc 100644
--- a/src/eap_peer/eap_peap.c
+++ b/src/eap_peer/eap_peap.c
@@ -253,6 +253,7 @@
 {
 	u8 *tk;
 	u8 isk[32], imck[60];
+	int resumed;
 
 	/*
 	 * Tunnel key (TK) is the first 60 octets of the key generated by
@@ -263,8 +264,12 @@
 		return -1;
 	wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TK", tk, 60);
 
-	if (data->reauth &&
-	    tls_connection_resumed(sm->ssl_ctx, data->ssl.conn)) {
+	resumed = tls_connection_resumed(sm->ssl_ctx, data->ssl.conn);
+	wpa_printf(MSG_DEBUG,
+		   "EAP-PEAP: CMK derivation - reauth=%d resumed=%d phase2_eap_started=%d phase2_success=%d",
+		   data->reauth, resumed, data->phase2_eap_started,
+		   data->phase2_success);
+	if (data->reauth && !data->phase2_eap_started && resumed) {
 		/* Fast-connect: IPMK|CMK = TK */
 		os_memcpy(data->ipmk, tk, 40);
 		wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK from TK",
diff --git a/src/eap_server/eap_server_fast.c b/src/eap_server/eap_server_fast.c
index e348eb3..2e03f88 100644
--- a/src/eap_server/eap_server_fast.c
+++ b/src/eap_server/eap_server_fast.c
@@ -412,11 +412,13 @@
 static void * eap_fast_init(struct eap_sm *sm)
 {
 	struct eap_fast_data *data;
-	u8 ciphers[5] = {
+	u8 ciphers[7] = {
 		TLS_CIPHER_ANON_DH_AES128_SHA,
 		TLS_CIPHER_AES128_SHA,
 		TLS_CIPHER_RSA_DHE_AES128_SHA,
 		TLS_CIPHER_RC4_SHA,
+		TLS_CIPHER_RSA_DHE_AES256_SHA,
+		TLS_CIPHER_AES256_SHA,
 		TLS_CIPHER_NONE
 	};
 
diff --git a/src/fst/fst_session.c b/src/fst/fst_session.c
index f804b12..9e4dada 100644
--- a/src/fst/fst_session.c
+++ b/src/fst/fst_session.c
@@ -447,7 +447,9 @@
 		 * the initiator’s MAC address, in which case, the responder
 		 * shall delete the received FST Setup Request.
 		 */
-		if (os_memcmp(mgmt->da, mgmt->sa, ETH_ALEN) > 0) {
+		if (fst_session_is_ready_pending(s) &&
+		    /* waiting for Setup Response */
+		    os_memcmp(mgmt->da, mgmt->sa, ETH_ALEN) > 0) {
 			fst_printf_session(s, MSG_WARNING,
 					   "FST Request dropped due to MAC comparison (our MAC is "
 					   MACSTR ")",
@@ -455,23 +457,26 @@
 			return;
 		}
 
-		if (!fst_session_is_ready_pending(s)) {
-			fst_printf_session(s, MSG_WARNING,
-					   "FST Request from " MACSTR
-					   " dropped due to inappropriate state %s",
-					   MAC2STR(mgmt->da),
-					   fst_session_state_name(s->state));
-			return;
-		}
+		/*
+		 * State is SETUP_COMPLETION (either in transition or not) or
+		 * TRANSITION_DONE (in transition).
+		 * Setup Request arriving in this state could mean:
+		 * 1. peer sent it before receiving our Setup Request (race
+		 *    condition)
+		 * 2. peer didn't receive our Setup Response. Peer is retrying
+		 *    after STT timeout
+		 * 3. peer's FST state machines are out of sync due to some
+		 *    other reason
+		 *
+		 * We will reset our session and create a new one instead.
+		 */
 
+		fst_printf_session(s, MSG_WARNING,
+			"resetting due to FST request");
 
 		/*
 		 * If FST Setup Request arrived with the same FSTS ID as one we
-		 * initialized before, it means the other side either didn't
-		 * receive our FST Request or skipped it for some reason (for
-		 * example, due to numerical MAC comparison).
-		 *
-		 * In this case, there's no need to tear down the session.
+		 * initialized before, there's no need to tear down the session.
 		 * Moreover, as FSTS ID is the same, the other side will
 		 * associate this tear down with the session it initiated that
 		 * will break the sync.
@@ -483,7 +488,6 @@
 					   "Skipping TearDown as the FST request has the same FSTS ID as initiated");
 		fst_session_set_state(s, FST_SESSION_STATE_INITIAL, &evext);
 		fst_session_stt_disarm(s);
-		fst_printf_session(s, MSG_WARNING, "reset due to FST request");
 	}
 
 	s = fst_session_create(g);
diff --git a/src/l2_packet/l2_packet_linux.c b/src/l2_packet/l2_packet_linux.c
index f52f7a2..a7a300e 100644
--- a/src/l2_packet/l2_packet_linux.c
+++ b/src/l2_packet/l2_packet_linux.c
@@ -33,8 +33,9 @@
 #ifndef CONFIG_NO_LINUX_PACKET_SOCKET_WAR
 	/* For working around Linux packet socket behavior and regression. */
 	int fd_br_rx;
-	int last_from_br;
+	int last_from_br, last_from_br_prev;
 	u8 last_hash[SHA1_MAC_LEN];
+	u8 last_hash_prev[SHA1_MAC_LEN];
 	unsigned int num_rx_br;
 #endif /* CONFIG_NO_LINUX_PACKET_SOCKET_WAR */
 };
@@ -171,6 +172,14 @@
 				   __func__);
 			return;
 		}
+		if (l2->last_from_br_prev &&
+		    os_memcmp(hash, l2->last_hash_prev, SHA1_MAC_LEN) == 0) {
+			wpa_printf(MSG_DEBUG, "%s: Drop duplicate RX(prev)",
+				   __func__);
+			return;
+		}
+		os_memcpy(l2->last_hash_prev, l2->last_hash, SHA1_MAC_LEN);
+		l2->last_from_br_prev = l2->last_from_br;
 		os_memcpy(l2->last_hash, hash, SHA1_MAC_LEN);
 	}
 
@@ -206,6 +215,11 @@
 	wpa_printf(MSG_DEBUG, "%s: src=" MACSTR " len=%d",
 		   __func__, MAC2STR(ll.sll_addr), (int) res);
 
+	if (os_memcmp(ll.sll_addr, l2->own_addr, ETH_ALEN) == 0) {
+		wpa_printf(MSG_DEBUG, "%s: Drop RX of own frame", __func__);
+		return;
+	}
+
 	addr[0] = buf;
 	len[0] = res;
 	sha1_vector(1, addr, len, hash);
@@ -214,6 +228,13 @@
 		wpa_printf(MSG_DEBUG, "%s: Drop duplicate RX", __func__);
 		return;
 	}
+	if (!l2->last_from_br_prev &&
+	    os_memcmp(hash, l2->last_hash_prev, SHA1_MAC_LEN) == 0) {
+		wpa_printf(MSG_DEBUG, "%s: Drop duplicate RX(prev)", __func__);
+		return;
+	}
+	os_memcpy(l2->last_hash_prev, l2->last_hash, SHA1_MAC_LEN);
+	l2->last_from_br_prev = l2->last_from_br;
 	l2->last_from_br = 1;
 	os_memcpy(l2->last_hash, hash, SHA1_MAC_LEN);
 	l2->rx_callback(l2->rx_callback_ctx, ll.sll_addr, buf, res);
diff --git a/src/l2_packet/l2_packet_pcap.c b/src/l2_packet/l2_packet_pcap.c
index bb4f4a3..423c099 100644
--- a/src/l2_packet/l2_packet_pcap.c
+++ b/src/l2_packet/l2_packet_pcap.c
@@ -312,6 +312,18 @@
 }
 
 
+struct l2_packet_data * l2_packet_init_bridge(
+	const char *br_ifname, const char *ifname, const u8 *own_addr,
+	unsigned short protocol,
+	void (*rx_callback)(void *ctx, const u8 *src_addr,
+			    const u8 *buf, size_t len),
+	void *rx_callback_ctx, int l2_hdr)
+{
+	return l2_packet_init(br_ifname, own_addr, protocol, rx_callback,
+			      rx_callback_ctx, l2_hdr);
+}
+
+
 void l2_packet_deinit(struct l2_packet_data *l2)
 {
 	if (l2 == NULL)
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index d901169..d28b4cd 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -1221,9 +1221,14 @@
 
 	p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING;
 	p2p_clear_timeout(p2p);
+	if (p2p->pending_listen_freq) {
+		p2p_dbg(p2p, "Clear pending_listen_freq for p2p_find");
+		p2p->pending_listen_freq = 0;
+	}
 	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
 	p2p->find_type = type;
 	p2p_device_clear_reported(p2p);
+	os_memset(p2p->sd_query_no_ack, 0, ETH_ALEN);
 	p2p_set_state(p2p, P2P_SEARCH);
 	p2p->search_delay = search_delay;
 	p2p->in_search_delay = 0;
@@ -3159,13 +3164,18 @@
 
 static int p2p_pre_find_operation(struct p2p_data *p2p, struct p2p_device *dev)
 {
+	int res;
+
 	if (dev->sd_pending_bcast_queries == 0) {
 		/* Initialize with total number of registered broadcast
 		 * SD queries. */
 		dev->sd_pending_bcast_queries = p2p->num_p2p_sd_queries;
 	}
 
-	if (p2p_start_sd(p2p, dev) == 0)
+	res = p2p_start_sd(p2p, dev);
+	if (res == -2)
+		return -2;
+	if (res == 0)
 		return 1;
 
 	if (dev->req_config_methods &&
@@ -3185,7 +3195,7 @@
 void p2p_continue_find(struct p2p_data *p2p)
 {
 	struct p2p_device *dev;
-	int found;
+	int found, res;
 
 	p2p_set_state(p2p, P2P_SEARCH);
 
@@ -3198,10 +3208,13 @@
 		}
 		if (!found)
 			continue;
-		if (p2p_pre_find_operation(p2p, dev) > 0) {
+		res = p2p_pre_find_operation(p2p, dev);
+		if (res > 0) {
 			p2p->last_p2p_find_oper = dev;
 			return;
 		}
+		if (res == -2)
+			goto skip_sd;
 	}
 
 	/*
@@ -3209,14 +3222,19 @@
 	 * iteration device.
 	 */
 	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
-		if (p2p_pre_find_operation(p2p, dev) > 0) {
+		res = p2p_pre_find_operation(p2p, dev);
+		if (res > 0) {
 			p2p->last_p2p_find_oper = dev;
 			return;
 		}
+		if (res == -2)
+			goto skip_sd;
 		if (dev == p2p->last_p2p_find_oper)
 			break;
 	}
 
+skip_sd:
+	os_memset(p2p->sd_query_no_ack, 0, ETH_ALEN);
 	p2p_listen_in_find(p2p, 1);
 }
 
@@ -3228,8 +3246,17 @@
 	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
 
 	if (!success) {
-		if (p2p->sd_peer)
+		if (p2p->sd_peer) {
+			if (is_zero_ether_addr(p2p->sd_query_no_ack)) {
+				os_memcpy(p2p->sd_query_no_ack,
+					  p2p->sd_peer->info.p2p_device_addr,
+					  ETH_ALEN);
+				p2p_dbg(p2p,
+					"First SD Query no-ACK in this search iteration: "
+					MACSTR, MAC2STR(p2p->sd_query_no_ack));
+			}
 			p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
+		}
 		p2p->sd_peer = NULL;
 		if (p2p->state != P2P_IDLE)
 			p2p_continue_find(p2p);
@@ -3354,7 +3381,7 @@
 				NULL, p2p->p2ps_prov->adv_id,
 				p2p->p2ps_prov->session_id,
 				0, 0, NULL, 0, 0, 0,
-				NULL, NULL, 0, 0);
+				NULL, NULL, 0, 0, NULL, 0);
 		}
 
 		if (p2p->user_initiated_pd)
@@ -3438,9 +3465,11 @@
 		 * operation was started.
 		 */
 		p2p_dbg(p2p, "Ignore old scan result for " MACSTR
-			" (rx_time=%u.%06u)",
+			" (rx_time=%u.%06u find_start=%u.%06u)",
 			MAC2STR(bssid), (unsigned int) rx_time->sec,
-			(unsigned int) rx_time->usec);
+			(unsigned int) rx_time->usec,
+			(unsigned int) p2p->find_start.sec,
+			(unsigned int) p2p->find_start.usec);
 		return 0;
 	}
 
diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h
index bfdb2c9..244fca4 100644
--- a/src/p2p/p2p.h
+++ b/src/p2p/p2p.h
@@ -1074,7 +1074,8 @@
 				   size_t persist_ssid_size, int response_done,
 				   int prov_start, const char *session_info,
 				   const u8 *feat_cap, size_t feat_cap_len,
-				   unsigned int freq);
+				   unsigned int freq, const u8 *group_ssid,
+				   size_t group_ssid_len);
 
 	/**
 	 * prov_disc_resp_cb - Callback for indicating completion of PD Response
diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h
index 7f65ace..47524d4 100644
--- a/src/p2p/p2p_i.h
+++ b/src/p2p/p2p_i.h
@@ -308,6 +308,18 @@
 	 */
 	int num_p2p_sd_queries;
 
+	/**
+	 * sd_query_no_ack - The first peer (Dev Addr) that did not ACK SD Query
+	 *
+	 * This is used to track the first peer that did not ACK an SD Query
+	 * within a single P2P Search iteration. All zeros address means no such
+	 * peer was yet seen. This information is used to allow a new Listen and
+	 * Search phases to be once every pending SD Query has been sent once to
+	 * each peer instead of looping all pending attempts continuously until
+	 * running out of retry maximums.
+	 */
+	u8 sd_query_no_ack[ETH_ALEN];
+
 	/* GO Negotiation data */
 
 	/**
diff --git a/src/p2p/p2p_pd.c b/src/p2p/p2p_pd.c
index c416ab6..d70a43c 100644
--- a/src/p2p/p2p_pd.c
+++ b/src/p2p/p2p_pd.c
@@ -1028,7 +1028,8 @@
 					     NULL, adv_id, session_id,
 					     0, 0, msg.persistent_ssid,
 					     msg.persistent_ssid_len,
-					     0, 0, NULL, NULL, 0, freq);
+					     0, 0, NULL, NULL, 0, freq,
+					     NULL, 0);
 	} else if (msg.status && *msg.status == P2P_SC_SUCCESS_DEFERRED &&
 		   p2p->p2ps_prov) {
 		p2p->p2ps_prov->status = reject;
@@ -1041,7 +1042,8 @@
 						     session_id, conncap, 0,
 						     msg.persistent_ssid,
 						     msg.persistent_ssid_len, 0,
-						     0, NULL, NULL, 0, freq);
+						     0, NULL, NULL, 0, freq,
+						     NULL, 0);
 		else
 			p2p->cfg->p2ps_prov_complete(p2p->cfg->cb_ctx,
 						     *msg.status,
@@ -1053,7 +1055,8 @@
 						     msg.persistent_ssid_len, 0,
 						     0, NULL,
 						     (const u8 *) &resp_fcap,
-						     sizeof(resp_fcap), freq);
+						     sizeof(resp_fcap), freq,
+						     NULL, 0);
 	} else if (msg.status && p2p->p2ps_prov) {
 		p2p->p2ps_prov->status = P2P_SC_SUCCESS;
 		p2p->cfg->p2ps_prov_complete(p2p->cfg->cb_ctx, *msg.status, sa,
@@ -1064,7 +1067,7 @@
 					     msg.persistent_ssid_len,
 					     0, 0, NULL,
 					     (const u8 *) &resp_fcap,
-					     sizeof(resp_fcap), freq);
+					     sizeof(resp_fcap), freq, NULL, 0);
 	} else if (msg.status) {
 	} else if (auto_accept && reject == P2P_SC_SUCCESS) {
 		p2p->cfg->p2ps_prov_complete(p2p->cfg->cb_ctx, P2P_SC_SUCCESS,
@@ -1075,7 +1078,11 @@
 					     msg.persistent_ssid_len,
 					     0, 0, NULL,
 					     (const u8 *) &resp_fcap,
-					     sizeof(resp_fcap), freq);
+					     sizeof(resp_fcap), freq,
+					     msg.group_id ?
+					     msg.group_id + ETH_ALEN : NULL,
+					     msg.group_id ?
+					     msg.group_id_len - ETH_ALEN : 0);
 	} else if (reject == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE &&
 		   (!msg.session_info || !msg.session_info_len)) {
 		p2p->p2ps_prov->method = msg.wps_config_methods;
@@ -1088,7 +1095,7 @@
 					     msg.persistent_ssid_len,
 					     0, 1, NULL,
 					     (const u8 *) &resp_fcap,
-					     sizeof(resp_fcap), freq);
+					     sizeof(resp_fcap), freq, NULL, 0);
 	} else if (reject == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE) {
 		size_t buf_len = msg.session_info_len;
 		char *buf = os_malloc(2 * buf_len + 1);
@@ -1106,7 +1113,7 @@
 				msg.persistent_ssid, msg.persistent_ssid_len,
 				0, 1, buf,
 				(const u8 *) &resp_fcap, sizeof(resp_fcap),
-				freq);
+				freq, NULL, 0);
 
 			os_free(buf);
 		}
@@ -1468,7 +1475,9 @@
 				group_mac, adv_id, p2p->p2ps_prov->session_id,
 				conncap, passwd_id, msg.persistent_ssid,
 				msg.persistent_ssid_len, 1, 0, NULL,
-				msg.feature_cap, msg.feature_cap_len, freq);
+				msg.feature_cap, msg.feature_cap_len, freq,
+				msg.group_id ? msg.group_id + ETH_ALEN : NULL,
+				msg.group_id ? msg.group_id_len - ETH_ALEN : 0);
 		}
 		p2ps_prov_free(p2p);
 	} else if (status != P2P_SC_SUCCESS &&
@@ -1479,7 +1488,7 @@
 				p2p->cfg->cb_ctx, status, sa, adv_mac,
 				p2p->p2ps_prov->session_mac,
 				group_mac, adv_id, p2p->p2ps_prov->session_id,
-				0, 0, NULL, 0, 1, 0, NULL, NULL, 0, 0);
+				0, 0, NULL, 0, 1, 0, NULL, NULL, 0, 0, NULL, 0);
 		p2ps_prov_free(p2p);
 	}
 
diff --git a/src/p2p/p2p_sd.c b/src/p2p/p2p_sd.c
index 559af9d..2ef4c51 100644
--- a/src/p2p/p2p_sd.c
+++ b/src/p2p/p2p_sd.c
@@ -288,6 +288,14 @@
 	query = p2p_pending_sd_req(p2p, dev);
 	if (query == NULL)
 		return -1;
+	if (p2p->state == P2P_SEARCH &&
+	    os_memcmp(p2p->sd_query_no_ack, dev->info.p2p_device_addr,
+		      ETH_ALEN) == 0) {
+		p2p_dbg(p2p, "Do not start Service Discovery with " MACSTR
+			" due to it being the first no-ACK peer in this search iteration",
+			MAC2STR(dev->info.p2p_device_addr));
+		return -2;
+	}
 
 	p2p_dbg(p2p, "Start Service Discovery with " MACSTR,
 		MAC2STR(dev->info.p2p_device_addr));
diff --git a/src/wps/wps.c b/src/wps/wps.c
index fbaf85a..7c6dcb2 100644
--- a/src/wps/wps.c
+++ b/src/wps/wps.c
@@ -19,6 +19,10 @@
 int wps_version_number = 0x20;
 int wps_testing_dummy_cred = 0;
 int wps_corrupt_pkhash = 0;
+int wps_force_auth_types_in_use = 0;
+u16 wps_force_auth_types = 0;
+int wps_force_encr_types_in_use = 0;
+u16 wps_force_encr_types = 0;
 #endif /* CONFIG_WPS_TESTING */
 
 
diff --git a/src/wps/wps.h b/src/wps/wps.h
index 2c91d16..ff4dd10 100644
--- a/src/wps/wps.h
+++ b/src/wps/wps.h
@@ -1,6 +1,6 @@
 /*
  * Wi-Fi Protected Setup
- * Copyright (c) 2007-2013, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2007-2016, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -664,6 +664,16 @@
 	u16 encr_types;
 
 	/**
+	 * encr_types_rsn - Enabled encryption types for RSN (WPS_ENCR_*)
+	 */
+	u16 encr_types_rsn;
+
+	/**
+	 * encr_types_wpa - Enabled encryption types for WPA (WPS_ENCR_*)
+	 */
+	u16 encr_types_wpa;
+
+	/**
 	 * auth_types - Authentication types (bit field of WPS_AUTH_*)
 	 */
 	u16 auth_types;
diff --git a/src/wps/wps_attr_build.c b/src/wps/wps_attr_build.c
index b689357..748620f 100644
--- a/src/wps/wps_attr_build.c
+++ b/src/wps/wps_attr_build.c
@@ -1,6 +1,6 @@
 /*
  * Wi-Fi Protected Setup - attribute building
- * Copyright (c) 2008, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2008-2016, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -298,7 +298,16 @@
 	auth_types &= ~WPS_AUTH_WPA;
 	auth_types &= ~WPS_AUTH_WPA2;
 	auth_types &= ~WPS_AUTH_SHARED;
-	wpa_printf(MSG_DEBUG, "WPS:  * Authentication Type Flags");
+#ifdef CONFIG_WPS_TESTING
+	if (wps_force_auth_types_in_use) {
+		wpa_printf(MSG_DEBUG,
+			   "WPS: Testing - replace auth type 0x%x with 0x%x",
+			   auth_types, wps_force_auth_types);
+		auth_types = wps_force_auth_types;
+	}
+#endif /* CONFIG_WPS_TESTING */
+	wpa_printf(MSG_DEBUG, "WPS:  * Authentication Type Flags (0x%x)",
+		   auth_types);
 	wpabuf_put_be16(msg, ATTR_AUTH_TYPE_FLAGS);
 	wpabuf_put_be16(msg, 2);
 	wpabuf_put_be16(msg, auth_types);
@@ -310,7 +319,16 @@
 {
 	u16 encr_types = WPS_ENCR_TYPES;
 	encr_types &= ~WPS_ENCR_WEP;
-	wpa_printf(MSG_DEBUG, "WPS:  * Encryption Type Flags");
+#ifdef CONFIG_WPS_TESTING
+	if (wps_force_encr_types_in_use) {
+		wpa_printf(MSG_DEBUG,
+			   "WPS: Testing - replace encr type 0x%x with 0x%x",
+			   encr_types, wps_force_encr_types);
+		encr_types = wps_force_encr_types;
+	}
+#endif /* CONFIG_WPS_TESTING */
+	wpa_printf(MSG_DEBUG, "WPS:  * Encryption Type Flags (0x%x)",
+		   encr_types);
 	wpabuf_put_be16(msg, ATTR_ENCR_TYPE_FLAGS);
 	wpabuf_put_be16(msg, 2);
 	wpabuf_put_be16(msg, encr_types);
diff --git a/src/wps/wps_defs.h b/src/wps/wps_defs.h
index a23b979..301864d 100644
--- a/src/wps/wps_defs.h
+++ b/src/wps/wps_defs.h
@@ -14,6 +14,10 @@
 extern int wps_version_number;
 extern int wps_testing_dummy_cred;
 extern int wps_corrupt_pkhash;
+extern int wps_force_auth_types_in_use;
+extern u16 wps_force_auth_types;
+extern int wps_force_encr_types_in_use;
+extern u16 wps_force_encr_types;
 #define WPS_VERSION wps_version_number
 
 #else /* CONFIG_WPS_TESTING */
diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c
index 4ca3a42..25e88d5 100644
--- a/src/wps/wps_registrar.c
+++ b/src/wps/wps_registrar.c
@@ -1,6 +1,6 @@
 /*
  * Wi-Fi Protected Setup - Registrar
- * Copyright (c) 2008-2013, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2008-2016, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -1606,6 +1606,9 @@
 	wps->cred.ssid_len = wps->wps->ssid_len;
 
 	/* Select the best authentication and encryption type */
+	wpa_printf(MSG_DEBUG,
+		   "WPS: Own auth types 0x%x - masked Enrollee auth types 0x%x",
+		   wps->wps->auth_types, wps->auth_type);
 	if (wps->auth_type & WPS_AUTH_WPA2PSK)
 		wps->auth_type = WPS_AUTH_WPA2PSK;
 	else if (wps->auth_type & WPS_AUTH_WPAPSK)
@@ -1619,6 +1622,14 @@
 	}
 	wps->cred.auth_type = wps->auth_type;
 
+	wpa_printf(MSG_DEBUG,
+		   "WPS: Own encr types 0x%x (rsn: 0x%x, wpa: 0x%x) - masked Enrollee encr types 0x%x",
+		   wps->wps->encr_types, wps->wps->encr_types_rsn,
+		   wps->wps->encr_types_wpa, wps->encr_type);
+	if (wps->wps->ap && wps->auth_type == WPS_AUTH_WPA2PSK)
+		wps->encr_type &= wps->wps->encr_types_rsn;
+	else if (wps->wps->ap && wps->auth_type == WPS_AUTH_WPAPSK)
+		wps->encr_type &= wps->wps->encr_types_wpa;
 	if (wps->auth_type == WPS_AUTH_WPA2PSK ||
 	    wps->auth_type == WPS_AUTH_WPAPSK) {
 		if (wps->encr_type & WPS_ENCR_AES)
@@ -2343,6 +2354,23 @@
 
 	wpa_printf(MSG_DEBUG, "WPS: Enrollee Authentication Type flags 0x%x",
 		   auth_types);
+#ifdef WPS_WORKAROUNDS
+	/*
+	 * Some deployed implementations seem to advertise incorrect information
+	 * in this attribute. A value of 0x1b (WPA2 + WPA + WPAPSK + OPEN, but
+	 * no WPA2PSK) has been reported to be used. Add WPA2PSK to the list to
+	 * avoid issues with building Credentials that do not use the strongest
+	 * actually supported authentication option (that device does support
+	 * WPA2PSK even when it does not claim it here).
+	 */
+	if ((auth_types &
+	     (WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK)) ==
+	    (WPS_AUTH_WPA2 | WPS_AUTH_WPAPSK)) {
+		wpa_printf(MSG_DEBUG,
+			   "WPS: Workaround - assume Enrollee supports WPA2PSK based on claimed WPA2 support");
+		auth_types |= WPS_AUTH_WPA2PSK;
+	}
+#endif /* WPS_WORKAROUNDS */
 	wps->auth_type = wps->wps->auth_types & auth_types;
 	if (wps->auth_type == 0) {
 		wpa_printf(MSG_DEBUG, "WPS: No match in supported "