Cumulative patch from commit 324ade51e168f28430f4429849becd0f08d507c0 (DO NOT MERGE)

324ade5 TLS: Make tls_cert_chain_failure_event() more robust
c6231b5 TLS: Remove storing of never-read value
15a6813 Remove unnecessary cleanup assignment in SHA1Final()
ef3866a nl80211: Don't call linux_iface_up() for a dedicated P2P Device
c2ed779 mesh: Document Mesh Peering Management element structure in more detail
b2817cd mesh: Check PMKID in AMPE Action frames
6c33eed mesh: Fix PMKID to match the standard
ede7770 wpa_supplicant: Do not wait for monitor on P2P Device interface
1c94570 Do not wait for monitor to attach if no control interface
f98674a Clone default LIBS value to LIBS_* for other tools
7d2f674 Add "GET_CAPABILITY acs" to allow ACS build option to be detected
d990971 wpa_supplicant: Enable Automatic Channel Selection support for AP mode
96bc508 Handle survey event properly in wpa_supplicant
d39f796 EAP-TNC peer: Remove dead code related to fragmentation
662512e P2PS: Remove dead code
abbbaa4 TNC: Print received IF-TNCCS message as debug ASCII hexdump
d745f02 EAP-TNC peer: Allow fragment_size to be configured
a67e7e5 RADIUS: Add EACCES to list of recognized send() errno values
5bd9be4 Fix RADIUS Called-Station-Id to not escape SSID
0764dd6 TLS client: Multi-OCSP check to cover intermediate CAs
d6b536f Add ocsp=3 configuration parameter for multi-OCSP
0268383 TLS: Move variable declaration to the beginning of the block
b567775 TLS client: OCSP stapling with ocsp_multi option (RFC 6961)
8ea6a27 TLS server: OCSP stapling with ocsp_multi option (RFC 6961)
5addb0d Server configuration for OCSP stapling with ocsp_multi (RFC 6961)
bca0872 TLS server: OCSP stapling
9532bd2 GnuTLS: OCSP stapling on the server side
6241766 Use wpa_msg() for the "RSN: PMKID mismatch" message
e161451 EAP-EKE: Merge identical error return paths
13cb0a6 EAP-EKE: Reject too long Prot() data when building a frame
0ab0de8 Document previously missing key_mgmt values

Change-Id: I9ac7d0da03d8baf4542e276ab20cb56e44bfa33c
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/hostapd/Makefile b/hostapd/Makefile
index fa5435d..45afedf 100644
--- a/hostapd/Makefile
+++ b/hostapd/Makefile
@@ -6,6 +6,21 @@
 CFLAGS = -MMD -O2 -Wall -g
 endif
 
+ifdef LIBS
+# If LIBS is set with some global build system defaults, clone those for
+# LIBS_c, LIBS_h, and LIBS_n to cover hostapd_cli, hlr_auc_gw, and
+# nt_password_hash as well.
+ifndef LIBS_c
+LIBS_c := $(LIBS)
+endif
+ifndef LIBS_h
+LIBS_h := $(LIBS)
+endif
+ifndef LIBS_n
+LIBS_n := $(LIBS)
+endif
+endif
+
 CFLAGS += $(EXTRA_CFLAGS)
 CFLAGS += -I$(abspath ../src)
 CFLAGS += -I$(abspath ../src/utils)
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index f2163b8..503d479 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -2132,6 +2132,9 @@
 	} else if (os_strcmp(buf, "ocsp_stapling_response") == 0) {
 		os_free(bss->ocsp_stapling_response);
 		bss->ocsp_stapling_response = os_strdup(pos);
+	} else if (os_strcmp(buf, "ocsp_stapling_response_multi") == 0) {
+		os_free(bss->ocsp_stapling_response_multi);
+		bss->ocsp_stapling_response_multi = os_strdup(pos);
 	} else if (os_strcmp(buf, "dh_file") == 0) {
 		os_free(bss->dh_file);
 		bss->dh_file = os_strdup(pos);
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index 4f51140..ecd4328 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -795,6 +795,11 @@
 #	-respout /tmp/ocsp-cache.der
 #ocsp_stapling_response=/tmp/ocsp-cache.der
 
+# Cached OCSP stapling response list (DER encoded OCSPResponseList)
+# This is similar to ocsp_stapling_response, but the extended version defined in
+# RFC 6961 to allow multiple OCSP responses to be provided.
+#ocsp_stapling_response_multi=/tmp/ocsp-multi-cache.der
+
 # dh_file: File path to DH/DSA parameters file (in PEM format)
 # This is an optional configuration file for setting parameters for an
 # ephemeral DH key exchange. In most cases, the default RSA authentication does
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index cf9b2ce..88074f2 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -471,6 +471,7 @@
 	os_free(conf->private_key);
 	os_free(conf->private_key_passwd);
 	os_free(conf->ocsp_stapling_response);
+	os_free(conf->ocsp_stapling_response_multi);
 	os_free(conf->dh_file);
 	os_free(conf->openssl_ciphers);
 	os_free(conf->pac_opaque_encr_key);
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index ff9dcb0..44bcccc 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -341,6 +341,7 @@
 	int check_crl;
 	unsigned int tls_session_lifetime;
 	char *ocsp_stapling_response;
+	char *ocsp_stapling_response_multi;
 	char *dh_file;
 	char *openssl_ciphers;
 	u8 *pac_opaque_encr_key;
diff --git a/src/ap/authsrv.c b/src/ap/authsrv.c
index c9111f6..cdb49cd 100644
--- a/src/ap/authsrv.c
+++ b/src/ap/authsrv.c
@@ -173,6 +173,8 @@
 		params.openssl_ciphers = hapd->conf->openssl_ciphers;
 		params.ocsp_stapling_response =
 			hapd->conf->ocsp_stapling_response;
+		params.ocsp_stapling_response_multi =
+			hapd->conf->ocsp_stapling_response_multi;
 
 		if (tls_global_set_params(hapd->ssl_ctx, &params)) {
 			wpa_printf(MSG_ERROR, "Failed to set TLS parameters");
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index fd07201..aad0d81 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -549,8 +549,8 @@
 
 
 #ifdef CONFIG_ACS
-static void hostapd_acs_channel_selected(struct hostapd_data *hapd,
-					 struct acs_selected_channels *acs_res)
+void hostapd_acs_channel_selected(struct hostapd_data *hapd,
+				  struct acs_selected_channels *acs_res)
 {
 	int ret, i;
 
@@ -945,6 +945,8 @@
 	ieee802_1x_receive(hapd, src, data, data_len);
 }
 
+#endif /* HOSTAPD */
+
 
 static struct hostapd_channel_data * hostapd_get_mode_channel(
 	struct hostapd_iface *iface, unsigned int freq)
@@ -1019,10 +1021,9 @@
 }
 
 
-static void hostapd_event_get_survey(struct hostapd_data *hapd,
-				     struct survey_results *survey_results)
+void hostapd_event_get_survey(struct hostapd_iface *iface,
+			      struct survey_results *survey_results)
 {
-	struct hostapd_iface *iface = hapd->iface;
 	struct freq_survey *survey, *tmp;
 	struct hostapd_channel_data *chan;
 
@@ -1054,6 +1055,7 @@
 }
 
 
+#ifdef HOSTAPD
 #ifdef NEED_AP_MLME
 
 static void hostapd_event_iface_unavailable(struct hostapd_data *hapd)
@@ -1261,7 +1263,7 @@
 			data->connect_failed_reason.code);
 		break;
 	case EVENT_SURVEY:
-		hostapd_event_get_survey(hapd, &data->survey_results);
+		hostapd_event_get_survey(hapd->iface, &data->survey_results);
 		break;
 #ifdef NEED_AP_MLME
 	case EVENT_INTERFACE_UNAVAILABLE:
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index 8161a59..7b59f80 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -493,6 +493,11 @@
 			 int ssi_signal);
 void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
 			     int offset, int width, int cf1, int cf2);
+struct survey_results;
+void hostapd_event_get_survey(struct hostapd_iface *iface,
+			      struct survey_results *survey_results);
+void hostapd_acs_channel_selected(struct hostapd_data *hapd,
+				  struct acs_selected_channels *acs_res);
 
 const struct hostapd_eap_user *
 hostapd_get_eap_user(struct hostapd_data *hapd, const u8 *identity,
diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c
index f566603..e3b3d94 100644
--- a/src/ap/ieee802_1x.c
+++ b/src/ap/ieee802_1x.c
@@ -475,6 +475,7 @@
 {
 	char buf[128];
 	struct hostapd_radius_attr *attr;
+	int len;
 
 	if (!hostapd_config_get_radius_attr(req_attr,
 					    RADIUS_ATTR_NAS_IP_ADDRESS) &&
@@ -506,15 +507,15 @@
 		return -1;
 	}
 
-	os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT ":%s",
-		    MAC2STR(hapd->own_addr),
-		    wpa_ssid_txt(hapd->conf->ssid.ssid,
-				 hapd->conf->ssid.ssid_len));
-	buf[sizeof(buf) - 1] = '\0';
+	len = os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT ":",
+			  MAC2STR(hapd->own_addr));
+	os_memcpy(&buf[len], hapd->conf->ssid.ssid,
+		  hapd->conf->ssid.ssid_len);
+	len += hapd->conf->ssid.ssid_len;
 	if (!hostapd_config_get_radius_attr(req_attr,
 					    RADIUS_ATTR_CALLED_STATION_ID) &&
 	    !radius_msg_add_attr(msg, RADIUS_ATTR_CALLED_STATION_ID,
-				 (u8 *) buf, os_strlen(buf))) {
+				 (u8 *) buf, len)) {
 		wpa_printf(MSG_ERROR, "Could not add Called-Station-Id");
 		return -1;
 	}
