corrected copyright notices
[gnutls.git] / lib / gnutls_extensions.c
blob2cf9c26d9271c36375f247ecc7d7b6422e1d6102
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 <ext/srtp.h>
43 #include <gnutls_num.h>
46 static void _gnutls_ext_unset_resumed_session_data (gnutls_session_t session,
47 uint16_t type);
50 static size_t extfunc_size = 0;
51 static extension_entry_st *extfunc = NULL;
53 static gnutls_ext_parse_type_t
54 _gnutls_ext_parse_type (uint16_t type)
56 size_t i;
58 for (i = 0; i < extfunc_size; i++)
60 if (extfunc[i].type == type)
61 return extfunc[i].parse_type;
64 return GNUTLS_EXT_NONE;
67 static gnutls_ext_recv_func
68 _gnutls_ext_func_recv (uint16_t type, gnutls_ext_parse_type_t parse_type)
70 size_t i;
72 for (i = 0; i < extfunc_size; i++)
73 if (extfunc[i].type == type)
74 if (parse_type == GNUTLS_EXT_ANY || extfunc[i].parse_type == parse_type)
75 return extfunc[i].recv_func;
77 return NULL;
80 static gnutls_ext_deinit_data_func
81 _gnutls_ext_func_deinit (uint16_t type)
83 size_t i;
85 for (i = 0; i < extfunc_size; i++)
86 if (extfunc[i].type == type)
87 return extfunc[i].deinit_func;
89 return NULL;
92 static gnutls_ext_unpack_func
93 _gnutls_ext_func_unpack (uint16_t type)
95 size_t i;
97 for (i = 0; i < extfunc_size; i++)
98 if (extfunc[i].type == type)
99 return extfunc[i].unpack_func;
101 return NULL;
105 static const char *
106 _gnutls_extension_get_name (uint16_t type)
108 size_t i;
110 for (i = 0; i < extfunc_size; i++)
111 if (extfunc[i].type == type)
112 return extfunc[i].name;
114 return NULL;
117 /* Checks if the extension we just received is one of the
118 * requested ones. Otherwise it's a fatal error.
120 static int
121 _gnutls_extension_list_check (gnutls_session_t session, uint16_t type)
123 if (session->security_parameters.entity == GNUTLS_CLIENT)
125 int i;
127 for (i = 0; i < session->internals.extensions_sent_size; i++)
129 if (type == session->internals.extensions_sent[i])
130 return 0; /* ok found */
133 return GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION;
136 return 0;
140 _gnutls_parse_extensions (gnutls_session_t session,
141 gnutls_ext_parse_type_t parse_type,
142 const uint8_t * data, int data_size)
144 int next, ret;
145 int pos = 0;
146 uint16_t type;
147 const uint8_t *sdata;
148 gnutls_ext_recv_func ext_recv;
149 uint16_t size;
151 #ifdef DEBUG
152 int i;
154 if (session->security_parameters.entity == GNUTLS_CLIENT)
155 for (i = 0; i < session->internals.extensions_sent_size; i++)
157 _gnutls_handshake_log ("EXT[%d]: expecting extension '%s'\n",
158 session,
159 _gnutls_extension_get_name
160 (session->internals.extensions_sent[i]));
162 #endif
164 DECR_LENGTH_RET (data_size, 2, 0);
165 next = _gnutls_read_uint16 (data);
166 pos += 2;
168 DECR_LENGTH_RET (data_size, next, 0);
172 DECR_LENGTH_RET (next, 2, 0);
173 type = _gnutls_read_uint16 (&data[pos]);
174 pos += 2;
176 if ((ret = _gnutls_extension_list_check (session, type)) < 0)
178 gnutls_assert ();
179 return ret;
182 DECR_LENGTH_RET (next, 2, 0);
183 size = _gnutls_read_uint16 (&data[pos]);
184 pos += 2;
186 DECR_LENGTH_RET (next, size, 0);
187 sdata = &data[pos];
188 pos += size;
190 ext_recv = _gnutls_ext_func_recv (type, parse_type);
191 if (ext_recv == NULL)
193 _gnutls_handshake_log ("EXT[%p]: Found extension '%s/%d'\n", session,
194 _gnutls_extension_get_name (type), type);
196 continue;
199 _gnutls_handshake_log ("EXT[%p]: Parsing extension '%s/%d' (%d bytes)\n",
200 session, _gnutls_extension_get_name (type), type,
201 size);
203 if ((ret = ext_recv (session, sdata, size)) < 0)
205 gnutls_assert ();
206 return ret;
210 while (next > 2);
212 return 0;
216 /* Adds the extension we want to send in the extensions list.
217 * This list is used to check whether the (later) received
218 * extensions are the ones we requested.
220 void
221 _gnutls_extension_list_add (gnutls_session_t session, uint16_t type)
224 if (session->security_parameters.entity == GNUTLS_CLIENT)
226 if (session->internals.extensions_sent_size < MAX_EXT_TYPES)
228 session->internals.extensions_sent[session->internals.
229 extensions_sent_size] = type;
230 session->internals.extensions_sent_size++;
232 else
234 _gnutls_handshake_log ("extensions: Increase MAX_EXT_TYPES\n");
240 _gnutls_gen_extensions (gnutls_session_t session, gnutls_buffer_st * extdata,
241 gnutls_ext_parse_type_t parse_type)
243 int size;
244 int pos, size_pos, ret;
245 size_t i, init_size = extdata->length;
247 pos = extdata->length; /* we will store length later on */
248 _gnutls_buffer_append_prefix( extdata, 16, 0);
250 for (i = 0; i < extfunc_size; i++)
252 extension_entry_st *p = &extfunc[i];
254 if (p->send_func == NULL)
255 continue;
257 if (parse_type != GNUTLS_EXT_ANY && p->parse_type != parse_type)
258 continue;
260 ret = _gnutls_buffer_append_prefix( extdata, 16, p->type);
261 if (ret < 0)
262 return gnutls_assert_val(ret);
264 size_pos = extdata->length;
265 ret = _gnutls_buffer_append_prefix (extdata, 16, 0);
266 if (ret < 0)
267 return gnutls_assert_val(ret);
269 size = p->send_func (session, extdata);
270 /* returning GNUTLS_E_INT_RET_0 means to send an empty
271 * extension of this type.
273 if (size > 0 || size == GNUTLS_E_INT_RET_0)
275 if (size == GNUTLS_E_INT_RET_0)
276 size = 0;
278 /* write the real size */
279 _gnutls_write_uint16(size, &extdata->data[size_pos]);
281 /* add this extension to the extension list
283 _gnutls_extension_list_add (session, p->type);
285 _gnutls_handshake_log ("EXT[%p]: Sending extension %s (%d bytes)\n",
286 session, p->name, size);
288 else if (size < 0)
290 gnutls_assert ();
291 return size;
293 else if (size == 0)
294 extdata->length -= 4; /* reset type and size */
297 /* remove any initial data, and the size of the header */
298 size = extdata->length - init_size - 2;
300 if ( size > 0)
301 _gnutls_write_uint16(size, &extdata->data[pos]);
302 else if (size == 0) extdata->length -= 2; /* the length bytes */
304 return size;
308 _gnutls_ext_init (void)
310 int ret;
312 ret = _gnutls_ext_register (&ext_mod_max_record_size);
313 if (ret != GNUTLS_E_SUCCESS)
314 return ret;
316 ret = _gnutls_ext_register (&ext_mod_status_request);
317 if (ret != GNUTLS_E_SUCCESS)
318 return ret;
320 ret = _gnutls_ext_register (&ext_mod_cert_type);
321 if (ret != GNUTLS_E_SUCCESS)
322 return ret;
324 ret = _gnutls_ext_register (&ext_mod_server_name);
325 if (ret != GNUTLS_E_SUCCESS)
326 return ret;
328 ret = _gnutls_ext_register (&ext_mod_sr);
329 if (ret != GNUTLS_E_SUCCESS)
330 return ret;
332 #ifdef ENABLE_SRP
333 ret = _gnutls_ext_register (&ext_mod_srp);
334 if (ret != GNUTLS_E_SUCCESS)
335 return ret;
336 #endif
338 ret = _gnutls_ext_register (&ext_mod_heartbeat);
339 if (ret != GNUTLS_E_SUCCESS)
340 return ret;
342 ret = _gnutls_ext_register (&ext_mod_session_ticket);
343 if (ret != GNUTLS_E_SUCCESS)
344 return ret;
346 ret = _gnutls_ext_register (&ext_mod_supported_ecc);
347 if (ret != GNUTLS_E_SUCCESS)
348 return ret;
350 ret = _gnutls_ext_register (&ext_mod_supported_ecc_pf);
351 if (ret != GNUTLS_E_SUCCESS)
352 return ret;
354 ret = _gnutls_ext_register (&ext_mod_sig);
355 if (ret != GNUTLS_E_SUCCESS)
356 return ret;
358 #ifdef ENABLE_DTLS_SRTP
359 ret = _gnutls_ext_register (&ext_mod_srtp);
360 if (ret != GNUTLS_E_SUCCESS)
361 return ret;
362 #endif
364 return GNUTLS_E_SUCCESS;
367 void
368 _gnutls_ext_deinit (void)
370 gnutls_free (extfunc);
371 extfunc = NULL;
372 extfunc_size = 0;
376 _gnutls_ext_register (extension_entry_st * mod)
378 extension_entry_st *p;
380 p = gnutls_realloc (extfunc, sizeof (*extfunc) * (extfunc_size + 1));
381 if (!p)
383 gnutls_assert ();
384 return GNUTLS_E_MEMORY_ERROR;
387 extfunc = p;
389 memcpy (&extfunc[extfunc_size], mod, sizeof (*mod));
391 extfunc_size++;
393 return GNUTLS_E_SUCCESS;
397 _gnutls_ext_pack (gnutls_session_t session, gnutls_buffer_st * packed)
399 unsigned int i;
400 int ret;
401 extension_priv_data_t data;
402 int cur_size;
403 int size_offset;
404 int total_exts_pos;
405 int exts = 0;
407 total_exts_pos = packed->length;
408 BUFFER_APPEND_NUM (packed, 0);
410 for (i = 0; i < extfunc_size; i++)
412 ret = _gnutls_ext_get_session_data (session, extfunc[i].type, &data);
413 if (ret >= 0 && extfunc[i].pack_func != NULL)
415 BUFFER_APPEND_NUM (packed, extfunc[i].type);
417 size_offset = packed->length;
418 BUFFER_APPEND_NUM (packed, 0);
420 cur_size = packed->length;
422 ret = extfunc[i].pack_func (data, packed);
423 if (ret < 0)
425 gnutls_assert ();
426 return ret;
429 exts++;
430 /* write the actual size */
431 _gnutls_write_uint32 (packed->length - cur_size,
432 packed->data + size_offset);
436 _gnutls_write_uint32 (exts, packed->data + total_exts_pos);
438 return 0;
442 void
443 _gnutls_ext_restore_resumed_session (gnutls_session_t session)
445 int i;
448 /* clear everything except MANDATORY extensions */
449 for (i = 0; i < MAX_EXT_TYPES; i++)
451 if (session->internals.extension_int_data[i].set != 0 &&
452 _gnutls_ext_parse_type (session->internals.
453 extension_int_data[i].type) !=
454 GNUTLS_EXT_MANDATORY)
456 _gnutls_ext_unset_session_data (session,
457 session->
458 internals.extension_int_data[i].
459 type);
463 /* copy resumed to main */
464 for (i = 0; i < MAX_EXT_TYPES; i++)
466 if (session->internals.resumed_extension_int_data[i].set != 0 &&
467 _gnutls_ext_parse_type (session->
468 internals.resumed_extension_int_data[i].
469 type) != GNUTLS_EXT_MANDATORY)
471 _gnutls_ext_set_session_data (session,
472 session->
473 internals.resumed_extension_int_data
474 [i].type,
475 session->
476 internals.resumed_extension_int_data
477 [i].priv);
478 session->internals.resumed_extension_int_data[i].set = 0;
485 static void
486 _gnutls_ext_set_resumed_session_data (gnutls_session_t session, uint16_t type,
487 extension_priv_data_t data)
489 int i;
491 for (i = 0; i < MAX_EXT_TYPES; i++)
493 if (session->internals.resumed_extension_int_data[i].type == type
494 || session->internals.resumed_extension_int_data[i].set == 0)
497 if (session->internals.resumed_extension_int_data[i].set != 0)
498 _gnutls_ext_unset_resumed_session_data (session, type);
500 session->internals.resumed_extension_int_data[i].type = type;
501 session->internals.resumed_extension_int_data[i].priv = data;
502 session->internals.resumed_extension_int_data[i].set = 1;
503 return;
509 _gnutls_ext_unpack (gnutls_session_t session, gnutls_buffer_st * packed)
511 int i, ret;
512 extension_priv_data_t data;
513 gnutls_ext_unpack_func unpack;
514 int max_exts = 0;
515 uint16_t type;
516 int size_for_type, cur_pos;
519 BUFFER_POP_NUM (packed, max_exts);
520 for (i = 0; i < max_exts; i++)
522 BUFFER_POP_NUM (packed, type);
523 BUFFER_POP_NUM (packed, size_for_type);
525 cur_pos = packed->length;
527 unpack = _gnutls_ext_func_unpack (type);
528 if (unpack == NULL)
530 gnutls_assert ();
531 return GNUTLS_E_PARSING_ERROR;
534 ret = unpack (packed, &data);
535 if (ret < 0)
537 gnutls_assert ();
538 return ret;
541 /* verify that unpack read the correct bytes */
542 cur_pos = cur_pos - packed->length;
543 if (cur_pos /* read length */ != size_for_type)
545 gnutls_assert ();
546 return GNUTLS_E_PARSING_ERROR;
549 _gnutls_ext_set_resumed_session_data (session, type, data);
552 return 0;
554 error:
555 return ret;
558 void
559 _gnutls_ext_unset_session_data (gnutls_session_t session, uint16_t type)
561 gnutls_ext_deinit_data_func deinit;
562 extension_priv_data_t data;
563 int ret, i;
565 deinit = _gnutls_ext_func_deinit (type);
566 ret = _gnutls_ext_get_session_data (session, type, &data);
568 if (ret >= 0 && deinit != NULL)
570 deinit (data);
573 for (i = 0; i < MAX_EXT_TYPES; i++)
575 if (session->internals.extension_int_data[i].type == type)
577 session->internals.extension_int_data[i].set = 0;
578 return;
584 static void
585 _gnutls_ext_unset_resumed_session_data (gnutls_session_t session,
586 uint16_t type)
588 gnutls_ext_deinit_data_func deinit;
589 extension_priv_data_t data;
590 int ret, i;
592 deinit = _gnutls_ext_func_deinit (type);
593 ret = _gnutls_ext_get_resumed_session_data (session, type, &data);
595 if (ret >= 0 && deinit != NULL)
597 deinit (data);
600 for (i = 0; i < MAX_EXT_TYPES; i++)
602 if (session->internals.resumed_extension_int_data[i].type == type)
604 session->internals.resumed_extension_int_data[i].set = 0;
605 return;
611 /* Deinitializes all data that are associated with TLS extensions.
613 void
614 _gnutls_ext_free_session_data (gnutls_session_t session)
616 unsigned int i;
618 for (i = 0; i < extfunc_size; i++)
620 _gnutls_ext_unset_session_data (session, extfunc[i].type);
623 for (i = 0; i < extfunc_size; i++)
625 _gnutls_ext_unset_resumed_session_data (session, extfunc[i].type);
630 /* This function allows and extension to store data in the current session
631 * and retrieve them later on. We use functions instead of a pointer to a
632 * private pointer, to allow API additions by individual extensions.
634 void
635 _gnutls_ext_set_session_data (gnutls_session_t session, uint16_t type,
636 extension_priv_data_t data)
638 unsigned int i;
639 gnutls_ext_deinit_data_func deinit;
641 deinit = _gnutls_ext_func_deinit (type);
643 for (i = 0; i < MAX_EXT_TYPES; i++)
645 if (session->internals.extension_int_data[i].type == type
646 || session->internals.extension_int_data[i].set == 0)
648 if (session->internals.extension_int_data[i].set != 0)
650 if (deinit)
651 deinit (session->internals.extension_int_data[i].priv);
653 session->internals.extension_int_data[i].type = type;
654 session->internals.extension_int_data[i].priv = data;
655 session->internals.extension_int_data[i].set = 1;
656 return;
662 _gnutls_ext_get_session_data (gnutls_session_t session,
663 uint16_t type, extension_priv_data_t * data)
665 int i;
667 for (i = 0; i < MAX_EXT_TYPES; i++)
669 if (session->internals.extension_int_data[i].set != 0 &&
670 session->internals.extension_int_data[i].type == type)
672 *data = session->internals.extension_int_data[i].priv;
673 return 0;
676 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
680 _gnutls_ext_get_resumed_session_data (gnutls_session_t session,
681 uint16_t type,
682 extension_priv_data_t * data)
684 int i;
686 for (i = 0; i < MAX_EXT_TYPES; i++)
688 if (session->internals.resumed_extension_int_data[i].set != 0 &&
689 session->internals.resumed_extension_int_data[i].type == type)
691 *data = session->internals.resumed_extension_int_data[i].priv;
692 return 0;
695 return GNUTLS_E_INVALID_REQUEST;