2 * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
3 * Free Software Foundation, Inc.
5 * Author: Nikos Mavrogiannopoulos, Simon Josefsson
7 * This file is part of GnuTLS.
9 * The GnuTLS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1 of
12 * the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
26 /* Functions that relate to the TLS hello extension parsing.
27 * Hello extensions are packets appended in the TLS hello packet, and
28 * allow for extra functionality.
31 #include "gnutls_int.h"
32 #include "gnutls_extensions.h"
33 #include "gnutls_errors.h"
34 #include "ext_max_record.h"
35 #include <ext_cert_type.h>
36 #include <ext_server_name.h>
38 #include <ext_session_ticket.h>
39 #include <ext_safe_renegotiation.h>
40 #include <ext_signature.h>
41 #include <ext_safe_renegotiation.h>
42 #include <gnutls_num.h>
45 static void _gnutls_ext_unset_resumed_session_data (gnutls_session_t session,
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)
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)
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;
79 static gnutls_ext_deinit_data_func
80 _gnutls_ext_func_deinit (uint16_t type)
84 for (i = 0; i < extfunc_size; i++)
85 if (extfunc[i].type == type)
86 return extfunc[i].deinit_func;
91 static gnutls_ext_unpack_func
92 _gnutls_ext_func_unpack (uint16_t type)
96 for (i = 0; i < extfunc_size; i++)
97 if (extfunc[i].type == type)
98 return extfunc[i].unpack_func;
105 _gnutls_extension_get_name (uint16_t type)
109 for (i = 0; i < extfunc_size; i++)
110 if (extfunc[i].type == type)
111 return extfunc[i].name;
116 /* Checks if the extension we just received is one of the
117 * requested ones. Otherwise it's a fatal error.
120 _gnutls_extension_list_check (gnutls_session_t session, uint16_t type)
122 if (session->security_parameters.entity == GNUTLS_CLIENT)
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;
139 _gnutls_parse_extensions (gnutls_session_t session,
140 gnutls_ext_parse_type_t parse_type,
141 const opaque * data, int data_size)
147 gnutls_ext_recv_func ext_recv;
153 if (session->security_parameters.entity == GNUTLS_CLIENT)
154 for (i = 0; i < session->internals.extensions_sent_size; i++)
156 _gnutls_debug_log ("EXT[%d]: expecting extension '%s'\n",
158 _gnutls_extension_get_name
159 (session->internals.extensions_sent[i]));
163 DECR_LENGTH_RET (data_size, 2, 0);
164 next = _gnutls_read_uint16 (data);
167 DECR_LENGTH_RET (data_size, next, 0);
171 DECR_LENGTH_RET (next, 2, 0);
172 type = _gnutls_read_uint16 (&data[pos]);
176 _gnutls_debug_log ("EXT[%p]: Found extension '%s/%d'\n", session,
177 _gnutls_extension_get_name (type), type);
180 if ((ret = _gnutls_extension_list_check (session, type)) < 0)
186 DECR_LENGTH_RET (next, 2, 0);
187 size = _gnutls_read_uint16 (&data[pos]);
190 DECR_LENGTH_RET (next, size, 0);
194 ext_recv = _gnutls_ext_func_recv (type, parse_type);
195 if (ext_recv == NULL)
198 _gnutls_debug_log ("EXT[%p]: Parsing extension '%s/%d' (%d bytes)\n",
199 session, _gnutls_extension_get_name (type), type,
202 if ((ret = ext_recv (session, sdata, size)) < 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.
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++;
233 _gnutls_debug_log ("extensions: Increase MAX_EXT_TYPES\n");
239 _gnutls_gen_extensions (gnutls_session_t session, opaque * data,
240 size_t data_size, gnutls_ext_parse_type_t parse_type)
251 return GNUTLS_E_INTERNAL_ERROR;
254 /* allocate enough data for each extension.
256 sdata_size = data_size;
257 sdata = gnutls_malloc (sdata_size);
261 return GNUTLS_E_MEMORY_ERROR;
265 for (i = 0; i < extfunc_size; i++)
267 extension_entry_st *p = &extfunc[i];
269 if (p->send_func == NULL)
272 if (parse_type != GNUTLS_EXT_ANY && p->parse_type != parse_type)
275 size = p->send_func (session, sdata, sdata_size);
276 if (size > 0 || size == GNUTLS_E_INT_RET_0)
278 if (size == GNUTLS_E_INT_RET_0)
281 if (data_size < pos + (size_t) size + 4)
285 return GNUTLS_E_INTERNAL_ERROR;
288 /* write extension type */
289 _gnutls_write_uint16 (p->type, &data[pos]);
293 _gnutls_write_uint16 (size, &data[pos]);
296 memcpy (&data[pos], sdata, size);
299 /* add this extension to the extension list
301 _gnutls_extension_list_add (session, p->type);
303 _gnutls_debug_log ("EXT[%p]: Sending extension %s (%d bytes)\n",
304 session, p->name, size);
315 pos -= 2; /* remove the size of the size header! */
317 _gnutls_write_uint16 (pos, data);
330 _gnutls_ext_init (void)
334 ret = _gnutls_ext_register (&ext_mod_max_record_size);
335 if (ret != GNUTLS_E_SUCCESS)
338 ret = _gnutls_ext_register (&ext_mod_cert_type);
339 if (ret != GNUTLS_E_SUCCESS)
343 ret = _gnutls_ext_register (&ext_mod_server_name);
344 if (ret != GNUTLS_E_SUCCESS)
347 ret = _gnutls_ext_register (&ext_mod_sr);
348 if (ret != GNUTLS_E_SUCCESS)
352 ret = _gnutls_ext_register (&ext_mod_srp);
353 if (ret != GNUTLS_E_SUCCESS)
357 #ifdef ENABLE_SESSION_TICKET
358 ret = _gnutls_ext_register (&ext_mod_session_ticket);
359 if (ret != GNUTLS_E_SUCCESS)
363 ret = _gnutls_ext_register (&ext_mod_sig);
364 if (ret != GNUTLS_E_SUCCESS)
367 return GNUTLS_E_SUCCESS;
371 _gnutls_ext_deinit (void)
373 gnutls_free (extfunc);
379 _gnutls_ext_register (extension_entry_st * mod)
381 extension_entry_st *p;
383 p = gnutls_realloc (extfunc, sizeof (*extfunc) * (extfunc_size + 1));
387 return GNUTLS_E_MEMORY_ERROR;
392 memcpy (&extfunc[extfunc_size], mod, sizeof (*mod));
396 return GNUTLS_E_SUCCESS;
400 * gnutls_ext_register:
401 * @type: the 16-bit integer referring to the extension type
402 * @name: human printable name of the extension used for debugging
403 * @parse_type: either #GNUTLS_EXT_TLS or %GNUTLS_EXT_APPLICATION.
404 * @recv_func: a function to receive extension data
405 * @send_func: a function to send extension data
407 * This function is used to register a new TLS extension handler.
409 * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
411 * Deprecated in: 2.12.0
414 gnutls_ext_register (int type,
416 gnutls_ext_parse_type_t parse_type,
417 gnutls_ext_recv_func recv_func,
418 gnutls_ext_send_func send_func)
420 extension_entry_st ee;
422 memset (&ee, 0, sizeof (ee));
426 ee.parse_type = parse_type;
427 ee.recv_func = recv_func;
428 ee.send_func = send_func;
429 /* FIXME: Why is this exported? Should it be removed? */
430 return _gnutls_ext_register (&ee);
434 _gnutls_ext_pack (gnutls_session_t session, gnutls_buffer_st * packed)
437 extension_priv_data_t data;
443 total_exts_pos = packed->length;
444 BUFFER_APPEND_NUM (packed, 0);
446 for (i = 0; i < extfunc_size; i++)
448 ret = _gnutls_ext_get_session_data (session, extfunc[i].type, &data);
449 if (ret >= 0 && extfunc[i].pack_func != NULL)
451 BUFFER_APPEND_NUM (packed, extfunc[i].type);
453 size_offset = packed->length;
454 BUFFER_APPEND_NUM (packed, 0);
456 cur_size = packed->length;
458 ret = extfunc[i].pack_func (data, packed);
466 /* write the actual size */
467 _gnutls_write_uint32 (packed->length - cur_size,
468 packed->data + size_offset);
472 _gnutls_write_uint32 (exts, packed->data + total_exts_pos);
479 _gnutls_ext_restore_resumed_session (gnutls_session_t session)
484 /* clear everything except MANDATORY extensions */
485 for (i = 0; i < MAX_EXT_TYPES; i++)
487 if (session->internals.extension_int_data[i].set != 0 &&
488 _gnutls_ext_parse_type (session->internals.
489 extension_int_data[i].type) !=
490 GNUTLS_EXT_MANDATORY)
492 _gnutls_ext_unset_session_data (session,
494 internals.extension_int_data[i].
499 /* copy resumed to main */
500 for (i = 0; i < MAX_EXT_TYPES; i++)
502 if (session->internals.resumed_extension_int_data[i].set != 0 &&
503 _gnutls_ext_parse_type (session->
504 internals.resumed_extension_int_data[i].
505 type) != GNUTLS_EXT_MANDATORY)
507 _gnutls_ext_set_session_data (session,
509 internals.resumed_extension_int_data
512 internals.resumed_extension_int_data
514 session->internals.resumed_extension_int_data[i].set = 0;
522 _gnutls_ext_set_resumed_session_data (gnutls_session_t session, uint16_t type,
523 extension_priv_data_t data)
527 for (i = 0; i < MAX_EXT_TYPES; i++)
529 if (session->internals.resumed_extension_int_data[i].type == type
530 || session->internals.resumed_extension_int_data[i].set == 0)
533 if (session->internals.resumed_extension_int_data[i].set != 0)
534 _gnutls_ext_unset_resumed_session_data (session, type);
536 session->internals.resumed_extension_int_data[i].type = type;
537 session->internals.resumed_extension_int_data[i].priv = data;
538 session->internals.resumed_extension_int_data[i].set = 1;
545 _gnutls_ext_unpack (gnutls_session_t session, gnutls_buffer_st * packed)
548 extension_priv_data_t data;
549 gnutls_ext_unpack_func unpack;
552 int size_for_type, cur_pos;
555 BUFFER_POP_NUM (packed, max_exts);
556 for (i = 0; i < max_exts; i++)
558 BUFFER_POP_NUM (packed, type);
559 BUFFER_POP_NUM (packed, size_for_type);
561 cur_pos = packed->length;
563 unpack = _gnutls_ext_func_unpack (type);
567 return GNUTLS_E_PARSING_ERROR;
570 ret = unpack (packed, &data);
577 /* verify that unpack read the correct bytes */
578 cur_pos = cur_pos - packed->length;
579 if (cur_pos /* read length */ != size_for_type)
582 return GNUTLS_E_PARSING_ERROR;
585 _gnutls_ext_set_resumed_session_data (session, type, data);
595 _gnutls_ext_unset_session_data (gnutls_session_t session, uint16_t type)
597 gnutls_ext_deinit_data_func deinit;
598 extension_priv_data_t data;
601 deinit = _gnutls_ext_func_deinit (type);
602 ret = _gnutls_ext_get_session_data (session, type, &data);
604 if (ret >= 0 && deinit != NULL)
609 for (i = 0; i < MAX_EXT_TYPES; i++)
611 if (session->internals.extension_int_data[i].type == type)
613 session->internals.extension_int_data[i].set = 0;
621 _gnutls_ext_unset_resumed_session_data (gnutls_session_t session,
624 gnutls_ext_deinit_data_func deinit;
625 extension_priv_data_t data;
628 deinit = _gnutls_ext_func_deinit (type);
629 ret = _gnutls_ext_get_resumed_session_data (session, type, &data);
631 if (ret >= 0 && deinit != NULL)
636 for (i = 0; i < MAX_EXT_TYPES; i++)
638 if (session->internals.resumed_extension_int_data[i].type == type)
640 session->internals.resumed_extension_int_data[i].set = 0;
647 /* Deinitializes all data that are associated with TLS extensions.
650 _gnutls_ext_free_session_data (gnutls_session_t session)
654 for (i = 0; i < extfunc_size; i++)
656 _gnutls_ext_unset_session_data (session, extfunc[i].type);
659 for (i = 0; i < extfunc_size; i++)
661 _gnutls_ext_unset_resumed_session_data (session, extfunc[i].type);
666 /* This function allows and extension to store data in the current session
667 * and retrieve them later on. We use functions instead of a pointer to a
668 * private pointer, to allow API additions by individual extensions.
671 _gnutls_ext_set_session_data (gnutls_session_t session, uint16_t type,
672 extension_priv_data_t data)
675 gnutls_ext_deinit_data_func deinit;
677 deinit = _gnutls_ext_func_deinit (type);
679 for (i = 0; i < MAX_EXT_TYPES; i++)
681 if (session->internals.extension_int_data[i].type == type
682 || session->internals.extension_int_data[i].set == 0)
684 if (session->internals.extension_int_data[i].set != 0)
687 deinit (session->internals.extension_int_data[i].priv);
689 session->internals.extension_int_data[i].type = type;
690 session->internals.extension_int_data[i].priv = data;
691 session->internals.extension_int_data[i].set = 1;
698 _gnutls_ext_get_session_data (gnutls_session_t session,
699 uint16_t type, extension_priv_data_t * data)
703 for (i = 0; i < MAX_EXT_TYPES; i++)
705 if (session->internals.extension_int_data[i].set != 0 &&
706 session->internals.extension_int_data[i].type == type)
708 *data = session->internals.extension_int_data[i].priv;
712 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
716 _gnutls_ext_get_resumed_session_data (gnutls_session_t session,
718 extension_priv_data_t * data)
722 for (i = 0; i < MAX_EXT_TYPES; i++)
724 if (session->internals.resumed_extension_int_data[i].set != 0 &&
725 session->internals.resumed_extension_int_data[i].type == type)
727 *data = session->internals.resumed_extension_int_data[i].priv;
731 return GNUTLS_E_INVALID_REQUEST;