2 * Copyright (C) 2007, 2008, 2010 Free Software Foundation, Inc.
4 * Author: 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 2.1 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
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
25 /* This file contains support functions for 'TLS Handshake Message for
26 * Supplemental Data' (RFC 4680).
28 * The idea here is simple. gnutls_handshake() in gnuts_handshake.c
29 * will call _gnutls_gen_supplemental and _gnutls_parse_supplemental
30 * when some extension requested that supplemental data be sent or
31 * received. Extension request this by setting the flags
32 * do_recv_supplemental or do_send_supplemental in the session.
34 * The functions in this file iterate through the _gnutls_supplemental
35 * array, and calls the send/recv functions for each respective data
38 * The receive function of each data type is responsible for decoding
39 * its own data. If the extension did not expect to receive
40 * supplemental data, it should return GNUTLS_E_UNEXPECTED_PACKET.
41 * Otherwise, it just parse the data as normal.
43 * The send function needs to append the 2-byte data format type, and
44 * append the 2-byte length of its data, and the data. If it doesn't
45 * want to send any data, it is fine to return without doing anything.
48 #include "gnutls_int.h"
49 #include "gnutls_supplemental.h"
50 #include "gnutls_errors.h"
51 #include "gnutls_num.h"
53 typedef int (*supp_recv_func
) (gnutls_session_t session
,
54 const opaque
* data
, size_t data_size
);
55 typedef int (*supp_send_func
) (gnutls_session_t session
,
56 gnutls_buffer_st
* buf
);
61 gnutls_supplemental_data_format_type_t type
;
62 supp_recv_func supp_recv_func
;
63 supp_send_func supp_send_func
;
64 } gnutls_supplemental_entry
;
66 gnutls_supplemental_entry _gnutls_supplemental
[] = {
71 * gnutls_supplemental_get_name:
72 * @type: is a supplemental data format type
74 * Convert a #gnutls_supplemental_data_format_type_t value to a
77 * Returns: a string that contains the name of the specified
78 * supplemental data format type, or %NULL for unknown types.
81 gnutls_supplemental_get_name (gnutls_supplemental_data_format_type_t type
)
83 gnutls_supplemental_entry
*p
;
85 for (p
= _gnutls_supplemental
; p
->name
!= NULL
; p
++)
93 get_supp_func_recv (gnutls_supplemental_data_format_type_t type
)
95 gnutls_supplemental_entry
*p
;
97 for (p
= _gnutls_supplemental
; p
->name
!= NULL
; p
++)
99 return p
->supp_recv_func
;
105 _gnutls_gen_supplemental (gnutls_session_t session
, gnutls_buffer_st
* buf
)
107 gnutls_supplemental_entry
*p
;
110 /* Make room for 3 byte length field. */
111 ret
= _gnutls_buffer_append_data (buf
, "\0\0\0", 3);
118 for (p
= _gnutls_supplemental
; p
->name
; p
++)
120 supp_send_func supp_send
= p
->supp_send_func
;
121 size_t sizepos
= buf
->length
;
123 /* Make room for supplement type and length byte length field. */
124 ret
= _gnutls_buffer_append_data (buf
, "\0\0\0\0", 4);
131 ret
= supp_send (session
, buf
);
138 /* If data were added, store type+length, otherwise reset. */
139 if (buf
->length
> sizepos
+ 4)
141 buf
->data
[sizepos
] = 0;
142 buf
->data
[sizepos
+ 1] = p
->type
;
143 buf
->data
[sizepos
+ 2] = ((buf
->length
- sizepos
- 4) >> 8) & 0xFF;
144 buf
->data
[sizepos
+ 3] = (buf
->length
- sizepos
- 4) & 0xFF;
150 buf
->data
[0] = ((buf
->length
- 3) >> 16) & 0xFF;
151 buf
->data
[1] = ((buf
->length
- 3) >> 8) & 0xFF;
152 buf
->data
[2] = (buf
->length
- 3) & 0xFF;
154 _gnutls_debug_log ("EXT[%p]: Sending %d bytes of supplemental data\n",
155 session
, (int) buf
->length
);
161 _gnutls_parse_supplemental (gnutls_session_t session
,
162 const uint8_t * data
, int datalen
)
164 const opaque
*p
= data
;
165 ssize_t dsize
= datalen
;
169 total_size
= _gnutls_read_uint24 (p
);
172 if (dsize
!= (ssize_t
) total_size
)
175 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER
;
180 uint16_t supp_data_type
;
181 uint16_t supp_data_length
;
182 supp_recv_func recv_func
;
185 supp_data_type
= _gnutls_read_uint16 (p
);
189 supp_data_length
= _gnutls_read_uint16 (p
);
192 _gnutls_debug_log ("EXT[%p]: Got supplemental type=%02x length=%d\n",
193 session
, supp_data_type
, supp_data_length
);
195 recv_func
= get_supp_func_recv (supp_data_type
);
198 int ret
= recv_func (session
, p
, supp_data_length
);
208 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER
;
211 DECR_LEN (dsize
, supp_data_length
);
212 p
+= supp_data_length
;