updates in latex build
[gnutls.git] / lib / gnutls_extensions.c
blob42857d015732b9e9e69fca79123e30a702b5433d
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/session_ticket.h>
36 #include <ext/safe_renegotiation.h>
37 #include <ext/signature.h>
38 #include <ext/safe_renegotiation.h>
39 #include <ext/ecc.h>
40 #include <gnutls_num.h>
43 static void _gnutls_ext_unset_resumed_session_data (gnutls_session_t session,
44 uint16_t type);
47 static size_t extfunc_size = 0;
48 static extension_entry_st *extfunc = NULL;
50 static gnutls_ext_parse_type_t
51 _gnutls_ext_parse_type (uint16_t type)
53 size_t i;
55 for (i = 0; i < extfunc_size; i++)
57 if (extfunc[i].type == type)
58 return extfunc[i].parse_type;
61 return GNUTLS_EXT_NONE;
64 static gnutls_ext_recv_func
65 _gnutls_ext_func_recv (uint16_t type, gnutls_ext_parse_type_t parse_type)
67 size_t i;
69 for (i = 0; i < extfunc_size; i++)
70 if (extfunc[i].type == type)
71 if (parse_type == GNUTLS_EXT_ANY || extfunc[i].parse_type == parse_type)
72 return extfunc[i].recv_func;
74 return NULL;
77 static gnutls_ext_deinit_data_func
78 _gnutls_ext_func_deinit (uint16_t type)
80 size_t i;
82 for (i = 0; i < extfunc_size; i++)
83 if (extfunc[i].type == type)
84 return extfunc[i].deinit_func;
86 return NULL;
89 static gnutls_ext_unpack_func
90 _gnutls_ext_func_unpack (uint16_t type)
92 size_t i;
94 for (i = 0; i < extfunc_size; i++)
95 if (extfunc[i].type == type)
96 return extfunc[i].unpack_func;
98 return NULL;
102 static const char *
103 _gnutls_extension_get_name (uint16_t type)
105 size_t i;
107 for (i = 0; i < extfunc_size; i++)
108 if (extfunc[i].type == type)
109 return extfunc[i].name;
111 return NULL;
114 /* Checks if the extension we just received is one of the
115 * requested ones. Otherwise it's a fatal error.
117 static int
118 _gnutls_extension_list_check (gnutls_session_t session, uint16_t type)
120 if (session->security_parameters.entity == GNUTLS_CLIENT)
122 int i;
124 for (i = 0; i < session->internals.extensions_sent_size; i++)
126 if (type == session->internals.extensions_sent[i])
127 return 0; /* ok found */
130 return GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION;
133 return 0;
137 _gnutls_parse_extensions (gnutls_session_t session,
138 gnutls_ext_parse_type_t parse_type,
139 const uint8_t * data, int data_size)
141 int next, ret;
142 int pos = 0;
143 uint16_t type;
144 const uint8_t *sdata;
145 gnutls_ext_recv_func ext_recv;
146 uint16_t size;
148 #ifdef DEBUG
149 int i;
151 if (session->security_parameters.entity == GNUTLS_CLIENT)
152 for (i = 0; i < session->internals.extensions_sent_size; i++)
154 _gnutls_handshake_log ("EXT[%d]: expecting extension '%s'\n",
155 session,
156 _gnutls_extension_get_name
157 (session->internals.extensions_sent[i]));
159 #endif
161 DECR_LENGTH_RET (data_size, 2, 0);
162 next = _gnutls_read_uint16 (data);
163 pos += 2;
165 DECR_LENGTH_RET (data_size, next, 0);
169 DECR_LENGTH_RET (next, 2, 0);
170 type = _gnutls_read_uint16 (&data[pos]);
171 pos += 2;
173 #if 0
174 _gnutls_handshake_log ("EXT[%p]: Found extension '%s/%d'\n", session,
175 _gnutls_extension_get_name (type), type);
176 #endif
178 if ((ret = _gnutls_extension_list_check (session, type)) < 0)
180 gnutls_assert ();
181 return ret;
184 DECR_LENGTH_RET (next, 2, 0);
185 size = _gnutls_read_uint16 (&data[pos]);
186 pos += 2;
188 DECR_LENGTH_RET (next, size, 0);
189 sdata = &data[pos];
190 pos += size;
192 ext_recv = _gnutls_ext_func_recv (type, parse_type);
193 if (ext_recv == NULL)
194 continue;
196 _gnutls_handshake_log ("EXT[%p]: Parsing extension '%s/%d' (%d bytes)\n",
197 session, _gnutls_extension_get_name (type), type,
198 size);
200 if ((ret = ext_recv (session, sdata, size)) < 0)
202 gnutls_assert ();
203 return ret;
207 while (next > 2);
209 return 0;
213 /* Adds the extension we want to send in the extensions list.
214 * This list is used to check whether the (later) received
215 * extensions are the ones we requested.
217 void
218 _gnutls_extension_list_add (gnutls_session_t session, uint16_t type)
221 if (session->security_parameters.entity == GNUTLS_CLIENT)
223 if (session->internals.extensions_sent_size < MAX_EXT_TYPES)
225 session->internals.extensions_sent[session->internals.
226 extensions_sent_size] = type;
227 session->internals.extensions_sent_size++;
229 else
231 _gnutls_handshake_log ("extensions: Increase MAX_EXT_TYPES\n");
237 _gnutls_gen_extensions (gnutls_session_t session, gnutls_buffer_st * extdata,
238 gnutls_ext_parse_type_t parse_type)
240 int size;
241 int pos, size_pos, ret;
242 size_t i, init_size = extdata->length;
244 pos = extdata->length; /* we will store length later on */
245 _gnutls_buffer_append_prefix( extdata, 16, 0);
247 for (i = 0; i < extfunc_size; i++)
249 extension_entry_st *p = &extfunc[i];
251 if (p->send_func == NULL)
252 continue;
254 if (parse_type != GNUTLS_EXT_ANY && p->parse_type != parse_type)
255 continue;
257 ret = _gnutls_buffer_append_prefix( extdata, 16, p->type);
258 if (ret < 0)
259 return gnutls_assert_val(ret);
261 size_pos = extdata->length;
262 ret = _gnutls_buffer_append_prefix (extdata, 16, 0);
263 if (ret < 0)
264 return gnutls_assert_val(ret);
266 size = p->send_func (session, extdata);
267 /* returning GNUTLS_E_INT_RET_0 means to send an empty
268 * extension of this type.
270 if (size > 0 || size == GNUTLS_E_INT_RET_0)
272 if (size == GNUTLS_E_INT_RET_0)
273 size = 0;
275 /* write the real size */
276 _gnutls_write_uint16(size, &extdata->data[size_pos]);
278 /* add this extension to the extension list
280 _gnutls_extension_list_add (session, p->type);
282 _gnutls_handshake_log ("EXT[%p]: Sending extension %s (%d bytes)\n",
283 session, p->name, size);
285 else if (size < 0)
287 gnutls_assert ();
288 return size;
290 else if (size == 0)
291 extdata->length -= 4; /* reset type and size */
294 /* remove any initial data, and the size of the header */
295 size = extdata->length - init_size - 2;
297 if ( size > 0)
298 _gnutls_write_uint16(size, &extdata->data[pos]);
299 else if (size == 0) extdata->length -= 2; /* the length bytes */
301 return size;
305 _gnutls_ext_init (void)
307 int ret;
309 ret = _gnutls_ext_register (&ext_mod_max_record_size);
310 if (ret != GNUTLS_E_SUCCESS)
311 return ret;
313 ret = _gnutls_ext_register (&ext_mod_cert_type);
314 if (ret != GNUTLS_E_SUCCESS)
315 return ret;
318 ret = _gnutls_ext_register (&ext_mod_server_name);
319 if (ret != GNUTLS_E_SUCCESS)
320 return ret;
322 ret = _gnutls_ext_register (&ext_mod_sr);
323 if (ret != GNUTLS_E_SUCCESS)
324 return ret;
326 #ifdef ENABLE_SRP
327 ret = _gnutls_ext_register (&ext_mod_srp);
328 if (ret != GNUTLS_E_SUCCESS)
329 return ret;
330 #endif
332 ret = _gnutls_ext_register (&ext_mod_session_ticket);
333 if (ret != GNUTLS_E_SUCCESS)
334 return ret;
336 ret = _gnutls_ext_register (&ext_mod_supported_ecc);
337 if (ret != GNUTLS_E_SUCCESS)
338 return ret;
340 ret = _gnutls_ext_register (&ext_mod_supported_ecc_pf);
341 if (ret != GNUTLS_E_SUCCESS)
342 return ret;
344 ret = _gnutls_ext_register (&ext_mod_sig);
345 if (ret != GNUTLS_E_SUCCESS)
346 return ret;
348 return GNUTLS_E_SUCCESS;
351 void
352 _gnutls_ext_deinit (void)
354 gnutls_free (extfunc);
355 extfunc = NULL;
356 extfunc_size = 0;
360 _gnutls_ext_register (extension_entry_st * mod)
362 extension_entry_st *p;
364 p = gnutls_realloc (extfunc, sizeof (*extfunc) * (extfunc_size + 1));
365 if (!p)
367 gnutls_assert ();
368 return GNUTLS_E_MEMORY_ERROR;
371 extfunc = p;
373 memcpy (&extfunc[extfunc_size], mod, sizeof (*mod));
375 extfunc_size++;
377 return GNUTLS_E_SUCCESS;
381 _gnutls_ext_pack (gnutls_session_t session, gnutls_buffer_st * packed)
383 unsigned int i;
384 int ret;
385 extension_priv_data_t data;
386 int cur_size;
387 int size_offset;
388 int total_exts_pos;
389 int exts = 0;
391 total_exts_pos = packed->length;
392 BUFFER_APPEND_NUM (packed, 0);
394 for (i = 0; i < extfunc_size; i++)
396 ret = _gnutls_ext_get_session_data (session, extfunc[i].type, &data);
397 if (ret >= 0 && extfunc[i].pack_func != NULL)
399 BUFFER_APPEND_NUM (packed, extfunc[i].type);
401 size_offset = packed->length;
402 BUFFER_APPEND_NUM (packed, 0);
404 cur_size = packed->length;
406 ret = extfunc[i].pack_func (data, packed);
407 if (ret < 0)
409 gnutls_assert ();
410 return ret;
413 exts++;
414 /* write the actual size */
415 _gnutls_write_uint32 (packed->length - cur_size,
416 packed->data + size_offset);
420 _gnutls_write_uint32 (exts, packed->data + total_exts_pos);
422 return 0;
426 void
427 _gnutls_ext_restore_resumed_session (gnutls_session_t session)
429 int i;
432 /* clear everything except MANDATORY extensions */
433 for (i = 0; i < MAX_EXT_TYPES; i++)
435 if (session->internals.extension_int_data[i].set != 0 &&
436 _gnutls_ext_parse_type (session->internals.
437 extension_int_data[i].type) !=
438 GNUTLS_EXT_MANDATORY)
440 _gnutls_ext_unset_session_data (session,
441 session->
442 internals.extension_int_data[i].
443 type);
447 /* copy resumed to main */
448 for (i = 0; i < MAX_EXT_TYPES; i++)
450 if (session->internals.resumed_extension_int_data[i].set != 0 &&
451 _gnutls_ext_parse_type (session->
452 internals.resumed_extension_int_data[i].
453 type) != GNUTLS_EXT_MANDATORY)
455 _gnutls_ext_set_session_data (session,
456 session->
457 internals.resumed_extension_int_data
458 [i].type,
459 session->
460 internals.resumed_extension_int_data
461 [i].priv);
462 session->internals.resumed_extension_int_data[i].set = 0;
469 static void
470 _gnutls_ext_set_resumed_session_data (gnutls_session_t session, uint16_t type,
471 extension_priv_data_t data)
473 int i;
475 for (i = 0; i < MAX_EXT_TYPES; i++)
477 if (session->internals.resumed_extension_int_data[i].type == type
478 || session->internals.resumed_extension_int_data[i].set == 0)
481 if (session->internals.resumed_extension_int_data[i].set != 0)
482 _gnutls_ext_unset_resumed_session_data (session, type);
484 session->internals.resumed_extension_int_data[i].type = type;
485 session->internals.resumed_extension_int_data[i].priv = data;
486 session->internals.resumed_extension_int_data[i].set = 1;
487 return;
493 _gnutls_ext_unpack (gnutls_session_t session, gnutls_buffer_st * packed)
495 int i, ret;
496 extension_priv_data_t data;
497 gnutls_ext_unpack_func unpack;
498 int max_exts = 0;
499 uint16_t type;
500 int size_for_type, cur_pos;
503 BUFFER_POP_NUM (packed, max_exts);
504 for (i = 0; i < max_exts; i++)
506 BUFFER_POP_NUM (packed, type);
507 BUFFER_POP_NUM (packed, size_for_type);
509 cur_pos = packed->length;
511 unpack = _gnutls_ext_func_unpack (type);
512 if (unpack == NULL)
514 gnutls_assert ();
515 return GNUTLS_E_PARSING_ERROR;
518 ret = unpack (packed, &data);
519 if (ret < 0)
521 gnutls_assert ();
522 return ret;
525 /* verify that unpack read the correct bytes */
526 cur_pos = cur_pos - packed->length;
527 if (cur_pos /* read length */ != size_for_type)
529 gnutls_assert ();
530 return GNUTLS_E_PARSING_ERROR;
533 _gnutls_ext_set_resumed_session_data (session, type, data);
536 return 0;
538 error:
539 return ret;
542 void
543 _gnutls_ext_unset_session_data (gnutls_session_t session, uint16_t type)
545 gnutls_ext_deinit_data_func deinit;
546 extension_priv_data_t data;
547 int ret, i;
549 deinit = _gnutls_ext_func_deinit (type);
550 ret = _gnutls_ext_get_session_data (session, type, &data);
552 if (ret >= 0 && deinit != NULL)
554 deinit (data);
557 for (i = 0; i < MAX_EXT_TYPES; i++)
559 if (session->internals.extension_int_data[i].type == type)
561 session->internals.extension_int_data[i].set = 0;
562 return;
568 static void
569 _gnutls_ext_unset_resumed_session_data (gnutls_session_t session,
570 uint16_t type)
572 gnutls_ext_deinit_data_func deinit;
573 extension_priv_data_t data;
574 int ret, i;
576 deinit = _gnutls_ext_func_deinit (type);
577 ret = _gnutls_ext_get_resumed_session_data (session, type, &data);
579 if (ret >= 0 && deinit != NULL)
581 deinit (data);
584 for (i = 0; i < MAX_EXT_TYPES; i++)
586 if (session->internals.resumed_extension_int_data[i].type == type)
588 session->internals.resumed_extension_int_data[i].set = 0;
589 return;
595 /* Deinitializes all data that are associated with TLS extensions.
597 void
598 _gnutls_ext_free_session_data (gnutls_session_t session)
600 unsigned int i;
602 for (i = 0; i < extfunc_size; i++)
604 _gnutls_ext_unset_session_data (session, extfunc[i].type);
607 for (i = 0; i < extfunc_size; i++)
609 _gnutls_ext_unset_resumed_session_data (session, extfunc[i].type);
614 /* This function allows and extension to store data in the current session
615 * and retrieve them later on. We use functions instead of a pointer to a
616 * private pointer, to allow API additions by individual extensions.
618 void
619 _gnutls_ext_set_session_data (gnutls_session_t session, uint16_t type,
620 extension_priv_data_t data)
622 unsigned int i;
623 gnutls_ext_deinit_data_func deinit;
625 deinit = _gnutls_ext_func_deinit (type);
627 for (i = 0; i < MAX_EXT_TYPES; i++)
629 if (session->internals.extension_int_data[i].type == type
630 || session->internals.extension_int_data[i].set == 0)
632 if (session->internals.extension_int_data[i].set != 0)
634 if (deinit)
635 deinit (session->internals.extension_int_data[i].priv);
637 session->internals.extension_int_data[i].type = type;
638 session->internals.extension_int_data[i].priv = data;
639 session->internals.extension_int_data[i].set = 1;
640 return;
646 _gnutls_ext_get_session_data (gnutls_session_t session,
647 uint16_t type, extension_priv_data_t * data)
649 int i;
651 for (i = 0; i < MAX_EXT_TYPES; i++)
653 if (session->internals.extension_int_data[i].set != 0 &&
654 session->internals.extension_int_data[i].type == type)
656 *data = session->internals.extension_int_data[i].priv;
657 return 0;
660 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
664 _gnutls_ext_get_resumed_session_data (gnutls_session_t session,
665 uint16_t type,
666 extension_priv_data_t * data)
668 int i;
670 for (i = 0; i < MAX_EXT_TYPES; i++)
672 if (session->internals.resumed_extension_int_data[i].set != 0 &&
673 session->internals.resumed_extension_int_data[i].type == type)
675 *data = session->internals.resumed_extension_int_data[i].priv;
676 return 0;
679 return GNUTLS_E_INVALID_REQUEST;