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 <gnutls_num.h>
44 static void _gnutls_ext_unset_resumed_session_data (gnutls_session_t session
,
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
)
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
)
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
;
78 static gnutls_ext_deinit_data_func
79 _gnutls_ext_func_deinit (uint16_t type
)
83 for (i
= 0; i
< extfunc_size
; i
++)
84 if (extfunc
[i
].type
== type
)
85 return extfunc
[i
].deinit_func
;
90 static gnutls_ext_unpack_func
91 _gnutls_ext_func_unpack (uint16_t type
)
95 for (i
= 0; i
< extfunc_size
; i
++)
96 if (extfunc
[i
].type
== type
)
97 return extfunc
[i
].unpack_func
;
104 _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
)
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
;
138 _gnutls_parse_extensions (gnutls_session_t session
,
139 gnutls_ext_parse_type_t parse_type
,
140 const uint8_t * data
, int data_size
)
145 const uint8_t *sdata
;
146 gnutls_ext_recv_func ext_recv
;
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",
157 _gnutls_extension_get_name
158 (session
->internals
.extensions_sent
[i
]));
162 DECR_LENGTH_RET (data_size
, 2, 0);
163 next
= _gnutls_read_uint16 (data
);
166 DECR_LENGTH_RET (data_size
, next
, 0);
170 DECR_LENGTH_RET (next
, 2, 0);
171 type
= _gnutls_read_uint16 (&data
[pos
]);
175 _gnutls_handshake_log ("EXT[%p]: Found extension '%s/%d'\n", session
,
176 _gnutls_extension_get_name (type
), type
);
179 if ((ret
= _gnutls_extension_list_check (session
, type
)) < 0)
185 DECR_LENGTH_RET (next
, 2, 0);
186 size
= _gnutls_read_uint16 (&data
[pos
]);
189 DECR_LENGTH_RET (next
, size
, 0);
193 ext_recv
= _gnutls_ext_func_recv (type
, parse_type
);
194 if (ext_recv
== NULL
)
197 _gnutls_handshake_log ("EXT[%p]: Parsing extension '%s/%d' (%d bytes)\n",
198 session
, _gnutls_extension_get_name (type
), type
,
201 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.
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
++;
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
)
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
)
255 if (parse_type
!= GNUTLS_EXT_ANY
&& p
->parse_type
!= parse_type
)
258 ret
= _gnutls_buffer_append_prefix( extdata
, 16, p
->type
);
260 return gnutls_assert_val(ret
);
262 size_pos
= extdata
->length
;
263 ret
= _gnutls_buffer_append_prefix (extdata
, 16, 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
)
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
);
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
]);
300 else if (size
== 0) extdata
->length
-= 2; /* the length bytes */
306 _gnutls_ext_init (void)
310 ret
= _gnutls_ext_register (&ext_mod_max_record_size
);
311 if (ret
!= GNUTLS_E_SUCCESS
)
314 ret
= _gnutls_ext_register (&ext_mod_cert_type
);
315 if (ret
!= GNUTLS_E_SUCCESS
)
319 ret
= _gnutls_ext_register (&ext_mod_server_name
);
320 if (ret
!= GNUTLS_E_SUCCESS
)
323 ret
= _gnutls_ext_register (&ext_mod_sr
);
324 if (ret
!= GNUTLS_E_SUCCESS
)
328 ret
= _gnutls_ext_register (&ext_mod_srp
);
329 if (ret
!= GNUTLS_E_SUCCESS
)
333 ret
= _gnutls_ext_register (&ext_mod_heartbeat
);
334 if (ret
!= GNUTLS_E_SUCCESS
)
337 ret
= _gnutls_ext_register (&ext_mod_session_ticket
);
338 if (ret
!= GNUTLS_E_SUCCESS
)
341 ret
= _gnutls_ext_register (&ext_mod_supported_ecc
);
342 if (ret
!= GNUTLS_E_SUCCESS
)
345 ret
= _gnutls_ext_register (&ext_mod_supported_ecc_pf
);
346 if (ret
!= GNUTLS_E_SUCCESS
)
349 ret
= _gnutls_ext_register (&ext_mod_sig
);
350 if (ret
!= GNUTLS_E_SUCCESS
)
353 return GNUTLS_E_SUCCESS
;
357 _gnutls_ext_deinit (void)
359 gnutls_free (extfunc
);
365 _gnutls_ext_register (extension_entry_st
* mod
)
367 extension_entry_st
*p
;
369 p
= gnutls_realloc (extfunc
, sizeof (*extfunc
) * (extfunc_size
+ 1));
373 return GNUTLS_E_MEMORY_ERROR
;
378 memcpy (&extfunc
[extfunc_size
], mod
, sizeof (*mod
));
382 return GNUTLS_E_SUCCESS
;
386 _gnutls_ext_pack (gnutls_session_t session
, gnutls_buffer_st
* packed
)
390 extension_priv_data_t data
;
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
);
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
);
432 _gnutls_ext_restore_resumed_session (gnutls_session_t session
)
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
,
447 internals
.extension_int_data
[i
].
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
,
462 internals
.resumed_extension_int_data
465 internals
.resumed_extension_int_data
467 session
->internals
.resumed_extension_int_data
[i
].set
= 0;
475 _gnutls_ext_set_resumed_session_data (gnutls_session_t session
, uint16_t type
,
476 extension_priv_data_t data
)
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;
498 _gnutls_ext_unpack (gnutls_session_t session
, gnutls_buffer_st
* packed
)
501 extension_priv_data_t data
;
502 gnutls_ext_unpack_func unpack
;
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
);
520 return GNUTLS_E_PARSING_ERROR
;
523 ret
= unpack (packed
, &data
);
530 /* verify that unpack read the correct bytes */
531 cur_pos
= cur_pos
- packed
->length
;
532 if (cur_pos
/* read length */ != size_for_type
)
535 return GNUTLS_E_PARSING_ERROR
;
538 _gnutls_ext_set_resumed_session_data (session
, type
, data
);
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
;
554 deinit
= _gnutls_ext_func_deinit (type
);
555 ret
= _gnutls_ext_get_session_data (session
, type
, &data
);
557 if (ret
>= 0 && deinit
!= NULL
)
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;
574 _gnutls_ext_unset_resumed_session_data (gnutls_session_t session
,
577 gnutls_ext_deinit_data_func deinit
;
578 extension_priv_data_t data
;
581 deinit
= _gnutls_ext_func_deinit (type
);
582 ret
= _gnutls_ext_get_resumed_session_data (session
, type
, &data
);
584 if (ret
>= 0 && deinit
!= NULL
)
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;
600 /* Deinitializes all data that are associated with TLS extensions.
603 _gnutls_ext_free_session_data (gnutls_session_t session
)
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.
624 _gnutls_ext_set_session_data (gnutls_session_t session
, uint16_t type
,
625 extension_priv_data_t data
)
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)
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;
651 _gnutls_ext_get_session_data (gnutls_session_t session
,
652 uint16_t type
, extension_priv_data_t
* data
)
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
;
665 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
;
669 _gnutls_ext_get_resumed_session_data (gnutls_session_t session
,
671 extension_priv_data_t
* data
)
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
;
684 return GNUTLS_E_INVALID_REQUEST
;