corrected typos
[gnutls.git] / lib / gnutls_extensions.c
blob28a852b7d238ebb9ca3763de52c790408fbb348d
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 ret = _gnutls_ext_register (&ext_mod_srtp);
359 if (ret != GNUTLS_E_SUCCESS)
360 return ret;
362 return GNUTLS_E_SUCCESS;
365 void
366 _gnutls_ext_deinit (void)
368 gnutls_free (extfunc);
369 extfunc = NULL;
370 extfunc_size = 0;
374 _gnutls_ext_register (extension_entry_st * mod)
376 extension_entry_st *p;
378 p = gnutls_realloc (extfunc, sizeof (*extfunc) * (extfunc_size + 1));
379 if (!p)
381 gnutls_assert ();
382 return GNUTLS_E_MEMORY_ERROR;
385 extfunc = p;
387 memcpy (&extfunc[extfunc_size], mod, sizeof (*mod));
389 extfunc_size++;
391 return GNUTLS_E_SUCCESS;
395 _gnutls_ext_pack (gnutls_session_t session, gnutls_buffer_st * packed)
397 unsigned int i;
398 int ret;
399 extension_priv_data_t data;
400 int cur_size;
401 int size_offset;
402 int total_exts_pos;
403 int exts = 0;
405 total_exts_pos = packed->length;
406 BUFFER_APPEND_NUM (packed, 0);
408 for (i = 0; i < extfunc_size; i++)
410 ret = _gnutls_ext_get_session_data (session, extfunc[i].type, &data);
411 if (ret >= 0 && extfunc[i].pack_func != NULL)
413 BUFFER_APPEND_NUM (packed, extfunc[i].type);
415 size_offset = packed->length;
416 BUFFER_APPEND_NUM (packed, 0);
418 cur_size = packed->length;
420 ret = extfunc[i].pack_func (data, packed);
421 if (ret < 0)
423 gnutls_assert ();
424 return ret;
427 exts++;
428 /* write the actual size */
429 _gnutls_write_uint32 (packed->length - cur_size,
430 packed->data + size_offset);
434 _gnutls_write_uint32 (exts, packed->data + total_exts_pos);
436 return 0;
440 void
441 _gnutls_ext_restore_resumed_session (gnutls_session_t session)
443 int i;
446 /* clear everything except MANDATORY extensions */
447 for (i = 0; i < MAX_EXT_TYPES; i++)
449 if (session->internals.extension_int_data[i].set != 0 &&
450 _gnutls_ext_parse_type (session->internals.
451 extension_int_data[i].type) !=
452 GNUTLS_EXT_MANDATORY)
454 _gnutls_ext_unset_session_data (session,
455 session->
456 internals.extension_int_data[i].
457 type);
461 /* copy resumed to main */
462 for (i = 0; i < MAX_EXT_TYPES; i++)
464 if (session->internals.resumed_extension_int_data[i].set != 0 &&
465 _gnutls_ext_parse_type (session->
466 internals.resumed_extension_int_data[i].
467 type) != GNUTLS_EXT_MANDATORY)
469 _gnutls_ext_set_session_data (session,
470 session->
471 internals.resumed_extension_int_data
472 [i].type,
473 session->
474 internals.resumed_extension_int_data
475 [i].priv);
476 session->internals.resumed_extension_int_data[i].set = 0;
483 static void
484 _gnutls_ext_set_resumed_session_data (gnutls_session_t session, uint16_t type,
485 extension_priv_data_t data)
487 int i;
489 for (i = 0; i < MAX_EXT_TYPES; i++)
491 if (session->internals.resumed_extension_int_data[i].type == type
492 || session->internals.resumed_extension_int_data[i].set == 0)
495 if (session->internals.resumed_extension_int_data[i].set != 0)
496 _gnutls_ext_unset_resumed_session_data (session, type);
498 session->internals.resumed_extension_int_data[i].type = type;
499 session->internals.resumed_extension_int_data[i].priv = data;
500 session->internals.resumed_extension_int_data[i].set = 1;
501 return;
507 _gnutls_ext_unpack (gnutls_session_t session, gnutls_buffer_st * packed)
509 int i, ret;
510 extension_priv_data_t data;
511 gnutls_ext_unpack_func unpack;
512 int max_exts = 0;
513 uint16_t type;
514 int size_for_type, cur_pos;
517 BUFFER_POP_NUM (packed, max_exts);
518 for (i = 0; i < max_exts; i++)
520 BUFFER_POP_NUM (packed, type);
521 BUFFER_POP_NUM (packed, size_for_type);
523 cur_pos = packed->length;
525 unpack = _gnutls_ext_func_unpack (type);
526 if (unpack == NULL)
528 gnutls_assert ();
529 return GNUTLS_E_PARSING_ERROR;
532 ret = unpack (packed, &data);
533 if (ret < 0)
535 gnutls_assert ();
536 return ret;
539 /* verify that unpack read the correct bytes */
540 cur_pos = cur_pos - packed->length;
541 if (cur_pos /* read length */ != size_for_type)
543 gnutls_assert ();
544 return GNUTLS_E_PARSING_ERROR;
547 _gnutls_ext_set_resumed_session_data (session, type, data);
550 return 0;
552 error:
553 return ret;
556 void
557 _gnutls_ext_unset_session_data (gnutls_session_t session, uint16_t type)
559 gnutls_ext_deinit_data_func deinit;
560 extension_priv_data_t data;
561 int ret, i;
563 deinit = _gnutls_ext_func_deinit (type);
564 ret = _gnutls_ext_get_session_data (session, type, &data);
566 if (ret >= 0 && deinit != NULL)
568 deinit (data);
571 for (i = 0; i < MAX_EXT_TYPES; i++)
573 if (session->internals.extension_int_data[i].type == type)
575 session->internals.extension_int_data[i].set = 0;
576 return;
582 static void
583 _gnutls_ext_unset_resumed_session_data (gnutls_session_t session,
584 uint16_t type)
586 gnutls_ext_deinit_data_func deinit;
587 extension_priv_data_t data;
588 int ret, i;
590 deinit = _gnutls_ext_func_deinit (type);
591 ret = _gnutls_ext_get_resumed_session_data (session, type, &data);
593 if (ret >= 0 && deinit != NULL)
595 deinit (data);
598 for (i = 0; i < MAX_EXT_TYPES; i++)
600 if (session->internals.resumed_extension_int_data[i].type == type)
602 session->internals.resumed_extension_int_data[i].set = 0;
603 return;
609 /* Deinitializes all data that are associated with TLS extensions.
611 void
612 _gnutls_ext_free_session_data (gnutls_session_t session)
614 unsigned int i;
616 for (i = 0; i < extfunc_size; i++)
618 _gnutls_ext_unset_session_data (session, extfunc[i].type);
621 for (i = 0; i < extfunc_size; i++)
623 _gnutls_ext_unset_resumed_session_data (session, extfunc[i].type);
628 /* This function allows and extension to store data in the current session
629 * and retrieve them later on. We use functions instead of a pointer to a
630 * private pointer, to allow API additions by individual extensions.
632 void
633 _gnutls_ext_set_session_data (gnutls_session_t session, uint16_t type,
634 extension_priv_data_t data)
636 unsigned int i;
637 gnutls_ext_deinit_data_func deinit;
639 deinit = _gnutls_ext_func_deinit (type);
641 for (i = 0; i < MAX_EXT_TYPES; i++)
643 if (session->internals.extension_int_data[i].type == type
644 || session->internals.extension_int_data[i].set == 0)
646 if (session->internals.extension_int_data[i].set != 0)
648 if (deinit)
649 deinit (session->internals.extension_int_data[i].priv);
651 session->internals.extension_int_data[i].type = type;
652 session->internals.extension_int_data[i].priv = data;
653 session->internals.extension_int_data[i].set = 1;
654 return;
660 _gnutls_ext_get_session_data (gnutls_session_t session,
661 uint16_t type, extension_priv_data_t * data)
663 int i;
665 for (i = 0; i < MAX_EXT_TYPES; i++)
667 if (session->internals.extension_int_data[i].set != 0 &&
668 session->internals.extension_int_data[i].type == type)
670 *data = session->internals.extension_int_data[i].priv;
671 return 0;
674 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
678 _gnutls_ext_get_resumed_session_data (gnutls_session_t session,
679 uint16_t type,
680 extension_priv_data_t * data)
682 int i;
684 for (i = 0; i < MAX_EXT_TYPES; i++)
686 if (session->internals.resumed_extension_int_data[i].set != 0 &&
687 session->internals.resumed_extension_int_data[i].type == type)
689 *data = session->internals.resumed_extension_int_data[i].priv;
690 return 0;
693 return GNUTLS_E_INVALID_REQUEST;