2 * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
3 * Free Software Foundation, Inc.
5 * Author: Nikos Mavrogiannopoulos, Simon Josefsson
7 * This file is part of GnuTLS.
9 * The GnuTLS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1 of
12 * the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
26 /* Functions that relate to the TLS hello extension parsing.
27 * Hello extensions are packets appended in the TLS hello packet, and
28 * allow for extra functionality.
31 #include "gnutls_int.h"
32 #include "gnutls_extensions.h"
33 #include "gnutls_errors.h"
34 #include "ext_max_record.h"
35 #include <ext_cert_type.h>
36 #include <ext_server_name.h>
38 #include <ext_session_ticket.h>
39 #include <ext_safe_renegotiation.h>
40 #include <ext_signature.h>
41 #include <ext_safe_renegotiation.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 opaque
* data
, int data_size
)
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_debug_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
]);
176 _gnutls_debug_log ("EXT[%p]: Found extension '%s/%d'\n", session
,
177 _gnutls_extension_get_name (type
), type
);
180 if ((ret
= _gnutls_extension_list_check (session
, type
)) < 0)
186 DECR_LENGTH_RET (next
, 2, 0);
187 size
= _gnutls_read_uint16 (&data
[pos
]);
190 DECR_LENGTH_RET (next
, size
, 0);
194 ext_recv
= _gnutls_ext_func_recv (type
, parse_type
);
195 if (ext_recv
== NULL
)
198 _gnutls_debug_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_debug_log ("extensions: Increase MAX_EXT_TYPES\n");
239 _gnutls_gen_extensions (gnutls_session_t session
, opaque
* data
,
240 size_t data_size
, gnutls_ext_parse_type_t parse_type
)
251 return GNUTLS_E_INTERNAL_ERROR
;
254 /* allocate enough data for each extension.
256 sdata_size
= data_size
;
257 sdata
= gnutls_malloc (sdata_size
);
261 return GNUTLS_E_MEMORY_ERROR
;
265 for (i
= 0; i
< extfunc_size
; i
++)
267 extension_entry_st
*p
= &extfunc
[i
];
269 if (p
->send_func
== NULL
)
272 if (parse_type
!= GNUTLS_EXT_ANY
&& p
->parse_type
!= parse_type
)
275 size
= p
->send_func (session
, sdata
, sdata_size
);
276 if (size
> 0 || size
== GNUTLS_E_INT_RET_0
)
278 if (size
== GNUTLS_E_INT_RET_0
)
281 if (data_size
< pos
+ (size_t) size
+ 4)
285 return GNUTLS_E_INTERNAL_ERROR
;
288 /* write extension type */
289 _gnutls_write_uint16 (p
->type
, &data
[pos
]);
293 _gnutls_write_uint16 (size
, &data
[pos
]);
296 memcpy (&data
[pos
], sdata
, size
);
299 /* add this extension to the extension list
301 _gnutls_extension_list_add (session
, p
->type
);
303 _gnutls_debug_log ("EXT[%p]: Sending extension %s (%d bytes)\n",
304 session
, p
->name
, size
);
315 pos
-= 2; /* remove the size of the size header! */
317 _gnutls_write_uint16 (pos
, data
);
330 _gnutls_ext_init (void)
334 ret
= _gnutls_ext_register (&ext_mod_max_record_size
);
335 if (ret
!= GNUTLS_E_SUCCESS
)
338 ret
= _gnutls_ext_register (&ext_mod_cert_type
);
339 if (ret
!= GNUTLS_E_SUCCESS
)
343 ret
= _gnutls_ext_register (&ext_mod_server_name
);
344 if (ret
!= GNUTLS_E_SUCCESS
)
347 ret
= _gnutls_ext_register (&ext_mod_sr
);
348 if (ret
!= GNUTLS_E_SUCCESS
)
352 ret
= _gnutls_ext_register (&ext_mod_srp
);
353 if (ret
!= GNUTLS_E_SUCCESS
)
357 #ifdef ENABLE_SESSION_TICKET
358 ret
= _gnutls_ext_register (&ext_mod_session_ticket
);
359 if (ret
!= GNUTLS_E_SUCCESS
)
363 ret
= _gnutls_ext_register (&ext_mod_sig
);
364 if (ret
!= GNUTLS_E_SUCCESS
)
367 return GNUTLS_E_SUCCESS
;
371 _gnutls_ext_deinit (void)
373 gnutls_free (extfunc
);
379 _gnutls_ext_register (extension_entry_st
* mod
)
381 extension_entry_st
*p
;
383 p
= gnutls_realloc (extfunc
, sizeof (*extfunc
) * (extfunc_size
+ 1));
387 return GNUTLS_E_MEMORY_ERROR
;
392 memcpy (&extfunc
[extfunc_size
], mod
, sizeof (*mod
));
396 return GNUTLS_E_SUCCESS
;
400 * gnutls_ext_register:
401 * @type: the 16-bit integer referring to the extension type
402 * @name: human printable name of the extension used for debugging
403 * @parse_type: either #GNUTLS_EXT_TLS or %GNUTLS_EXT_APPLICATION.
404 * @recv_func: a function to receive extension data
405 * @send_func: a function to send extension data
407 * This function is used to register a new TLS extension handler.
409 * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
411 * Deprecated in: 2.12.0
414 gnutls_ext_register (int type
,
416 gnutls_ext_parse_type_t parse_type
,
417 gnutls_ext_recv_func recv_func
,
418 gnutls_ext_send_func send_func
)
420 extension_entry_st ee
;
422 memset (&ee
, 0, sizeof (ee
));
426 ee
.parse_type
= parse_type
;
427 ee
.recv_func
= recv_func
;
428 ee
.send_func
= send_func
;
429 /* FIXME: Why is this exported? Should it be removed? */
430 return _gnutls_ext_register (&ee
);
434 _gnutls_ext_pack (gnutls_session_t session
, gnutls_buffer_st
* packed
)
437 extension_priv_data_t data
;
443 total_exts_pos
= packed
->length
;
444 BUFFER_APPEND_NUM (packed
, 0);
446 for (i
= 0; i
< extfunc_size
; i
++)
448 ret
= _gnutls_ext_get_session_data (session
, extfunc
[i
].type
, &data
);
449 if (ret
>= 0 && extfunc
[i
].pack_func
!= NULL
)
451 BUFFER_APPEND_NUM (packed
, extfunc
[i
].type
);
453 size_offset
= packed
->length
;
454 BUFFER_APPEND_NUM (packed
, 0);
456 cur_size
= packed
->length
;
458 ret
= extfunc
[i
].pack_func (data
, packed
);
466 /* write the actual size */
467 _gnutls_write_uint32 (packed
->length
- cur_size
,
468 packed
->data
+ size_offset
);
472 _gnutls_write_uint32 (exts
, packed
->data
+ total_exts_pos
);
479 _gnutls_ext_restore_resumed_session (gnutls_session_t session
)
484 /* clear everything except MANDATORY extensions */
485 for (i
= 0; i
< MAX_EXT_TYPES
; i
++)
487 if (session
->internals
.extension_int_data
[i
].set
!= 0 &&
488 _gnutls_ext_parse_type (session
->internals
.
489 extension_int_data
[i
].type
) !=
490 GNUTLS_EXT_MANDATORY
)
492 _gnutls_ext_unset_session_data (session
,
494 internals
.extension_int_data
[i
].
499 /* copy resumed to main */
500 for (i
= 0; i
< MAX_EXT_TYPES
; i
++)
502 if (session
->internals
.resumed_extension_int_data
[i
].set
!= 0 &&
503 _gnutls_ext_parse_type (session
->
504 internals
.resumed_extension_int_data
[i
].
505 type
) != GNUTLS_EXT_MANDATORY
)
507 _gnutls_ext_set_session_data (session
,
509 internals
.resumed_extension_int_data
512 internals
.resumed_extension_int_data
514 session
->internals
.resumed_extension_int_data
[i
].set
= 0;
522 _gnutls_ext_set_resumed_session_data (gnutls_session_t session
, uint16_t type
,
523 extension_priv_data_t data
)
527 for (i
= 0; i
< MAX_EXT_TYPES
; i
++)
529 if (session
->internals
.resumed_extension_int_data
[i
].type
== type
530 || session
->internals
.resumed_extension_int_data
[i
].set
== 0)
533 if (session
->internals
.resumed_extension_int_data
[i
].set
!= 0)
534 _gnutls_ext_unset_resumed_session_data (session
, type
);
536 session
->internals
.resumed_extension_int_data
[i
].type
= type
;
537 session
->internals
.resumed_extension_int_data
[i
].priv
= data
;
538 session
->internals
.resumed_extension_int_data
[i
].set
= 1;
545 _gnutls_ext_unpack (gnutls_session_t session
, gnutls_buffer_st
* packed
)
548 extension_priv_data_t data
;
549 gnutls_ext_unpack_func unpack
;
552 int size_for_type
, cur_pos
;
555 BUFFER_POP_NUM (packed
, max_exts
);
556 for (i
= 0; i
< max_exts
; i
++)
558 BUFFER_POP_NUM (packed
, type
);
559 BUFFER_POP_NUM (packed
, size_for_type
);
561 cur_pos
= packed
->length
;
563 unpack
= _gnutls_ext_func_unpack (type
);
567 return GNUTLS_E_PARSING_ERROR
;
570 ret
= unpack (packed
, &data
);
577 /* verify that unpack read the correct bytes */
578 cur_pos
= cur_pos
- packed
->length
;
579 if (cur_pos
/* read length */ != size_for_type
)
582 return GNUTLS_E_PARSING_ERROR
;
585 _gnutls_ext_set_resumed_session_data (session
, type
, data
);
595 _gnutls_ext_unset_session_data (gnutls_session_t session
, uint16_t type
)
597 gnutls_ext_deinit_data_func deinit
;
598 extension_priv_data_t data
;
601 deinit
= _gnutls_ext_func_deinit (type
);
602 ret
= _gnutls_ext_get_session_data (session
, type
, &data
);
604 if (ret
>= 0 && deinit
!= NULL
)
609 for (i
= 0; i
< MAX_EXT_TYPES
; i
++)
611 if (session
->internals
.extension_int_data
[i
].type
== type
)
613 session
->internals
.extension_int_data
[i
].set
= 0;
621 _gnutls_ext_unset_resumed_session_data (gnutls_session_t session
,
624 gnutls_ext_deinit_data_func deinit
;
625 extension_priv_data_t data
;
628 deinit
= _gnutls_ext_func_deinit (type
);
629 ret
= _gnutls_ext_get_resumed_session_data (session
, type
, &data
);
631 if (ret
>= 0 && deinit
!= NULL
)
636 for (i
= 0; i
< MAX_EXT_TYPES
; i
++)
638 if (session
->internals
.resumed_extension_int_data
[i
].type
== type
)
640 session
->internals
.resumed_extension_int_data
[i
].set
= 0;
647 /* Deinitializes all data that are associated with TLS extensions.
650 _gnutls_ext_free_session_data (gnutls_session_t session
)
654 for (i
= 0; i
< extfunc_size
; i
++)
656 _gnutls_ext_unset_session_data (session
, extfunc
[i
].type
);
659 for (i
= 0; i
< extfunc_size
; i
++)
661 _gnutls_ext_unset_resumed_session_data (session
, extfunc
[i
].type
);
666 /* This function allows and extension to store data in the current session
667 * and retrieve them later on. We use functions instead of a pointer to a
668 * private pointer, to allow API additions by individual extensions.
671 _gnutls_ext_set_session_data (gnutls_session_t session
, uint16_t type
,
672 extension_priv_data_t data
)
675 gnutls_ext_deinit_data_func deinit
;
677 deinit
= _gnutls_ext_func_deinit (type
);
679 for (i
= 0; i
< MAX_EXT_TYPES
; i
++)
681 if (session
->internals
.extension_int_data
[i
].type
== type
682 || session
->internals
.extension_int_data
[i
].set
== 0)
684 if (session
->internals
.extension_int_data
[i
].set
!= 0)
687 deinit (session
->internals
.extension_int_data
[i
].priv
);
689 session
->internals
.extension_int_data
[i
].type
= type
;
690 session
->internals
.extension_int_data
[i
].priv
= data
;
691 session
->internals
.extension_int_data
[i
].set
= 1;
698 _gnutls_ext_get_session_data (gnutls_session_t session
,
699 uint16_t type
, extension_priv_data_t
* data
)
703 for (i
= 0; i
< MAX_EXT_TYPES
; i
++)
705 if (session
->internals
.extension_int_data
[i
].set
!= 0 &&
706 session
->internals
.extension_int_data
[i
].type
== type
)
708 *data
= session
->internals
.extension_int_data
[i
].priv
;
712 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
;
716 _gnutls_ext_get_resumed_session_data (gnutls_session_t session
,
718 extension_priv_data_t
* data
)
722 for (i
= 0; i
< MAX_EXT_TYPES
; i
++)
724 if (session
->internals
.resumed_extension_int_data
[i
].set
!= 0 &&
725 session
->internals
.resumed_extension_int_data
[i
].type
== type
)
727 *data
= session
->internals
.resumed_extension_int_data
[i
].priv
;
731 return GNUTLS_E_INVALID_REQUEST
;