manpagez: man pages & more
info gnutls
Home | html | info | man
[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.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.

Add configure option like --enable-foobar or --disable-foobar.

This step is useful when the extension code is large and it might be desirable to disable the extension under some circumstances. Otherwise it can be safely skipped.

Whether to chose enable or disable 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")

These lines should go in lib/m4/hooks.m4.

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.

Add an entry to _gnutls_extensions in gnutls_extensions.c.

A typical entry would be:

  int ret;

#if ENABLE_FOOBAR
  ret = _gnutls_ext_register (&foobar_ext);
  if (ret != GNUTLS_E_SUCCESS)
    return ret;
#endif

Most likely you’ll need to add an #include "ext/foobar.h", that will contain something like like:

  extension_entry_st foobar_ext = {
    .name = "FOOBAR",
    .type = GNUTLS_EXTENSION_FOOBAR,
    .parse_type = GNUTLS_EXT_TLS,
    .recv_func = _foobar_recv_params,
    .send_func = _foobar_send_params,
    .pack_func = _foobar_pack,
    .unpack_func = _foobar_unpack,
    .deinit_func = NULL
  }

The GNUTLS_EXTENSION_FOOBAR is the integer value you added to gnutls_int.h earlier. In this structure you specify the functions to read the extension from the hello message, the function to send the reply to, and two more functions to pack and unpack from stored session data (e.g. when resumming a session). The deinit function will be called to deinitialize the extension’s private parameters, if any.

Note that the conditional ENABLE_FOOBAR definition should only be used if step 1 with the configure options has taken place.

Add new files that implement the extension.

The functions you are responsible to add are those mentioned in the previous step. They should be added in a file such as ext/foobar.c and headers should be placed in ext/foobar.h. As a starter, you could add this:

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

int
_foobar_send_params (gnutls_session_t session, gnutls_buffer_st* data)
{
  return 0;
}

int
_foobar_pack (extension_priv_data_t epriv, gnutls_buffer_st * ps)
{
   /* Append the extension's internal state to buffer */
   return 0;
}

int
_foobar_unpack (gnutls_buffer_st * ps, extension_priv_data_t * epriv)
{
   /* Read the internal state from buffer */
   return 0;
}

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

The _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 from the list in Error Codes and Descriptions. Return 0 on success.

An extension typically stores private information in the session data for later usage. That can be done using the functions _gnutls_ext_set_session_data and _gnutls_ext_get_session_data. You can check simple examples at ext/max_record.c and ext/server_name.c extensions. That private information can be saved and restored across session resumption if the following functions are set:

The _foobar_pack function is responsible for packing internal extension data to save them in the session resumption storage.

The _foobar_unpack function is responsible for restoring session data from the session resumption storage.

Recall that both the client and server, send and receive 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,
                            gnutls_buffer_st * data)
{
  if (session->security_parameters.entity == GNUTLS_CLIENT)
    return foobar_send_client (session, data);
  else
    return foobar_send_server (session, data);
}

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 ext/Makefile.am as well, for example:

if ENABLE_FOOBAR
libgnutls_ext_la_SOURCES += ext/foobar.c ext/foobar.h
endif

Add API functions to enable/disable the extension.

It might be desirable to allow users of the extension to request use of the extension, or set extension specific data. This can be implemented by adding extension specific function calls that can be added to includes/gnutls/gnutls.h, as long as the LGPLv3+ applies. The implementation of the function should lie in the ext/foobar.c file.

To make the API available in the shared library you need to add the symbol in lib/libgnutls.map, so that the symbol is exported properly.

When writing GTK-DOC style documentation for your new APIs, don’t forget to add Since: tags to indicate the GnuTLS version the API was introduced in.


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

This document was generated on January 4, 2012 using texi2html 5.0.

© manpagez.com 2000-2025
Individual documents may contain additional copyright information.