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 @subheading Adding a new Supplemental Data Handshake Message
326 TLS handshake extensions allow to send so called supplemental data
327 handshake messages @xcite{RFC4680}. This short section explains how to
328 implement a supplemental data handshake message for a given TLS extension.
330 First of all, modify your extension @code{foobar} in the way, the that
332 @code{session->security_parameters.@-do_send_supplemental}
334 @code{session->security_parameters.@-do_recv_supplemental}
339 _gnutls_foobar_recv_params (gnutls_session_t session, const opaque * data,
343 session->security_parameters.do_recv_supplemental=1;
348 _gnutls_foobar_send_params (gnutls_session_t session, gnutls_buffer_st *extdata)
351 session->security_parameters.do_send_supplemental=1;
356 Furthermore add the functions @funcintref{_foobar_supp_recv_params}
357 and @funcintref{_foobar_supp_send_params} to @code{_foobar.h} and
358 @code{_foobar.c}. The following example code shows how to send a
359 ``Hello World'' string in the supplemental data handshake message:
363 _foobar_supp_recv_params(gnutls_session_t session, const opaque *data, size_t _data_size)
365 uint8_t len = _data_size;
368 msg = gnutls_malloc(len);
369 if (msg == NULL) return GNUTLS_E_MEMORY_ERROR;
371 memcpy(msg, data, len);
374 /* do something with msg */
381 _foobar_supp_send_params(gnutls_session_t session, gnutls_buffer_st *buf)
383 unsigned char *msg = "hello world";
384 int len = strlen(msg);
386 _gnutls_buffer_append_data_prefix(buf, 8, msg, len);
392 Afterwards, add the new supplemental data handshake message to
393 @code{lib/gnutls_supplemental.c} by adding a new entry to the
394 @code{_gnutls_supplemental[]} structure:
397 gnutls_supplemental_entry _gnutls_supplemental[] =
400 GNUTLS_SUPPLEMENTAL_FOOBAR_DATA,
401 _foobar_supp_recv_params,
402 _foobar_supp_send_params@},
407 You have to include your @code{foobar.h} header file as well:
413 Lastly, add the new supplemental data type to
414 @code{lib/includes/gnutls/gnutls.h}:
419 GNUTLS_SUPPLEMENTAL_USER_MAPPING_DATA = 0,
420 GNUTLS_SUPPLEMENTAL_FOOBAR_DATA = 1
421 @} gnutls_supplemental_data_format_type_t;
424 @node Cryptographic Backend
425 @section Cryptographic Backend
426 Today most new processors, either for embedded or desktop systems
427 include either instructions intended to speed up cryptographic operations,
428 or a co-processor with cryptographic capabilities. Taking advantage of
429 those is a challenging task for every cryptographic application or
430 library. Unfortunately the cryptographic library that GnuTLS is based
431 on takes no advantage of these capabilities. For this reason GnuTLS handles
432 this internally by following a layered approach to accessing
433 cryptographic operations as in @ref{fig:crypto-layers}.
435 @float Figure,fig:crypto-layers
436 @image{gnutls-crypto-layers,12cm}
437 @caption{GnuTLS cryptographic back-end design.}
440 The TLS layer uses a cryptographic provider layer, that will in turn either
441 use the default crypto provider -- a software crypto library, or use an external
442 crypto provider, if available in the local system. The reason of handling
443 the external cryptographic provider in GnuTLS and not delegating it to
444 the cryptographic libraries, is that none of the supported cryptographic
445 libraries support @code{/dev/crypto} or CPU-optimized cryptography in
448 @subheading Cryptographic library layer
449 The Cryptographic library layer, currently supports only
450 libnettle. Older versions of GnuTLS used to support libgcrypt,
451 but it was switched with nettle mainly for performance reasons@footnote{See
452 @url{http://lists.gnu.org/archive/html/gnutls-devel/2011-02/msg00079.html}.}
453 and secondary because it is a simpler library to use.
454 In the future other cryptographic libraries might be supported as well.
456 @subheading External cryptography provider
457 Systems that include a cryptographic co-processor, typically come with
458 kernel drivers to utilize the operations from software. For this reason
459 GnuTLS provides a layer where each individual algorithm used can be replaced
460 by another implementation, i.e., the one provided by the driver. The
461 FreeBSD, OpenBSD and Linux kernels@footnote{Check @url{http://home.gna.org/cryptodev-linux/}
462 for the Linux kernel implementation of @code{/dev/crypto}.} include already
463 a number of hardware assisted implementations, and also provide an interface
464 to access them, called @code{/dev/crypto}.
465 GnuTLS will take advantage of this interface if compiled with special
466 options. That is because in most systems where hardware-assisted
467 cryptographic operations are not available, using this interface might
468 actually harm performance.
470 In systems that include cryptographic instructions with the CPU's
471 instructions set, using the kernel interface will introduce an
472 unneeded layer. For this reason GnuTLS includes such optimizations
473 found in popular processors such as the AES-NI or VIA PADLOCK instruction sets.
474 This is achieved using a mechanism that detects CPU capabilities and
475 overrides parts of crypto back-end at runtime.
476 The next section discusses the registration of a detected algorithm
477 optimization. For more information please consult the @acronym{GnuTLS}
478 source code in @code{lib/accelerated/}.
480 @subsubheading Overriding specific algorithms
481 When an optimized implementation of a single algorithm is available,
482 say a hardware assisted version of @acronym{AES-CBC} then the
483 following (internal) functions, from @code{crypto-backend.h}, can
484 be used to register those algorithms.
488 @item @code{gnutls_crypto_single_cipher_register}:
489 To register a cipher algorithm.
491 @item @code{gnutls_crypto_single_digest_register}:
492 To register a hash (digest) or MAC algorithm.
496 Those registration functions will only replace the specified algorithm
497 and leave the rest of subsystem intact.
499 @subsubheading Overriding the cryptographic library
500 In some systems, that might contain a broad acceleration engine, it
501 might be desirable to override big parts of the cryptographic back-end,
502 or even all of them. The following functions are provided for this reason.
506 @item @code{gnutls_crypto_cipher_register}:
507 To override the cryptographic algorithms back-end.
509 @item @code{gnutls_crypto_digest_register}:
510 To override the digest algorithms back-end.
512 @item @code{gnutls_crypto_rnd_register}:
513 To override the random number generator back-end.
515 @item @code{gnutls_crypto_bigint_register}:
516 To override the big number number operations back-end.
518 @item @code{gnutls_crypto_pk_register}:
519 To override the public key encryption back-end. This is tied to the
520 big number operations so either none or both of them should be overriden.