From dea76650aa0e7f0034650e5c0c43f77ea6eb17a3 Mon Sep 17 00:00:00 2001
From: Nikos Mavrogiannopoulos <nmav@redhat.com>
Date: Aug 04 2016 06:22:38 +0000
Subject: [PATCH 1/8] Removed pitfalls mentioned for old versions of GnuTLS


Also removed text about explicit initialization no longer
applicable. That text did not apply in any recent Fedora or on RHEL7.

---

diff --git a/en-US/Features-TLS.xml b/en-US/Features-TLS.xml
index a2c0afd..ebdd83d 100644
--- a/en-US/Features-TLS.xml
+++ b/en-US/Features-TLS.xml
@@ -215,58 +215,10 @@
     <section id="sect-Defensive_Coding-TLS-Pitfalls-GNUTLS">
       <title>GNUTLS Pitfalls</title>
       <para>
-	Older versions of GNUTLS had several peculiarities.  As of
-	GNUTLS 3.3.10, they have been addressed, so these are only a
-	concern for applications which have to run with older GNUTLS
-	versions.
+	Older versions of GNUTLS had several peculiarities described
+	in previous versions of this guide; as of GNUTLS 3.3.10, these 
+	issues are no longer applicable.
       </para>
-      <itemizedlist>
-	<listitem>
-	  <para>
-	    The dynamic shared object provided by GNTULS links to
-	    <filename>libpthread.so.0</filename>.  Loading the
-	    threading library too late causes problems, so the main
-	    program should be linked with <literal>-lpthread</literal>
-	    as well.  As a result, it can be difficult to use GNUTLS
-	    in a plugin which is loaded with the
-	    <function>dlopen</function> function.  Another side effect
-	    is that applications which merely link against GNUTLS
-	    (even without actually using it) may incur a substantial
-	    overhead because other libraries automatically switch to
-	    thread-safe algorithms.
-	  </para>
-	</listitem>
-	<listitem>
-	  <para>
-	    The <function>gnutls_global_init</function> function must
-	    be called before using any functionality provided by the
-	    library.  This function is not thread-safe, so external
-	    locking is required, but it is not clear which lock should
-	    be used.  Omitting the synchronization does not just lead
-	    to a memory leak, as it is suggested in the GNUTLS
-	    documentation, but to undefined behavior because there is
-	    no barrier that would enforce memory ordering.
-	  </para>
-	</listitem>
-	<listitem>
-	  <para>
-	    The <function>gnutls_global_deinit</function> function
-	    does not actually deallocate all resources allocated by
-	    <function>gnutls_global_init</function>.  It is currently
-	    not thread-safe.  Therefore, it is best to avoid calling
-	    it altogether.
-	  </para>
-	</listitem>
-	<listitem>
-	  <para>
-	    The X.509 implementation in GNUTLS is rather lenient.  For
-	    example, it is possible to create and process X.509
-	    version&nbsp;1 certificates which carry extensions.  These
-	    certificates are (correctly) rejected by other
-	    implementations.
-	  </para>
-	</listitem>
-      </itemizedlist>
     </section>
     <section id="sect-Defensive_Coding-TLS-Pitfalls-OpenJDK">
       <title>OpenJDK Pitfalls</title>
@@ -522,19 +474,6 @@
 	exploratory and needs to be replaced before production use.
       </para>
       <para>
-	The GNUTLS library needs explicit initialization:
-      </para>
-      <informalexample id="ex-Defensive_Coding-TLS-GNUTLS-Init">
-	<xi:include href="snippets/Features-TLS-GNUTLS-Init.xml"
-		    xmlns:xi="http://www.w3.org/2001/XInclude" />
-      </informalexample>
-      <para>
-	Failing to do so can result in obscure failures in Base64
-	decoding.  See <xref
-	linkend="sect-Defensive_Coding-TLS-Pitfalls-GNUTLS"/> for
-	additional aspects of initialization.
-      </para>
-      <para>
 	Before setting up TLS connections, a credentials objects has
 	to be allocated and initialized with the set of trusted root
 	CAs (<xref
diff --git a/en-US/snippets/Features-TLS-GNUTLS-Init.xml b/en-US/snippets/Features-TLS-GNUTLS-Init.xml
index 519522e..ab2777d 100644
--- a/en-US/snippets/Features-TLS-GNUTLS-Init.xml
+++ b/en-US/snippets/Features-TLS-GNUTLS-Init.xml
@@ -3,5 +3,7 @@
 ]>
 <!-- Automatically generated file.  Do not edit. -->
 <programlisting language="C">
+// This is only necessary if compatibility with GnuTLS prior to
+// 3.3.0 is required.
 gnutls_global_init();
 </programlisting>
diff --git a/src/TLS-Client-GNUTLS.c b/src/TLS-Client-GNUTLS.c
index 4ee2c82..77da93b 100644
--- a/src/TLS-Client-GNUTLS.c
+++ b/src/TLS-Client-GNUTLS.c
@@ -84,6 +84,8 @@ main(int argc, char **argv)
   }
 
   //+ Features TLS-GNUTLS-Init
+  // This is only necessary if compatibility with GnuTLS prior to
+  // 3.3.0 is required.
   gnutls_global_init();
   //-
 

From b1f32880486b7b88246b56e6cec46c0001338c84 Mon Sep 17 00:00:00 2001
From: Nikos Mavrogiannopoulos <nmav@redhat.com>
Date: Aug 04 2016 06:22:45 +0000
Subject: [PATCH 2/8] mention TLS in Transport Layer Security section title


