How to use GnuTLS in applications
*********************************

Introduction
============

General idea
------------

A brief description of how GnuTLS works internally is shown at fig:gnutls-design. This section may become more clear after having read the rest of this section. As shown in the figure, there is a read-only global state that is initialized once by the global initialization function.  This global structure, among others, contains the memory allocation functions used, and structures needed for the ASN.1 parser.  This structure is never modified by any GnuTLS function, except for the deinitialization function which frees all allocated memory and is called after the program has permanently finished using GnuTLS.

Figure: High level design of GnuTLS.

The credentials structures are used by the authentication methods, such as certificate authentication. They store certificates, privates keys, and other information that is needed to prove the identity to the peer, and/or verify the indentity of the peer. The information stored in the credentials structures is initialized once and then can be shared by many TLS sessions.

A GnuTLS session contains all the required information to handle one secure connection. The session communicates with the peers using the provided functions of the transport layer. Every session has a unique session ID shared with the peer.

Since TLS sessions can be resumed, servers need a database back-end to hold the session's parameters.  Every GnuTLS session after a successful handshake calls the appropriate back-end function (see resume) to store the newly negotiated session. The session database is examined by the server just after having received the client hello (The first message in a TLS handshake), and if the session ID sent by the client, matches a stored session, the stored session will be retrieved, and the new session will be a resumed one, and will share the same session ID with the previous one.

Error handling
--------------

In GnuTLS most functions return an integer type as a result. In almost all cases a zero or a positive number means success, and a negative number indicates failure, or a situation that some action has to be taken. Thus negative error codes may be fatal or not.

Fatal errors terminate the connection immediately and further sends and receives will be disallowed.  Such an example is GNUTLS_E_DECRYPTION_FAILED. Non-fatal errors may warn about something, i.e., a warning alert was received, or indicate the some action has to be taken. This is the case with the error code GNUTLS_E_REHANDSHAKE returned by gnutls_record_recv. This error code indicates that the server requests a re-handshake. The client may ignore this request, or may reply with an alert.  You can test if an error code is a fatal one by using the gnutls_error_is_fatal. All errors can be converted to a descriptive string using gnutls_strerror.

If any non fatal errors, that require an action, are to be returned by a function, these error codes will be documented in the function's reference. For example the error codes GNUTLS_E_WARNING_ALERT_RECEIVED and GNUTLS_E_FATAL_ALERT_RECEIVED that may returned when receiving data, should be handled by notifying the user of the alert (as explained in Handling alerts). See Error codes, for a description of the available error codes.

Common types
------------

Several functions in GnuTLS use gnutls_datum_t which is convenient way to combine a pointer to data and data's size. Its definition is shown below.
  typedef struct
  {
    unsigned char *data;
    unsigned int size;
  } gnutls_datum_t;

Other functions that require data for scattered read use a structure similar to struct iovec typically used by readv. It is shown below.
  typedef struct
  {
    void *iov_base;             /* Starting address */
    size_t iov_len;             /* Number of bytes to transfer */
  } giovec_t;

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.

gnutls_global_set_log_level,gnutls_global_set_log_function

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 provided function will receive an message and the corresponding TLS session. The session information might be used to derive IP addresses or other information about the peer involved.

gnutls_global_set_audit_log_function

Thread safety
-------------

The GnuTLS library is thread safe by design, meaning that objects of the library such as TLS sessions, can be safely divided across threads as long as a single thread accesses a single object. This is sufficient to support a server which handles several sessions per thread. If, however, an object needs to be shared across threads then access must be protected with a mutex. Read-only access to objects, for example the credentials holding structures, is also thread-safe.

The random generator of the cryptographic back-end, is not thread safe and requires mutex locks which are setup by GnuTLS. Applications can either call gnutls_global_init which will initialize the default operating system provided locks (i.e. pthreads on GNU/Linux and CriticalSection on Windows), or manually specify the locking system using the function gnutls_global_set_mutex before calling gnutls_global_init. Setting mutexes manually is recommended only for applications that have full control of the underlying libraries. If this is not the case, the use of the operating system defaults is recommended. An example of non-native thread usage is shown below.

     #include <gnutls/gnutls.h>

     int main()
     {
        /* When the system mutexes are not to be used
         * gnutls_global_set_mutex() must be called explicitly
         */
        gnutls_global_set_mutex (mutex_init, mutex_deinit,
                                 mutex_lock, mutex_unlock);
        gnutls_global_init();
     }

gnutls_global_set_mutex

Callback functions
------------------

There are several cases where GnuTLS may need out of band input from your program. This is now implemented using some callback functions, which your program is expected to register.

