documented updates
[gnutls.git] / lib / gnutls_extensions.c
blobaab0a67e89dd8f20f331f5a402629be476d91399
1 /*
2 * Copyright (C) 2001-2012 Free Software Foundation, Inc.
4 * Author: Nikos Mavrogiannopoulos, Simon Josefsson
6 * This file is part of GnuTLS.
8 * The GnuTLS is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 3 of
11 * the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>
23 /* Functions that relate to the TLS hello extension parsing.
24 * Hello extensions are packets appended in the TLS hello packet, and
25 * allow for extra functionality.
28 #include "gnutls_int.h"
29 #include "gnutls_extensions.h"
30 #include "gnutls_errors.h"
31 #include "ext/max_record.h"
32 #include <ext/cert_type.h>
33 #include <ext/server_name.h>
34 #include <ext/srp.h>
35 #include <ext/heartbeat.h>
36 #include <ext/session_ticket.h>
37 #include <ext/safe_renegotiation.h>
38 #include <ext/signature.h>
39 #include <ext/safe_renegotiation.h>
40 #include <ext/ecc.h>
41 #include <ext/status_request.h>
42 #include <gnutls_num.h>
45 static void _gnutls_ext_unset_resumed_session_data (gnutls_session_t session,
46 uint16_t type);
49 static size_t extfunc_size = 0;
50 static extension_entry_st *extfunc = NULL;
52 static gnutls_ext_parse_type_t
53 _gnutls_ext_parse_type (uint16_t type)
55 size_t i;
57 for (i = 0; i < extfunc_size; i++)
59 if (extfunc[i].type == type)
60 return extfunc[i].parse_type;
63 return GNUTLS_EXT_NONE;
66 static gnutls_ext_recv_func
67 _gnutls_ext_func_recv (uint16_t type, gnutls_ext_parse_type_t parse_type)
69 size_t i;
71 for (i = 0; i < extfunc_size; i++)
72 if (extfunc[i].type == type)
73 if (parse_type == GNUTLS_EXT_ANY || extfunc[i].parse_type == parse_type)
74 return extfunc[i].recv_func;
76 return NULL;
79 static gnutls_ext_deinit_data_func
80 _gnutls_ext_func_deinit (uint16_t type)
82 size_t i;
84 for (i = 0; i < extfunc_size; i++)
85 if (extfunc[i].type == type)
86 return extfunc[i].deinit_func;
88 return NULL;
91 static gnutls_ext_unpack_func
92 _gnutls_ext_func_unpack (uint16_t type)
94 size_t i;
96 for (i = 0; i < extfunc_size; i++)
97 if (extfunc[i].type == type)
98 return extfunc[i].unpack_func;
100 return NULL;
104 static const char *
105 _gnutls_extension_get_name (uint16_t type)
107 size_t i;
109 for (i = 0; i < extfunc_size; i++)
110 if (extfunc[i].type == type)
111 return extfunc[i].name;
113 return NULL;
116 /* Checks if the extension we just received is one of the
117 * requested ones. Otherwise it's a fatal error.
119 static int
120 _gnutls_extension_list_check (gnutls_session_t session, uint16_t type)
122 if (session->security_parameters.entity == GNUTLS_CLIENT)
124 int i;
126 for (i = 0; i < session->internals.extensions_sent_size; i++)
128 if (type == session->internals.extensions_sent[i])
129 return 0; /* ok found */
132 return GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION;
135 return 0;
139 _gnutls_parse_extensions (gnutls_session_t session,
140 gnutls_ext_parse_type_t parse_type,
141 const uint8_t * data, int data_size)
143 int next, ret;
144 int pos = 0;
145 uint16_t type;
146 const uint8_t *sdata;
147 gnutls_ext_recv_func ext_recv;
148 uint16_t size;
150 #ifdef DEBUG
151 int i;
153 if (session->security_parameters.entity == GNUTLS_CLIENT)
154 for (i = 0; i < session->internals.extensions_sent_size; i++)
156 _gnutls_handshake_log ("EXT[%d]: expecting extension '%s'\n",
157 session,
158 _gnutls_extension_get_name
159 (session->internals.extensions_sent[i]));
161 #endif
163 DECR_LENGTH_RET (data_size, 2, 0);
164 next = _gnutls_read_uint16 (data);
165 pos += 2;
167 DECR_LENGTH_RET (data_size, next, 0);
171 DECR_LENGTH_RET (next, 2, 0);
172 type = _gnutls_read_uint16 (&data[pos]);
173 pos += 2;
175 if ((ret = _gnutls_extension_list_check (session, type)) < 0)
177 gnutls_assert ();
178 return ret;
181 DECR_LENGTH_RET (next, 2, 0);
182 size = _gnutls_read_uint16 (&data[pos]);
183 pos += 2;
185 DECR_LENGTH_RET (next, size, 0);
186 sdata = &data[pos];
187 pos += size;
189 ext_recv = _gnutls_ext_func_recv (type, parse_type);
190 if (ext_recv == NULL)
192 _gnutls_handshake_log ("EXT[%p]: Found extension '%s/%d'\n", session,
193 _gnutls_extension_get_name (type), type);
195 continue;
198 _gnutls_handshake_log ("EXT[%p]: Parsing extension '%s/%d' (%d bytes)\n",
199 session, _gnutls_extension_get_name (type), type,
200 size);
202 if ((ret = ext_recv (session, sdata, size)) < 0)
204 gnutls_assert ();
205 return ret;
209 while (next > 2);
211 return 0;
215 /* Adds the extension we want to send in the extensions list.
216 * This list is used to check whether the (later) received
217 * extensions are the ones we requested.
219 void
220 _gnutls_extension_list_add (gnutls_session_t session, uint16_t type)
223 if (session->security_parameters.entity == GNUTLS_CLIENT)
225 if (session->internals.extensions_sent_size < MAX_EXT_TYPES)
227 session->internals.extensions_sent[session->internals.
228 extensions_sent_size] = type;
229 session->internals.extensions_sent_size++;
231 else
233 _gnutls_handshake_log ("extensions: Increase MAX_EXT_TYPES\n");
239 _gnutls_gen_extensions (gnutls_session_t session, gnutls_buffer_st * extdata,
240 gnutls_ext_parse_type_t parse_type)
242 int size;
243 int pos, size_pos, ret;
244 size_t i, init_size = extdata->length;
246 pos = extdata->length; /* we will store length later on */
247 _gnutls_buffer_append_prefix( extdata, 16, 0);
249 for (i = 0; i < extfunc_size; i++)
251 extension_entry_st *p = &extfunc[i];
253 if (p->send_func == NULL)
254 continue;
256 if (parse_type != GNUTLS_EXT_ANY && p->parse_type != parse_type)
257 continue;
259 ret = _gnutls_buffer_append_prefix( extdata, 16, p->type);
260 if (ret < 0)
261 return gnutls_assert_val(ret);
263 size_pos = extdata->length;
264 ret = _gnutls_buffer_append_prefix (extdata, 16, 0);
265 if (ret < 0)
266 return gnutls_assert_val(ret);
268 size = p->send_func (session, extdata);
269 /* returning GNUTLS_E_INT_RET_0 means to send an empty
270 * extension of this type.
272 if (size > 0 || size == GNUTLS_E_INT_RET_0)
274 if (size == GNUTLS_E_INT_RET_0)
275 size = 0;
277 /* write the real size */
278 _gnutls_write_uint16(size, &extdata->data[size_pos]);
280 /* add this extension to the extension list
282 _gnutls_extension_list_add (session, p->type);
284 _gnutls_handshake_log ("EXT[%p]: Sending extension %s (%d bytes)\n",
285 session, p->name, size);
287 else if (size < 0)
289 gnutls_assert ();
290 return size;
292 else if (size == 0)
293 extdata->length -= 4; /* reset type and size */
296 /* remove any initial data, and the size of the header */
297 size = extdata->length - init_size - 2;
299 if ( size > 0)
300 _gnutls_write_uint16(size, &extdata->data[pos]);
301 else if (size == 0) extdata->length -= 2; /* the length bytes */
303 return size;
307 _gnutls_ext_init (void)
309 int ret;
311 ret = _gnutls_ext_register (&ext_mod_max_record_size);
312 if (ret != GNUTLS_E_SUCCESS)
313 return ret;
315 ret = _gnutls_ext_register (&ext_mod_status_request);
316 if (ret != GNUTLS_E_SUCCESS)
317 return ret;
319 ret = _gnutls_ext_register (&ext_mod_cert_type);
320 if (ret != GNUTLS_E_SUCCESS)
321 return ret;
323 ret = _gnutls_ext_register (&ext_mod_server_name);
324 if (ret != GNUTLS_E_SUCCESS)
325 return ret;
327 ret = _gnutls_ext_register (&ext_mod_sr);
328 if (ret != GNUTLS_E_SUCCESS)
329 return ret;
331 #ifdef ENABLE_SRP
332 ret = _gnutls_ext_register (&ext_mod_srp);
333 if (ret != GNUTLS_E_SUCCESS)
334 return ret;
335 #endif
337 ret = _gnutls_ext_register (&ext_mod_heartbeat);
338 if (ret != GNUTLS_E_SUCCESS)
339 return ret;
341 ret = _gnutls_ext_register (&ext_mod_session_ticket);
342 if (ret != GNUTLS_E_SUCCESS)
343 return ret;
345 ret = _gnutls_ext_register (&ext_mod_supported_ecc);
346 if (ret != GNUTLS_E_SUCCESS)
347 return ret;
349 ret = _gnutls_ext_register (&ext_mod_supported_ecc_pf);
350 if (ret != GNUTLS_E_SUCCESS)
351 return ret;
353 ret = _gnutls_ext_register (&ext_mod_sig);
354 if (ret != GNUTLS_E_SUCCESS)
355 return ret;
357 return GNUTLS_E_SUCCESS;
360 void
361 _gnutls_ext_deinit (void)
363 gnutls_free (extfunc);
364 extfunc = NULL;
365 extfunc_size = 0;
369 _gnutls_ext_register (extension_entry_st * mod)
371 extension_entry_st *p;
373 p = gnutls_realloc (extfunc, sizeof (*extfunc) * (extfunc_size + 1));
374 if (!p)
376 gnutls_assert ();
377 return GNUTLS_E_MEMORY_ERROR;
380 extfunc = p;
382 memcpy (&extfunc[extfunc_size], mod, sizeof (*mod));
384 extfunc_size++;
386 return GNUTLS_E_SUCCESS;
390 _gnutls_ext_pack (gnutls_session_t session, gnutls_buffer_st * packed)
392 unsigned int i;
393 int ret;
394 extension_priv_data_t data;
395 int cur_size;
396 int size_offset;
397 int total_exts_pos;
398 int exts = 0;
400 total_exts_pos = packed->length;
401 BUFFER_APPEND_NUM (packed, 0);
403 for (i = 0; i < extfunc_size; i++)
405 ret = _gnutls_ext_get_session_data (session, extfunc[i].type, &data);
406 if (ret >= 0 && extfunc[i].pack_func != NULL)
408 BUFFER_APPEND_NUM (packed, extfunc[i].type);
410 size_offset = packed->length;
411 BUFFER_APPEND_NUM (packed, 0);
413 cur_size = packed->length;
415 ret = extfunc[i].pack_func (data, packed);
416 if (ret < 0)
418 gnutls_assert ();
419 return ret;
422 exts++;
423 /* write the actual size */
424 _gnutls_write_uint32 (packed->length - cur_size,
425 packed->data + size_offset);
429 _gnutls_write_uint32 (exts, packed->data + total_exts_pos);
431 return 0;
435 void
436 _gnutls_ext_restore_resumed_session (gnutls_session_t session)
438 int i;
441 /* clear everything except MANDATORY extensions */
442 for (i = 0; i < MAX_EXT_TYPES; i++)
444 if (session->internals.extension_int_data[i].set != 0 &&
445 _gnutls_ext_parse_type (session->internals.
446 extension_int_data[i].type) !=
447 GNUTLS_EXT_MANDATORY)
449 _gnutls_ext_unset_session_data (session,
450 session->
451 internals.extension_int_data[i].
452 type);
456 /* copy resumed to main */
457 for (i = 0; i < MAX_EXT_TYPES; i++)
459 if (session->internals.resumed_extension_int_data[i].set != 0 &&
460 _gnutls_ext_parse_type (session->
461 internals.resumed_extension_int_data[i].
462 type) != GNUTLS_EXT_MANDATORY)
464 _gnutls_ext_set_session_data (session,
465 session->
466 internals.resumed_extension_int_data
467 [i].type,
468 session->
469 internals.resumed_extension_int_data
470 [i].priv);
471 session->internals.resumed_extension_int_data[i].set = 0;
478 static void
479 _gnutls_ext_set_resumed_session_data (gnutls_session_t session, uint16_t type,
480 extension_priv_data_t data)
482 int i;
484 for (i = 0; i < MAX_EXT_TYPES; i++)
486 if (session->internals.resumed_extension_int_data[i].type == type
487 || session->internals.resumed_extension_int_data[i].set == 0)
490 if (session->internals.resumed_extension_int_data[i].set != 0)
491 _gnutls_ext_unset_resumed_session_data (session, type);
493 session->internals.resumed_extension_int_data[i].type = type;
494 session->internals.resumed_extension_int_data[i].priv = data;
495 session->internals.resumed_extension_int_data[i].set = 1;
496 return;
502 _gnutls_ext_unpack (gnutls_session_t session, gnutls_buffer_st * packed)
504 int i, ret;
505 extension_priv_data_t data;
506 gnutls_ext_unpack_func unpack;
507 int max_exts = 0;
508 uint16_t type;
509 int size_for_type, cur_pos;
512 BUFFER_POP_NUM (packed, max_exts);
513 for (i = 0; i < max_exts; i++)
515 BUFFER_POP_NUM (packed, type);
516 BUFFER_POP_NUM (packed, size_for_type);
518 cur_pos = packed->length;
520 unpack = _gnutls_ext_func_unpack (type);
521 if (unpack == NULL)
523 gnutls_assert ();
524 return GNUTLS_E_PARSING_ERROR;
527 ret = unpack (packed, &data);
528 if (ret < 0)
530 gnutls_assert ();
531 return ret;
534 /* verify that unpack read the correct bytes */
535 cur_pos = cur_pos - packed->length;
536 if (cur_pos /* read length */ != size_for_type)
538 gnutls_assert ();
539 return GNUTLS_E_PARSING_ERROR;
542 _gnutls_ext_set_resumed_session_data (session, type, data);
545 return 0;
547 error:
548 return ret;
551 void
552 _gnutls_ext_unset_session_data (gnutls_session_t session, uint16_t type)
554 gnutls_ext_deinit_data_func deinit;
555 extension_priv_data_t data;
556 int ret, i;
558 deinit = _gnutls_ext_func_deinit (type);
559 ret = _gnutls_ext_get_session_data (session, type, &data);
561 if (ret >= 0 && deinit != NULL)
563 deinit (data);
566 for (i = 0; i < MAX_EXT_TYPES; i++)
568 if (session->internals.extension_int_data[i].type == type)
570 session->internals.extension_int_data[i].set = 0;
571 return;
577 static void
578 _gnutls_ext_unset_resumed_session_data (gnutls_session_t session,
579 uint16_t type)
581 gnutls_ext_deinit_data_func deinit;
582 extension_priv_data_t data;
583 int ret, i;
585 deinit = _gnutls_ext_func_deinit (type);
586 ret = _gnutls_ext_get_resumed_session_data (session, type, &data);
588 if (ret >= 0 && deinit != NULL)
590 deinit (data);
593 for (i = 0; i < MAX_EXT_TYPES; i++)
595 if (session->internals.resumed_extension_int_data[i].type == type)
597 session->internals.resumed_extension_int_data[i].set = 0;
598 return;
604 /* Deinitializes all data that are associated with TLS extensions.
606 void
607 _gnutls_ext_free_session_data (gnutls_session_t session)
609 unsigned int i;
611 for (i = 0; i < extfunc_size; i++)
613 _gnutls_ext_unset_session_data (session, extfunc[i].type);
616 for (i = 0; i < extfunc_size; i++)
618 _gnutls_ext_unset_resumed_session_data (session, extfunc[i].type);
623 /* This function allows and extension to store data in the current session
624 * and retrieve them later on. We use functions instead of a pointer to a
625 * private pointer, to allow API additions by individual extensions.
627 void
628 _gnutls_ext_set_session_data (gnutls_session_t session, uint16_t type,
629 extension_priv_data_t data)
631 unsigned int i;
632 gnutls_ext_deinit_data_func deinit;
634 deinit = _gnutls_ext_func_deinit (type);
636 for (i = 0; i < MAX_EXT_TYPES; i++)
638 if (session->internals.extension_int_data[i].type == type
639 || session->internals.extension_int_data[i].set == 0)
641 if (session->internals.extension_int_data[i].set != 0)
643 if (deinit)
644 deinit (session->internals.extension_int_data[i].priv);
646 session->internals.extension_int_data[i].type = type;
647 session->internals.extension_int_data[i].priv = data;
648 session->internals.extension_int_data[i].set = 1;
649 return;
655 _gnutls_ext_get_session_data (gnutls_session_t session,
656 uint16_t type, extension_priv_data_t * data)
658 int i;
660 for (i = 0; i < MAX_EXT_TYPES; i++)
662 if (session->internals.extension_int_data[i].set != 0 &&
663 session->internals.extension_int_data[i].type == type)
665 *data = session->internals.extension_int_data[i].priv;
666 return 0;
669 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
673 _gnutls_ext_get_resumed_session_data (gnutls_session_t session,
674 uint16_t type,
675 extension_priv_data_t * data)
677 int i;
679 for (i = 0; i < MAX_EXT_TYPES; i++)
681 if (session->internals.resumed_extension_int_data[i].set != 0 &&
682 session->internals.resumed_extension_int_data[i].type == type)
684 *data = session->internals.resumed_extension_int_data[i].priv;
685 return 0;
688 return GNUTLS_E_INVALID_REQUEST;