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 * Certificate Handling::
16 * Cryptographic Backend::
19 @node The TLS Protocol
20 @section The TLS Protocol
21 The main needs for the TLS protocol to be used are
22 shown in the image below.
24 @image{gnutls-client-server-use-case,9cm}
26 This is being accomplished by the following object diagram.
27 Note that since @acronym{GnuTLS} is being developed in C
28 object are just structures with attributes. The operations listed
29 are functions that require the first parameter to be that object.
30 @image{gnutls-objects,15cm}
32 @node TLS Handshake Protocol
33 @section TLS Handshake Protocol
34 The @acronym{GnuTLS} handshake protocol is implemented as a state
35 machine that waits for input or returns immediately when the non-blocking
36 transport layer functions are used. The main idea is shown in the following
39 @image{gnutls-handshake-state,9cm}
41 Also the way the input is processed varies per ciphersuite. Several
42 implementations of the internal handlers are available and
43 @ref{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.
48 @image{gnutls-handshake-sequence,12cm}
50 @node TLS Authentication Methods
51 @section TLS Authentication Methods
52 In @acronym{GnuTLS} authentication methods can be implemented quite
53 easily. Since the required changes to add a new authentication method
54 affect only the handshake protocol, a simple interface is used. An
55 authentication method needs only to implement the functions as seen in
58 @image{gnutls-mod_auth_st,12cm}
60 The functions that need to be implemented are the ones responsible for
61 interpreting the handshake protocol messages. It is common for such
62 functions to read data from one or more @code{credentials_t}
63 structures@footnote{such as the
64 @code{gnutls_certificate_credentials_t} structures} and write data,
65 such as certificates, usernames etc. to @code{auth_info_t} structures.
67 Simple examples of existing authentication methods can be seen in
68 @code{auth_psk.c} for PSK ciphersuites and @code{auth_srp.c} for SRP
69 ciphersuites. After implementing these functions the structure holding
70 its pointers has to be registered in @code{gnutls_algorithms.c} in the
71 @code{_gnutls_kx_algorithms} structure.
73 @node TLS Extension Handling
74 @section TLS Extension Handling
75 As with authentication methods, the TLS extensions handlers can be
76 implemented using the following interface.
78 @image{gnutls-extensions_st,12cm}
80 Here there are two functions, one for receiving the extension data
81 and one for sending. These functions have to check internally whether
82 they operate in client or server side.
84 A simple example of an extension handler can be seen in
85 @code{ext_srp.c} After implementing these functions, together with the
86 extension number they handle, they have to be registered in
87 @code{gnutls_extensions.c} in the @code{_gnutls_extensions} structure.
89 @subsection Adding a New TLS Extension
91 Adding support for a new TLS extension is done from time to time, and
92 the process to do so is not difficult. Here are the steps you need to
93 follow if you wish to do this yourself. For sake of discussion, let's
94 consider adding support for the hypothetical TLS extension
99 @item Add @code{configure} option like @code{--enable-foobar} or @code{--disable-foobar}.
101 This step is useful when the extension code is large and it might be desirable
102 to disable the extension under some circumstances. Otherwise it can be safely
105 Whether to chose enable or disable depends on whether you intend to make the extension be
106 enabled by default. Look at existing checks (i.e., SRP, authz) for
107 how to model the code. For example:
110 AC_MSG_CHECKING([whether to disable foobar support])
111 AC_ARG_ENABLE(foobar,
112 AS_HELP_STRING([--disable-foobar],
113 [disable foobar support]),
115 if test x$ac_enable_foobar != xno; then
117 AC_DEFINE(ENABLE_FOOBAR, 1, [enable foobar])
122 AM_CONDITIONAL(ENABLE_FOOBAR, test "$ac_enable_foobar" != "no")
125 These lines should go in @code{lib/m4/hooks.m4}.
127 @item Add IANA extension value to @code{extensions_t} in @code{gnutls_int.h}.
129 A good name for the value would be GNUTLS_EXTENSION_FOOBAR. Check
130 with @url{http://www.iana.org/assignments/tls-extensiontype-values}
131 for allocated values. For experiments, you could pick a number but
132 remember that some consider it a bad idea to deploy such modified
133 version since it will lead to interoperability problems in the future
134 when the IANA allocates that number to someone else, or when the
135 foobar protocol is allocated another number.
137 @item Add an entry to @code{_gnutls_extensions} in @code{gnutls_extensions.c}.
139 A typical entry would be:
149 ret = _gnutls_ext_register (&foobar_ext);
150 if (ret != GNUTLS_E_SUCCESS)
155 Most likely you'll need to add an @code{#include "ext_foobar.h"}, that
156 will contain something like
159 extension_entry_st foobar_ext = @{
161 .type = GNUTLS_EXTENSION_FOOBAR,
162 .parse_type = GNUTLS_EXT_TLS,
163 .recv_func = _foobar_recv_params,
164 .send_func = _foobar_send_params,
165 .pack_func = _foobar_pack,
166 .unpack_func = _foobar_unpack,
171 The GNUTLS_EXTENSION_FOOBAR is the integer value you added to
172 @code{gnutls_int.h} earlier. In this structure you specify the
173 functions to read the extension from the hello message, the function
174 to send the reply to, and two more functions to pack and unpack from
175 stored session data (e.g. when resumming a session). The @code{deinit} function
176 will be called to deinitialize the extension's private parameters, if any.
178 Note that the conditional @code{ENABLE_FOOBAR} definition should only be
179 used if step 1 with the @code{configure} options has taken place.
181 @item Add new files @code{ext_foobar.c} and @code{ext_foobar.h} that implement the extension.
183 The functions you are responsible to add are those mentioned in the
184 previous step. As a starter, you could add this:
188 _foobar_recv_params (gnutls_session_t session,
196 _foobar_send_params (gnutls_session_t session,
204 _foobar_pack (extension_priv_data_t epriv, gnutls_buffer_st * ps)
206 /* Append the extension's internal state to buffer */
211 _foobar_unpack (gnutls_buffer_st * ps, extension_priv_data_t * epriv)
213 /* Read the internal state from buffer */
218 The @code{_foobar_recv_params} function is responsible for
219 parsing incoming extension data (both in the client and server).
221 The @code{_foobar_send_params} function is responsible for
222 sending extension data (both in the client and server).
224 The @code{_foobar_pack} function is responsible for packing
225 internal extension data to save them in the session storage.
227 The @code{_foobar_unpack} function is responsible for
228 restoring session data from the session storage.
230 If you receive length fields that doesn't match, return
231 @code{GNUTLS_E_UNEXPECTED_PACKET_LENGTH}. If you receive invalid
232 data, return @code{GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER}. You can use
233 other error codes too. Return 0 on success.
235 The function could store some information in the @code{session}
236 variable for later usage. That can be done using the functions
237 @code{_gnutls_ext_set_session_data} and
238 @code{_gnutls_ext_get_session_data}. You can check simple examples
239 at @code{ext_max_record.c} and @code{ext_server_name.c} extensions.
241 Recall that both the client and server both send and receives
242 parameters, and your code most likely will need to do different things
243 depending on which mode it is in. It may be useful to make this
244 distinction explicit in the code. Thus, for example, a better
245 template than above would be:
249 _gnutls_foobar_recv_params (gnutls_session_t session,
253 if (session->security_parameters.entity == GNUTLS_CLIENT)
254 return foobar_recv_client (session, data, data_size);
256 return foobar_recv_server (session, data, data_size);
260 _gnutls_foobar_send_params (gnutls_session_t session,
264 if (session->security_parameters.entity == GNUTLS_CLIENT)
265 return foobar_send_client (session, data, data_size);
267 return foobar_send_server (session, data, data_size);
271 The functions used would be declared as @code{static} functions, of
272 the appropriate prototype, in the same file.
274 When adding the files, you'll need to add them to @code{Makefile.am}
275 as well, for example:
279 COBJECTS += ext_foobar.c
280 HFILES += ext_foobar.h
284 @item Add API functions to enable/disable the extension.
286 Normally the client will have one API to request use of the extension,
287 and setting some extension specific data. The server will have one
288 API to let the library know that it is willing to accept the
289 extension, often this is implemented through a callback but it doesn't
292 The APIs need to be added to @code{includes/gnutls/gnutls.h} or
293 @code{includes/gnutls/extra.h} as appropriate. It is recommended that
294 if you don't have a requirement to use the LGPLv2.1+ license for your
295 extension, that you place your work under the GPLv3+ license and thus
296 in the libgnutls-extra library.
298 You can implement the API function in the @code{ext_foobar.c} file, or
299 if that file ends up becoming rather larger, add a
300 @code{gnutls_foobar.c} file.
302 To make the API available in the shared library you need to add the
303 symbol in @code{lib/libgnutls.map} or
304 @code{libextra/libgnutls-extra.map} as appropriate, so that the symbol
305 is exported properly.
307 When writing GTK-DOC style documentation for your new APIs, don't
308 forget to add @code{Since:} tags to indicate the GnuTLS version the
309 API was introduced in.
313 @node Certificate Handling
314 @section Certificate Handling
315 What is provided by the certificate handling functions
316 is summarized in the following diagram.
318 @image{gnutls-certificate-user-use-case,12cm}
320 @node Cryptographic Backend
321 @section Cryptographic Backend
322 Today most new processors, either for embedded or desktop systems
323 include either instructions intended to speed up cryptographic operations,
324 or a co-processor with cryptographic capabilities. Taking advantage of
325 those is a challenging task for every cryptographic application or
326 library. Unfortunately the cryptographic libraries that GnuTLS is based
327 on take no advantage of these properties. For this reason GnuTLS handles
328 this internally by following a layered approach to accessing
329 cryptographic operations as in the following figure.
331 @image{gnutls-crypto-layers,12cm}
333 The TLS layer uses a cryptographic provider layer, that will in turn either
334 use the default crypto provider - a crypto library, or use an external
335 crypto provider, if available.
337 @subsection Cryptographic Library layer
338 The Cryptographic Library layer, can currently be used either with
339 libgcrypt or libnettle, each of one has its advantages and some
340 disadvantages. Libgcrypt is a self-contained library, pretty broad
341 in scope that supports many algorithms. In some processors like VIA,
342 it will also use the available crypto instruction set hence providing
343 performance benefit comparing to plain software implementation.
344 Libnettle provides only software implementation
345 of the basic algorithms required in TLS, and is on average 30% faster
346 that libgcrypt on almost all algorithms. For
347 this reason libnettle is library used by default in GnuTLS.
349 @subsection External cryptography provider
350 Systems that include a cryptographic co-processor, typically come with
351 kernel drivers to utilize the operations from software. For this reason
352 GnuTLS provides a layer where each individual algorithm used can be replaced
353 by another implementation, i.e. the one provided by the driver. The
354 FreeBSD, OpenBSD and Linux kernels@footnote{Check @url{http://home.gna.org/cryptodev-linux/}
355 for the Linux kernel implementation of @code{/dev/crypto}.} include already
356 a number of hardware assisted implementations, and also provide an interface
357 to access them, called @code{/dev/crypto}.
358 GnuTLS will take advantage of this interface if compiled with special
359 options. That is because in most systems where hardware-assisted
360 cryptographic operations are not available, using this interface might
361 actually reduce performance.
363 It is possible to override parts of crypto backend both at runtime and compile
364 time. Here we discuss the runtime possibility. The API
365 available for this functionality is in @code{gnutls/crypto.h} header
368 @subsubsection Override specific algorithms
369 When an optimized implementation of a single algorithm is available,
370 say a hardware assisted version of @acronym{AES-CBC} then the
371 following functions can be used to register those algorithms.
375 @item @ref{gnutls_crypto_single_cipher_register2}
376 To register a cipher algorithm.
378 @ref{gnutls_crypto_single_digest_register2}
379 To register a hash (digest) or MAC algorithm.
383 Those registration functions will only replace the specified algorithm
384 and leave the rest of subsystem intact.
386 @subsubsection Override parts of the backend
387 In some systems, such as embedded ones, it might be desirable to
388 override big parts of the cryptographic backend, or even all of
389 them. For this reason the following functions are provided.
393 @item @ref{gnutls_crypto_cipher_register2}
394 To override the cryptographic algorithms backend.
396 @item @ref{gnutls_crypto_digest_register2}
397 To override the digest algorithms backend.
399 @item @ref{gnutls_crypto_rnd_register2}
400 To override the random number generator backend.
402 @item @ref{gnutls_crypto_bigint_register2}
403 To override the big number number operations backend.
405 @item @ref{gnutls_crypto_pk_register2}
406 To override the public key encryption backend. This is tight to the
407 big number operations so either both of them should be updated or care
408 must be taken to use the same format.
412 If all of them are used then GnuTLS will no longer use libgcrypt.