Blame doc/cha-internals.texi

Packit Service 4684c1
@node Internal architecture of GnuTLS
Packit Service 4684c1
@chapter Internal Architecture of GnuTLS
Packit Service 4684c1
@cindex internal architecture
Packit Service 4684c1
Packit Service 4684c1
This chapter is to give a brief description of the
Packit Service 4684c1
way @acronym{GnuTLS} works. The focus is to give an idea
Packit Service 4684c1
to potential developers and those who want to know what
Packit Service 4684c1
happens inside the black box.
Packit Service 4684c1
Packit Service 4684c1
@menu
Packit Service 4684c1
* The TLS Protocol::
Packit Service 4684c1
* TLS Handshake Protocol::
Packit Service 4684c1
* TLS Authentication Methods::
Packit Service 4684c1
* TLS Hello Extension Handling::
Packit Service 4684c1
* Cryptographic Backend::
Packit Service 4684c1
* Random Number Generators-internals::
Packit Service 4684c1
* FIPS140-2 mode::
Packit Service 4684c1
@end menu
Packit Service 4684c1
Packit Service 4684c1
@node The TLS Protocol
Packit Service 4684c1
@section The TLS Protocol
Packit Service 4684c1
The main use case for the TLS protocol is shown in @ref{fig-client-server}.
Packit Service 4684c1
A user of a library implementing the protocol expects no less than this functionality,
Packit Service 4684c1
i.e., to be able to set parameters such as the accepted security level, perform a
Packit Service 4684c1
negotiation with the peer and be able to exchange data.
Packit Service 4684c1
Packit Service 4684c1
@float Figure,fig-client-server
Packit Service 4684c1
@image{gnutls-client-server-use-case,9cm}
Packit Service 4684c1
@caption{TLS protocol use case.}
Packit Service 4684c1
@end float
Packit Service 4684c1
Packit Service 4684c1
@node TLS Handshake Protocol
Packit Service 4684c1
@section TLS Handshake Protocol
Packit Service 4684c1
The @acronym{GnuTLS} handshake protocol is implemented as a state
Packit Service 4684c1
machine that waits for input or returns immediately when the non-blocking
Packit Service 4684c1
transport layer functions are used. The main idea is shown in @ref{fig-gnutls-handshake}.
Packit Service 4684c1
Packit Service 4684c1
@float Figure,fig-gnutls-handshake
Packit Service 4684c1
@image{gnutls-handshake-state,9cm}
Packit Service 4684c1
@caption{GnuTLS handshake state machine.}
Packit Service 4684c1
@end float
Packit Service 4684c1
Packit Service 4684c1
Also the way the input is processed varies per ciphersuite. Several
Packit Service 4684c1
implementations of the internal handlers are available and
Packit Service 4684c1
@funcref{gnutls_handshake} only multiplexes the input to the appropriate
Packit Service 4684c1
handler. For example a @acronym{PSK} ciphersuite has a different
Packit Service 4684c1
implementation of the @code{process_client_key_exchange} than a
Packit Service 4684c1
certificate ciphersuite. We illustrate the idea in @ref{fig-gnutls-handshake-sequence}.
Packit Service 4684c1
Packit Service 4684c1
@float Figure,fig-gnutls-handshake-sequence
Packit Service 4684c1
@image{gnutls-handshake-sequence,12cm}
Packit Service 4684c1
@caption{GnuTLS handshake process sequence.}
Packit Service 4684c1
@end float
Packit Service 4684c1
Packit Service 4684c1
@node TLS Authentication Methods
Packit Service 4684c1
@section TLS Authentication Methods
Packit Service 4684c1
In @acronym{GnuTLS} authentication methods can be implemented quite
Packit Service 4684c1
easily.  Since the required changes to add a new authentication method
Packit Service 4684c1
affect only the handshake protocol, a simple interface is used. An
Packit Service 4684c1
authentication method needs to implement the functions shown below.
Packit Service 4684c1
Packit Service 4684c1
@verbatim
Packit Service 4684c1
typedef struct
Packit Service 4684c1
{
Packit Service 4684c1
  const char *name;
Packit Service 4684c1
  int (*gnutls_generate_server_certificate) (gnutls_session_t, gnutls_buffer_st*);
Packit Service 4684c1
  int (*gnutls_generate_client_certificate) (gnutls_session_t, gnutls_buffer_st*);
Packit Service 4684c1
  int (*gnutls_generate_server_kx) (gnutls_session_t, gnutls_buffer_st*);
Packit Service 4684c1
  int (*gnutls_generate_client_kx) (gnutls_session_t, gnutls_buffer_st*);
Packit Service 4684c1
  int (*gnutls_generate_client_cert_vrfy) (gnutls_session_t, gnutls_buffer_st *);
Packit Service 4684c1
  int (*gnutls_generate_server_certificate_request) (gnutls_session_t,
Packit Service 4684c1
                                                     gnutls_buffer_st *);
Packit Service 4684c1
Packit Service 4684c1
  int (*gnutls_process_server_certificate) (gnutls_session_t, opaque *,
Packit Service 4684c1
                                            size_t);
Packit Service 4684c1
  int (*gnutls_process_client_certificate) (gnutls_session_t, opaque *,
Packit Service 4684c1
                                            size_t);
Packit Service 4684c1
  int (*gnutls_process_server_kx) (gnutls_session_t, opaque *, size_t);
Packit Service 4684c1
  int (*gnutls_process_client_kx) (gnutls_session_t, opaque *, size_t);
Packit Service 4684c1
  int (*gnutls_process_client_cert_vrfy) (gnutls_session_t, opaque *, size_t);
Packit Service 4684c1
  int (*gnutls_process_server_certificate_request) (gnutls_session_t,
Packit Service 4684c1
                                                    opaque *, size_t);
Packit Service 4684c1
} mod_auth_st;
Packit Service 4684c1
@end verbatim
Packit Service 4684c1
Packit Service 4684c1
Those functions are responsible for the
Packit Service 4684c1
interpretation of the handshake protocol messages. It is common for such
Packit Service 4684c1
functions to read data from one or more @code{credentials_t}
Packit Service 4684c1
structures@footnote{such as the
Packit Service 4684c1
@code{gnutls_certificate_credentials_t} structures} and write data,
Packit Service 4684c1
such as certificates, usernames etc. to @code{auth_info_t} structures.
Packit Service 4684c1
Packit Service 4684c1
Packit Service 4684c1
Simple examples of existing authentication methods can be seen in
Packit Service 4684c1
@code{auth/@-psk.c} for PSK ciphersuites and @code{auth/@-srp.c} for SRP
Packit Service 4684c1
ciphersuites. After implementing these functions the structure holding
Packit Service 4684c1
its pointers has to be registered in @code{gnutls_@-algorithms.c} in the
Packit Service 4684c1
@code{_gnutls_@-kx_@-algorithms} structure.
Packit Service 4684c1
Packit Service 4684c1
@node TLS Hello Extension Handling
Packit Service 4684c1
@section TLS Extension Handling
Packit Service 4684c1
As with authentication methods, adding TLS hello extensions can be done
Packit Service 4684c1
quite easily by implementing the interface shown below.
Packit Service 4684c1
Packit Service 4684c1
@verbatim
Packit Service 4684c1
typedef int (*gnutls_ext_recv_func) (gnutls_session_t session,
Packit Service 4684c1
                                     const unsigned char *data, size_t len);
