summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile.am6
-rw-r--r--lib/ext_oprfi.c227
-rw-r--r--lib/ext_oprfi.h33
-rw-r--r--lib/gnutls_extensions.c6
-rw-r--r--lib/gnutls_int.h11
-rw-r--r--lib/gnutls_kx.c72
6 files changed, 349 insertions, 6 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am
index b20abb621d..50c83e31a3 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -80,6 +80,10 @@ if ENABLE_AUTHZ
COBJECTS += ext_authz.c
endif
+if ENABLE_OPRFI
+COBJECTS += ext_oprfi.c
+endif
+
HFILES = debug.h gnutls_compress.h defines.h gnutls_cipher.h \
gnutls_buffers.h gnutls_errors.h gnutls_int.h \
gnutls_handshake.h gnutls_num.h gnutls_algorithms.h \
@@ -95,7 +99,7 @@ HFILES = debug.h gnutls_compress.h defines.h gnutls_cipher.h \
ext_srp.h gnutls_srp.h auth_srp.h auth_srp_passwd.h \
gnutls_helper.h auth_psk.h auth_psk_passwd.h \
ext_inner_application.h gnutls_extra_hooks.h \
- gnutls_supplemental.h ext_authz.h
+ gnutls_supplemental.h ext_authz.h ext_oprfi.h
# Separate so we can create the documentation
diff --git a/lib/ext_oprfi.c b/lib/ext_oprfi.c
new file mode 100644
index 0000000000..9741641e5e
--- /dev/null
+++ b/lib/ext_oprfi.c
@@ -0,0 +1,227 @@
+/*
+ * 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
+ *
+ */
+
+/* Implementation of Opaque PRF Input:
+ * http://tools.ietf.org/id/draft-rescorla-tls-opaque-prf-input-00.txt
+ *
+ */
+
+#include <ext_oprfi.h>
+
+#include <gnutls_errors.h>
+#include <gnutls_num.h>
+
+int
+oprfi_recv_server (gnutls_session_t session,
+ const opaque * data,
+ size_t _data_size)
+{
+ ssize_t data_size = _data_size;
+ uint16_t len;
+ int ret;
+
+ if (!session->security_parameters.extensions.oprfi_cb)
+ {
+ gnutls_assert ();
+ return 0;
+ }
+
+ DECR_LEN (data_size, 2);
+ len = _gnutls_read_uint16 (data);
+ data += 2;
+
+ if (len != data_size)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
+ }
+
+ /* Store incoming data. */
+ session->security_parameters.extensions.oprfi_client_len = len;
+ session->security_parameters.extensions.oprfi_client = gnutls_malloc (len);
+ if (!session->security_parameters.extensions.oprfi_client)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+ memcpy (session->security_parameters.extensions.oprfi_client, data, len);
+
+ return 0;
+}
+
+int
+oprfi_recv_client (gnutls_session_t session,
+ const opaque * data,
+ size_t _data_size)
+{
+ ssize_t data_size = _data_size;
+ uint16_t len;
+ int ret;
+
+ if (session->security_parameters.extensions.oprfi_client == NULL)
+ {
+ gnutls_assert ();
+ return 0;
+ }
+
+ DECR_LEN (data_size, 2);
+ len = _gnutls_read_uint16 (data);
+ data += 2;
+
+ if (len != data_size)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
+ }
+
+ if (len != session->security_parameters.extensions.oprfi_client_len)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
+ }
+
+ /* Store incoming data. */
+ session->security_parameters.extensions.oprfi_server_len = len;
+ session->security_parameters.extensions.oprfi_server = gnutls_malloc (len);
+ if (!session->security_parameters.extensions.oprfi_server)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+ memcpy (session->security_parameters.extensions.oprfi_server, data, len);
+
+ return 0;
+}
+
+int
+_gnutls_oprfi_recv_params (gnutls_session_t session,
+ const opaque * data,
+ size_t data_size)
+{
+ if (session->security_parameters.entity == GNUTLS_CLIENT)
+ return oprfi_recv_client (session, data, data_size);
+ else
+ return oprfi_recv_server (session, data, data_size);
+}
+
+int
+oprfi_send_client (gnutls_session_t session,
+ opaque * data,
+ size_t _data_size)
+{
+ opaque *p = data;
+ ssize_t data_size = _data_size;
+ int oprf_size = session->security_parameters.extensions.oprfi_client_len;
+
+ if (oprf_size == 0)
+ return 0;
+
+ DECR_LENGTH_RET (data_size, 2, GNUTLS_E_SHORT_MEMORY_BUFFER);
+ _gnutls_write_uint16 (oprf_size, p);
+ p += 2;
+
+ DECR_LENGTH_RET (data_size, oprf_size, GNUTLS_E_SHORT_MEMORY_BUFFER);
+
+ memcpy (p, session->security_parameters.extensions.oprfi_client, oprf_size);
+
+ return 2 + oprf_size;
+}
+
+int
+oprfi_send_server (gnutls_session_t session,
+ opaque * data,
+ size_t _data_size)
+{
+ opaque *p = data;
+ int ret;
+ ssize_t data_size = _data_size;
+ size_t len;
+
+ /* Allocate buffer for outgoing data. */
+ session->security_parameters.extensions.oprfi_server_len =
+ session->security_parameters.extensions.oprfi_client_len;
+ session->security_parameters.extensions.oprfi_server =
+ gnutls_malloc (session->security_parameters.extensions.oprfi_server_len);
+ if (!session->security_parameters.extensions.oprfi_server)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ /* Get outgoing data. */
+ ret = session->security_parameters.extensions.oprfi_cb
+ (session, session->security_parameters.extensions.oprfi_userdata,
+ session->security_parameters.extensions.oprfi_client_len,
+ session->security_parameters.extensions.oprfi_client,
+ session->security_parameters.extensions.oprfi_server);
+ if (ret < 0)
+ {
+ gnutls_assert ();
+ gnutls_free (session->security_parameters.extensions.oprfi_server);
+ return ret;
+ }
+
+ DECR_LENGTH_RET (data_size, 2, GNUTLS_E_SHORT_MEMORY_BUFFER);
+ _gnutls_write_uint16 (session->security_parameters.
+ extensions.oprfi_server_len, p);
+ p += 2;
+
+ DECR_LENGTH_RET (data_size, session->security_parameters.
+ extensions.oprfi_server_len, GNUTLS_E_SHORT_MEMORY_BUFFER);
+
+ memcpy (p, session->security_parameters.extensions.oprfi_server,
+ session->security_parameters.extensions.oprfi_server_len);
+
+ return 2 + session->security_parameters.extensions.oprfi_server_len;
+}
+
+int
+_gnutls_oprfi_send_params (gnutls_session_t session,
+ opaque * data,
+ size_t data_size)
+{
+ if (session->security_parameters.entity == GNUTLS_CLIENT)
+ return oprfi_send_client (session, data, data_size);
+ else
+ return oprfi_send_server (session, data, data_size);
+}
+
+void
+gnutls_oprfi_enable_client (gnutls_session_t session,
+ size_t len,
+ unsigned char *data)
+{
+ session->security_parameters.extensions.oprfi_client_len = len;
+ session->security_parameters.extensions.oprfi_client = data;
+}
+
+
+void
+gnutls_oprfi_enable_server (gnutls_session_t session,
+ gnutls_oprfi_callback_func cb,
+ void *userdata)
+{
+ session->security_parameters.extensions.oprfi_cb = cb;
+ session->security_parameters.extensions.oprfi_userdata = userdata;
+}
diff --git a/lib/ext_oprfi.h b/lib/ext_oprfi.h
new file mode 100644
index 0000000000..7f75be9c7e
--- /dev/null
+++ b/lib/ext_oprfi.h
@@ -0,0 +1,33 @@
+/*
+ * 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_oprfi_recv_params (gnutls_session_t state,
+ const opaque * data,
+ size_t data_size);
+
+int _gnutls_oprfi_send_params (gnutls_session_t state,
+ opaque * data,
+ size_t data_size);
diff --git a/lib/gnutls_extensions.c b/lib/gnutls_extensions.c
index bb6a64d49a..20b1bbd414 100644
--- a/lib/gnutls_extensions.c
+++ b/lib/gnutls_extensions.c
@@ -33,6 +33,7 @@
#include "ext_max_record.h"
#include <ext_cert_type.h>
#include <ext_server_name.h>
+#include <ext_oprfi.h>
#include <ext_srp.h>
#include <ext_inner_application.h>
#include <ext_authz.h>
@@ -64,6 +65,11 @@ gnutls_extension_entry _gnutls_extensions[MAX_EXT_SIZE] = {
GNUTLS_EXTENSION_ENTRY (GNUTLS_EXTENSION_SERVER_NAME,
_gnutls_server_name_recv_params,
_gnutls_server_name_send_params),
+#ifdef ENABLE_OPRFI
+ GNUTLS_EXTENSION_ENTRY (GNUTLS_EXTENSION_OPAQUE_PRF_INPUT,
+ _gnutls_oprfi_recv_params,
+ _gnutls_oprfi_send_params),
+#endif
#ifdef ENABLE_SRP
GNUTLS_EXTENSION_ENTRY (GNUTLS_EXTENSION_SRP,
_gnutls_srp_recv_params,
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index 3e6ef39575..1c9f10e5f5 100644
--- a/lib/gnutls_int.h
+++ b/lib/gnutls_int.h
@@ -144,6 +144,9 @@ typedef enum extensions_t
GNUTLS_EXTENSION_AUTHZ_CLIENT = 7,
GNUTLS_EXTENSION_AUTHZ_SERVER = 8,
GNUTLS_EXTENSION_CERT_TYPE = 9,
+#ifdef ENABLE_OPRFI
+ GNUTLS_EXTENSION_OPAQUE_PRF_INPUT = ENABLE_OPRFI,
+#endif
GNUTLS_EXTENSION_SRP = 12,
GNUTLS_EXTENSION_INNER_APPLICATION = 37703
} extensions_t;
@@ -284,6 +287,14 @@ typedef struct
gnutls_authz_recv_callback_func authz_recv_callback;
gnutls_authz_send_callback_func authz_send_callback;
gnutls_buffer authz_data;
+
+ /* Opaque PRF input. */
+ gnutls_oprfi_callback_func oprfi_cb;
+ void *oprfi_userdata;
+ opaque *oprfi_client;
+ uint16_t oprfi_client_len;
+ opaque *oprfi_server;
+ uint16_t oprfi_server_len;
} tls_ext_st;
/* auth_info_t structures now MAY contain malloced
diff --git a/lib/gnutls_kx.c b/lib/gnutls_kx.c
index edd1fb696a..05a5dc95dd 100644
--- a/lib/gnutls_kx.c
+++ b/lib/gnutls_kx.c
@@ -59,13 +59,8 @@ static int
generate_normal_master (gnutls_session_t session, int keep_premaster)
{
int ret = 0;
- opaque rnd[2 * TLS_RANDOM_SIZE + 1];
char buf[512];
- memcpy (rnd, session->security_parameters.client_random, TLS_RANDOM_SIZE);
- memcpy (&rnd[TLS_RANDOM_SIZE],
- session->security_parameters.server_random, TLS_RANDOM_SIZE);
-
_gnutls_hard_log ("INT: PREMASTER SECRET[%d]: %s\n", PREMASTER.size,
_gnutls_bin2hex (PREMASTER.data, PREMASTER.size, buf,
sizeof (buf)));
@@ -78,6 +73,12 @@ generate_normal_master (gnutls_session_t session, int keep_premaster)
if (gnutls_protocol_get_version (session) == GNUTLS_SSL3)
{
+ opaque rnd[2 * TLS_RANDOM_SIZE + 1];
+
+ memcpy (rnd, session->security_parameters.client_random, TLS_RANDOM_SIZE);
+ memcpy (&rnd[TLS_RANDOM_SIZE],
+ session->security_parameters.server_random, TLS_RANDOM_SIZE);
+
ret =
_gnutls_ssl3_generate_random (PREMASTER.data, PREMASTER.size,
rnd, 2 * TLS_RANDOM_SIZE,
@@ -86,8 +87,69 @@ generate_normal_master (gnutls_session_t session, int keep_premaster)
master_secret);
}
+ else if (session->security_parameters.extensions.oprfi_client_len > 0 &&
+ session->security_parameters.extensions.oprfi_server_len > 0)
+ {
+ opaque *rnd;
+ size_t rndlen = 2 * TLS_RANDOM_SIZE;
+
+ rndlen += session->security_parameters.extensions.oprfi_client_len;
+ rndlen += session->security_parameters.extensions.oprfi_server_len;
+
+ rnd = gnutls_malloc (rndlen + 1);
+ if (!rnd)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ _gnutls_hard_log ("INT: CLIENT OPRFI[%d]: %s\n",
+ session->security_parameters.
+ extensions.oprfi_server_len,
+ _gnutls_bin2hex (session->security_parameters.
+ extensions.oprfi_client,
+ session->security_parameters.
+ extensions.oprfi_client_len,
+ buf, sizeof (buf)));
+ _gnutls_hard_log ("INT: SERVER OPRFI[%d]: %s\n",
+ session->security_parameters.
+ extensions.oprfi_server_len,
+ _gnutls_bin2hex (session->security_parameters.
+ extensions.oprfi_server,
+ session->security_parameters.
+ extensions.oprfi_server_len,
+ buf, sizeof (buf)));
+
+ memcpy (rnd, session->security_parameters.client_random,
+ TLS_RANDOM_SIZE);
+ memcpy (rnd + TLS_RANDOM_SIZE,
+ session->security_parameters.extensions.oprfi_client,
+ session->security_parameters.extensions.oprfi_client_len);
+ memcpy (rnd + TLS_RANDOM_SIZE +
+ session->security_parameters.extensions.oprfi_client_len,
+ session->security_parameters.server_random,
+ TLS_RANDOM_SIZE);
+ memcpy (rnd + TLS_RANDOM_SIZE +
+ session->security_parameters.extensions.oprfi_client_len +
+ TLS_RANDOM_SIZE,
+ session->security_parameters.extensions.oprfi_server,
+ session->security_parameters.extensions.oprfi_server_len);
+
+ ret = _gnutls_PRF (session, PREMASTER.data, PREMASTER.size,
+ MASTER_SECRET, strlen (MASTER_SECRET),
+ rnd, rndlen, TLS_MASTER_SIZE,
+ session->security_parameters.master_secret);
+
+ gnutls_free (rnd);
+ }
else
{
+ opaque rnd[2 * TLS_RANDOM_SIZE + 1];
+
+ memcpy (rnd, session->security_parameters.client_random, TLS_RANDOM_SIZE);
+ memcpy (&rnd[TLS_RANDOM_SIZE],
+ session->security_parameters.server_random, TLS_RANDOM_SIZE);
+
ret =
_gnutls_PRF (session, PREMASTER.data, PREMASTER.size,
MASTER_SECRET, strlen (MASTER_SECRET),