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/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;