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