[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

12. Internal Architecture of GnuTLS

This chapter is to give a brief description of the way GnuTLS works. The focus is to give an idea to potential developers and those who want to know what happens inside the black box.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

12.1 The TLS Protocol

The main needs for the TLS protocol to be used are shown in the image below.

gnutls-client-server-use-case

This is being accomplished by the following object diagram. Note that since GnuTLS is being developed in C object are just structures with attributes. The operations listed are functions that require the first parameter to be that object. gnutls-objects


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

12.2 TLS Handshake Protocol

The GnuTLS handshake protocol is implemented as a state machine that waits for input or returns immediately when the non-blocking transport layer functions are used. The main idea is shown in the following figure.

gnutls-handshake-state

Also the way the input is processed varies per ciphersuite. Several implementations of the internal handlers are available and gnutls_handshake only multiplexes the input to the appropriate handler. For example a PSK ciphersuite has a different implementation of the process_client_key_exchange than a certificate ciphersuite.

gnutls-handshake-sequence


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

12.3 TLS Authentication Methods

In GnuTLS authentication methods can be implemented quite easily. Since the required changes to add a new authentication method affect only the handshake protocol, a simple interface is used. An authentication method needs only to implement the functions as seen in the figure below.

gnutls-mod_auth_st

The functions that need to be implemented are the ones responsible for interpreting the handshake protocol messages. It is common for such functions to read data from one or more credentials_t structures(17) and write data, such as certificates, usernames etc. to auth_info_t structures.

Simple examples of existing authentication methods can be seen in auth_psk.c for PSK ciphersuites and auth_srp.c for SRP ciphersuites. After implementing these functions the structure holding its pointers has to be registered in gnutls_algorithms.c in the _gnutls_kx_algorithms structure.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

12.4 TLS Extension Handling

As with authentication methods, the TLS extensions handlers can be implemented using the following interface.

gnutls-extensions_st

Here there are two functions, one for receiving the extension data and one for sending. These functions have to check internally whether they operate in client or server side.

A simple example of an extension handler can be seen in ext_srp.c After implementing these functions, together with the extension number they handle, they have to be registered in gnutls_extensions.c in the _gnutls_extensions structure.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

12.4.1 Adding a New TLS Extension

Adding support for a new TLS extension is done from time to time, and the process to do so is not difficult. Here are the steps you need to follow if you wish to do this yourself. For sake of discussion, let's consider adding support for the hypothetical TLS extension foobar.

  1. Modify configure.in to add --enable-foobar or --disable-foobar.

    Which to chose depends on whether you intend to make the extension be enabled by default. Look at existing checks (i.e., SRP, authz) for how to model the code. For example:

     
    AC_MSG_CHECKING([whether to disable foobar support])
    AC_ARG_ENABLE(foobar,
    	AS_HELP_STRING([--disable-foobar],
    		[disable foobar support]),
    	ac_enable_foobar=no)
    if test x$ac_enable_foobar != xno; then
     AC_MSG_RESULT(no)
     AC_DEFINE(ENABLE_FOOBAR, 1, [enable foobar])
    else
     ac_full=0
     AC_MSG_RESULT(yes)
    fi
    AM_CONDITIONAL(ENABLE_FOOBAR, test "$ac_enable_foobar" != "no")
    
  2. Add IANA extension value to extensions_t in gnutls_int.h.

    A good name for the value would be GNUTLS_EXTENSION_FOOBAR. Check with http://www.iana.org/assignments/tls-extensiontype-values for allocated values. For experiments, you could pick a number but remember that some consider it a bad idea to deploy such modified version since it will lead to interoperability problems in the future when the IANA allocates that number to someone else, or when the foobar protocol is allocated another number.

  3. Add an entry to _gnutls_extensions in gnutls_extensions.c.

    A typical entry would be:

     
    #if ENABLE_FOOBAR
      GNUTLS_EXTENSION_ENTRY (GNUTLS_EXTENSION_FOOBAR,
    			  _gnutls_foobar_recv_params,
    			  _gnutls_foobar_send_params),
    #endif
    

    The GNUTLS_EXTENSION_FOOBAR is the integer value you added to gnutls_int.h earlier. The two functions are new functions that you will need to implement, most likely you'll need to add an #include "ext_foobar.h" as well.

  4. Add new files ext_foobar.c and ext_foobar.h that implements the extension.

    The functions you are responsible to add are those mentioned in the previous step. As a starter, you could add this:

     
    int
    _gnutls_foobar_recv_params (gnutls_session_t session,
                                const opaque * data,
                                size_t data_size)
    {
      return 0;
    }
    
    int
    _gnutls_foobar_send_params (gnutls_session_t session,
                                opaque * data,
                                size_t _data_size)
    {
      return 0;
    }
    

    The _gnutls_foobar_recv_params function is responsible for parsing incoming extension data (both in the client and server).

    The _gnutls_foobar_send_params function is responsible for sending extension data (both in the client and server).

    If you receive length fields that doesn't match, return GNUTLS_E_UNEXPECTED_PACKET_LENGTH. If you receive invalid data, return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER. You can use other error codes too. Return 0 on success.

    The function typically store some information in the session variable for later usage. If you need to add new fields there, check tls_ext_st in gnutls_int.h and compare with existing TLS extension specific variables.

    Recall that both the client and server both send and receives parameters, and your code most likely will need to do different things depending on which mode it is in. It may be useful to make this distinction explicit in the code. Thus, for example, a better template than above would be:

     
    int
    _gnutls_foobar_recv_params (gnutls_session_t session,
                                const opaque * data,
                                size_t data_size)
    {
      if (session->security_parameters.entity == GNUTLS_CLIENT)
        return foobar_recv_client (session, data, data_size);
      else
        return foobar_recv_server (session, data, data_size);
    }
    
    int
    _gnutls_foobar_send_params (gnutls_session_t session,
                                opaque * data,
                                size_t data_size)
    {
      if (session->security_parameters.entity == GNUTLS_CLIENT)
        return foobar_send_client (session, data, data_size);
      else
        return foobar_send_server (session, data, data_size);
    }
    

    The functions used would be declared as static functions, of the appropriate prototype, in the same file.

    When adding the files, you'll need to add them to Makefile.am as well, for example:

     
    if ENABLE_FOOBAR
    COBJECTS += ext_foobar.c
    HFILES += ext_foobar.h
    endif
    
  5. Add API functions to enable/disable the extension.

    Normally the client will have one API to request use of the extension, and setting some extension specific data. The server will have one API to let the library know that it is willing to accept the extension, often this is implemented through a callback but it doesn't have to.

    The APIs need to be added to includes/gnutls/gnutls.h or includes/gnutls/extra.h as appropriate. It is recommended that if you don't have a requirement to use the LGPLv2.1+ license for your extension, that you place your work under the GPLv3+ license and thus in the libgnutls-extra library.

    You can implement the API function in the ext_foobar.c file, or if that file ends up becoming rather larger, add a gnutls_foobar.c file.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

12.5 Certificate Handling

What is provided by the certificate handling functions is summarized in the following diagram.

gnutls-certificate-user-use-case


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

12.6 Cryptographic Backend

Several new systems provide hardware assisted cryptographic algorithm implementations that offer implementations some orders of magnitude faster than the software. For this reason in current releases of GnuTLS it is possible to override parts of the crypto backend or the whole. It is possible to override them both at runtime and compile time, however here we will discuss the runtime possibility. The API available for this functionality is in gnutls/crypto.h header file.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

12.6.1 Override specific algorithms

When an optimized implementation of a single algorithm is available, say a hardware assisted version of AES-CBC then the following functions can be used to register those algorithms.

Those registration functions will only replace the specified algorithm and leave the rest of subsystem intact.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

12.6.2 Override parts of the backend

In some systems, such as embedded ones, it might be desirable to override big parts of the cryptographic backend, or even all of them. For this reason the following functions are provided.

If all of them are used then GnuTLS will no longer use libgcrypt.


[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated on July, 20 2009 using texi2html 1.76.