diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Makefile.am | 6 | ||||
-rw-r--r-- | lib/ext_oprfi.c | 227 | ||||
-rw-r--r-- | lib/ext_oprfi.h | 33 | ||||
-rw-r--r-- | lib/gnutls_extensions.c | 6 | ||||
-rw-r--r-- | lib/gnutls_int.h | 11 | ||||
-rw-r--r-- | lib/gnutls_kx.c | 72 |
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), |