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 2.1 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>
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>
41 #include <ext/status_request.h>
44 #include <ext/dumbfw.h>
45 #include <gnutls_num.h>
48 static void _gnutls_ext_unset_resumed_session_data(gnutls_session_t
49 session, uint16_t type);
52 static size_t extfunc_size = 0;
53 static extension_entry_st *extfunc = NULL;
55 static gnutls_ext_parse_type_t _gnutls_ext_parse_type(uint16_t type)
59 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)
72 for (i = 0; i < extfunc_size; i++)
73 if (extfunc[i].type == type)
74 if (parse_type == GNUTLS_EXT_ANY
75 || extfunc[i].parse_type == parse_type)
76 return extfunc[i].recv_func;
81 static gnutls_ext_deinit_data_func _gnutls_ext_func_deinit(uint16_t type)
85 for (i = 0; i < extfunc_size; i++)
86 if (extfunc[i].type == type)
87 return extfunc[i].deinit_func;
92 static gnutls_ext_unpack_func _gnutls_ext_func_unpack(uint16_t type)
96 for (i = 0; i < extfunc_size; i++)
97 if (extfunc[i].type == type)
98 return extfunc[i].unpack_func;
104 static const char *_gnutls_extension_get_name(uint16_t type)
108 for (i = 0; i < extfunc_size; i++)
109 if (extfunc[i].type == type)
110 return extfunc[i].name;
115 /* Checks if the extension we just received is one of the
116 * requested ones. Otherwise it's a fatal error.
119 _gnutls_extension_list_check(gnutls_session_t session, uint16_t type)
121 if (session->security_parameters.entity == GNUTLS_CLIENT) {
124 for (i = 0; i < session->internals.extensions_sent_size;
126 if (type == session->internals.extensions_sent[i])
127 return 0; /* ok found */
130 return GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION;
137 _gnutls_parse_extensions(gnutls_session_t session,
138 gnutls_ext_parse_type_t parse_type,
139 const uint8_t * data, int data_size)
144 const uint8_t *sdata;
145 gnutls_ext_recv_func ext_recv;
151 if (session->security_parameters.entity == GNUTLS_CLIENT)
152 for (i = 0; i < session->internals.extensions_sent_size;
154 _gnutls_handshake_log
155 ("EXT[%d]: expecting extension '%s'\n",
157 _gnutls_extension_get_name(session->internals.
163 DECR_LENGTH_RET(data_size, 2, 0);
164 next = _gnutls_read_uint16(data);
167 DECR_LENGTH_RET(data_size, next, 0);
170 DECR_LENGTH_RET(next, 2, 0);
171 type = _gnutls_read_uint16(&data[pos]);
175 _gnutls_extension_list_check(session, type)) < 0) {
180 DECR_LENGTH_RET(next, 2, 0);
181 size = _gnutls_read_uint16(&data[pos]);
184 DECR_LENGTH_RET(next, size, 0);
188 ext_recv = _gnutls_ext_func_recv(type, parse_type);
189 if (ext_recv == NULL) {
190 _gnutls_handshake_log
191 ("EXT[%p]: Found extension '%s/%d'\n", session,
192 _gnutls_extension_get_name(type), type);
197 _gnutls_handshake_log
198 ("EXT[%p]: Parsing extension '%s/%d' (%d bytes)\n",
199 session, _gnutls_extension_get_name(type), type,
202 if ((ret = ext_recv(session, sdata, size)) < 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 _gnutls_extension_list_add(gnutls_session_t session, uint16_t type)
221 if (session->security_parameters.entity == GNUTLS_CLIENT) {
222 if (session->internals.extensions_sent_size <
224 session->internals.extensions_sent[session->
225 internals.extensions_sent_size]
227 session->internals.extensions_sent_size++;
229 _gnutls_handshake_log
230 ("extensions: Increase MAX_EXT_TYPES\n");
236 _gnutls_gen_extensions(gnutls_session_t session,
237 gnutls_buffer_st * extdata,
238 gnutls_ext_parse_type_t parse_type)
241 int pos, size_pos, ret;
242 size_t i, init_size = extdata->length;
244 pos = extdata->length; /* we will store length later on */
246 ret = _gnutls_buffer_append_prefix(extdata, 16, 0);
248 return gnutls_assert_val(ret);
250 for (i = 0; i < extfunc_size; i++) {
251 extension_entry_st *p = &extfunc[i];
253 if (p->send_func == NULL)
256 if (parse_type != GNUTLS_EXT_ANY
257 && p->parse_type != parse_type)
260 ret = _gnutls_buffer_append_prefix(extdata, 16, p->type);
262 return gnutls_assert_val(ret);
264 size_pos = extdata->length;
265 ret = _gnutls_buffer_append_prefix(extdata, 16, 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) {
274 if (size == GNUTLS_E_INT_RET_0)
277 /* write the real size */
278 _gnutls_write_uint16(size,
279 &extdata->data[size_pos]);
281 /* add this extension to the extension list
283 _gnutls_extension_list_add(session, p->type);
285 _gnutls_handshake_log
286 ("EXT[%p]: Sending extension %s (%d bytes)\n",
287 session, p->name, size);
288 } else if (size < 0) {
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;
299 _gnutls_write_uint16(size, &extdata->data[pos]);
301 extdata->length -= 2; /* the length bytes */
306 int _gnutls_ext_init(void)
310 ret = _gnutls_ext_register(&ext_mod_max_record_size);
311 if (ret != GNUTLS_E_SUCCESS)
315 ret = _gnutls_ext_register(&ext_mod_status_request);
316 if (ret != GNUTLS_E_SUCCESS)
320 #ifdef ENABLE_OPENPGP
321 ret = _gnutls_ext_register(&ext_mod_cert_type);
322 if (ret != GNUTLS_E_SUCCESS)
326 ret = _gnutls_ext_register(&ext_mod_server_name);
327 if (ret != GNUTLS_E_SUCCESS)
330 ret = _gnutls_ext_register(&ext_mod_sr);
331 if (ret != GNUTLS_E_SUCCESS)
335 ret = _gnutls_ext_register(&ext_mod_srp);
336 if (ret != GNUTLS_E_SUCCESS)
340 #ifdef ENABLE_HEARTBEAT
341 ret = _gnutls_ext_register(&ext_mod_heartbeat);
342 if (ret != GNUTLS_E_SUCCESS)
346 #ifdef ENABLE_SESSION_TICKETS
347 ret = _gnutls_ext_register(&ext_mod_session_ticket);
348 if (ret != GNUTLS_E_SUCCESS)
352 ret = _gnutls_ext_register(&ext_mod_supported_ecc);
353 if (ret != GNUTLS_E_SUCCESS)
356 ret = _gnutls_ext_register(&ext_mod_supported_ecc_pf);
357 if (ret != GNUTLS_E_SUCCESS)
360 ret = _gnutls_ext_register(&ext_mod_sig);
361 if (ret != GNUTLS_E_SUCCESS)
364 #ifdef ENABLE_DTLS_SRTP
365 ret = _gnutls_ext_register(&ext_mod_srtp);
366 if (ret != GNUTLS_E_SUCCESS)
371 ret = _gnutls_ext_register(&ext_mod_alpn);
372 if (ret != GNUTLS_E_SUCCESS)
376 /* This must be the last extension registered.
378 ret = _gnutls_ext_register(&ext_mod_dumbfw);
379 if (ret != GNUTLS_E_SUCCESS)
382 return GNUTLS_E_SUCCESS;
385 void _gnutls_ext_deinit(void)
387 gnutls_free(extfunc);
392 int _gnutls_ext_register(extension_entry_st * mod)
394 extension_entry_st *p;
396 p = gnutls_realloc_fast(extfunc,
397 sizeof(*extfunc) * (extfunc_size + 1));
400 return GNUTLS_E_MEMORY_ERROR;
405 memcpy(&extfunc[extfunc_size], mod, sizeof(*mod));
409 return GNUTLS_E_SUCCESS;
412 int _gnutls_ext_before_epoch_change(gnutls_session_t session)
417 for (i = 0; i < extfunc_size; i++) {
418 if (extfunc[i].epoch_func != NULL) {
419 ret = extfunc[i].epoch_func(session);
421 return gnutls_assert_val(ret);
429 int _gnutls_ext_pack(gnutls_session_t session, gnutls_buffer_st * packed)
433 extension_priv_data_t data;
439 total_exts_pos = packed->length;
440 BUFFER_APPEND_NUM(packed, 0);
442 for (i = 0; i < extfunc_size; i++) {
444 _gnutls_ext_get_session_data(session, extfunc[i].type,
446 if (ret >= 0 && extfunc[i].pack_func != NULL) {
447 BUFFER_APPEND_NUM(packed, extfunc[i].type);
449 size_offset = packed->length;
450 BUFFER_APPEND_NUM(packed, 0);
452 cur_size = packed->length;
454 ret = extfunc[i].pack_func(data, packed);
461 /* write the actual size */
462 _gnutls_write_uint32(packed->length - cur_size,
463 packed->data + size_offset);
467 _gnutls_write_uint32(exts, packed->data + total_exts_pos);
472 void _gnutls_ext_restore_resumed_session(gnutls_session_t session)
477 /* clear everything except MANDATORY extensions */
478 for (i = 0; i < MAX_EXT_TYPES; i++) {
479 if (session->internals.extension_int_data[i].set != 0 &&
480 _gnutls_ext_parse_type(session->
481 internals.extension_int_data[i].
482 type) != GNUTLS_EXT_MANDATORY) {
483 _gnutls_ext_unset_session_data(session,
490 /* copy resumed to main */
491 for (i = 0; i < MAX_EXT_TYPES; i++) {
492 if (session->internals.resumed_extension_int_data[i].set !=
494 && _gnutls_ext_parse_type(session->internals.
495 resumed_extension_int_data
497 GNUTLS_EXT_MANDATORY) {
498 _gnutls_ext_set_session_data(session,
500 resumed_extension_int_data
503 resumed_extension_int_data
505 session->internals.resumed_extension_int_data[i].
514 _gnutls_ext_set_resumed_session_data(gnutls_session_t session,
516 extension_priv_data_t data)
520 for (i = 0; i < MAX_EXT_TYPES; i++) {
521 if (session->internals.resumed_extension_int_data[i].
523 || session->internals.resumed_extension_int_data[i].
526 if (session->internals.
527 resumed_extension_int_data[i].set != 0)
528 _gnutls_ext_unset_resumed_session_data
531 session->internals.resumed_extension_int_data[i].
533 session->internals.resumed_extension_int_data[i].
535 session->internals.resumed_extension_int_data[i].
542 int _gnutls_ext_unpack(gnutls_session_t session, gnutls_buffer_st * packed)
545 extension_priv_data_t data;
546 gnutls_ext_unpack_func unpack;
549 int size_for_type, cur_pos;
552 BUFFER_POP_NUM(packed, max_exts);
553 for (i = 0; i < max_exts; i++) {
554 BUFFER_POP_NUM(packed, type);
555 BUFFER_POP_NUM(packed, size_for_type);
557 cur_pos = packed->length;
559 unpack = _gnutls_ext_func_unpack(type);
560 if (unpack == NULL) {
562 return GNUTLS_E_PARSING_ERROR;
565 ret = unpack(packed, &data);
571 /* verify that unpack read the correct bytes */
572 cur_pos = cur_pos - packed->length;
573 if (cur_pos /* read length */ != size_for_type) {
575 return GNUTLS_E_PARSING_ERROR;
578 _gnutls_ext_set_resumed_session_data(session, type, data);
588 _gnutls_ext_unset_session_data(gnutls_session_t session, uint16_t type)
590 gnutls_ext_deinit_data_func deinit;
591 extension_priv_data_t data;
594 deinit = _gnutls_ext_func_deinit(type);
595 ret = _gnutls_ext_get_session_data(session, type, &data);
597 if (ret >= 0 && deinit != NULL) {
601 for (i = 0; i < MAX_EXT_TYPES; i++) {
602 if (session->internals.extension_int_data[i].type == type) {
603 session->internals.extension_int_data[i].set = 0;
611 _gnutls_ext_unset_resumed_session_data(gnutls_session_t session,
614 gnutls_ext_deinit_data_func deinit;
615 extension_priv_data_t data;
618 deinit = _gnutls_ext_func_deinit(type);
619 ret = _gnutls_ext_get_resumed_session_data(session, type, &data);
621 if (ret >= 0 && deinit != NULL) {
625 for (i = 0; i < MAX_EXT_TYPES; i++) {
626 if (session->internals.resumed_extension_int_data[i].
628 session->internals.resumed_extension_int_data[i].
636 /* Deinitializes all data that are associated with TLS extensions.
638 void _gnutls_ext_free_session_data(gnutls_session_t session)
642 for (i = 0; i < extfunc_size; i++) {
643 _gnutls_ext_unset_session_data(session, extfunc[i].type);
646 for (i = 0; i < extfunc_size; i++) {
647 _gnutls_ext_unset_resumed_session_data(session,
653 /* This function allows and extension to store data in the current session
654 * and retrieve them later on. We use functions instead of a pointer to a
655 * private pointer, to allow API additions by individual extensions.
658 _gnutls_ext_set_session_data(gnutls_session_t session, uint16_t type,
659 extension_priv_data_t data)
662 gnutls_ext_deinit_data_func deinit;
664 deinit = _gnutls_ext_func_deinit(type);
666 for (i = 0; i < MAX_EXT_TYPES; i++) {
667 if (session->internals.extension_int_data[i].type == type
668 || session->internals.extension_int_data[i].set == 0) {
669 if (session->internals.extension_int_data[i].set !=
672 deinit(session->internals.
673 extension_int_data[i].priv);
675 session->internals.extension_int_data[i].type =
677 session->internals.extension_int_data[i].priv =
679 session->internals.extension_int_data[i].set = 1;
686 _gnutls_ext_get_session_data(gnutls_session_t session,
687 uint16_t type, extension_priv_data_t * data)
691 for (i = 0; i < MAX_EXT_TYPES; i++) {
692 if (session->internals.extension_int_data[i].set != 0 &&
693 session->internals.extension_int_data[i].type == type)
696 session->internals.extension_int_data[i].priv;
700 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
704 _gnutls_ext_get_resumed_session_data(gnutls_session_t session,
706 extension_priv_data_t * data)
710 for (i = 0; i < MAX_EXT_TYPES; i++) {
711 if (session->internals.resumed_extension_int_data[i].set !=
713 && session->internals.resumed_extension_int_data[i].
717 resumed_extension_int_data[i].priv;
721 return GNUTLS_E_INVALID_REQUEST;