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/session_ticket.h>
36 #include <ext/safe_renegotiation.h>
37 #include <ext/signature.h>
38 #include <ext/safe_renegotiation.h>
40 #include <gnutls_num.h>
43 static void _gnutls_ext_unset_resumed_session_data (gnutls_session_t session
,
47 static size_t extfunc_size
= 0;
48 static extension_entry_st
*extfunc
= NULL
;
50 static gnutls_ext_parse_type_t
51 _gnutls_ext_parse_type (uint16_t type
)
55 for (i
= 0; i
< extfunc_size
; i
++)
57 if (extfunc
[i
].type
== type
)
58 return extfunc
[i
].parse_type
;
61 return GNUTLS_EXT_NONE
;
64 static gnutls_ext_recv_func
65 _gnutls_ext_func_recv (uint16_t type
, gnutls_ext_parse_type_t parse_type
)
69 for (i
= 0; i
< extfunc_size
; i
++)
70 if (extfunc
[i
].type
== type
)
71 if (parse_type
== GNUTLS_EXT_ANY
|| extfunc
[i
].parse_type
== parse_type
)
72 return extfunc
[i
].recv_func
;
77 static gnutls_ext_deinit_data_func
78 _gnutls_ext_func_deinit (uint16_t type
)
82 for (i
= 0; i
< extfunc_size
; i
++)
83 if (extfunc
[i
].type
== type
)
84 return extfunc
[i
].deinit_func
;
89 static gnutls_ext_unpack_func
90 _gnutls_ext_func_unpack (uint16_t type
)
94 for (i
= 0; i
< extfunc_size
; i
++)
95 if (extfunc
[i
].type
== type
)
96 return extfunc
[i
].unpack_func
;
103 _gnutls_extension_get_name (uint16_t type
)
107 for (i
= 0; i
< extfunc_size
; i
++)
108 if (extfunc
[i
].type
== type
)
109 return extfunc
[i
].name
;
114 /* Checks if the extension we just received is one of the
115 * requested ones. Otherwise it's a fatal error.
118 _gnutls_extension_list_check (gnutls_session_t session
, uint16_t type
)
120 if (session
->security_parameters
.entity
== GNUTLS_CLIENT
)
124 for (i
= 0; i
< session
->internals
.extensions_sent_size
; i
++)
126 if (type
== session
->internals
.extensions_sent
[i
])
127 return 0; /* ok found */
130 return GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION
;
137 _gnutls_parse_extensions (gnutls_session_t session
,
138 gnutls_ext_parse_type_t parse_type
,
139 const uint8_t * data
, int data_size
)
144 const uint8_t *sdata
;
145 gnutls_ext_recv_func ext_recv
;
151 if (session
->security_parameters
.entity
== GNUTLS_CLIENT
)
152 for (i
= 0; i
< session
->internals
.extensions_sent_size
; i
++)
154 _gnutls_handshake_log ("EXT[%d]: expecting extension '%s'\n",
156 _gnutls_extension_get_name
157 (session
->internals
.extensions_sent
[i
]));
161 DECR_LENGTH_RET (data_size
, 2, 0);
162 next
= _gnutls_read_uint16 (data
);
165 DECR_LENGTH_RET (data_size
, next
, 0);
169 DECR_LENGTH_RET (next
, 2, 0);
170 type
= _gnutls_read_uint16 (&data
[pos
]);
174 _gnutls_handshake_log ("EXT[%p]: Found extension '%s/%d'\n", session
,
175 _gnutls_extension_get_name (type
), type
);
178 if ((ret
= _gnutls_extension_list_check (session
, type
)) < 0)
184 DECR_LENGTH_RET (next
, 2, 0);
185 size
= _gnutls_read_uint16 (&data
[pos
]);
188 DECR_LENGTH_RET (next
, size
, 0);
192 ext_recv
= _gnutls_ext_func_recv (type
, parse_type
);
193 if (ext_recv
== NULL
)
196 _gnutls_handshake_log ("EXT[%p]: Parsing extension '%s/%d' (%d bytes)\n",
197 session
, _gnutls_extension_get_name (type
), type
,
200 if ((ret
= ext_recv (session
, sdata
, size
)) < 0)
213 /* Adds the extension we want to send in the extensions list.
214 * This list is used to check whether the (later) received
215 * extensions are the ones we requested.
218 _gnutls_extension_list_add (gnutls_session_t session
, uint16_t type
)
221 if (session
->security_parameters
.entity
== GNUTLS_CLIENT
)
223 if (session
->internals
.extensions_sent_size
< MAX_EXT_TYPES
)
225 session
->internals
.extensions_sent
[session
->internals
.
226 extensions_sent_size
] = type
;
227 session
->internals
.extensions_sent_size
++;
231 _gnutls_handshake_log ("extensions: Increase MAX_EXT_TYPES\n");
237 _gnutls_gen_extensions (gnutls_session_t session
, gnutls_buffer_st
* extdata
,
238 gnutls_ext_parse_type_t parse_type
)
241 int pos
, size_pos
, ret
;
242 size_t i
, init_size
= extdata
->length
;
244 pos
= extdata
->length
; /* we will store length later on */
245 _gnutls_buffer_append_prefix( extdata
, 16, 0);
247 for (i
= 0; i
< extfunc_size
; i
++)
249 extension_entry_st
*p
= &extfunc
[i
];
251 if (p
->send_func
== NULL
)
254 if (parse_type
!= GNUTLS_EXT_ANY
&& p
->parse_type
!= parse_type
)
257 ret
= _gnutls_buffer_append_prefix( extdata
, 16, p
->type
);
259 return gnutls_assert_val(ret
);
261 size_pos
= extdata
->length
;
262 ret
= _gnutls_buffer_append_prefix (extdata
, 16, 0);
264 return gnutls_assert_val(ret
);
266 size
= p
->send_func (session
, extdata
);
267 /* returning GNUTLS_E_INT_RET_0 means to send an empty
268 * extension of this type.
270 if (size
> 0 || size
== GNUTLS_E_INT_RET_0
)
272 if (size
== GNUTLS_E_INT_RET_0
)
275 /* write the real size */
276 _gnutls_write_uint16(size
, &extdata
->data
[size_pos
]);
278 /* add this extension to the extension list
280 _gnutls_extension_list_add (session
, p
->type
);
282 _gnutls_handshake_log ("EXT[%p]: Sending extension %s (%d bytes)\n",
283 session
, p
->name
, size
);
291 extdata
->length
-= 4; /* reset type and size */
294 /* remove any initial data, and the size of the header */
295 size
= extdata
->length
- init_size
- 2;
298 _gnutls_write_uint16(size
, &extdata
->data
[pos
]);
299 else if (size
== 0) extdata
->length
-= 2; /* the length bytes */
305 _gnutls_ext_init (void)
309 ret
= _gnutls_ext_register (&ext_mod_max_record_size
);
310 if (ret
!= GNUTLS_E_SUCCESS
)
313 ret
= _gnutls_ext_register (&ext_mod_cert_type
);
314 if (ret
!= GNUTLS_E_SUCCESS
)
318 ret
= _gnutls_ext_register (&ext_mod_server_name
);
319 if (ret
!= GNUTLS_E_SUCCESS
)
322 ret
= _gnutls_ext_register (&ext_mod_sr
);
323 if (ret
!= GNUTLS_E_SUCCESS
)
327 ret
= _gnutls_ext_register (&ext_mod_srp
);
328 if (ret
!= GNUTLS_E_SUCCESS
)
332 ret
= _gnutls_ext_register (&ext_mod_session_ticket
);
333 if (ret
!= GNUTLS_E_SUCCESS
)
336 ret
= _gnutls_ext_register (&ext_mod_supported_ecc
);
337 if (ret
!= GNUTLS_E_SUCCESS
)
340 ret
= _gnutls_ext_register (&ext_mod_supported_ecc_pf
);
341 if (ret
!= GNUTLS_E_SUCCESS
)
344 ret
= _gnutls_ext_register (&ext_mod_sig
);
345 if (ret
!= GNUTLS_E_SUCCESS
)
348 return GNUTLS_E_SUCCESS
;
352 _gnutls_ext_deinit (void)
354 gnutls_free (extfunc
);
360 _gnutls_ext_register (extension_entry_st
* mod
)
362 extension_entry_st
*p
;
364 p
= gnutls_realloc (extfunc
, sizeof (*extfunc
) * (extfunc_size
+ 1));
368 return GNUTLS_E_MEMORY_ERROR
;
373 memcpy (&extfunc
[extfunc_size
], mod
, sizeof (*mod
));
377 return GNUTLS_E_SUCCESS
;
381 _gnutls_ext_pack (gnutls_session_t session
, gnutls_buffer_st
* packed
)
385 extension_priv_data_t data
;
391 total_exts_pos
= packed
->length
;
392 BUFFER_APPEND_NUM (packed
, 0);
394 for (i
= 0; i
< extfunc_size
; i
++)
396 ret
= _gnutls_ext_get_session_data (session
, extfunc
[i
].type
, &data
);
397 if (ret
>= 0 && extfunc
[i
].pack_func
!= NULL
)
399 BUFFER_APPEND_NUM (packed
, extfunc
[i
].type
);
401 size_offset
= packed
->length
;
402 BUFFER_APPEND_NUM (packed
, 0);
404 cur_size
= packed
->length
;
406 ret
= extfunc
[i
].pack_func (data
, packed
);
414 /* write the actual size */
415 _gnutls_write_uint32 (packed
->length
- cur_size
,
416 packed
->data
+ size_offset
);
420 _gnutls_write_uint32 (exts
, packed
->data
+ total_exts_pos
);
427 _gnutls_ext_restore_resumed_session (gnutls_session_t session
)
432 /* clear everything except MANDATORY extensions */
433 for (i
= 0; i
< MAX_EXT_TYPES
; i
++)
435 if (session
->internals
.extension_int_data
[i
].set
!= 0 &&
436 _gnutls_ext_parse_type (session
->internals
.
437 extension_int_data
[i
].type
) !=
438 GNUTLS_EXT_MANDATORY
)
440 _gnutls_ext_unset_session_data (session
,
442 internals
.extension_int_data
[i
].
447 /* copy resumed to main */
448 for (i
= 0; i
< MAX_EXT_TYPES
; i
++)
450 if (session
->internals
.resumed_extension_int_data
[i
].set
!= 0 &&
451 _gnutls_ext_parse_type (session
->
452 internals
.resumed_extension_int_data
[i
].
453 type
) != GNUTLS_EXT_MANDATORY
)
455 _gnutls_ext_set_session_data (session
,
457 internals
.resumed_extension_int_data
460 internals
.resumed_extension_int_data
462 session
->internals
.resumed_extension_int_data
[i
].set
= 0;
470 _gnutls_ext_set_resumed_session_data (gnutls_session_t session
, uint16_t type
,
471 extension_priv_data_t data
)
475 for (i
= 0; i
< MAX_EXT_TYPES
; i
++)
477 if (session
->internals
.resumed_extension_int_data
[i
].type
== type
478 || session
->internals
.resumed_extension_int_data
[i
].set
== 0)
481 if (session
->internals
.resumed_extension_int_data
[i
].set
!= 0)
482 _gnutls_ext_unset_resumed_session_data (session
, type
);
484 session
->internals
.resumed_extension_int_data
[i
].type
= type
;
485 session
->internals
.resumed_extension_int_data
[i
].priv
= data
;
486 session
->internals
.resumed_extension_int_data
[i
].set
= 1;
493 _gnutls_ext_unpack (gnutls_session_t session
, gnutls_buffer_st
* packed
)
496 extension_priv_data_t data
;
497 gnutls_ext_unpack_func unpack
;
500 int size_for_type
, cur_pos
;
503 BUFFER_POP_NUM (packed
, max_exts
);
504 for (i
= 0; i
< max_exts
; i
++)
506 BUFFER_POP_NUM (packed
, type
);
507 BUFFER_POP_NUM (packed
, size_for_type
);
509 cur_pos
= packed
->length
;
511 unpack
= _gnutls_ext_func_unpack (type
);
515 return GNUTLS_E_PARSING_ERROR
;
518 ret
= unpack (packed
, &data
);
525 /* verify that unpack read the correct bytes */
526 cur_pos
= cur_pos
- packed
->length
;
527 if (cur_pos
/* read length */ != size_for_type
)
530 return GNUTLS_E_PARSING_ERROR
;
533 _gnutls_ext_set_resumed_session_data (session
, type
, data
);
543 _gnutls_ext_unset_session_data (gnutls_session_t session
, uint16_t type
)
545 gnutls_ext_deinit_data_func deinit
;
546 extension_priv_data_t data
;
549 deinit
= _gnutls_ext_func_deinit (type
);
550 ret
= _gnutls_ext_get_session_data (session
, type
, &data
);
552 if (ret
>= 0 && deinit
!= NULL
)
557 for (i
= 0; i
< MAX_EXT_TYPES
; i
++)
559 if (session
->internals
.extension_int_data
[i
].type
== type
)
561 session
->internals
.extension_int_data
[i
].set
= 0;
569 _gnutls_ext_unset_resumed_session_data (gnutls_session_t session
,
572 gnutls_ext_deinit_data_func deinit
;
573 extension_priv_data_t data
;
576 deinit
= _gnutls_ext_func_deinit (type
);
577 ret
= _gnutls_ext_get_resumed_session_data (session
, type
, &data
);
579 if (ret
>= 0 && deinit
!= NULL
)
584 for (i
= 0; i
< MAX_EXT_TYPES
; i
++)
586 if (session
->internals
.resumed_extension_int_data
[i
].type
== type
)
588 session
->internals
.resumed_extension_int_data
[i
].set
= 0;
595 /* Deinitializes all data that are associated with TLS extensions.
598 _gnutls_ext_free_session_data (gnutls_session_t session
)
602 for (i
= 0; i
< extfunc_size
; i
++)
604 _gnutls_ext_unset_session_data (session
, extfunc
[i
].type
);
607 for (i
= 0; i
< extfunc_size
; i
++)
609 _gnutls_ext_unset_resumed_session_data (session
, extfunc
[i
].type
);
614 /* This function allows and extension to store data in the current session
615 * and retrieve them later on. We use functions instead of a pointer to a
616 * private pointer, to allow API additions by individual extensions.
619 _gnutls_ext_set_session_data (gnutls_session_t session
, uint16_t type
,
620 extension_priv_data_t data
)
623 gnutls_ext_deinit_data_func deinit
;
625 deinit
= _gnutls_ext_func_deinit (type
);
627 for (i
= 0; i
< MAX_EXT_TYPES
; i
++)
629 if (session
->internals
.extension_int_data
[i
].type
== type
630 || session
->internals
.extension_int_data
[i
].set
== 0)
632 if (session
->internals
.extension_int_data
[i
].set
!= 0)
635 deinit (session
->internals
.extension_int_data
[i
].priv
);
637 session
->internals
.extension_int_data
[i
].type
= type
;
638 session
->internals
.extension_int_data
[i
].priv
= data
;
639 session
->internals
.extension_int_data
[i
].set
= 1;
646 _gnutls_ext_get_session_data (gnutls_session_t session
,
647 uint16_t type
, extension_priv_data_t
* data
)
651 for (i
= 0; i
< MAX_EXT_TYPES
; i
++)
653 if (session
->internals
.extension_int_data
[i
].set
!= 0 &&
654 session
->internals
.extension_int_data
[i
].type
== type
)
656 *data
= session
->internals
.extension_int_data
[i
].priv
;
660 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
;
664 _gnutls_ext_get_resumed_session_data (gnutls_session_t session
,
666 extension_priv_data_t
* data
)
670 for (i
= 0; i
< MAX_EXT_TYPES
; i
++)
672 if (session
->internals
.resumed_extension_int_data
[i
].set
!= 0 &&
673 session
->internals
.resumed_extension_int_data
[i
].type
== type
)
675 *data
= session
->internals
.resumed_extension_int_data
[i
].priv
;
679 return GNUTLS_E_INVALID_REQUEST
;