summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Josefsson <simon@josefsson.org>2007-02-21 10:43:29 +0000
committerSimon Josefsson <simon@josefsson.org>2007-02-21 10:43:29 +0000
commitfb9ecf7b5f0269eadd9d2f739611da222ef9f9a0 (patch)
tree4a4787052a15df68de884489e3a1a1f0621d8dc3
parentbb17ae85820a43a952e841420bd58df40a0f2465 (diff)
downloadgnutls-fb9ecf7b5f0269eadd9d2f739611da222ef9f9a0.tar.gz
New file.
-rw-r--r--lib/gnutls_supplemental.c197
-rw-r--r--lib/gnutls_supplemental.h35
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);