Blame doc/cha-internals.texi

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