Packit Service 4684c1
typedef int (*gnutls_ext_send_func) (gnutls_session_t session,
Packit Service 4684c1
                                     gnutls_buffer_st *extdata);
Packit Service 4684c1
@end verbatim
Packit Service 4684c1
Packit Service 4684c1
Here there are two main functions, one for parsing the received extension data
Packit Service 4684c1
and one for formatting the extension data that must be send. These functions
Packit Service 4684c1
have to check internally whether they operate within a client or a server session.
Packit Service 4684c1
Packit Service 4684c1
A simple example of an extension handler can be seen in
Packit Service 4684c1
@code{lib/ext/@-srp.c} in GnuTLS' source code. After implementing these functions,
Packit Service 4684c1
the extension has to be registered. Registering an extension can be done in two
Packit Service 4684c1
ways. You can create a GnuTLS internal extension and register it in
Packit Service 4684c1
@code{hello_ext.c} or write an external extension (not inside GnuTLS but
Packit Service 4684c1
inside an application using GnuTLS) and register it via the exported functions
Packit Service 4684c1
@funcref{gnutls_session_ext_register} or @funcref{gnutls_ext_register}.
Packit Service 4684c1
Packit Service 4684c1
@subheading Adding a new TLS hello extension
Packit Service 4684c1
Packit Service 4684c1
Adding support for a new TLS hello extension is done from time to time, and
Packit Service 4684c1
the process to do so is not difficult. Here are the steps you need to
Packit Service 4684c1
follow if you wish to do this yourself. For the sake of discussion, let's
Packit Service 4684c1
consider adding support for the hypothetical TLS extension @code{foobar}.
Packit Service 4684c1
The following section is about adding an hello extension to GnuTLS itself.
Packit Service 4684c1
For custom application extensions you should check the exported functions
Packit Service 4684c1
@funcref{gnutls_session_ext_register} or @funcref{gnutls_ext_register}.
Packit Service 4684c1
Packit Service 4684c1
@subsubheading Add @code{configure} option like @code{--enable-foobar} or @code{--disable-foobar}.
Packit Service 4684c1
Packit Service 4684c1
This step is useful when the extension code is large and it might be desirable
Packit Service 4684c1
under some circumstances to be able to leave out the extension during compilation of GnuTLS.
Packit Service 4684c1
If you don't need this kind of feature this step can be safely skipped.
Packit Service 4684c1
Packit Service 4684c1
Whether to choose enable or disable depends on whether you intend to make the extension be
Packit Service 4684c1
enabled by default. Look at existing checks (i.e., SRP, authz) for
Packit Service 4684c1
how to model the code. For example:
Packit Service 4684c1
Packit Service 4684c1
@example
Packit Service 4684c1
AC_MSG_CHECKING([whether to disable foobar support])
Packit Service 4684c1
AC_ARG_ENABLE(foobar,
Packit Service 4684c1
	AS_HELP_STRING([--disable-foobar],
Packit Service 4684c1
		[disable foobar support]),
Packit Service 4684c1
	ac_enable_foobar=no)
Packit Service 4684c1
if test x$ac_enable_foobar != xno; then
Packit Service 4684c1
 AC_MSG_RESULT(no)
Packit Service 4684c1
 AC_DEFINE(ENABLE_FOOBAR, 1, [enable foobar])
Packit Service 4684c1
else
Packit Service 4684c1
 ac_full=0
Packit Service 4684c1
 AC_MSG_RESULT(yes)
