corrected typo
[gnutls.git] / lib / gnutls_extensions.c
blob54c5b4f972208ec2da5df7f57d0b3d687b16bd8e
1 /*
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,
22 * USA
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>
37 #include <ext_srp.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,
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 opaque * data, int data_size)
143 int next, ret;
144 int pos = 0;
145 uint16_t type;
146 const opaque *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_debug_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 0
176 _gnutls_debug_log ("EXT[%p]: Found extension '%s/%d'\n", session,
177 _gnutls_extension_get_name (type), type);
178 #endif
180 if ((ret = _gnutls_extension_list_check (session, type)) < 0)
182 gnutls_assert ();
183 return ret;
186 DECR_LENGTH_RET (next, 2, 0);
187 size = _gnutls_read_uint16 (&data[pos]);
188 pos += 2;
190 DECR_LENGTH_RET (next, size, 0);
191 sdata = &data[pos];
192 pos += size;
194 ext_recv = _gnutls_ext_func_recv (type, parse_type);
195 if (ext_recv == NULL)
196 continue;
198 _gnutls_debug_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_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)
242 int size;
243 uint16_t pos = 0;
244 opaque *sdata;
245 size_t sdata_size;
246 size_t i;
248 if (data_size < 2)
250 gnutls_assert ();
251 return GNUTLS_E_INTERNAL_ERROR;
254 /* allocate enough data for each extension.
256 sdata_size = data_size;
257 sdata = gnutls_malloc (sdata_size);
258 if (sdata == NULL)
260 gnutls_assert ();
261 return GNUTLS_E_MEMORY_ERROR;
264 pos += 2;
265 for (i = 0; i < extfunc_size; i++)
267 extension_entry_st *p = &extfunc[i];
269 if (p->send_func == NULL)
270 continue;
272 if (parse_type != GNUTLS_EXT_ANY && p->parse_type != parse_type)
273 continue;
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)
279 size = 0;
281 if (data_size < pos + (size_t) size + 4)
283 gnutls_assert ();
284 gnutls_free (sdata);
285 return GNUTLS_E_INTERNAL_ERROR;
288 /* write extension type */
289 _gnutls_write_uint16 (p->type, &data[pos]);
290 pos += 2;
292 /* write size */
293 _gnutls_write_uint16 (size, &data[pos]);
294 pos += 2;
296 memcpy (&data[pos], sdata, size);
297 pos += 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);
306 else if (size < 0)
308 gnutls_assert ();
309 gnutls_free (sdata);
310 return size;
314 size = pos;
315 pos -= 2; /* remove the size of the size header! */
317 _gnutls_write_uint16 (pos, data);
319 if (size == 2)
320 { /* empty */
321 size = 0;
324 gnutls_free (sdata);
325 return size;
330 _gnutls_ext_init (void)
332 int ret;
334 ret = _gnutls_ext_register (&ext_mod_max_record_size);
335 if (ret != GNUTLS_E_SUCCESS)
336 return ret;
338 ret = _gnutls_ext_register (&ext_mod_cert_type);
339 if (ret != GNUTLS_E_SUCCESS)
340 return ret;
343 ret = _gnutls_ext_register (&ext_mod_server_name);
344 if (ret != GNUTLS_E_SUCCESS)
345 return ret;
347 ret = _gnutls_ext_register (&ext_mod_sr);
348 if (ret != GNUTLS_E_SUCCESS)
349 return ret;
351 #ifdef ENABLE_SRP
352 ret = _gnutls_ext_register (&ext_mod_srp);
353 if (ret != GNUTLS_E_SUCCESS)
354 return ret;
355 #endif
357 #ifdef ENABLE_SESSION_TICKET
358 ret = _gnutls_ext_register (&ext_mod_session_ticket);
359 if (ret != GNUTLS_E_SUCCESS)
360 return ret;
361 #endif
363 ret = _gnutls_ext_register (&ext_mod_sig);
364 if (ret != GNUTLS_E_SUCCESS)
365 return ret;
367 return GNUTLS_E_SUCCESS;
370 void
371 _gnutls_ext_deinit (void)
373 gnutls_free (extfunc);
374 extfunc = NULL;
375 extfunc_size = 0;
379 _gnutls_ext_register (extension_entry_st * mod)
381 extension_entry_st *p;
383 p = gnutls_realloc (extfunc, sizeof (*extfunc) * (extfunc_size + 1));
384 if (!p)
386 gnutls_assert ();
387 return GNUTLS_E_MEMORY_ERROR;
390 extfunc = p;
392 memcpy (&extfunc[extfunc_size], mod, sizeof (*mod));
394 extfunc_size++;
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,
415 const char *name,
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));
424 ee.type = type;
425 ee.name = name;
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)
436 int i, ret;
437 extension_priv_data_t data;
438 int cur_size;
439 int size_offset;
440 int total_exts_pos;
441 int exts = 0;
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);
459 if (ret < 0)
461 gnutls_assert ();
462 return ret;
465 exts++;
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);
474 return 0;
478 void
479 _gnutls_ext_restore_resumed_session (gnutls_session_t session)
481 int i;
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,
493 session->
494 internals.extension_int_data[i].
495 type);
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,
508 session->
509 internals.resumed_extension_int_data
510 [i].type,
511 session->
512 internals.resumed_extension_int_data
513 [i].priv);
514 session->internals.resumed_extension_int_data[i].set = 0;
521 static void
522 _gnutls_ext_set_resumed_session_data (gnutls_session_t session, uint16_t type,
523 extension_priv_data_t data)
525 int i;
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;
539 return;
545 _gnutls_ext_unpack (gnutls_session_t session, gnutls_buffer_st * packed)
547 int i, ret;
548 extension_priv_data_t data;
549 gnutls_ext_unpack_func unpack;
550 int max_exts = 0;
551 uint16_t type;
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);
564 if (unpack == NULL)
566 gnutls_assert ();
567 return GNUTLS_E_PARSING_ERROR;
570 ret = unpack (packed, &data);
571 if (ret < 0)
573 gnutls_assert ();
574 return ret;
577 /* verify that unpack read the correct bytes */
578 cur_pos = cur_pos - packed->length;
579 if (cur_pos /* read length */ != size_for_type)
581 gnutls_assert ();
582 return GNUTLS_E_PARSING_ERROR;
585 _gnutls_ext_set_resumed_session_data (session, type, data);
588 return 0;
590 error:
591 return ret;
594 void
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;
599 int ret, i;
601 deinit = _gnutls_ext_func_deinit (type);
602 ret = _gnutls_ext_get_session_data (session, type, &data);
604 if (ret >= 0 && deinit != NULL)
606 deinit (data);
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;
614 return;
620 static void
621 _gnutls_ext_unset_resumed_session_data (gnutls_session_t session,
622 uint16_t type)
624 gnutls_ext_deinit_data_func deinit;
625 extension_priv_data_t data;
626 int ret, i;
628 deinit = _gnutls_ext_func_deinit (type);
629 ret = _gnutls_ext_get_resumed_session_data (session, type, &data);
631 if (ret >= 0 && deinit != NULL)
633 deinit (data);
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;
641 return;
647 /* Deinitializes all data that are associated with TLS extensions.
649 void
650 _gnutls_ext_free_session_data (gnutls_session_t session)
652 int i;
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.
670 void
671 _gnutls_ext_set_session_data (gnutls_session_t session, uint16_t type,
672 extension_priv_data_t data)
674 int i;
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)
686 if (deinit)
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;
692 return;
698 _gnutls_ext_get_session_data (gnutls_session_t session,
699 uint16_t type, extension_priv_data_t * data)
701 int i;
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;
709 return 0;
712 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
716 _gnutls_ext_get_resumed_session_data (gnutls_session_t session,
717 uint16_t type,
718 extension_priv_data_t * data)
720 int i;
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;
728 return 0;
731 return GNUTLS_E_INVALID_REQUEST;