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>
43 #include <gnutls_num.h>
46 static void _gnutls_ext_unset_resumed_session_data (gnutls_session_t session
,
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
)
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
)
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
;
80 static gnutls_ext_deinit_data_func
81 _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
93 _gnutls_ext_func_unpack (uint16_t type
)
97 for (i
= 0; i
< extfunc_size
; i
++)
98 if (extfunc
[i
].type
== type
)
99 return extfunc
[i
].unpack_func
;
106 _gnutls_extension_get_name (uint16_t type
)
110 for (i
= 0; i
< extfunc_size
; i
++)
111 if (extfunc
[i
].type
== type
)
112 return extfunc
[i
].name
;
117 /* Checks if the extension we just received is one of the
118 * requested ones. Otherwise it's a fatal error.
121 _gnutls_extension_list_check (gnutls_session_t session
, uint16_t type
)
123 if (session
->security_parameters
.entity
== GNUTLS_CLIENT
)
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
;
140 _gnutls_parse_extensions (gnutls_session_t session
,
141 gnutls_ext_parse_type_t parse_type
,
142 const uint8_t * data
, int data_size
)
147 const uint8_t *sdata
;
148 gnutls_ext_recv_func ext_recv
;
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",
159 _gnutls_extension_get_name
160 (session
->internals
.extensions_sent
[i
]));
164 DECR_LENGTH_RET (data_size
, 2, 0);
165 next
= _gnutls_read_uint16 (data
);
168 DECR_LENGTH_RET (data_size
, next
, 0);
172 DECR_LENGTH_RET (next
, 2, 0);
173 type
= _gnutls_read_uint16 (&data
[pos
]);
176 if ((ret
= _gnutls_extension_list_check (session
, type
)) < 0)
182 DECR_LENGTH_RET (next
, 2, 0);
183 size
= _gnutls_read_uint16 (&data
[pos
]);
186 DECR_LENGTH_RET (next
, size
, 0);
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
);
199 _gnutls_handshake_log ("EXT[%p]: Parsing extension '%s/%d' (%d bytes)\n",
200 session
, _gnutls_extension_get_name (type
), type
,
203 if ((ret
= ext_recv (session
, sdata
, size
)) < 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.
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
++;
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
)
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
)
257 if (parse_type
!= GNUTLS_EXT_ANY
&& 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
)
275 if (size
== GNUTLS_E_INT_RET_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
);
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;
301 _gnutls_write_uint16(size
, &extdata
->data
[pos
]);
302 else if (size
== 0) extdata
->length
-= 2; /* the length bytes */
308 _gnutls_ext_init (void)
312 ret
= _gnutls_ext_register (&ext_mod_max_record_size
);
313 if (ret
!= GNUTLS_E_SUCCESS
)
316 ret
= _gnutls_ext_register (&ext_mod_status_request
);
317 if (ret
!= GNUTLS_E_SUCCESS
)
320 ret
= _gnutls_ext_register (&ext_mod_cert_type
);
321 if (ret
!= GNUTLS_E_SUCCESS
)
324 ret
= _gnutls_ext_register (&ext_mod_server_name
);
325 if (ret
!= GNUTLS_E_SUCCESS
)
328 ret
= _gnutls_ext_register (&ext_mod_sr
);
329 if (ret
!= GNUTLS_E_SUCCESS
)
333 ret
= _gnutls_ext_register (&ext_mod_srp
);
334 if (ret
!= GNUTLS_E_SUCCESS
)
338 ret
= _gnutls_ext_register (&ext_mod_heartbeat
);
339 if (ret
!= GNUTLS_E_SUCCESS
)
342 ret
= _gnutls_ext_register (&ext_mod_session_ticket
);
343 if (ret
!= GNUTLS_E_SUCCESS
)
346 ret
= _gnutls_ext_register (&ext_mod_supported_ecc
);
347 if (ret
!= GNUTLS_E_SUCCESS
)
350 ret
= _gnutls_ext_register (&ext_mod_supported_ecc_pf
);
351 if (ret
!= GNUTLS_E_SUCCESS
)
354 ret
= _gnutls_ext_register (&ext_mod_sig
);
355 if (ret
!= GNUTLS_E_SUCCESS
)
358 ret
= _gnutls_ext_register (&ext_mod_srtp
);
359 if (ret
!= GNUTLS_E_SUCCESS
)
362 return GNUTLS_E_SUCCESS
;
366 _gnutls_ext_deinit (void)
368 gnutls_free (extfunc
);
374 _gnutls_ext_register (extension_entry_st
* mod
)
376 extension_entry_st
*p
;
378 p
= gnutls_realloc (extfunc
, sizeof (*extfunc
) * (extfunc_size
+ 1));
382 return GNUTLS_E_MEMORY_ERROR
;
387 memcpy (&extfunc
[extfunc_size
], mod
, sizeof (*mod
));
391 return GNUTLS_E_SUCCESS
;
395 _gnutls_ext_pack (gnutls_session_t session
, gnutls_buffer_st
* packed
)
399 extension_priv_data_t data
;
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
);
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
);
441 _gnutls_ext_restore_resumed_session (gnutls_session_t session
)
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
,
456 internals
.extension_int_data
[i
].
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
,
471 internals
.resumed_extension_int_data
474 internals
.resumed_extension_int_data
476 session
->internals
.resumed_extension_int_data
[i
].set
= 0;
484 _gnutls_ext_set_resumed_session_data (gnutls_session_t session
, uint16_t type
,
485 extension_priv_data_t data
)
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;
507 _gnutls_ext_unpack (gnutls_session_t session
, gnutls_buffer_st
* packed
)
510 extension_priv_data_t data
;
511 gnutls_ext_unpack_func unpack
;
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
);
529 return GNUTLS_E_PARSING_ERROR
;
532 ret
= unpack (packed
, &data
);
539 /* verify that unpack read the correct bytes */
540 cur_pos
= cur_pos
- packed
->length
;
541 if (cur_pos
/* read length */ != size_for_type
)
544 return GNUTLS_E_PARSING_ERROR
;
547 _gnutls_ext_set_resumed_session_data (session
, type
, data
);
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
;
563 deinit
= _gnutls_ext_func_deinit (type
);
564 ret
= _gnutls_ext_get_session_data (session
, type
, &data
);
566 if (ret
>= 0 && deinit
!= NULL
)
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;
583 _gnutls_ext_unset_resumed_session_data (gnutls_session_t session
,
586 gnutls_ext_deinit_data_func deinit
;
587 extension_priv_data_t data
;
590 deinit
= _gnutls_ext_func_deinit (type
);
591 ret
= _gnutls_ext_get_resumed_session_data (session
, type
, &data
);
593 if (ret
>= 0 && deinit
!= NULL
)
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;
609 /* Deinitializes all data that are associated with TLS extensions.
612 _gnutls_ext_free_session_data (gnutls_session_t session
)
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.
633 _gnutls_ext_set_session_data (gnutls_session_t session
, uint16_t type
,
634 extension_priv_data_t data
)
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)
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;
660 _gnutls_ext_get_session_data (gnutls_session_t session
,
661 uint16_t type
, extension_priv_data_t
* data
)
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
;
674 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
;
678 _gnutls_ext_get_resumed_session_data (gnutls_session_t session
,
680 extension_priv_data_t
* data
)
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
;
693 return GNUTLS_E_INVALID_REQUEST
;