documented fix
[gnutls.git] / lib / gnutls_extensions.c
blobeb07d28621635de5ff0e3999b7baaa1e84d2e3f2
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 <gnutls_num.h>
44 static void _gnutls_ext_unset_resumed_session_data (gnutls_session_t session,
45 uint16_t type);
48 static size_t extfunc_size = 0;
49 static extension_entry_st *extfunc = NULL;
51 static gnutls_ext_parse_type_t
52 _gnutls_ext_parse_type (uint16_t type)
54 size_t i;
56 for (i = 0; i < extfunc_size; i++)
58 if (extfunc[i].type == type)
59 return extfunc[i].parse_type;
62 return GNUTLS_EXT_NONE;
65 static gnutls_ext_recv_func
66 _gnutls_ext_func_recv (uint16_t type, gnutls_ext_parse_type_t parse_type)
68 size_t i;
70 for (i = 0; i < extfunc_size; i++)
71 if (extfunc[i].type == type)
72 if (parse_type == GNUTLS_EXT_ANY || extfunc[i].parse_type == parse_type)
73 return extfunc[i].recv_func;
75 return NULL;
78 static gnutls_ext_deinit_data_func
79 _gnutls_ext_func_deinit (uint16_t type)
81 size_t i;
83 for (i = 0; i < extfunc_size; i++)
84 if (extfunc[i].type == type)
85 return extfunc[i].deinit_func;
87 return NULL;
90 static gnutls_ext_unpack_func
91 _gnutls_ext_func_unpack (uint16_t type)
93 size_t i;
95 for (i = 0; i < extfunc_size; i++)
96 if (extfunc[i].type == type)
97 return extfunc[i].unpack_func;
99 return NULL;
103 static const char *
104 _gnutls_extension_get_name (uint16_t type)
106 size_t i;
108 for (i = 0; i < extfunc_size; i++)
109 if (extfunc[i].type == type)
110 return extfunc[i].name;
112 return NULL;
115 /* Checks if the extension we just received is one of the
116 * requested ones. Otherwise it's a fatal error.
118 static int
119 _gnutls_extension_list_check (gnutls_session_t session, uint16_t type)
121 if (session->security_parameters.entity == GNUTLS_CLIENT)
123 int i;
125 for (i = 0; i < session->internals.extensions_sent_size; i++)
127 if (type == session->internals.extensions_sent[i])
128 return 0; /* ok found */
131 return GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION;
134 return 0;
138 _gnutls_parse_extensions (gnutls_session_t session,
139 gnutls_ext_parse_type_t parse_type,
140 const uint8_t * data, int data_size)
142 int next, ret;
143 int pos = 0;
144 uint16_t type;
145 const uint8_t *sdata;
146 gnutls_ext_recv_func ext_recv;
147 uint16_t size;
149 #ifdef DEBUG
150 int i;
152 if (session->security_parameters.entity == GNUTLS_CLIENT)
153 for (i = 0; i < session->internals.extensions_sent_size; i++)
155 _gnutls_handshake_log ("EXT[%d]: expecting extension '%s'\n",
156 session,
157 _gnutls_extension_get_name
158 (session->internals.extensions_sent[i]));
160 #endif
162 DECR_LENGTH_RET (data_size, 2, 0);
163 next = _gnutls_read_uint16 (data);
164 pos += 2;
166 DECR_LENGTH_RET (data_size, next, 0);
170 DECR_LENGTH_RET (next, 2, 0);
171 type = _gnutls_read_uint16 (&data[pos]);
172 pos += 2;
174 #if 0
175 _gnutls_handshake_log ("EXT[%p]: Found extension '%s/%d'\n", session,
176 _gnutls_extension_get_name (type), type);
177 #endif
179 if ((ret = _gnutls_extension_list_check (session, type)) < 0)
181 gnutls_assert ();
182 return ret;
185 DECR_LENGTH_RET (next, 2, 0);
186 size = _gnutls_read_uint16 (&data[pos]);
187 pos += 2;
189 DECR_LENGTH_RET (next, size, 0);
190 sdata = &data[pos];
191 pos += size;
193 ext_recv = _gnutls_ext_func_recv (type, parse_type);
194 if (ext_recv == NULL)
195 continue;
197 _gnutls_handshake_log ("EXT[%p]: Parsing extension '%s/%d' (%d bytes)\n",
198 session, _gnutls_extension_get_name (type), type,
199 size);
201 if ((ret = ext_recv (session, sdata, size)) < 0)
203 gnutls_assert ();
204 return ret;
208 while (next > 2);
210 return 0;
214 /* Adds the extension we want to send in the extensions list.
215 * This list is used to check whether the (later) received
216 * extensions are the ones we requested.
218 void
219 _gnutls_extension_list_add (gnutls_session_t session, uint16_t type)
222 if (session->security_parameters.entity == GNUTLS_CLIENT)
224 if (session->internals.extensions_sent_size < MAX_EXT_TYPES)
226 session->internals.extensions_sent[session->internals.
227 extensions_sent_size] = type;
228 session->internals.extensions_sent_size++;
230 else
232 _gnutls_handshake_log ("extensions: Increase MAX_EXT_TYPES\n");
238 _gnutls_gen_extensions (gnutls_session_t session, gnutls_buffer_st * extdata,
239 gnutls_ext_parse_type_t parse_type)
241 int size;
242 int pos, size_pos, ret;
243 size_t i, init_size = extdata->length;
245 pos = extdata->length; /* we will store length later on */
246 _gnutls_buffer_append_prefix( extdata, 16, 0);
248 for (i = 0; i < extfunc_size; i++)
250 extension_entry_st *p = &extfunc[i];
252 if (p->send_func == NULL)
253 continue;
255 if (parse_type != GNUTLS_EXT_ANY && p->parse_type != parse_type)
256 continue;
258 ret = _gnutls_buffer_append_prefix( extdata, 16, p->type);
259 if (ret < 0)
260 return gnutls_assert_val(ret);
262 size_pos = extdata->length;
263 ret = _gnutls_buffer_append_prefix (extdata, 16, 0);
264 if (ret < 0)
265 return gnutls_assert_val(ret);
267 size = p->send_func (session, extdata);
268 /* returning GNUTLS_E_INT_RET_0 means to send an empty
269 * extension of this type.
271 if (size > 0 || size == GNUTLS_E_INT_RET_0)
273 if (size == GNUTLS_E_INT_RET_0)
274 size = 0;
276 /* write the real size */
277 _gnutls_write_uint16(size, &extdata->data[size_pos]);
279 /* add this extension to the extension list
281 _gnutls_extension_list_add (session, p->type);
283 _gnutls_handshake_log ("EXT[%p]: Sending extension %s (%d bytes)\n",
284 session, p->name, size);
286 else if (size < 0)
288 gnutls_assert ();
289 return size;
291 else if (size == 0)
292 extdata->length -= 4; /* reset type and size */
295 /* remove any initial data, and the size of the header */
296 size = extdata->length - init_size - 2;
298 if ( size > 0)
299 _gnutls_write_uint16(size, &extdata->data[pos]);
300 else if (size == 0) extdata->length -= 2; /* the length bytes */
302 return size;
306 _gnutls_ext_init (void)
308 int ret;
310 ret = _gnutls_ext_register (&ext_mod_max_record_size);
311 if (ret != GNUTLS_E_SUCCESS)
312 return ret;
314 ret = _gnutls_ext_register (&ext_mod_cert_type);
315 if (ret != GNUTLS_E_SUCCESS)
316 return ret;
319 ret = _gnutls_ext_register (&ext_mod_server_name);
320 if (ret != GNUTLS_E_SUCCESS)
321 return ret;
323 ret = _gnutls_ext_register (&ext_mod_sr);
324 if (ret != GNUTLS_E_SUCCESS)
325 return ret;
327 #ifdef ENABLE_SRP
328 ret = _gnutls_ext_register (&ext_mod_srp);
329 if (ret != GNUTLS_E_SUCCESS)
330 return ret;
331 #endif
333 ret = _gnutls_ext_register (&ext_mod_heartbeat);
334 if (ret != GNUTLS_E_SUCCESS)
335 return ret;
337 ret = _gnutls_ext_register (&ext_mod_session_ticket);
338 if (ret != GNUTLS_E_SUCCESS)
339 return ret;
341 ret = _gnutls_ext_register (&ext_mod_supported_ecc);
342 if (ret != GNUTLS_E_SUCCESS)
343 return ret;
345 ret = _gnutls_ext_register (&ext_mod_supported_ecc_pf);
346 if (ret != GNUTLS_E_SUCCESS)
347 return ret;
349 ret = _gnutls_ext_register (&ext_mod_sig);
350 if (ret != GNUTLS_E_SUCCESS)
351 return ret;
353 return GNUTLS_E_SUCCESS;
356 void
357 _gnutls_ext_deinit (void)
359 gnutls_free (extfunc);
360 extfunc = NULL;
361 extfunc_size = 0;
365 _gnutls_ext_register (extension_entry_st * mod)
367 extension_entry_st *p;
369 p = gnutls_realloc (extfunc, sizeof (*extfunc) * (extfunc_size + 1));
370 if (!p)
372 gnutls_assert ();
373 return GNUTLS_E_MEMORY_ERROR;
376 extfunc = p;
378 memcpy (&extfunc[extfunc_size], mod, sizeof (*mod));
380 extfunc_size++;
382 return GNUTLS_E_SUCCESS;
386 _gnutls_ext_pack (gnutls_session_t session, gnutls_buffer_st * packed)
388 unsigned int i;
389 int ret;
390 extension_priv_data_t data;
391 int cur_size;
392 int size_offset;
393 int total_exts_pos;
394 int exts = 0;
396 total_exts_pos = packed->length;
397 BUFFER_APPEND_NUM (packed, 0);
399 for (i = 0; i < extfunc_size; i++)
401 ret = _gnutls_ext_get_session_data (session, extfunc[i].type, &data);
402 if (ret >= 0 && extfunc[i].pack_func != NULL)
404 BUFFER_APPEND_NUM (packed, extfunc[i].type);
406 size_offset = packed->length;
407 BUFFER_APPEND_NUM (packed, 0);
409 cur_size = packed->length;
411 ret = extfunc[i].pack_func (data, packed);
412 if (ret < 0)
414 gnutls_assert ();
415 return ret;
418 exts++;
419 /* write the actual size */
420 _gnutls_write_uint32 (packed->length - cur_size,
421 packed->data + size_offset);
425 _gnutls_write_uint32 (exts, packed->data + total_exts_pos);
427 return 0;
431 void
432 _gnutls_ext_restore_resumed_session (gnutls_session_t session)
434 int i;
437 /* clear everything except MANDATORY extensions */
438 for (i = 0; i < MAX_EXT_TYPES; i++)
440 if (session->internals.extension_int_data[i].set != 0 &&
441 _gnutls_ext_parse_type (session->internals.
442 extension_int_data[i].type) !=
443 GNUTLS_EXT_MANDATORY)
445 _gnutls_ext_unset_session_data (session,
446 session->
447 internals.extension_int_data[i].
448 type);
452 /* copy resumed to main */
453 for (i = 0; i < MAX_EXT_TYPES; i++)
455 if (session->internals.resumed_extension_int_data[i].set != 0 &&
456 _gnutls_ext_parse_type (session->
457 internals.resumed_extension_int_data[i].
458 type) != GNUTLS_EXT_MANDATORY)
460 _gnutls_ext_set_session_data (session,
461 session->
462 internals.resumed_extension_int_data
463 [i].type,
464 session->
465 internals.resumed_extension_int_data
466 [i].priv);
467 session->internals.resumed_extension_int_data[i].set = 0;
474 static void
475 _gnutls_ext_set_resumed_session_data (gnutls_session_t session, uint16_t type,
476 extension_priv_data_t data)
478 int i;
480 for (i = 0; i < MAX_EXT_TYPES; i++)
482 if (session->internals.resumed_extension_int_data[i].type == type
483 || session->internals.resumed_extension_int_data[i].set == 0)
486 if (session->internals.resumed_extension_int_data[i].set != 0)
487 _gnutls_ext_unset_resumed_session_data (session, type);
489 session->internals.resumed_extension_int_data[i].type = type;
490 session->internals.resumed_extension_int_data[i].priv = data;
491 session->internals.resumed_extension_int_data[i].set = 1;
492 return;
498 _gnutls_ext_unpack (gnutls_session_t session, gnutls_buffer_st * packed)
500 int i, ret;
501 extension_priv_data_t data;
502 gnutls_ext_unpack_func unpack;
503 int max_exts = 0;
504 uint16_t type;
505 int size_for_type, cur_pos;
508 BUFFER_POP_NUM (packed, max_exts);
509 for (i = 0; i < max_exts; i++)
511 BUFFER_POP_NUM (packed, type);
512 BUFFER_POP_NUM (packed, size_for_type);
514 cur_pos = packed->length;
516 unpack = _gnutls_ext_func_unpack (type);
517 if (unpack == NULL)
519 gnutls_assert ();
520 return GNUTLS_E_PARSING_ERROR;
523 ret = unpack (packed, &data);
524 if (ret < 0)
526 gnutls_assert ();
527 return ret;
530 /* verify that unpack read the correct bytes */
531 cur_pos = cur_pos - packed->length;
532 if (cur_pos /* read length */ != size_for_type)
534 gnutls_assert ();
535 return GNUTLS_E_PARSING_ERROR;
538 _gnutls_ext_set_resumed_session_data (session, type, data);
541 return 0;
543 error:
544 return ret;
547 void
548 _gnutls_ext_unset_session_data (gnutls_session_t session, uint16_t type)
550 gnutls_ext_deinit_data_func deinit;
551 extension_priv_data_t data;
552 int ret, i;
554 deinit = _gnutls_ext_func_deinit (type);
555 ret = _gnutls_ext_get_session_data (session, type, &data);
557 if (ret >= 0 && deinit != NULL)
559 deinit (data);
562 for (i = 0; i < MAX_EXT_TYPES; i++)
564 if (session->internals.extension_int_data[i].type == type)
566 session->internals.extension_int_data[i].set = 0;
567 return;
573 static void
574 _gnutls_ext_unset_resumed_session_data (gnutls_session_t session,
575 uint16_t type)
577 gnutls_ext_deinit_data_func deinit;
578 extension_priv_data_t data;
579 int ret, i;
581 deinit = _gnutls_ext_func_deinit (type);
582 ret = _gnutls_ext_get_resumed_session_data (session, type, &data);
584 if (ret >= 0 && deinit != NULL)
586 deinit (data);
589 for (i = 0; i < MAX_EXT_TYPES; i++)
591 if (session->internals.resumed_extension_int_data[i].type == type)
593 session->internals.resumed_extension_int_data[i].set = 0;
594 return;
600 /* Deinitializes all data that are associated with TLS extensions.
602 void
603 _gnutls_ext_free_session_data (gnutls_session_t session)
605 unsigned int i;
607 for (i = 0; i < extfunc_size; i++)
609 _gnutls_ext_unset_session_data (session, extfunc[i].type);
612 for (i = 0; i < extfunc_size; i++)
614 _gnutls_ext_unset_resumed_session_data (session, extfunc[i].type);
619 /* This function allows and extension to store data in the current session
620 * and retrieve them later on. We use functions instead of a pointer to a
621 * private pointer, to allow API additions by individual extensions.
623 void
624 _gnutls_ext_set_session_data (gnutls_session_t session, uint16_t type,
625 extension_priv_data_t data)
627 unsigned int i;
628 gnutls_ext_deinit_data_func deinit;
630 deinit = _gnutls_ext_func_deinit (type);
632 for (i = 0; i < MAX_EXT_TYPES; i++)
634 if (session->internals.extension_int_data[i].type == type
635 || session->internals.extension_int_data[i].set == 0)
637 if (session->internals.extension_int_data[i].set != 0)
639 if (deinit)
640 deinit (session->internals.extension_int_data[i].priv);
642 session->internals.extension_int_data[i].type = type;
643 session->internals.extension_int_data[i].priv = data;
644 session->internals.extension_int_data[i].set = 1;
645 return;
651 _gnutls_ext_get_session_data (gnutls_session_t session,
652 uint16_t type, extension_priv_data_t * data)
654 int i;
656 for (i = 0; i < MAX_EXT_TYPES; i++)
658 if (session->internals.extension_int_data[i].set != 0 &&
659 session->internals.extension_int_data[i].type == type)
661 *data = session->internals.extension_int_data[i].priv;
662 return 0;
665 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
669 _gnutls_ext_get_resumed_session_data (gnutls_session_t session,
670 uint16_t type,
671 extension_priv_data_t * data)
673 int i;
675 for (i = 0; i < MAX_EXT_TYPES; i++)
677 if (session->internals.resumed_extension_int_data[i].set != 0 &&
678 session->internals.resumed_extension_int_data[i].type == type)
680 *data = session->internals.resumed_extension_int_data[i].priv;
681 return 0;
684 return GNUTLS_E_INVALID_REQUEST;