How To Use GnuTLS in Applications
*********************************

Preparation
===========

To use GnuTLS, you have to perform some changes to your sources and your build system. The necessary changes are explained in the following subsections.

Headers
-------

All the data types and functions of the GnuTLS library are defined in the header file gnutls/gnutls.h.  This must be included in all programs that make use of the GnuTLS library.

The extra functionality of the GnuTLS-extra library is available by including the header file gnutls/extra.h in your programs.

Initialization
--------------

GnuTLS must be initialized before it can be used.  The library is initialized by calling gnutls_global_init.  The resources allocated by the initialization process can be released if the application no longer has a need to call GnuTLS functions, this is done by calling gnutls_global_deinit.

The extra functionality of the GnuTLS-extra library is available after calling gnutls_global_init_extra.

In order to take advantage of the internationalization features in GnuTLS, such as translated error messages, the application must set the current locale using setlocale before initializing GnuTLS.

Version Check
-------------

It is often desirable to check that the version of `gnutls' used is indeed one which fits all requirements.  Even with binary compatibility new features may have been introduced but due to problem with the dynamic linker an old version is actually used.  So you may want to check that the version is okay right after program start-up. See the function gnutls_check_version.

Debugging and auditing
----------------------

In many cases things may not go as expected and further information, to assist debugging, from GnuTLS is desired. Those are the cases where the gnutls_global_set_log_level and gnutls_global_set_log_function are to be used. Those will print verbose information on the GnuTLS functions internal flow.

When debugging is not required, important issues, such as detected attacks on the protocol still need to be logged. This is provided by the logging function set by gnutls_global_set_audit_log_function. The set function accepts the detected error message and the corresponding TLS session. The session information might be used to derive IP addresses or other information about the peer involved.

Building the Source
-------------------

If you want to compile a source file including the gnutls/gnutls.h header file, you must make sure that the compiler can find it in the directory hierarchy.  This is accomplished by adding the path to the directory in which the header file is located to the compilers include file search path (via the -I option).

However, the path to the include file is determined at the time the source is configured.  To solve this problem, the library uses the external package pkg-config that knows the path to the include file and other configuration options.  The options that need to be added to the compiler invocation at compile time are output by the --cflags option to pkg-config gnutls.  The following example shows how it can be used at the command line:

     gcc -c foo.c `pkg-config gnutls --cflags`

Adding the output of pkg-config gnutls --cflags to the compilers command line will ensure that the compiler can find the gnutls/gnutls.h header file.

A similar problem occurs when linking the program with the library. Again, the compiler has to find the library files.  For this to work, the path to the library files has to be added to the library search path (via the -L option).  For this, the option --libs to pkg-config gnutls can be used.  For convenience, this option also outputs all other options that are required to link the program with the library (for instance, the -ltasn1 option).  The example shows how to link foo.o with the library to a program foo.

     gcc -o foo foo.o `pkg-config gnutls --libs`

Of course you can also combine both examples to a single command by specifying both options to pkg-config:

     gcc -o foo foo.c `pkg-config gnutls --cflags --libs`

Client Examples
===============

This section contains examples of TLS and SSL clients, using GnuTLS.  Note that these examples contain little or no error checking.  Some of the examples require functions implemented by another example.

Simple Client Example with Anonymous Authentication
---------------------------------------------------

The simplest client using TLS is the one that doesn't do any authentication.  This means no external certificates or passwords are needed to set up the connection.  As could be expected, the connection is vulnerable to man-in-the-middle (active or redirection) attacks. However, the data is integrity and privacy protected.

     [file ex-client1.c not included]

Simple Client Example with X.509 Certificate Support
----------------------------------------------------

Let's assume now that we want to create a TCP client which communicates with servers that use X.509 or OpenPGP certificate authentication. The following client is a very simple TLS client, it does not support session resuming, not even certificate verification. The TCP functions defined in this example are used in most of the other examples below, without redefining them.

     [file ex-client2.c not included]

Simple Datagram TLS client example
----------------------------------

This is a client that uses UDP to connect to a server. This is the DTLS equivalent to Simple client example with X.509 certificate support above.

     [file ex-client-udp.c not included]

Obtaining Session Information
-----------------------------

Most of the times it is desirable to know the security properties of the current established session.  This includes the underlying ciphers and the protocols involved.  That is the purpose of the following function.  Note that this function will print meaningful values only if called after a successful gnutls_handshake.

     [file ex-session-info.c not included]

Verifying Peer's Certificate
----------------------------

A TLS session is not secure just after the handshake procedure has finished.  It must be considered secure, only after the peer's certificate and identity have been verified. That is, you have to verify the signature in peer's certificate, the hostname in the certificate, and expiration dates.  Just after this step you should treat the connection as being a secure one.

     [file ex-rfc2818.c not included]

Using a Callback to Select the Certificate to Use
-------------------------------------------------

There are cases where a client holds several certificate and key pairs, and may not want to load all of them in the credentials structure.  The following example demonstrates the use of the certificate selection callback.

     [file ex-cert-select.c not included]

Verifying a Certificate
-----------------------

An example is listed below which uses the high level verification functions to verify a given certificate list.

     [file ex-verify.c not included]

Using a PKCS #11 token with TLS
-------------------------------

This example will demonstrate how to load keys and certificates from a PKCS #11 token, and use it with a TLS connection.

     [file ex-cert-select-pkcs11.c not included]

Client with Resume Capability Example
-------------------------------------

This is a modification of the simple client example. Here we demonstrate the use of session resumption. The client tries to connect once using TLS, close the connection and then try to establish a new connection using the previously negotiated data.

     [file ex-client-resume.c not included]

Simple Client Example with SRP Authentication
---------------------------------------------

The following client is a very simple SRP TLS client which connects to a server and authenticates using a username and a password. The server may authenticate itself using a certificate, and in that case it has to be verified.

     [file ex-client-srp.c not included]

Simple Client Example using the C++ API
---------------------------------------

The following client is a simple example of a client client utilizing the GnuTLS C++ API.

     [file ex-cxx.cpp not included]

Helper Function for TCP Connections
-----------------------------------

This helper function abstracts away TCP connection handling from the other examples.  It is required to build some examples.

     [file tcp.c not included]

Server Examples
===============

This section contains examples of TLS and SSL servers, using GnuTLS.

Echo Server with X.509 Authentication
-------------------------------------

This example is a very simple echo server which supports X.509 authentication, using the RSA ciphersuites.

     [file ex-serv1.c not included]

Echo Server with OpenPGP Authentication
---------------------------------------

The following example is an echo server which supports OpenPGP key authentication. You can easily combine this functionality ---that is have a server that supports both X.509 and OpenPGP certificates--- but we separated them to keep these examples as simple as possible.

     [file ex-serv-pgp.c not included]

Echo Server with SRP Authentication
-----------------------------------

This is a server which supports SRP authentication. It is also possible to combine this functionality with a certificate server. Here it is separate for simplicity.

     [file ex-serv-srp.c not included]

Echo Server with Anonymous Authentication
-----------------------------------------

This example server support anonymous authentication, and could be used to serve the example client for anonymous authentication.

     [file ex-serv-anon.c not included]

Miscellaneous Examples
======================

Checking for an Alert
---------------------

This is a function that checks if an alert has been received in the current session.

     [file ex-alert.c not included]

X.509 Certificate Parsing Example
---------------------------------

To demonstrate the X.509 parsing capabilities an example program is listed below.  That program reads the peer's certificate, and prints information about it.

     [file ex-x509-info.c not included]

Advanced and other topics
=========================

Parameter generation
--------------------

Several TLS ciphersuites require additional parameters that need to be generated or provided by the application. The Diffie-Hellman based ciphersuites (ANON-DH or DHE), require the group information to be provided. This information can be either be generated on the fly using gnutls_dh_params_generate2 or imported from some pregenerated value using gnutls_dh_params_import_pkcs3. The parameters can be used in a session by calling gnutls_certificate_set_dh_params or gnutls_anon_set_server_dh_params for anonymous sessions.

gnutls_dh_params_generate2,gnutls_dh_params_import_pkcs3,gnutls_certificate_set_dh_params,gnutls_anon_set_server_dh_params

Due to the time-consuming calculations required for the generation of Diffie-Hellman parameters we suggest against performing generation of them within an application. The certtool tool can be used to generate or export known safe values that can be stored in code or in a configuration file to provide the ability to replace. We also recommend the usage of gnutls_sec_param_to_pk_bits (see Selecting cryptographic key sizes) to determine the bit size of the parameters to be generated.

The ciphersuites that involve the RSA-EXPORT key exchange require additional parameters. Those ciphersuites are rarely used today because they are by design insecure, thus if you have no requirement for them, this section should be skipped. The RSA-EXPORT key exchange requires 512-bit RSA keys to be generated. It is recommended those parameters to be refreshed (regenerated) in short intervals. The following functions can be used for these parameters.

gnutls_rsa_params_generate2,gnutls_certificate_set_rsa_export_params,gnutls_rsa_params_import_pkcs1,gnutls_rsa_params_export_pkcs1

Keying Material Exporters
-------------------------

The TLS PRF can be used by other protocols to derive data.  The API to use is gnutls_prf.  The function needs to be provided with the label in the parameter label, and the extra data to mix in the extra parameter.  Depending on whether you want to mix in the client or server random data first, you can set the server_random_first parameter.

For example, after establishing a TLS session using gnutls_handshake, you can invoke the TLS PRF with this call:

     #define MYLABEL "EXPORTER-FOO"
     #define MYCONTEXT "some context data"
     char out[32];
     rc = gnutls_prf (session, strlen (MYLABEL), MYLABEL, 0,
                      strlen (MYCONTEXT), MYCONTEXT, 32, out);

If you don't want to mix in the client/server random, there is a more low-level TLS PRF interface called gnutls_prf_raw.

Channel Bindings
----------------

In user authentication protocols (e.g., EAP or SASL mechanisms) it is useful to have a unique string that identifies the secure channel that is used, to bind together the user authentication with the secure channel.  This can protect against man-in-the-middle attacks in some situations.  The unique strings is a ``channel bindings''.  For background and more discussion see RFC5056.

You can extract a channel bindings using the gnutls_session_channel_binding function.  Currently only the GNUTLS_CB_TLS_UNIQUE type is supported, which corresponds to the tls-unique channel bindings for TLS defined in RFC5929.

The following example describes how to print the channel binding data. Note that it must be run after a successful TLS handshake.

     {
       gnutls_datum_t cb;
       int rc;

       rc = gnutls_session_channel_binding (session,
                                            GNUTLS_CB_TLS_UNIQUE,
                                            &cb);
       if (rc)
         fprintf (stderr, "Channel binding error: %s\n",
                  gnutls_strerror (rc));
       else
         {
           size_t i;
           printf ("- Channel binding 'tls-unique': ");
           for (i = 0; i < cb.size; i++)
             printf ("%02x", cb.data[i]);
           printf ("\n");
         }
     }

Compatibility with the OpenSSL Library
--------------------------------------

To ease GnuTLS' integration with existing applications, a compatibility layer with the widely used OpenSSL library is included in the gnutls-openssl library. This compatibility layer is not complete and it is not intended to completely re-implement the OpenSSL API with GnuTLS.  It only provides limited source-level compatibility. There is currently no attempt to make it binary-compatible with OpenSSL.

The prototypes for the compatibility functions are in the gnutls/openssl.h header file.

Current limitations imposed by the compatibility layer include:

  * Error handling is not thread safe.