1 @node Internal architecture of GnuTLS
2 @chapter Internal Architecture of GnuTLS
3 @cindex internal architecture
5 This chapter is to give a brief description of the
6 way @acronym{GnuTLS} works. The focus is to give an idea
7 to potential developers and those who want to know what
8 happens inside the black box.
12 * TLS Handshake Protocol::
13 * TLS Authentication Methods::
14 * TLS Extension Handling::
15 * Cryptographic Backend::
18 @node The TLS Protocol
19 @section The TLS Protocol
20 The main use case for the TLS protocol is shown in @ref{fig:client-server}.
21 A user of a library implementing the protocol expects no less than this functionality,
22 i.e., to be able to set parameters such as the accepted security level, perform a
23 negotiation with the peer and be able to exchange data.
25 @float Figure,fig:client-server
26 @image{gnutls-client-server-use-case,9cm}
27 @caption{TLS protocol use case.}
30 @node TLS Handshake Protocol
31 @section TLS Handshake Protocol
32 The @acronym{GnuTLS} handshake protocol is implemented as a state
33 machine that waits for input or returns immediately when the non-blocking
34 transport layer functions are used. The main idea is shown in @ref{fig:gnutls-handshake}.
36 @float Figure,fig:gnutls-handshake
37 @image{gnutls-handshake-state,9cm}
38 @caption{GnuTLS handshake state machine.}
41 Also the way the input is processed varies per ciphersuite. Several
42 implementations of the internal handlers are available and
43 @funcref{gnutls_handshake} only multiplexes the input to the appropriate
44 handler. For example a @acronym{PSK} ciphersuite has a different
45 implementation of the @code{process_client_key_exchange} than a
46 certificate ciphersuite. We illustrate the idea in @ref{fig:gnutls-handshake-sequence}.
48 @float Figure,fig:gnutls-handshake-sequence
49 @image{gnutls-handshake-sequence,12cm}
50 @caption{GnuTLS handshake process sequence.}
53 @node TLS Authentication Methods
54 @section TLS Authentication Methods
55 In @acronym{GnuTLS} authentication methods can be implemented quite
56 easily. Since the required changes to add a new authentication method
57 affect only the handshake protocol, a simple interface is used. An
58 authentication method needs to implement the functions shown below.
64 int (*gnutls_generate_server_certificate) (gnutls_session_t, gnutls_buffer_st*);
65 int (*gnutls_generate_client_certificate) (gnutls_session_t, gnutls_buffer_st*);
66 int (*gnutls_generate_server_kx) (gnutls_session_t, gnutls_buffer_st*);
67 int (*gnutls_generate_client_kx) (gnutls_session_t, gnutls_buffer_st*);
68 int (*gnutls_generate_client_cert_vrfy) (gnutls_session_t, gnutls_buffer_st *);
69 int (*gnutls_generate_server_certificate_request) (gnutls_session_t,
72 int (*gnutls_process_server_certificate) (gnutls_session_t, opaque *,
74 int (*gnutls_process_client_certificate) (gnutls_session_t, opaque *,
76 int (*gnutls_process_server_kx) (gnutls_session_t, opaque *, size_t);
77 int (*gnutls_process_client_kx) (gnutls_session_t, opaque *, size_t);
78 int (*gnutls_process_client_cert_vrfy) (gnutls_session_t, opaque *, size_t);
79 int (*gnutls_process_server_certificate_request) (gnutls_session_t,
84 Those functions are responsible for the
85 interpretation of the handshake protocol messages. It is common for such
86 functions to read data from one or more @code{credentials_t}
87 structures@footnote{such as the
88 @code{gnutls_certificate_credentials_t} structures} and write data,
89 such as certificates, usernames etc. to @code{auth_info_t} structures.
92 Simple examples of existing authentication methods can be seen in
93 @code{auth/@-psk.c} for PSK ciphersuites and @code{auth/@-srp.c} for SRP
94 ciphersuites. After implementing these functions the structure holding
95 its pointers has to be registered in @code{gnutls_@-algorithms.c} in the
96 @code{_gnutls_@-kx_@-algorithms} structure.
98 @node TLS Extension Handling
99 @section TLS Extension Handling
100 As with authentication methods, the TLS extensions handlers can be
101 implemented using the interface shown below.
104 typedef int (*gnutls_ext_recv_func) (gnutls_session_t session,
105 const unsigned char *data, size_t len);
106 typedef int (*gnutls_ext_send_func) (gnutls_session_t session,
107 gnutls_buffer_st *extdata);
110 Here there are two functions, one for receiving the extension data
111 and one for sending. These functions have to check internally whether
112 they operate in client or server side.
114 A simple example of an extension handler can be seen in
115 @code{ext/@-srp.c} in GnuTLS' source code. After implementing these functions,
116 together with the extension number they handle, they have to be registered
117 using @funcintref{_gnutls_ext_register} in
118 @code{gnutls_extensions.c} typically within @funcintref{_gnutls_ext_init}.
120 @subheading Adding a new TLS extension
122 Adding support for a new TLS extension is done from time to time, and
123 the process to do so is not difficult. Here are the steps you need to
124 follow if you wish to do this yourself. For sake of discussion, let's
125 consider adding support for the hypothetical TLS extension
128 @subsubheading Add @code{configure} option like @code{--enable-foobar} or @code{--disable-foobar}.
130 This step is useful when the extension code is large and it might be desirable
131 to disable the extension under some circumstances. Otherwise it can be safely
134 Whether to chose enable or disable depends on whether you intend to make the extension be
135 enabled by default. Look at existing checks (i.e., SRP, authz) for
136 how to model the code. For example:
139 AC_MSG_CHECKING([whether to disable foobar support])
140 AC_ARG_ENABLE(foobar,
141 AS_HELP_STRING([--disable-foobar],
142 [disable foobar support]),
144 if test x$ac_enable_foobar != xno; then
146 AC_DEFINE(ENABLE_FOOBAR, 1, [enable foobar])
151 AM_CONDITIONAL(ENABLE_FOOBAR, test "$ac_enable_foobar" != "no")
154 These lines should go in @code{lib/m4/hooks.m4}.
156 @subsubheading Add IANA extension value to @code{extensions_t} in @code{gnutls_int.h}.
158 A good name for the value would be GNUTLS_EXTENSION_FOOBAR. Check
159 with @url{http://www.iana.org/assignments/tls-extensiontype-values}
160 for allocated values. For experiments, you could pick a number but
161 remember that some consider it a bad idea to deploy such modified
162 version since it will lead to interoperability problems in the future
163 when the IANA allocates that number to someone else, or when the
164 foobar protocol is allocated another number.
166 @subsubheading Add an entry to @code{_gnutls_extensions} in @code{gnutls_extensions.c}.
168 A typical entry would be:
174 ret = _gnutls_ext_register (&foobar_ext);
175 if (ret != GNUTLS_E_SUCCESS)
180 Most likely you'll need to add an @code{#include "ext/@-foobar.h"}, that
181 will contain something like
184 extension_entry_st foobar_ext = @{
186 .type = GNUTLS_EXTENSION_FOOBAR,
187 .parse_type = GNUTLS_EXT_TLS,
188 .recv_func = _foobar_recv_params,
189 .send_func = _foobar_send_params,
190 .pack_func = _foobar_pack,
191 .unpack_func = _foobar_unpack,
196 The GNUTLS_EXTENSION_FOOBAR is the integer value you added to
197 @code{gnutls_int.h} earlier. In this structure you specify the
198 functions to read the extension from the hello message, the function
199 to send the reply to, and two more functions to pack and unpack from
200 stored session data (e.g. when resumming a session). The @code{deinit} function
201 will be called to deinitialize the extension's private parameters, if any.
203 Note that the conditional @code{ENABLE_FOOBAR} definition should only be
204 used if step 1 with the @code{configure} options has taken place.
206 @subsubheading Add new files that implement the extension.
208 The functions you are responsible to add are those mentioned in the
209 previous step. They should be added in a file such as @code{ext/@-foobar.c}
210 and headers should be placed in @code{ext/@-foobar.h}.
211 As a starter, you could add this:
215 _foobar_recv_params (gnutls_session_t session, const opaque * data,
222 _foobar_send_params (gnutls_session_t session, gnutls_buffer_st* data)
228 _foobar_pack (extension_priv_data_t epriv, gnutls_buffer_st * ps)
230 /* Append the extension's internal state to buffer */
235 _foobar_unpack (gnutls_buffer_st * ps, extension_priv_data_t * epriv)
237 /* Read the internal state from buffer */
242 The @funcintref{_foobar_recv_params} function is responsible for
243 parsing incoming extension data (both in the client and server).
245 The @funcintref{_foobar_send_params} function is responsible for
246 sending extension data (both in the client and server).
248 If you receive length fields that don't match, return
249 @code{GNUTLS_E_@-UNEXPECTED_@-PACKET_@-LENGTH}. If you receive invalid
250 data, return @code{GNUTLS_E_@-RECEIVED_@-ILLEGAL_@-PARAMETER}. You can use
251 other error codes from the list in @ref{Error codes}. Return 0 on success.
253 An extension typically stores private information in the @code{session}
254 data for later usage. That can be done using the functions
255 @funcintref{_gnutls_ext_set_session_data} and
256 @funcintref{_gnutls_ext_get_session_data}. You can check simple examples
257 at @code{ext/@-max_@-record.c} and @code{ext/@-server_@-name.c} extensions.
258 That private information can be saved and restored across session
259 resumption if the following functions are set:
261 The @funcintref{_foobar_pack} function is responsible for packing
262 internal extension data to save them in the session resumption storage.
264 The @funcintref{_foobar_unpack} function is responsible for
265 restoring session data from the session resumption storage.
267 Recall that both the client and server, send and receive
268 parameters, and your code most likely will need to do different things
269 depending on which mode it is in. It may be useful to make this
270 distinction explicit in the code. Thus, for example, a better
271 template than above would be:
275 _gnutls_foobar_recv_params (gnutls_session_t session,
279 if (session->security_parameters.entity == GNUTLS_CLIENT)
280 return foobar_recv_client (session, data, data_size);
282 return foobar_recv_server (session, data, data_size);
286 _gnutls_foobar_send_params (gnutls_session_t session,
287 gnutls_buffer_st * data)
289 if (session->security_parameters.entity == GNUTLS_CLIENT)
290 return foobar_send_client (session, data);
292 return foobar_send_server (session, data);
296 The functions used would be declared as @code{static} functions, of
297 the appropriate prototype, in the same file.
298 When adding the files, you'll need to add them to @code{ext/@-Makefile.am}
299 as well, for example:
303 libgnutls_ext_la_SOURCES += ext/foobar.c ext/foobar.h
307 @subsubheading Add API functions to enable/disable the extension.
309 It might be desirable to allow users of the extension to
310 request use of the extension, or set extension specific data.
311 This can be implemented by adding extension specific function calls
312 that can be added to @code{includes/@-gnutls/@-gnutls.h},
313 as long as the LGPLv3+ applies.
314 The implementation of the function should lie in the @code{ext/@-foobar.c} file.
316 To make the API available in the shared library you need to add the
317 symbol in @code{lib/@-libgnutls.map}, so that the symbol
318 is exported properly.
320 When writing GTK-DOC style documentation for your new APIs, don't
321 forget to add @code{Since:} tags to indicate the GnuTLS version the
322 API was introduced in.
324 @node Cryptographic Backend
325 @section Cryptographic Backend
326 Today most new processors, either for embedded or desktop systems
327 include either instructions intended to speed up cryptographic operations,
328 or a co-processor with cryptographic capabilities. Taking advantage of
329 those is a challenging task for every cryptographic application or
330 library. Unfortunately the cryptographic library that GnuTLS is based
331 on takes no advantage of these capabilities. For this reason GnuTLS handles
332 this internally by following a layered approach to accessing
333 cryptographic operations as in @ref{fig:crypto-layers}.
335 @float Figure,fig:crypto-layers
336 @image{gnutls-crypto-layers,12cm}
337 @caption{GnuTLS cryptographic back-end design.}
340 The TLS layer uses a cryptographic provider layer, that will in turn either
341 use the default crypto provider -- a software crypto library, or use an external
342 crypto provider, if available in the local system. The reason of handling
343 the external cryptographic provider in GnuTLS and not delegating it to
344 the cryptographic libraries, is that none of the supported cryptographic
345 libraries support @code{/dev/crypto} or CPU-optimized cryptography in
348 @subheading Cryptographic library layer
349 The Cryptographic library layer, currently supports only
350 libnettle. Older versions of GnuTLS used to support libgcrypt,
351 but it was switched with nettle mainly for performance reasons@footnote{See
352 @url{http://lists.gnu.org/archive/html/gnutls-devel/2011-02/msg00079.html}.}
353 and secondary because it is a simpler library to use.
354 In the future other cryptographic libraries might be supported as well.
356 @subheading External cryptography provider
357 Systems that include a cryptographic co-processor, typically come with
358 kernel drivers to utilize the operations from software. For this reason
359 GnuTLS provides a layer where each individual algorithm used can be replaced
360 by another implementation, i.e., the one provided by the driver. The
361 FreeBSD, OpenBSD and Linux kernels@footnote{Check @url{http://home.gna.org/cryptodev-linux/}
362 for the Linux kernel implementation of @code{/dev/crypto}.} include already
363 a number of hardware assisted implementations, and also provide an interface
364 to access them, called @code{/dev/crypto}.
365 GnuTLS will take advantage of this interface if compiled with special
366 options. That is because in most systems where hardware-assisted
367 cryptographic operations are not available, using this interface might
368 actually harm performance.
370 In systems that include cryptographic instructions with the CPU's
371 instructions set, using the kernel interface will introduce an
372 unneeded layer. For this reason GnuTLS includes such optimizations
373 found in popular processors such as the AES-NI or VIA PADLOCK instruction sets.
374 This is achieved using a mechanism that detects CPU capabilities and
375 overrides parts of crypto back-end at runtime.
376 The next section discusses the registration of a detected algorithm
377 optimization. For more information please consult the @acronym{GnuTLS}
378 source code in @code{lib/accelerated/}.
380 @subsubheading Overriding specific algorithms
381 When an optimized implementation of a single algorithm is available,
382 say a hardware assisted version of @acronym{AES-CBC} then the
383 following (internal) functions, from @code{crypto-backend.h}, can
384 be used to register those algorithms.
388 @item @code{gnutls_crypto_single_cipher_register}:
389 To register a cipher algorithm.
391 @item @code{gnutls_crypto_single_digest_register}:
392 To register a hash (digest) or MAC algorithm.
396 Those registration functions will only replace the specified algorithm
397 and leave the rest of subsystem intact.
399 @subsubheading Overriding the cryptographic library
400 In some systems, that might contain a broad acceleration engine, it
401 might be desirable to override big parts of the cryptographic back-end,
402 or even all of them. The following functions are provided for this reason.
406 @item @code{gnutls_crypto_cipher_register}:
407 To override the cryptographic algorithms back-end.
409 @item @code{gnutls_crypto_digest_register}:
410 To override the digest algorithms back-end.
412 @item @code{gnutls_crypto_rnd_register}:
413 To override the random number generator back-end.
415 @item @code{gnutls_crypto_bigint_register}:
416 To override the big number number operations back-end.
418 @item @code{gnutls_crypto_pk_register}:
419 To override the public key encryption back-end. This is tied to the
420 big number operations so either none or both of them should be overriden.