---

diff --git a/en-US/Features-TLS.xml b/en-US/Features-TLS.xml
index ebdd83d..4758e83 100644
--- a/en-US/Features-TLS.xml
+++ b/en-US/Features-TLS.xml
@@ -2,7 +2,7 @@
 <!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
 ]>
 <chapter id="chap-Defensive_Coding-TLS">
-  <title>Transport Layer Security</title>
+  <title>Transport Layer Security (TLS)</title>
   <para>
     Transport Layer Security (TLS, formerly Secure Sockets
     Layer/SSL) is the recommended way to to protect integrity and

From 554750316e15c28402572c4f91b74ceceb6bce27 Mon Sep 17 00:00:00 2001
From: Nikos Mavrogiannopoulos <nmav@redhat.com>
Date: Aug 04 2016 06:22:49 +0000
Subject: [PATCH 3/8] TLS: gnutls: use gnutls_certificate_set_x509_system_trust


Avoid hard-coding any paths and use the function which is
portable across operating systems.

---

diff --git a/en-US/snippets/Features-TLS-Client-GNUTLS-Credentials.xml b/en-US/snippets/Features-TLS-Client-GNUTLS-Credentials.xml
index 6a5cd09..f69f552 100644
--- a/en-US/snippets/Features-TLS-Client-GNUTLS-Credentials.xml
+++ b/en-US/snippets/Features-TLS-Client-GNUTLS-Credentials.xml
@@ -11,19 +11,15 @@ if (ret != GNUTLS_E_SUCCESS) {
 	    gnutls_strerror(ret));
   exit(1);
 }
-// gnutls_certificate_set_x509_system_trust needs GNUTLS version 3.0
-// or newer, so we hard-code the path to the certificate store
-// instead.
-static const char ca_bundle[] = "/etc/ssl/certs/ca-bundle.crt";
-ret = gnutls_certificate_set_x509_trust_file
-  (cred, ca_bundle, GNUTLS_X509_FMT_PEM);
+
+ret = gnutls_certificate_set_x509_system_trust(cred);
 if (ret == 0) {
-  fprintf(stderr, "error: no certificates found in: %s\n", ca_bundle);
+  fprintf(stderr, "error: no certificates found in system trust store\n");
   exit(1);
 }
 if (ret &#60; 0) {
-  fprintf(stderr, "error: gnutls_certificate_set_x509_trust_files(%s): %s\n",
-	    ca_bundle, gnutls_strerror(ret));
+  fprintf(stderr, "error: gnutls_certificate_set_x509_system_trust: %s\n",
+	    gnutls_strerror(ret));
   exit(1);
 }
 </programlisting>
diff --git a/src/TLS-Client-GNUTLS.c b/src/TLS-Client-GNUTLS.c
index 77da93b..b0f5ce6 100644
--- a/src/TLS-Client-GNUTLS.c
+++ b/src/TLS-Client-GNUTLS.c
@@ -98,19 +98,15 @@ main(int argc, char **argv)
 	    gnutls_strerror(ret));
     exit(1);
   }
-  // gnutls_certificate_set_x509_system_trust needs GNUTLS version 3.0
-  // or newer, so we hard-code the path to the certificate store
-  // instead.
-  static const char ca_bundle[] = "/etc/ssl/certs/ca-bundle.crt";
-  ret = gnutls_certificate_set_x509_trust_file
-    (cred, ca_bundle, GNUTLS_X509_FMT_PEM);
+
+  ret = gnutls_certificate_set_x509_system_trust(cred);
   if (ret == 0) {
-    fprintf(stderr, "error: no certificates found in: %s\n", ca_bundle);
+    fprintf(stderr, "error: no certificates found in system trust store\n");
     exit(1);
   }
   if (ret < 0) {
-    fprintf(stderr, "error: gnutls_certificate_set_x509_trust_files(%s): %s\n",
-	    ca_bundle, gnutls_strerror(ret));
+    fprintf(stderr, "error: gnutls_certificate_set_x509_system_trust: %s\n",
+	    gnutls_strerror(ret));
     exit(1);
   }
   //-

From 1c84959ddbc00d09a64771e563ab60a68011cfcd Mon Sep 17 00:00:00 2001
From: Nikos Mavrogiannopoulos <nmav@redhat.com>
Date: Aug 04 2016 06:22:52 +0000
Subject: [PATCH 4/8] Mention only gnutls_certificate_verify_peers3()


Also use gnutls_transport_set_int() which requires no casts.
Also remove any description of code no longer applicable
in Fedora 2X or RHEL7.

---

diff --git a/en-US/Features-TLS.xml b/en-US/Features-TLS.xml
index 4758e83..1789853 100644
--- a/en-US/Features-TLS.xml
+++ b/en-US/Features-TLS.xml
@@ -515,7 +515,7 @@
       </example>
       <para>
 	After the handshake has been completed, the server certificate
-	needs to be verified (<xref
+	needs to be verified against the server's hostname (<xref
 	linkend="ex-Defensive_Coding-TLS-Client-GNUTLS-Verify"/>).  In
 	the example, the user-defined
 	<function>certificate_validity_override</function> function is
@@ -529,29 +529,6 @@
 		    xmlns:xi="http://www.w3.org/2001/XInclude" />
       </example>
       <para>
