diff options
author | Simon Josefsson <simon@josefsson.org> | 2007-02-21 10:43:29 +0000 |
---|---|---|
committer | Simon Josefsson <simon@josefsson.org> | 2007-02-21 10:43:29 +0000 |
commit | fb9ecf7b5f0269eadd9d2f739611da222ef9f9a0 (patch) | |
tree | 4a4787052a15df68de884489e3a1a1f0621d8dc3 | |
parent | bb17ae85820a43a952e841420bd58df40a0f2465 (diff) | |
download | gnutls-fb9ecf7b5f0269eadd9d2f739611da222ef9f9a0.tar.gz |
New file.
-rw-r--r-- | lib/gnutls_supplemental.c | 197 | ||||
-rw-r--r-- | lib/gnutls_supplemental.h | 35 |
2 files changed, 232 insertions, 0 deletions
diff --git a/lib/gnutls_supplemental.c b/lib/gnutls_supplemental.c new file mode 100644 index 0000000000..183647d944 --- /dev/null +++ b/lib/gnutls_supplemental.c @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2007 Free Software Foundation + * + * Author: Simon Josefsson + * + * This file is part of GNUTLS. + * + * The GNUTLS library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA + * + */ + +/* This file contains support functions for 'TLS Handshake Message for + * Supplemental Data' (RFC 4680). + * + * The idea here is simple. gnutls_handshake() in gnuts_handshake.c + * will call _gnutls_gen_supplemental and _gnutls_parse_supplemental + * when some extension requested that supplemental data be sent or + * received. Extension request this by setting the flags + * do_recv_supplemental or do_send_supplemental in the session. + * + * The functions in this file iterate through the _gnutls_supplemental + * array, and calls the send/recv functions for each respective data + * type. + * + * The receive function of each data type is responsible for decoding + * its own data. If the extension did not expect to receive + * supplemental data, it should return GNUTLS_E_UNEXPECTED_PACKET. + * Otherwise, it just parse the data as normal. + * + * The send function needs to append the 2-byte data format type, and + * append the 2-byte length of its data, and the data. If it doesn't + * want to send any data, it is fine to return without doing anything. + */ + +#include "gnutls_int.h" +#include "gnutls_supplemental.h" +#include "gnutls_errors.h" +#include "gnutls_num.h" + +typedef struct +{ + const char *name; + gnutls_supplemental_data_format_type_t type; + supp_recv_func supp_recv_func; + supp_send_func supp_send_func; +} gnutls_supplemental_entry; + +gnutls_supplemental_entry _gnutls_supplemental[] = { + { 0, 0, 0, 0 } +}; + +const char * +gnutls_supplemental_get_name (gnutls_supplemental_data_format_type_t type) +{ + gnutls_supplemental_entry *p; + + for(p = _gnutls_supplemental; p->name != NULL; p++) + if(p->type == type) + return p->name; + + return NULL; +} + +static supp_recv_func +get_supp_func_recv (gnutls_supplemental_data_format_type_t type) +{ + gnutls_supplemental_entry *p; + + for(p = _gnutls_supplemental; p->name != NULL; p++) + if(p->type == type) + return p->supp_recv_func; + + return NULL; +} + +int +_gnutls_gen_supplemental (gnutls_session_t session) +{ + gnutls_supplemental_entry *p; + gnutls_buffer *buf = &session->security_parameters.extensions.supp_data; + int ret; + + /* Make room for 3 byte length field. */ + ret = _gnutls_buffer_append (buf, "\0\0\0", 3); + if (ret < 0) + { + gnutls_assert (); + return ret; + } + + for(p = _gnutls_supplemental; p->name; p++) + { + supp_send_func supp_send = p->supp_send_func; + int ret; + + _gnutls_debug_log ("EXT[%x]: Generating supplemental %s\n", session, + gnutls_supplemental_get_name (p->type)); + + ret = supp_send (session); + if (ret < 0) + { + gnutls_assert (); + return ret; + } + } + + if (buf->length > 3) + { + buf->data[0] = ((buf->length - 3) << 16) & 0xFF; + buf->data[1] = ((buf->length - 3) << 8) & 0xFF; + buf->data[2] = (buf->length - 3) & 0xFF; + } + else + { + ret = _gnutls_string_copy_str (buf, ""); + if (ret < 0) + { + gnutls_assert (); + return ret; + } + } + + return buf->length; +} + +int +_gnutls_parse_supplemental (gnutls_session_t session, + const uint8_t * data, + int datalen) +{ + const opaque *p = data; + ssize_t dsize = datalen; + size_t total_size; + + DECR_LEN (dsize, 3); + total_size = _gnutls_read_uint24 (p); + p += 3; + + if (dsize != total_size) + { + gnutls_assert(); + return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; + } + + do + { + uint16_t supp_data_type; + uint16_t supp_data_length; + supp_recv_func recv_func; + + DECR_LEN (dsize, 2); + supp_data_type = _gnutls_read_uint16 (p); + p += 2; + + DECR_LEN (dsize, 2); + supp_data_length = _gnutls_read_uint16 (p); + p += 2; + + _gnutls_debug_log ("EXT[%x]: Got supplemental type=%d length=%d\n", + session, supp_data_type, supp_data_length); + + recv_func = get_supp_func_recv (supp_data_type); + if (recv_func) + { + int ret = recv_func (session, p, supp_data_length); + if (ret < 0) + { + gnutls_assert (); + return ret; + } + } + else + { + gnutls_assert (); + return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; + } + + DECR_LEN (dsize, supp_data_length); + p += supp_data_length; + } + while (dsize > 0); + + return 0; +} diff --git a/lib/gnutls_supplemental.h b/lib/gnutls_supplemental.h new file mode 100644 index 0000000000..32bd6174c8 --- /dev/null +++ b/lib/gnutls_supplemental.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2007 Free Software Foundation + * + * Author: Simon Josefsson + * + * This file is part of GNUTLS. + * + * The GNUTLS library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA + * + */ + +#include <gnutls_int.h> + +int _gnutls_parse_supplemental (gnutls_session_t session, + const uint8_t *data, + int data_size); +int _gnutls_gen_supplemental (gnutls_session_t session); + +typedef int (*supp_recv_func) (gnutls_session_t session, + const opaque *data, + size_t data_size); +typedef int (*supp_send_func) (gnutls_session_t session); |