diff --git a/src/common/sae.c b/src/common/sae.c
index b962ea2..6c00a7e 100644
--- a/src/common/sae.c
+++ b/src/common/sae.c
@@ -816,6 +816,7 @@
 	os_memset(keyseed, 0, sizeof(keyseed));
 	os_memcpy(sae->tmp->kck, keys, SAE_KCK_LEN);
 	os_memcpy(sae->pmk, keys + SAE_KCK_LEN, SAE_PMK_LEN);
+	os_memcpy(sae->pmkid, val, SAE_PMKID_LEN);
 	os_memset(keys, 0, sizeof(keys));
 	wpa_hexdump_key(MSG_DEBUG, "SAE: KCK", sae->tmp->kck, SAE_KCK_LEN);
 	wpa_hexdump_key(MSG_DEBUG, "SAE: PMK", sae->pmk, SAE_PMK_LEN);
diff --git a/src/common/sae.h b/src/common/sae.h
index c07026c..a4270bc 100644
--- a/src/common/sae.h
+++ b/src/common/sae.h
@@ -45,6 +45,7 @@
 	enum { SAE_NOTHING, SAE_COMMITTED, SAE_CONFIRMED, SAE_ACCEPTED } state;
 	u16 send_confirm;
 	u8 pmk[SAE_PMK_LEN];
+	u8 pmkid[SAE_PMKID_LEN];
 	struct crypto_bignum *peer_commit_scalar;
 	int group;
 	int sync;
diff --git a/src/crypto/sha1-internal.c b/src/crypto/sha1-internal.c
index f6658e6..ffcba66 100644
--- a/src/crypto/sha1-internal.c
+++ b/src/crypto/sha1-internal.c
@@ -297,7 +297,6 @@
 			 255);
 	}
 	/* Wipe variables */
-	i = 0;
 	os_memset(context->buffer, 0, 64);
 	os_memset(context->state, 0, 20);
 	os_memset(context->count, 0, 8);
diff --git a/src/crypto/tls.h b/src/crypto/tls.h
index bca94d6..453b4de 100644
--- a/src/crypto/tls.h
+++ b/src/crypto/tls.h
@@ -96,6 +96,7 @@
 #define TLS_CONN_EAP_FAST BIT(7)
 #define TLS_CONN_DISABLE_TLSv1_0 BIT(8)
 #define TLS_CONN_EXT_CERT_CHECK BIT(9)
+#define TLS_CONN_REQUIRE_OCSP_ALL BIT(10)
 
 /**
  * struct tls_connection_params - Parameters for TLS connection
@@ -140,6 +141,9 @@
  * @flags: Parameter options (TLS_CONN_*)
  * @ocsp_stapling_response: DER encoded file with cached OCSP stapling response
  *	or %NULL if OCSP is not enabled
+ * @ocsp_stapling_response_multi: DER encoded file with cached OCSP stapling
+ *	response list (OCSPResponseList for ocsp_multi in RFC 6961) or %NULL if
+ *	ocsp_multi is not enabled
  *
  * TLS connection parameters to be configured with tls_connection_set_params()
  * and tls_global_set_params().
@@ -180,6 +184,7 @@
 
 	unsigned int flags;
 	const char *ocsp_stapling_response;
+	const char *ocsp_stapling_response_multi;
 };
 
 
diff --git a/src/crypto/tls_gnutls.c b/src/crypto/tls_gnutls.c
index b1bec4a..c4cd3c1 100644
--- a/src/crypto/tls_gnutls.c
+++ b/src/crypto/tls_gnutls.c
@@ -37,6 +37,8 @@
 			 union tls_event_data *data);
 	void *cb_ctx;
 	int cert_in_cb;
+
+	char *ocsp_stapling_response;
 };
 
 struct tls_connection {
@@ -133,6 +135,7 @@
 		if (global->params_set)
 			gnutls_certificate_free_credentials(global->xcred);
 		os_free(global->session_data);
+		os_free(global->ocsp_stapling_response);
 		os_free(global);
 	}
 
@@ -347,6 +350,12 @@
 	if (conn == NULL || params == NULL)
 		return -1;
 
+	if (params->flags & TLS_CONN_REQUIRE_OCSP_ALL) {
+		wpa_printf(MSG_INFO,
+			   "GnuTLS: ocsp=3 not supported");
+		return -1;
+	}
+
 	if (params->flags & TLS_CONN_EXT_CERT_CHECK) {
 		wpa_printf(MSG_INFO,
 			   "GnuTLS: tls_ext_cert_check=1 not supported");
@@ -602,6 +611,44 @@
 }
 
 
+#if GNUTLS_VERSION_NUMBER >= 0x030103
+static int server_ocsp_status_req(gnutls_session_t session, void *ptr,
+				  gnutls_datum_t *resp)
+{
+	struct tls_global *global = ptr;
+	char *cached;
+	size_t len;
+
+	if (!global->ocsp_stapling_response) {
+		wpa_printf(MSG_DEBUG, "GnuTLS: OCSP status callback - no response configured");
+		return GNUTLS_E_NO_CERTIFICATE_STATUS;
+	}
+
+	cached = os_readfile(global->ocsp_stapling_response, &len);
+	if (!cached) {
+		wpa_printf(MSG_DEBUG,
+			   "GnuTLS: OCSP status callback - could not read response file (%s)",
+			   global->ocsp_stapling_response);
+		return GNUTLS_E_NO_CERTIFICATE_STATUS;
+	}
+
+	wpa_printf(MSG_DEBUG,
+		   "GnuTLS: OCSP status callback - send cached response");
+	resp->data = gnutls_malloc(len);
+	if (!resp->data) {
+		os_free(resp);
+		return GNUTLS_E_MEMORY_ERROR;
+	}
+
+	os_memcpy(resp->data, cached, len);
+	resp->size = len;
+	os_free(cached);
+
+	return GNUTLS_E_SUCCESS;
+}
+#endif /* 3.1.3 */
+
+
 int tls_global_set_params(void *tls_ctx,
 			  const struct tls_connection_params *params)
 {
@@ -696,6 +743,17 @@
 		}
 	}
 
+#if GNUTLS_VERSION_NUMBER >= 0x030103
+	os_free(global->ocsp_stapling_response);
+	if (params->ocsp_stapling_response)
+		global->ocsp_stapling_response =
+			os_strdup(params->ocsp_stapling_response);
+	else
+		global->ocsp_stapling_response = NULL;
+	gnutls_certificate_set_ocsp_status_request_function(
+		global->xcred, server_ocsp_status_req, global);
+#endif /* 3.1.3 */
+
 	global->params_set = 1;
 
 	return 0;
diff --git a/src/crypto/tls_internal.c b/src/crypto/tls_internal.c
index 8b90d56..01a7c97 100644
--- a/src/crypto/tls_internal.c
+++ b/src/crypto/tls_internal.c
@@ -331,6 +331,13 @@
 		return -1;
 	}
 
+	if (params->ocsp_stapling_response)
+		cred->ocsp_stapling_response =
+			os_strdup(params->ocsp_stapling_response);
+	if (params->ocsp_stapling_response_multi)
+		cred->ocsp_stapling_response_multi =
+			os_strdup(params->ocsp_stapling_response_multi);
+
 	return 0;
 #else /* CONFIG_TLS_INTERNAL_SERVER */
 	return -1;
diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c
index 1d75ba7..62277c4 100644
--- a/src/crypto/tls_openssl.c
+++ b/src/crypto/tls_openssl.c
@@ -3890,6 +3890,12 @@
 	if (conn == NULL)
 		return -1;
 