-	In the next step (<xref
-	linkend="ex-Defensive_Coding-TLS-Client-GNUTLS-Match"/>, the
-	certificate must be matched against the host name (note the
-	unusual return value from
-	<function>gnutls_x509_crt_check_hostname</function>).  Again,
-	an override function
-	<function>certificate_host_name_override</function> is called.
-	Note that the override must be keyed to the certificate
-	<emphasis>and</emphasis> the host name.  The function call can
-	be omitted if the override is not needed.
-      </para>
-      <example id="ex-Defensive_Coding-TLS-Client-GNUTLS-Match">
-	<title>Matching the server host name and certificate in a
-	GNUTLS client</title>
-	<xi:include href="snippets/Features-TLS-Client-GNUTLS-Match.xml"
-		    xmlns:xi="http://www.w3.org/2001/XInclude" />
-      </example>
-      <para>
-	In newer GNUTLS versions, certificate checking and host name
-	validation can be combined using the
-	<function>gnutls_certificate_verify_peers3</function> function.
-      </para>
-      <para>
 	An established TLS session can be used for sending and
 	receiving data, as in <xref
 	linkend="ex-Defensive_Coding-TLS-GNUTLS-Use"/>.
diff --git a/en-US/snippets/Features-TLS-Client-GNUTLS-Connect.xml b/en-US/snippets/Features-TLS-Client-GNUTLS-Connect.xml
index fbf1420..390405e 100644
--- a/en-US/snippets/Features-TLS-Client-GNUTLS-Connect.xml
+++ b/en-US/snippets/Features-TLS-Client-GNUTLS-Connect.xml
@@ -31,7 +31,7 @@ if (ret != GNUTLS_E_SUCCESS) {
 
 // Associate the socket with the session object and set the server
 // name.
-gnutls_transport_set_ptr(session, (gnutls_transport_ptr_t)(uintptr_t)sockfd);
+gnutls_transport_set_int(session, sockfd);
 ret = gnutls_server_name_set(session, GNUTLS_NAME_DNS,
 			       host, strlen(host));
 if (ret != GNUTLS_E_SUCCESS) {
diff --git a/en-US/snippets/Features-TLS-Client-GNUTLS-Verify.xml b/en-US/snippets/Features-TLS-Client-GNUTLS-Verify.xml
index a3c9365..eb89535 100644
--- a/en-US/snippets/Features-TLS-Client-GNUTLS-Verify.xml
+++ b/en-US/snippets/Features-TLS-Client-GNUTLS-Verify.xml
@@ -15,9 +15,9 @@ if (certs == NULL || certslen == 0) {
 
 // Validate the certificate chain.
 unsigned status = (unsigned)-1;
-ret = gnutls_certificate_verify_peers2(session, &#38;status);
+ret = gnutls_certificate_verify_peers3(session, host, &#38;status);
 if (ret != GNUTLS_E_SUCCESS) {
-  fprintf(stderr, "error: gnutls_certificate_verify_peers2: %s\n",
+  fprintf(stderr, "error: gnutls_certificate_verify_peers3: %s\n",
 	    gnutls_strerror(ret));
   exit(1);
 }
diff --git a/src/TLS-Client-GNUTLS.c b/src/TLS-Client-GNUTLS.c
index b0f5ce6..7c0fa7b 100644
--- a/src/TLS-Client-GNUTLS.c
+++ b/src/TLS-Client-GNUTLS.c
@@ -160,7 +160,7 @@ main(int argc, char **argv)
 
   // Associate the socket with the session object and set the server
   // name.
-  gnutls_transport_set_ptr(session, (gnutls_transport_ptr_t)(uintptr_t)sockfd);
+  gnutls_transport_set_int(session, sockfd);
   ret = gnutls_server_name_set(session, GNUTLS_NAME_DNS,
 			       host, strlen(host));
   if (ret != GNUTLS_E_SUCCESS) {
@@ -191,9 +191,9 @@ main(int argc, char **argv)
 
   // Validate the certificate chain.
   unsigned status = (unsigned)-1;
-  ret = gnutls_certificate_verify_peers2(session, &status);
+  ret = gnutls_certificate_verify_peers3(session, host, &status);
   if (ret != GNUTLS_E_SUCCESS) {
-    fprintf(stderr, "error: gnutls_certificate_verify_peers2: %s\n",
+    fprintf(stderr, "error: gnutls_certificate_verify_peers3: %s\n",
 	    gnutls_strerror(ret));
     exit(1);
   }
@@ -217,33 +217,6 @@ main(int argc, char **argv)
   }
   //-
 
-  //+ Features TLS-Client-GNUTLS-Match
-  // Match the peer certificate against the host name.
-  // We can only obtain a set of DER-encoded certificates from the
-  // session object, so we have to re-parse the peer certificate into
-  // a certificate object.
-  gnutls_x509_crt_t cert;
-  ret = gnutls_x509_crt_init(&cert);
-  if (ret != GNUTLS_E_SUCCESS) {
-    fprintf(stderr, "error: gnutls_x509_crt_init: %s\n",
-	    gnutls_strerror(ret));
-    exit(1);
-  }
-  // The peer certificate is the first certificate in the list.
-  ret = gnutls_x509_crt_import(cert, certs, GNUTLS_X509_FMT_DER);
-  if (ret != GNUTLS_E_SUCCESS) {
-    fprintf(stderr, "error: gnutls_x509_crt_import: %s\n",
-	    gnutls_strerror(ret));
-    exit(1);
-  }
-  ret = gnutls_x509_crt_check_hostname(cert, host);
-  if (ret == 0 && !certificate_host_name_override(certs[0], host)) {
-    fprintf(stderr, "error: host name does not match certificate\n");
-    exit(1);
-  }
-  gnutls_x509_crt_deinit(cert);
-  //-
-
   //+ Features TLS-GNUTLS-Use
   char buf[4096];
   snprintf(buf, sizeof(buf), "GET / HTTP/1.0\r\nHost: %s\r\n\r\n", host);

From a69cea175c4059de3736dd138c0d6160703b7370 Mon Sep 17 00:00:00 2001
From: Nikos Mavrogiannopoulos <nmav@redhat.com>
Date: Aug 04 2016 06:22:54 +0000
Subject: [PATCH 5/8] TLS: document the update-ca-trust


---

diff --git a/en-US/Features-TLS.xml b/en-US/Features-TLS.xml
index 1789853..2f4a653 100644
--- a/en-US/Features-TLS.xml
+++ b/en-US/Features-TLS.xml
@@ -281,16 +281,17 @@
 	<para>
 	  The client must configure the TLS library to use a set of
 	  trusted root certificates.  These certificates are provided
-	  by the system in <filename
-	  class="directory">/etc/ssl/certs</filename> or files derived
-	  from it.
+	  by the system in various formats and files. These are documented in <literal>update-ca-trust</literal>
+	  man page in Fedora. Portable applications should not hard-code
+	  any paths; they should rely on APIs which set the default
+	  for the system trust store.
 	</para>
       </listitem>
       <listitem>
 	<para>
 	  The client selects sufficiently strong cryptographic
 	  primitives and disables insecure ones (such as no-op
-	  encryption). Compression and SSL version 2 support must be
+	  encryption). Compression support and SSL version 3 or lower must be
 	  disabled (including the SSLv2-compatible handshake).
 	</para>
       </listitem>
@@ -546,7 +547,7 @@
 	linkend="ex-Defensive_Coding-TLS-GNUTLS-Disconnect"/>).
       </para>
       <example id="ex-Defensive_Coding-TLS-GNUTLS-Disconnect">
-	<title>Using a GNUTLS session</title>
+	<title>Closing a GNUTLS session in an orderly fashion</title>
 	<xi:include href="snippets/Features-TLS-GNUTLS-Disconnect.xml"
 		    xmlns:xi="http://www.w3.org/2001/XInclude" />
       </example>

From 0baf3aab19a1df777eb1c47217eea3203fb9560e Mon Sep 17 00:00:00 2001
From: Nikos Mavrogiannopoulos <nmav@redhat.com>
Date: Aug 04 2016 06:22:57 +0000
Subject: [PATCH 6/8] TLS-Client-NSS: enable AES-GCM


---

diff --git a/en-US/snippets/Features-TLS-NSS-Init.xml b/en-US/snippets/Features-TLS-NSS-Init.xml
index 6352282..939ff39 100644
--- a/en-US/snippets/Features-TLS-NSS-Init.xml
+++ b/en-US/snippets/Features-TLS-NSS-Init.xml
@@ -16,6 +16,14 @@ if (ctx == NULL) {
 
 // Ciphers to enable.
 static const PRUint16 good_ciphers[] = {
+  TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+  TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+  TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+  TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
+  TLS_RSA_WITH_AES_128_GCM_SHA256,
+  TLS_RSA_WITH_AES_256_GCM_SHA384,
+  TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
+  TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
   TLS_RSA_WITH_AES_128_CBC_SHA,
   TLS_RSA_WITH_AES_256_CBC_SHA,
   SSL_RSA_WITH_3DES_EDE_CBC_SHA,
diff --git a/src/TLS-Client-NSS.c b/src/TLS-Client-NSS.c
index 3faac5c..49525a0 100644
--- a/src/TLS-Client-NSS.c
+++ b/src/TLS-Client-NSS.c
@@ -107,6 +107,14 @@ main(int argc, char **argv)
 
   // Ciphers to enable.
   static const PRUint16 good_ciphers[] = {
+    TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+    TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+    TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+    TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
+    TLS_RSA_WITH_AES_128_GCM_SHA256,
+    TLS_RSA_WITH_AES_256_GCM_SHA384,
+    TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
+    TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
     TLS_RSA_WITH_AES_128_CBC_SHA,
     TLS_RSA_WITH_AES_256_CBC_SHA,
     SSL_RSA_WITH_3DES_EDE_CBC_SHA,

From f5efbe80bc13ee3ced7ff2ed1f116baaf8f8b8a8 Mon Sep 17 00:00:00 2001
From: Nikos Mavrogiannopoulos <nmav@redhat.com>
Date: Aug 04 2016 06:23:02 +0000
Subject: [PATCH 7/8] TLS: mention upstream documentation for libraries


---

diff --git a/en-US/Features-TLS.xml b/en-US/Features-TLS.xml
index 2f4a653..19e3db5 100644
--- a/en-US/Features-TLS.xml
+++ b/en-US/Features-TLS.xml
@@ -7,8 +7,20 @@
     Transport Layer Security (TLS, formerly Secure Sockets
     Layer/SSL) is the recommended way to to protect integrity and
     confidentiality while data is transferred over an untrusted
-    network connection, and to identify the endpoint.
+    network connection, and to identify the endpoint. At this
+    chapter we describe the available libraries in Fedora as well
+    as known pitfalls, and safe ways to write applications with them.
   </para>
+  <para>
+      When using any library, in addition to this guide, it is recommended to consult the
+      library' documentation.
+  </para>
+  <itemizedlist>
+    <listitem><para><ulink url="https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS">NSS documentation</ulink></para></listitem>
+    <listitem><para><ulink url="http://www.gnutls.org/manual/">GNUTLS documentation</ulink></para></listitem>
+    <listitem><para><ulink url="https://www.openssl.org/docs/">OpenSSL documentation</ulink></para></listitem>
+    <listitem><para><ulink url="https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html">OpenJDK documentation</ulink></para></listitem>
+  </itemizedlist>
   <section id="sect-Defensive_Coding-TLS-Pitfalls">
     <title>Common Pitfalls</title>
     <para>

From 9d525b7fd6528a5905dcd74013f35341d943580d Mon Sep 17 00:00:00 2001
From: Nikos Mavrogiannopoulos <nmav@redhat.com>
Date: Aug 04 2016 06:24:32 +0000
Subject: [PATCH 8/8] TLS: added GNUTLS server example


---

diff --git a/en-US/Features-TLS.xml b/en-US/Features-TLS.xml
index 19e3db5..4632abf 100644
--- a/en-US/Features-TLS.xml
+++ b/en-US/Features-TLS.xml
@@ -939,4 +939,138 @@
       </informalexample>
     </section>
   </section>
-</chapter>
+  <section id="sect-Defensive_Coding-TLS-Server">
+    <title>TLS Server</title>
+    <para>
+      Secure use of TLS in a server generally involves all of the
+      following steps.  (Individual instructions for specific TLS
+      implementations follow in the next sections.)
+    </para>
+    <itemizedlist>
+      <listitem>
+	<para>
+	  The server selects sufficiently strong cryptographic
+	  primitives and disables insecure ones (such as no-op
+	  encryption). Compression support and SSL version 3 or lower must be
+	  disabled (including the SSLv2-compatible handshake).
+	</para>
+      </listitem>
+      <listitem>
+	<para>
+	  The server sets its certificate and key files. The server may
+	  have multiple such files, either because it is serving multiple host
+	  names, or because (for example) it has both RSA and ECDSA parameters.
+	</para>
+      </listitem>
+      <listitem>
+	<para>
+	  The server needs to specify an OCSP status request response file.
+	  That is, a response from the certificate issuer's OCSP server which
+	  states that the certificate is valid. This response file should be updated
+	  during the server's operational lifetime. The update frequency depends
+	  on the OCSP server's update frequency. Typically that's between few days
+	  and a week.
+	</para>
+	<para>
+	  Setting this file allows the connecting clients to obtain and verify the
+	  OCSP response for the server's certificate as soon, without contacting
+	  third party servers. This is often called a stapled OCSP response, and
+	  it is possible for the server to require his clients to check the OCSP response
+	  by marking his certificate as OCSP MUST-staple (which is defined on
+	  any unfortunately named RFC: "rfc7633: Transport Layer Security (TLS) Feature Extension".
+	</para>
+      </listitem>
+    </itemizedlist>
+    <section id="sect-Defensive_Coding-TLS-Server-GNUTLS">
+      <title>Implementation of TLS Servers With GNUTLS</title>
+      <para>
+        While there are several types of TLS Servers, in this example we explore
+        a basic TLS server where the server is authenticated by the client using
+        certificate authentication.
+      </para>
+      <para>
+	Before setting up TLS connections, a credentials objects has
+	to be allocated and initialized with the server's certificate
+	and keys (<xref
+	linkend="ex-Defensive_Coding-TLS-Server-GNUTLS-Credentials"/>).
+      </para>
+      <para>
+        In the case of a Hardware Security Module, the <function>gnutls_certificate_set_x509_key_file</function>
+        should be provided with PKCS#11 URLs for the key and/or the certificate instead of files.
+      </para>
+      <example id="ex-Defensive_Coding-TLS-Server-GNUTLS-Credentials">
+	<title>Initializing a GNUTLS credentials structure</title>
+	<xi:include href="snippets/Features-TLS-Server-GNUTLS-Credentials.xml"
+		    xmlns:xi="http://www.w3.org/2001/XInclude" />
+      </example>
+      <para>
+	Similarly a set of acceptable ciphersuites must be generated
+	(<xref
+	linkend="ex-Defensive_Coding-TLS-Server-GNUTLS-Priorities"/>).
+      </para>
+      <example id="ex-Defensive_Coding-TLS-Server-GNUTLS-Priorities">
+	<title>Initializing a GNUTLS priorities structure</title>
+	<xi:include href="snippets/Features-TLS-Server-GNUTLS-Priorities.xml"
+		    xmlns:xi="http://www.w3.org/2001/XInclude" />
+      </example>
+      <para>
+	After the last TLS connection has been closed, these credentials
+	and priorities cache objects should be freed:
+      </para>
+      <informalexample>
+	<xi:include href="snippets/Features-TLS-Server-GNUTLS-Credentials-Close.xml"
+		    xmlns:xi="http://www.w3.org/2001/XInclude" />
+      </informalexample>
+      <para>
+	During its lifetime, the credentials object can be used to
+	initialize TLS session objects from multiple threads, provided
+	that it is not changed.
+      </para>
+      <para>
+        To support session resumption, GNUTLS requires to specify a set of
+        functions for storage and retrieval of session data. To support resumption
+        using session tickets (i.e., the client is expected to store its resumption data),
+        GNUTLS requires to generate an encryption key using <function>gnutls_session_ticket_key_generate</function>
+        and associate it with a server session with <function>gnutls_session_ticket_enable_server</function>.
+        We will not explore session resumption in our example.
+      </para>
+      <para>
+        The server may specify whether it requires a client to authenticate
+        itself using a certificate or not. If a client sends a certificate
+        the server must verify it similarly to a Client verifying a server's
+        certificate (<xref
+        linkend="ex-Defensive_Coding-TLS-Client-GNUTLS-Verify"/>). That
+        verification should occur in a callback set using <function>gnutls_session_set_verify_function</function>.
+        We will not explore further this option in this guide.
+      </para>
+      <example id="ex-Defensive_Coding-TLS-Server-GNUTLS-Accept">
+	<title>Establishing a TLS server connection using GNUTLS</title>
+	<xi:include href="snippets/Features-TLS-Server-GNUTLS-Accept.xml"
+		    xmlns:xi="http://www.w3.org/2001/XInclude" />
+      </example>
+      <para>
+	An established TLS session can be used for sending and
+	receiving data, identically as in the client case <xref
+	linkend="ex-Defensive_Coding-TLS-GNUTLS-Use"/>.
+      </para>
+      <example id="ex-Defensive_Coding-TLS-Server-GNUTLS-Use">
+	<title>Using a GNUTLS session</title>
+	<xi:include href="snippets/Features-TLS-GNUTLS-Use.xml"
+		    xmlns:xi="http://www.w3.org/2001/XInclude" />
+      </example>
+      <para>
+	To shut down a connection in an orderly manner, you
+	should call the <function>gnutls_bye</function> function,
+	and, the session object can be deallocated using
+	<function>gnutls_deinit</function>. This is similar to the client
+	case, but in this case the server doesn't wait for the client
+	reply of the connection (see <xref
+	linkend="ex-Defensive_Coding-TLS-Server-GNUTLS-Disconnect"/>).
+      </para>
+      <example id="ex-Defensive_Coding-TLS-Server-GNUTLS-Disconnect">
+	<title>Closing a GNUTLS session in an orderly fashion</title>
+	<xi:include href="snippets/Features-TLS-Server-GNUTLS-Disconnect.xml"
+		    xmlns:xi="http://www.w3.org/2001/XInclude" />
+      </example>
+    </section>
+  </section></chapter>
diff --git a/en-US/snippets/Features-TLS-Server-GNUTLS-Accept.xml b/en-US/snippets/Features-TLS-Server-GNUTLS-Accept.xml
new file mode 100644
index 0000000..8aac205
--- /dev/null
+++ b/en-US/snippets/Features-TLS-Server-GNUTLS-Accept.xml
@@ -0,0 +1,45 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+]>
+<!-- Automatically generated file.  Do not edit. -->
+<programlisting language="C">
+// Create the session object.
+for (;;) {
+  gnutls_session_t session;
+
+  sa_cli_len = sizeof(sa_cli);
+  sockfd = accept(listenfd, (struct sockaddr *) &#38;sa_cli, &#38;sa_cli_len);
+
+  ret = gnutls_init(&#38;session, GNUTLS_SERVER);
+  if (ret != GNUTLS_E_SUCCESS) {
+    fprintf(stderr, "error: gnutls_init: %s\n", gnutls_strerror(ret));
+    exit(1);
+  }
+
+  // Set the acceptable ciphersuites
+  ret = gnutls_priority_set(session, priority_cache);
+  if (ret != GNUTLS_E_SUCCESS) {
+    fprintf(stderr, "error: gnutls_priority_set: %s\n",
+	      gnutls_strerror(ret));
+    exit(1);
+  }
+
+  // Set the server's certificate object
+  ret = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, cred);
+  if (ret != GNUTLS_E_SUCCESS) {
+    fprintf(stderr, "error: gnutls_credentials_set: %s\n",
+	      gnutls_strerror(ret));
+    exit(1);
+  }
+
+  gnutls_certificate_server_set_request(session, GNUTLS_CERT_IGNORE);
+
+  gnutls_transport_set_int(session, sockfd);
+
+  // Establish the session.
+  ret = gnutls_handshake(session);
+  if (ret != GNUTLS_E_SUCCESS) {
+    fprintf(stderr, "error: gnutls_handshake: %s\n", gnutls_strerror(ret));
+    exit(1);
+  }
+</programlisting>
diff --git a/en-US/snippets/Features-TLS-Server-GNUTLS-Credentials-Close.xml b/en-US/snippets/Features-TLS-Server-GNUTLS-Credentials-Close.xml
new file mode 100644
index 0000000..6f7418c
--- /dev/null
+++ b/en-US/snippets/Features-TLS-Server-GNUTLS-Credentials-Close.xml
@@ -0,0 +1,8 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+]>
+<!-- Automatically generated file.  Do not edit. -->
+<programlisting language="C">
+gnutls_priority_deinit(priority_cache);
+gnutls_certificate_free_credentials(cred);
+</programlisting>
diff --git a/en-US/snippets/Features-TLS-Server-GNUTLS-Credentials.xml b/en-US/snippets/Features-TLS-Server-GNUTLS-Credentials.xml
new file mode 100644
index 0000000..e16ff17
--- /dev/null
+++ b/en-US/snippets/Features-TLS-Server-GNUTLS-Credentials.xml
@@ -0,0 +1,42 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+]>
+<!-- Automatically generated file.  Do not edit. -->
+<programlisting language="C">
+// Load the trusted CA certificates.
+const char *keyfile = argv[2];
+const char *certfile = argv[3];
+const char *ocspfile = NULL;
+
+if (argc &#62; 4)
+  ocspfile = argv[4];
+
+gnutls_certificate_credentials_t cred = NULL;
+int ret = gnutls_certificate_allocate_credentials(&#38;cred);
+if (ret != GNUTLS_E_SUCCESS) {
+  fprintf(stderr, "error: gnutls_certificate_allocate_credentials: %s\n",
+	    gnutls_strerror(ret));
+  exit(1);
+}
+
+// Set the server certificate and key files. These can be PEM
+// files, or PKCS#11 URLs in case an HSM is in use.
+ret =
+    gnutls_certificate_set_x509_key_file(cred, certfile, keyfile,
+					   GNUTLS_X509_FMT_PEM);
+if (ret &#60; 0) {
+  fprintf(stderr, "error: gnutls_certificate_set_x509_key_file: %s\n",
+	    gnutls_strerror(ret));
+  exit(1);
+}
+
+if (ocspfile) {
+  ret = gnutls_certificate_set_ocsp_status_request_file(cred, ocspfile, 0);
+  if (ret &#60; 0) {
+    fprintf(stderr,
+	      "error: gnutls_certificate_set_ocsp_status_request_file: %s\n",
+	      gnutls_strerror(ret));
+    exit(1);
+  }
+}
+</programlisting>
diff --git a/en-US/snippets/Features-TLS-Server-GNUTLS-Disconnect.xml b/en-US/snippets/Features-TLS-Server-GNUTLS-Disconnect.xml
new file mode 100644
index 0000000..bd02df0
--- /dev/null
+++ b/en-US/snippets/Features-TLS-Server-GNUTLS-Disconnect.xml
@@ -0,0 +1,14 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+]>
+<!-- Automatically generated file.  Do not edit. -->
+<programlisting language="C">
+// Initiate an orderly connection shutdown.
+ret = gnutls_bye(session, GNUTLS_SHUT_WR);
+if (ret &#60; 0) {
+  fprintf(stderr, "error: gnutls_bye: %s\n", gnutls_strerror(ret));
+  exit(1);
+}
+// Free the session object.
+gnutls_deinit(session);
+</programlisting>
diff --git a/en-US/snippets/Features-TLS-Server-GNUTLS-Priorities.xml b/en-US/snippets/Features-TLS-Server-GNUTLS-Priorities.xml
new file mode 100644
index 0000000..bce0b49
--- /dev/null
+++ b/en-US/snippets/Features-TLS-Server-GNUTLS-Priorities.xml
@@ -0,0 +1,18 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+]>
+<!-- Automatically generated file.  Do not edit. -->
+<programlisting language="C">
+// Create the ciphersuite priorities object
+gnutls_priority_t priority_cache;
+const char *errpos = NULL;
+
+ret = gnutls_priority_init(&#38;priority_cache, "PERFORMANCE:%SERVER_PRECEDENCE", &#38;errpos);
+if (ret == GNUTLS_E_PARSING_ERROR) {
+  fprintf(stderr, "error: gnutls_priority_init parsing error at: %s\n", errpos);
+  exit(1);
+} else if (ret &#60; 0) {
+  fprintf(stderr, "error: gnutls_priority_init: %s\n", gnutls_strerror(ret));
+  exit(1);
+}
+</programlisting>
diff --git a/src/TLS-Server-GNUTLS.c b/src/TLS-Server-GNUTLS.c
new file mode 100644
index 0000000..33182ce
--- /dev/null
+++ b/src/TLS-Server-GNUTLS.c
@@ -0,0 +1,162 @@
+#include <assert.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <gnutls/gnutls.h>
+#include <gnutls/crypto.h>
+#include <gnutls/x509.h>
+
+#include "tcp_connect.h"
+
+static void __attribute__ ((noreturn))
+    usage(const char *progname)
+{
+  fprintf(stderr, "usage: %s PORT KEY CERT OCSP\n", progname);
+  exit(2);
+}
+
+int main(int argc, char **argv)
+{
+  if (argc < 4) {
+    usage(argv[0]);
+  }
+  //+ Features TLS-GNUTLS-Init
+  // This is only necessary if compatibility with GnuTLS prior to
+  // 3.3.0 is required.
+  gnutls_global_init();
+  //-
+
+  //+ Features TLS-Server-GNUTLS-Credentials
+  // Load the trusted CA certificates.
+  const char *keyfile = argv[2];
+  const char *certfile = argv[3];
+  const char *ocspfile = NULL;
+
+  if (argc > 4)
+    ocspfile = argv[4];
+
+  gnutls_certificate_credentials_t cred = NULL;
+  int ret = gnutls_certificate_allocate_credentials(&cred);
+  if (ret != GNUTLS_E_SUCCESS) {
+    fprintf(stderr, "error: gnutls_certificate_allocate_credentials: %s\n",
+	    gnutls_strerror(ret));
+    exit(1);
+  }
+
+  // Set the server certificate and key files. These can be PEM
+  // files, or PKCS#11 URLs in case an HSM is in use.
+  ret =
+      gnutls_certificate_set_x509_key_file(cred, certfile, keyfile,
+					   GNUTLS_X509_FMT_PEM);
+  if (ret < 0) {
+    fprintf(stderr, "error: gnutls_certificate_set_x509_key_file: %s\n",
+	    gnutls_strerror(ret));
+    exit(1);
+  }
+
+  if (ocspfile) {
+    ret = gnutls_certificate_set_ocsp_status_request_file(cred, ocspfile, 0);
+    if (ret < 0) {
+      fprintf(stderr,
+	      "error: gnutls_certificate_set_ocsp_status_request_file: %s\n",
+	      gnutls_strerror(ret));
+      exit(1);
+    }
+  }
+  //-
+  //+ Features TLS-Server-GNUTLS-Priorities
+  // Create the ciphersuite priorities object
+  gnutls_priority_t priority_cache;
+  const char *errpos = NULL;
+
+  ret = gnutls_priority_init(&priority_cache, "PERFORMANCE:%SERVER_PRECEDENCE", &errpos);
+  if (ret == GNUTLS_E_PARSING_ERROR) {
+    fprintf(stderr, "error: gnutls_priority_init parsing error at: %s\n", errpos);
+    exit(1);
+  } else if (ret < 0) {
+    fprintf(stderr, "error: gnutls_priority_init: %s\n", gnutls_strerror(ret));
+    exit(1);
+  }
+  //-
+
+  const int port = atoi(argv[1]);
+  struct sockaddr_in sa_serv;
+  struct sockaddr_storage sa_cli;
+  socklen_t sa_cli_len;
+  int sockfd, listenfd;
+
+  listenfd = socket(AF_INET, SOCK_STREAM, 0);
+  memset(&sa_serv, '\0', sizeof(sa_serv));
+  sa_serv.sin_family = AF_INET;
+  sa_serv.sin_addr.s_addr = INADDR_ANY;
+  sa_serv.sin_port = htons(port);
+
+  if (bind(listenfd, (struct sockaddr *)&sa_serv, sizeof(sa_serv)) < 0) {
+    perror("bind");
+    exit(1);
+  }
+  //+ Features TLS-Server-GNUTLS-Accept
+  // Create the session object.
+  for (;;) {
+    gnutls_session_t session;
+
+    sa_cli_len = sizeof(sa_cli);
+    sockfd = accept(listenfd, (struct sockaddr *) &sa_cli, &sa_cli_len);
+
+    ret = gnutls_init(&session, GNUTLS_SERVER);
+    if (ret != GNUTLS_E_SUCCESS) {
+      fprintf(stderr, "error: gnutls_init: %s\n", gnutls_strerror(ret));
+      exit(1);
+    }
+
+    // Set the acceptable ciphersuites
+    ret = gnutls_priority_set(session, priority_cache);
+    if (ret != GNUTLS_E_SUCCESS) {
+      fprintf(stderr, "error: gnutls_priority_set: %s\n",
+	      gnutls_strerror(ret));
+      exit(1);
+    }
+
+    // Set the server's certificate object
+    ret = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, cred);
+    if (ret != GNUTLS_E_SUCCESS) {
+      fprintf(stderr, "error: gnutls_credentials_set: %s\n",
+	      gnutls_strerror(ret));
+      exit(1);
+    }
+
+    gnutls_certificate_server_set_request(session, GNUTLS_CERT_IGNORE);
+
+    gnutls_transport_set_int(session, sockfd);
+
+    // Establish the session.
+    ret = gnutls_handshake(session);
+    if (ret != GNUTLS_E_SUCCESS) {
+      fprintf(stderr, "error: gnutls_handshake: %s\n", gnutls_strerror(ret));
+      exit(1);
+    }
+    //-
+
+    //+ Features TLS-Server-GNUTLS-Disconnect
+    // Initiate an orderly connection shutdown.
+    ret = gnutls_bye(session, GNUTLS_SHUT_WR);
+    if (ret < 0) {
+      fprintf(stderr, "error: gnutls_bye: %s\n", gnutls_strerror(ret));
+      exit(1);
+    }
+    // Free the session object.
+    gnutls_deinit(session);
+    //-
+    close(sockfd);
+  }
+  //+ Features TLS-Server-GNUTLS-Credentials-Close
+  gnutls_priority_deinit(priority_cache);
+  gnutls_certificate_free_credentials(cred);
+  //-
+}
diff --git a/src/src.mk b/src/src.mk
index 18bd592..f556eea 100644
--- a/src/src.mk
+++ b/src/src.mk
@@ -34,8 +34,9 @@ JCFLAGS_TLSClientOpenJDK = -source 1.6 -target 1.6
 compile_and_link += C-String-Functions
 compile_and_link += TLS-Client-OpenSSL
 LIBS_TLS-Client-OpenSSL = -lssl -lcrypto
-compile_and_link += TLS-Client-GNUTLS
+compile_and_link += TLS-Client-GNUTLS TLS-Server-GNUTLS
 LIBS_TLS-Client-GNUTLS = -lgnutls
+LIBS_TLS-Server-GNUTLS = -lgnutls
 compile_and_link += TLS-Client-NSS
 CFLAGS_TLS-Client-NSS = -I/usr/include/nspr4 -I/usr/include/nss3
 LIBS_TLS-Client-NSS = -lnss3 -lnspr4 -lssl3

