Some updates on supplemental data handling.
[gnutls:gnutls.git] / doc / cha-internals.texi
1 @node Internal architecture of GnuTLS
2 @chapter Internal Architecture of GnuTLS
3 @cindex internal architecture
4
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.
9
10 @menu
11 * The TLS Protocol::
12 * TLS Handshake Protocol::
13 * TLS Authentication Methods::
14 * TLS Extension Handling::
15 * Cryptographic Backend::
16 @end menu
17
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.
24
25 @float Figure,fig:client-server
26 @image{gnutls-client-server-use-case,9cm}
27 @caption{TLS protocol use case.}
28 @end float
29
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}.
35
36 @float Figure,fig:gnutls-handshake
37 @image{gnutls-handshake-state,9cm}
38 @caption{GnuTLS handshake state machine.}
39 @end float
40
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}.
47
48 @float Figure,fig:gnutls-handshake-sequence
49 @image{gnutls-handshake-sequence,12cm}
50 @caption{GnuTLS handshake process sequence.}
51 @end float
52
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.
59
60 @verbatim
61 typedef struct 
62 {
63   const char *name;
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,
70                                                      gnutls_buffer_st *);
71
72   int (*gnutls_process_server_certificate) (gnutls_session_t, opaque *,
73                                             size_t);
74   int (*gnutls_process_client_certificate) (gnutls_session_t, opaque *,
75                                             size_t);
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,
80                                                     opaque *, size_t);
81 } mod_auth_st;
82 @end verbatim
83
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.
90
91
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.
97
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.
102
103 @verbatim
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);
108 @end verbatim
109
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. 
113
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}.
119
120 @subheading Adding a new TLS extension
121
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
126 @code{foobar}.
127
128 @subsubheading Add @code{configure} option like @code{--enable-foobar} or @code{--disable-foobar}.
129
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
132 skipped.
133
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:
137
138 @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]),
143         ac_enable_foobar=no)
144 if test x$ac_enable_foobar != xno; then
145  AC_MSG_RESULT(no)
146  AC_DEFINE(ENABLE_FOOBAR, 1, [enable foobar])
147 else
148  ac_full=0
149  AC_MSG_RESULT(yes)
150 fi
151 AM_CONDITIONAL(ENABLE_FOOBAR, test "$ac_enable_foobar" != "no")
152 @end example
153
154 These lines should go in @code{lib/m4/hooks.m4}.
155
156 @subsubheading Add IANA extension value to @code{extensions_t} in @code{gnutls_int.h}.
157
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.
165
166 @subsubheading Add an entry to @code{_gnutls_extensions} in @code{gnutls_extensions.c}.
167
168 A typical entry would be:
169
170 @example
171   int ret;
172
173 #if ENABLE_FOOBAR
174   ret = _gnutls_ext_register (&foobar_ext);
175   if (ret != GNUTLS_E_SUCCESS)
176     return ret;
177 #endif
178 @end example
179
180 Most likely you'll need to add an @code{#include "ext/@-foobar.h"}, that
181 will contain something like
182 like:
183 @example
184   extension_entry_st foobar_ext = @{
185     .name = "FOOBAR",
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,
192     .deinit_func = NULL
193   @}
194 @end example
195
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.
202
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.
205
206 @subsubheading Add new files that implement the extension.
207
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:
212
213 @example
214 int
215 _foobar_recv_params (gnutls_session_t session, const opaque * data,
216                      size_t data_size)
217 @{
218   return 0;
219 @}
220
221 int
222 _foobar_send_params (gnutls_session_t session, gnutls_buffer_st* data)
223 @{
224   return 0;
225 @}
226
227 int
228 _foobar_pack (extension_priv_data_t epriv, gnutls_buffer_st * ps)
229 @{
230    /* Append the extension's internal state to buffer */
231    return 0;
232 @}
233
234 int
235 _foobar_unpack (gnutls_buffer_st * ps, extension_priv_data_t * epriv)
236 @{
237    /* Read the internal state from buffer */
238    return 0;
239 @}
240 @end example
241
242 The @funcintref{_foobar_recv_params} function is responsible for
243 parsing incoming extension data (both in the client and server).
244
245 The @funcintref{_foobar_send_params} function is responsible for
246 sending extension data (both in the client and server).
247
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.
252
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:
260
261 The @funcintref{_foobar_pack} function is responsible for packing
262 internal extension data to save them in the session resumption storage.
263
264 The @funcintref{_foobar_unpack} function is responsible for
265 restoring session data from the session resumption storage.
266
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:
272
273 @example
274 int
275 _gnutls_foobar_recv_params (gnutls_session_t session,
276                             const opaque * data,
277                             size_t data_size)
278 @{
279   if (session->security_parameters.entity == GNUTLS_CLIENT)
280     return foobar_recv_client (session, data, data_size);
281   else
282     return foobar_recv_server (session, data, data_size);
283 @}
284
285 int
286 _gnutls_foobar_send_params (gnutls_session_t session,
287                             gnutls_buffer_st * data)
288 @{
289   if (session->security_parameters.entity == GNUTLS_CLIENT)
290     return foobar_send_client (session, data);
291   else
292     return foobar_send_server (session, data);
293 @}
294 @end example
295
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:
300
301 @example
302 if ENABLE_FOOBAR
303 libgnutls_ext_la_SOURCES += ext/foobar.c ext/foobar.h
304 endif
305 @end example
306
307 @subsubheading Add API functions to enable/disable the extension.
308
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.
315
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.
319
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.
323
324 @subheading Adding a new Supplemental Data Handshake Message
325
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.
329
330 First of all, modify your extension @code{foobar} in the way, the that
331 flags
332 @code{session->security_parameters.@-do_send_supplemental}
333 and
334 @code{session->security_parameters.@-do_recv_supplemental}
335 are set:
336
337 @example
338 int
339 _gnutls_foobar_recv_params (gnutls_session_t session, const opaque * data,
340                                  size_t _data_size)
341 @{
342    ...
343    session->security_parameters.do_recv_supplemental=1;
344    ...
345 @}
346
347 int
348 _gnutls_foobar_send_params (gnutls_session_t session, gnutls_buffer_st *extdata)
349 @{
350    ...
351    session->security_parameters.do_send_supplemental=1;
352    ...
353 @}
354 @end example
355
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:
360
361 @example
362 int 
363 _foobar_supp_recv_params(gnutls_session_t session, const opaque *data, size_t _data_size)
364 @{
365    uint8_t len = _data_size;
366    unsigned char *msg;
367
368    msg = gnutls_malloc(len);
369    if (msg == NULL) return GNUTLS_E_MEMORY_ERROR;
370
371    memcpy(msg, data, len);
372    msg[len]='\0';
373
374    /* do something with msg */
375    gnutls_free(msg);
376
377    return len;
378 @}
379
380 int 
381 _foobar_supp_send_params(gnutls_session_t session, gnutls_buffer_st *buf)
382 @{
383    unsigned char *msg = "hello world";
384    int len = strlen(msg);
385
386    _gnutls_buffer_append_data_prefix(buf, 8, msg, len);
387
388    return len;
389 @}
390 @end example
391
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:
395
396 @example
397 gnutls_supplemental_entry _gnutls_supplemental[] = 
398 @{
399   @{"foobar",
400    GNUTLS_SUPPLEMENTAL_FOOBAR_DATA,
401    _foobar_supp_recv_params,
402    _foobar_supp_send_params@},
403   @{0, 0, 0, 0@}
404 @};
405 @end example
406
407 You have to include your @code{foobar.h} header file as well:
408
409 @example
410 #include "foobar.h"
411 @end example
412
413 Lastly, add the new supplemental data type to
414 @code{lib/includes/gnutls/gnutls.h}:
415
416 @example
417 typedef enum
418 @{
419     GNUTLS_SUPPLEMENTAL_USER_MAPPING_DATA = 0,
420     GNUTLS_SUPPLEMENTAL_FOOBAR_DATA = 1
421 @} gnutls_supplemental_data_format_type_t;
422 @end example
423
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}.
434
435 @float Figure,fig:crypto-layers
436 @image{gnutls-crypto-layers,12cm}
437 @caption{GnuTLS cryptographic back-end design.}
438 @end float
439
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
446 an efficient way.
447
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.
455
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.
469
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/}.
479
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.
485
486 @itemize
487
488 @item @code{gnutls_crypto_single_cipher_register}:
489 To register a cipher algorithm.
490
491 @item @code{gnutls_crypto_single_digest_register}:
492 To register a hash (digest) or MAC algorithm.
493
494 @end itemize
495
496 Those registration functions will only replace the specified algorithm
497 and leave the rest of subsystem intact.
498
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.
503
504 @itemize
505
506 @item @code{gnutls_crypto_cipher_register}:
507 To override the cryptographic algorithms back-end.
508
509 @item @code{gnutls_crypto_digest_register}:
510 To override the digest algorithms back-end.
511
512 @item @code{gnutls_crypto_rnd_register}:
513 To override the random number generator back-end.
514
515 @item @code{gnutls_crypto_bigint_register}:
516 To override the big number number operations back-end.
517
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.
521
522 @end itemize
523