+	if (params->flags & TLS_CONN_REQUIRE_OCSP_ALL) {
+		wpa_printf(MSG_INFO,
+			   "OpenSSL: ocsp=3 not supported");
+		return -1;
+	}
+
 	/*
 	 * If the engine isn't explicitly configured, and any of the
 	 * cert/key fields are actually PKCS#11 URIs, then automatically
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index ed5e4a8..cdd1504 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -1735,9 +1735,6 @@
 	if (nl80211_init_bss(bss))
 		goto failed;
 
-	if (linux_iface_up(drv->global->ioctl_sock, ifname) > 0)
-		drv->start_iface_up = 1;
-
 	if (wpa_driver_nl80211_finish_drv_init(drv, set_addr, 1, driver_params))
 		goto failed;
 
@@ -2240,6 +2237,11 @@
 	if (!bss->if_dynamic && nl80211_get_ifmode(bss) == NL80211_IFTYPE_AP)
 		bss->static_ap = 1;
 
+	if (first &&
+	    nl80211_get_ifmode(bss) != NL80211_IFTYPE_P2P_DEVICE &&
+	    linux_iface_up(drv->global->ioctl_sock, bss->ifname) > 0)
+		drv->start_iface_up = 1;
+
 	if (wpa_driver_nl80211_capa(drv))
 		return -1;
 
diff --git a/src/eap_common/eap_eke_common.c b/src/eap_common/eap_eke_common.c
index 4dfdb3f..6217468 100644
--- a/src/eap_common/eap_eke_common.c
+++ b/src/eap_common/eap_eke_common.c
@@ -44,9 +44,7 @@
 	int dhlen;
 
 	dhlen = eap_eke_dh_len(dhgroup);
-	if (dhlen < 0)
-		return -1;
-	if (encr != EAP_EKE_ENCR_AES128_CBC)
+	if (dhlen < 0 || encr != EAP_EKE_ENCR_AES128_CBC)
 		return -1;
 	return AES_BLOCK_SIZE + dhlen;
 }
@@ -166,14 +164,11 @@
 	size_t pub_len, i;
 
 	generator = eap_eke_dh_generator(group);
-	if (generator < 0 || generator > 255)
+	dh = eap_eke_dh_group(group);
+	if (generator < 0 || generator > 255 || !dh)
 		return -1;
 	gen = generator;
 
-	dh = eap_eke_dh_group(group);
-	if (dh == NULL)
-		return -1;
-
 	/* x = random number 2 .. p-1 */
 	if (random_get_bytes(ret_priv, dh->prime_len))
 		return -1;
@@ -411,11 +406,8 @@
 	size_t len;
 	const struct dh_group *dh;
 
-	if (sess->encr != EAP_EKE_ENCR_AES128_CBC)
-		return -1;
-
 	dh = eap_eke_dh_group(sess->dhgroup);
-	if (dh == NULL)
+	if (sess->encr != EAP_EKE_ENCR_AES128_CBC || !dh)
 		return -1;
 
 	/* Decrypt peer DHComponent */
@@ -635,6 +627,7 @@
 
 	if (*prot_len < block_size + data_len + pad + icv_len) {
 		wpa_printf(MSG_INFO, "EAP-EKE: Not enough room for Prot() data");
+		return -1;
 	}
 	pos = prot;
 
@@ -653,10 +646,8 @@
 		pos += pad;
 	}
 
-	if (aes_128_cbc_encrypt(sess->ke, iv, e, data_len + pad) < 0)
-		return -1;
-
-	if (eap_eke_mac(sess->mac, sess->ki, e, data_len + pad, pos) < 0)
+	if (aes_128_cbc_encrypt(sess->ke, iv, e, data_len + pad) < 0 ||
+	    eap_eke_mac(sess->mac, sess->ki, e, data_len + pad, pos) < 0)
 		return -1;
 	pos += icv_len;
 
@@ -684,9 +675,8 @@
 	else
 		return -1;
 