An example of this type of functions are the push and pull callbacks which are used to specify the functions that will retrieve and send data to the transport layer.

gnutls_transport_set_push_function,gnutls_transport_set_pull_function

Other callback functions may require more complicated input and data to be allocated. Such an example is gnutls_srp_set_server_credentials_function. All callbacks should allocate and free memory using gnutls_malloc and gnutls_free.

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.

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.

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.

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`

When a program uses the GNU autoconf system, then the following line or similar can be used to detect the presence of GnuTLS.

     PKG_CHECK_MODULES([LIBGNUTLS], [gnutls >= 3.0.0])

     AC_SUBST([LIBGNUTLS_CFLAGS])
     AC_SUBST([LIBGNUTLS_LIBS])

Session initialization
======================

In the previous sections we have discussed the global initialization required for GnuTLS as well as the initialization required for each authentication method's credentials (see Authentication). In this section we elaborate on the TLS or DTLS session initiation. Each session is initialized using gnutls_init which among others is used to specify the type of the connection (server or client), and the underlying protocol type, i.e., datagram (UDP) or reliable (TCP).

gnutls_init

After the session initialization details on the allowed ciphersuites and protocol versions should be set using the priority functions such as gnutls_priority_set_direct. We elaborate on them in Priority Strings. The credentials used for the key exchange method, such as certificates or usernames and passwords should also be associated with the session current session using gnutls_credentials_set.

gnutls_credentials_set

Associating the credentials
===========================

Each authentication method is associated with a key exchange method, and a credentials type. The contents of the credentials is method-dependent, e.g. certificates for certificate authentication and should be initialized and associated with a session (see gnutls_credentials_set).  A mapping of the key exchange methods with the credential types is shown in tab:key-exchange-cred.

Authentication method   Key exchange   Client credentials   Server credentials

Certificate
KX_RSA,
KX_DHE_RSA,
KX_DHE_DSS,
KX_ECDHE_RSA,
KX_ECDHE_ECDSA,
KX_RSA_EXPORT
CRD_CERTIFICATE
CRD_CERTIFICATE

Password and certificate
KX_SRP_RSA, KX_SRP_DSS
CRD_SRP
CRD_CERTIFICATE, CRD_SRP

Password
KX_SRP
CRD_SRP
CRD_SRP

Anonymous
KX_ANON_DH,
KX_ANON_ECDH
CRD_ANON
CRD_ANON

Pre-shared key
KX_PSK,
KX_DHE_PSK, KX_ECDHE_PSK
CRD_PSK
CRD_PSK

Table: Key exchange algorithms and the corresponding credential types.

Certificates
------------

Server certificate authentication
.................................

When using certificates the server is required to have at least one certificate and private key pair. Clients may not hold such a pair, but a server could require it. In this section we discuss general issues applying to both client and server certificates. The next section will elaborate on issues arising from client authentication only.

gnutls_certificate_allocate_credentials,gnutls_certificate_free_credentials

After the credentials structures are initialized, the certificate and key pair must be loaded. This occurs before any TLS session is initialized, and the same structures are reused for multiple sessions. Depending on the certificate type different loading functions are available, as shown below. For X.509 certificates, the functions will accept and use a certificate chain that leads to a trusted authority. The certificate chain must be ordered in such way that every certificate certifies the one before it. The trusted authority's certificate need not to be included since the peer should possess it already.

gnutls_certificate_set_x509_key_mem,gnutls_certificate_set_x509_key,gnutls_certificate_set_x509_key_file

gnutls_certificate_set_openpgp_key_mem,gnutls_certificate_set_openpgp_key,gnutls_certificate_set_openpgp_key_file,gnutls_certificate_set_key

If multiple certificates are used with the functions above each client's request will be served with the certificate that matches the requested name (see Server name indication).

As an alternative to loading from files or buffers, a callback may be used for the server or the client to specify the certificate and the key at the handshake time. In that case a certificate should be selected according the peer's signature algorithm preferences. To get those preferences use gnutls_sign_algorithm_get_requested. Both functions are shown below.

gnutls_certificate_set_retrieve_function,gnutls_certificate_set_retrieve_function2,gnutls_sign_algorithm_get_requested

The functions above do not handle the requested server name automatically. A server would need to check the name requested by the client using gnutls_server_name_get, and serve the appropriate certificate.

In a handshake, the negotiated cipher suite depends on the certificate's parameters, so some key exchange methods might not be available with all certificates. GnuTLS will disable ciphersuites that are not compatible with the key, or the enabled authentication methods.  For example keys marked as sign-only, will not be able to access the plain RSA ciphersuites, that require decryption. It is not recommended to use RSA keys for both signing and encryption. If possible use a different key for the DHE-RSA which uses signing and RSA that requires decryption. All the key exchange methods shown in tab:key-exchange are available in certificate authentication.

Client certificate authentication
.................................

If a certificate is to be requested from the client during the handshake, the server will send a certificate request message. This behavior is controlled gnutls_certificate_server_set_request. The request contains a list of the acceptable by the server certificate signers. This list is constructed using the trusted certificate authorities of the server. In cases where the server supports a large number of certificate authorities it makes sense not to advertise all of the names to save bandwidth. That can be controlled using the function gnutls_certificate_send_x509_rdn_sequence. This however will have the side-effect of not restricting the client to certificates signed by server's acceptable signers.

gnutls_certificate_server_set_request

gnutls_certificate_send_x509_rdn_sequence

Client or server certificate verification
.........................................

Certificate verification is possible by loading the trusted authorities into the credentials structure by using the following functions, applicable to X.509 and OpenPGP certificates.

gnutls_certificate_set_x509_trust_file,gnutls_certificate_set_openpgp_keyring_file

The peer's certificate is not automatically verified and one should call gnutls_certificate_verify_peers2 after a successful handshake to verify the certificate's signature. Alternative the verification can occur during the handshake by using gnutls_certificate_set_verify_function.

In order to report a detailed verification output, an alternative way has to be used. For that, one should call gnutls_certificate_get_peers to obtain the raw certificate of the peer and verify it using the functions discussed in X.509 certificates.

gnutls_certificate_verify_peers2

gnutls_certificate_set_verify_function

SRP
---

The initialization functions in SRP credentials differ between client and server. Clients supporting SRP should set the username and password prior to connection, to the credentials structure. Alternatively gnutls_srp_set_client_credentials_function may be used instead, to specify a callback function that should return the SRP username and password. The callback is called once during the TLS handshake.

gnutls_srp_allocate_server_credentials,gnutls_srp_allocate_client_credentials,gnutls_srp_free_server_credentials,gnutls_srp_free_client_credentials,gnutls_srp_set_client_credentials

gnutls_srp_set_client_credentials_function

In server side the default behavior of GnuTLS is to read the usernames and SRP verifiers from password files. These password file format is compatible the with the Stanford srp libraries format.  If a different password file format is to be used, then gnutls_srp_set_server_credentials_function should be called, to set an appropriate callback.

gnutls_srp_set_server_credentials_file

gnutls_srp_set_server_credentials_function

PSK
---

The initialization functions in PSK credentials differ between client and server.

gnutls_psk_allocate_server_credentials,gnutls_psk_allocate_client_credentials,gnutls_psk_free_server_credentials,gnutls_psk_free_client_credentials

Clients supporting PSK should supply the username and key before a TLS session is established.  Alternatively gnutls_psk_set_client_credentials_function can be used to specify a callback function. This has the advantage that the callback will be called only if PSK has been negotiated.

gnutls_psk_set_client_credentials

gnutls_psk_set_client_credentials_function

In server side the default behavior of GnuTLS is to read the usernames and PSK keys from a password file. The password file should contain usernames and keys in hexadecimal format. The name of the password file can be stored to the credentials structure by calling gnutls_psk_set_server_credentials_file.  If a different password file format is to be used, then a callback should be set instead by gnutls_psk_set_server_credentials_function.

The server can help the client chose a suitable username and password, by sending a hint. Note that there is no common profile for the PSK hint and applications are discouraged to use it. A server, may specify the hint by calling gnutls_psk_set_server_credentials_hint.  The client can retrieve the hint, for example in the callback function, using gnutls_psk_client_get_hint.

gnutls_psk_set_server_credentials_file

gnutls_psk_set_server_credentials_function,gnutls_psk_set_server_credentials_hint,gnutls_psk_client_get_hint

Anonymous
---------

The key exchange methods for anonymous authentication might require Diffie-Hellman parameters to be generated by the server and associated with an anonymous credentials structure. Check Parameter generation for more information. The initialization functions for the credentials are shown below.

gnutls_anon_allocate_server_credentials,gnutls_anon_allocate_client_credentials,gnutls_anon_free_server_credentials,gnutls_anon_free_client_credentials

Setting up the transport layer
==============================

The next step is to setup the underlying transport layer details. The Berkeley sockets are implicitly used by GnuTLS, thus a call to gnutls_transport_set_ptr2 would be sufficient to specify the socket descriptor.

gnutls_transport_set_ptr2

gnutls_transport_set_ptr

If however another transport layer than TCP is selected, then the following functions have to be specified.

gnutls_transport_set_push_function gnutls_transport_set_vec_push_function gnutls_transport_set_pull_function

The functions above accept a callback function which should return the number of bytes written, or -1 on error and should set errno appropriately. In some environments, setting errno is unreliable. For example Windows have several errno variables in different CRTs, or in other systems it may be a non thread-local variable.  If this is a concern to you, call gnutls_transport_set_errno with the intended errno value instead of setting errno directly.

gnutls_transport_set_errno

GnuTLS currently only interprets the EINTR, EAGAIN and EMSGSIZE errno values and returns the corresponding GnuTLS error codes:

  * GNUTLS_E_INTERRUPTED

  * GNUTLS_E_AGAIN

  * GNUTLS_E_LARGE_PACKET

The EINTR and EAGAIN values are returned by interrupted system calls, or when non blocking IO is used.  All GnuTLS functions can be resumed (called again), if any of the above error codes is returned. The EMSGSIZE value is returned when attempting to send a large datagram.

In the case of DTLS it is also desirable to override the generic transport functions with functions that emulate the operation of recvfrom and sendto. In addition DTLS requires timers during the receive of a handshake message, set using the gnutls_transport_set_pull_timeout_function function. To check the retransmission timers the function gnutls_dtls_get_timeout is provided, which returns the time remaining until the next retransmission, or better the time until gnutls_handshake should be called again.

gnutls_transport_set_pull_timeout_function gnutls_dtls_get_timeout

Asynchronous operation
----------------------

GnuTLS can be used with asynchronous socket or event-driven programming. The approach is similar to using Berkeley sockets under such an environment. The blocking, due to network interaction, calls such as gnutls_handshake, gnutls_record_recv, can be set to non-blocking by setting the underlying sockets to non-blocking. If other push and pull functions are setup, then they should behave the same way as recv and send when used in a non-blocking way, i.e., set errno to EAGAIN. Since, during a TLS protocol session GnuTLS does not block except for network interaction, the non blocking EAGAIN errno will be propagated and GnuTLS functions will return the GNUTLS_E_AGAIN error code. Such calls can be resumed the same way as a system call would. The only exception is gnutls_record_send, which if interrupted subsequent calls need not to include the data to be sent (can be called with NULL argument).

The select system call can also be used in combination with the GnuTLS functions. select allows monitoring of sockets and notifies on them being ready for reading or writing data. Note however that this system call cannot notify on data present in GnuTLS read buffers, it is only applicable to the kernel sockets API. Thus if you are using it for reading from a GnuTLS session, make sure that any cached data are read completely. That can be achieved by checking there are no data waiting to be read (using gnutls_record_check_pending), either before the select system call, or after a call to gnutls_record_recv. GnuTLS does not keep a write buffer, thus when writing no additional actions are required.

Although in the TLS protocol implementation each call to receive or send function implies to restoring the same function that was interrupted, in the DTLS protocol this requirement isn't true. There are cases where a retransmission is required, which are indicated by a received message and thus gnutls_record_get_direction must be called to decide which operation to restore, i.e., send or receive. gnutls_record_get_direction

Moreover, to prevent blocking from DTLS' retransmission timers to block a handshake, the gnutls_init function should be called with the GNUTLS_NONBLOCK flag set (see Session initialization).

DTLS sessions
-------------

Because datagram TLS can operate over connections where the peer of a server cannot be reliably verified, functionality is available to prevent denial of service attacks. GnuTLS requires a server to generate a secret key that is used to sign a cookie (A key of 128 bits or 16 bytes should be sufficient for this purpose.). That cookie is sent to the client using gnutls_dtls_cookie_send, and the client must reply using the correct cookie. The server side should verify the initial message sent by client using gnutls_dtls_cookie_verify. If successful the session should be initialized and associated with the cookie using gnutls_dtls_prestate_set, before proceeding to the handshake.

gnutls_key_generate,gnutls_dtls_cookie_send,gnutls_dtls_cookie_verify,gnutls_dtls_prestate_set

Note that the above apply to server side only and they are not mandatory to be used. Not using them, however, allows denial of service attacks. The client side cookie handling is part of gnutls_handshake.

Datagrams are typically restricted by a maximum transfer unit (MTU). For that both client and server side should set the correct maximum transfer unit for the layer underneath GnuTLS. This will allow proper fragmentation of DTLS messages and prevent messages from being silently discarded by the transport layer. The ``correct'' maximum transfer unit can be obtained through a path MTU discovery mechanism RFC4821.

gnutls_dtls_set_mtu,gnutls_dtls_get_mtu,gnutls_dtls_get_data_mtu

TLS handshake
=============

Once a session has been initialized and a network connection has been set up, TLS and DTLS protocols perform a handshake. The handshake is the actual key exchange.

gnutls_handshake

The handshake process doesn't ensure the verification of the peer's identity. When certificates are in use, this can be done, either after the handshake is complete, or during the handshake if gnutls_certificate_set_verify_function has been used. In both cases the gnutls_certificate_verify_peers2 function can be used to verify the peer's certificate (see Certificate authentication for more information).

gnutls_certificate_verify_peers2

Data transfer and termination
=============================

Once the handshake is complete and peer's identity has been verified data can be exchanged. The available functions resemble the POSIX recv and send functions. It is suggested to use gnutls_error_is_fatal to check whether the error codes returned by these functions are fatal for the protocol or can be ignored.

gnutls_record_send

gnutls_record_recv

gnutls_error_is_fatal

Although, in the TLS protocol the receive function can be called at any time, when DTLS is used the GnuTLS receive functions must be called once a message is available for reading, even if no data are expected. This is because in DTLS various (internal) actions may be required due to retransmission timers. Moreover, an extended receive function is shown below, which allows the extraction of the message's sequence number. Due to the unreliable nature of the protocol, this field allows distinguishing out-of-order messages.

gnutls_record_recv_seq

The gnutls_record_check_pending helper function is available to allow checking whether data are available to be read in a GnuTLS session buffers. Note that this function complements but does not replace select, i.e., gnutls_record_check_pending reports no data to be read, select should be called to check for data in the network buffers.

gnutls_record_check_pending gnutls_record_get_direction

Once a TLS or DTLS session is no longer needed, it is recommended to use gnutls_bye to terminate the session. That way the peer is notified securely about the intention of termination, which allows distinguishing it from a malicious connection termination. A session can be deinitialized with the gnutls_deinit function.

gnutls_bye gnutls_deinit

Handling alerts
===============

During a TLS connection alert messages may be exchanged by the two peers. Those messages may be fatal, meaning the connection must be terminated afterwards, or warning when something needs to be reported to the peer, but without interrupting the session. The error codes GNUTLS_E_WARNING_ALERT_RECEIVED or GNUTLS_E_FATAL_ALERT_RECEIVED signal those alerts when received, and may be returned by all GnuTLS functions that receive data from the peer, being gnutls_handshake and gnutls_record_recv.

If those error codes are received the alert and its level should be logged or reported to the peer using the functions below.

gnutls_alert_get gnutls_alert_get_name

The peer may also be warned or notified of a fatal issue by using one of the functions below. All the available alerts are listed in The Alert Protocol.

gnutls_alert_send gnutls_error_to_alert

Priority strings
================

In order to specify cipher suite preferences on a TLS session there are priority functions that accept a string specifying the enabled for the handshake algorithms. That string may contain a single initial keyword such as in tab:prio-keywords and may be followed by additional algorithm or special keywords.

gnutls_priority_set_direct,gnutls_priority_set

Keyword   Description
PERFORMANCE
All the known to be secure ciphersuites are enabled,
limited to 128 bit ciphers and sorted by terms of speed
performance. The message authenticity security level is of 64 bits or more.

NORMAL
Means all the known to be secure ciphersuites. The ciphers are sorted by security
margin, although the 256-bit ciphers are included as a fallback only.
The message authenticity security level is of 64 bits or more.

SECURE128
Means all known to be secure ciphersuites that offer a
security level 128-bit or more and a message authenticity
security level of 80 bits or more.

SECURE192
Means all the known to be secure ciphersuites that offer a
security level 192-bit or more and a message authenticity
security level of 128 bits or more.

SECURE256
Currently alias for SECURE192.

SUITEB128
Means all the NSA Suite B cryptography (RFC5430) ciphersuites
with an 128 bit security level.

SUITEB192
Means all the NSA Suite B cryptography (RFC5430) ciphersuites
with an 192 bit security level.

EXPORT
Means all ciphersuites are enabled, including the
low-security 40 bit ciphers.

NONE
Means nothing is enabled.  This disables even protocols and
compression methods. It should be followed by the
algorithms to be enabled.

Table: Supported initial keywords.

Unless the initial keyword is "NONE" the defaults (in preference order) are for TLS protocols TLS 1.2, TLS1.1, TLS1.0, SSL3.0; for compression NULL; for certificate types X.509. In key exchange algorithms when in NORMAL or SECURE levels the perfect forward secrecy algorithms take precedence of the other protocols.  In all cases all the supported key exchange algorithms are enabled (Except for the RSA-EXPORT which is only enabled in EXPORT level.).

Note that the SECURE levels distinguish between overall security level and message authenticity security level. That is because the message authenticity security level requires the adversary to break the algorithms at real-time during the protocol run, whilst the overall security level refers to off-line adversaries (e.g. adversaries breaking the ciphertext years after it was captured).

The NONE keyword, if used, must followed by keywords specifying the algorithms and protocols to be enabled. The other initial keywords may be followed by such keywords. The order with which every algorithm or protocol is specified is significant. Algorithms specified before others will take precedence. The supported algorithms and protocols are shown in tab:prio-algorithms. To avoid collisions in order to specify a compression algorithm in the priority string you have to prefix it with "COMP-", protocol versions with "VERS-", signature algorithms with "SIGN-" and certificate types with "CTYPE-". All other algorithms don't need a prefix. Each specified keyword can be prefixed with any of the following characters.

'!' or '-'
     appended with an algorithm will remove this algorithm.

"+"
     appended with an algorithm will add this algorithm.

Type   Keywords
Ciphers
AES-128-CBC, AES-256-CBC, AES-128-GCM, CAMELLIA-128-CBC,
CAMELLIA-256-CBC, ARCFOUR-128, 3DES-CBC ARCFOUR-40. Catch all
name is CIPHER-ALL which will add all the algorithms from NORMAL
priority.

Key exchange
RSA, DHE-RSA, DHE-DSS, SRP, SRP-RSA, SRP-DSS,
PSK, DHE-PSK, ECDHE-RSA, ANON-ECDH, ANON-DH, RSA-EXPORT. The
Catch all name is KX-ALL which will add all the algorithms from NORMAL
priority.

MAC
MD5, SHA1, SHA256, AEAD (used with
GCM ciphers only). All algorithms from NORMAL priority can be accessed with MAC-ALL.

Compression algorithms
COMP-NULL, COMP-DEFLATE. Catch all is COMP-ALL.

TLS versions
VERS-SSL3.0, VERS-TLS1.0, VERS-TLS1.1,
VERS-TLS1.2, VERS-DTLS1.0. Catch all is VERS-TLS-ALL.

Signature algorithms
SIGN-RSA-SHA1, SIGN-RSA-SHA224,
SIGN-RSA-SHA256, SIGN-RSA-SHA384, SIGN-RSA-SHA512, SIGN-DSA-SHA1,
SIGN-DSA-SHA224, SIGN-DSA-SHA256, SIGN-RSA-MD5. Catch all
is SIGN-ALL. This is only valid for TLS 1.2 and later.

Elliptic curves
CURVE-SECP192R1, CURVE-SECP224R1, CURVE-SECP256R1, CURVE-SECP384R1, CURVE-SECP521R1. Catch all is CURVE-ALL.

Table: The supported algorithm keywords in priority strings.

Note that the DHE key exchange methods are generally slower (It depends on the group used.  Primes with lesser bits are always faster, but also easier to break.  See Selecting cryptographic key sizes for the acceptable security levels.) than their elliptic curves counterpart (ECDHE). Moreover the plain Diffie-Hellman key exchange requires parameters to be generated and associated with a credentials structure by the server (see Parameter generation).

The available special keywords are shown in tab:prio-special.

Keyword   Description

%COMPAT
will enable compatibility mode. It might mean that violations
of the protocols are allowed as long as maximum compatibility with
problematic clients and servers is achieved. More specifically this
string would disable TLS record random padding and tolerate packets
over the maximum allowed TLS record.

%NO_EXTENSIONS
will prevent the sending of any TLS extensions in client side. Note
that TLS 1.2 requires extensions to be used, as well as safe
renegotiation thus this option must be used with care.

%SERVER_PRECEDENCE
The ciphersuite will be selected according to server priorities
and not the client's.

%DISABLE_SAFE_RENEGOTIATION
will disable safe renegotiation
completely.  Do not use unless you know what you are doing.
Testing purposes only.

%UNSAFE_RENEGOTIATION
will allow handshakes and re-handshakes
without the safe renegotiation extension.  Note that for clients
this mode is insecure (you may be under attack), and for servers it
will allow insecure clients to connect (which could be fooled by an
attacker).  Do not use unless you know what you are doing and want
maximum compatibility.

%PARTIAL_RENEGOTIATION
will allow initial handshakes to proceed,
but not re-handshakes.  This leaves the client vulnerable to attack,
and servers will be compatible with non-upgraded clients for
initial handshakes.  This is currently the default for clients and
servers, for compatibility reasons.

%SAFE_RENEGOTIATION
will enforce safe renegotiation.  Clients and
servers will refuse to talk to an insecure peer.  Currently this
causes interoperability problems, but is required for full protection.

%SSL3_RECORD_VERSION
will use SSL3.0 record version in client hello.
This is the default.

%LATEST_RECORD_VERSION
will use the latest TLS version record version in client hello.

%VERIFY_ALLOW_SIGN_RSA_MD5
will allow RSA-MD5 signatures in certificate chains.

%VERIFY_ALLOW_X509_V1_CA_CRT
will allow V1 CAs in chains.

Table: Special priority string keywords.

Finally the ciphersuites enabled by any priority string can be listed using the gnutls-cli application (see gnutls-cli Invocation), or by using the priority functions as in Listing the ciphersuites in a priority string.

Example priority strings are:

     The default priority without the HMAC-MD5:
         "NORMAL:-MD5"

     Specifying RSA with AES-128-CBC:
         "NONE:+VERS-TLS-ALL:+MAC-ALL:+RSA:+AES-128-CBC:+SIGN-ALL:+COMP-NULL"

     Specifying the defaults except ARCFOUR-128:
         "NORMAL:-ARCFOUR-128"

     Enabling the 128-bit secure ciphers, while disabling SSL 3.0 and
     enabling compression:
         "SECURE128:-VERS-SSL3.0:+COMP-DEFLATE"

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

Session resumption
------------------

Client side
...........

To reduce time and roundtrips spent in a handshake the client can request session resumption from a server that previously shared a session with. For that the client has to retrieve and store the session parameters. Before establishing a new session to the same server the parameters must be re-associated with the GnuTLS session using gnutls_session_set_data.

gnutls_session_get_data,gnutls_session_get_id,gnutls_session_set_data

Keep in mind that sessions will be expired after some time, depending on the server, and a server may choose not to resume a session even when requested to.  The expiration is to prevent temporal session keys from becoming long-term keys. Also note that as a client you must enable, using the priority functions, at least the algorithms used in the last session.

It is highly recommended for clients to enable the session ticket extension using gnutls_session_ticket_enable_client in order to allow resumption with servers that do not store any state.

gnutls_session_ticket_enable_client

gnutls_session_is_resumed

Server side
...........

In order to support resumption a server can store the session security parameters in a local database or by using session tickets (see Session tickets) to delegate storage to the client. Because session tickets might not be supported by all clients, servers could combine the two methods.

A storing server needs to specify callback functions to store, retrieve and delete session data. These can be registered with the functions below. The stored sessions in the database can be checked using gnutls_db_check_entry for expiration.

gnutls_db_set_retrieve_function,gnutls_db_set_store_function,gnutls_db_set_ptr,gnutls_db_set_remove_function gnutls_db_check_entry

A server utilizing tickets should generate ticket encryption and authentication keys using gnutls_session_ticket_key_generate. Those keys should be associated with the GnuTLS session using gnutls_session_ticket_enable_server.

gnutls_session_ticket_enable_server gnutls_session_ticket_key_generate gnutls_session_resumption_requested

A server enabling both session tickets and a storage for session data would use session tickets when clients support it and the storage otherwise.

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 parameters to be provided. Those can either be be generated on the fly using gnutls_dh_params_generate2 or imported from pregenerated data using gnutls_dh_params_import_pkcs3. The parameters can be used in a TLS 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 generated parameters.

Note that the information stored in the generated PKCS #3 structure changed with GnuTLS 3.0.9. Since that version the privateValueLength member of the structure is set, allowing the server utilizing the parameters to use keys of the size of the security parameter. This provides better performance in key exchange.

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, the rest of this section can 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

To allow renewal of the parameters within an application without accessing the credentials, which are a shared structure, an alternative interface is available using a callback function.

gnutls_certificate_set_params_function

Keying material exporters
-------------------------

The TLS PRF can be used by other protocols to derive keys based on the TLS master secret.  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 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.  That unique string is called a ``channel binding''.  For background and discussion see RFC5056.

In GnuTLS you can extract a channel binding using the gnutls_session_channel_binding function.  Currently only the type GNUTLS_CB_TLS_UNIQUE is supported, which corresponds to the tls-unique channel binding 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");
         }
     }

Interoperability
----------------

The TLS protocols support many ciphersuites, extensions and version numbers. As a result, few implementations are not able to properly interoperate once faced with extensions or version protocols they do not support and understand. The TLS protocol allows for a graceful downgrade to the commonly supported options, but practice shows it is not always implemented correctly.

Because there is no way to achieve maximum interoperability with broken peers without sacrificing security, GnuTLS ignores such peers by default. This might not be acceptable in cases where maximum compatibility is required. Thus we allow enabling compatibility with broken peers using priority strings (see Priority Strings). A conservative priority string that would disable certain TLS protocol options that are known to cause compatibility problems, is shown below.
NORMAL:%COMPAT

For broken peers that do not tolerate TLS version numbers over TLS 1.0 another priority string is:
NORMAL:-VERS-TLS-ALL:+VERS-TLS1.0:+VERS-SSL3.0:%COMPAT
This priority string will in addition to above, only enable SSL 3.0 and TLS 1.0 as protocols. Note however that there are known attacks against those protocol versions, especially over the CBC-mode ciphersuites. To mitigate them another priority string that only allows the stream cipher ARCFOUR is below.
NORMAL:-VERS-TLS-ALL:+VERS-TLS1.0:+VERS-SSL3.0:-CIPHER-ALL:+ARCFOUR-128:%COMPAT

Compatibility with the OpenSSL library
--------------------------------------

To ease GnuTLS' integration with existing applications, a compatibility layer with the 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.

The prototypes for the compatibility functions are in the gnutls/openssl.h header file. The limitations imposed by the compatibility layer include:

  * Error handling is not thread safe.

Using the cryptographic library
===============================

GnuTLS is not a low-level cryptographic library, i.e., it does not provide access to basic cryptographic primitives. However it abstracts the internal cryptographic back-end (see Cryptographic Backend), providing symmetric crypto, hash and HMAC algorithms, as well access to the random number generation.

Symmetric cryptography
----------------------

The available functions to access symmetric crypto algorithms operations are shown below. The supported algorithms are the algorithms required by the TLS protocol. They are listed in tab:ciphers.

gnutls_cipher_init,gnutls_cipher_encrypt2,gnutls_cipher_decrypt2,gnutls_cipher_set_iv,gnutls_cipher_deinit

In order to support authenticated encryption with associated data (AEAD) algorithms the following functions are provided to set the associated data and retrieve the authentication tag.

gnutls_cipher_add_auth,gnutls_cipher_tag

Hash and HMAC functions
-----------------------

The available operations to access hash functions and hash-MAC (HMAC) algorithms are shown below. HMAC algorithms provided keyed hash functionality. They supported HMAC algorithms are listed in tab:macs.

gnutls_hmac_init,gnutls_hmac,gnutls_hmac_output,gnutls_hmac_deinit,gnutls_hmac_get_len,gnutls_hmac_fast

The available functions to access hash functions are shown below. The supported hash functions are the same as the HMAC algorithms.

gnutls_hash_init,gnutls_hash,gnutls_hash_output,gnutls_hash_deinit,gnutls_hash_get_len,gnutls_hash_fast

Random number generation
------------------------

Access to the random number generator is provided using the gnutls_rnd function. It allows obtaining random data of various levels.

gnutls_rnd_level_t,The random number levels. gnutls_rnd

Selecting cryptographic key sizes
=================================

Because many algorithms are involved in TLS, it is not easy to set a consistent security level.  For this reason in tab:key-sizes we present some correspondence between key sizes of symmetric algorithms and public key algorithms based on ECRYPT. Those can be used to generate certificates with appropriate key sizes as well as select parameters for Diffie-Hellman and SRP authentication.

Security bits   RSA, DH and SRP parameter size   ECC key size   Security parameter   Description

80
1248
160
LOW
Very short term protection against agencies

96
1776
192
LEGACY
Legacy standard level

112
2432
224
NORMAL
Medium-term protection

128
3248
256
HIGH
Long term protection

256
15424
512
ULTRA
Foreseeable future

Table: Key sizes and security parameters.

The first column  provides a security parameter in a number of bits. This gives an indication of the number of combinations to be tried by an adversary to brute force a key. For example to test all possible keys in a 112 bit security parameter 2^112 combinations have to be tried. For today's technology this is infeasible. The next two columns correlate the security parameter with actual bit sizes of parameters for DH, RSA, SRP and ECC algorithms. A mapping to gnutls_sec_param_t value is given for each security parameter, on the next column, and finally a brief description of the level.

Note, however, that the values suggested here are nothing more than an educated guess that is valid today. There are no guarantees that an algorithm will remain unbreakable or that these values will remain constant in time. There could be scientific breakthroughs that cannot be predicted or total failure of the current public key systems by quantum computers. On the other hand though the cryptosystems used in TLS are selected in a conservative way and such catastrophic breakthroughs or failures are believed to be unlikely. The NIST publication SP 800-57 NISTSP80057 contains a similar table.

When using GnuTLS and a decision on bit sizes for a public key algorithm is required, use of the following functions is recommended:

gnutls_sec_param_to_pk_bits

gnutls_pk_bits_to_sec_param

Those functions will convert a human understandable security parameter of gnutls_sec_param_t type, to a number of bits suitable for a public key algorithm.

The following functions will set the minimum acceptable group size for Diffie-Hellman and SRP authentication. gnutls_dh_set_prime_bits,gnutls_srp_set_prime_bits