Packit Service 4684c1
fi
Packit Service 4684c1
AM_CONDITIONAL(ENABLE_FOOBAR, test "$ac_enable_foobar" != "no")
Packit Service 4684c1
@end example
Packit Service 4684c1
Packit Service 4684c1
These lines should go in @code{lib/m4/hooks.m4}.
Packit Service 4684c1
Packit Service 4684c1
@subsubheading Add an extension identifier to @code{extensions_t} in @code{gnutls_int.h}.
Packit Service 4684c1
Packit Service 4684c1
A good name for the identifier would be GNUTLS_EXTENSION_FOOBAR. If the
Packit Service 4684c1
extension that you are implementing is an extension that is officially
Packit Service 4684c1
registered by IANA then it is recommended to use its official name such
Packit Service 4684c1
that the extension can be correctly identified by other developers. Check
Packit Service 4684c1
with @url{https://www.iana.org/assignments/tls-extensiontype-values}
Packit Service 4684c1
for registered extensions.
Packit Service 4684c1
Packit Service 4684c1
@subsubheading Register the extension in @code{lib/hello_ext.c}.
Packit Service 4684c1
Packit Service 4684c1
In order for the extension to be executed you need to register it in the
Packit Service 4684c1
@code{static hello_ext_entry_st const *extfunc[]} list in @code{lib/hello_ext.c}.
Packit Service 4684c1
Packit Service 4684c1
A typical entry would be:
Packit Service 4684c1
Packit Service 4684c1
@example
Packit Service 4684c1
#ifdef ENABLE_FOOBAR
Packit Service 4684c1
	[GNUTLS_EXTENSION_FOOBAR] = &ext_mod_foobar,
Packit Service 4684c1
#endif
Packit Service 4684c1
@end example
Packit Service 4684c1
Packit Service 4684c1
Also for every extension you need to create an @code{hello_ext_entry_st}
Packit Service 4684c1
that describes the extension. This structure is placed in the designated
Packit Service 4684c1
c file for your extension and its name is used in the registration entry
Packit Service 4684c1
as depicted above.
Packit Service 4684c1
Packit Service 4684c1
The structure of @code{hello_ext_entry_st} is as follows:
Packit Service 4684c1
@example
Packit Service 4684c1
  const hello_ext_entry_st ext_mod_foobar = @{
Packit Service 4684c1
    .name = "FOOBAR",
Packit Service 4684c1
    .tls_id = 255,
Packit Service 4684c1
    .gid = GNUTLS_EXTENSION_FOOBAR,
Packit Service 4684c1
    .parse_type = GNUTLS_EXT_TLS,
Packit Service 4684c1
    .validity = GNUTLS_EXT_FLAG_CLIENT_HELLO |
Packit Service 4684c1
	GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO |
Packit Service 4684c1
	GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO |
Packit Service 4684c1
	GNUTLS_EXT_FLAG_TLS,
Packit Service 4684c1
    .recv_func = _gnutls_foobar_recv_params,
Packit Service 4684c1
    .send_func = _gnutls_foobar_send_params,
Packit Service 4684c1
    .pack_func = _gnutls_foobar_pack,
Packit Service 4684c1
    .unpack_func = _gnutls_foobar_unpack,
Packit Service 4684c1
    .deinit_func = _gnutls_foobar_deinit,
Packit Service 4684c1
    .cannot_be_overriden = 1
Packit Service 4684c1
  @};
Packit Service 4684c1
@end example
Packit Service 4684c1
Packit Service 4684c1
The GNUTLS_EXTENSION_FOOBAR is the identifier that you've added to
Packit Service 4684c1
@code{gnutls_int.h} earlier. The @code{.tls_id} should contain the number
Packit Service 4684c1
that IANA has assigned to this extension, or an unassigned number of your
Packit Service 4684c1
choice if this is an unregistered extension. In the rest of this structure
Packit Service 4684c1
you specify the functions to handle the extension data. The @code{receive} function
Packit Service 4684c1
will be called upon reception of the data and will be used to parse or
Packit Service 4684c1
interpret the extension data. The @code{send} function will be called prior to
Packit Service 4684c1
sending the extension data on the wire and will be used to format the data
Packit Service 4684c1
such that it can be send over the wire. The @code{pack} and @code{unpack}
Packit Service 4684c1
functions will be used to prepare the data for storage in case of session resumption
Packit Service 4684c1
(and vice versa). The @code{deinit} function will be called to deinitialize
Packit Service 4684c1
the extension's private parameters, if any.
Packit Service 4684c1
Packit Service 4684c1
Look at @code{gnutls_ext_parse_type_t} and @code{gnutls_ext_flags_t} for a complete
Packit Service 4684c1
list of available flags.
Packit Service 4684c1
Packit Service 4684c1
Note that the conditional @code{ENABLE_FOOBAR} definition should only be
Packit Service 4684c1
used if step 1 with the @code{configure} options has taken place.
Packit Service 4684c1
Packit Service 4684c1
@subsubheading Add new files that implement the hello extension.
Packit Service 4684c1
Packit Service 4684c1
To keep things structured every extension should have its own files. The
Packit Service 4684c1
functions that you should (at least) add are those referenced in the struct
Packit Service 4684c1
from the previous step. Use descriptive file names such as @code{lib/ext/@-foobar.c}
Packit Service 4684c1
and for the corresponding header @code{lib/ext/@-foobar.h}.
Packit Service 4684c1
As a starter, you could add this:
Packit Service 4684c1
Packit Service 4684c1
@example
Packit Service 4684c1
int
Packit Service 4684c1
_gnutls_foobar_recv_params (gnutls_session_t session, const uint8_t * data,
Packit Service 4684c1
                     size_t data_size)
Packit Service 4684c1
@{
Packit Service 4684c1
  return 0;
Packit Service 4684c1
@}
Packit Service 4684c1
Packit Service 4684c1
int
Packit Service 4684c1
_gnutls_foobar_send_params (gnutls_session_t session, gnutls_buffer_st* data)
Packit Service 4684c1
@{
Packit Service 4684c1
  return 0;
Packit Service 4684c1
@}
Packit Service 4684c1
Packit Service 4684c1
int
Packit Service 4684c1
_gnutls_foobar_pack (extension_priv_data_t epriv, gnutls_buffer_st * ps)
Packit Service 4684c1
@{
Packit Service 4684c1
   /* Append the extension's internal state to buffer */
Packit Service 4684c1
   return 0;
Packit Service 4684c1
@}
Packit Service 4684c1
Packit Service 4684c1
int
Packit Service 4684c1
_gnutls_foobar_unpack (gnutls_buffer_st * ps, extension_priv_data_t * epriv)
Packit Service 4684c1
@{
Packit Service 4684c1
   /* Read the internal state from buffer */
Packit Service 4684c1
   return 0;
Packit Service 4684c1
@}
Packit Service 4684c1
@end example
Packit Service 4684c1
Packit Service 4684c1
The @funcintref{_gnutls_foobar_recv_params} function is responsible for
Packit Service 4684c1
parsing incoming extension data (both in the client and server).
Packit Service 4684c1
Packit Service 4684c1
The @funcintref{_gnutls_foobar_send_params} function is responsible for
Packit Service 4684c1
formatting extension data such that it can be send over the wire (both in
Packit Service 4684c1
the client and server). It should append data to provided buffer and
Packit Service 4684c1
return a positive (or zero) number on success or a negative error code.
Packit Service 4684c1
Previous to 3.6.0 versions of GnuTLS required that function to return the
Packit Service 4684c1
number of bytes that were written. If zero is returned and no bytes are
Packit Service 4684c1
appended the extension will not be sent. If a zero byte extension is to
Packit Service 4684c1
be sent this function must return @code{GNUTLS_E_INT_RET_0}.
Packit Service 4684c1
Packit Service 4684c1
If you receive length fields that don't match, return
Packit Service 4684c1
@code{GNUTLS_E_@-UNEXPECTED_@-PACKET_@-LENGTH}.  If you receive invalid
Packit Service 4684c1
data, return @code{GNUTLS_E_@-RECEIVED_@-ILLEGAL_@-PARAMETER}.  You can use
Packit Service 4684c1
other error codes from the list in @ref{Error codes}. Return 0 on success.
Packit Service 4684c1
Packit Service 4684c1
An extension typically stores private information in the @code{session}
Packit Service 4684c1
data for later usage. That can be done using the functions
Packit Service 4684c1
@funcintref{_gnutls_hello_ext_set_datum} and
Packit Service 4684c1
@funcintref{_gnutls_hello_ext_get_datum}. You can check simple examples
Packit Service 4684c1
at @code{lib/ext/@-max_@-record.c} and @code{lib/ext/@-server_@-name.c} extensions.
Packit Service 4684c1
That private information can be saved and restored across session
Packit Service 4684c1
resumption if the following functions are set:
Packit Service 4684c1
Packit Service 4684c1
The @funcintref{_gnutls_foobar_pack} function is responsible for packing
Packit Service 4684c1
internal extension data to save them in the session resumption storage.
Packit Service 4684c1
Packit Service 4684c1
The @funcintref{_gnutls_foobar_unpack} function is responsible for
Packit Service 4684c1
restoring session data from the session resumption storage.
Packit Service 4684c1
Packit Service 4684c1
When the internal data is stored using the @funcintref{_gnutls_hello_ext_set_datum},
Packit Service 4684c1
then you can rely on the default pack and unpack functions:
Packit Service 4684c1
@funcintref{_gnutls_hello_ext_default_pack} and
Packit Service 4684c1
@funcintref{_gnutls_hello_ext_default_unpack}.
Packit Service 4684c1
Packit Service 4684c1
Recall that both for the client and server, the send and receive
Packit Service 4684c1
functions most likely will need to do different things
Packit Service 4684c1
depending on which mode they are in. It may be useful to make this
Packit Service 4684c1
distinction explicit in the code. Thus, for example, a better
Packit Service 4684c1
template than above would be:
Packit Service 4684c1
Packit Service 4684c1
@example
Packit Service 4684c1
int
Packit Service 4684c1
_gnutls_foobar_recv_params (gnutls_session_t session,
Packit Service 4684c1
                            const uint8_t * data,
Packit Service 4684c1
                            size_t data_size)
Packit Service 4684c1
@{
Packit Service 4684c1
  if (session->security_parameters.entity == GNUTLS_CLIENT)
Packit Service 4684c1
    return foobar_recv_client (session, data, data_size);
Packit Service 4684c1
  else
Packit Service 4684c1
    return foobar_recv_server (session, data, data_size);
Packit Service 4684c1
@}
Packit Service 4684c1
Packit Service 4684c1
int
Packit Service 4684c1
_gnutls_foobar_send_params (gnutls_session_t session,
Packit Service 4684c1
                            gnutls_buffer_st * data)
Packit Service 4684c1
@{
Packit Service 4684c1
  if (session->security_parameters.entity == GNUTLS_CLIENT)
Packit Service 4684c1
    return foobar_send_client (session, data);
Packit Service 4684c1
  else
Packit Service 4684c1
    return foobar_send_server (session, data);
Packit Service 4684c1
@}
Packit Service 4684c1
@end example
Packit Service 4684c1
Packit Service 4684c1
The functions used would be declared as @code{static} functions, of
Packit Service 4684c1
the appropriate prototype, in the same file.
Packit Service 4684c1
Packit Service 4684c1
When adding the new extension files, you'll need to add them to @code{lib/ext/@-Makefile.am}
Packit Service 4684c1
as well, for example:
Packit Service 4684c1
Packit Service 4684c1
@example
Packit Service 4684c1
if ENABLE_FOOBAR
Packit Service 4684c1
libgnutls_ext_la_SOURCES += ext/foobar.c ext/foobar.h
Packit Service 4684c1
endif
Packit Service 4684c1
@end example
Packit Service 4684c1
Packit Service 4684c1
@subsubheading Add API functions to use the extension.
Packit Service 4684c1
Packit Service 4684c1
It might be desirable to allow users of the extension to
Packit Service 4684c1
request the use of the extension, or set extension specific data.
Packit Service 4684c1
This can be implemented by adding extension specific function calls
Packit Service 4684c1
that can be added to @code{includes/@-gnutls/@-gnutls.h},
Packit Service 4684c1
as long as the LGPLv2.1+ applies.
Packit Service 4684c1
The implementation of these functions should lie in the @code{lib/ext/@-foobar.c} file.
Packit Service 4684c1
Packit Service 4684c1
To make the API available in the shared library you need to add the added
Packit Service 4684c1
symbols in @code{lib/@-libgnutls.map}, so that the symbols are exported properly.
Packit Service 4684c1
Packit Service 4684c1
When writing GTK-DOC style documentation for your new APIs, don't
Packit Service 4684c1
forget to add @code{Since:} tags to indicate the GnuTLS version the
Packit Service 4684c1
API was introduced in.
Packit Service 4684c1
Packit Service 4684c1
@subheading Adding a new Supplemental Data Handshake Message
Packit Service 4684c1
Packit Service 4684c1
TLS handshake extensions allow to send so called supplemental data
Packit Service 4684c1
handshake messages @xcite{RFC4680}. This short section explains how to
Packit Service 4684c1
implement a supplemental data handshake message for a given TLS extension.
Packit Service 4684c1
Packit Service 4684c1
First of all, modify your extension @code{foobar} in the way, to instruct
Packit Service 4684c1
the handshake process to send and receive supplemental data, as shown below.
Packit Service 4684c1
Packit Service 4684c1
@example
Packit Service 4684c1
int
Packit Service 4684c1
_gnutls_foobar_recv_params (gnutls_session_t session, const opaque * data,
Packit Service 4684c1
                                 size_t _data_size)
Packit Service 4684c1
@{
Packit Service 4684c1
   ...
Packit Service 4684c1
   gnutls_supplemental_recv(session, 1);
Packit Service 4684c1
   ...
Packit Service 4684c1
@}
Packit Service 4684c1
Packit Service 4684c1
int
Packit Service 4684c1
_gnutls_foobar_send_params (gnutls_session_t session, gnutls_buffer_st *extdata)
Packit Service 4684c1
@{
Packit Service 4684c1
   ...
Packit Service 4684c1
   gnutls_supplemental_send(session, 1);
Packit Service 4684c1
   ...
Packit Service 4684c1
@}
Packit Service 4684c1
@end example
Packit Service 4684c1
Packit Service 4684c1
Furthermore you'll need two new functions @funcintref{_foobar_supp_recv_params}
Packit Service 4684c1
and @funcintref{_foobar_supp_send_params}, which must conform to the following
Packit Service 4684c1
prototypes.
Packit Service 4684c1
Packit Service 4684c1
@example
Packit Service 4684c1
typedef int (*gnutls_supp_recv_func)(gnutls_session_t session,
Packit Service 4684c1
                                     const unsigned char *data,
Packit Service 4684c1
                                     size_t data_size);
Packit Service 4684c1
typedef int (*gnutls_supp_send_func)(gnutls_session_t session,
Packit Service 4684c1
                                     gnutls_buffer_t buf);
Packit Service 4684c1
@end example
Packit Service 4684c1
Packit Service 4684c1
The following example code shows how to send a
Packit Service 4684c1
``Hello World'' string in the supplemental data handshake message.
Packit Service 4684c1
Packit Service 4684c1
@example
Packit Service 4684c1
int
Packit Service 4684c1
_foobar_supp_recv_params(gnutls_session_t session, const opaque *data, size_t _data_size)
Packit Service 4684c1
@{
Packit Service 4684c1
   uint8_t len = _data_size;
Packit Service 4684c1
   unsigned char *msg;
Packit Service 4684c1
Packit Service 4684c1
   msg = gnutls_malloc(len);
Packit Service 4684c1
   if (msg == NULL) return GNUTLS_E_MEMORY_ERROR;
Packit Service 4684c1
Packit Service 4684c1
   memcpy(msg, data, len);
Packit Service 4684c1
   msg[len]='\0';
Packit Service 4684c1
Packit Service 4684c1
   /* do something with msg */
Packit Service 4684c1
   gnutls_free(msg);
Packit Service 4684c1
Packit Service 4684c1
   return len;
Packit Service 4684c1
@}
Packit Service 4684c1
Packit Service 4684c1
int
Packit Service 4684c1
_foobar_supp_send_params(gnutls_session_t session, gnutls_buffer_t buf)
Packit Service 4684c1
@{
Packit Service 4684c1
   unsigned char *msg = "hello world";
Packit Service 4684c1
   int len = strlen(msg);
Packit Service 4684c1
Packit Service 4684c1
   if (gnutls_buffer_append_data(buf, msg, len) < 0)
Packit Service 4684c1
       abort();
Packit Service 4684c1
Packit Service 4684c1
   return len;
Packit Service 4684c1
@}
Packit Service 4684c1
@end example
Packit Service 4684c1
Packit Service 4684c1
Afterwards, register the new supplemental data using @funcref{gnutls_session_supplemental_register},
Packit Service 4684c1
or @funcref{gnutls_supplemental_register} at some point in your program.
Packit Service 4684c1
Packit Service 4684c1
@node Cryptographic Backend
Packit Service 4684c1
@section Cryptographic Backend
Packit Service 4684c1
Packit Service 4684c1
Today most new processors, either for embedded or desktop systems
Packit Service 4684c1
include either instructions  intended to speed up cryptographic operations,
Packit Service 4684c1
or a co-processor with cryptographic capabilities. Taking advantage of
Packit Service 4684c1
those is a challenging task for every cryptographic  application or
Packit Service 4684c1
library. GnuTLS handles the cryptographic provider in a modular
Packit Service 4684c1
way, following a layered approach to access
Packit Service 4684c1
cryptographic operations as in @ref{fig-crypto-layers}.
Packit Service 4684c1
Packit Service 4684c1
@float Figure,fig-crypto-layers
Packit Service 4684c1
@image{gnutls-crypto-layers,12cm}
Packit Service 4684c1
@caption{GnuTLS cryptographic back-end design.}
Packit Service 4684c1
@end float
Packit Service 4684c1
Packit Service 4684c1
The TLS layer uses a cryptographic provider layer, that will in turn either
Packit Service 4684c1
use the default crypto provider -- a software crypto library, or use an external
Packit Service 4684c1
crypto provider, if available in the local system. The reason of handling
Packit Service 4684c1
the external cryptographic provider in GnuTLS and not delegating it to
Packit Service 4684c1
the cryptographic libraries, is that none of the supported cryptographic
Packit Service 4684c1
libraries support @code{/dev/crypto} or CPU-optimized cryptography in
Packit Service 4684c1
an efficient way.
Packit Service 4684c1
Packit Service 4684c1
@subheading Cryptographic library layer
Packit Service 4684c1
The Cryptographic library layer, currently supports only
Packit Service 4684c1
libnettle. Older versions of GnuTLS used to support libgcrypt,
Packit Service 4684c1
but it was switched with nettle mainly for performance reasons@footnote{See
Packit Service 4684c1
@url{https://lists.gnu.org/archive/html/gnutls-devel/2011-02/msg00079.html}.}
Packit Service 4684c1
and secondary because it is a simpler library to use.
Packit Service 4684c1
In the future other cryptographic libraries might be supported as well.
Packit Service 4684c1
Packit Service 4684c1
@subheading External cryptography provider
Packit Service 4684c1
Systems that include a cryptographic co-processor, typically come with
Packit Service 4684c1
kernel drivers to utilize the operations from software. For this reason
Packit Service 4684c1
GnuTLS provides a layer where each individual algorithm used can be replaced
Packit Service 4684c1
by another implementation, i.e., the one provided by the driver. The
Packit Service 4684c1
FreeBSD, OpenBSD and Linux kernels@footnote{Check @url{https://home.gna.org/cryptodev-linux/}
Packit Service 4684c1
for the Linux kernel implementation of @code{/dev/crypto}.} include already
Packit Service 4684c1
a number of hardware assisted implementations, and also provide an interface
Packit Service 4684c1
to access them, called @code{/dev/crypto}.
Packit Service 4684c1
GnuTLS will take advantage of this interface if compiled with special
Packit Service 4684c1
options. That is because in most systems where hardware-assisted
Packit Service 4684c1
cryptographic operations are not available, using this interface might
Packit Service 4684c1
actually harm performance.
Packit Service 4684c1
Packit Service 4684c1
In systems that include cryptographic instructions with the CPU's
Packit Service 4684c1
instructions set, using the kernel interface will introduce an
Packit Service 4684c1
unneeded layer. For this reason GnuTLS includes such optimizations
Packit Service 4684c1
found in popular processors such as the AES-NI or VIA PADLOCK instruction sets.
Packit Service 4684c1
This is achieved using a mechanism that detects CPU capabilities and
Packit Service 4684c1
overrides parts of crypto back-end at runtime.
Packit Service 4684c1
The next section discusses the registration of a detected algorithm
Packit Service 4684c1
optimization. For more information please consult the @acronym{GnuTLS}
Packit Service 4684c1
source code in @code{lib/accelerated/}.
Packit Service 4684c1
Packit Service 4684c1
@subsubheading Overriding specific algorithms
Packit Service 4684c1
When an optimized implementation of a single algorithm is available,
Packit Service 4684c1
say a hardware assisted version of @acronym{AES-CBC} then the
Packit Service 4684c1
following functions, from @code{crypto.h}, can
Packit Service 4684c1
be used to register those algorithms.
Packit Service 4684c1
Packit Service 4684c1
@itemize
Packit Service 4684c1
Packit Service 4684c1
@item @funcref{gnutls_crypto_register_cipher}:
Packit Service 4684c1
To register a cipher algorithm.
Packit Service 4684c1
Packit Service 4684c1
@item @funcref{gnutls_crypto_register_aead_cipher}:
Packit Service 4684c1
To register an AEAD cipher algorithm.
Packit Service 4684c1
Packit Service 4684c1
@item @funcref{gnutls_crypto_register_mac}:
Packit Service 4684c1
To register a MAC algorithm.
Packit Service 4684c1
Packit Service 4684c1
@item @funcref{gnutls_crypto_register_digest}:
Packit Service 4684c1
To register a hash algorithm.
Packit Service 4684c1
Packit Service 4684c1
@end itemize
Packit Service 4684c1
Packit Service 4684c1
Those registration functions will only replace the specified algorithm
Packit Service 4684c1
and leave the rest of subsystem intact.
Packit Service 4684c1
Packit Service 4684c1
Packit Service 4684c1
@subheading Protecting keys through isolation
Packit Service 4684c1
Packit Service 4684c1
For asymmetric or public keys, GnuTLS supports PKCS #11 which allows
Packit Service 4684c1
operation without access to long term keys, in addition to CPU offloading.
Packit Service 4684c1
For more information see @ref{Hardware security modules and abstract key types}.
Packit Service 4684c1
Packit Service 4684c1
Packit Service 4684c1
@node Random Number Generators-internals
Packit Service 4684c1
@section Random Number Generators
Packit Service 4684c1
Packit Service 4684c1
@subheading About the generators
Packit Service 4684c1
Packit Service 4684c1
GnuTLS provides two random generators. The default, and the AES-DRBG random
Packit Service 4684c1
generator which is only used when the library is compiled with support for
Packit Service 4684c1
FIPS140-2 and the system is in FIPS140-2 mode.
Packit Service 4684c1
Packit Service 4684c1
@subheading The default generator - inner workings
Packit Service 4684c1
Packit Service 4684c1
The random number generator levels in @code{gnutls_rnd_level_t} map to two CHACHA-based random generators which
Packit Service 4684c1
are initially seeded using the OS random device, e.g., @code{/dev/urandom}
Packit Service 4684c1
or @code{getrandom()}. These random generators are unique per thread, and
Packit Service 4684c1
are automatically re-seeded when a fork is detected.
Packit Service 4684c1
Packit Service 4684c1
The reason the CHACHA cipher was selected for the GnuTLS' PRNG is the fact
Packit Service 4684c1
that CHACHA is considered a secure and fast stream cipher, and is already
Packit Service 4684c1
defined for use in TLS protocol. As such, the utilization of it would
Packit Service 4684c1
not stress the CPU caches, and would allow for better performance on busy
Packit Service 4684c1
servers, irrespective of their architecture (e.g., even if AES is not
Packit Service 4684c1
available with an optimized instruction set).
Packit Service 4684c1
Packit Service 4684c1
The generators are unique per thread to allow lock-free operation. That
Packit Service 4684c1
induces a cost of around 140-bytes for the state of the generators per
Packit Service 4684c1
thread, on threads that would utilize @funcref{gnutls_rnd}. At the same time
Packit Service 4684c1
it allows fast and lock-free access to the generators. The lock-free access
Packit Service 4684c1
benefits servers which utilize more than 4 threads, while imposes no cost on
Packit Service 4684c1
single threaded processes.
Packit Service 4684c1
Packit Service 4684c1
On the first call to @funcref{gnutls_rnd} the generators are seeded with two independent
Packit Service 4684c1
keys obtained from the OS random device. Their seed is used to output a fixed amount
Packit Service 4684c1
of bytes before re-seeding; the number of bytes output varies per generator.
Packit Service 4684c1
Packit Service 4684c1
One generator is dedicated for the @code{GNUTLS_RND_NONCE} level, and the
Packit Service 4684c1
second is shared for the @code{GNUTLS_RND_KEY} and @code{GNUTLS_RND_RANDOM}
Packit Service 4684c1
levels. For the rest of this section we refer to the first as the nonce
Packit Service 4684c1
generator and the second as the key generator.
Packit Service 4684c1
Packit Service 4684c1
The nonce generator will reseed after outputting a fixed amount of bytes
Packit Service 4684c1
(typically few megabytes), or after few hours of operation without reaching
Packit Service 4684c1
the limit has passed. It is being re-seed using
Packit Service 4684c1
the key generator to obtain a new key for the CHACHA cipher, which is mixed
Packit Service 4684c1
with its old one.
Packit Service 4684c1
Packit Service 4684c1
Similarly, the key generator, will also re-seed after a fixed amount
Packit Service 4684c1
of bytes is generated (typically less than the nonce), and will also re-seed
Packit Service 4684c1
based on time, i.e., after few hours of operation without reaching the limit
Packit Service 4684c1
for a re-seed. For its re-seed it mixes mixes data obtained from the OS random
Packit Service 4684c1
device with the previous key.
Packit Service 4684c1
Packit Service 4684c1
Although the key generator used to provide data for the @code{GNUTLS_RND_RANDOM}
Packit Service 4684c1
and @code{GNUTLS_RND_KEY} levels is identical, when used with the @code{GNUTLS_RND_KEY} level
Packit Service 4684c1
a re-key of the PRNG using its own output, is additionally performed. That ensures that
Packit Service 4684c1
the recovery of the PRNG state will not be sufficient to recover previously generated values.
Packit Service 4684c1
Packit Service 4684c1
Packit Service 4684c1
@subheading The AES-DRBG generator - inner workings
Packit Service 4684c1
Packit Service 4684c1
Similar with the default generator, the random number generator levels in @code{gnutls_rnd_level_t} map to two
Packit Service 4684c1
AES-DRBG random generators which are initially seeded using the OS random device,
Packit Service 4684c1
e.g., @code{/dev/urandom} or @code{getrandom()}. These random generators are
Packit Service 4684c1
unique per thread, and are automatically re-seeded when a fork is detected.
Packit Service 4684c1
Packit Service 4684c1
The AES-DRBG generator is based on the AES cipher in counter mode and is
Packit Service 4684c1
re-seeded after a fixed amount of bytes are generated.
Packit Service 4684c1
Packit Service 4684c1
Packit Service 4684c1
@subheading Defense against PRNG attacks
Packit Service 4684c1
Packit Service 4684c1
This section describes the counter-measures available in the Pseudo-random number generator (PRNG)
Packit Service 4684c1
of GnuTLS for known attacks as described in @xcite{PRNGATTACKS}. Note that, the attacks on a PRNG such as
Packit Service 4684c1
state-compromise, assume a quite powerful adversary which has in practice
Packit Service 4684c1
access to the PRNG state.
Packit Service 4684c1
Packit Service 4684c1
@subsubheading Cryptanalytic
Packit Service 4684c1
Packit Service 4684c1
To defend against cryptanalytic attacks GnuTLS' PRNG is a stream cipher
Packit Service 4684c1
designed to defend against the same attacks. As such, GnuTLS' PRNG strength
Packit Service 4684c1
with regards to this attack relies on the underlying crypto block,
Packit Service 4684c1
which at the time of writing is CHACHA. That is easily replaceable in
Packit Service 4684c1
the future if attacks are found to be possible in that cipher.
Packit Service 4684c1
Packit Service 4684c1
@subsubheading Input-based attacks
Packit Service 4684c1
Packit Service 4684c1
These attacks assume that the attacker can influence the input that is used
Packit Service 4684c1
to form the state of the PRNG. To counter these attacks GnuTLS does not
Packit Service 4684c1
gather input from the system environment but rather relies on the OS
Packit Service 4684c1
provided random generator. That is the @code{/dev/urandom} or
Packit Service 4684c1
@code{getentropy}/@code{getrandom} system calls. As such, GnuTLS' PRNG
Packit Service 4684c1
is as strong as the system random generator can assure with regards to
Packit Service 4684c1
input-based attacks.
Packit Service 4684c1
Packit Service 4684c1
@subsubheading State-compromise: Backtracking
Packit Service 4684c1
Packit Service 4684c1
A backtracking attack, assumes that an adversary obtains at some point of time
Packit Service 4684c1
access to the generator state, and wants to recover past bytes. As the
Packit Service 4684c1
GnuTLS generator is fine-tuned to provide multiple levels, such an attack
Packit Service 4684c1
mainly concerns levels @code{GNUTLS_RND_RANDOM} and @code{GNUTLS_RND_KEY},
Packit Service 4684c1
since @code{GNUTLS_RND_NONCE} is intended to output non-secret data.
Packit Service 4684c1
The @code{GNUTLS_RND_RANDOM} generator at the time of writing can output
Packit Service 4684c1
2MB prior to being re-seeded thus this is its upper bound for previously
Packit Service 4684c1
generated data recovered using this attack. That assumes that the state
Packit Service 4684c1
of the operating system random generator is unknown to the attacker, and we carry that
Packit Service 4684c1
assumption on the next paragraphs. The usage of @code{GNUTLS_RND_KEY} level
Packit Service 4684c1
ensures that no backtracking is possible for all output data, by re-keying
Packit Service 4684c1
the PRNG using its own output.
Packit Service 4684c1
Packit Service 4684c1
Such an attack reflects the real world scenario where application's memory is
Packit Service 4684c1
temporarily compromised, while the kernel's memory is inaccessible.
Packit Service 4684c1
Packit Service 4684c1
@subsubheading State-compromise: Permanent Compromise Attack
Packit Service 4684c1
Packit Service 4684c1
A permanent compromise attack implies that once an attacker compromises the
Packit Service 4684c1
state of GnuTLS' random generator at a specific time, future and past
Packit Service 4684c1
outputs from the generator are compromised. For past outputs the
Packit Service 4684c1
previous paragraph applies. For future outputs, both the @code{GNUTLS_RND_RANDOM}
Packit Service 4684c1
and the @code{GNUTLS_RND_KEY} will recover after 2MB of data have been generated
Packit Service 4684c1
or few hours have passed (two at the time of writing). Similarly the @code{GNUTLS_RND_NONCE}
Packit Service 4684c1
level generator will recover after several megabytes of output is generated,
Packit Service 4684c1
or its re-key time is reached.
Packit Service 4684c1
Packit Service 4684c1
@subsubheading State-compromise: Iterative guessing
Packit Service 4684c1
Packit Service 4684c1
This attack assumes that after an attacker obtained the PRNG state
Packit Service 4684c1
at some point, is able to recover the state at a later time by observing
Packit Service 4684c1
outputs of the PRNG. That is countered by switching the key to generators
Packit Service 4684c1
using a combination of a fresh key and the old one (using XOR), at
Packit Service 4684c1
re-seed time. All levels are immune to such attack after a re-seed.
Packit Service 4684c1
Packit Service 4684c1
@subsubheading State-compromise: Meet-in-the-Middle
Packit Service 4684c1
Packit Service 4684c1
This attack assumes that the attacker obtained the PRNG state at
Packit Service 4684c1
two distinct times, and being able to recover the state at the third time
Packit Service 4684c1
after observing the output of the PRNG. Given the approach described
Packit Service 4684c1
on the above paragraph, all levels are immune to such attack.
Packit Service 4684c1
Packit Service 4684c1
@node FIPS140-2 mode
Packit Service 4684c1
@section FIPS140-2 mode
Packit Service 4684c1
Packit Service 4684c1
GnuTLS can operate in a special mode for FIPS140-2. That mode of operation
Packit Service 4684c1
is for the conformance to NIST's FIPS140-2 publication, which consists of policies
Packit Service 4684c1
for cryptographic modules (such as software libraries). Its implementation in
Packit Service 4684c1
GnuTLS is designed for Red Hat Enterprise Linux, and can only be enabled
Packit Service 4684c1
when the library is explicitly compiled with the '--enable-fips140-mode'
Packit Service 4684c1
configure option.
Packit Service 4684c1
Packit Service 4684c1
There are two distinct library states with regard to FIPS140-2: the FIPS140-2
Packit Service 4684c1
mode is @emph{installed} if @code{/etc/system-fips} is present, and the
Packit Service 4684c1
FIPS140-2 mode is @emph{enabled} if @code{/proc/sys/crypto/fips_enabled}
Packit Service 4684c1
contains '1', which is typically set with the ``fips=1'' kernel command line
Packit Service 4684c1
option.
Packit Service 4684c1
Packit Service 4684c1
When the FIPS140-2 mode is installed, the operation of the library is modified
Packit Service 4684c1
as follows.
Packit Service 4684c1
Packit Service 4684c1
@itemize
Packit Service 4684c1
@item The random generator used switches to DRBG-AES
Packit Service 4684c1
@item The integrity of the GnuTLS and dependent libraries is checked on startup
Packit Service 4684c1
@item Algorithm self-tests are run on library load
Packit Service 4684c1
@end itemize
Packit Service 4684c1
Packit Service 4684c1
When the FIPS140-2 mode is enabled, The operation of the library is in addition
Packit Service 4684c1
modified as follows.
Packit Service 4684c1
Packit Service 4684c1
@itemize
Packit Service 4684c1
@item Only approved by FIPS140-2 algorithms are enabled
Packit Service 4684c1
@item Only approved by FIPS140-2 key lengths are allowed for key generation
Packit Service 4684c1
@item Any cryptographic operation will be refused if any of the self-tests failed
Packit Service 4684c1
@end itemize
Packit Service 4684c1
Packit Service 4684c1
Packit Service 4684c1
There are also few environment variables which modify that operation. The
Packit Service 4684c1
environment variable @code{GNUTLS_SKIP_FIPS_INTEGRITY_CHECKS} will disable
Packit Service 4684c1
the library integrity tests on startup, and the variable
Packit Service 4684c1
@code{GNUTLS_FORCE_FIPS_MODE} can be set to force a value from
Packit Service 4684c1
@ref{gnutls_fips_mode_t}, i.e., '1' will enable the FIPS140-2
Packit Service 4684c1
mode, while '0' will disable it.
Packit Service 4684c1
Packit Service 4684c1
The integrity checks for the dependent libraries and GnuTLS are performed
Packit Service 4684c1
using '.hmac' files which are present at the same path as the library. The
Packit Service 4684c1
key for the operations can be provided on compile-time with the configure
Packit Service 4684c1
option '--with-fips140-key'. The MAC algorithm used is HMAC-SHA256.
Packit Service 4684c1
Packit Service 4684c1
On runtime an application can verify whether the library is in FIPS140-2
Packit Service 4684c1
mode using the @funcref{gnutls_fips140_mode_enabled} function.
Packit Service 4684c1
Packit Service 4684c1
@subheading Relaxing FIPS140-2 requirements
Packit Service 4684c1
Packit Service 4684c1
The library by default operates in a strict enforcing mode, ensuring that
Packit Service 4684c1
all constraints imposed by the FIPS140-2 specification are enforced. However
Packit Service 4684c1
the application can relax these requirements via @funcref{gnutls_fips140_set_mode}
Packit Service 4684c1
which can switch to alternative modes as in @ref{gnutls_fips_mode_t}.
Packit Service 4684c1
Packit Service 4684c1
@showenumdesc{gnutls_fips_mode_t,The @code{gnutls_@-fips_@-mode_t} enumeration.}
Packit Service 4684c1
Packit Service 4684c1
The intention of this API is to be used by applications which may run in
Packit Service 4684c1
FIPS140-2 mode, while they utilize few algorithms not in the allowed set,
Packit Service 4684c1
e.g., for non-security related purposes. In these cases applications should
Packit Service 4684c1
wrap the non-compliant code within blocks like the following.
Packit Service 4684c1
Packit Service 4684c1
@example
Packit Service 4684c1
GNUTLS_FIPS140_SET_LAX_MODE();
Packit Service 4684c1
Packit Service 4684c1
_gnutls_hash_fast(GNUTLS_DIG_MD5, buffer, sizeof(buffer), output);
Packit Service 4684c1
Packit Service 4684c1
GNUTLS_FIPS140_SET_STRICT_MODE();
Packit Service 4684c1
@end example
Packit Service 4684c1
Packit Service 4684c1
The @code{GNUTLS_FIPS140_SET_LAX_MODE} and
Packit Service 4684c1
@code{GNUTLS_FIPS140_SET_STRICT_MODE} are macros to simplify the following
Packit Service 4684c1
sequence of calls.
Packit Service 4684c1
Packit Service 4684c1
@example
Packit Service 4684c1
if (gnutls_fips140_mode_enabled())
Packit Service 4684c1
  gnutls_fips140_set_mode(GNUTLS_FIPS140_LAX, GNUTLS_FIPS140_SET_MODE_THREAD);
Packit Service 4684c1
Packit Service 4684c1
_gnutls_hash_fast(GNUTLS_DIG_MD5, buffer, sizeof(buffer), output);
Packit Service 4684c1
Packit Service 4684c1
if (gnutls_fips140_mode_enabled())
Packit Service 4684c1
  gnutls_fips140_set_mode(GNUTLS_FIPS140_STRICT, GNUTLS_FIPS140_SET_MODE_THREAD);
Packit Service 4684c1
@end example
Packit Service 4684c1
Packit Service 4684c1
The reason of the @code{GNUTLS_FIPS140_SET_MODE_THREAD} flag in the
Packit Service 4684c1
previous calls is to localize the change in the mode. Note also, that
Packit Service 4684c1
such a block has no effect when the library is not operating
Packit Service 4684c1
under FIPS140-2 mode, and thus it can be considered a no-op.
Packit Service 4684c1
Packit Service 4684c1
Applications could also switch FIPS140-2 mode explicitly off, by calling
Packit Service 4684c1
@example
Packit Service 4684c1
gnutls_fips140_set_mode(GNUTLS_FIPS140_LAX, 0);
Packit Service 4684c1
@end example