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 #ifdef ENABLE_DTLS_SRTP
359 ret
= _gnutls_ext_register (&ext_mod_srtp
);
360 if (ret
!= GNUTLS_E_SUCCESS
)
364 return GNUTLS_E_SUCCESS
;
368 _gnutls_ext_deinit (void)
370 gnutls_free (extfunc
);
376 _gnutls_ext_register (extension_entry_st
* mod
)
378 extension_entry_st
*p
;
380 p
= gnutls_realloc (extfunc
, sizeof (*extfunc
) * (extfunc_size
+ 1));
384 return GNUTLS_E_MEMORY_ERROR
;
389 memcpy (&extfunc
[extfunc_size
], mod
, sizeof (*mod
));
393 return GNUTLS_E_SUCCESS
;
397 _gnutls_ext_pack (gnutls_session_t session
, gnutls_buffer_st
* packed
)
401 extension_priv_data_t data
;
407 total_exts_pos
= packed
->length
;
408 BUFFER_APPEND_NUM (packed
, 0);
410 for (i
= 0; i
< extfunc_size
; i
++)
412 ret
= _gnutls_ext_get_session_data (session
, extfunc
[i
].type
, &data
);
413 if (ret
>= 0 && extfunc
[i
].pack_func
!= NULL
)
415 BUFFER_APPEND_NUM (packed
, extfunc
[i
].type
);
417 size_offset
= packed
->length
;
418 BUFFER_APPEND_NUM (packed
, 0);
420 cur_size
= packed
->length
;
422 ret
= extfunc
[i
].pack_func (data
, packed
);
430 /* write the actual size */
431 _gnutls_write_uint32 (packed
->length
- cur_size
,
432 packed
->data
+ size_offset
);
436 _gnutls_write_uint32 (exts
, packed
->data
+ total_exts_pos
);
443 _gnutls_ext_restore_resumed_session (gnutls_session_t session
)
448 /* clear everything except MANDATORY extensions */
449 for (i
= 0; i
< MAX_EXT_TYPES
; i
++)
451 if (session
->internals
.extension_int_data
[i
].set
!= 0 &&
452 _gnutls_ext_parse_type (session
->internals
.
453 extension_int_data
[i
].type
) !=
454 GNUTLS_EXT_MANDATORY
)
456 _gnutls_ext_unset_session_data (session
,
458 internals
.extension_int_data
[i
].
463 /* copy resumed to main */
464 for (i
= 0; i
< MAX_EXT_TYPES
; i
++)
466 if (session
->internals
.resumed_extension_int_data
[i
].set
!= 0 &&
467 _gnutls_ext_parse_type (session
->
468 internals
.resumed_extension_int_data
[i
].
469 type
) != GNUTLS_EXT_MANDATORY
)
471 _gnutls_ext_set_session_data (session
,
473 internals
.resumed_extension_int_data
476 internals
.resumed_extension_int_data
478 session
->internals
.resumed_extension_int_data
[i
].set
= 0;
486 _gnutls_ext_set_resumed_session_data (gnutls_session_t session
, uint16_t type
,
487 extension_priv_data_t data
)
491 for (i
= 0; i
< MAX_EXT_TYPES
; i
++)
493 if (session
->internals
.resumed_extension_int_data
[i
].type
== type
494 || session
->internals
.resumed_extension_int_data
[i
].set
== 0)
497 if (session
->internals
.resumed_extension_int_data
[i
].set
!= 0)
498 _gnutls_ext_unset_resumed_session_data (session
, type
);
500 session
->internals
.resumed_extension_int_data
[i
].type
= type
;
501 session
->internals
.resumed_extension_int_data
[i
].priv
= data
;
502 session
->internals
.resumed_extension_int_data
[i
].set
= 1;
509 _gnutls_ext_unpack (gnutls_session_t session
, gnutls_buffer_st
* packed
)
512 extension_priv_data_t data
;
513 gnutls_ext_unpack_func unpack
;
516 int size_for_type
, cur_pos
;
519 BUFFER_POP_NUM (packed
, max_exts
);
520 for (i
= 0; i
< max_exts
; i
++)
522 BUFFER_POP_NUM (packed
, type
);
523 BUFFER_POP_NUM (packed
, size_for_type
);
525 cur_pos
= packed
->length
;
527 unpack
= _gnutls_ext_func_unpack (type
);
531 return GNUTLS_E_PARSING_ERROR
;
534 ret
= unpack (packed
, &data
);
541 /* verify that unpack read the correct bytes */
542 cur_pos
= cur_pos
- packed
->length
;
543 if (cur_pos
/* read length */ != size_for_type
)
546 return GNUTLS_E_PARSING_ERROR
;
549 _gnutls_ext_set_resumed_session_data (session
, type
, data
);
559 _gnutls_ext_unset_session_data (gnutls_session_t session
, uint16_t type
)
561 gnutls_ext_deinit_data_func deinit
;
562 extension_priv_data_t data
;
565 deinit
= _gnutls_ext_func_deinit (type
);
566 ret
= _gnutls_ext_get_session_data (session
, type
, &data
);
568 if (ret
>= 0 && deinit
!= NULL
)
573 for (i
= 0; i
< MAX_EXT_TYPES
; i
++)
575 if (session
->internals
.extension_int_data
[i
].type
== type
)
577 session
->internals
.extension_int_data
[i
].set
= 0;
585 _gnutls_ext_unset_resumed_session_data (gnutls_session_t session
,
588 gnutls_ext_deinit_data_func deinit
;
589 extension_priv_data_t data
;
592 deinit
= _gnutls_ext_func_deinit (type
);
593 ret
= _gnutls_ext_get_resumed_session_data (session
, type
, &data
);
595 if (ret
>= 0 && deinit
!= NULL
)
600 for (i
= 0; i
< MAX_EXT_TYPES
; i
++)
602 if (session
->internals
.resumed_extension_int_data
[i
].type
== type
)
604 session
->internals
.resumed_extension_int_data
[i
].set
= 0;
611 /* Deinitializes all data that are associated with TLS extensions.
614 _gnutls_ext_free_session_data (gnutls_session_t session
)
618 for (i
= 0; i
< extfunc_size
; i
++)
620 _gnutls_ext_unset_session_data (session
, extfunc
[i
].type
);
623 for (i
= 0; i
< extfunc_size
; i
++)
625 _gnutls_ext_unset_resumed_session_data (session
, extfunc
[i
].type
);
630 /* This function allows and extension to store data in the current session
631 * and retrieve them later on. We use functions instead of a pointer to a
632 * private pointer, to allow API additions by individual extensions.
635 _gnutls_ext_set_session_data (gnutls_session_t session
, uint16_t type
,
636 extension_priv_data_t data
)
639 gnutls_ext_deinit_data_func deinit
;
641 deinit
= _gnutls_ext_func_deinit (type
);
643 for (i
= 0; i
< MAX_EXT_TYPES
; i
++)
645 if (session
->internals
.extension_int_data
[i
].type
== type
646 || session
->internals
.extension_int_data
[i
].set
== 0)
648 if (session
->internals
.extension_int_data
[i
].set
!= 0)
651 deinit (session
->internals
.extension_int_data
[i
].priv
);
653 session
->internals
.extension_int_data
[i
].type
= type
;
654 session
->internals
.extension_int_data
[i
].priv
= data
;
655 session
->internals
.extension_int_data
[i
].set
= 1;
662 _gnutls_ext_get_session_data (gnutls_session_t session
,
663 uint16_t type
, extension_priv_data_t
* data
)
667 for (i
= 0; i
< MAX_EXT_TYPES
; i
++)
669 if (session
->internals
.extension_int_data
[i
].set
!= 0 &&
670 session
->internals
.extension_int_data
[i
].type
== type
)
672 *data
= session
->internals
.extension_int_data
[i
].priv
;
676 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
;
680 _gnutls_ext_get_resumed_session_data (gnutls_session_t session
,
682 extension_priv_data_t
* data
)
686 for (i
= 0; i
< MAX_EXT_TYPES
; i
++)
688 if (session
->internals
.resumed_extension_int_data
[i
].set
!= 0 &&
689 session
->internals
.resumed_extension_int_data
[i
].type
== type
)
691 *data
= session
->internals
.resumed_extension_int_data
[i
].priv
;
695 return GNUTLS_E_INVALID_REQUEST
;