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>
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>
42 #include <gnutls_num.h>
45 static void _gnutls_ext_unset_resumed_session_data (gnutls_session_t session
,
49 static size_t extfunc_size
= 0;
50 static extension_entry_st
*extfunc
= NULL
;
52 static gnutls_ext_parse_type_t
53 _gnutls_ext_parse_type (uint16_t type
)
57 for (i
= 0; i
< extfunc_size
; i
++)
59 if (extfunc
[i
].type
== type
)
60 return extfunc
[i
].parse_type
;
63 return GNUTLS_EXT_NONE
;
66 static gnutls_ext_recv_func
67 _gnutls_ext_func_recv (uint16_t type
, gnutls_ext_parse_type_t parse_type
)
71 for (i
= 0; i
< extfunc_size
; i
++)
72 if (extfunc
[i
].type
== type
)
73 if (parse_type
== GNUTLS_EXT_ANY
|| extfunc
[i
].parse_type
== parse_type
)
74 return extfunc
[i
].recv_func
;
79 static gnutls_ext_deinit_data_func
80 _gnutls_ext_func_deinit (uint16_t type
)
84 for (i
= 0; i
< extfunc_size
; i
++)
85 if (extfunc
[i
].type
== type
)
86 return extfunc
[i
].deinit_func
;
91 static gnutls_ext_unpack_func
92 _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
;
105 _gnutls_extension_get_name (uint16_t type
)
109 for (i
= 0; i
< extfunc_size
; i
++)
110 if (extfunc
[i
].type
== type
)
111 return extfunc
[i
].name
;
116 /* Checks if the extension we just received is one of the
117 * requested ones. Otherwise it's a fatal error.
120 _gnutls_extension_list_check (gnutls_session_t session
, uint16_t type
)
122 if (session
->security_parameters
.entity
== GNUTLS_CLIENT
)
126 for (i
= 0; i
< session
->internals
.extensions_sent_size
; i
++)
128 if (type
== session
->internals
.extensions_sent
[i
])
129 return 0; /* ok found */
132 return GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION
;
139 _gnutls_parse_extensions (gnutls_session_t session
,
140 gnutls_ext_parse_type_t parse_type
,
141 const uint8_t * data
, int data_size
)
146 const uint8_t *sdata
;
147 gnutls_ext_recv_func ext_recv
;
153 if (session
->security_parameters
.entity
== GNUTLS_CLIENT
)
154 for (i
= 0; i
< session
->internals
.extensions_sent_size
; i
++)
156 _gnutls_handshake_log ("EXT[%d]: expecting extension '%s'\n",
158 _gnutls_extension_get_name
159 (session
->internals
.extensions_sent
[i
]));
163 DECR_LENGTH_RET (data_size
, 2, 0);
164 next
= _gnutls_read_uint16 (data
);
167 DECR_LENGTH_RET (data_size
, next
, 0);
171 DECR_LENGTH_RET (next
, 2, 0);
172 type
= _gnutls_read_uint16 (&data
[pos
]);
175 if ((ret
= _gnutls_extension_list_check (session
, type
)) < 0)
181 DECR_LENGTH_RET (next
, 2, 0);
182 size
= _gnutls_read_uint16 (&data
[pos
]);
185 DECR_LENGTH_RET (next
, size
, 0);
189 ext_recv
= _gnutls_ext_func_recv (type
, parse_type
);
190 if (ext_recv
== NULL
)
192 _gnutls_handshake_log ("EXT[%p]: Found extension '%s/%d'\n", session
,
193 _gnutls_extension_get_name (type
), type
);
198 _gnutls_handshake_log ("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)
215 /* Adds the extension we want to send in the extensions list.
216 * This list is used to check whether the (later) received
217 * extensions are the ones we requested.
220 _gnutls_extension_list_add (gnutls_session_t session
, uint16_t type
)
223 if (session
->security_parameters
.entity
== GNUTLS_CLIENT
)
225 if (session
->internals
.extensions_sent_size
< MAX_EXT_TYPES
)
227 session
->internals
.extensions_sent
[session
->internals
.
228 extensions_sent_size
] = type
;
229 session
->internals
.extensions_sent_size
++;
233 _gnutls_handshake_log ("extensions: Increase MAX_EXT_TYPES\n");
239 _gnutls_gen_extensions (gnutls_session_t session
, gnutls_buffer_st
* extdata
,
240 gnutls_ext_parse_type_t parse_type
)
243 int pos
, size_pos
, ret
;
244 size_t i
, init_size
= extdata
->length
;
246 pos
= extdata
->length
; /* we will store length later on */
247 _gnutls_buffer_append_prefix( extdata
, 16, 0);
249 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
&& p
->parse_type
!= parse_type
)
259 ret
= _gnutls_buffer_append_prefix( extdata
, 16, p
->type
);
261 return gnutls_assert_val(ret
);
263 size_pos
= extdata
->length
;
264 ret
= _gnutls_buffer_append_prefix (extdata
, 16, 0);
266 return gnutls_assert_val(ret
);
268 size
= p
->send_func (session
, extdata
);
269 /* returning GNUTLS_E_INT_RET_0 means to send an empty
270 * extension of this type.
272 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
, &extdata
->data
[size_pos
]);
280 /* add this extension to the extension list
282 _gnutls_extension_list_add (session
, p
->type
);
284 _gnutls_handshake_log ("EXT[%p]: Sending extension %s (%d bytes)\n",
285 session
, p
->name
, size
);
293 extdata
->length
-= 4; /* reset type and size */
296 /* remove any initial data, and the size of the header */
297 size
= extdata
->length
- init_size
- 2;
300 _gnutls_write_uint16(size
, &extdata
->data
[pos
]);
301 else if (size
== 0) extdata
->length
-= 2; /* the length bytes */
307 _gnutls_ext_init (void)
311 ret
= _gnutls_ext_register (&ext_mod_max_record_size
);
312 if (ret
!= GNUTLS_E_SUCCESS
)
315 ret
= _gnutls_ext_register (&ext_mod_status_request
);
316 if (ret
!= GNUTLS_E_SUCCESS
)
319 ret
= _gnutls_ext_register (&ext_mod_cert_type
);
320 if (ret
!= GNUTLS_E_SUCCESS
)
323 ret
= _gnutls_ext_register (&ext_mod_server_name
);
324 if (ret
!= GNUTLS_E_SUCCESS
)
327 ret
= _gnutls_ext_register (&ext_mod_sr
);
328 if (ret
!= GNUTLS_E_SUCCESS
)
332 ret
= _gnutls_ext_register (&ext_mod_srp
);
333 if (ret
!= GNUTLS_E_SUCCESS
)
337 ret
= _gnutls_ext_register (&ext_mod_heartbeat
);
338 if (ret
!= GNUTLS_E_SUCCESS
)
341 ret
= _gnutls_ext_register (&ext_mod_session_ticket
);
342 if (ret
!= GNUTLS_E_SUCCESS
)
345 ret
= _gnutls_ext_register (&ext_mod_supported_ecc
);
346 if (ret
!= GNUTLS_E_SUCCESS
)
349 ret
= _gnutls_ext_register (&ext_mod_supported_ecc_pf
);
350 if (ret
!= GNUTLS_E_SUCCESS
)
353 ret
= _gnutls_ext_register (&ext_mod_sig
);
354 if (ret
!= GNUTLS_E_SUCCESS
)
357 return GNUTLS_E_SUCCESS
;
361 _gnutls_ext_deinit (void)
363 gnutls_free (extfunc
);
369 _gnutls_ext_register (extension_entry_st
* mod
)
371 extension_entry_st
*p
;
373 p
= gnutls_realloc (extfunc
, sizeof (*extfunc
) * (extfunc_size
+ 1));
377 return GNUTLS_E_MEMORY_ERROR
;
382 memcpy (&extfunc
[extfunc_size
], mod
, sizeof (*mod
));
386 return GNUTLS_E_SUCCESS
;
390 _gnutls_ext_pack (gnutls_session_t session
, gnutls_buffer_st
* packed
)
394 extension_priv_data_t data
;
400 total_exts_pos
= packed
->length
;
401 BUFFER_APPEND_NUM (packed
, 0);
403 for (i
= 0; i
< extfunc_size
; i
++)
405 ret
= _gnutls_ext_get_session_data (session
, extfunc
[i
].type
, &data
);
406 if (ret
>= 0 && extfunc
[i
].pack_func
!= NULL
)
408 BUFFER_APPEND_NUM (packed
, extfunc
[i
].type
);
410 size_offset
= packed
->length
;
411 BUFFER_APPEND_NUM (packed
, 0);
413 cur_size
= packed
->length
;
415 ret
= extfunc
[i
].pack_func (data
, packed
);
423 /* write the actual size */
424 _gnutls_write_uint32 (packed
->length
- cur_size
,
425 packed
->data
+ size_offset
);
429 _gnutls_write_uint32 (exts
, packed
->data
+ total_exts_pos
);
436 _gnutls_ext_restore_resumed_session (gnutls_session_t session
)
441 /* clear everything except MANDATORY extensions */
442 for (i
= 0; i
< MAX_EXT_TYPES
; i
++)
444 if (session
->internals
.extension_int_data
[i
].set
!= 0 &&
445 _gnutls_ext_parse_type (session
->internals
.
446 extension_int_data
[i
].type
) !=
447 GNUTLS_EXT_MANDATORY
)
449 _gnutls_ext_unset_session_data (session
,
451 internals
.extension_int_data
[i
].
456 /* copy resumed to main */
457 for (i
= 0; i
< MAX_EXT_TYPES
; i
++)
459 if (session
->internals
.resumed_extension_int_data
[i
].set
!= 0 &&
460 _gnutls_ext_parse_type (session
->
461 internals
.resumed_extension_int_data
[i
].
462 type
) != GNUTLS_EXT_MANDATORY
)
464 _gnutls_ext_set_session_data (session
,
466 internals
.resumed_extension_int_data
469 internals
.resumed_extension_int_data
471 session
->internals
.resumed_extension_int_data
[i
].set
= 0;
479 _gnutls_ext_set_resumed_session_data (gnutls_session_t session
, uint16_t type
,
480 extension_priv_data_t data
)
484 for (i
= 0; i
< MAX_EXT_TYPES
; i
++)
486 if (session
->internals
.resumed_extension_int_data
[i
].type
== type
487 || session
->internals
.resumed_extension_int_data
[i
].set
== 0)
490 if (session
->internals
.resumed_extension_int_data
[i
].set
!= 0)
491 _gnutls_ext_unset_resumed_session_data (session
, type
);
493 session
->internals
.resumed_extension_int_data
[i
].type
= type
;
494 session
->internals
.resumed_extension_int_data
[i
].priv
= data
;
495 session
->internals
.resumed_extension_int_data
[i
].set
= 1;
502 _gnutls_ext_unpack (gnutls_session_t session
, gnutls_buffer_st
* packed
)
505 extension_priv_data_t data
;
506 gnutls_ext_unpack_func unpack
;
509 int size_for_type
, cur_pos
;
512 BUFFER_POP_NUM (packed
, max_exts
);
513 for (i
= 0; i
< max_exts
; i
++)
515 BUFFER_POP_NUM (packed
, type
);
516 BUFFER_POP_NUM (packed
, size_for_type
);
518 cur_pos
= packed
->length
;
520 unpack
= _gnutls_ext_func_unpack (type
);
524 return GNUTLS_E_PARSING_ERROR
;
527 ret
= unpack (packed
, &data
);
534 /* verify that unpack read the correct bytes */
535 cur_pos
= cur_pos
- packed
->length
;
536 if (cur_pos
/* read length */ != size_for_type
)
539 return GNUTLS_E_PARSING_ERROR
;
542 _gnutls_ext_set_resumed_session_data (session
, type
, data
);
552 _gnutls_ext_unset_session_data (gnutls_session_t session
, uint16_t type
)
554 gnutls_ext_deinit_data_func deinit
;
555 extension_priv_data_t data
;
558 deinit
= _gnutls_ext_func_deinit (type
);
559 ret
= _gnutls_ext_get_session_data (session
, type
, &data
);
561 if (ret
>= 0 && deinit
!= NULL
)
566 for (i
= 0; i
< MAX_EXT_TYPES
; i
++)
568 if (session
->internals
.extension_int_data
[i
].type
== type
)
570 session
->internals
.extension_int_data
[i
].set
= 0;
578 _gnutls_ext_unset_resumed_session_data (gnutls_session_t session
,
581 gnutls_ext_deinit_data_func deinit
;
582 extension_priv_data_t data
;
585 deinit
= _gnutls_ext_func_deinit (type
);
586 ret
= _gnutls_ext_get_resumed_session_data (session
, type
, &data
);
588 if (ret
>= 0 && deinit
!= NULL
)
593 for (i
= 0; i
< MAX_EXT_TYPES
; i
++)
595 if (session
->internals
.resumed_extension_int_data
[i
].type
== type
)
597 session
->internals
.resumed_extension_int_data
[i
].set
= 0;
604 /* Deinitializes all data that are associated with TLS extensions.
607 _gnutls_ext_free_session_data (gnutls_session_t session
)
611 for (i
= 0; i
< extfunc_size
; i
++)
613 _gnutls_ext_unset_session_data (session
, extfunc
[i
].type
);
616 for (i
= 0; i
< extfunc_size
; i
++)
618 _gnutls_ext_unset_resumed_session_data (session
, extfunc
[i
].type
);
623 /* This function allows and extension to store data in the current session
624 * and retrieve them later on. We use functions instead of a pointer to a
625 * private pointer, to allow API additions by individual extensions.
628 _gnutls_ext_set_session_data (gnutls_session_t session
, uint16_t type
,
629 extension_priv_data_t data
)
632 gnutls_ext_deinit_data_func deinit
;
634 deinit
= _gnutls_ext_func_deinit (type
);
636 for (i
= 0; i
< MAX_EXT_TYPES
; i
++)
638 if (session
->internals
.extension_int_data
[i
].type
== type
639 || session
->internals
.extension_int_data
[i
].set
== 0)
641 if (session
->internals
.extension_int_data
[i
].set
!= 0)
644 deinit (session
->internals
.extension_int_data
[i
].priv
);
646 session
->internals
.extension_int_data
[i
].type
= type
;
647 session
->internals
.extension_int_data
[i
].priv
= data
;
648 session
->internals
.extension_int_data
[i
].set
= 1;
655 _gnutls_ext_get_session_data (gnutls_session_t session
,
656 uint16_t type
, extension_priv_data_t
* data
)
660 for (i
= 0; i
< MAX_EXT_TYPES
; i
++)
662 if (session
->internals
.extension_int_data
[i
].set
!= 0 &&
663 session
->internals
.extension_int_data
[i
].type
== type
)
665 *data
= session
->internals
.extension_int_data
[i
].priv
;
669 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
;
673 _gnutls_ext_get_resumed_session_data (gnutls_session_t session
,
675 extension_priv_data_t
* data
)
679 for (i
= 0; i
< MAX_EXT_TYPES
; i
++)
681 if (session
->internals
.resumed_extension_int_data
[i
].set
!= 0 &&
682 session
->internals
.resumed_extension_int_data
[i
].type
== type
)
684 *data
= session
->internals
.resumed_extension_int_data
[i
].priv
;
688 return GNUTLS_E_INVALID_REQUEST
;