-	if (prot_len < 2 * block_size + icv_len)
-		return -1;
-	if ((prot_len - icv_len) % block_size)
+	if (prot_len < 2 * block_size + icv_len ||
+	    (prot_len - icv_len) % block_size)
 		return -1;
 
 	if (eap_eke_mac(sess->mac, sess->ki, prot + block_size,
@@ -737,22 +727,14 @@
 	sess->mac = mac;
 
 	sess->prf_len = eap_eke_prf_len(prf);
-	if (sess->prf_len < 0)
-		return -1;
 	sess->nonce_len = eap_eke_nonce_len(prf);
-	if (sess->nonce_len < 0)
-		return -1;
 	sess->auth_len = eap_eke_auth_len(prf);
-	if (sess->auth_len < 0)
-		return -1;
 	sess->dhcomp_len = eap_eke_dhcomp_len(sess->dhgroup, sess->encr);
-	if (sess->dhcomp_len < 0)
-		return -1;
 	sess->pnonce_len = eap_eke_pnonce_len(sess->mac);
-	if (sess->pnonce_len < 0)
-		return -1;
 	sess->pnonce_ps_len = eap_eke_pnonce_ps_len(sess->mac);
-	if (sess->pnonce_ps_len < 0)
+	if (sess->prf_len < 0 || sess->nonce_len < 0 || sess->auth_len < 0 ||
+	    sess->dhcomp_len < 0 || sess->pnonce_len < 0 ||
+	    sess->pnonce_ps_len < 0)
 		return -1;
 
 	return 0;
diff --git a/src/eap_peer/eap_tls_common.c b/src/eap_peer/eap_tls_common.c
index c270832..406c162 100644
--- a/src/eap_peer/eap_tls_common.c
+++ b/src/eap_peer/eap_tls_common.c
@@ -196,8 +196,10 @@
 
 	if (config->ocsp)
 		params->flags |= TLS_CONN_REQUEST_OCSP;
-	if (config->ocsp == 2)
+	if (config->ocsp >= 2)
 		params->flags |= TLS_CONN_REQUIRE_OCSP;
+	if (config->ocsp == 3)
+		params->flags |= TLS_CONN_REQUIRE_OCSP_ALL;
 	data->conn = tls_connection_init(data->ssl_ctx);
 	if (data->conn == NULL) {
 		wpa_printf(MSG_INFO, "SSL: Failed to initialize new TLS "
diff --git a/src/eap_peer/eap_tnc.c b/src/eap_peer/eap_tnc.c
index 25b9f12..e4294bb 100644
--- a/src/eap_peer/eap_tnc.c
+++ b/src/eap_peer/eap_tnc.c
@@ -10,6 +10,7 @@
 
 #include "common.h"
 #include "eap_i.h"
+#include "eap_config.h"
 #include "tncc.h"
 
 
@@ -35,12 +36,16 @@
 static void * eap_tnc_init(struct eap_sm *sm)
 {
 	struct eap_tnc_data *data;
+	struct eap_peer_config *config = eap_get_config(sm);
 
 	data = os_zalloc(sizeof(*data));
 	if (data == NULL)
 		return NULL;
 	data->state = WAIT_START;
-	data->fragment_size = 1300;
+	if (config && config->fragment_size)
+		data->fragment_size = config->fragment_size;
+	else
+		data->fragment_size = 1300;
 	data->tncc = tncc_init();
 	if (data->tncc == NULL) {
 		os_free(data);
@@ -345,11 +350,6 @@
 	ret->decision = DECISION_UNCOND_SUCC;
 	ret->allowNotifications = TRUE;
 
-	if (data->out_buf) {
-		data->state = PROC_MSG;
-		return eap_tnc_build_msg(data, ret, id);
-	}
-
 	if (tncs_done) {
 		resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TNC, 1,
 				     EAP_CODE_RESPONSE, eap_get_id(reqData));
diff --git a/src/eap_peer/tncc.c b/src/eap_peer/tncc.c
index 7ca956e..9965513 100644
--- a/src/eap_peer/tncc.c
+++ b/src/eap_peer/tncc.c
@@ -694,6 +694,8 @@
 	enum tncc_process_res res = TNCCS_PROCESS_OK_NO_RECOMMENDATION;
 	int recommendation_msg = 0;
 
+	wpa_hexdump_ascii(MSG_MSGDUMP, "TNC: Received IF-TNCCS message",
+			  msg, len);
 	buf = dup_binstr(msg, len);
 	if (buf == NULL)
 		return TNCCS_PROCESS_ERROR;
diff --git a/src/radius/radius_client.c b/src/radius/radius_client.c
index 0bcdb45..b24bbf8 100644
--- a/src/radius/radius_client.c
+++ b/src/radius/radius_client.c
@@ -308,7 +308,7 @@
 	int _errno = errno;
 	wpa_printf(MSG_INFO, "send[RADIUS,s=%d]: %s", s, strerror(errno));
 	if (_errno == ENOTCONN || _errno == EDESTADDRREQ || _errno == EINVAL ||
-	    _errno == EBADF || _errno == ENETUNREACH) {
+	    _errno == EBADF || _errno == ENETUNREACH || _errno == EACCES) {
 		hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
 			       HOSTAPD_LEVEL_INFO,
 			       "Send failed - maybe interface status changed -"
diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
index 669f658..64ef933 100644
--- a/src/rsn_supp/wpa.c
+++ b/src/rsn_supp/wpa.c
@@ -270,7 +270,7 @@
 				 * much we can do here without knowing what
 				 * exactly caused the server to misbehave.
 				 */
-				wpa_dbg(sm->ctx->msg_ctx, MSG_INFO,
+				wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
 					"RSN: PMKID mismatch - authentication server may have derived different MSK?!");
 				return -1;
 			}
diff --git a/src/tls/tlsv1_client.c b/src/tls/tlsv1_client.c
index cc404c1..9bc0d21 100644
--- a/src/tls/tlsv1_client.c
+++ b/src/tls/tlsv1_client.c
@@ -111,7 +111,6 @@
 		pos += conn->rl.iv_size;
 		/* server_write_IV */
 		os_memcpy(conn->rl.read_iv, pos, conn->rl.iv_size);
-		pos += conn->rl.iv_size;
 	} else {
 		/*
 		 * Use IV field to set the mask value for TLS v1.1. A fixed
diff --git a/src/tls/tlsv1_client_ocsp.c b/src/tls/tlsv1_client_ocsp.c
index 2d5cdb9..1d7b68c 100644
--- a/src/tls/tlsv1_client_ocsp.c
+++ b/src/tls/tlsv1_client_ocsp.c
@@ -316,6 +316,7 @@
 
 static enum tls_ocsp_result
 tls_process_ocsp_responses(struct tlsv1_client *conn,
+			   struct x509_certificate *cert,
 			   struct x509_certificate *issuer, const u8 *resp,
 			   size_t len)
 {
@@ -335,8 +336,7 @@
 				   hdr.class, hdr.tag);
 			return TLS_OCSP_INVALID;
 		}
-		if (tls_process_ocsp_single_response(conn, conn->server_cert,
-						     issuer,
+		if (tls_process_ocsp_single_response(conn, cert, issuer,
 						     hdr.payload, hdr.length,
 						     &res) == 0)
 			return res;
@@ -350,8 +350,9 @@
 
 
 static enum tls_ocsp_result
-tls_process_basic_ocsp_response(struct tlsv1_client *conn, const u8 *resp,
-				size_t len)
+tls_process_basic_ocsp_response(struct tlsv1_client *conn,
+				struct x509_certificate *srv_cert,
+				const u8 *resp, size_t len)
 {
 	struct asn1_hdr hdr;
 	const u8 *pos, *end;
@@ -365,6 +366,7 @@
 	struct x509_name name; /* used if key_hash == NULL */
 	char buf[100];
 	os_time_t produced_at;
+	enum tls_ocsp_result res;
 
 	wpa_hexdump(MSG_MSGDUMP, "OCSP: BasicOCSPResponse", resp, len);
 
@@ -594,20 +596,20 @@
 		/* Ignore for now. */
 	}
 
-	if (!conn->server_cert) {
+	if (!srv_cert) {
 		wpa_printf(MSG_DEBUG,
 			   "OCSP: Server certificate not known - cannot check OCSP response");
 		goto no_resp;
 	}
 
-	if (conn->server_cert->next) {
+	if (srv_cert->next) {
 		/* Issuer has already been verified in the chain */
-		issuer = conn->server_cert->next;
+		issuer = srv_cert->next;
 	} else {
 		/* Find issuer from the set of trusted certificates */
 		for (issuer = conn->cred ? conn->cred->trusted_certs : NULL;
 		     issuer; issuer = issuer->next) {
-			if (x509_name_compare(&conn->server_cert->issuer,
+			if (x509_name_compare(&srv_cert->issuer,
 					      &issuer->subject) == 0)
 				break;
 		}
@@ -625,7 +627,7 @@
 	} else {
 		for (signer = certs; signer; signer = signer->next) {
 			if (!ocsp_responder_id_match(signer, &name, key_hash) ||
-			    x509_name_compare(&conn->server_cert->issuer,
+			    x509_name_compare(&srv_cert->issuer,
 					      &issuer->subject) != 0 ||
 			    !(signer->ext_key_usage &
 			      X509_EXT_KEY_USAGE_OCSP) ||
@@ -654,8 +656,13 @@
 		    return TLS_OCSP_INVALID;
 	}
 
-	return tls_process_ocsp_responses(conn, issuer, responses,
-					  responses_len);
+	res = tls_process_ocsp_responses(conn, srv_cert, issuer,
+					 responses, responses_len);
+	if (res == TLS_OCSP_REVOKED)
+		srv_cert->ocsp_revoked = 1;
+	else if (res == TLS_OCSP_GOOD)
+		srv_cert->ocsp_good = 1;
+	return res;
 
 no_resp:
 	x509_free_name(&name);
@@ -677,6 +684,9 @@
 	u8 resp_status;
 	struct asn1_oid oid;
 	char obuf[80];
+	struct x509_certificate *cert;
+	enum tls_ocsp_result res = TLS_OCSP_NO_RESPONSE;
+	enum tls_ocsp_result res_first = res;
 
 	wpa_hexdump(MSG_MSGDUMP, "TLSv1: OCSPResponse", resp, len);
 
@@ -769,5 +779,25 @@
 		return TLS_OCSP_INVALID;
 	}
 
-	return tls_process_basic_ocsp_response(conn, hdr.payload, hdr.length);
+	cert = conn->server_cert;
+	while (cert) {
+		if (!cert->ocsp_good && !cert->ocsp_revoked) {
+			char sbuf[128];
+
+			x509_name_string(&cert->subject, sbuf, sizeof(sbuf));
+			wpa_printf(MSG_DEBUG,
+				   "OCSP: Trying to find certificate status for %s",
+				   sbuf);
+
+			res = tls_process_basic_ocsp_response(conn, cert,
+							      hdr.payload,
+							      hdr.length);
+			if (cert == conn->server_cert)
+				res_first = res;
+		}
+		if (res == TLS_OCSP_REVOKED || cert->issuer_trusted)
+			break;
+		cert = cert->next;
+	}
+	return res == TLS_OCSP_REVOKED ? res : res_first;
 }
diff --git a/src/tls/tlsv1_client_read.c b/src/tls/tlsv1_client_read.c
index ff12452..244c3cb 100644
--- a/src/tls/tlsv1_client_read.c
+++ b/src/tls/tlsv1_client_read.c
@@ -326,7 +326,7 @@
 	union tls_event_data ev;
 	char subject[128];
 
-	if (!conn->event_cb)
+	if (!conn->event_cb || !cert)
 		return;
 
 	os_memset(&ev, 0, sizeof(ev));
@@ -790,14 +790,40 @@
 }
 
 
+static enum tls_ocsp_result
+tls_process_certificate_status_ocsp_response(struct tlsv1_client *conn,
+					     const u8 *pos, size_t len)
+{
+	const u8 *end = pos + len;
+	u32 ocsp_resp_len;
+
+	/* opaque OCSPResponse<1..2^24-1>; */
+	if (end - pos < 3) {
+		wpa_printf(MSG_INFO, "TLSv1: Too short OCSPResponse");
+		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
+		return TLS_OCSP_INVALID;
+	}
+	ocsp_resp_len = WPA_GET_BE24(pos);
+	pos += 3;
+	if (end - pos < ocsp_resp_len) {
+		wpa_printf(MSG_INFO, "TLSv1: Truncated OCSPResponse");
+		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
+		return TLS_OCSP_INVALID;
+	}
+
+	return tls_process_ocsp_response(conn, pos, ocsp_resp_len);
+}
+
+
 static int tls_process_certificate_status(struct tlsv1_client *conn, u8 ct,
 					   const u8 *in_data, size_t *in_len)
 {
 	const u8 *pos, *end;
 	size_t left, len;
 	u8 type, status_type;
-	u32 ocsp_resp_len;
 	enum tls_ocsp_result res;
+	struct x509_certificate *cert;
+	int depth;
 
 	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
 		wpa_printf(MSG_DEBUG,
@@ -850,6 +876,7 @@
 	 *     CertificateStatusType status_type;
 	 *     select (status_type) {
 	 *         case ocsp: OCSPResponse;
+	 *         case ocsp_multi: OCSPResponseList;
 	 *     } response;
 	 * } CertificateStatus;
 	 */
@@ -862,32 +889,110 @@
 	wpa_printf(MSG_DEBUG, "TLSv1: CertificateStatus status_type %u",
 		   status_type);
 
-	if (status_type != 1 /* ocsp */) {
+	if (status_type == 1 /* ocsp */) {
+		res = tls_process_certificate_status_ocsp_response(
+			conn, pos, end - pos);
+	} else if (status_type == 2 /* ocsp_multi */) {
+		int good = 0, revoked = 0;
+		u32 resp_len;
+
+		res = TLS_OCSP_NO_RESPONSE;
+
+		/*
+		 * opaque OCSPResponse<0..2^24-1>;
+		 *
+		 * struct {
+		 *   OCSPResponse ocsp_response_list<1..2^24-1>;
+		 * } OCSPResponseList;
+		 */
+		if (end - pos < 3) {
+			wpa_printf(MSG_DEBUG,
+				   "TLSv1: Truncated OCSPResponseList");
+			res = TLS_OCSP_INVALID;
+			goto done;
+		}
+		resp_len = WPA_GET_BE24(pos);
+		pos += 3;
+		if (end - pos < resp_len) {
+			wpa_printf(MSG_DEBUG,
+				   "TLSv1: Truncated OCSPResponseList(len=%u)",
+				   resp_len);
+			res = TLS_OCSP_INVALID;
+			goto done;
+		}
+		end = pos + resp_len;
+
+		while (end - pos >= 3) {
+			resp_len = WPA_GET_BE24(pos);
+			pos += 3;
+			if (resp_len > end - pos) {
+				wpa_printf(MSG_DEBUG,
+					   "TLSv1: Truncated OCSPResponse(len=%u; left=%d) in ocsp_multi",
+					   resp_len, (int) (end - pos));
+				res = TLS_OCSP_INVALID;
+				break;
+			}
+			if (!resp_len)
+				continue; /* Skip an empty response */
+			res = tls_process_certificate_status_ocsp_response(
+				conn, pos - 3, resp_len + 3);
+			if (res == TLS_OCSP_REVOKED)
+				revoked++;
+			else if (res == TLS_OCSP_GOOD)
+				good++;
+			pos += resp_len;
+		}
+
+		if (revoked)
+			res = TLS_OCSP_REVOKED;
+		else if (good)
+			res = TLS_OCSP_GOOD;
+	} else {
 		wpa_printf(MSG_DEBUG,
 			   "TLSv1: Ignore unsupported CertificateStatus");
 		goto skip;
 	}
 
-	/* opaque OCSPResponse<1..2^24-1>; */
-	if (end - pos < 3) {
-		wpa_printf(MSG_INFO, "TLSv1: Too short OCSPResponse");
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
-		return -1;
-	}
-	ocsp_resp_len = WPA_GET_BE24(pos);
-	pos += 3;
-	if (end - pos < ocsp_resp_len) {
-		wpa_printf(MSG_INFO, "TLSv1: Truncated OCSPResponse");
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
+done:
+	if (res == TLS_OCSP_REVOKED) {
+		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
+			  TLS_ALERT_CERTIFICATE_REVOKED);
+		for (cert = conn->server_cert, depth = 0; cert;
+		     cert = cert->next, depth++) {
+			if (cert->ocsp_revoked) {
+				tls_cert_chain_failure_event(
+					conn, depth, cert, TLS_FAIL_REVOKED,
+					"certificate revoked");
+			}
+		}
 		return -1;
 	}
 
-	res = tls_process_ocsp_response(conn, pos, ocsp_resp_len);
-	switch (res) {
-	case TLS_OCSP_NO_RESPONSE:
-		if (!(conn->flags & TLS_CONN_REQUIRE_OCSP))
-			goto skip;
+	if (conn->flags & TLS_CONN_REQUIRE_OCSP_ALL) {
+		/*
+		 * Verify that each certificate on the chain that is not part
+		 * of the trusted certificates has a good status. If not,
+		 * terminate handshake.
+		 */
+		for (cert = conn->server_cert, depth = 0; cert;
+		     cert = cert->next, depth++) {
+			if (!cert->ocsp_good) {
+				tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
+					  TLS_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE);
+				tls_cert_chain_failure_event(
+					conn, depth, cert,
+					TLS_FAIL_UNSPECIFIED,
+					"bad certificate status response");
+				return -1;
+			}
+			if (cert->issuer_trusted)
+				break;
+		}
+	}
+
+	if ((conn->flags & TLS_CONN_REQUIRE_OCSP) && res != TLS_OCSP_GOOD) {
 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
+			  res == TLS_OCSP_INVALID ? TLS_ALERT_DECODE_ERROR :
 			  TLS_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE);
 		if (conn->server_cert)
 			tls_cert_chain_failure_event(
@@ -895,28 +1000,8 @@
 				TLS_FAIL_UNSPECIFIED,
 				"bad certificate status response");
 		return -1;
-	case TLS_OCSP_INVALID:
-		if (!(conn->flags & TLS_CONN_REQUIRE_OCSP))
-			goto skip; /* ignore - process as if no response */
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
-		if (conn->server_cert)
-			tls_cert_chain_failure_event(
-				conn, 0, conn->server_cert,
-				TLS_FAIL_UNSPECIFIED,
-				"bad certificate status response");
-		return -1;
-	case TLS_OCSP_GOOD:
-		wpa_printf(MSG_DEBUG, "TLSv1: OCSP response good");
-		break;
-	case TLS_OCSP_REVOKED:
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_CERTIFICATE_REVOKED);
-		if (conn->server_cert)
-			tls_cert_chain_failure_event(
-				conn, 0, conn->server_cert, TLS_FAIL_REVOKED,
-				"certificate revoked");
-		return -1;
 	}
+
 	conn->ocsp_resp_received = 1;
 
 skip:
diff --git a/src/tls/tlsv1_client_write.c b/src/tls/tlsv1_client_write.c
index 8e8cb5e..04d895e 100644
--- a/src/tls/tlsv1_client_write.c
+++ b/src/tls/tlsv1_client_write.c
@@ -192,6 +192,46 @@
 		pos += 2;
 		WPA_PUT_BE16(pos, 0); /* request_extensions(empty) */
 		pos += 2;
+
+		wpa_printf(MSG_DEBUG,
+			   "TLSv1: Add status_request_v2 extension for OCSP stapling");
+		/* ExtensionsType extension_type = status_request_v2(17) */
+		WPA_PUT_BE16(pos, TLS_EXT_STATUS_REQUEST_V2);
+		pos += 2;
+		/* opaque extension_data<0..2^16-1> length */
+		WPA_PUT_BE16(pos, 7);
+		pos += 2;
+
+		/*
+		 * RFC 6961, 2.2:
+		 * struct {
+		 *     CertificateStatusType status_type;
+		 *     uint16 request_length;
+		 *     select (status_type) {
+		 *         case ocsp: OCSPStatusRequest;
+		 *         case ocsp_multi: OCSPStatusRequest;
+		 *     } request;
+		 * } CertificateStatusRequestItemV2;
+		 *
+		 * enum { ocsp(1), ocsp_multi(2), (255) } CertificateStatusType;
+		 *
+		 * struct {
+		 * CertificateStatusRequestItemV2
+		 *     certificate_status_req_list<1..2^16-1>;
+		 * } CertificateStatusRequestListV2;
+		 */
+
+		/* certificate_status_req_list<1..2^16-1> */
+		WPA_PUT_BE16(pos, 5);
+		pos += 2;
+
+		/* CertificateStatusRequestItemV2 */
+		*pos++ = 2; /* status_type = ocsp_multi(2) */
+		/* OCSPStatusRequest as shown above for v1 */
+		WPA_PUT_BE16(pos, 0); /* responder_id_list(empty) */
+		pos += 2;
+		WPA_PUT_BE16(pos, 0); /* request_extensions(empty) */
+		pos += 2;
 	}
 
 	if (pos == ext_start + 2)
diff --git a/src/tls/tlsv1_common.h b/src/tls/tlsv1_common.h
index 7a252fe..e30b15a 100644
--- a/src/tls/tlsv1_common.h
+++ b/src/tls/tlsv1_common.h
@@ -170,6 +170,7 @@
 #define TLS_EXT_TRUNCATED_HMAC			4 /* RFC 4366 */
 #define TLS_EXT_STATUS_REQUEST			5 /* RFC 4366 */
 #define TLS_EXT_SIGNATURE_ALGORITHMS		13 /* RFC 5246 */
+#define TLS_EXT_STATUS_REQUEST_V2		17 /* RFC 6961 */
 #define TLS_EXT_SESSION_TICKET			35 /* RFC 4507 */
 
 #define TLS_EXT_PAC_OPAQUE TLS_EXT_SESSION_TICKET /* EAP-FAST terminology */
diff --git a/src/tls/tlsv1_cred.c b/src/tls/tlsv1_cred.c
index 92f97c7..52c1ae0 100644
--- a/src/tls/tlsv1_cred.c
+++ b/src/tls/tlsv1_cred.c
@@ -36,6 +36,8 @@
 	crypto_private_key_free(cred->key);
 	os_free(cred->dh_p);
 	os_free(cred->dh_g);
+	os_free(cred->ocsp_stapling_response);
+	os_free(cred->ocsp_stapling_response_multi);
 	os_free(cred);
 }
 
diff --git a/src/tls/tlsv1_cred.h b/src/tls/tlsv1_cred.h
index b4bfe38..716e93c 100644
--- a/src/tls/tlsv1_cred.h
+++ b/src/tls/tlsv1_cred.h
@@ -24,6 +24,9 @@
 	size_t dh_p_len;
 	u8 *dh_g; /* generator */
 	size_t dh_g_len;
+
+	char *ocsp_stapling_response;
+	char *ocsp_stapling_response_multi;
 };
 
 
diff --git a/src/tls/tlsv1_server_i.h b/src/tls/tlsv1_server_i.h
index 96d79b3..29c6678 100644
--- a/src/tls/tlsv1_server_i.h
+++ b/src/tls/tlsv1_server_i.h
@@ -55,6 +55,9 @@
 	void *log_cb_ctx;
 
 	int use_session_ticket;
+	unsigned int status_request:1;
+	unsigned int status_request_v2:1;
+	unsigned int status_request_multi:1;
 
 	u8 *dh_secret;
 	size_t dh_secret_len;
diff --git a/src/tls/tlsv1_server_read.c b/src/tls/tlsv1_server_read.c
index 8347d7a..4aa8a01 100644
--- a/src/tls/tlsv1_server_read.c
+++ b/src/tls/tlsv1_server_read.c
@@ -46,6 +46,78 @@
 }
 
 
+static void tls_process_status_request_item(struct tlsv1_server *conn,
+					    const u8 *req, size_t req_len)
+{
+	const u8 *pos, *end;
+	u8 status_type;
+
+	pos = req;
+	end = req + req_len;
+
+	/*
+	 * RFC 6961, 2.2:
+	 * struct {
+	 *   CertificateStatusType status_type;
+	 *   uint16 request_length;
+	 *   select (status_type) {
+	 *     case ocsp: OCSPStatusRequest;
+	 *     case ocsp_multi: OCSPStatusRequest;
+	 *   } request;
+	 * } CertificateStatusRequestItemV2;
+	 *
+	 * enum { ocsp(1), ocsp_multi(2), (255) } CertificateStatusType;
+	 */
+
+	if (end - pos < 1)
+		return; /* Truncated data */
+
+	status_type = *pos++;
+	wpa_printf(MSG_DEBUG, "TLSv1: CertificateStatusType %u", status_type);
+	if (status_type != 1 && status_type != 2)
+		return; /* Unsupported status type */
+	/*
+	 * For now, only OCSP stapling is supported, so ignore the specific
+	 * request, if any.
+	 */
+	wpa_hexdump(MSG_DEBUG, "TLSv1: OCSPStatusRequest", pos, end - pos);
+
+	if (status_type == 2)
+		conn->status_request_multi = 1;
+}
+
+
+static void tls_process_status_request_v2(struct tlsv1_server *conn,
+					  const u8 *ext, size_t ext_len)
+{
+	const u8 *pos, *end;
+
+	conn->status_request_v2 = 1;
+
+	pos = ext;
+	end = ext + ext_len;
+
+	/*
+	 * RFC 6961, 2.2:
+	 * struct {
+	 *   CertificateStatusRequestItemV2
+	 *                    certificate_status_req_list<1..2^16-1>;
+	 * } CertificateStatusRequestListV2;
+	 */
+
+	while (end - pos >= 2) {
+		u16 len;
+
+		len = WPA_GET_BE16(pos);
+		pos += 2;
+		if (len > end - pos)
+			break; /* Truncated data */
+		tls_process_status_request_item(conn, pos, len);
+		pos += len;
+	}
+}
+
+
 static int tls_process_client_hello(struct tlsv1_server *conn, u8 ct,
 				    const u8 *in_data, size_t *in_len)
 {
@@ -267,6 +339,11 @@
 						  ext_len);
 					conn->session_ticket_len = ext_len;
 				}
+			} else if (ext_type == TLS_EXT_STATUS_REQUEST) {
+				conn->status_request = 1;
+			} else if (ext_type == TLS_EXT_STATUS_REQUEST_V2) {
+				tls_process_status_request_v2(conn, pos,
+							      ext_len);
 			}
 
 			pos += ext_len;
diff --git a/src/tls/tlsv1_server_write.c b/src/tls/tlsv1_server_write.c
index e7c5e22..bdc6c11 100644
--- a/src/tls/tlsv1_server_write.c
+++ b/src/tls/tlsv1_server_write.c
@@ -42,7 +42,7 @@
 static int tls_write_server_hello(struct tlsv1_server *conn,
 				  u8 **msgpos, u8 *end)
 {
-	u8 *pos, *rhdr, *hs_start, *hs_length;
+	u8 *pos, *rhdr, *hs_start, *hs_length, *ext_start;
 	struct os_time now;
 	size_t rlen;
 
@@ -97,6 +97,32 @@
 	/* CompressionMethod compression_method */
 	*pos++ = TLS_COMPRESSION_NULL;
 
+	/* Extension */
+	ext_start = pos;
+	pos += 2;
+
+	if (conn->status_request) {
+		/* Add a status_request extension with empty extension_data */
+		/* ExtensionsType extension_type = status_request(5) */
+		WPA_PUT_BE16(pos, TLS_EXT_STATUS_REQUEST);
+		pos += 2;
+		/* opaque extension_data<0..2^16-1> length */
+		WPA_PUT_BE16(pos, 0);
+		pos += 2;
+	}
+
+	if (conn->status_request_v2) {
+		/*
+		  Add a status_request_v2 extension with empty extension_data
+		*/
+		/* ExtensionsType extension_type = status_request_v2(17) */
+		WPA_PUT_BE16(pos, TLS_EXT_STATUS_REQUEST_V2);
+		pos += 2;
+		/* opaque extension_data<0..2^16-1> length */
+		WPA_PUT_BE16(pos, 0);
+		pos += 2;
+	}
+
 	if (conn->session_ticket && conn->session_ticket_cb) {
 		int res = conn->session_ticket_cb(
 			conn->session_ticket_cb_ctx,
@@ -133,6 +159,11 @@
 		 */
 	}
 
+	if (pos == ext_start + 2)
+		pos -= 2; /* no extensions */
+	else
+		WPA_PUT_BE16(ext_start, pos - ext_start - 2);
+
 	WPA_PUT_BE24(hs_length, pos - hs_length - 3);
 	tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start);
 
@@ -244,6 +275,93 @@
 }
 
 
+static int tls_write_server_certificate_status(struct tlsv1_server *conn,
+					       u8 **msgpos, u8 *end,
+					       int ocsp_multi,
+					       char *ocsp_resp,
+					       size_t ocsp_resp_len)
+{
+	u8 *pos, *rhdr, *hs_start, *hs_length;
+	size_t rlen;
+
+	if (!ocsp_resp) {
+		 /*
+		  * Client did not request certificate status or there is no
+		  * matching response cached.
+		  */
+		return 0;
+	}
+
+	pos = *msgpos;
+	if (TLS_RECORD_HEADER_LEN + 1 + 3 + 1 + 3 + ocsp_resp_len >
+	    (unsigned int) (end - pos)) {
+		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
+				   TLS_ALERT_INTERNAL_ERROR);
+		return -1;
+	}
+
+	tlsv1_server_log(conn, "Send CertificateStatus (multi=%d)", ocsp_multi);
+	rhdr = pos;
+	pos += TLS_RECORD_HEADER_LEN;
+
+	/* opaque fragment[TLSPlaintext.length] */
+
+	/* Handshake */
+	hs_start = pos;
+	/* HandshakeType msg_type */
+	*pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE_STATUS;
+	/* uint24 length (to be filled) */
+	hs_length = pos;
+	pos += 3;
+
+	/* body - CertificateStatus
+	 *
+	 * struct {
+	 *     CertificateStatusType status_type;
+	 *     select (status_type) {
+	 *         case ocsp: OCSPResponse;
+	 *         case ocsp_multi: OCSPResponseList;
+	 *     } response;
+	 * } CertificateStatus;
+	 *
+	 * opaque OCSPResponse<1..2^24-1>;
+	 *
+	 * struct {
+	 *   OCSPResponse ocsp_response_list<1..2^24-1>;
+	 * } OCSPResponseList;
+	 */
+
+	/* CertificateStatusType status_type */
+	if (ocsp_multi)
+		*pos++ = 2; /* ocsp_multi(2) */
+	else
+		*pos++ = 1; /* ocsp(1) */
+	/* uint24 length of OCSPResponse */
+	WPA_PUT_BE24(pos, ocsp_resp_len);
+	pos += 3;
+	os_memcpy(pos, ocsp_resp, ocsp_resp_len);
+	pos += ocsp_resp_len;
+
+	WPA_PUT_BE24(hs_length, pos - hs_length - 3);
+
+	if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
+			      rhdr, end - rhdr, hs_start, pos - hs_start,
+			      &rlen) < 0) {
+		wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record");
+		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
+				   TLS_ALERT_INTERNAL_ERROR);
+		return -1;
+	}
+	pos = rhdr + rlen;
+
+	tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start);
+
+	*msgpos = pos;
+
+	return 0;
+}
+
+
 static int tls_write_server_key_exchange(struct tlsv1_server *conn,
 					 u8 **msgpos, u8 *end)
 {
@@ -810,24 +928,46 @@
 {
 	u8 *msg, *end, *pos;
 	size_t msglen;
+	int ocsp_multi = 0;
+	char *ocsp_resp = NULL;
+	size_t ocsp_resp_len = 0;
 
 	*out_len = 0;
 
-	msglen = 1000 + tls_server_cert_chain_der_len(conn);
+	if (conn->status_request_multi &&
+	    conn->cred->ocsp_stapling_response_multi) {
+		ocsp_resp = os_readfile(
+			conn->cred->ocsp_stapling_response_multi,
+			&ocsp_resp_len);
+		ocsp_multi = 1;
+	} else if ((conn->status_request || conn->status_request_v2) &&
+		   conn->cred->ocsp_stapling_response) {
+		ocsp_resp = os_readfile(conn->cred->ocsp_stapling_response,
+					&ocsp_resp_len);
+	}
+	if (!ocsp_resp)
+		ocsp_resp_len = 0;
+
+	msglen = 1000 + tls_server_cert_chain_der_len(conn) + ocsp_resp_len;
 
 	msg = os_malloc(msglen);
-	if (msg == NULL)
+	if (msg == NULL) {
+		os_free(ocsp_resp);
 		return NULL;
+	}
 
 	pos = msg;
 	end = msg + msglen;
 
 	if (tls_write_server_hello(conn, &pos, end) < 0) {
 		os_free(msg);
+		os_free(ocsp_resp);
 		return NULL;
 	}
 
 	if (conn->use_session_ticket) {
+		os_free(ocsp_resp);
+
 		/* Abbreviated handshake using session ticket; RFC 4507 */
 		if (tls_write_server_change_cipher_spec(conn, &pos, end) < 0 ||
 		    tls_write_server_finished(conn, &pos, end) < 0) {
@@ -844,12 +984,16 @@
 
 	/* Full handshake */
 	if (tls_write_server_certificate(conn, &pos, end) < 0 ||
+	    tls_write_server_certificate_status(conn, &pos, end, ocsp_multi,
+						ocsp_resp, ocsp_resp_len) < 0 ||
 	    tls_write_server_key_exchange(conn, &pos, end) < 0 ||
 	    tls_write_server_certificate_request(conn, &pos, end) < 0 ||
 	    tls_write_server_hello_done(conn, &pos, end) < 0) {
 		os_free(msg);
+		os_free(ocsp_resp);
 		return NULL;
 	}
+	os_free(ocsp_resp);
 
 	*out_len = pos - msg;
 
diff --git a/src/tls/x509v3.c b/src/tls/x509v3.c
index 5521390..75f222c 100644
--- a/src/tls/x509v3.c
+++ b/src/tls/x509v3.c
@@ -1339,6 +1339,7 @@
 	size_t left;
 	char sbuf[128];
 	unsigned long value;
+	const u8 *subject_dn;
 
 	/* tbsCertificate TBSCertificate ::= SEQUENCE */
 	if (asn1_get_next(buf, len, &hdr) < 0 ||
@@ -1436,7 +1437,6 @@
 		return -1;
 
 	/* subject Name */
-	const u8 *subject_dn;
 	subject_dn = pos;
 	if (x509_parse_name(pos, end - pos, &cert->subject, &pos))
 		return -1;
@@ -2038,6 +2038,7 @@
 	os_get_time(&now);
 
 	for (cert = chain, idx = 0; cert; cert = cert->next, idx++) {
+		cert->issuer_trusted = 0;
 		x509_name_string(&cert->subject, buf, sizeof(buf)); 
 		wpa_printf(MSG_DEBUG, "X509: %lu: %s", idx, buf);
 
@@ -2123,6 +2124,7 @@
 
 			wpa_printf(MSG_DEBUG, "X509: Trusted certificate "
 				   "found to complete the chain");
+			cert->issuer_trusted = 1;
 			chain_trusted = 1;
 		}
 	}
diff --git a/src/tls/x509v3.h b/src/tls/x509v3.h
index dcdb4a3..7df8e2a 100644
--- a/src/tls/x509v3.h
+++ b/src/tls/x509v3.h
@@ -106,6 +106,11 @@
 	size_t cert_len;
 	const u8 *tbs_cert_start;
 	size_t tbs_cert_len;
+
+	/* Meta data used for certificate validation */
+	unsigned int ocsp_good:1;
+	unsigned int ocsp_revoked:1;
+	unsigned int issuer_trusted:1;
 };
 
 enum {
diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk
index f62b30a..95690bf 100644
--- a/wpa_supplicant/Android.mk
+++ b/wpa_supplicant/Android.mk
@@ -856,6 +856,12 @@
 endif
 endif
 
+ifdef CONFIG_ACS
+L_CFLAGS += -DCONFIG_ACS
+OBJS += src/ap/acs.c
+LIBS += -lm
+endif
+
 ifdef CONFIG_PCSC
 # PC/SC interface for smartcards (USIM, GSM SIM)
 L_CFLAGS += -DPCSC_FUNCS -I/usr/include/PCSC
diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile
index 6bab7d1..8fa35e5 100644
--- a/wpa_supplicant/Makefile
+++ b/wpa_supplicant/Makefile
@@ -6,6 +6,17 @@
 CFLAGS = -MMD -O2 -Wall -g
 endif
 
+ifdef LIBS
+# If LIBS is set with some global build system defaults, clone those for
+# LIBS_c and LIBS_p to cover wpa_passphrase and wpa_cli as well.
+ifndef LIBS_c
+LIBS_c := $(LIBS)
+endif
+ifndef LIBS_p
+LIBS_p := $(LIBS)
+endif
+endif
+
 export LIBDIR ?= /usr/local/lib/
 export INCDIR ?= /usr/local/include/
 export BINDIR ?= /usr/local/sbin/
@@ -884,6 +895,12 @@
 endif
 endif
 
+ifdef CONFIG_ACS
+CFLAGS += -DCONFIG_ACS
+OBJS += ../src/ap/acs.o
+LIBS += -lm
+endif
+
 ifdef CONFIG_PCSC
 # PC/SC interface for smartcards (USIM, GSM SIM)
 CFLAGS += -DPCSC_FUNCS -I/usr/include/PCSC
diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
index 27fa2a9..105fb1c 100644
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -213,6 +213,14 @@
 	if (wpa_supplicant_conf_ap_ht(wpa_s, ssid, conf))
 		return -1;
 
+#ifdef CONFIG_ACS
+	if (ssid->acs) {
+		/* Setting channel to 0 in order to enable ACS */
+		conf->channel = 0;
+		wpa_printf(MSG_DEBUG, "Use automatic channel selection");
+	}
+#endif /* CONFIG_ACS */
+
 	if (ieee80211_is_dfs(ssid->frequency) && wpa_s->conf->country[0]) {
 		conf->ieee80211h = 1;
 		conf->ieee80211d = 1;
@@ -558,6 +566,11 @@
 {
 	struct wpa_supplicant *wpa_s = ctx;
 
+#ifdef CONFIG_ACS
+	if (wpa_s->current_ssid && wpa_s->current_ssid->acs)
+		wpa_s->assoc_freq = wpa_s->ap_iface->freq;
+#endif /* CONFIG_ACS */
+
 	wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
 
 	if (wpa_s->ap_configured_cb)
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index f2ae4fd..85717e9 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -1920,6 +1920,9 @@
 	{ INT_RANGE(mixed_cell, 0, 1) },
 	{ INT_RANGE(frequency, 0, 65000) },
 	{ INT_RANGE(fixed_freq, 0, 1) },
+#ifdef CONFIG_ACS
+	{ INT_RANGE(acs, 0, 1) },
+#endif /* CONFIG_ACS */
 #ifdef CONFIG_MESH
 	{ FUNC(mesh_basic_rates) },
 	{ INT(dot11MeshMaxRetries) },
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index 80e3e56..6ea113e 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -747,6 +747,9 @@
 	INT(no_auto_peer);
 	INT(frequency);
 	INT(fixed_freq);
+#ifdef CONFIG_ACS
+	INT(acs);
+#endif /* CONFIG_ACS */
 	write_int(f, "proactive_key_caching", ssid->proactive_key_caching, -1);
 	INT(disabled);
 	INT(peerkey);
diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h
index de8157a..b296826 100644
--- a/wpa_supplicant/config_ssid.h
+++ b/wpa_supplicant/config_ssid.h
@@ -431,6 +431,18 @@
 	 */
 	int fixed_freq;
 
+#ifdef CONFIG_ACS
+	/**
+	 * ACS - Automatic Channel Selection for AP mode
+	 *
+	 * If present, it will be handled together with frequency.
+	 * frequency will be used to determine hardware mode only, when it is
+	 * used for both hardware mode and channel when used alone. This will
+	 * force the channel to be set to 0, thus enabling ACS.
+	 */
+	int acs;
+#endif /* CONFIG_ACS */
+
 	/**
 	 * mesh_basic_rates - BSS Basic rate set for mesh network
 	 *
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index d1274f6..ecf8d2d 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -3937,6 +3937,15 @@
 	}
 #endif /* CONFIG_FIPS */
 
+#ifdef CONFIG_ACS
+	if (os_strcmp(field, "acs") == 0) {
+		res = os_snprintf(buf, buflen, "ACS");
+		if (os_snprintf_error(buflen, res))
+			return -1;
+		return res;
+	}
+#endif /* CONFIG_ACS */
+
 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
 		   field);
 
diff --git a/wpa_supplicant/ctrl_iface_unix.c b/wpa_supplicant/ctrl_iface_unix.c
index 2c71b2d..7b36751 100644
--- a/wpa_supplicant/ctrl_iface_unix.c
+++ b/wpa_supplicant/ctrl_iface_unix.c
@@ -1058,6 +1058,9 @@
 	struct sockaddr_un from;
 	socklen_t fromlen = sizeof(from);
 
+	if (priv->sock == -1)
+		return;
+
 	for (;;) {
 		wpa_printf(MSG_DEBUG, "CTRL_IFACE - %s - wait for monitor to "
 			   "attach", priv->wpa_s->ifname);
diff --git a/wpa_supplicant/defconfig b/wpa_supplicant/defconfig
index e2e4bdc..8b1d121 100644
--- a/wpa_supplicant/defconfig
+++ b/wpa_supplicant/defconfig
@@ -513,3 +513,29 @@
 
 # OS X builds. This is only for building eapol_test.
 #CONFIG_OSX=y
+
+# Automatic Channel Selection
+# This will allow wpa_supplicant to pick the channel automatically when channel
+# is set to "0".
+#
+# TODO: Extend parser to be able to parse "channel=acs_survey" as an alternative
+# to "channel=0". This would enable us to eventually add other ACS algorithms in
+# similar way.
+#
+# Automatic selection is currently only done through initialization, later on
+# we hope to do background checks to keep us moving to more ideal channels as
+# time goes by. ACS is currently only supported through the nl80211 driver and
+# your driver must have survey dump capability that is filled by the driver
+# during scanning.
+#
+# TODO: In analogy to hostapd be able to customize the ACS survey algorithm with
+# a newly to create wpa_supplicant.conf variable acs_num_scans.
+#
+# Supported ACS drivers:
+# * ath9k
+# * ath5k
+# * ath10k
+#
+# For more details refer to:
+# http://wireless.kernel.org/en/users/Documentation/acs
+#CONFIG_ACS=y
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 1ac177e..3c60cc1 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -3942,6 +3942,22 @@
 				     data->mesh_peer.ie_len);
 #endif /* CONFIG_MESH */
 		break;
+	case EVENT_SURVEY:
+#ifdef CONFIG_AP
+		if (!wpa_s->ap_iface)
+			break;
+		hostapd_event_get_survey(wpa_s->ap_iface,
+					 &data->survey_results);
+#endif /* CONFIG_AP */
+		break;
+	case EVENT_ACS_CHANNEL_SELECTED:
+#ifdef CONFIG_ACS
+		if (!wpa_s->ap_iface)
+			break;
+		hostapd_acs_channel_selected(wpa_s->ap_iface->bss[0],
+					     &data->acs_selected_channels);
+#endif /* CONFIG_ACS */
+		break;
 	default:
 		wpa_msg(wpa_s, MSG_INFO, "Unknown event %d", event);
 		break;
diff --git a/wpa_supplicant/mesh_mpm.c b/wpa_supplicant/mesh_mpm.c
index 7ebd4d2..4caa55c 100644
--- a/wpa_supplicant/mesh_mpm.c
+++ b/wpa_supplicant/mesh_mpm.c
@@ -20,11 +20,11 @@
 #include "mesh_rsn.h"
 
 struct mesh_peer_mgmt_ie {
-	const u8 *proto_id;
-	const u8 *llid;
-	const u8 *plid;
-	const u8 *reason;
-	const u8 *pmk;
+	const u8 *proto_id; /* Mesh Peering Protocol Identifier (2 octets) */
+	const u8 *llid; /* Local Link ID (2 octets) */
+	const u8 *plid; /* Peer Link ID (conditional, 2 octets) */
+	const u8 *reason; /* Reason Code (conditional, 2 octets) */
+	const u8 *chosen_pmk; /* Chosen PMK (optional, 16 octets) */
 };
 
 static void plink_timer(void *eloop_ctx, void *user_data);
@@ -72,10 +72,10 @@
 {
 	os_memset(mpm_ie, 0, sizeof(*mpm_ie));
 
-	/* remove optional PMK at end */
-	if (len >= 16) {
-		len -= 16;
-		mpm_ie->pmk = ie + len - 16;
+	/* Remove optional Chosen PMK field at end */
+	if (len >= SAE_PMKID_LEN) {
+		mpm_ie->chosen_pmk = ie + len - SAE_PMKID_LEN;
+		len -= SAE_PMKID_LEN;
 	}
 
 	if ((action_field == PLINK_OPEN && len != 4) ||
@@ -101,8 +101,8 @@
 		len -= 2;
 	}
 
-	/* plid, present for confirm, and possibly close */
-	if (len)
+	/* Peer Link ID, present for confirm, and possibly close */
+	if (len >= 2)
 		mpm_ie->plid = ie;
 
 	return 0;
@@ -1014,6 +1014,7 @@
 	if ((mconf->security & MESH_CONF_SEC_AMPE) &&
 	    mesh_rsn_process_ampe(wpa_s, sta, &elems,
 				  &mgmt->u.action.category,
+				  peer_mgmt_ie.chosen_pmk,
 				  ies, ie_len)) {
 		wpa_printf(MSG_DEBUG, "MPM: RSN process rejected frame");
 		return;
diff --git a/wpa_supplicant/mesh_rsn.c b/wpa_supplicant/mesh_rsn.c
index 747f1ae..5d88274 100644
--- a/wpa_supplicant/mesh_rsn.c
+++ b/wpa_supplicant/mesh_rsn.c
@@ -328,10 +328,7 @@
 
 void mesh_rsn_get_pmkid(struct mesh_rsn *rsn, struct sta_info *sta, u8 *pmkid)
 {
-	/* don't expect wpa auth to cache the pmkid for now */
-	rsn_pmkid(sta->sae->pmk, PMK_LEN, rsn->wpa_s->own_addr,
-		  sta->addr, pmkid,
-		  wpa_key_mgmt_sha256(wpa_auth_sta_key_mgmt(sta->wpa_sm)));
+	os_memcpy(pmkid, sta->sae->pmkid, SAE_PMKID_LEN);
 }
 
 
@@ -503,6 +500,7 @@
 
 int mesh_rsn_process_ampe(struct wpa_supplicant *wpa_s, struct sta_info *sta,
 			  struct ieee802_11_elems *elems, const u8 *cat,
+			  const u8 *chosen_pmk,
 			  const u8 *start, size_t elems_len)
 {
 	int ret = 0;
@@ -516,6 +514,12 @@
 	const size_t aad_len[] = { ETH_ALEN, ETH_ALEN,
 				   (elems->mic - 2) - cat };
 
+	if (chosen_pmk && os_memcmp(chosen_pmk, sta->sae->pmkid, PMKID_LEN)) {
+		wpa_msg(wpa_s, MSG_DEBUG,
+			"Mesh RSN: Invalid PMKID (Chosen PMK did not match calculated PMKID)");
+		return -1;
+	}
+
 	if (!elems->mic || elems->mic_len < AES_BLOCK_SIZE) {
 		wpa_msg(wpa_s, MSG_DEBUG, "Mesh RSN: missing mic ie");
 		return -1;
diff --git a/wpa_supplicant/mesh_rsn.h b/wpa_supplicant/mesh_rsn.h
index b1471b2..89601d4 100644
--- a/wpa_supplicant/mesh_rsn.h
+++ b/wpa_supplicant/mesh_rsn.h
@@ -30,6 +30,7 @@
 			   const u8 *cat, struct wpabuf *buf);
 int mesh_rsn_process_ampe(struct wpa_supplicant *wpa_s, struct sta_info *sta,
 			  struct ieee802_11_elems *elems, const u8 *cat,
+			  const u8 *chosen_pmk,
 			  const u8 *start, size_t elems_len);
 void mesh_auth_timer(void *eloop_ctx, void *user_data);
 
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index 45dae50..d6acbd0 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -774,13 +774,6 @@
 
 	case P2PS_SETUP_GROUP_OWNER | P2PS_SETUP_NEW:
 	case P2PS_SETUP_GROUP_OWNER | P2PS_SETUP_CLIENT:
-		/*
-		 * Peer has an active GO, so if the role allows it and
-		 * we do not have any active roles, become client.
-		 */
-		if ((role & P2PS_SETUP_CLIENT) && !go_wpa_s && !cli_wpa_s)
-			return P2PS_SETUP_CLIENT;
-
 		if (cli_wpa_s)
 			conncap = P2PS_SETUP_GROUP_OWNER;
 		else {
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 29683bc..e588992 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -5227,7 +5227,7 @@
 
 	if (global->params.wait_for_monitor) {
 		for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
-			if (wpa_s->ctrl_iface)
+			if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
 				wpa_supplicant_ctrl_iface_wait(
 					wpa_s->ctrl_iface);
 	}
diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf
index e33b720..e204061 100644
--- a/wpa_supplicant/wpa_supplicant.conf
+++ b/wpa_supplicant/wpa_supplicant.conf
@@ -586,6 +586,8 @@
 #	0 = do not use OCSP stapling (TLS certificate status extension)
 #	1 = try to use OCSP stapling, but not require response
 #	2 = require valid OCSP stapling response
+#	3 = require valid OCSP stapling response for all not-trusted
+#	    certificates in the server certificate chain
 #
 # sim_num: Identifier for which SIM to use in multi-SIM devices
 #
@@ -748,8 +750,18 @@
 # IEEE8021X = IEEE 802.1X using EAP authentication and (optionally) dynamically
 #	generated WEP keys
 # NONE = WPA is not used; plaintext or static WEP could be used
+# WPA-NONE = WPA-None for IBSS (deprecated; use proto=RSN key_mgmt=WPA-PSK
+#	instead)
+# FT-PSK = Fast BSS Transition (IEEE 802.11r) with pre-shared key
+# FT-EAP = Fast BSS Transition (IEEE 802.11r) with EAP authentication
 # WPA-PSK-SHA256 = Like WPA-PSK but using stronger SHA256-based algorithms
 # WPA-EAP-SHA256 = Like WPA-EAP but using stronger SHA256-based algorithms
+# SAE = Simultaneous authentication of equals; pre-shared key/password -based
+#	authentication with stronger security than WPA-PSK especially when using
+#	not that strong password
+# FT-SAE = SAE with FT
+# WPA-EAP-SUITE-B = Suite B 128-bit level
+# WPA-EAP-SUITE-B-192 = Suite B 192-bit level
 # If not set, this defaults to: WPA-PSK WPA-EAP
 #
 # ieee80211w: whether management frame protection is enabled
@@ -1074,6 +1086,8 @@
 #	0 = do not use OCSP stapling (TLS certificate status extension)
 #	1 = try to use OCSP stapling, but not require response
 #	2 = require valid OCSP stapling response
+#	3 = require valid OCSP stapling response for all not-trusted
+#	    certificates in the server certificate chain
 #
 # openssl_ciphers: OpenSSL specific cipher configuration
 #	This can be used to override the global openssl_ciphers configuration