#3 Updates in TLS protocol section
Closed 6 years ago by mjahoda. Opened 7 years ago by nmav.
nmav/defensive-coding-guide update-tls  into  master

TLS: added GNUTLS server example
Nikos Mavrogiannopoulos • 7 years ago  
TLS: mention upstream documentation for libraries
Nikos Mavrogiannopoulos • 7 years ago  
TLS-Client-NSS: enable AES-GCM
Nikos Mavrogiannopoulos • 7 years ago  
TLS: document the update-ca-trust
Nikos Mavrogiannopoulos • 7 years ago  
Mention only gnutls_certificate_verify_peers3()
Nikos Mavrogiannopoulos • 7 years ago  
mention TLS in Transport Layer Security section title
Nikos Mavrogiannopoulos • 7 years ago  
Removed pitfalls mentioned for old versions of GnuTLS
Nikos Mavrogiannopoulos • 7 years ago  
file modified
+159 -96
@@ -2,13 +2,25 @@ 

  <!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

      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>
@@ -215,58 +227,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>
@@ -329,16 +293,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>
@@ -522,19 +487,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
@@ -576,7 +528,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
@@ -590,29 +542,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"/>.
@@ -630,7 +559,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>
@@ -1010,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>

@@ -31,7 +31,7 @@ 

  

  // 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) {

@@ -11,19 +11,15 @@ 

  	    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>

@@ -15,9 +15,9 @@ 

  

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

  }

@@ -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>

@@ -16,6 +16,14 @@ 

  

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

@@ -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>

@@ -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>

@@ -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>

@@ -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>

@@ -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>

file modified
+10 -39
@@ -84,6 +84,8 @@ 

    }

  

    //+ Features TLS-GNUTLS-Init

+   // This is only necessary if compatibility with GnuTLS prior to

+   // 3.3.0 is required.

    gnutls_global_init();

    //-

  
@@ -96,19 +98,15 @@ 

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

    }

    //-
@@ -162,7 +160,7 @@ 

  

    // 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) {
@@ -193,9 +191,9 @@ 

  

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

    }
@@ -219,33 +217,6 @@ 

    }

    //-

  

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

file modified
+8
@@ -107,6 +107,14 @@ 

  

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

@@ -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);

+   //-

+ }

file modified
+2 -1
@@ -34,8 +34,9 @@ 

  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

This update brings the gnutls description up-to-date with current Fedora releases, mentions the shared system certificates in Fedora, adds a server example with gnutls, and updates the set of algorithms used in NSS client example.

rebased

7 years ago

Note that the repository includes the snippets/ directory which is auto-generated. This patch set updates the auto-generated files as well.

8 new commits added

  • TLS: added GNUTLS server example
  • TLS: mention upstream documentation for libraries
  • TLS-Client-NSS: enable AES-GCM
  • TLS: document the update-ca-trust
  • Mention only gnutls_certificate_verify_peers3()
  • TLS: gnutls: use gnutls_certificate_set_x509_system_trust
  • mention TLS in Transport Layer Security section title
  • Removed pitfalls mentioned for old versions of GnuTLS
7 years ago

rebased

7 years ago

Pull-Request has been closed by mjahoda

6 years ago