the internal API to store/retrieve during resumption.
Removed OPRFI since it was never standardized and was never actually included in gnutls
since it was in inactive ifdef. This was instead of rewriting it to use the new API.
* Version 2.11.0 (unreleased)
+** libgnutls: Internal API for extensions augmented to allow
+safe storing and loading of data on resumption. OPRFI extension
+was removed.
+
** libgnutls: Added support for DSA-SHA256 and DSA-SHA224
** libgnutls: Added PKCS #11 support and an API to access objects in
* Server examples::
* Miscellaneous examples::
* Compatibility with the OpenSSL library::
-* Opaque PRF Input TLS Extension::
* Keying Material Exporters::
@end menu
@end itemize
-@node Opaque PRF Input TLS Extension
-@section Opaque PRF Input TLS Extension
-@cindex Opaque PRF Input
-
-GnuTLS supports the Opaque PRF Input TLS extension
-(@code{draft-rescorla-tls-opaque-prf-input-00.txt}). The API consists
-of one API for use in the client, @ref{gnutls_oprfi_enable_client},
-and one API for use in the server, @ref{gnutls_oprfi_enable_server}.
-You must invoke both functions before calling @ref{gnutls_handshake}.
-The server utilizes a callback function into the application. The
-callback can look at the random string provided by the client, and
-also set the server string. The string lengths must be equal
-according to the protocol.
-
@node Keying Material Exporters
@section Keying Material Exporters
@cindex Keying Material Exporters
#include "auth_srp.h"
#include <gnutls_str.h>
#include <gnutls_datum.h>
+#include <ext_srp.h>
const mod_auth_st srp_auth_struct = {
"SRP",
size_t n_b, tmp_size;
char buf[64];
uint8_t *data_b;
+ extension_priv_data_t epriv;
+ srp_ext_st * priv;
+
+ ret = _gnutls_ext_get_session_data( session, GNUTLS_EXTENSION_SRP, &epriv);
+ if (ret < 0) /* peer didn't send a username */
+ {
+ gnutls_assert();
+ return GNUTLS_E_UNKNOWN_SRP_USERNAME;
+ }
+ priv = epriv.ptr;
if ((ret =
_gnutls_auth_info_set (session, GNUTLS_CRD_SRP,
info = _gnutls_get_auth_info (session);
username = info->username;
- _gnutls_str_cpy (username, MAX_SRP_USERNAME,
- session->security_parameters.extensions.srp_username);
+ _gnutls_str_cpy (username, MAX_SRP_USERNAME, priv->username);
ret = _gnutls_srp_pwd_read_entry (session, username, &pwd_entry);
char *username, *password;
char buf[64];
gnutls_srp_client_credentials_t cred;
+ extension_priv_data_t epriv;
+ srp_ext_st * priv;
+ ret = _gnutls_ext_get_session_data( session, GNUTLS_EXTENSION_SRP, &epriv);
+ if (ret < 0) /* peer didn't send a username */
+ {
+ gnutls_assert();
+ return GNUTLS_E_UNKNOWN_SRP_USERNAME;
+ }
+ priv = epriv.ptr;
cred = (gnutls_srp_client_credentials_t)
_gnutls_get_cred (session->key, GNUTLS_CRD_SRP, NULL);
return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
}
- if (session->internals.srp_username == NULL)
+ if (priv->username == NULL)
{
username = cred->username;
password = cred->password;
}
else
{
- username = session->internals.srp_username;
- password = session->internals.srp_password;
+
+ username = priv->username;
+ password = priv->password;
}
if (username == NULL || password == NULL)
char *username, *password;
ssize_t data_size = _data_size;
gnutls_srp_client_credentials_t cred;
+ extension_priv_data_t epriv;
+ srp_ext_st * priv;
+
+ ret = _gnutls_ext_get_session_data( session, GNUTLS_EXTENSION_SRP, &epriv);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ return GNUTLS_E_UNKNOWN_SRP_USERNAME;
+ }
+ priv = epriv.ptr;
cred = (gnutls_srp_client_credentials_t)
_gnutls_get_cred (session->key, GNUTLS_CRD_SRP, NULL);
return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
}
- if (session->internals.srp_username == NULL)
+ if (priv->username == NULL)
{
username = cred->username;
password = cred->password;
}
else
{
- username = session->internals.srp_username;
- password = session->internals.srp_password;
+ username = priv->username;
+ password = priv->password;
}
if (username == NULL || password == NULL)
#include <gnutls_state.h>
#include <gnutls_num.h>
+/* Maps record size to numbers according to the
+ * extensions draft.
+ */
inline static int _gnutls_num2cert_type (int num);
inline static int _gnutls_cert_type2num (int record_size);
+static int _gnutls_cert_type_recv_params (gnutls_session_t session,
+ const opaque * data, size_t data_size);
+static int _gnutls_cert_type_send_params (gnutls_session_t session, opaque * data,
+ size_t);
+
+extension_entry_st ext_mod_cert_type = {
+ .name = "CERT TYPE",
+ .type = GNUTLS_EXTENSION_CERT_TYPE,
+ .parse_type = GNUTLS_EXT_TLS,
+
+ .recv_func = _gnutls_cert_type_recv_params,
+ .send_func = _gnutls_cert_type_send_params,
+ .pack_func = NULL,
+ .unpack_func = NULL,
+ .deinit_func = NULL
+};
/*
* In case of a server: if a CERT_TYPE extension type is received then it stores
*
*/
-int
+static int
_gnutls_cert_type_recv_params (gnutls_session_t session,
const opaque * data, size_t _data_size)
{
/* returns data_size or a negative number on failure
*/
-int
+static int
_gnutls_cert_type_send_params (gnutls_session_t session, opaque * data,
size_t data_size)
{
*
*/
-/* Maps record size to numbers according to the
- * extensions draft.
- */
-int _gnutls_cert_type_recv_params (gnutls_session_t session,
- const opaque * data, size_t data_size);
-int _gnutls_cert_type_send_params (gnutls_session_t session, opaque * data,
- size_t);
+#ifndef EXT_CERT_TYPE_H
+#define EXT_CERT_TYPE_H
+
+#include <gnutls_extensions.h>
+
+extern extension_entry_st ext_mod_cert_type;
+
+#endif
#include "gnutls_int.h"
#include "gnutls_errors.h"
#include "gnutls_num.h"
+#include <gnutls_extensions.h>
#include <ext_max_record.h>
+static int _gnutls_max_record_recv_params (gnutls_session_t session,
+ const opaque * data, size_t data_size);
+static int _gnutls_max_record_send_params (gnutls_session_t session, opaque * data,
+ size_t);
+
+static int _gnutls_max_record_unpack(gnutls_buffer_st* ps, extension_priv_data_t* _priv);
+static int _gnutls_max_record_pack(extension_priv_data_t _priv, gnutls_buffer_st* ps);
+
+/* Maps record size to numbers according to the
+ * extensions draft.
+ */
+static int _gnutls_mre_num2record (int num);
+static int _gnutls_mre_record2num (uint16_t record_size);
+
+
+extension_entry_st ext_mod_max_record_size = {
+ .name = "MAX RECORD SIZE",
+ .type = GNUTLS_EXTENSION_MAX_RECORD_SIZE,
+ .parse_type = GNUTLS_EXT_TLS,
+
+ .recv_func = _gnutls_max_record_recv_params,
+ .send_func = _gnutls_max_record_send_params,
+ .pack_func = _gnutls_max_record_pack,
+ .unpack_func = _gnutls_max_record_unpack,
+ .deinit_func = NULL
+};
+
/*
* In case of a server: if a MAX_RECORD_SIZE extension type is received then it stores
* into the session the new value. The server may use gnutls_get_max_record_size(),
*
*/
-int
+static int
_gnutls_max_record_recv_params (gnutls_session_t session,
const opaque * data, size_t _data_size)
{
ssize_t new_size;
ssize_t data_size = _data_size;
+ extension_priv_data_t epriv;
+ int ret;
if (session->security_parameters.entity == GNUTLS_SERVER)
{
}
}
else
- { /* CLIENT SIDE - we must check if the sent record size is the right one
- */
+ { /* CLIENT SIDE - we must check if the sent record size is the right one
+ */
if (data_size > 0)
{
+ ret = _gnutls_ext_get_session_data( session,
+ GNUTLS_EXTENSION_MAX_RECORD_SIZE, &epriv);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
if (data_size != 1)
{
new_size = _gnutls_mre_num2record (data[0]);
- if (new_size < 0
- || new_size != session->internals.proposed_record_size)
+ if (new_size < 0 || new_size != epriv.num)
{
gnutls_assert ();
return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
else
{
session->security_parameters.max_record_recv_size =
- session->internals.proposed_record_size;
+ epriv.num;
}
}
/* returns data_size or a negative number on failure
*/
-int
+static int
_gnutls_max_record_send_params (gnutls_session_t session, opaque * data,
size_t data_size)
{
uint16_t len;
+ int ret;
+
/* this function sends the client extension data (dnsname) */
if (session->security_parameters.entity == GNUTLS_CLIENT)
{
+ extension_priv_data_t epriv;
+
+ ret = _gnutls_ext_get_session_data( session,
+ GNUTLS_EXTENSION_MAX_RECORD_SIZE, &epriv);
+ if (ret < 0) /* it is ok not to have it */
+ {
+ return 0;
+ }
- if (session->internals.proposed_record_size != DEFAULT_MAX_RECORD_SIZE)
+ if (epriv.num != DEFAULT_MAX_RECORD_SIZE)
{
len = 1;
if (data_size < len)
}
data[0] =
- (uint8_t) _gnutls_mre_record2num (session->
- internals.proposed_record_size);
+ (uint8_t) _gnutls_mre_record2num (epriv.num);
return len;
}
return 0;
}
+
+static int _gnutls_max_record_pack(extension_priv_data_t epriv, gnutls_buffer_st* ps)
+{
+int ret;
+
+ BUFFER_APPEND_NUM(ps, epriv.num);
+
+ return 0;
+
+}
+
+static int _gnutls_max_record_unpack(gnutls_buffer_st* ps, extension_priv_data_t* _priv)
+{
+extension_priv_data_t epriv;
+int ret;
+
+ BUFFER_POP_NUM(ps, epriv.num);
+
+ *_priv = epriv;
+
+ ret = 0;
+error:
+ return ret;
+}
+
+
/* Maps numbers to record sizes according to the
* extensions draft.
*/
-int
+static int
_gnutls_mre_num2record (int num)
{
switch (num)
/* Maps record size to numbers according to the
* extensions draft.
*/
-int
+static int
_gnutls_mre_record2num (uint16_t record_size)
{
switch (record_size)
}
}
+
+/**
+ * gnutls_record_get_max_size:
+ * @session: is a #gnutls_session_t structure.
+ *
+ * Get the record size. The maximum record size is negotiated by the
+ * client after the first handshake message.
+ *
+ * Returns: The maximum record packet size in this connection.
+ **/
+size_t
+gnutls_record_get_max_size (gnutls_session_t session)
+{
+ /* Recv will hold the negotiated max record size
+ * always.
+ */
+ return session->security_parameters.max_record_recv_size;
+}
+
+
+/**
+ * gnutls_record_set_max_size:
+ * @session: is a #gnutls_session_t structure.
+ * @size: is the new size
+ *
+ * This function sets the maximum record packet size in this
+ * connection. This property can only be set to clients. The server
+ * may choose not to accept the requested size.
+ *
+ * Acceptable values are 512(=2^9), 1024(=2^10), 2048(=2^11) and
+ * 4096(=2^12). The requested record size does get in effect
+ * immediately only while sending data. The receive part will take
+ * effect after a successful handshake.
+ *
+ * This function uses a TLS extension called 'max record size'. Not
+ * all TLS implementations use or even understand this extension.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (zero) is returned,
+ * otherwise an error code is returned.
+ **/
+ssize_t
+gnutls_record_set_max_size (gnutls_session_t session, size_t size)
+{
+ ssize_t new_size;
+ extension_priv_data_t epriv;
+
+ if (session->security_parameters.entity == GNUTLS_SERVER)
+ return GNUTLS_E_INVALID_REQUEST;
+
+ new_size = _gnutls_mre_record2num (size);
+
+ if (new_size < 0)
+ {
+ gnutls_assert ();
+ return new_size;
+ }
+
+ session->security_parameters.max_record_send_size = size;
+ epriv.num = size;
+
+ _gnutls_ext_set_session_data(session, GNUTLS_EXTENSION_MAX_RECORD_SIZE, epriv);
+
+ return 0;
+}
*
*/
-/* Maps record size to numbers according to the
- * extensions draft.
- */
-int _gnutls_mre_num2record (int num);
-int _gnutls_mre_record2num (uint16_t record_size);
-int _gnutls_max_record_recv_params (gnutls_session_t session,
- const opaque * data, size_t data_size);
-int _gnutls_max_record_send_params (gnutls_session_t session, opaque * data,
- size_t);
+#ifndef EXT_MAX_RECORD_H
+#define EXT_MAX_RECORD_H
+
+#include <gnutls_extensions.h>
+
+extern extension_entry_st ext_mod_max_record_size;
+
+#endif
+++ /dev/null
-/*
- * Copyright (C) 2007, 2010 Free Software Foundation, Inc.
- *
- * Author: Simon Josefsson
- *
- * This file is part of GnuTLS.
- *
- * The GnuTLS 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->internals.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;
-
- if (!session->security_parameters.extensions.oprfi_client ||
- !session->internals.oprfi_cb)
- return 0;
-
- /* 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->internals.oprfi_cb
- (session, session->internals.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);
-}
-
-/**
- * gnutls_oprfi_enable_client:
- * @session: is a #gnutls_session_t structure.
- * @len: length of Opaque PRF data to use in client.
- * @data: Opaque PRF data to use in client.
- *
- * Request that the client should attempt to negotiate the Opaque PRF
- * Input TLS extension, using the given data as the client's Opaque
- * PRF input.
- *
- * The data is copied into the session context after this call, so you
- * may de-allocate it immediately after calling this function.
- **/
-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;
-}
-
-/**
- * gnutls_oprfi_enable_server:
- * @session: is a #gnutls_session_t structure.
- * @cb: function pointer to Opaque PRF extension server callback.
- * @userdata: hook passed to callback function for passing application state.
- *
- * Request that the server should attempt to accept the Opaque PRF
- * Input TLS extension. If the client requests the extension, the
- * provided callback @cb will be invoked. The callback must have the
- * following prototype:
- *
- * int callback (gnutls_session_t session, void *userdata,
- * size_t oprfi_len, const unsigned char *in_oprfi,
- * unsigned char *out_oprfi);
- *
- * The callback can inspect the client-provided data in the input
- * parameters, and specify its own opaque prf input data in the output
- * variable. The function must return 0 on success, otherwise the
- * handshake will be aborted.
- **/
-void
-gnutls_oprfi_enable_server (gnutls_session_t session,
- gnutls_oprfi_callback_func cb, void *userdata)
-{
- session->internals.oprfi_cb = cb;
- session->internals.oprfi_userdata = userdata;
-}
+++ /dev/null
-/*
- * Copyright (C) 2007, 2010 Free Software Foundation, Inc.
- *
- * Author: Simon Josefsson
- *
- * This file is part of GnuTLS.
- *
- * The GnuTLS 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);
#include <ext_safe_renegotiation.h>
#include <gnutls_errors.h>
-int
-_gnutls_safe_renegotiation_recv_params (gnutls_session_t session,
+
+static int _gnutls_sr_recv_params (gnutls_session_t state,
+ const opaque * data,
+ size_t data_size);
+static int _gnutls_sr_send_params (gnutls_session_t state,
+ opaque * data, size_t);
+static int _gnutls_sr_pack(extension_priv_data_t epriv, gnutls_buffer_st* ps);
+static int _gnutls_sr_unpack(gnutls_buffer_st* ps, extension_priv_data_t* _priv);
+static void _gnutls_sr_deinit_data(extension_priv_data_t priv);
+
+extension_entry_st ext_mod_sr = {
+ .name = "SAFE RENEGOTIATION",
+ .type = GNUTLS_EXTENSION_SAFE_RENEGOTIATION,
+ .parse_type = GNUTLS_EXT_MANDATORY,
+
+ .recv_func = _gnutls_sr_recv_params,
+ .send_func = _gnutls_sr_send_params,
+ .pack_func = NULL,
+ .unpack_func = NULL,
+ .deinit_func = _gnutls_sr_deinit_data,
+};
+
+int _gnutls_ext_sr_finished( gnutls_session_t session, void* vdata, size_t vdata_size, int dir)
+{
+int ret;
+sr_ext_st* priv;
+extension_priv_data_t epriv;
+
+ if (session->internals.priorities.sr == SR_DISABLED)
+ {
+ return 0;
+ }
+
+ ret = _gnutls_ext_get_session_data( session,
+ GNUTLS_EXTENSION_SAFE_RENEGOTIATION, &epriv);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ return ret;
+ }
+ priv = epriv.ptr;
+
+ /* Save data for safe renegotiation.
+ */
+ if (vdata_size > MAX_VERIFY_DATA_SIZE)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ if ((session->security_parameters.entity == GNUTLS_CLIENT && dir == 0) ||
+ (session->security_parameters.entity == GNUTLS_SERVER && dir == 1))
+ {
+ priv->client_verify_data_len = vdata_size;
+ memcpy (priv->client_verify_data, vdata, vdata_size);
+ }
+ else
+ {
+ priv->server_verify_data_len = vdata_size;
+ memcpy (priv->server_verify_data, vdata, vdata_size);
+ }
+
+ return 0;
+}
+
+int _gnutls_ext_sr_verify(gnutls_session_t session)
+{
+int ret;
+sr_ext_st* priv = NULL;
+extension_priv_data_t epriv;
+
+ if (session->internals.priorities.sr == SR_DISABLED)
+ {
+ gnutls_assert ();
+ return 0;
+ }
+
+ ret = _gnutls_ext_get_session_data( session,
+ GNUTLS_EXTENSION_SAFE_RENEGOTIATION, &epriv);
+ if (ret >= 0)
+ priv = epriv.ptr;
+
+ /* Safe renegotiation */
+
+ if (priv && priv->safe_renegotiation_received)
+ {
+ if ((priv->ri_extension_data_len < priv->client_verify_data_len) ||
+ (memcmp (priv->ri_extension_data,
+ priv->client_verify_data, priv->client_verify_data_len)))
+ {
+ gnutls_assert ();
+ _gnutls_handshake_log ("HSK[%p]: Safe renegotiation failed [1]\n",
+ session);
+ return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
+ }
+
+ if (session->security_parameters.entity == GNUTLS_CLIENT)
+ {
+ if ((priv->ri_extension_data_len !=
+ priv->client_verify_data_len + priv->server_verify_data_len) ||
+ memcmp (priv->ri_extension_data + priv->client_verify_data_len,
+ priv->server_verify_data,
+ priv->server_verify_data_len) != 0)
+ {
+ gnutls_assert ();
+ _gnutls_handshake_log
+ ("HSK[%p]: Safe renegotiation failed [2]\n", session);
+ return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
+ }
+ }
+ else /* Make sure there are 0 extra bytes */
+ {
+ if (priv->ri_extension_data_len != priv->client_verify_data_len)
+ {
+ gnutls_assert ();
+ _gnutls_handshake_log
+ ("HSK[%p]: Safe renegotiation failed [3]\n", session);
+ return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
+ }
+ }
+
+ _gnutls_handshake_log ("HSK[%p]: Safe renegotiation succeeded\n",
+ session);
+ }
+ else /* safe renegotiation not received... */
+ {
+ if (priv && priv->connection_using_safe_renegotiation)
+ {
+ gnutls_assert ();
+ _gnutls_handshake_log
+ ("HSK[%p]: Peer previously asked for safe renegotiation\n",
+ session);
+ return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
+ }
+
+ /* Clients can't tell if it's an initial negotiation */
+ if (session->internals.initial_negotiation_completed)
+ {
+ if (session->internals.priorities.sr < SR_PARTIAL)
+ {
+ _gnutls_handshake_log
+ ("HSK[%p]: Allowing unsafe (re)negotiation\n", session);
+ }
+ else
+ {
+ gnutls_assert ();
+ _gnutls_handshake_log
+ ("HSK[%p]: Denying unsafe (re)negotiation\n", session);
+ return GNUTLS_E_UNSAFE_RENEGOTIATION_DENIED;
+ }
+ }
+ else
+ {
+ if (session->internals.priorities.sr < SR_SAFE)
+ {
+ _gnutls_handshake_log
+ ("HSK[%p]: Allowing unsafe initial negotiation\n", session);
+ }
+ else
+ {
+ gnutls_assert ();
+ _gnutls_handshake_log
+ ("HSK[%p]: Denying unsafe initial negotiation\n", session);
+ return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/* if a server received the special ciphersuite.
+ */
+int _gnutls_ext_sr_recv_cs(gnutls_session_t session)
+{
+ int ret, set = 0;
+ sr_ext_st* priv;
+ extension_priv_data_t epriv;
+
+ ret = _gnutls_ext_get_session_data( session,
+ GNUTLS_EXTENSION_SAFE_RENEGOTIATION, &epriv);
+ if (ret < 0)
+ {
+ set = 1;
+ }
+ else if (ret < 0)
+ {
+ gnutls_assert();
+ return ret;
+ }
+
+ if (set != 0)
+ {
+ priv = gnutls_calloc(1, sizeof(*priv));
+ if (priv == NULL)
+ {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+ epriv.ptr = priv;
+ }
+ else
+ priv = epriv.ptr;
+
+ priv->safe_renegotiation_received = 1;
+ priv->connection_using_safe_renegotiation = 1;
+
+ if (set != 0)
+ _gnutls_ext_set_session_data( session, GNUTLS_EXTENSION_SAFE_RENEGOTIATION, epriv);
+
+ return 0;
+}
+
+static int
+_gnutls_sr_recv_params (gnutls_session_t session,
const opaque * data,
size_t _data_size)
{
- tls_ext_st *ext = &session->security_parameters.extensions;
int len = data[0];
ssize_t data_size = _data_size;
+ sr_ext_st* priv;
+ extension_priv_data_t epriv;
+ int set = 0, ret;
DECR_LEN (data_size, len + 1 /* count the first byte and payload */ );
return 0;
}
+ ret = _gnutls_ext_get_session_data( session,
+ GNUTLS_EXTENSION_SAFE_RENEGOTIATION, &epriv);
+ if (ret < 0 && session->security_parameters.entity == GNUTLS_SERVER)
+ {
+ set = 1;
+ }
+ else if (ret < 0)
+ {
+ gnutls_assert();
+ return ret;
+ }
+
+ if (set != 0)
+ {
+ priv = gnutls_calloc(1, sizeof(*priv));
+ if (priv == NULL)
+ {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+ epriv.ptr = priv;
+ }
+ else
+ priv = epriv.ptr;
+
/* It is not legal to receive this extension on a renegotiation and
* not receive it on the initial negotiation.
*/
if (session->internals.initial_negotiation_completed != 0 &&
- session->internals.connection_using_safe_renegotiation == 0)
+ priv->connection_using_safe_renegotiation == 0)
{
gnutls_assert ();
return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
}
- if (len > sizeof (ext->ri_extension_data))
+ if (len > sizeof (priv->ri_extension_data))
{
gnutls_assert ();
return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
}
if (len > 0)
- memcpy (ext->ri_extension_data, &data[1], len);
- ext->ri_extension_data_len = len;
+ memcpy (priv->ri_extension_data, &data[1], len);
+ priv->ri_extension_data_len = len;
/* "safe renegotiation received" means on *this* handshake; "connection using
* safe renegotiation" means that the initial hello received on the connection
* indicated safe renegotiation.
*/
- session->internals.safe_renegotiation_received = 1;
- session->internals.connection_using_safe_renegotiation = 1;
+ priv->safe_renegotiation_received = 1;
+ priv->connection_using_safe_renegotiation = 1;
+ if (set != 0)
+ _gnutls_ext_set_session_data( session, GNUTLS_EXTENSION_SAFE_RENEGOTIATION, epriv);
return 0;
}
-int
-_gnutls_safe_renegotiation_send_params (gnutls_session_t session,
+static int
+_gnutls_sr_send_params (gnutls_session_t session,
opaque * data, size_t _data_size)
{
/* The format of this extension is a one-byte length of verify data followed
* the minimum extension is one byte: 0x00.
*/
ssize_t data_size = _data_size;
- tls_ext_st *ext = &session->security_parameters.extensions;
+ sr_ext_st* priv;
+ int ret, set = 0;
+ extension_priv_data_t epriv;
if (session->internals.priorities.sr == SR_DISABLED)
{
return 0;
}
+ ret = _gnutls_ext_get_session_data( session,
+ GNUTLS_EXTENSION_SAFE_RENEGOTIATION, &epriv);
+ if (ret < 0)
+ {
+ set = 1;
+ }
+
+ if (set != 0)
+ {
+ priv = gnutls_calloc(1, sizeof(*priv));
+ if (priv == NULL)
+ {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+ epriv.ptr = priv;
+
+ _gnutls_ext_set_session_data( session, GNUTLS_EXTENSION_SAFE_RENEGOTIATION, epriv);
+ }
+ else
+ priv = epriv.ptr;
+
data[0] = 0;
/* Always offer the extension if we're a client */
- if (session->internals.connection_using_safe_renegotiation ||
+ if (priv->connection_using_safe_renegotiation ||
session->security_parameters.entity == GNUTLS_CLIENT)
{
DECR_LEN (data_size, 1);
- data[0] = ext->client_verify_data_len;
+ data[0] = priv->client_verify_data_len;
- DECR_LEN (data_size, ext->client_verify_data_len);
+ DECR_LEN (data_size, priv->client_verify_data_len);
- if (ext->client_verify_data_len > 0)
- memcpy (&data[1], ext->client_verify_data,
- ext->client_verify_data_len);
+ if (priv->client_verify_data_len > 0)
+ memcpy (&data[1], priv->client_verify_data, priv->client_verify_data_len);
if (session->security_parameters.entity == GNUTLS_SERVER)
- {
- data[0] += ext->server_verify_data_len;
+ {
+ data[0] += priv->server_verify_data_len;
- DECR_LEN (data_size, ext->server_verify_data_len);
+ DECR_LEN (data_size, priv->server_verify_data_len);
- if (ext->server_verify_data_len > 0)
- memcpy (&data[1 + ext->client_verify_data_len],
- ext->server_verify_data, ext->server_verify_data_len);
- }
+ if (priv->server_verify_data_len > 0)
+ memcpy (&data[1 + priv->client_verify_data_len],
+ priv->server_verify_data, priv->server_verify_data_len);
+ }
}
else
return 0;
return 1 + data[0]; /* don't forget the length byte */
}
+static void _gnutls_sr_deinit_data(extension_priv_data_t priv)
+{
+ gnutls_free(priv.ptr);
+}
+
+#if 0
+
+static int _gnutls_sr_pack(extension_priv_data_t epriv, gnutls_buffer_st* ps)
+{
+sr_ext_st* priv = epriv.ptr;
+int ret;
+
+ BUFFER_APPEND_PFX(ps, priv->client_verify_data, priv->client_verify_data_len);
+ BUFFER_APPEND_PFX(ps, priv->server_verify_data, priv->server_verify_data_len);
+ BUFFER_APPEND_PFX(ps, priv->ri_extension_data, priv->ri_extension_data_len);
+
+ return 0;
+}
+
+static int _gnutls_sr_unpack(gnutls_buffer_st* ps, extension_priv_data_t* _priv)
+{
+sr_ext_st* priv;
+int ret;
+extension_priv_data_t epriv;
+
+ priv = gnutls_calloc(1, sizeof(*priv));
+ if (priv == NULL)
+ {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ BUFFER_POP_NUM(ps, priv->client_verify_data_len);
+ BUFFER_POP(ps, priv->client_verify_data, priv->client_verify_data_len);
+
+ BUFFER_POP_NUM(ps, priv->server_verify_data_len);
+ BUFFER_POP(ps, priv->server_verify_data, priv->server_verify_data_len);
+
+ BUFFER_POP_NUM(ps, priv->ri_extension_data_len);
+ BUFFER_POP(ps, priv->ri_extension_data, priv->ri_extension_data_len);
+
+ epriv.ptr = priv;
+ *_priv = epriv;
+
+ ret = 0;
+
+error:
+ return ret;
+}
+
+#endif
+
/**
* gnutls_safe_renegotiation_status:
* @session: is a #gnutls_session_t structure.
int
gnutls_safe_renegotiation_status (gnutls_session_t session)
{
- return session->internals.connection_using_safe_renegotiation;
+int ret;
+sr_ext_st* priv;
+extension_priv_data_t epriv;
+
+ ret = _gnutls_ext_get_session_data( session,
+ GNUTLS_EXTENSION_SAFE_RENEGOTIATION, &epriv);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ return 0;
+ }
+ priv = epriv.ptr;
+
+ return priv->connection_using_safe_renegotiation;
}
+
#ifndef EXT_SAFE_RENEGOTIATION_H
# define EXT_SAFE_RENEGOTIATION_H
-int _gnutls_safe_renegotiation_recv_params (gnutls_session_t state,
- const opaque * data,
- size_t data_size);
-int _gnutls_safe_renegotiation_send_params (gnutls_session_t state,
- opaque * data, size_t);
+#include <gnutls_extensions.h>
+
+typedef struct {
+ uint8_t client_verify_data[MAX_VERIFY_DATA_SIZE];
+ size_t client_verify_data_len;
+ uint8_t server_verify_data[MAX_VERIFY_DATA_SIZE];
+ size_t server_verify_data_len;
+ uint8_t ri_extension_data[MAX_VERIFY_DATA_SIZE * 2]; /* max signal is 72 bytes in s->c sslv3 */
+ size_t ri_extension_data_len;
+
+ int safe_renegotiation_received:1;
+ int initial_negotiation_completed:1;
+ int connection_using_safe_renegotiation:1;
+} sr_ext_st;
+
+extern extension_entry_st ext_mod_sr;
+
+int _gnutls_ext_sr_finished( gnutls_session_t session, void* vdata,
+ size_t vdata_size, int dir);
+int _gnutls_ext_sr_recv_cs(gnutls_session_t session);
+int _gnutls_ext_sr_verify(gnutls_session_t session);
#endif /* EXT_SAFE_RENEGOTIATION_H */
#include "gnutls_num.h"
#include <ext_server_name.h>
+static int _gnutls_server_name_recv_params (gnutls_session_t session,
+ const opaque * data, size_t data_size);
+static int _gnutls_server_name_send_params (gnutls_session_t session,
+ opaque * data, size_t);
+
+static int _gnutls_server_name_unpack(gnutls_buffer_st* ps, extension_priv_data_t* _priv);
+static int _gnutls_server_name_pack(extension_priv_data_t _priv, gnutls_buffer_st* ps);
+static void _gnutls_server_name_deinit_data(extension_priv_data_t priv);
+
+
+extension_entry_st ext_mod_server_name = {
+ .name = "SERVER NAME",
+ .type = GNUTLS_EXTENSION_SERVER_NAME,
+ .parse_type = GNUTLS_EXT_APPLICATION,
+
+ .recv_func = _gnutls_server_name_recv_params,
+ .send_func = _gnutls_server_name_send_params,
+ .pack_func = _gnutls_server_name_pack,
+ .unpack_func = _gnutls_server_name_unpack,
+ .deinit_func = _gnutls_server_name_deinit_data,
+};
+
/*
* In case of a server: if a NAME_DNS extension type is received then
* it stores into the session the value of NAME_DNS. The server may
* in the session then it sends the extension to the peer.
*
*/
-
-int
-_gnutls_server_name_recv_params (gnutls_session_t session,
+static int _gnutls_server_name_recv_params (gnutls_session_t session,
const opaque * data, size_t _data_size)
{
int i;
uint16_t len, type;
ssize_t data_size = _data_size;
int server_names = 0;
-
+ server_name_ext_st* priv;
+ extension_priv_data_t epriv;
+
if (session->security_parameters.entity == GNUTLS_SERVER)
{
DECR_LENGTH_RET (data_size, 2, 0);
server_names = MAX_SERVER_NAME_EXTENSIONS;
}
- session->security_parameters.extensions.server_names_size =
- server_names;
if (server_names == 0)
return 0; /* no names found */
+ priv = gnutls_calloc(1, sizeof(*priv));
+ if (priv == NULL)
+ {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ priv->server_names_size = server_names;
p = data + 2;
for (i = 0; i < server_names; i++)
switch (type)
{
- case 0: /* NAME_DNS */
+ case 0: /* NAME_DNS */
if (len <= MAX_SERVER_NAME_SIZE)
{
- memcpy (session->security_parameters.
- extensions.server_names[i].name, p, len);
- session->security_parameters.extensions.server_names[i].
- name_length = len;
- session->security_parameters.extensions.server_names[i].
- type = GNUTLS_NAME_DNS;
+ memcpy (priv->server_names[i].name, p, len);
+ priv->server_names[i].name_length = len;
+ priv->server_names[i].type = GNUTLS_NAME_DNS;
break;
}
}
/* move to next record */
p += len;
}
+
+ epriv.ptr = priv;
+ _gnutls_ext_set_session_data(session, GNUTLS_EXTENSION_SERVER_NAME, epriv);
+
}
+
return 0;
}
/* returns data_size or a negative number on failure
*/
-int
+static int
_gnutls_server_name_send_params (gnutls_session_t session,
opaque * data, size_t _data_size)
{
opaque *p;
unsigned i;
ssize_t data_size = _data_size;
- int total_size = 0;
+ int total_size = 0, ret;
+ server_name_ext_st* priv;
+ extension_priv_data_t epriv;
+
+ ret = _gnutls_ext_get_session_data( session, GNUTLS_EXTENSION_SERVER_NAME, &epriv);
+ if (ret < 0)
+ return 0;
+
/* this function sends the client extension data (dnsname)
*/
if (session->security_parameters.entity == GNUTLS_CLIENT)
{
+ priv = epriv.ptr;
- if (session->security_parameters.extensions.server_names_size == 0)
+ if (priv->server_names_size == 0)
return 0;
/* uint16_t
*/
total_size = 2;
for (i = 0;
- i < session->security_parameters.extensions.server_names_size; i++)
+ i < priv->server_names_size; i++)
{
/* count the total size
*/
- len =
- session->security_parameters.extensions.
- server_names[i].name_length;
+ len = priv->server_names[i].name_length;
/* uint8_t + uint16_t + size
*/
DECR_LENGTH_RET (data_size, 2, GNUTLS_E_SHORT_MEMORY_BUFFER);
_gnutls_write_uint16 (total_size - 2, p);
p += 2;
-
for (i = 0;
- i < session->security_parameters.extensions.server_names_size; i++)
+ i < priv->server_names_size; i++)
{
- switch (session->security_parameters.extensions.server_names[i].
- type)
+ switch (priv->server_names[i].type)
{
case GNUTLS_NAME_DNS:
-
- len =
- session->security_parameters.extensions.server_names[i].
- name_length;
+ len = priv->server_names[i].name_length;
if (len == 0)
break;
_gnutls_write_uint16 (len, p);
p += 2;
- memcpy (p,
- session->security_parameters.extensions.server_names[i].
- name, len);
+ memcpy (p, priv->server_names[i].name, len);
p += len;
break;
default:
unsigned int *type, unsigned int indx)
{
char *_data = data;
+ server_name_ext_st* priv;
+ int ret;
+ extension_priv_data_t epriv;
if (session->security_parameters.entity == GNUTLS_CLIENT)
{
gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
}
+
+ ret = _gnutls_ext_get_session_data( session, GNUTLS_EXTENSION_SERVER_NAME, &epriv);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+ }
+
+ priv = epriv.ptr;
- if (indx + 1 > session->security_parameters.extensions.server_names_size)
+ if (indx + 1 > priv->server_names_size)
{
return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
}
- *type = session->security_parameters.extensions.server_names[indx].type;
+ *type = priv->server_names[indx].type;
- if (*data_length > /* greater since we need one extra byte for the null */
- session->security_parameters.extensions.server_names[indx].name_length)
+ if (*data_length > /* greater since we need one extra byte for the null */
+ priv->server_names[indx].name_length)
{
- *data_length =
- session->security_parameters.extensions.
- server_names[indx].name_length;
- memcpy (data,
- session->security_parameters.extensions.server_names[indx].name,
+ *data_length = priv->server_names[indx].name_length;
+ memcpy (data, priv->server_names[indx].name,
*data_length);
if (*type == GNUTLS_NAME_DNS) /* null terminate */
}
else
{
- *data_length =
- session->security_parameters.extensions.
- server_names[indx].name_length;
+ *data_length = priv->server_names[indx].name_length;
return GNUTLS_E_SHORT_MEMORY_BUFFER;
}
gnutls_server_name_type_t type,
const void *name, size_t name_length)
{
- int server_names;
+ int server_names, ret;
+ server_name_ext_st* priv;
+ extension_priv_data_t epriv;
+ int set = 0;
if (session->security_parameters.entity == GNUTLS_SERVER)
{
if (name_length > MAX_SERVER_NAME_SIZE)
return GNUTLS_E_SHORT_MEMORY_BUFFER;
- server_names =
- session->security_parameters.extensions.server_names_size + 1;
+ ret = _gnutls_ext_get_session_data( session, GNUTLS_EXTENSION_SERVER_NAME, &epriv);
+ if (ret < 0)
+ {
+ set = 1;
+ }
+
+ if (set != 0)
+ {
+ priv = gnutls_calloc(1, sizeof(*priv));
+ if (priv == NULL)
+ {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+ epriv.ptr = priv;
+ }
+ else
+ priv = epriv.ptr;
+
+ server_names = priv->server_names_size + 1;
if (server_names > MAX_SERVER_NAME_EXTENSIONS)
server_names = MAX_SERVER_NAME_EXTENSIONS;
- session->security_parameters.extensions.server_names
- [server_names - 1].type = type;
- memcpy (session->security_parameters.
- extensions.server_names[server_names - 1].name, name, name_length);
- session->security_parameters.extensions.server_names[server_names -
- 1].name_length =
- name_length;
+ priv->server_names[server_names - 1].type = type;
+ memcpy (priv->server_names[server_names - 1].name, name, name_length);
+ priv->server_names[server_names - 1].name_length = name_length;
+
+ priv->server_names_size++;
+
+ if (set != 0)
+ _gnutls_ext_set_session_data(session, GNUTLS_EXTENSION_SERVER_NAME, epriv);
+
+ return 0;
+}
+
+static void _gnutls_server_name_deinit_data(extension_priv_data_t priv)
+{
+ gnutls_free(priv.ptr);
+}
+
+static int _gnutls_server_name_pack(extension_priv_data_t epriv, gnutls_buffer_st* ps)
+{
+server_name_ext_st* priv = epriv.ptr;
+int i, ret;
+
+ BUFFER_APPEND_NUM(ps, priv->server_names_size);
+ for (i = 0; i < priv->server_names_size;i++)
+ {
+ BUFFER_APPEND_NUM(ps, priv->server_names[i].type);
+ BUFFER_APPEND_PFX(ps, priv->server_names[i].name,
+ priv->server_names[i].name_length);
+ }
+ return 0;
+}
+
+static int _gnutls_server_name_unpack(gnutls_buffer_st* ps, extension_priv_data_t* _priv)
+{
+server_name_ext_st* priv;
+int i, ret;
+extension_priv_data_t epriv;
- session->security_parameters.extensions.server_names_size++;
+ priv = gnutls_calloc(1, sizeof(*priv));
+ if (priv == NULL)
+ {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+ BUFFER_POP_NUM(ps, priv->server_names_size);
+ for (i = 0; i < priv->server_names_size;i++)
+ {
+ BUFFER_POP_NUM(ps, priv->server_names[i].type);
+ BUFFER_POP_NUM(ps, priv->server_names[i].name_length);
+ if (priv->server_names[i].name_length > sizeof(priv->server_names[i].name))
+ {
+ gnutls_assert();
+ return GNUTLS_E_PARSING_ERROR;
+ }
+ BUFFER_POP(ps, priv->server_names[i].name, priv->server_names[i].name_length);
+ }
+
+ epriv.ptr = priv;
+ *_priv = epriv;
+
return 0;
+
+error:
+ gnutls_free(priv);
+ return ret;
}
+
* USA
*
*/
+#ifndef EXT_SERVER_NAME_H
+#define EXT_SERVER_NAME_H
-int _gnutls_server_name_recv_params (gnutls_session_t session,
- const opaque * data, size_t data_size);
-int _gnutls_server_name_send_params (gnutls_session_t session,
- opaque * data, size_t);
+#include <gnutls_extensions.h>
+
+typedef struct
+{
+ opaque name[MAX_SERVER_NAME_SIZE];
+ unsigned name_length;
+ gnutls_server_name_type_t type;
+} server_name_st;
+
+#define MAX_SERVER_NAME_EXTENSIONS 3
+
+typedef struct {
+ server_name_st server_names[MAX_SERVER_NAME_EXTENSIONS];
+ /* limit server_name extensions */
+ unsigned server_names_size;
+} server_name_ext_st;
+
+extern extension_entry_st ext_mod_server_name;
+
+#endif
#include <random.h>
#include <ext_session_ticket.h>
#include <gnutls_mbuffers.h>
+#include <gnutls_extensions.h>
#ifdef ENABLE_SESSION_TICKET
#define MAC_SIZE 32
+static int session_ticket_recv_params (gnutls_session_t session,
+ const opaque * data,
+ size_t data_size);
+static int session_ticket_send_params (gnutls_session_t session,
+ opaque * data, size_t data_size);
+static int session_ticket_unpack(gnutls_buffer_st* ps, extension_priv_data_t* _priv);
+static int session_ticket_pack(extension_priv_data_t _priv, gnutls_buffer_st* ps);
+static void session_ticket_deinit_data(extension_priv_data_t priv);
+
+extension_entry_st ext_mod_session_ticket = {
+ .name = "SESSION TICKET",
+ .type = GNUTLS_EXTENSION_SESSION_TICKET,
+ .parse_type = GNUTLS_EXT_TLS,
+
+ .recv_func = session_ticket_recv_params,
+ .send_func = session_ticket_send_params,
+ .pack_func = session_ticket_pack,
+ .unpack_func = session_ticket_unpack,
+ .deinit_func = session_ticket_deinit_data,
+};
+
+struct gnutls_session_ticket_key_st
+{
+ opaque key_name[SESSION_TICKET_KEY_NAME_SIZE];
+ opaque key[SESSION_TICKET_KEY_SIZE];
+ opaque mac_secret[SESSION_TICKET_MAC_SECRET_SIZE];
+};
+
+typedef struct {
+ int session_ticket_enable;
+ int session_ticket_renew;
+ opaque session_ticket_IV[SESSION_TICKET_IV_SIZE];
+
+ opaque* session_ticket;
+ int session_ticket_len;
+
+ struct gnutls_session_ticket_key_st key;
+} session_ticket_ext_st;
+
struct ticket
{
opaque key_name[KEY_NAME_SIZE];
}
static int
-decrypt_ticket (gnutls_session_t session, struct ticket *ticket)
+decrypt_ticket (gnutls_session_t session, session_ticket_ext_st* priv, struct ticket *ticket)
{
cipher_hd_st cipher_hd;
gnutls_datum_t key, IV, mac_secret, state;
- opaque final[32];
+ opaque final[MAC_SECRET_SIZE];
time_t timestamp = time (0);
int ret;
/* Check the integrity of ticket using HMAC-SHA-256. */
- mac_secret.data = (void *)
- session->internals.session_ticket_key->mac_secret;
+ mac_secret.data = (void *) priv->key.mac_secret;
mac_secret.size = MAC_SECRET_SIZE;
ret = digest_ticket (&mac_secret, ticket, final);
if (ret < 0)
}
/* Decrypt encrypted_state using 128-bit AES in CBC mode. */
- key.data = (void *) session->internals.session_ticket_key->key;
+ key.data = (void *) priv->key.key;
key.size = KEY_SIZE;
IV.data = ticket->IV;
IV.size = IV_SIZE;
}
static int
-encrypt_ticket (gnutls_session_t session, struct ticket *ticket)
+encrypt_ticket (gnutls_session_t session, session_ticket_ext_st* priv, struct ticket *ticket)
{
cipher_hd_st cipher_hd;
gnutls_datum_t key, IV, mac_secret, state, encrypted_state;
return ret;
}
blocksize = gnutls_cipher_get_block_size (GNUTLS_CIPHER_AES_128_CBC);
+
encrypted_state.size =
((state.size + blocksize - 1) / blocksize) * blocksize;
encrypted_state.data = gnutls_malloc (encrypted_state.size);
_gnutls_free_datum (&state);
/* Encrypt state using 128-bit AES in CBC mode. */
- key.data = (void *) session->internals.session_ticket_key->key;
+ key.data = (void *) priv->key.key;
key.size = KEY_SIZE;
- IV.data = session->internals.session_ticket_IV;
+ IV.data = priv->session_ticket_IV;
IV.size = IV_SIZE;
ret =
_gnutls_cipher_init (&cipher_hd, GNUTLS_CIPHER_AES_128_CBC, &key, &IV);
}
/* Fill the ticket structure to compute MAC. */
- memcpy (ticket->key_name,
- session->internals.session_ticket_key->key_name, KEY_NAME_SIZE);
+ memcpy (ticket->key_name, priv->key.key_name, KEY_NAME_SIZE);
memcpy (ticket->IV, IV.data, IV.size);
ticket->encrypted_state_len = encrypted_state.size;
ticket->encrypted_state = encrypted_state.data;
- mac_secret.data =
- (void *) session->internals.session_ticket_key->mac_secret;
+ mac_secret.data = priv->key.mac_secret;
mac_secret.size = MAC_SECRET_SIZE;
ret = digest_ticket (&mac_secret, ticket, ticket->mac);
if (ret < 0)
return 0;
}
-int
-_gnutls_session_ticket_recv_params (gnutls_session_t session,
+static int
+session_ticket_recv_params (gnutls_session_t session,
const opaque * data, size_t _data_size)
{
ssize_t data_size = _data_size;
+ session_ticket_ext_st* priv=NULL;
+ extension_priv_data_t epriv;
+ int ret;
- if (!session->internals.session_ticket_enable)
+ ret = _gnutls_ext_get_session_data( session, GNUTLS_EXTENSION_SESSION_TICKET, &epriv);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ return ret;
+ }
+ priv = epriv.ptr;
+
+ if (!priv->session_ticket_enable)
return 0;
if (session->security_parameters.entity == GNUTLS_SERVER)
/* The client requested a new session ticket. */
if (data_size == 0)
{
- session->internals.session_ticket_renew = 1;
+ priv->session_ticket_renew = 1;
return 0;
}
/* If the key name of the ticket does not match the one that we
hold, issue a new ticket. */
- if (memcmp (ticket.key_name,
- session->internals.session_ticket_key->key_name,
- KEY_NAME_SIZE))
+ if (memcmp (ticket.key_name, priv->key.key_name, KEY_NAME_SIZE))
{
- session->internals.session_ticket_renew = 1;
+ priv->session_ticket_renew = 1;
return 0;
}
memcpy (ticket.encrypted_state, encrypted_state,
ticket.encrypted_state_len);
- ret = decrypt_ticket (session, &ticket);
+ ret = decrypt_ticket (session, priv, &ticket);
gnutls_free (ticket.encrypted_state);
if (ret < 0)
{
- session->internals.session_ticket_renew = 1;
+ priv->session_ticket_renew = 1;
return 0;
}
}
- else
+ else /* Client */
{
if (data_size == 0)
{
- session->internals.session_ticket_renew = 1;
+ priv->session_ticket_renew = 1;
return 0;
}
}
/* returns a positive number if we send the extension data, zero if we
do not want to send it, and a negative number on failure.
*/
-int
-_gnutls_session_ticket_send_params (gnutls_session_t session,
+static int
+session_ticket_send_params (gnutls_session_t session,
opaque * data, size_t _data_size)
{
ssize_t data_size = _data_size;
+ session_ticket_ext_st* priv=NULL;
+ extension_priv_data_t epriv;
+ int ret;
- if (!session->internals.session_ticket_enable)
+ ret = _gnutls_ext_get_session_data( session, GNUTLS_EXTENSION_SESSION_TICKET, &epriv);
+ if (ret >= 0)
+ priv = epriv.ptr;
+
+ if (priv == NULL || !priv->session_ticket_enable)
return 0;
if (session->security_parameters.entity == GNUTLS_SERVER)
{
- if (session->internals.session_ticket_renew)
+ if (priv && priv->session_ticket_renew)
{
return GNUTLS_E_INT_RET_0;
}
}
else
{
- if (session->internals.resumed_security_parameters.
- extensions.session_ticket_len > 0)
+ ret = _gnutls_ext_get_resumed_session_data( session, GNUTLS_EXTENSION_SESSION_TICKET, &epriv);
+ if (ret >= 0)
+ priv = epriv.ptr;
+
+ if (ret < 0 || !priv->session_ticket_enable)
+ return 0;
+
+ if (priv->session_ticket_len > 0)
{
- DECR_LENGTH_RET (data_size,
- session->internals.
- resumed_security_parameters.extensions.
- session_ticket_len, GNUTLS_E_SHORT_MEMORY_BUFFER);
- memcpy (data,
- session->internals.resumed_security_parameters.
- extensions.session_ticket,
- session->internals.resumed_security_parameters.
- extensions.session_ticket_len);
-
- return session->internals.resumed_security_parameters.extensions.
- session_ticket_len;
+ DECR_LENGTH_RET (data_size, priv->session_ticket_len, GNUTLS_E_SHORT_MEMORY_BUFFER);
+ memcpy (data, priv->session_ticket, priv->session_ticket_len);
+
+ return priv->session_ticket_len;
}
else
{
return 0;
}
+
+static void session_ticket_deinit_data(extension_priv_data_t epriv)
+{
+session_ticket_ext_st* priv = epriv.ptr;
+
+ gnutls_free(priv->session_ticket);
+ gnutls_free(priv);
+}
+
+static int session_ticket_pack(extension_priv_data_t epriv, gnutls_buffer_st* ps)
+{
+session_ticket_ext_st* priv = epriv.ptr;
+int ret;
+
+ BUFFER_APPEND_PFX(ps, priv->session_ticket, priv->session_ticket_len);
+
+ return 0;
+}
+
+static int session_ticket_unpack(gnutls_buffer_st* ps, extension_priv_data_t* _priv)
+{
+session_ticket_ext_st* priv=NULL;
+int ret;
+extension_priv_data_t epriv;
+gnutls_datum ticket;
+
+ priv = gnutls_calloc(1, sizeof(*priv));
+ if (priv == NULL)
+ {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ BUFFER_POP_DATUM(ps, &ticket);
+ priv->session_ticket = ticket.data;
+ priv->session_ticket_len = ticket.size;
+
+ epriv.ptr = priv;
+ *_priv = epriv;
+
+ ret = 0;
+
+error:
+ gnutls_free(priv);
+ return ret;
+}
+
+
+
/**
* gnutls_session_ticket_key_generate:
* @key: is a pointer to a #gnutls_datum_t which will contain a newly
int
gnutls_session_ticket_enable_client (gnutls_session_t session)
{
+ session_ticket_ext_st* priv=NULL;
+ extension_priv_data_t epriv;
+
if (!session)
{
gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
}
- session->internals.session_ticket_enable = 1;
+ priv = gnutls_calloc(1, sizeof(*priv));
+ if (priv == NULL)
+ {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+ priv->session_ticket_enable = 1;
+ epriv.ptr = priv;
+
+ _gnutls_ext_set_session_data(session,
+ GNUTLS_EXTENSION_SESSION_TICKET, epriv);
+
return 0;
}
const gnutls_datum_t * key)
{
int ret;
+ session_ticket_ext_st* priv=NULL;
+ extension_priv_data_t epriv;
if (!session || !key
|| key->size != sizeof (struct gnutls_session_ticket_key_st))
return GNUTLS_E_INVALID_REQUEST;
}
+ priv = gnutls_calloc(1, sizeof(*priv));
+ if (priv == NULL)
+ {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+ epriv.ptr = priv;
+
ret = _gnutls_rnd (GNUTLS_RND_RANDOM,
- session->internals.session_ticket_IV, IV_SIZE);
+ priv->session_ticket_IV, IV_SIZE);
if (ret < 0)
{
gnutls_assert ();
return ret;
}
- session->internals.session_ticket_key =
- (struct gnutls_session_ticket_key_st *) key->data;
- session->internals.session_ticket_enable = 1;
+ memcpy(&priv->key, key->data, key->size);
+ priv->session_ticket_enable = 1;
+
+ _gnutls_ext_set_session_data(session,
+ GNUTLS_EXTENSION_SESSION_TICKET, epriv);
+
return 0;
}
-int
-_gnutls_send_new_session_ticket (gnutls_session_t session, int again)
-{
- mbuffer_st *bufel = NULL;
- uint8_t *data = NULL, *p;
- int data_size = 0;
- int ret;
- struct ticket ticket;
- uint16_t ticket_len;
- gnutls_cipher_algorithm_t write_bulk_cipher_algorithm;
- gnutls_mac_algorithm_t write_mac_algorithm;
- gnutls_compression_method_t write_compression_algorithm;
-
#define SAVE_WRITE_SECURITY_PARAMETERS \
do \
{ \
} \
while (0)
+int
+_gnutls_send_new_session_ticket (gnutls_session_t session, int again)
+{
+ mbuffer_st *bufel = NULL;
+ uint8_t *data = NULL, *p;
+ int data_size = 0;
+ int ret;
+ struct ticket ticket;
+ uint16_t ticket_len;
+ gnutls_cipher_algorithm_t write_bulk_cipher_algorithm;
+ gnutls_mac_algorithm_t write_mac_algorithm;
+ gnutls_compression_method_t write_compression_algorithm;
+ session_ticket_ext_st* priv=NULL;
+ extension_priv_data_t epriv;
+
if (again == 0)
{
+ ret = _gnutls_ext_get_session_data( session, GNUTLS_EXTENSION_SESSION_TICKET, &epriv);
+ if (ret < 0)
+ return 0;
+ priv = epriv.ptr;
+
+ if (!priv->session_ticket_renew)
+ return 0;
+
/* XXX: Temporarily set write algorithms to be used.
_gnutls_write_connection_state_init() does this job, but it also
triggers encryption, while NewSessionTicket should not be
if (ret < 0)
return ret;
- ret = encrypt_ticket (session, &ticket);
+ ret = encrypt_ticket (session, priv, &ticket);
RESTORE_WRITE_SECURITY_PARAMETERS;
if (ret < 0)
{
data = _mbuffer_get_udata_ptr(bufel);
p = data;
- /* FIXME: ticket lifetime is fixed to 10 days, which should be
- customizable. */
- _gnutls_write_uint32 (864000, p);
+
+ _gnutls_write_uint32 ( session->internals.expire_time, p);
p += 4;
_gnutls_write_uint16 (ticket_len, p);
uint32_t lifetime_hint;
uint16_t ticket_len;
int ret;
+ session_ticket_ext_st* priv=NULL;
+ extension_priv_data_t epriv;
+
+ ret = _gnutls_ext_get_session_data( session, GNUTLS_EXTENSION_SESSION_TICKET, &epriv);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ return 0;
+ }
+ priv = epriv.ptr;
+
+ if (!priv->session_ticket_renew)
+ return 0;
ret = _gnutls_recv_handshake (session, &data, &data_size,
GNUTLS_HANDSHAKE_NEW_SESSION_TICKET,
p += 2;
DECR_LENGTH_COM (data_size, ticket_len, goto error);
- session->security_parameters.extensions.session_ticket =
- gnutls_realloc (session->security_parameters.extensions.session_ticket,
- ticket_len);
- if (!session->security_parameters.extensions.session_ticket)
+ priv->session_ticket = gnutls_realloc (priv->session_ticket, ticket_len);
+ if (!priv->session_ticket)
{
gnutls_assert ();
gnutls_free (data);
return GNUTLS_E_MEMORY_ERROR;
}
- memcpy (session->security_parameters.extensions.session_ticket,
- p, ticket_len);
+ memcpy (priv->session_ticket, p, ticket_len);
gnutls_free (data);
- session->security_parameters.extensions.session_ticket_len = ticket_len;
+ priv->session_ticket_len = ticket_len;
/* Discard the current session ID. (RFC5077 3.4) */
ret = _gnutls_generate_session_id (session->security_parameters.session_id,
- &session->
- security_parameters.session_id_size);
+ &session->security_parameters.session_id_size);
if (ret < 0)
{
gnutls_assert ();
gnutls_free (data);
- gnutls_free (session->security_parameters.extensions.session_ticket);
+ gnutls_free (priv->session_ticket);
+ priv->session_ticket = NULL;
return GNUTLS_E_INTERNAL_ERROR;
}
return 0;
*
*/
-#ifdef ENABLE_SESSION_TICKET
+#ifndef EXT_SESSION_TICKET_H
+# define EXT_SESSION_TICKET_H
-int _gnutls_session_ticket_recv_params (gnutls_session_t session,
- const opaque * data,
- size_t data_size);
-int _gnutls_session_ticket_send_params (gnutls_session_t session,
- opaque * data, size_t data_size);
+# ifdef ENABLE_SESSION_TICKET
+
+#include <gnutls_extensions.h>
+
+extern extension_entry_st ext_mod_session_ticket;
int _gnutls_send_new_session_ticket (gnutls_session_t session, int again);
int _gnutls_recv_new_session_ticket (gnutls_session_t session);
+# endif
#endif
#include <gnutls_num.h>
#include <gnutls_algorithms.h>
+static int _gnutls_signature_algorithm_recv_params (gnutls_session_t session,
+ const opaque * data,
+ size_t data_size);
+static int _gnutls_signature_algorithm_send_params (gnutls_session_t session,
+ opaque * data, size_t);
+static void signature_algorithms_deinit_data(extension_priv_data_t priv);
+static int signature_algorithms_pack(extension_priv_data_t epriv, gnutls_buffer_st* ps);
+static int signature_algorithms_unpack(gnutls_buffer_st* ps, extension_priv_data_t* _priv);
+
+extension_entry_st ext_mod_sig = {
+ .name = "SIGNATURE ALGORITHMS",
+ .type = GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
+ .parse_type = GNUTLS_EXT_TLS,
+
+ .recv_func = _gnutls_signature_algorithm_recv_params,
+ .send_func = _gnutls_signature_algorithm_send_params,
+ .pack_func = signature_algorithms_pack,
+ .unpack_func = signature_algorithms_unpack,
+ .deinit_func = signature_algorithms_deinit_data,
+};
+
+typedef struct {
+ /* TLS 1.2 signature algorithms */
+ gnutls_sign_algorithm_t sign_algorithms[MAX_SIGNATURE_ALGORITHMS];
+ uint16_t sign_algorithms_size;
+} sig_ext_st;
+
/* generates a SignatureAndHashAlgorithm structure with length as prefix
* by using the setup priorities.
*/
return len + 2;
}
+
/* Parses the Signature Algorithm structure and stores data into
* session->security_parameters.extensions.
*/
const opaque * data, size_t data_size)
{
int sig, i;
+ sig_ext_st * priv;
+ extension_priv_data_t epriv;
- session->security_parameters.extensions.sign_algorithms_size = 0;
+ priv = gnutls_calloc(1, sizeof(*priv));
+ if (priv == NULL)
+ {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
for (i = 0; i < data_size; i += 2)
{
sig = _gnutls_tls_aid_to_sign (&aid);
if (sig != GNUTLS_SIGN_UNKNOWN)
{
- session->security_parameters.extensions.sign_algorithms[session->
- security_parameters.
- extensions.sign_algorithms_size++]
+ priv->sign_algorithms[priv->sign_algorithms_size++]
= sig;
- if (session->security_parameters.extensions.sign_algorithms_size ==
- MAX_SIGNATURE_ALGORITHMS)
+ if (priv->sign_algorithms_size == MAX_SIGNATURE_ALGORITHMS)
break;
}
}
+ epriv.ptr = priv;
+ _gnutls_ext_set_session_data(session, GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS, epriv);
+
return 0;
}
* then it is an error;
*/
-int
+static int
_gnutls_signature_algorithm_recv_params (gnutls_session_t session,
const opaque * data,
size_t _data_size)
{
uint16_t len;
-
DECR_LEN (data_size, 2);
len = _gnutls_read_uint16 (data);
DECR_LEN (data_size, len);
/* returns data_size or a negative number on failure
*/
-int
+static int
_gnutls_signature_algorithm_send_params (gnutls_session_t session,
opaque * data, size_t data_size)
{
gnutls_digest_algorithm_t * hash)
{
unsigned i;
+ int ret;
gnutls_protocol_t ver = gnutls_protocol_get_version (session);
+ sig_ext_st * priv;
+ extension_priv_data_t epriv;
+ ret = _gnutls_ext_get_session_data(session, GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
+ &epriv);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ return ret;
+ }
+ priv = epriv.ptr;
if (!_gnutls_version_has_selectable_sighash (ver)
- || session->security_parameters.extensions.sign_algorithms_size == 0)
+ || priv->sign_algorithms_size == 0)
/* none set, allow all */
{
*hash = GNUTLS_DIG_SHA1;
}
for (i = 0;
- i < session->security_parameters.extensions.sign_algorithms_size; i++)
+ i < priv->sign_algorithms_size; i++)
{
if (_gnutls_sign_get_pk_algorithm
- (session->security_parameters.extensions.sign_algorithms[i]) == pk)
+ (priv->sign_algorithms[i]) == pk)
{
*hash =
- _gnutls_sign_get_hash_algorithm (session->security_parameters.
- extensions.sign_algorithms[i]);
- return session->security_parameters.extensions.sign_algorithms[i];
+ _gnutls_sign_get_hash_algorithm (priv->sign_algorithms[i]);
+ return priv->sign_algorithms[i];
}
}
gnutls_sign_algorithm_t sig)
{
unsigned i;
+ int ret;
gnutls_protocol_t ver = gnutls_protocol_get_version (session);
+ sig_ext_st * priv;
+ extension_priv_data_t epriv;
+
+ ret = _gnutls_ext_get_session_data(session, GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
+ &epriv);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ return ret;
+ }
+ priv = epriv.ptr;
if (!_gnutls_version_has_selectable_sighash (ver)
- || session->security_parameters.extensions.sign_algorithms_size == 0)
+ || priv->sign_algorithms_size == 0)
/* none set, allow all */
{
return 0;
}
for (i = 0;
- i < session->security_parameters.extensions.sign_algorithms_size; i++)
+ i < priv->sign_algorithms_size; i++)
{
- if (session->security_parameters.extensions.sign_algorithms[i] == sig)
+ if (priv->sign_algorithms[i] == sig)
{
return 0; /* ok */
}
gnutls_sign_algorithm_t sig)
{
unsigned i;
+ int ret;
gnutls_protocol_t ver = gnutls_protocol_get_version (session);
+ sig_ext_st * priv;
+ extension_priv_data_t epriv;
+
+ ret = _gnutls_ext_get_session_data(session, GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
+ &epriv);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ return 0;
+ }
+ priv = epriv.ptr;
if (!_gnutls_version_has_selectable_sighash (ver)
- || session->security_parameters.extensions.sign_algorithms_size == 0)
+ || priv->sign_algorithms_size == 0)
/* none set, allow all */
{
return 0;
return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM;
}
+static void signature_algorithms_deinit_data(extension_priv_data_t priv)
+{
+ gnutls_free(priv.ptr);
+}
+
+static int signature_algorithms_pack(extension_priv_data_t epriv, gnutls_buffer_st* ps)
+{
+sig_ext_st* priv = epriv.ptr;
+int ret, i;
+
+ BUFFER_APPEND_NUM(ps, priv->sign_algorithms_size);
+ for (i = 0; i < priv->sign_algorithms_size;i++)
+ {
+ BUFFER_APPEND_NUM(ps, priv->sign_algorithms[i]);
+ }
+ return 0;
+}
+
+static int signature_algorithms_unpack(gnutls_buffer_st* ps, extension_priv_data_t* _priv)
+{
+sig_ext_st* priv;
+int i, ret;
+extension_priv_data_t epriv;
+
+ priv = gnutls_calloc(1, sizeof(*priv));
+ if (priv == NULL)
+ {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ BUFFER_POP_NUM(ps, priv->sign_algorithms_size);
+ for (i = 0; i < priv->sign_algorithms_size;i++)
+ {
+ BUFFER_POP_NUM(ps, priv->sign_algorithms[i]);
+ }
+
+ epriv.ptr = priv;
+ *_priv = epriv;
+
+ return 0;
+
+error:
+ gnutls_free(priv);
+ return ret;
+}
+
+
+
/**
* gnutls_sign_algorithm_get_requested:
* @session: is a #gnutls_session_t structure.
gnutls_sign_algorithm_t * algo)
{
gnutls_protocol_t ver = gnutls_protocol_get_version (session);
+ sig_ext_st * priv;
+ extension_priv_data_t epriv;
+ int ret;
+
+ ret = _gnutls_ext_get_session_data(session, GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
+ &epriv);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ return ret;
+ }
+ priv = epriv.ptr;
if (!_gnutls_version_has_selectable_sighash (ver)
- || session->security_parameters.extensions.sign_algorithms_size == 0)
+ || priv->sign_algorithms_size == 0)
{
return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
}
- if (indx < session->security_parameters.extensions.sign_algorithms_size)
+ if (indx < priv->sign_algorithms_size)
{
- *algo = session->security_parameters.extensions.sign_algorithms[indx];
+ *algo = priv->sign_algorithms[indx];
return 0;
}
else
/* signature algorithms extension
*/
-int _gnutls_signature_algorithm_recv_params (gnutls_session_t session,
- const opaque * data,
- size_t data_size);
-int _gnutls_signature_algorithm_send_params (gnutls_session_t session,
- opaque * data, size_t);
+#ifndef EXT_SIGNATURE_H
+# define EXT_SIGNATURE_H
+
+#include <gnutls_extensions.h>
+
+extern extension_entry_st ext_mod_sig;
+
int _gnutls_session_sign_algo_requested (gnutls_session_t session,
gnutls_sign_algorithm_t sig);
gnutls_sign_algorithm_t _gnutls_session_get_sign_algo (gnutls_session_t
opaque * data, size_t max_data_size);
int _gnutls_session_sign_algo_enabled (gnutls_session_t session,
gnutls_sign_algorithm_t sig);
+
+#endif
#include "gnutls_errors.h"
#include "gnutls_algorithms.h"
#include <gnutls_num.h>
+#include <gnutls_extensions.h>
-int
+static int _gnutls_srp_unpack(gnutls_buffer_st* ps, extension_priv_data_t* _priv);
+static int _gnutls_srp_pack(extension_priv_data_t epriv, gnutls_buffer_st* ps);
+static void _gnutls_srp_deinit_data(extension_priv_data_t epriv);
+static int _gnutls_srp_recv_params (gnutls_session_t state, const opaque * data,
+ size_t data_size);
+static int _gnutls_srp_send_params (gnutls_session_t state, opaque * data, size_t);
+
+extension_entry_st ext_mod_srp = {
+ .name = "SRP",
+ .type = GNUTLS_EXTENSION_SRP,
+ .parse_type = GNUTLS_EXT_TLS,
+
+ .recv_func = _gnutls_srp_recv_params,
+ .send_func = _gnutls_srp_send_params,
+ .pack_func = _gnutls_srp_pack,
+ .unpack_func = _gnutls_srp_unpack,
+ .deinit_func = _gnutls_srp_deinit_data
+};
+
+
+static int
_gnutls_srp_recv_params (gnutls_session_t session, const opaque * data,
size_t _data_size)
{
uint8_t len;
ssize_t data_size = _data_size;
-
+ extension_priv_data_t epriv;
+ srp_ext_st * priv;
+
if (session->security_parameters.entity == GNUTLS_SERVER)
{
if (data_size > 0)
gnutls_assert ();
return GNUTLS_E_ILLEGAL_SRP_USERNAME;
}
- memcpy (session->security_parameters.extensions.srp_username,
- &data[1], len);
- /* null terminated */
- session->security_parameters.extensions.srp_username[len] = 0;
+
+ priv = gnutls_calloc(1, sizeof(*priv));
+ if (priv == NULL)
+ {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ priv->username = gnutls_malloc(len+1);
+ if (priv->username)
+ {
+ memcpy (priv->username, &data[1], len);
+ /* null terminated */
+ priv->username[len] = 0;
+ }
+
+ epriv.ptr = priv;
+ _gnutls_ext_set_session_data(session, GNUTLS_EXTENSION_SRP, epriv);
}
}
return 0;
/* returns data_size or a negative number on failure
* data is allocated locally
*/
-int
+static int
_gnutls_srp_send_params (gnutls_session_t session, opaque * data,
size_t data_size)
{
unsigned len;
+ extension_priv_data_t epriv;
+ srp_ext_st * priv;
if (_gnutls_kx_priority (session, GNUTLS_KX_SRP) < 0 &&
_gnutls_kx_priority (session, GNUTLS_KX_SRP_DSS) < 0 &&
return GNUTLS_E_SHORT_MEMORY_BUFFER;
}
- session->internals.srp_username = username;
- session->internals.srp_password = password;
+ priv = gnutls_malloc(sizeof(*priv));
+ if (priv == NULL)
+ {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ priv->username = username;
+ priv->password = password;
+
+ epriv.ptr = priv;
+ _gnutls_ext_set_session_data(session, GNUTLS_EXTENSION_SRP, epriv);
data[0] = (uint8_t) len;
memcpy (&data[1], username, len);
return 0;
}
+static void _gnutls_srp_deinit_data(extension_priv_data_t epriv)
+{
+ srp_ext_st * priv = epriv.ptr;
+
+ gnutls_free(priv->username);
+ gnutls_free(priv->password);
+ gnutls_free(priv);
+}
+
+static int _gnutls_srp_pack(extension_priv_data_t epriv, gnutls_buffer_st* ps)
+{
+srp_ext_st* priv = epriv.ptr;
+int ret;
+int password_len = 0, username_len = 0;
+
+ if (priv->username)
+ username_len = strlen(priv->username);
+
+ if (priv->password)
+ password_len = strlen(priv->password);
+
+ BUFFER_APPEND_PFX(ps, priv->username, username_len);
+ BUFFER_APPEND_PFX(ps, priv->password, password_len);
+
+ return 0;
+}
+
+static int _gnutls_srp_unpack(gnutls_buffer_st* ps, extension_priv_data_t* _priv)
+{
+srp_ext_st* priv;
+int ret;
+extension_priv_data_t epriv;
+gnutls_datum username = { NULL, 0 }, password = {NULL, 0};
+
+ priv = gnutls_calloc(1, sizeof(*priv));
+ if (priv == NULL)
+ {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ BUFFER_POP_DATUM(ps, &username);
+ BUFFER_POP_DATUM(ps, &password);
+
+ priv->username = username.data;
+ priv->password = password.data;
+
+ epriv.ptr = priv;
+ *_priv = epriv;
+
+ return 0;
+
+error:
+ _gnutls_free_datum(&username);
+ _gnutls_free_datum(&password);
+ return ret;
+}
+
+
#endif /* ENABLE_SRP */
*
*/
-#ifdef ENABLE_SRP
+#ifndef EXT_SRP_H
+#define EXT_SRP_H
-#define IS_SRP_KX(kx) ((kx == GNUTLS_KX_SRP || (kx == GNUTLS_KX_SRP_RSA) || \
+#include <gnutls_extensions.h>
+
+# ifdef ENABLE_SRP
+
+# define IS_SRP_KX(kx) ((kx == GNUTLS_KX_SRP || (kx == GNUTLS_KX_SRP_RSA) || \
kx == GNUTLS_KX_SRP_DSS)?1:0)
-int _gnutls_srp_recv_params (gnutls_session_t state, const opaque * data,
- size_t data_size);
-int _gnutls_srp_send_params (gnutls_session_t state, opaque * data, size_t);
+extern extension_entry_st ext_mod_srp;
+
+typedef struct {
+ char* username;
+ char* password;
+} srp_ext_st;
+
+# endif
#endif
switch (type)
{
case GNUTLS_APPLICATION_DATA:
- _gnutls_buffer_get_data (&session->internals.application_data_buffer,
+ _gnutls_buffer_pop_data (&session->internals.application_data_buffer,
data, &length);
_gnutls_buffers_log ("BUFFER[REC][AD]: Read %d bytes of Data(%d)\n",
(int) length, (int) type);
break;
case GNUTLS_HANDSHAKE:
- _gnutls_buffer_get_data (&session->internals.handshake_data_buffer,
+ _gnutls_buffer_pop_data (&session->internals.handshake_data_buffer,
data, &length);
_gnutls_buffers_log ("BUF[REC][HD]: Read %d bytes of Data(%d)\n",
(int) length, (int) type);
case GNUTLS_INNER_APPLICATION:
- _gnutls_buffer_get_data (&session->internals.ia_data_buffer, data,
+ _gnutls_buffer_pop_data (&session->internals.ia_data_buffer, data,
&length);
_gnutls_buffers_log ("BUF[REC][IA]: Read %d bytes of Data(%d)\n",
(int) length, (int) type);
gnutls_assert ();
tmp = sizeOfPtr;
- _gnutls_buffer_get_data (&session->internals.handshake_recv_buffer,
+ _gnutls_buffer_pop_data (&session->internals.handshake_recv_buffer,
iptr, &tmp);
return tmp;
}
gnutls_assert ();
tmp = sizeOfPtr;
- _gnutls_buffer_get_data (&session->internals.handshake_recv_buffer,
+ _gnutls_buffer_pop_data (&session->internals.handshake_recv_buffer,
iptr, &tmp);
left -= tmp;
#include <gnutls_num.h>
#include <gnutls_datum.h>
#include <gnutls_state.h>
+#include <gnutls_extensions.h>
static const char keyexp[] = "key expansion";
static const int keyexp_length = sizeof (keyexp) - 1;
export_flag);
}
-#define CPY_EXTENSIONS \
- gnutls_free(dst->extensions.session_ticket); \
- gnutls_free(dst->extensions.oprfi_client); \
- gnutls_free(dst->extensions.oprfi_server); \
- memcpy(&dst->extensions.server_names, &src->extensions, sizeof(src->extensions)); \
- memset(&src->extensions, 0, sizeof(src->extensions)) /* avoid duplicate free's */
-
#define CPY_COMMON dst->entity = src->entity; \
dst->kx_algorithm = src->kx_algorithm; \
memcpy( &dst->current_cipher_suite, &src->current_cipher_suite, sizeof(cipher_suite_st)); \
dst->timestamp = src->timestamp; \
dst->max_record_recv_size = src->max_record_recv_size; \
dst->max_record_send_size = src->max_record_send_size; \
- dst->version = src->version; \
- memcpy( &dst->inner_secret, &src->inner_secret, GNUTLS_MASTER_SIZE)
+ dst->version = src->version
static void
_gnutls_cpy_read_security_parameters (security_parameters_st *
dst, security_parameters_st * src)
{
CPY_COMMON;
- CPY_EXTENSIONS; /* only do once */
dst->write_bulk_cipher_algorithm = src->write_bulk_cipher_algorithm;
dst->write_mac_algorithm = src->write_mac_algorithm;
return rc;
}
else
- { /* RESUME_TRUE */
+ { /* RESUME_TRUE */
_gnutls_cpy_read_security_parameters (&session->security_parameters,
&session->
internals.resumed_security_parameters);
_gnutls_cpy_write_security_parameters (&session->security_parameters,
&session->
internals.resumed_security_parameters);
+ _gnutls_ext_restore_resumed_session(session);
}
rc = _gnutls_set_write_keys (session);
#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_session_ticket.h>
#include <ext_safe_renegotiation.h>
#include <ext_safe_renegotiation.h>
#include <gnutls_num.h>
-typedef struct
-{
- const char *name;
- uint16_t type;
- gnutls_ext_parse_type_t parse_type;
- /* this function must return 0 when Not Applicable
- * size of extension data if ok
- * < 0 on other error.
- */
- gnutls_ext_recv_func recv_func;
+static void _gnutls_ext_unset_resumed_session_data(gnutls_session_t session, uint16_t type);
- /* this function must return 0 when Not Applicable
- * size of extension data if ok
- * GNUTLS_E_INT_RET_0 if extension data size is zero
- * < 0 on other error.
- */
- gnutls_ext_send_func send_func;
-} gnutls_extension_entry;
static size_t extfunc_size = 0;
-static gnutls_extension_entry *extfunc = NULL;
+static extension_entry_st *extfunc = NULL;
+
+static gnutls_ext_parse_type_t
+_gnutls_ext_parse_type (uint16_t type)
+{
+ size_t i;
+
+ for (i = 0; i < extfunc_size; i++)
+ {
+ if (extfunc[i].type == type)
+ return extfunc[i].parse_type;
+ }
+
+ return GNUTLS_EXT_NONE;
+}
static gnutls_ext_recv_func
_gnutls_ext_func_recv (uint16_t type, gnutls_ext_parse_type_t parse_type)
return NULL;
}
+static gnutls_ext_deinit_data_func
+_gnutls_ext_func_deinit (uint16_t type)
+{
+ size_t i;
+
+ for (i = 0; i < extfunc_size; i++)
+ if (extfunc[i].type == type)
+ return extfunc[i].deinit_func;
+
+ return NULL;
+}
+
+static gnutls_ext_unpack_func
+_gnutls_ext_func_unpack (uint16_t type)
+{
+ size_t i;
+
+ for (i = 0; i < extfunc_size; i++)
+ if (extfunc[i].type == type)
+ return extfunc[i].unpack_func;
+
+ return NULL;
+}
+
+
static const char *
_gnutls_extension_get_name (uint16_t type)
{
pos += 2;
for (i = 0; i < extfunc_size; i++)
{
- gnutls_extension_entry *p = &extfunc[i];
+ extension_entry_st *p = &extfunc[i];
if (p->send_func == NULL)
continue;
*/
_gnutls_extension_list_add (session, p->type);
- _gnutls_debug_log ("EXT[%p]: Sending extension %s\n",
- session, p->name);
+ _gnutls_debug_log ("EXT[%p]: Sending extension %s (%d bytes)\n",
+ session, p->name, size);
}
else if (size < 0)
{
{
int ret;
- ret = gnutls_ext_register (GNUTLS_EXTENSION_MAX_RECORD_SIZE,
- "MAX_RECORD_SIZE",
- GNUTLS_EXT_TLS,
- _gnutls_max_record_recv_params,
- _gnutls_max_record_send_params);
+ ret = _gnutls_ext_register (&ext_mod_max_record_size);
if (ret != GNUTLS_E_SUCCESS)
return ret;
- ret = gnutls_ext_register (GNUTLS_EXTENSION_CERT_TYPE,
- "CERT_TYPE",
- GNUTLS_EXT_TLS,
- _gnutls_cert_type_recv_params,
- _gnutls_cert_type_send_params);
+ ret = _gnutls_ext_register (&ext_mod_cert_type);
if (ret != GNUTLS_E_SUCCESS)
return ret;
- ret = gnutls_ext_register (GNUTLS_EXTENSION_SERVER_NAME,
- "SERVER_NAME",
- GNUTLS_EXT_APPLICATION,
- _gnutls_server_name_recv_params,
- _gnutls_server_name_send_params);
- if (ret != GNUTLS_E_SUCCESS)
- return ret;
- ret = gnutls_ext_register (GNUTLS_EXTENSION_SAFE_RENEGOTIATION,
- "SAFE_RENEGOTIATION",
- GNUTLS_EXT_MANDATORY,
- _gnutls_safe_renegotiation_recv_params,
- _gnutls_safe_renegotiation_send_params);
+ ret = _gnutls_ext_register (&ext_mod_server_name);
if (ret != GNUTLS_E_SUCCESS)
return ret;
-#ifdef ENABLE_OPRFI
- ret = gnutls_ext_register (GNUTLS_EXTENSION_OPAQUE_PRF_INPUT,
- "OPAQUE_PRF_INPUT",
- GNUTLS_EXT_TLS,
- _gnutls_oprfi_recv_params,
- _gnutls_oprfi_send_params);
+ ret = _gnutls_ext_register (&ext_mod_sr);
if (ret != GNUTLS_E_SUCCESS)
return ret;
-#endif
#ifdef ENABLE_SRP
- ret = gnutls_ext_register (GNUTLS_EXTENSION_SRP,
- "SRP",
- GNUTLS_EXT_TLS,
- _gnutls_srp_recv_params,
- _gnutls_srp_send_params);
+ ret = _gnutls_ext_register (&ext_mod_srp);
if (ret != GNUTLS_E_SUCCESS)
return ret;
#endif
+
#ifdef ENABLE_SESSION_TICKET
- ret = gnutls_ext_register (GNUTLS_EXTENSION_SESSION_TICKET,
- "SESSION_TICKET",
- GNUTLS_EXT_TLS,
- _gnutls_session_ticket_recv_params,
- _gnutls_session_ticket_send_params);
+ ret = _gnutls_ext_register (&ext_mod_session_ticket);
if (ret != GNUTLS_E_SUCCESS)
return ret;
#endif
- ret = gnutls_ext_register (GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
- "SIGNATURE_ALGORITHMS",
- GNUTLS_EXT_TLS,
- _gnutls_signature_algorithm_recv_params,
- _gnutls_signature_algorithm_send_params);
+ ret = _gnutls_ext_register (&ext_mod_sig);
if (ret != GNUTLS_E_SUCCESS)
return ret;
extfunc_size = 0;
}
+int
+_gnutls_ext_register (extension_entry_st* mod)
+{
+ extension_entry_st *p;
+
+ p = gnutls_realloc (extfunc, sizeof (*extfunc) * (extfunc_size + 1));
+ if (!p)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ extfunc = p;
+
+ memcpy(&extfunc[extfunc_size], mod, sizeof(*mod));
+
+ extfunc_size++;
+
+ return GNUTLS_E_SUCCESS;
+}
+
/**
* gnutls_ext_register:
* @type: the 16-bit integer referring to the extension type
gnutls_ext_recv_func recv_func,
gnutls_ext_send_func send_func)
{
- gnutls_extension_entry *p;
+extension_entry_st ee;
+
+ memset(&ee, 0, sizeof(ee));
+
+ ee.type = type;
+ ee.name = name;
+ ee.parse_type = parse_type;
+ ee.recv_func = recv_func;
+ ee.send_func = send_func;
+ /* FIXME: Why is this exported? Should it be removed? */
+ return _gnutls_ext_register (&ee);
+}
- p = gnutls_realloc (extfunc, sizeof (*extfunc) * (extfunc_size + 1));
- if (!p)
+int _gnutls_ext_pack(gnutls_session_t session, gnutls_buffer_st* packed)
+{
+int i, ret;
+extension_priv_data_t data;
+int cur_size;
+void* size_pos;
+void* total_exts_pos;
+int exts = 0;
+
+ total_exts_pos = packed->data + packed->length;
+
+ BUFFER_APPEND_NUM(packed, 0);
+
+ for (i = 0; i < extfunc_size; i++)
{
- gnutls_assert ();
- return GNUTLS_E_MEMORY_ERROR;
+ ret = _gnutls_ext_get_session_data(session, extfunc[i].type, &data);
+ if (ret >= 0 && extfunc[i].pack_func != NULL)
+ {
+ BUFFER_APPEND_NUM(packed, extfunc[i].type);
+
+ size_pos = packed->data + packed->length;
+
+ BUFFER_APPEND_NUM(packed, 0);
+
+ cur_size = packed->length;
+
+ ret = extfunc[i].pack_func(data, packed);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ return ret;
+ }
+
+ exts++;
+ /* write the actual size */
+ _gnutls_write_uint32(packed->length-cur_size, size_pos);
+ }
}
- extfunc = p;
- extfunc[extfunc_size].type = type;
- extfunc[extfunc_size].name = name;
- extfunc[extfunc_size].parse_type = parse_type;
- extfunc[extfunc_size].recv_func = recv_func;
- extfunc[extfunc_size].send_func = send_func;
+ _gnutls_write_uint32(exts, total_exts_pos);
- extfunc_size++;
+ return 0;
+
+}
- return GNUTLS_E_SUCCESS;
+void _gnutls_ext_restore_resumed_session(gnutls_session_t session)
+{
+int i;
+
+
+ /* clear everything except MANDATORY extensions */
+ for (i=0;i<MAX_EXT_TYPES;i++)
+ {
+ if (session->internals.extension_int_data[i].set != 0 &&
+ _gnutls_ext_parse_type(session->internals.extension_int_data[i].type) != GNUTLS_EXT_MANDATORY)
+ {
+ _gnutls_ext_unset_session_data(session, session->internals.extension_int_data[i].type);
+ }
+ }
+
+ /* copy resumed to main */
+ for (i=0;i<MAX_EXT_TYPES;i++)
+ {
+ if (session->internals.resumed_extension_int_data[i].set != 0 &&
+ _gnutls_ext_parse_type(session->internals.resumed_extension_int_data[i].type) != GNUTLS_EXT_MANDATORY)
+ {
+ _gnutls_ext_set_session_data(session, session->internals.resumed_extension_int_data[i].type,
+ session->internals.resumed_extension_int_data[i].priv);
+ session->internals.resumed_extension_int_data[i].set = 0;
+ }
+ }
+
+}
+
+
+static void _gnutls_ext_set_resumed_session_data(gnutls_session_t session, uint16_t type,
+ extension_priv_data_t data)
+{
+int i;
+
+ for (i=0;i<MAX_EXT_TYPES;i++)
+ {
+ if (session->internals.resumed_extension_int_data[i].type == type)
+ {
+
+ if (session->internals.resumed_extension_int_data[i].set != 0)
+ _gnutls_ext_unset_resumed_session_data(session, type);
+
+ session->internals.resumed_extension_int_data[i].type = type;
+ session->internals.resumed_extension_int_data[i].priv = data;
+ session->internals.resumed_extension_int_data[i].set = 1;
+ return;
+ }
+ }
+}
+
+int _gnutls_ext_unpack(gnutls_session_t session, gnutls_buffer_st* packed)
+{
+int i, ret;
+extension_priv_data_t data;
+gnutls_ext_unpack_func unpack;
+int max_exts = 0;
+uint16_t type;
+int size_for_type, cur_pos;
+
+ BUFFER_POP_NUM(packed, max_exts);
+ for (i = 0; i < max_exts; i++)
+ {
+ BUFFER_POP_NUM(packed, type);
+ BUFFER_POP_NUM(packed, size_for_type);
+
+ cur_pos = packed->length;
+
+ unpack = _gnutls_ext_func_unpack(type);
+ if (unpack == NULL)
+ {
+ gnutls_assert();
+ return GNUTLS_E_PARSING_ERROR;
+ }
+
+ ret = unpack(packed, &data);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ return ret;
+ }
+
+ /* verify that unpack read the correct bytes */
+ cur_pos = cur_pos - packed->length;
+ if (cur_pos /* read length */ != size_for_type)
+ {
+ gnutls_assert();
+ return GNUTLS_E_PARSING_ERROR;
+ }
+ _gnutls_ext_set_resumed_session_data(session, type, data);
+ }
+
+ return 0;
+
+error:
+ return ret;
+}
+
+void _gnutls_ext_unset_session_data(gnutls_session_t session, uint16_t type)
+{
+gnutls_ext_deinit_data_func deinit;
+extension_priv_data_t data;
+int ret, i;
+
+ deinit = _gnutls_ext_func_deinit (type);
+ ret = _gnutls_ext_get_session_data(session, type, &data);
+
+ if (ret >= 0 && deinit != NULL)
+ {
+ deinit(data);
+ }
+
+ for (i=0;i<MAX_EXT_TYPES;i++)
+ {
+ if (session->internals.extension_int_data[i].type == type)
+ {
+ session->internals.extension_int_data[i].set = 0;
+ return;
+ }
+ }
+
+}
+
+static void _gnutls_ext_unset_resumed_session_data(gnutls_session_t session, uint16_t type)
+{
+gnutls_ext_deinit_data_func deinit;
+extension_priv_data_t data;
+int ret, i;
+
+ deinit = _gnutls_ext_func_deinit (type);
+ ret = _gnutls_ext_get_resumed_session_data(session, type, &data);
+
+ if (ret >= 0 && deinit != NULL)
+ {
+ deinit(data);
+ }
+
+ for (i=0;i<MAX_EXT_TYPES;i++)
+ {
+ if (session->internals.resumed_extension_int_data[i].type == type)
+ {
+ session->internals.resumed_extension_int_data[i].set = 0;
+ return;
+ }
+ }
+
+}
+
+/* Deinitializes all data that are associated with TLS extensions.
+ */
+void _gnutls_ext_free_session_data(gnutls_session_t session)
+{
+int i;
+
+ for (i = 0; i < extfunc_size; i++)
+ {
+ _gnutls_ext_unset_session_data(session, extfunc[i].type);
+ }
+
+ for (i = 0; i < extfunc_size; i++)
+ {
+ _gnutls_ext_unset_resumed_session_data(session, extfunc[i].type);
+ }
+
+}
+
+/* This function allows and extension to store data in the current session
+ * and retrieve them later on. We use functions instead of a pointer to a
+ * private pointer, to allow API additions by individual extensions.
+ */
+void _gnutls_ext_set_session_data(gnutls_session_t session, uint16_t type,
+ extension_priv_data_t data)
+{
+int i;
+gnutls_ext_deinit_data_func deinit;
+
+ deinit = _gnutls_ext_func_deinit (type);
+
+ for (i=0;i<MAX_EXT_TYPES;i++)
+ {
+ if (session->internals.extension_int_data[i].type == type || session->internals.extension_int_data[i].set == 0)
+ {
+ if (session->internals.extension_int_data[i].set != 0)
+ {
+ if (deinit) deinit(session->internals.extension_int_data[i].priv);
+ }
+ session->internals.extension_int_data[i].type = type;
+ session->internals.extension_int_data[i].priv = data;
+ session->internals.extension_int_data[i].set = 1;
+ return;
+ }
+ }
+}
+
+int _gnutls_ext_get_session_data(gnutls_session_t session,
+ uint16_t type, extension_priv_data_t* data)
+{
+int i;
+
+ for (i=0;i<MAX_EXT_TYPES;i++)
+ {
+ if (session->internals.extension_int_data[i].set != 0 &&
+ session->internals.extension_int_data[i].type == type)
+ {
+ *data = session->internals.extension_int_data[i].priv;
+ return 0;
+ }
+ }
+ return GNUTLS_E_INVALID_REQUEST;
+}
+
+int _gnutls_ext_get_resumed_session_data(gnutls_session_t session,
+ uint16_t type, extension_priv_data_t* data)
+{
+int i;
+
+ for (i=0;i<MAX_EXT_TYPES;i++)
+ {
+ if (session->internals.resumed_extension_int_data[i].set != 0 &&
+ session->internals.resumed_extension_int_data[i].type == type)
+ {
+ *data = session->internals.resumed_extension_int_data[i].priv;
+ return 0;
+ }
+ }
+ return GNUTLS_E_INVALID_REQUEST;
}
*
*/
+#ifndef GNUTLS_EXTENSIONS_H
+#define GNUTLS_EXTENSIONS_H
+
int _gnutls_parse_extensions (gnutls_session_t session,
gnutls_ext_parse_type_t parse_type,
const opaque * data, int data_size);
void _gnutls_ext_deinit (void);
void _gnutls_extension_list_add (gnutls_session_t session, uint16_t type);
+
+typedef void (*gnutls_ext_deinit_data_func) (extension_priv_data_t data);
+typedef int (*gnutls_ext_pack_func) (extension_priv_data_t data, gnutls_buffer_st* packed_data);
+typedef int (*gnutls_ext_unpack_func) (gnutls_buffer_st* packed_data, extension_priv_data_t* data);
+
+void _gnutls_ext_free_session_data(gnutls_session_t session);
+
+/* functions to be used by extensions internally
+ */
+void _gnutls_ext_unset_session_data(gnutls_session_t session, uint16_t type);
+void _gnutls_ext_set_session_data(gnutls_session_t session, uint16_t type,
+ extension_priv_data_t);
+int _gnutls_ext_get_session_data(gnutls_session_t session,
+ uint16_t type, extension_priv_data_t*);
+int _gnutls_ext_get_resumed_session_data(gnutls_session_t session,
+ uint16_t type, extension_priv_data_t* data);
+
+void _gnutls_ext_restore_resumed_session(gnutls_session_t session);
+
+/* for session packing */
+int _gnutls_ext_pack(gnutls_session_t session, gnutls_buffer_st* packed);
+int _gnutls_ext_unpack(gnutls_session_t session, gnutls_buffer_st* packed);
+
+typedef struct
+{
+ const char *name;
+ uint16_t type;
+ gnutls_ext_parse_type_t parse_type;
+
+ /* this function must return 0 when Not Applicable
+ * size of extension data if ok
+ * < 0 on other error.
+ */
+ gnutls_ext_recv_func recv_func;
+
+ /* this function must return 0 when Not Applicable
+ * size of extension data if ok
+ * GNUTLS_E_INT_RET_0 if extension data size is zero
+ * < 0 on other error.
+ */
+ gnutls_ext_send_func send_func;
+
+ gnutls_ext_deinit_data_func deinit_func; /* this will be called to deinitialize
+ * internal data
+ */
+ gnutls_ext_pack_func pack_func; /* packs internal data to machine independent format */
+ gnutls_ext_unpack_func unpack_func; /* unpacks internal data */
+
+} extension_entry_st;
+
+int _gnutls_ext_register (extension_entry_st*);
+
+#endif
if (session->internals.finished_func)
session->internals.finished_func (session, data, vdata_size);
- /* Save data for safe renegotiation.
- */
- if (vdata_size > MAX_VERIFY_DATA_SIZE)
- {
- gnutls_assert ();
- return GNUTLS_E_INTERNAL_ERROR;
- }
-
- if (session->security_parameters.entity == GNUTLS_CLIENT)
- {
- session->security_parameters.extensions.client_verify_data_len =
- vdata_size;
-
- memcpy (session->security_parameters.extensions.client_verify_data, data, vdata_size);
- }
- else
- {
- session->security_parameters.extensions.server_verify_data_len = vdata_size;
- memcpy (session->security_parameters.extensions.server_verify_data,
- data, vdata_size);
- }
+ ret = _gnutls_ext_sr_finished( session, data, vdata_size, 0);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ return ret;
+ }
ret = _gnutls_send_handshake (session, bufel, GNUTLS_HANDSHAKE_FINISHED);
}
int data_size;
int ret;
int vrfysize;
- tls_ext_st *ext;
ret =
_gnutls_recv_handshake (session, &vrfy, &vrfysize,
}
gnutls_free (vrfy);
- /* Save peer's verify data for safe renegotiation */
- if (data_size > MAX_VERIFY_DATA_SIZE)
- {
- gnutls_assert ();
- return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
- }
-
- ext = &session->security_parameters.extensions;
-
- if (session->security_parameters.entity == GNUTLS_CLIENT)
- {
- memcpy (ext->server_verify_data, data, data_size);
- ext->server_verify_data_len = data_size;
- }
- else
+ ret = _gnutls_ext_sr_finished( session, data, data_size, 1);
+ if (ret < 0)
{
- memcpy (ext->client_verify_data, data, data_size);
- ext->client_verify_data_len = data_size;
+ gnutls_assert();
+ return ret;
}
session->internals.initial_negotiation_completed = 1;
{
_gnutls_handshake_log
("HSK[%p]: Received safe renegotiation CS\n", session);
- session->internals.safe_renegotiation_received = 1;
- session->internals.connection_using_safe_renegotiation = 1;
+ retval = _gnutls_ext_sr_recv_cs(session);
+ if (retval < 0)
+ {
+ gnutls_assert();
+ return retval;
+ }
break;
}
}
/* This should be sufficient by now. It should hold all the extensions
* plus the headers in a hello message.
*/
-#define MAX_EXT_DATA_LENGTH 1024
+#define MAX_EXT_DATA_LENGTH 4096
/* This function sends the client hello handshake message.
*/
return GNUTLS_E_MEMORY_ERROR;
}
data = _mbuffer_get_udata_ptr(bufel);
- extdatalen = MAX_EXT_DATA_LENGTH
- +
- session->internals.resumed_security_parameters.
- extensions.session_ticket_len;
+ extdatalen = MAX_EXT_DATA_LENGTH;
extdata = gnutls_malloc (extdatalen);
if (extdata == NULL)
if (ret > 0)
{
- bufel = _mbuffer_append_data (bufel, extdata, ret);
+ bufel = _mbuffer_push_data (bufel, extdata, ret);
if (bufel == NULL)
{
gnutls_assert ();
ret = _gnutls_copy_comp_methods (session, extdata, extdatalen);
if (ret > 0)
{
- bufel = _mbuffer_append_data (bufel, extdata, ret);
+ bufel = _mbuffer_push_data (bufel, extdata, ret);
if (bufel == NULL)
{
gnutls_assert ();
if (ret > 0)
{
- bufel = _mbuffer_append_data (bufel, extdata, ret);
+ bufel = _mbuffer_push_data (bufel, extdata, ret);
if (bufel == NULL)
{
gnutls_assert ();
datalen = 0;
-#ifdef ENABLE_SRP
- if (IS_SRP_KX
- (_gnutls_cipher_suite_get_kx_algo
- (&session->security_parameters.current_cipher_suite)))
- {
- /* While resuming we cannot check the username extension since it is
- * not available at this point. It will be copied on connection
- * state activation.
- */
- if (session->internals.resumed == RESUME_FALSE &&
- session->security_parameters.extensions.srp_username[0] == 0)
- {
- /* The peer didn't send a valid SRP extension with the
- * SRP username. The draft requires that we send a fatal
- * alert and abort.
- */
- gnutls_assert ();
- return GNUTLS_E_UNKNOWN_SRP_USERNAME;
- }
- }
-#endif
-
if (again == 0)
{
datalen = 2 + session_id_len + 1 + GNUTLS_RANDOM_SIZE + 3;
{
int ret;
- session->internals.safe_renegotiation_received = 0;
-
if (session->security_parameters.entity == GNUTLS_CLIENT)
{
ret = _gnutls_send_client_hello (session, again);
_gnutls_recv_hello (gnutls_session_t session, opaque * data, int datalen)
{
int ret;
- tls_ext_st *ext;
if (session->security_parameters.entity == GNUTLS_CLIENT)
{
}
}
- if (session->internals.priorities.sr == SR_DISABLED)
- {
- gnutls_assert ();
- return ret;
- }
-
- /* Safe renegotiation */
- ext = &session->security_parameters.extensions;
-
- if (session->internals.safe_renegotiation_received)
- {
- if ((ext->ri_extension_data_len < ext->client_verify_data_len) ||
- (memcmp (ext->ri_extension_data,
- ext->client_verify_data, ext->client_verify_data_len)))
- {
- gnutls_assert ();
- _gnutls_handshake_log ("HSK[%p]: Safe renegotiation failed [1]\n",
- session);
- return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
- }
-
- if (session->security_parameters.entity == GNUTLS_CLIENT)
- {
- if ((ext->ri_extension_data_len !=
- ext->client_verify_data_len + ext->server_verify_data_len) ||
- memcmp (ext->ri_extension_data + ext->client_verify_data_len,
- ext->server_verify_data,
- ext->server_verify_data_len) != 0)
- {
- gnutls_assert ();
- _gnutls_handshake_log
- ("HSK[%p]: Safe renegotiation failed [2]\n", session);
- return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
- }
- }
- else /* Make sure there are 0 extra bytes */
- {
- if (ext->ri_extension_data_len != ext->client_verify_data_len)
- {
- gnutls_assert ();
- _gnutls_handshake_log
- ("HSK[%p]: Safe renegotiation failed [3]\n", session);
- return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
- }
- }
-
- _gnutls_handshake_log ("HSK[%p]: Safe renegotiation succeeded\n",
- session);
- }
- else /* safe renegotiation not received... */
+ ret = _gnutls_ext_sr_verify(session);
+ if (ret < 0)
{
- if (session->internals.connection_using_safe_renegotiation)
- {
- gnutls_assert ();
- _gnutls_handshake_log
- ("HSK[%p]: Peer previously asked for safe renegotiation\n",
- session);
- return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
- }
-
- /* Clients can't tell if it's an initial negotiation */
- if (session->internals.initial_negotiation_completed)
- {
-
- if (session->internals.priorities.sr < SR_PARTIAL)
- {
- _gnutls_handshake_log
- ("HSK[%p]: Allowing unsafe (re)negotiation\n", session);
- }
- else
- {
- gnutls_assert ();
- _gnutls_handshake_log
- ("HSK[%p]: Denying unsafe (re)negotiation\n", session);
- return GNUTLS_E_UNSAFE_RENEGOTIATION_DENIED;
- }
- }
- else
- {
- if (session->internals.priorities.sr < SR_SAFE)
- {
- _gnutls_handshake_log
- ("HSK[%p]: Allowing unsafe initial negotiation\n", session);
- }
- else
- {
- gnutls_assert ();
- _gnutls_handshake_log
- ("HSK[%p]: Denying unsafe initial negotiation\n", session);
- return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
- }
- }
+ gnutls_assert();
+ return ret;
}
- return ret;
+ return 0;
}
/* The packets in gnutls_handshake (it's more broad than original TLS handshake)
IMED_RET ("recv hello", ret, 1);
case STATE70:
- if (session->security_parameters.extensions.do_recv_supplemental)
+ if (session->security_parameters.do_recv_supplemental)
{
ret = _gnutls_recv_supplemental (session);
STATE = STATE70;
IMED_RET ("recv server hello done", ret, 1);
case STATE71:
- if (session->security_parameters.extensions.do_send_supplemental)
+ if (session->security_parameters.do_send_supplemental)
{
ret = _gnutls_send_supplemental (session, AGAIN (STATE71));
STATE = STATE71;
gnutls_assert ();
return ret;
}
-
/* Initialize the connection session (start encryption) - in case of client
*/
if (init == TRUE)
IMED_RET ("send hello", ret, 0);
case STATE70:
- if (session->security_parameters.extensions.do_send_supplemental)
+ if (session->security_parameters.do_send_supplemental)
{
ret = _gnutls_send_supplemental (session, AGAIN (STATE70));
STATE = STATE70;
IMED_RET ("send server hello done", ret, 0);
case STATE71:
- if (session->security_parameters.extensions.do_recv_supplemental)
+ if (session->security_parameters.do_recv_supplemental)
{
ret = _gnutls_recv_supplemental (session);
STATE = STATE71;
{
case STATE0:
case STATE40:
- if (session->internals.session_ticket_renew)
- {
- ret =
- _gnutls_send_new_session_ticket (session, AGAIN (STATE40));
- STATE = STATE40;
- IMED_RET ("send handshake new session ticket", ret, 0);
- }
+ ret = _gnutls_send_new_session_ticket (session, AGAIN (STATE40));
+ STATE = STATE40;
+ IMED_RET ("send handshake new session ticket", ret, 0);
STATE = STATE0;
default:
break;
{
case STATE0:
case STATE41:
- if (session->internals.session_ticket_renew)
- {
- ret = _gnutls_recv_new_session_ticket (session);
- STATE = STATE41;
- IMED_RET ("recv handshake new session ticket", ret, 1);
- }
+ ret = _gnutls_recv_new_session_ticket (session);
+ STATE = STATE41;
+ IMED_RET ("recv handshake new session ticket", ret, 1);
STATE = STATE0;
default:
break;
/* we can receive up to MAX_EXT_TYPES extensions.
*/
-#define MAX_EXT_TYPES 64
+#define MAX_EXT_TYPES 32
/* The initial size of the receive
* buffer size. This will grow if larger
{ GNUTLS_EXTENSION_SERVER_NAME = 0,
GNUTLS_EXTENSION_MAX_RECORD_SIZE = 1,
GNUTLS_EXTENSION_CERT_TYPE = 9,
-#ifdef ENABLE_OPRFI
- GNUTLS_EXTENSION_OPAQUE_PRF_INPUT = ENABLE_OPRFI,
-#endif
GNUTLS_EXTENSION_SRP = 12,
GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS = 13,
GNUTLS_EXTENSION_SESSION_TICKET = 35,
typedef enum
{ CIPHER_STREAM, CIPHER_BLOCK } cipher_type_t;
-typedef enum valid_session_t
-{ VALID_TRUE, VALID_FALSE } valid_session_t;
-typedef enum resumable_session_t
-{ RESUME_TRUE,
- RESUME_FALSE
-} resumable_session_t;
+#define RESUME_TRUE 0
+#define RESUME_FALSE -1
/* Record Protocol */
typedef enum content_type_t
* structures also - see SRP).
*/
-typedef struct
-{
- opaque name[MAX_SERVER_NAME_SIZE];
- unsigned name_length;
- gnutls_server_name_type_t type;
-} server_name_st;
-
-#define MAX_SERVER_NAME_EXTENSIONS 3
#define MAX_SIGNATURE_ALGORITHMS 16
-struct gnutls_session_ticket_key_st
-{
- opaque key_name[SESSION_TICKET_KEY_NAME_SIZE];
- opaque key[SESSION_TICKET_KEY_SIZE];
- opaque mac_secret[SESSION_TICKET_MAC_SECRET_SIZE];
-};
-
#define MAX_VERIFY_DATA_SIZE 36 /* in SSL 3.0, 12 in TLS 1.0 */
-/* If you want the extension data to be kept across resuming sessions
- * then modify CPY_EXTENSIONS in gnutls_constate.c
- */
-typedef struct
-{
- server_name_st server_names[MAX_SERVER_NAME_EXTENSIONS];
- /* limit server_name extensions */
- unsigned server_names_size;
-
- opaque srp_username[MAX_SRP_USERNAME + 1];
-
- /* TLS 1.2 signature algorithms */
- gnutls_sign_algorithm_t sign_algorithms[MAX_SIGNATURE_ALGORITHMS];
- uint16_t sign_algorithms_size;
-
- /* TLS/IA data. */
- int gnutls_ia_enable, gnutls_ia_peer_enable;
- int gnutls_ia_allowskip, gnutls_ia_peer_allowskip;
-
- /* Used by extensions that enable supplemental data. */
- int do_recv_supplemental, do_send_supplemental;
-
- opaque *session_ticket;
- uint16_t session_ticket_len;
-
- /*** Those below do not get copied when resuming session
- ***/
-
- /* Opaque PRF input. */
- opaque *oprfi_client;
- uint16_t oprfi_client_len;
- opaque *oprfi_server;
- uint16_t oprfi_server_len;
-
- /* Safe renegotiation. */
- uint8_t client_verify_data[MAX_VERIFY_DATA_SIZE];
- size_t client_verify_data_len;
- uint8_t server_verify_data[MAX_VERIFY_DATA_SIZE];
- size_t server_verify_data_len;
- uint8_t ri_extension_data[MAX_VERIFY_DATA_SIZE * 2]; /* max signal is 72 bytes in s->c sslv3 */
- size_t ri_extension_data_len;
-
-} tls_ext_st;
-
/* auth_info_t structures now MAY contain malloced
* elements.
*/
opaque session_id[TLS_MAX_SESSION_ID_SIZE];
uint8_t session_id_size;
time_t timestamp;
- tls_ext_st extensions;
/* The send size is the one requested by the programmer.
* The recv size is the one negotiated with the peer.
gnutls_certificate_type_t cert_type;
gnutls_protocol_t version; /* moved here */
- /* For TLS/IA. XXX: Move to IA credential? */
- opaque inner_secret[GNUTLS_MASTER_SIZE];
+ /* FIXME: The following are not saved in the session storage
+ * for session resumption.
+ */
+
+ /* Used by extensions that enable supplemental data: Which ones
+ * do that? Do they belong in security parameters?
+ */
+ int do_recv_supplemental, do_send_supplemental;
} security_parameters_st;
/* This structure holds the generated keys
gnutls_handshake_description_t recv_type;
} handshake_header_buffer_st;
+typedef union
+{
+ void* ptr;
+ uint32_t num;
+} extension_priv_data_t;
typedef struct
{
gnutls_buffer_st handshake_data_buffer; /* this is a buffer that holds the current handshake message */
gnutls_buffer_st ia_data_buffer; /* holds inner application data (TLS/IA) */
- resumable_session_t resumable; /* TRUE or FALSE - if we can resume that session */
+ int resumable:1; /* TRUE or FALSE - if we can resume that session */
handshake_state_t handshake_state; /* holds
* a number which indicates where
* the handshake procedure has been
* no interruption has happened.
*/
- valid_session_t valid_connection; /* true or FALSE - if this session is valid */
+ int invalid_connection:1; /* true or FALSE - if this session is valid */
- int may_not_read; /* if it's 0 then we can read/write, otherwise it's forbiden to read/write
+ int may_not_read:1; /* if it's 0 then we can read/write, otherwise it's forbiden to read/write
*/
- int may_not_write;
- int read_eof; /* non-zero if we have received a closure alert. */
+ int may_not_write:1;
+ int read_eof:1; /* non-zero if we have received a closure alert. */
int last_alert; /* last alert received */
struct gnutls_priority_st priorities;
/* resumed session */
- resumable_session_t resumed; /* RESUME_TRUE or FALSE - if we are resuming a session */
+ int resumed:1; /* RESUME_TRUE or FALSE - if we are resuming a session */
security_parameters_st resumed_security_parameters;
/* sockets internals */
/* 0 if no peeked data was kept, 1 otherwise.
*/
- int have_peeked_data;
+ int have_peeked_data:1;
int expire_time; /* after expire_time seconds this session will expire */
struct mod_auth_st_int *auth_struct; /* used in handshake packets and KX algorithms */
*/
gnutls_handshake_post_client_hello_func user_hello_func;
- /* Holds the record size requested by the
- * user.
- */
- uint16_t proposed_record_size;
-
/* holds the selected certificate and key.
* use _gnutls_selected_certs_deinit() and _gnutls_selected_certs_set()
* to change them.
gnutls_cert *selected_cert_list;
int selected_cert_list_length;
struct gnutls_privkey_st *selected_key;
- int selected_need_free;
+ int selected_need_free:1;
/* holds the extensions we sent to the peer
* (in case of a client)
* record packet will have. */
opaque default_record_version[2];
- int cbc_protection_hack;
-
void *user_ptr;
int enable_private; /* non zero to
*/
opaque rsa_pms_version[2];
- char *srp_username;
- char *srp_password;
-
/* Here we cache the DH or RSA parameters got from the
* credentials structure, or from a callback. That is to
* minimize external calls.
*/
uint16_t srp_prime_bits;
- int session_ticket_enable, session_ticket_renew;
-
- int safe_renegotiation_received:1;
int initial_negotiation_completed:1;
- int connection_using_safe_renegotiation:1;
-
- /* Oprfi */
- gnutls_oprfi_callback_func oprfi_cb;
- const void *oprfi_userdata;
- /* Session Ticket */
- struct gnutls_session_ticket_key_st *session_ticket_key;
- opaque session_ticket_IV[SESSION_TICKET_IV_SIZE];
+ struct {
+ uint16_t type;
+ extension_priv_data_t priv;
+ int set:1;
+ } extension_int_data[MAX_EXT_TYPES];
+
+ struct {
+ uint16_t type;
+ extension_priv_data_t priv;
+ int set:1;
+ } resumed_extension_int_data[MAX_EXT_TYPES];
/* If you add anything here, check _gnutls_handshake_internal_state_clear().
*/
#include <gnutls_datum.h>
#include <gnutls_rsa_export.h>
#include <gnutls_mbuffers.h>
+#include "../libextra/ext_inner_application.h" /* isn't this too much? */
/* This is a temporary function to be used before the generate_*
internal API is changed to use mbuffers. For now we don't avoid the
security_parameters.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 * GNUTLS_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), NULL));
- _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), NULL));
-
- memcpy (rnd, session->security_parameters.client_random,
- GNUTLS_RANDOM_SIZE);
- memcpy (rnd + GNUTLS_RANDOM_SIZE,
- session->security_parameters.extensions.oprfi_client,
- session->security_parameters.extensions.oprfi_client_len);
- memcpy (rnd + GNUTLS_RANDOM_SIZE +
- session->security_parameters.extensions.oprfi_client_len,
- session->security_parameters.server_random, GNUTLS_RANDOM_SIZE);
- memcpy (rnd + GNUTLS_RANDOM_SIZE +
- session->security_parameters.extensions.oprfi_client_len +
- GNUTLS_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, GNUTLS_MASTER_SIZE,
- session->security_parameters.master_secret);
-
- gnutls_free (rnd);
- }
else
{
opaque rnd[2 * GNUTLS_RANDOM_SIZE + 1];
}
/* TLS/IA inner secret is derived from the master secret. */
- memcpy (session->security_parameters.inner_secret,
- session->security_parameters.master_secret, GNUTLS_MASTER_SIZE);
+ _gnutls_ia_derive_inner_secret(session);
if (!keep_premaster)
_gnutls_free_datum (&PREMASTER);
}
mbuffer_st*
-_mbuffer_append_data (mbuffer_st *bufel, void* newdata, size_t newdata_size)
+_mbuffer_push_data (mbuffer_st *bufel, void* newdata, size_t newdata_size)
{
bufel = gnutls_realloc_fast (bufel, bufel->msg.size+newdata_size+sizeof (mbuffer_st));
if (bufel == NULL)
/* This is dangerous since it will replace bufel with a new
* one.
*/
-mbuffer_st* _mbuffer_append_data (mbuffer_st *bufel, void* newdata, size_t newdata_size);
+mbuffer_st* _mbuffer_push_data (mbuffer_st *bufel, void* newdata, size_t newdata_size);
/* For "user" use. One can have buffer data and header.
inline static void
session_invalidate (gnutls_session_t session)
{
- session->internals.valid_connection = VALID_FALSE;
+ session->internals.invalid_connection = 1;
}
inline static int
session_is_valid (gnutls_session_t session)
{
- if (session->internals.valid_connection == VALID_FALSE)
+ if (session->internals.invalid_connection != 0)
return GNUTLS_E_INVALID_SESSION;
return 0;
sizeofdata);
}
-/**
- * gnutls_record_get_max_size:
- * @session: is a #gnutls_session_t structure.
- *
- * Get the record size. The maximum record size is negotiated by the
- * client after the first handshake message.
- *
- * Returns: The maximum record packet size in this connection.
- **/
-size_t
-gnutls_record_get_max_size (gnutls_session_t session)
-{
- /* Recv will hold the negotiated max record size
- * always.
- */
- return session->security_parameters.max_record_recv_size;
-}
-
-
-/**
- * gnutls_record_set_max_size:
- * @session: is a #gnutls_session_t structure.
- * @size: is the new size
- *
- * This function sets the maximum record packet size in this
- * connection. This property can only be set to clients. The server
- * may choose not to accept the requested size.
- *
- * Acceptable values are 512(=2^9), 1024(=2^10), 2048(=2^11) and
- * 4096(=2^12). The requested record size does get in effect
- * immediately only while sending data. The receive part will take
- * effect after a successful handshake.
- *
- * This function uses a TLS extension called 'max record size'. Not
- * all TLS implementations use or even understand this extension.
- *
- * Returns: On success, %GNUTLS_E_SUCCESS (zero) is returned,
- * otherwise an error code is returned.
- **/
-ssize_t
-gnutls_record_set_max_size (gnutls_session_t session, size_t size)
-{
- ssize_t new_size;
-
- if (session->security_parameters.entity == GNUTLS_SERVER)
- return GNUTLS_E_INVALID_REQUEST;
-
- new_size = _gnutls_mre_record2num (size);
-
- if (new_size < 0)
- {
- gnutls_assert ();
- return new_size;
- }
-
- session->security_parameters.max_record_send_size = size;
-
- session->internals.proposed_record_size = size;
-
- return 0;
-}
#include <gnutls_session_pack.h>
#include <gnutls_datum.h>
#include <gnutls_num.h>
+#include <gnutls_extensions.h>
-#define PACK_HEADER_SIZE 1
-#define MAX_SEC_PARAMS 7+MAX_SRP_USERNAME+MAX_SERVER_NAME_EXTENSIONS*(3+MAX_SERVER_NAME_SIZE)+165
static int pack_certificate_auth_info (gnutls_session_t,
- gnutls_datum_t * packed_session);
+ gnutls_buffer_st * packed_session);
static int unpack_certificate_auth_info (gnutls_session_t,
- const gnutls_datum_t *
+ gnutls_buffer_st *
packed_session);
static int unpack_srp_auth_info (gnutls_session_t session,
- const gnutls_datum_t * packed_session);
+ gnutls_buffer_st * packed_session);
static int pack_srp_auth_info (gnutls_session_t session,
- gnutls_datum_t * packed_session);
+ gnutls_buffer_st * packed_session);
static int unpack_psk_auth_info (gnutls_session_t session,
- const gnutls_datum_t * packed_session);
+ gnutls_buffer_st * packed_session);
static int pack_psk_auth_info (gnutls_session_t session,
- gnutls_datum_t * packed_session);
+ gnutls_buffer_st * packed_session);
static int unpack_anon_auth_info (gnutls_session_t session,
- const gnutls_datum_t * packed_session);
+ gnutls_buffer_st * packed_session);
static int pack_anon_auth_info (gnutls_session_t session,
- gnutls_datum_t * packed_session);
+ gnutls_buffer_st * packed_session);
static int unpack_security_parameters (gnutls_session_t session,
- const gnutls_datum_t * packed_session);
+ gnutls_buffer_st * packed_session);
static int pack_security_parameters (gnutls_session_t session,
- gnutls_datum_t * packed_session);
+ gnutls_buffer_st * packed_session);
/* Since auth_info structures contain malloced data, this function
gnutls_datum_t * packed_session)
{
int ret;
+ gnutls_buffer_st sb;
+ opaque id;
if (packed_session == NULL)
{
return GNUTLS_E_INTERNAL_ERROR;
}
+ _gnutls_buffer_init(&sb);
- switch (gnutls_auth_get_type (session))
+ id = gnutls_auth_get_type (session);
+ BUFFER_APPEND(&sb, &id, 1);
+
+ switch (id)
{
#ifdef ENABLE_SRP
case GNUTLS_CRD_SRP:
- ret = pack_srp_auth_info (session, packed_session);
+ ret = pack_srp_auth_info (session, &sb);
if (ret < 0)
{
gnutls_assert ();
#endif
#ifdef ENABLE_PSK
case GNUTLS_CRD_PSK:
- ret = pack_psk_auth_info (session, packed_session);
+ ret = pack_psk_auth_info (session, &sb);
if (ret < 0)
{
gnutls_assert ();
#endif
#ifdef ENABLE_ANON
case GNUTLS_CRD_ANON:
- ret = pack_anon_auth_info (session, packed_session);
+ ret = pack_anon_auth_info (session, &sb);
if (ret < 0)
{
gnutls_assert ();
break;
#endif
case GNUTLS_CRD_CERTIFICATE:
- ret = pack_certificate_auth_info (session, packed_session);
+ ret = pack_certificate_auth_info (session, &sb);
if (ret < 0)
{
gnutls_assert ();
/* Auth_info structures copied. Now copy security_parameters_st.
* packed_session must have allocated space for the security parameters.
*/
- ret = pack_security_parameters (session, packed_session);
+ ret = pack_security_parameters (session, &sb);
if (ret < 0)
{
gnutls_assert ();
- _gnutls_free_datum (packed_session);
+ _gnutls_buffer_clear(&sb);
return ret;
}
-
- return 0;
+
+ ret = _gnutls_ext_pack(session, &sb);
+ if (ret < 0)
+ {
+ gnutls_assert ();
+ _gnutls_buffer_clear(&sb);
+ return ret;
+ }
+
+ ret = _gnutls_buffer_to_datum(&sb, packed_session);
+
+ return ret;
}
const gnutls_datum_t * packed_session)
{
int ret;
+ gnutls_buffer_st sb;
+ opaque id;
+
+ _gnutls_buffer_init(&sb);
if (packed_session == NULL || packed_session->size == 0)
{
return GNUTLS_E_INTERNAL_ERROR;
}
+ ret = _gnutls_buffer_append_data(&sb, packed_session->data, packed_session->size);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ return ret;
+ }
+
if (_gnutls_get_auth_info (session) != NULL)
{
_gnutls_free_auth_info (session);
}
- switch (packed_session->data[0])
+ BUFFER_POP(&sb, &id, 1);
+
+ switch (id)
{
#ifdef ENABLE_SRP
case GNUTLS_CRD_SRP:
- ret = unpack_srp_auth_info (session, packed_session);
+ ret = unpack_srp_auth_info (session, &sb);
if (ret < 0)
{
gnutls_assert ();
- return ret;
+ goto error;
}
break;
#endif
#ifdef ENABLE_PSK
case GNUTLS_CRD_PSK:
- ret = unpack_psk_auth_info (session, packed_session);
+ ret = unpack_psk_auth_info (session, &sb);
if (ret < 0)
{
gnutls_assert ();
- return ret;
+ goto error;
}
break;
#endif
#ifdef ENABLE_ANON
case GNUTLS_CRD_ANON:
- ret = unpack_anon_auth_info (session, packed_session);
+ ret = unpack_anon_auth_info (session, &sb);
if (ret < 0)
{
gnutls_assert ();
break;
#endif
case GNUTLS_CRD_CERTIFICATE:
- ret = unpack_certificate_auth_info (session, packed_session);
+ ret = unpack_certificate_auth_info (session, &sb);
if (ret < 0)
{
gnutls_assert ();
- return ret;
+ goto error;
}
break;
default:
gnutls_assert ();
- return GNUTLS_E_INTERNAL_ERROR;
+ ret = GNUTLS_E_INTERNAL_ERROR;
+ goto error;
}
/* Auth_info structures copied. Now copy security_parameters_st.
* packed_session must have allocated space for the security parameters.
*/
- ret = unpack_security_parameters (session, packed_session);
+ ret = unpack_security_parameters (session, &sb);
if (ret < 0)
{
gnutls_assert ();
- return ret;
+ goto error;
+ }
+
+ ret = _gnutls_ext_unpack(session, &sb);
+ if (ret < 0)
+ {
+ gnutls_assert ();
+ goto error;
}
- return 0;
+ ret = 0;
+
+error:
+ _gnutls_buffer_clear(&sb);
+
+ return ret;
}
+
/* Format:
* 1 byte the credentials type
* 4 bytes the size of the whole structure
*/
static int
pack_certificate_auth_info (gnutls_session_t session,
- gnutls_datum_t * packed_session)
+ gnutls_buffer_st * ps)
{
- unsigned int pos = 0, i;
- int cert_size, pack_size;
+ unsigned int i;
+ int cur_size, ret;
cert_auth_info_t info = _gnutls_get_auth_info (session);
+ void* size_pos;
- if (info)
- {
- cert_size = 4;
+ size_pos = ps->data + ps->length;
- for (i = 0; i < info->ncerts; i++)
- cert_size += 4 + info->raw_certificate_list[i].size;
-
- pack_size = 2 + 4 + info->dh.prime.size +
- 4 + info->dh.generator.size + 4 + info->dh.public_key.size +
- 4 + info->rsa_export.modulus.size +
- 4 + info->rsa_export.exponent.size + cert_size;
- }
- else
- pack_size = 0;
-
- packed_session->size = PACK_HEADER_SIZE + pack_size + sizeof (uint32_t);
-
- /* calculate the size and allocate the data.
- */
- packed_session->data =
- gnutls_malloc (packed_session->size + MAX_SEC_PARAMS + 2 +
- session->security_parameters.extensions.
- session_ticket_len);
+ BUFFER_APPEND_NUM(ps, 0);
+ cur_size = ps->length;
- if (packed_session->data == NULL)
- {
- gnutls_assert ();
- return GNUTLS_E_MEMORY_ERROR;
- }
-
- packed_session->data[0] = GNUTLS_CRD_CERTIFICATE;
- _gnutls_write_uint32 (pack_size, &packed_session->data[PACK_HEADER_SIZE]);
- pos += 4 + PACK_HEADER_SIZE;
-
-
- if (pack_size > 0)
+ if (info)
{
- _gnutls_write_uint16 (info->dh.secret_bits, &packed_session->data[pos]);
- pos += 2;
-
- _gnutls_write_datum32 (&packed_session->data[pos], info->dh.prime);
- pos += 4 + info->dh.prime.size;
- _gnutls_write_datum32 (&packed_session->data[pos], info->dh.generator);
- pos += 4 + info->dh.generator.size;
- _gnutls_write_datum32 (&packed_session->data[pos], info->dh.public_key);
- pos += 4 + info->dh.public_key.size;
+ BUFFER_APPEND_NUM( ps, info->dh.secret_bits);
+ BUFFER_APPEND_PFX( ps, info->dh.prime.data, info->dh.prime.size);
+ BUFFER_APPEND_PFX( ps, info->dh.generator.data, info->dh.generator.size);
+ BUFFER_APPEND_PFX( ps, info->dh.public_key.data, info->dh.public_key.size);
+ BUFFER_APPEND_PFX( ps, info->rsa_export.modulus.data, info->rsa_export.modulus.size);
+ BUFFER_APPEND_PFX( ps, info->rsa_export.exponent.data, info->rsa_export.exponent.size);
- _gnutls_write_datum32 (&packed_session->data[pos],
- info->rsa_export.modulus);
- pos += 4 + info->rsa_export.modulus.size;
- _gnutls_write_datum32 (&packed_session->data[pos],
- info->rsa_export.exponent);
- pos += 4 + info->rsa_export.exponent.size;
-
- _gnutls_write_uint32 (info->ncerts, &packed_session->data[pos]);
- pos += 4;
+ BUFFER_APPEND_NUM( ps, info->ncerts);
for (i = 0; i < info->ncerts; i++)
- {
- _gnutls_write_datum32 (&packed_session->data[pos],
- info->raw_certificate_list[i]);
- pos += sizeof (uint32_t) + info->raw_certificate_list[i].size;
- }
+ BUFFER_APPEND_PFX( ps, info->raw_certificate_list[i].data, info->raw_certificate_list[i].size);
}
+ /* write the real size */
+ _gnutls_write_uint32(ps->length-cur_size, size_pos);
+
return 0;
}
*/
static int
unpack_certificate_auth_info (gnutls_session_t session,
- const gnutls_datum_t * packed_session)
+ gnutls_buffer_st * ps)
{
- int pos = 0, size, ret;
- unsigned int i = 0, j;
+ int ret;
+ unsigned int i = 0, j = 0;
size_t pack_size;
- cert_auth_info_t info;
-
- if (packed_session->data[0] != GNUTLS_CRD_CERTIFICATE)
- {
- gnutls_assert ();
- return GNUTLS_E_INVALID_REQUEST;
- }
+ cert_auth_info_t info = NULL;
- pack_size = _gnutls_read_uint32 (&packed_session->data[PACK_HEADER_SIZE]);
- pos += PACK_HEADER_SIZE + 4;
+ BUFFER_POP_NUM(ps, pack_size);
if (pack_size == 0)
return 0; /* nothing to be done */
- /* a simple check for integrity */
- if (pack_size + PACK_HEADER_SIZE + 4 > packed_session->size)
- {
- gnutls_assert ();
- return GNUTLS_E_INVALID_REQUEST;
- }
-
/* client and server have the same auth_info here
*/
ret =
return GNUTLS_E_INTERNAL_ERROR;
}
- info->dh.secret_bits = _gnutls_read_uint16 (&packed_session->data[pos]);
- pos += 2;
-
- size = _gnutls_read_uint32 (&packed_session->data[pos]);
- pos += 4;
- ret = _gnutls_set_datum (&info->dh.prime, &packed_session->data[pos], size);
- if (ret < 0)
- {
- gnutls_assert ();
- goto error;
- }
- pos += size;
-
- size = _gnutls_read_uint32 (&packed_session->data[pos]);
- pos += 4;
- ret =
- _gnutls_set_datum (&info->dh.generator, &packed_session->data[pos], size);
- if (ret < 0)
- {
- gnutls_assert ();
- goto error;
- }
- pos += size;
-
- size = _gnutls_read_uint32 (&packed_session->data[pos]);
- pos += 4;
- ret =
- _gnutls_set_datum (&info->dh.public_key, &packed_session->data[pos],
- size);
- if (ret < 0)
- {
- gnutls_assert ();
- goto error;
- }
- pos += size;
-
- size = _gnutls_read_uint32 (&packed_session->data[pos]);
- pos += 4;
- ret =
- _gnutls_set_datum (&info->rsa_export.modulus,
- &packed_session->data[pos], size);
- if (ret < 0)
- {
- gnutls_assert ();
- goto error;
- }
- pos += size;
+ BUFFER_POP_NUM(ps, info->dh.secret_bits);
- size = _gnutls_read_uint32 (&packed_session->data[pos]);
- pos += 4;
- ret =
- _gnutls_set_datum (&info->rsa_export.exponent,
- &packed_session->data[pos], size);
- if (ret < 0)
- {
- gnutls_assert ();
- goto error;
- }
- pos += size;
+ BUFFER_POP_DATUM(ps, &info->dh.prime);
+ BUFFER_POP_DATUM(ps, &info->dh.generator);
+ BUFFER_POP_DATUM(ps, &info->dh.public_key);
+ BUFFER_POP_DATUM(ps, &info->rsa_export.modulus);
+ BUFFER_POP_DATUM(ps, &info->rsa_export.exponent);
- info->ncerts = _gnutls_read_uint32 (&packed_session->data[pos]);
- pos += 4;
+ BUFFER_POP_NUM(ps, info->ncerts);
if (info->ncerts > 0)
{
- info->raw_certificate_list =
- gnutls_calloc (info->ncerts, sizeof (gnutls_datum_t));
+ info->raw_certificate_list = gnutls_calloc (info->ncerts, sizeof (gnutls_datum_t));
if (info->raw_certificate_list == NULL)
- {
- gnutls_assert ();
- ret = GNUTLS_E_MEMORY_ERROR;
- goto error;
- }
+ {
+ gnutls_assert ();
+ ret = GNUTLS_E_MEMORY_ERROR;
+ goto error;
+ }
}
for (i = 0; i < info->ncerts; i++)
{
- size = _gnutls_read_uint32 (&packed_session->data[pos]);
- pos += sizeof (uint32_t);
-
- ret =
- _gnutls_set_datum (&info->raw_certificate_list[i],
- &packed_session->data[pos], size);
- pos += size;
-
- if (ret < 0)
- {
- gnutls_assert ();
- goto error;
- }
+ BUFFER_POP_DATUM(ps, &info->raw_certificate_list[i]);
}
-
return 0;
error:
- _gnutls_free_datum (&info->dh.prime);
- _gnutls_free_datum (&info->dh.generator);
- _gnutls_free_datum (&info->dh.public_key);
+ if (info)
+ {
+ _gnutls_free_datum (&info->dh.prime);
+ _gnutls_free_datum (&info->dh.generator);
+ _gnutls_free_datum (&info->dh.public_key);
- _gnutls_free_datum (&info->rsa_export.modulus);
- _gnutls_free_datum (&info->rsa_export.exponent);
+ _gnutls_free_datum (&info->rsa_export.modulus);
+ _gnutls_free_datum (&info->rsa_export.exponent);
- for (j = 0; j < i; j++)
- _gnutls_free_datum (&info->raw_certificate_list[j]);
+ for (j = 0; j < i; j++)
+ _gnutls_free_datum (&info->raw_certificate_list[j]);
- gnutls_free (info->raw_certificate_list);
+ gnutls_free (info->raw_certificate_list);
+ }
return ret;
* x bytes the SRP username
*/
static int
-pack_srp_auth_info (gnutls_session_t session, gnutls_datum_t * packed_session)
+pack_srp_auth_info (gnutls_session_t session, gnutls_buffer_st * ps)
{
srp_server_auth_info_t info = _gnutls_get_auth_info (session);
- int pack_size;
+ int len, ret;
+ void* size_pos;
+ size_t cur_size;
if (info && info->username)
- pack_size = strlen (info->username) + 1; /* include the terminating null */
+ len = strlen (info->username) + 1; /* include the terminating null */
else
- pack_size = 0;
+ len = 0;
- packed_session->size = PACK_HEADER_SIZE + pack_size + sizeof (uint32_t);
+ size_pos = ps->data + ps->length;
- /* calculate the size and allocate the data.
- */
- packed_session->data =
- gnutls_malloc (packed_session->size + MAX_SEC_PARAMS + 2 +
- session->security_parameters.extensions.
- session_ticket_len);
+ BUFFER_APPEND_NUM(ps, 0);
+ cur_size = ps->length;
- if (packed_session->data == NULL)
- {
- gnutls_assert ();
- return GNUTLS_E_MEMORY_ERROR;
- }
-
- packed_session->data[0] = GNUTLS_CRD_SRP;
- _gnutls_write_uint32 (pack_size, &packed_session->data[PACK_HEADER_SIZE]);
+ BUFFER_APPEND_PFX(ps, info->username, len);
- if (pack_size > 0)
- memcpy (&packed_session->data[PACK_HEADER_SIZE + sizeof (uint32_t)],
- info->username, pack_size + 1);
+ /* write the real size */
+ _gnutls_write_uint32(ps->length-cur_size, size_pos);
return 0;
}
static int
unpack_srp_auth_info (gnutls_session_t session,
- const gnutls_datum_t * packed_session)
+ gnutls_buffer_st * ps)
{
size_t username_size;
int ret;
srp_server_auth_info_t info;
- if (packed_session->data[0] != GNUTLS_CRD_SRP)
- {
- gnutls_assert ();
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- username_size =
- _gnutls_read_uint32 (&packed_session->data[PACK_HEADER_SIZE]);
-
- if (username_size == 0)
- return 0; /* nothing to be done */
-
- /* a simple check for integrity */
- if (username_size + 4 + PACK_HEADER_SIZE > packed_session->size)
+ BUFFER_POP_NUM(ps, username_size);
+ if (username_size > sizeof(info->username))
{
- gnutls_assert ();
- return GNUTLS_E_INVALID_REQUEST;
+ gnutls_assert();
+ return GNUTLS_E_INTERNAL_ERROR;
}
+
ret =
_gnutls_auth_info_set (session, GNUTLS_CRD_SRP,
return GNUTLS_E_INTERNAL_ERROR;
}
- memcpy (info->username,
- &packed_session->data[PACK_HEADER_SIZE + sizeof (uint32_t)],
- username_size);
+ BUFFER_POP(ps, info->username, username_size);
- return 0;
+ ret = 0;
+
+error:
+ return ret;
}
#endif
*/
static int
pack_anon_auth_info (gnutls_session_t session,
- gnutls_datum_t * packed_session)
+ gnutls_buffer_st * ps)
{
+ int cur_size, ret;
anon_auth_info_t info = _gnutls_get_auth_info (session);
- int pos = 0;
- size_t pack_size;
-
- if (info)
- pack_size = 2 + 4 * 3 + info->dh.prime.size +
- info->dh.generator.size + info->dh.public_key.size;
- else
- pack_size = 0;
+ void* size_pos;
- packed_session->size = PACK_HEADER_SIZE + pack_size + sizeof (uint32_t);
+ size_pos = ps->data + ps->length;
- /* calculate the size and allocate the data.
- */
- packed_session->data =
- gnutls_malloc (packed_session->size + MAX_SEC_PARAMS + 2 +
- session->security_parameters.extensions.
- session_ticket_len);
+ BUFFER_APPEND_NUM(ps, 0);
+ cur_size = ps->length;
- if (packed_session->data == NULL)
+ if (info)
{
- gnutls_assert ();
- return GNUTLS_E_MEMORY_ERROR;
+ BUFFER_APPEND_NUM( ps, info->dh.secret_bits);
+ BUFFER_APPEND_PFX( ps, info->dh.prime.data, info->dh.prime.size);
+ BUFFER_APPEND_PFX( ps, info->dh.generator.data, info->dh.generator.size);
+ BUFFER_APPEND_PFX( ps, info->dh.public_key.data, info->dh.public_key.size);
}
- packed_session->data[0] = GNUTLS_CRD_ANON;
- _gnutls_write_uint32 (pack_size, &packed_session->data[PACK_HEADER_SIZE]);
- pos += 4 + PACK_HEADER_SIZE;
-
- if (pack_size > 0)
- {
- _gnutls_write_uint16 (info->dh.secret_bits, &packed_session->data[pos]);
- pos += 2;
-
- _gnutls_write_datum32 (&packed_session->data[pos], info->dh.prime);
- pos += 4 + info->dh.prime.size;
- _gnutls_write_datum32 (&packed_session->data[pos], info->dh.generator);
- pos += 4 + info->dh.generator.size;
- _gnutls_write_datum32 (&packed_session->data[pos], info->dh.public_key);
- pos += 4 + info->dh.public_key.size;
-
- }
+ /* write the real size */
+ _gnutls_write_uint32(ps->length-cur_size, size_pos);
return 0;
}
static int
unpack_anon_auth_info (gnutls_session_t session,
- const gnutls_datum_t * packed_session)
+ gnutls_buffer_st * ps)
{
+ int ret;
size_t pack_size;
- int pos = 0, size, ret;
- anon_auth_info_t info;
-
- if (packed_session->data[0] != GNUTLS_CRD_ANON)
- {
- gnutls_assert ();
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- pack_size = _gnutls_read_uint32 (&packed_session->data[PACK_HEADER_SIZE]);
- pos += PACK_HEADER_SIZE + 4;
+ anon_auth_info_t info = NULL;
+ BUFFER_POP_NUM(ps, pack_size);
if (pack_size == 0)
- return 0; /* nothing to be done */
+ return 0; /* nothing to be done */
- /* a simple check for integrity */
- if (pack_size + PACK_HEADER_SIZE + 4 > packed_session->size)
- {
- gnutls_assert ();
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- /* client and serer have the same auth_info here
+ /* client and server have the same auth_info here
*/
ret =
_gnutls_auth_info_set (session, GNUTLS_CRD_ANON,
return GNUTLS_E_INTERNAL_ERROR;
}
- info->dh.secret_bits = _gnutls_read_uint16 (&packed_session->data[pos]);
- pos += 2;
+ BUFFER_POP_NUM(ps, info->dh.secret_bits);
- size = _gnutls_read_uint32 (&packed_session->data[pos]);
- pos += 4;
- ret = _gnutls_set_datum (&info->dh.prime, &packed_session->data[pos], size);
- if (ret < 0)
- {
- gnutls_assert ();
- goto error;
- }
- pos += size;
+ BUFFER_POP_DATUM(ps, &info->dh.prime);
+ BUFFER_POP_DATUM(ps, &info->dh.generator);
+ BUFFER_POP_DATUM(ps, &info->dh.public_key);
- size = _gnutls_read_uint32 (&packed_session->data[pos]);
- pos += 4;
- ret =
- _gnutls_set_datum (&info->dh.generator, &packed_session->data[pos], size);
- if (ret < 0)
- {
- gnutls_assert ();
- goto error;
- }
- pos += size;
+ return 0;
- size = _gnutls_read_uint32 (&packed_session->data[pos]);
- pos += 4;
- ret =
- _gnutls_set_datum (&info->dh.public_key, &packed_session->data[pos],
- size);
- if (ret < 0)
+error:
+ if (info)
{
- gnutls_assert ();
- goto error;
+ _gnutls_free_datum (&info->dh.prime);
+ _gnutls_free_datum (&info->dh.generator);
+ _gnutls_free_datum (&info->dh.public_key);
}
- pos += size;
-
- return 0;
-error:
- _gnutls_free_datum (&info->dh.prime);
- _gnutls_free_datum (&info->dh.generator);
- _gnutls_free_datum (&info->dh.public_key);
return ret;
}
#endif /* ANON */
* x bytes the public key
*/
static int
-pack_psk_auth_info (gnutls_session_t session, gnutls_datum_t * packed_session)
+pack_psk_auth_info (gnutls_session_t session, gnutls_buffer_st * ps)
{
psk_auth_info_t info;
- int pack_size, username_size = 0, hint_size = 0, pos;
+ int username_len;
+ int hint_len, ret;
+ void* size_pos;
+ size_t cur_size;
info = _gnutls_get_auth_info (session);
- if (info)
- {
- username_size = strlen (info->username) + 1; /* include the terminating null */
- hint_size = strlen (info->hint) + 1; /* include the terminating null */
-
- pack_size = 1 + 4 + 4 + username_size + 4 + hint_size +
- +2 + 4 + info->dh.prime.size + 4 + info->dh.generator.size +
- 4 + info->dh.public_key.size;
- }
+ if (info && info->username)
+ username_len = strlen (info->username) + 1; /* include the terminating null */
else
- pack_size = 0;
+ username_len = 0;
- packed_session->size = PACK_HEADER_SIZE + pack_size + sizeof (uint32_t);
-
- /* calculate the size and allocate the data.
- */
- packed_session->data =
- gnutls_malloc (packed_session->size + MAX_SEC_PARAMS + 2 +
- session->security_parameters.extensions.
- session_ticket_len);
-
- if (packed_session->data == NULL)
- {
- gnutls_assert ();
- return GNUTLS_E_MEMORY_ERROR;
- }
-
- pos = 0;
-
- packed_session->data[pos] = GNUTLS_CRD_PSK;
- pos++;
-
- _gnutls_write_uint32 (pack_size, &packed_session->data[pos]);
- pos += 4;
-
- if (pack_size > 0)
- {
- _gnutls_write_uint32 (username_size, &packed_session->data[pos]);
- pos += 4;
-
- memcpy (&packed_session->data[pos], info->username, username_size);
- pos += username_size;
+ if (info && info->hint)
+ hint_len = strlen (info->hint) + 1; /* include the terminating null */
+ else
+ hint_len = 0;
- _gnutls_write_uint32 (hint_size, &packed_session->data[pos]);
- pos += 4;
+ size_pos = ps->data + ps->length;
- memcpy (&packed_session->data[pos], info->hint, hint_size);
- pos += hint_size;
+ BUFFER_APPEND_NUM(ps, 0);
+ cur_size = ps->length;
- _gnutls_write_uint16 (info->dh.secret_bits, &packed_session->data[pos]);
- pos += 2;
+ BUFFER_APPEND_PFX(ps, info->username, username_len);
+ BUFFER_APPEND_PFX(ps, info->hint, hint_len);
- _gnutls_write_datum32 (&packed_session->data[pos], info->dh.prime);
- pos += 4 + info->dh.prime.size;
- _gnutls_write_datum32 (&packed_session->data[pos], info->dh.generator);
- pos += 4 + info->dh.generator.size;
- _gnutls_write_datum32 (&packed_session->data[pos], info->dh.public_key);
- pos += 4 + info->dh.public_key.size;
- }
+ BUFFER_APPEND_NUM( ps, info->dh.secret_bits);
+ BUFFER_APPEND_PFX( ps, info->dh.prime.data, info->dh.prime.size);
+ BUFFER_APPEND_PFX( ps, info->dh.generator.data, info->dh.generator.size);
+ BUFFER_APPEND_PFX( ps, info->dh.public_key.data, info->dh.public_key.size);
+ /* write the real size */
+ _gnutls_write_uint32(ps->length-cur_size, size_pos);
return 0;
}
static int
unpack_psk_auth_info (gnutls_session_t session,
- const gnutls_datum_t * packed_session)
+ gnutls_buffer_st * ps)
{
size_t username_size, hint_size;
- size_t pack_size;
- int pos = 0, size, ret;
+ int ret;
psk_auth_info_t info;
- if (packed_session->data[0] != GNUTLS_CRD_PSK)
- {
- gnutls_assert ();
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- pack_size = _gnutls_read_uint32 (&packed_session->data[PACK_HEADER_SIZE]);
- pos += PACK_HEADER_SIZE + 4;
-
-
- if (pack_size == 0)
- return 0; /* nothing to be done */
-
- /* a simple check for integrity */
- if (pack_size + PACK_HEADER_SIZE + 4 > packed_session->size)
- {
- gnutls_assert ();
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- /* client and serer have the same auth_info here
- */
ret =
_gnutls_auth_info_set (session, GNUTLS_CRD_PSK,
sizeof (psk_auth_info_st), 1);
return GNUTLS_E_INTERNAL_ERROR;
}
- username_size = _gnutls_read_uint32 (&packed_session->data[pos]);
- pos += 4;
-
- memcpy (info->username, &packed_session->data[pos], username_size);
- pos += username_size;
-
- hint_size = _gnutls_read_uint32 (&packed_session->data[pos]);
- pos += 4;
-
- memcpy (info->hint, &packed_session->data[pos], hint_size);
- pos += hint_size;
-
- info->dh.secret_bits = _gnutls_read_uint16 (&packed_session->data[pos]);
- pos += 2;
-
- size = _gnutls_read_uint32 (&packed_session->data[pos]);
- pos += 4;
- ret = _gnutls_set_datum (&info->dh.prime, &packed_session->data[pos], size);
- if (ret < 0)
+ BUFFER_POP_NUM(ps, username_size);
+ if (username_size > sizeof(info->username))
{
- gnutls_assert ();
- goto error;
+ gnutls_assert();
+ return GNUTLS_E_INTERNAL_ERROR;
}
- pos += size;
- size = _gnutls_read_uint32 (&packed_session->data[pos]);
- pos += 4;
- ret =
- _gnutls_set_datum (&info->dh.generator, &packed_session->data[pos], size);
- if (ret < 0)
- {
- gnutls_assert ();
- goto error;
- }
- pos += size;
+ BUFFER_POP(ps, info->username, username_size);
- size = _gnutls_read_uint32 (&packed_session->data[pos]);
- pos += 4;
- ret =
- _gnutls_set_datum (&info->dh.public_key, &packed_session->data[pos],
- size);
- if (ret < 0)
+ BUFFER_POP_NUM(ps, hint_size);
+ if (hint_size > sizeof(info->hint))
{
- gnutls_assert ();
- goto error;
+ gnutls_assert();
+ return GNUTLS_E_INTERNAL_ERROR;
}
- pos += size;
+ BUFFER_POP(ps, info->hint, hint_size);
- return 0;
+ BUFFER_POP_NUM(ps, info->dh.secret_bits);
+
+ BUFFER_POP_DATUM(ps, &info->dh.prime);
+ BUFFER_POP_DATUM(ps, &info->dh.generator);
+ BUFFER_POP_DATUM(ps, &info->dh.public_key);
+ ret = 0;
+
error:
_gnutls_free_datum (&info->dh.prime);
_gnutls_free_datum (&info->dh.generator);
_gnutls_free_datum (&info->dh.public_key);
+
return ret;
}
#endif
* -------------------
* MAX: 165 bytes
*
- * EXTENSIONS:
- * 2 bytes the record send size
- * 2 bytes the record recv size
- *
- * 1 byte the SRP username size
- * x bytes the SRP username (MAX_SRP_USERNAME)
- *
- * 2 bytes the number of server name extensions (up to MAX_SERVER_NAME_EXTENSIONS)
- * 1 byte the first name type
- * 2 bytes the size of the first name
- * x bytes the first name (MAX_SERVER_NAME_SIZE)
- * and so on...
- * 2 bytes the session ticket size
- * x bytes the session ticket (MAX_SESSION_TICKET_SIZE)
- *
- * --------------------
- * MAX: 7+MAX_SRP_USERNAME+MAX_SERVER_NAME_EXTENSIONS*(3+MAX_SERVER_NAME_SIZE)+MAX_SESSION_TICKET_SIZE
*/
static int
pack_security_parameters (gnutls_session_t session,
- gnutls_datum_t * packed_session)
+ gnutls_buffer_st * ps)
{
- int pos = 0;
- size_t len, init, i;
+
+ int ret;
+ void* size_pos;
+ size_t cur_size;
/* move after the auth info stuff.
*/
- init =
- _gnutls_read_uint32 (&packed_session->data[PACK_HEADER_SIZE]) + 4 +
- PACK_HEADER_SIZE;
-
- pos = init + 4; /* make some space to write later the size */
-
- packed_session->data[pos++] = session->security_parameters.entity;
- packed_session->data[pos++] = session->security_parameters.kx_algorithm;
- packed_session->data[pos++] =
- session->security_parameters.read_bulk_cipher_algorithm;
- packed_session->data[pos++] =
- session->security_parameters.read_mac_algorithm;
- packed_session->data[pos++] =
- session->security_parameters.read_compression_algorithm;
- packed_session->data[pos++] =
- session->security_parameters.write_bulk_cipher_algorithm;
- packed_session->data[pos++] =
- session->security_parameters.write_mac_algorithm;
- packed_session->data[pos++] =
- session->security_parameters.write_compression_algorithm;
- packed_session->data[pos++] =
- session->security_parameters.current_cipher_suite.suite[0];
- packed_session->data[pos++] =
- session->security_parameters.current_cipher_suite.suite[1];
-
- packed_session->data[pos++] = session->security_parameters.cert_type;
- packed_session->data[pos++] = session->security_parameters.version;
-
- memcpy (&packed_session->data[pos],
- session->security_parameters.master_secret, GNUTLS_MASTER_SIZE);
- pos += GNUTLS_MASTER_SIZE;
-
- memcpy (&packed_session->data[pos],
- session->security_parameters.client_random, GNUTLS_RANDOM_SIZE);
- pos += GNUTLS_RANDOM_SIZE;
- memcpy (&packed_session->data[pos],
- session->security_parameters.server_random, GNUTLS_RANDOM_SIZE);
- pos += GNUTLS_RANDOM_SIZE;
-
- packed_session->data[pos++] = session->security_parameters.session_id_size;
- memcpy (&packed_session->data[pos], session->security_parameters.session_id,
- session->security_parameters.session_id_size);
- pos += session->security_parameters.session_id_size;
-
- _gnutls_write_uint32 (session->security_parameters.timestamp,
- &packed_session->data[pos]);
- pos += 4;
-
- /* Extensions */
- _gnutls_write_uint16 (session->security_parameters.max_record_send_size,
- &packed_session->data[pos]);
- pos += 2;
-
- _gnutls_write_uint16 (session->security_parameters.max_record_recv_size,
- &packed_session->data[pos]);
- pos += 2;
-
- /* SRP */
- len =
- strlen ((char *) session->security_parameters.extensions.srp_username);
- packed_session->data[pos++] = len;
- memcpy (&packed_session->data[pos],
- session->security_parameters.extensions.srp_username, len);
- pos += len;
-
- _gnutls_write_uint16 (session->security_parameters.
- extensions.server_names_size,
- &packed_session->data[pos]);
- pos += 2;
-
- for (i = 0; i < session->security_parameters.extensions.server_names_size;
- i++)
- {
- packed_session->data[pos++] =
- session->security_parameters.extensions.server_names[i].type;
- _gnutls_write_uint16 (session->security_parameters.
- extensions.server_names[i].name_length,
- &packed_session->data[pos]);
- pos += 2;
-
- memcpy (&packed_session->data[pos],
- session->security_parameters.extensions.server_names[i].name,
- session->security_parameters.extensions.
- server_names[i].name_length);
- pos +=
- session->security_parameters.extensions.server_names[i].name_length;
- }
+ size_pos = ps->data + ps->length;
+
+ BUFFER_APPEND_NUM(ps, 0);
+ cur_size = ps->length;
+
- _gnutls_write_uint16 (session->security_parameters.
- extensions.session_ticket_len,
- &packed_session->data[pos]);
- pos += 2;
- memcpy (&packed_session->data[pos],
- session->security_parameters.extensions.session_ticket,
- session->security_parameters.extensions.session_ticket_len);
- pos += session->security_parameters.extensions.session_ticket_len;
+ BUFFER_APPEND(ps, &session->security_parameters.entity, 1);
+ BUFFER_APPEND(ps, &session->security_parameters.kx_algorithm, 1);
+ BUFFER_APPEND(ps, &session->security_parameters.read_bulk_cipher_algorithm, 1);
+ BUFFER_APPEND(ps, &session->security_parameters.read_mac_algorithm, 1);
+ BUFFER_APPEND(ps, &session->security_parameters.read_compression_algorithm, 1);
+ BUFFER_APPEND(ps, &session->security_parameters.write_bulk_cipher_algorithm, 1);
+ BUFFER_APPEND(ps, &session->security_parameters.write_mac_algorithm, 1);
+ BUFFER_APPEND(ps, &session->security_parameters.write_compression_algorithm, 1);
+ BUFFER_APPEND(ps, &session->security_parameters.current_cipher_suite.suite[0], 1);
+ BUFFER_APPEND(ps, &session->security_parameters.current_cipher_suite.suite[1], 1);
+ BUFFER_APPEND(ps, &session->security_parameters.cert_type, 1);
+ BUFFER_APPEND(ps, &session->security_parameters.version, 1);
- /* write the total size */
- _gnutls_write_uint32 (pos - init - 4, &packed_session->data[init]);
- packed_session->size += pos - init;
+ BUFFER_APPEND(ps, session->security_parameters.master_secret, GNUTLS_MASTER_SIZE);
+ BUFFER_APPEND(ps, session->security_parameters.client_random, GNUTLS_RANDOM_SIZE);
+ BUFFER_APPEND(ps, session->security_parameters.server_random, GNUTLS_RANDOM_SIZE);
+ BUFFER_APPEND_NUM(ps, session->security_parameters.session_id_size);
+ BUFFER_APPEND_NUM(ps, session->security_parameters.max_record_send_size);
+ BUFFER_APPEND_NUM(ps, session->security_parameters.max_record_recv_size);
+ BUFFER_APPEND(ps, session->security_parameters.session_id, session->security_parameters.session_id_size);
+
+ BUFFER_APPEND_NUM(ps, session->security_parameters.timestamp);
+
+ _gnutls_write_uint32(ps->length-cur_size, size_pos);
return 0;
}
-
static int
unpack_security_parameters (gnutls_session_t session,
- const gnutls_datum_t * packed_session)
+ gnutls_buffer_st * ps)
{
- size_t pack_size, init, i;
- int pos = 0, len;
+ size_t pack_size;
+ int ret;
time_t timestamp = time (0);
-
- /* skip the auth info stuff */
- init =
- _gnutls_read_uint32 (&packed_session->data[PACK_HEADER_SIZE]) + 4 +
- PACK_HEADER_SIZE;
-
- pos = init;
-
- pack_size = _gnutls_read_uint32 (&packed_session->data[pos]);
- pos += 4;
-
+ BUFFER_POP_NUM(ps, pack_size);
if (pack_size == 0)
return GNUTLS_E_INVALID_REQUEST;
- /* a simple check for integrity */
- if (pack_size > MAX_SEC_PARAMS + 2 + MAX_SESSION_TICKET_SIZE)
- {
- gnutls_assert ();
- return GNUTLS_E_INVALID_REQUEST;
- }
-
memset (&session->internals.resumed_security_parameters, 0,
sizeof (session->internals.resumed_security_parameters));
- session->internals.resumed_security_parameters.entity =
- packed_session->data[pos++];
- session->internals.resumed_security_parameters.kx_algorithm =
- packed_session->data[pos++];
- session->internals.resumed_security_parameters.read_bulk_cipher_algorithm =
- packed_session->data[pos++];
- session->internals.resumed_security_parameters.read_mac_algorithm =
- packed_session->data[pos++];
- session->internals.resumed_security_parameters.read_compression_algorithm =
- packed_session->data[pos++];
- session->internals.resumed_security_parameters.write_bulk_cipher_algorithm =
- packed_session->data[pos++];
- session->internals.resumed_security_parameters.write_mac_algorithm =
- packed_session->data[pos++];
- session->internals.resumed_security_parameters.write_compression_algorithm =
- packed_session->data[pos++];
- session->internals.resumed_security_parameters.
- current_cipher_suite.suite[0] = packed_session->data[pos++];
- session->internals.resumed_security_parameters.
- current_cipher_suite.suite[1] = packed_session->data[pos++];
-
- session->internals.resumed_security_parameters.cert_type =
- packed_session->data[pos++];
- session->internals.resumed_security_parameters.version =
- packed_session->data[pos++];
-
- memcpy (session->internals.resumed_security_parameters.master_secret,
- &packed_session->data[pos], GNUTLS_MASTER_SIZE);
- pos += GNUTLS_MASTER_SIZE;
-
- memcpy (session->internals.resumed_security_parameters.client_random,
- &packed_session->data[pos], GNUTLS_RANDOM_SIZE);
- pos += GNUTLS_RANDOM_SIZE;
- memcpy (session->internals.resumed_security_parameters.server_random,
- &packed_session->data[pos], GNUTLS_RANDOM_SIZE);
- pos += GNUTLS_RANDOM_SIZE;
-
- session->internals.resumed_security_parameters.session_id_size =
- packed_session->data[pos++];
- memcpy (session->internals.resumed_security_parameters.session_id,
- &packed_session->data[pos],
+
+ BUFFER_POP(ps, &session->internals.resumed_security_parameters.entity, 1);
+ BUFFER_POP(ps, &session->internals.resumed_security_parameters.kx_algorithm, 1);
+ BUFFER_POP(ps, &session->internals.resumed_security_parameters.read_bulk_cipher_algorithm, 1);
+ BUFFER_POP(ps, &session->internals.resumed_security_parameters.read_mac_algorithm, 1);
+ BUFFER_POP(ps, &session->internals.resumed_security_parameters.read_compression_algorithm, 1);
+ BUFFER_POP(ps, &session->internals.resumed_security_parameters.write_bulk_cipher_algorithm, 1);
+ BUFFER_POP(ps, &session->internals.resumed_security_parameters.write_mac_algorithm, 1);
+ BUFFER_POP(ps, &session->internals.resumed_security_parameters.write_compression_algorithm, 1);
+ BUFFER_POP(ps, &session->internals.resumed_security_parameters.current_cipher_suite.suite[0], 1);
+ BUFFER_POP(ps, &session->internals.resumed_security_parameters.
+ current_cipher_suite.suite[1], 1);
+ BUFFER_POP(ps, &session->internals.resumed_security_parameters.cert_type, 1);
+ BUFFER_POP(ps, &session->internals.resumed_security_parameters.version, 1);
+
+ BUFFER_POP(ps, &session->internals.resumed_security_parameters.master_secret,
+ GNUTLS_MASTER_SIZE);
+
+ BUFFER_POP(ps, &session->internals.resumed_security_parameters.client_random,
+ GNUTLS_RANDOM_SIZE);
+ BUFFER_POP(ps, &session->internals.resumed_security_parameters.server_random,
+ GNUTLS_RANDOM_SIZE);
+ BUFFER_POP_NUM(ps, session->internals.resumed_security_parameters.session_id_size);
+
+ BUFFER_POP(ps, &session->internals.resumed_security_parameters.session_id,
session->internals.resumed_security_parameters.session_id_size);
- pos += session->internals.resumed_security_parameters.session_id_size;
- session->internals.resumed_security_parameters.timestamp =
- _gnutls_read_uint32 (&packed_session->data[pos]);
- pos += 4;
+ BUFFER_POP_NUM(ps, session->internals.resumed_security_parameters.timestamp);
+ BUFFER_POP_NUM(ps, session->internals.resumed_security_parameters.max_record_send_size);
+ BUFFER_POP_NUM(ps, session->internals.resumed_security_parameters.max_record_recv_size);
if (timestamp - session->internals.resumed_security_parameters.timestamp >
session->internals.expire_time
return GNUTLS_E_EXPIRED;
}
- /* Extensions */
- session->internals.resumed_security_parameters.max_record_send_size =
- _gnutls_read_uint16 (&packed_session->data[pos]);
- pos += 2;
-
- session->internals.resumed_security_parameters.max_record_recv_size =
- _gnutls_read_uint16 (&packed_session->data[pos]);
- pos += 2;
-
-
- /* SRP */
- len = packed_session->data[pos++]; /* srp username length */
- memcpy (session->internals.resumed_security_parameters.
- extensions.srp_username, &packed_session->data[pos], len);
- session->internals.resumed_security_parameters.
- extensions.srp_username[len] = 0;
- pos += len;
-
- session->internals.resumed_security_parameters.
- extensions.server_names_size =
- _gnutls_read_uint16 (&packed_session->data[pos]);
- pos += 2;
- for (i = 0;
- i <
- session->internals.resumed_security_parameters.
- extensions.server_names_size; i++)
- {
- session->internals.resumed_security_parameters.
- extensions.server_names[i].type = packed_session->data[pos++];
- session->internals.resumed_security_parameters.
- extensions.server_names[i].name_length =
- _gnutls_read_uint16 (&packed_session->data[pos]);
- pos += 2;
-
- memcpy (session->internals.resumed_security_parameters.
- extensions.server_names[i].name, &packed_session->data[pos],
- session->internals.resumed_security_parameters.
- extensions.server_names[i].name_length);
- pos +=
- session->internals.resumed_security_parameters.
- extensions.server_names[i].name_length;
- }
-
- session->internals.resumed_security_parameters.
- extensions.session_ticket_len =
- _gnutls_read_uint16 (&packed_session->data[pos]);
- pos += 2;
- session->internals.resumed_security_parameters.extensions.session_ticket =
- gnutls_malloc (session->internals.resumed_security_parameters.
- extensions.session_ticket_len);
- memcpy (session->internals.resumed_security_parameters.
- extensions.session_ticket, &packed_session->data[pos],
- session->internals.resumed_security_parameters.
- extensions.session_ticket_len);
+ ret = 0;
- return 0;
+error:
+ return ret;
}
#include <auth_psk.h>
#include <gnutls_algorithms.h>
#include <gnutls_rsa_export.h>
+#include <gnutls_extensions.h>
/* These should really be static, but src/tests.c calls them. Make
them public functions? */
session->internals.extensions_sent_size = 0;
/* by default no selected certificate */
- session->internals.proposed_record_size = DEFAULT_MAX_RECORD_SIZE;
session->internals.adv_version_major = 0;
session->internals.adv_version_minor = 0;
session->internals.v2_hello = 0;
session->internals.adv_version_minor = 0;
session->internals.adv_version_minor = 0;
session->internals.direction = 0;
- session->internals.safe_renegotiation_received = 0;
/* use out of band data for the last
* handshake messages received.
_gnutls_handshake_internal_state_clear (session);
_gnutls_handshake_io_buffer_clear (session);
+ _gnutls_ext_free_session_data (session);
_gnutls_free_datum (&session->connection_state.read_mac_secret);
_gnutls_free_datum (&session->connection_state.write_mac_secret);
session->key = NULL;
}
- gnutls_free (session->internals.srp_username);
-
- if (session->internals.srp_password)
- {
- memset (session->internals.srp_password, 0,
- strlen (session->internals.srp_password));
- gnutls_free (session->internals.srp_password);
- }
-
- gnutls_free (session->security_parameters.extensions.session_ticket);
- gnutls_free (session->internals.resumed_security_parameters.
- extensions.session_ticket);
-
memset (session, 0, sizeof (struct gnutls_session_int));
gnutls_free (session);
}
str->length = 0;
}
-#define MIN_CHUNK 256
+#define MIN_CHUNK 1024
int
_gnutls_buffer_append_data (gnutls_buffer_st * dest, const void *data,
* data are appended in the buffer.
*/
void
-_gnutls_buffer_get_datum (gnutls_buffer_st * str, gnutls_datum_t * data,
+_gnutls_buffer_pop_datum (gnutls_buffer_st * str, gnutls_datum_t * data,
size_t req_size)
{
return;
}
+/* converts the buffer to a datum if possible. After this call the buffer
+ * is at an usable state and might not be used or deinitialized */
+int
+_gnutls_buffer_to_datum (gnutls_buffer_st * str, gnutls_datum_t * data)
+{
+
+ if (str->length == 0)
+ {
+ data->data = NULL;
+ data->size = 0;
+ return 0;
+ }
+
+ if (str->allocd != str->data)
+ {
+ data->data = gnutls_malloc(str->length);
+ if (data->data == NULL)
+ {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+ memcpy(data->data, str->data, str->length);
+ data->size = str->length;
+ _gnutls_buffer_clear(str);
+ }
+ else
+ {
+ data->data = str->data;
+ data->size = str->length;
+ }
+
+ return 0;
+}
+
/* returns data from a string in a constant buffer.
*/
void
-_gnutls_buffer_get_data (gnutls_buffer_st * str, void *data, size_t * req_size)
+_gnutls_buffer_pop_data (gnutls_buffer_st * str, void *data, size_t * req_size)
{
gnutls_datum_t tdata;
- _gnutls_buffer_get_datum (str, &tdata, *req_size);
+ _gnutls_buffer_pop_datum (str, &tdata, *req_size);
*req_size = tdata.size;
memcpy (data, tdata.data, tdata.size);
return 0;
}
+
+int _gnutls_buffer_append_prefix (gnutls_buffer_st * buf, size_t data_size)
+{
+ opaque ss[4];
+ _gnutls_write_uint32(data_size, ss);
+ return _gnutls_buffer_append_data(buf, ss, 4);
+}
+
+/* Reads an uint32 number from the buffer. If check is non zero it will also check whether
+ * the number read, is less than the data in the buffer
+ */
+int _gnutls_buffer_pop_prefix (gnutls_buffer_st * buf, size_t *data_size, int check)
+{
+ size_t size;
+
+ if (buf->length < 4) {
+ gnutls_assert();
+ return GNUTLS_E_PARSING_ERROR;
+ }
+
+ size = _gnutls_read_uint32(buf->data);
+ if (check && size > buf->length-4) {
+ gnutls_assert();
+ return GNUTLS_E_PARSING_ERROR;
+ }
+
+ buf->data+=4;
+ buf->length-=4;
+
+ *data_size = size;
+
+ return 0;
+}
+
+int _gnutls_buffer_pop_datum_prefix (gnutls_buffer_st * buf, gnutls_datum_t* data)
+{
+ size_t size;
+ int ret;
+
+ ret = _gnutls_buffer_pop_prefix(buf, &size, 1);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ if (size > 0) {
+ size_t osize = size;
+ _gnutls_buffer_pop_datum(buf, data, size);
+ if (osize != data->size) {
+ gnutls_assert();
+ return GNUTLS_E_PARSING_ERROR;
+ }
+ } else {
+ data->size = 0;
+ data->data = NULL;
+ }
+
+ return 0;
+}
+
+int _gnutls_buffer_append_data_prefix (gnutls_buffer_st * buf, const void *data,
+ size_t data_size)
+{
+ _gnutls_buffer_append_prefix(buf, data_size);
+ if (data_size > 0)
+ return _gnutls_buffer_append_data(buf, data, data_size);
+
+ return 0;
+}
+
+int _gnutls_buffer_pop_data_prefix (gnutls_buffer_st * buf, void * data, size_t * data_size)
+{
+ size_t size;
+ int ret;
+
+ ret = _gnutls_buffer_pop_prefix(buf, &size, 1);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ if (size > 0)
+ _gnutls_buffer_pop_data(buf, data, data_size);
+
+ return 0;
+}
+
# define GNUTLS_STR_H
#include <gnutls_int.h>
+#include <gnutls_datum.h>
void _gnutls_str_cpy (char *dest, size_t dest_tot_size, const char *src);
void _gnutls_mem_cpy (char *dest, size_t dest_tot_size, const char *src,
int _gnutls_buffer_append_data (gnutls_buffer_st *, const void *data,
size_t data_size);
-void _gnutls_buffer_get_data (gnutls_buffer_st *, void *, size_t * size);
-void _gnutls_buffer_get_datum (gnutls_buffer_st *, gnutls_datum_t *,
+#include <gnutls_num.h>
+
+int _gnutls_buffer_append_prefix (gnutls_buffer_st * buf, size_t data_size);
+
+int _gnutls_buffer_append_data_prefix (gnutls_buffer_st * buf,
+ const void *data, size_t data_size);
+void _gnutls_buffer_pop_data (gnutls_buffer_st *, void *, size_t * size);
+void _gnutls_buffer_pop_datum (gnutls_buffer_st *, gnutls_datum_t *,
size_t max_size);
+int _gnutls_buffer_pop_prefix (gnutls_buffer_st * buf, size_t *data_size, int check);
+
+int _gnutls_buffer_pop_data_prefix (gnutls_buffer_st * buf, void * data, size_t * data_size);
+
+int _gnutls_buffer_pop_datum_prefix (gnutls_buffer_st * buf, gnutls_datum_t* data);
+int _gnutls_buffer_to_datum (gnutls_buffer_st * str, gnutls_datum_t * data);
+
int _gnutls_buffer_escape(gnutls_buffer_st * dest, const char *const invalid_chars);
int _gnutls_buffer_unescape(gnutls_buffer_st * dest);
const char *hostname);
#define MAX_CN 256
+#define BUFFER_APPEND(b, x, s) { \
+ ret = _gnutls_buffer_append_data(b, x, s); \
+ if (ret < 0) { \
+ gnutls_assert(); \
+ return ret; \
+ } \
+ }
+
+#define BUFFER_APPEND_PFX(b, x, s) { \
+ ret = _gnutls_buffer_append_data_prefix(b, x, s); \
+ if (ret < 0) { \
+ gnutls_assert(); \
+ return ret; \
+ } \
+ }
+
+#define BUFFER_APPEND_NUM(b, s) { \
+ ret = _gnutls_buffer_append_prefix(b, s); \
+ if (ret < 0) { \
+ gnutls_assert(); \
+ return ret; \
+ } \
+ }
+
+
+#define BUFFER_POP(b, x, s) { \
+ size_t is = s; \
+ _gnutls_buffer_pop_data(b, x, &is); \
+ if (is != s) { \
+ ret = GNUTLS_E_PARSING_ERROR; \
+ gnutls_assert(); \
+ goto error; \
+ } \
+ }
+
+#define BUFFER_POP_DATUM(b, o) { \
+ gnutls_datum_t d; \
+ ret = _gnutls_buffer_pop_datum_prefix(b, &d); \
+ if (ret >= 0) \
+ ret = _gnutls_set_datum (o, d.data, d.size); \
+ if (ret < 0) { \
+ gnutls_assert(); \
+ goto error; \
+ } \
+ }
+
+#define BUFFER_POP_NUM(b, o) { \
+ size_t s; \
+ ret = _gnutls_buffer_pop_prefix(b, &s, 0); \
+ if (ret < 0) { \
+ gnutls_assert(); \
+ goto error; \
+ } \
+ o = s; \
+ }
+
#endif
gnutls_sign_func
gnutls_sign_callback_get (gnutls_session_t session, void **userdata);
+ int gnutls_ext_register (int type,
+ const char *name,
+ gnutls_ext_parse_type_t parse_type,
+ gnutls_ext_recv_func recv_func,
+ gnutls_ext_send_func send_func) _GNUTLS_GCC_ATTR_DEPRECATED;
+
#endif /* _GNUTLS_COMPAT_H */
GNUTLS_EXT_NONE = 4,
} gnutls_ext_parse_type_t;
- int gnutls_ext_register (int type,
- const char *name,
- gnutls_ext_parse_type_t parse_type,
- gnutls_ext_recv_func recv_func,
- gnutls_ext_send_func send_func);
/**
* gnutls_server_name_type_t:
_gnutls_hash_init;
_gnutls_hash_deinit;
_gnutls_hash;
+ _gnutls_ext_get_session_data;
+ _gnutls_ext_set_session_data;
+ _gnutls_ext_register;
+ _gnutls_buffer_append_prefix;
+ _gnutls_buffer_append_data_prefix;
+ _gnutls_buffer_pop_data;
+ _gnutls_buffer_pop_prefix;
# Internal symbols needed by psktool:
return ret;
}
- _gnutls_buffer_get_data(&str, output, size);
+ _gnutls_buffer_pop_data(&str, output, size);
_gnutls_buffer_clear(&str);
if (buf)
{
- _gnutls_buffer_get_data (&out_str, buf, sizeof_buf);
+ _gnutls_buffer_pop_data (&out_str, buf, sizeof_buf);
buf[*sizeof_buf] = 0;
}
else
#define NO 0
#define YES 1
-int
+static int _gnutls_inner_application_recv_params (gnutls_session_t session,
+ const opaque * data,
+ size_t data_size);
+static int _gnutls_inner_application_send_params (gnutls_session_t session,
+ opaque * data, size_t);
+static int ia_unpack(gnutls_buffer_st* ps, extension_priv_data_t* _priv);
+static int ia_pack(extension_priv_data_t _priv, gnutls_buffer_st* ps);
+static void ia_deinit_data(extension_priv_data_t priv);
+
+extension_entry_st ext_mod_ia = {
+ .name = "INNER APPLICATION",
+ .type = GNUTLS_EXTENSION_INNER_APPLICATION,
+ .parse_type = GNUTLS_EXT_TLS,
+
+ .recv_func = _gnutls_inner_application_recv_params,
+ .send_func = _gnutls_inner_application_send_params,
+ .pack_func = ia_pack,
+ .unpack_func = ia_unpack,
+ .deinit_func = ia_deinit_data,
+};
+
+static int
_gnutls_inner_application_recv_params (gnutls_session_t session,
const opaque * data, size_t data_size)
{
- tls_ext_st *ext = &session->security_parameters.extensions;
+ extension_priv_data_t epriv;
+ ia_ext_st *priv;
+ int ret;
if (data_size != 1)
{
return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
}
- ext->gnutls_ia_peer_enable = 1;
- ext->gnutls_ia_peer_allowskip = 0;
+ ret = _gnutls_ext_get_session_data( session, GNUTLS_EXTENSION_INNER_APPLICATION, &epriv);
+ if (ret < 0)
+ {
+ priv = gnutls_calloc(1, sizeof(*priv));
+ if (priv == NULL)
+ {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ epriv.ptr = priv;
+ _gnutls_ext_set_session_data(session, GNUTLS_EXTENSION_INNER_APPLICATION, epriv);
+ }
+ else
+ priv = epriv.ptr;
+
+ priv->flags |= IA_PEER_ENABLE;
+ priv->flags &= ~IA_PEER_ALLOW_SKIP;
switch ((unsigned char) *data)
{
- case NO: /* Peer's ia_on_resume == no */
- ext->gnutls_ia_peer_allowskip = 1;
+ case NO: /* Peer's ia_on_resume == no */
+ priv->flags |= IA_PEER_ALLOW_SKIP;
break;
case YES:
gnutls_assert ();
}
+
return 0;
}
/* returns data_size or a negative number on failure
*/
-int
+static int
_gnutls_inner_application_send_params (gnutls_session_t session,
opaque * data, size_t data_size)
{
- tls_ext_st *ext = &session->security_parameters.extensions;
+ extension_priv_data_t epriv;
+ ia_ext_st * priv = NULL;
+ int ret;
+
+ ret = _gnutls_ext_get_session_data( session, GNUTLS_EXTENSION_INNER_APPLICATION, &epriv);
+ if (ret < 0)
+ {
+ priv = gnutls_calloc(1, sizeof(*priv));
+ if (priv == NULL)
+ {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ epriv.ptr = priv;
+ _gnutls_ext_set_session_data(session, GNUTLS_EXTENSION_INNER_APPLICATION, epriv);
+ }
+ else
+ priv = epriv.ptr;
/* Set ext->gnutls_ia_enable depending on whether we have a TLS/IA
credential in the session. */
if (session->security_parameters.entity == GNUTLS_CLIENT)
{
gnutls_ia_client_credentials_t cred = (gnutls_ia_client_credentials_t)
- _gnutls_get_cred (session->key, GNUTLS_CRD_IA, NULL);
+ _gnutls_get_cred (session->key, GNUTLS_CRD_IA, NULL);
if (cred)
- ext->gnutls_ia_enable = 1;
+ priv->flags |= IA_ENABLE;
}
- else
+ else /* SERVER */
{
- gnutls_ia_server_credentials_t cred = (gnutls_ia_server_credentials_t)
- _gnutls_get_cred (session->key, GNUTLS_CRD_IA, NULL);
+ gnutls_ia_server_credentials_t cred;
+
+ cred = (gnutls_ia_server_credentials_t)
+ _gnutls_get_cred (session->key, GNUTLS_CRD_IA, NULL);
if (cred)
- ext->gnutls_ia_enable = 1;
+ priv->flags |= IA_PEER_ENABLE;
}
/* If we don't want gnutls_ia locally, or we are a server and the
* client doesn't want it, don't advertise TLS/IA support at all, as
* required. */
- if (!ext->gnutls_ia_enable)
+ if (!(priv->flags & IA_ENABLE))
return 0;
if (session->security_parameters.entity == GNUTLS_SERVER &&
- !ext->gnutls_ia_peer_enable)
+ !(priv->flags & IA_PEER_ENABLE))
return 0;
/* We'll advertise. Check if there's room in the hello buffer. */
/* Client: value follows local setting */
- if (ext->gnutls_ia_allowskip)
- *data = NO;
+ if (priv->flags & IA_ALLOW_SKIP)
+ *data = NO;
}
else
{
* always skip IA on resumption, because recv_ext isn't even called
* to record the peer's support for IA at all. Simon? */
- if (ext->gnutls_ia_allowskip &&
- ext->gnutls_ia_peer_allowskip &&
- session->internals.resumed == RESUME_TRUE)
- *data = NO;
+ if ((priv->flags & IA_ALLOW_SKIP) &&
+ (priv->flags & IA_PEER_ALLOW_SKIP) &&
+ session->internals.resumed == RESUME_TRUE)
+ *data = NO;
}
return 1;
}
+
+static void ia_deinit_data(extension_priv_data_t priv)
+{
+ gnutls_free(priv.ptr);
+}
+
+static int ia_pack(extension_priv_data_t epriv, gnutls_buffer_st* ps)
+{
+ia_ext_st* priv = epriv.ptr;
+int ret;
+
+ BUFFER_APPEND_NUM(ps, priv->flags);
+ BUFFER_APPEND_PFX(ps, priv->inner_secret, GNUTLS_MASTER_SIZE);
+
+ return 0;
+}
+
+static int ia_unpack(gnutls_buffer_st* ps, extension_priv_data_t* _priv)
+{
+ia_ext_st* priv;
+int size, ret;
+extension_priv_data_t epriv;
+
+ priv = gnutls_calloc(1, sizeof(*priv));
+ if (priv == NULL)
+ {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ BUFFER_POP_NUM(ps, priv->flags);
+ BUFFER_POP_NUM(ps, size);
+ if (size != GNUTLS_MASTER_SIZE)
+ {
+ gnutls_assert();
+ return GNUTLS_E_PARSING_ERROR;
+ }
+ BUFFER_POP(ps, priv->inner_secret, GNUTLS_MASTER_SIZE);
+
+ epriv.ptr = priv;
+ *_priv = epriv;
+
+ return 0;
+
+error:
+ gnutls_free(priv);
+ return ret;
+}
+
*
*/
-int _gnutls_inner_application_recv_params (gnutls_session_t session,
- const opaque * data,
- size_t data_size);
-int _gnutls_inner_application_send_params (gnutls_session_t session,
- opaque * data, size_t);
+#ifndef EXT_IA_H
+#define EXT_IA_H
+
+#include <gnutls_extensions.h>
+
+#define IA_PEER_ENABLE (1 << 1)
+#define IA_PEER_ALLOW_SKIP (1 << 2)
+#define IA_ENABLE (1 << 3)
+#define IA_ALLOW_SKIP (1 << 4)
+
+extension_entry_st ext_mod_ia;
+
+typedef struct {
+ unsigned int flags;
+ /* For TLS/IA. XXX: Move to IA credential? */
+ opaque inner_secret[GNUTLS_MASTER_SIZE];
+} ia_ext_st;
+
+inline static void _gnutls_ia_derive_inner_secret(gnutls_session_t session)
+{
+extension_priv_data_t epriv;
+ia_ext_st *priv;
+int ret;
+
+ ret = _gnutls_ext_get_session_data( session, GNUTLS_EXTENSION_INNER_APPLICATION, &epriv);
+ if (ret < 0)
+ {
+ return ;
+ }
+ priv = epriv.ptr;
+
+ memcpy (priv->inner_secret,
+ session->security_parameters.master_secret, GNUTLS_MASTER_SIZE);
+
+}
+
+#endif
if (_gnutls_init_extra != 1)
return 0;
- ret = gnutls_ext_register (GNUTLS_EXTENSION_INNER_APPLICATION,
- "INNER_APPLICATION",
- GNUTLS_EXT_TLS,
- _gnutls_inner_application_recv_params,
- _gnutls_inner_application_send_params);
+ ret = _gnutls_ext_register (&ext_mod_ia);
if (ret != GNUTLS_E_SUCCESS)
return ret;
#include "gnutls_num.h"
#include "gnutls_state.h"
#include <gnutls/extra.h>
+#include <ext_inner_application.h>
#define CHECKSUM_SIZE 12
int ret;
opaque *seed;
size_t seedsize = 2 * GNUTLS_RANDOM_SIZE + extra_size;
+ extension_priv_data_t epriv;
+ ia_ext_st *priv;
+
+ ret = _gnutls_ext_get_session_data( session, GNUTLS_EXTENSION_INNER_APPLICATION, &epriv);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ return ret;
+ }
+ priv = epriv.ptr;
seed = gnutls_malloc (seedsize);
if (!seed)
session->security_parameters.client_random, GNUTLS_RANDOM_SIZE);
memcpy (seed + 2 * GNUTLS_RANDOM_SIZE, extra, extra_size);
- ret = _gnutls_PRF (session, session->security_parameters.inner_secret,
+ ret = _gnutls_PRF (session, priv->inner_secret,
GNUTLS_MASTER_SIZE,
label, label_size, seed, seedsize, outsize, out);
size_t session_keys_size,
const char *session_keys)
{
+ extension_priv_data_t epriv;
+ ia_ext_st *priv;
+ int ret;
+
+ ret = _gnutls_ext_get_session_data( session, GNUTLS_EXTENSION_INNER_APPLICATION, &epriv);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ return ret;
+ }
+ priv = epriv.ptr;
+
return _gnutls_ia_prf (session,
sizeof (inner_permutation_label) - 1,
inner_permutation_label,
session_keys_size,
session_keys,
GNUTLS_RANDOM_SIZE,
- session->security_parameters.inner_secret);
+ priv->inner_secret);
}
/**
void
gnutls_ia_extract_inner_secret (gnutls_session_t session, char *buffer)
{
- memcpy (buffer, session->security_parameters.inner_secret,
- GNUTLS_MASTER_SIZE);
+ extension_priv_data_t epriv;
+ ia_ext_st *priv;
+ int ret;
+
+ ret = _gnutls_ext_get_session_data( session, GNUTLS_EXTENSION_INNER_APPLICATION, &epriv);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ return;
+ }
+ priv = epriv.ptr;
+
+ memcpy (buffer, priv->inner_secret, GNUTLS_MASTER_SIZE);
}
/**
sizeof (server_finished_label);
ssize_t len;
int ret;
+ extension_priv_data_t epriv;
+ ia_ext_st *priv;
+
+ ret = _gnutls_ext_get_session_data( session, GNUTLS_EXTENSION_INNER_APPLICATION, &epriv);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ return ret;
+ }
+ priv = epriv.ptr;
- ret = _gnutls_PRF (session, session->security_parameters.inner_secret,
+ ret = _gnutls_PRF (session, priv->inner_secret,
GNUTLS_MASTER_SIZE, label, size_of_label - 1,
/* XXX specification unclear on seed. */
"", 0, CHECKSUM_SIZE, local_checksum);
int size_of_label = client ? sizeof (server_finished_label) :
sizeof (client_finished_label);
int ret;
+ extension_priv_data_t epriv;
+ ia_ext_st *priv;
- ret = _gnutls_PRF (session, session->security_parameters.inner_secret,
+ ret = _gnutls_ext_get_session_data( session, GNUTLS_EXTENSION_INNER_APPLICATION, &epriv);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ return ret;
+ }
+ priv = epriv.ptr;
+
+ ret = _gnutls_PRF (session, priv->inner_secret,
GNUTLS_MASTER_SIZE,
label, size_of_label - 1,
"", 0, CHECKSUM_SIZE, local_checksum);
int
gnutls_ia_handshake_p (gnutls_session_t session)
{
- tls_ext_st *ext = &session->security_parameters.extensions;
+ extension_priv_data_t epriv;
+ ia_ext_st * priv;
+ int ret;
+
+ ret = _gnutls_ext_get_session_data( session, GNUTLS_EXTENSION_SERVER_NAME, &epriv);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ return ret;
+ }
+ priv = epriv.ptr;
/* Either local side or peer doesn't do TLS/IA: don't do IA */
- if (!ext->gnutls_ia_enable || !ext->gnutls_ia_peer_enable)
+ if (!(priv->flags & IA_ENABLE) || !(priv->flags & IA_PEER_ENABLE))
return 0;
/* Not resuming or we don't allow skipping on resumption locally: do IA */
- if (!ext->gnutls_ia_allowskip || !gnutls_session_is_resumed (session))
+ if (!(priv->flags & IA_ALLOW_SKIP) || !gnutls_session_is_resumed (session))
return 1;
/* If we're resuming and we and the peer both allow skipping on resumption:
* don't do IA */
- return !ext->gnutls_ia_peer_allowskip;
+ return !(priv->flags & IA_PEER_ALLOW_SKIP);
}
* calling gnutls_ia_handshake() or one of the lower level gnutls_ia_*
* functions.
**/
-void
-gnutls_ia_enable (gnutls_session_t session, int allow_skip_on_resume)
+void gnutls_ia_enable (gnutls_session_t session, int allow_skip_on_resume)
{
- session->security_parameters.extensions.gnutls_ia_enable = 1;
- session->security_parameters.extensions.gnutls_ia_allowskip =
- allow_skip_on_resume;
+ extension_priv_data_t epriv;
+ ia_ext_st * priv;
+
+ priv = gnutls_calloc(1, sizeof(*priv));
+ if (priv == NULL)
+ {
+ gnutls_assert();
+ return;
+ }
+
+ epriv.ptr = priv;
+
+ priv->flags |= IA_ENABLE;
+ if (allow_skip_on_resume)
+ priv->flags |= IA_ALLOW_SKIP;
+
+ _gnutls_ext_set_session_data(session, GNUTLS_EXTENSION_INNER_APPLICATION, epriv);
+
}
}
}
-#ifdef ENABLE_OPRFI
- if (info.opaque_prf_input)
- gnutls_oprfi_enable_client (session, strlen (info.opaque_prf_input),
- info.opaque_prf_input);
-#endif
-
#ifdef ENABLE_SESSION_TICKET
- if (!info.noticket)
+ if (disable_extensions ==0 && !info.noticket)
gnutls_session_ticket_enable_client (session);
#endif
&session_data_size);
gnutls_session_get_id (hd.session, NULL, &session_id_size);
+
session_id = malloc (session_id_size);
gnutls_session_get_id (hd.session, session_id, &session_id_size);
static int mac_priority[PRI_MAX];
static int cert_type_priority[PRI_MAX];
-#if ENABLE_OPRFI
-int
-oprfi_callback (gnutls_session_t session,
- void *userdata,
- size_t oprfi_len,
- const unsigned char *in_oprfi, unsigned char *out_oprfi)
-{
- size_t ourlen = strlen (info.opaque_prf_input);
- size_t i;
-
- printf ("- Received Opaque PRF data of %d bytes\n", oprfi_len);
- printf (" data: ");
- for (i = 0; i < oprfi_len; i++)
- printf ("%02x", in_oprfi[i]);
- printf ("\n");
-
- memset (out_oprfi, 0, oprfi_len);
- strncpy (out_oprfi, info.opaque_prf_input, oprfi_len);
-
- return 0;
-}
-#endif
-
static gnutls_session_t
initialize_session (void)
{
gnutls_certificate_server_set_request (session, GNUTLS_CERT_REQUEST);
}
-#ifdef ENABLE_OPRFI
- if (info.opaque_prf_input)
- gnutls_oprfi_enable_server (session, oprfi_callback, NULL);
-#endif
-
return session;
}
tlsia_LDADD = ../libextra/libgnutls-extra.la $(LDADD) $(LTLIBREADLINE)
endif
-if ENABLE_OPRFI
-ctests += oprfi
-endif
-
check_PROGRAMS = $(ctests)
dist_check_SCRIPTS = rfc2253-escape-test
+++ /dev/null
-/*
- * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software
- * Foundation, Inc.
- *
- * Author: Simon Josefsson
- *
- * This file is part of GnuTLS.
- *
- * GnuTLS is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * GnuTLS 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
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GnuTLS; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-/* Parts copied from GnuTLS example programs. */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <sys/wait.h>
-#include <arpa/inet.h>
-#include <unistd.h>
-#include <gnutls/gnutls.h>
-
-#include "utils.h"
-
-static void
-tls_log_func (int level, const char *str)
-{
- fprintf (stderr, "|<%d>| %s", level, str);
-}
-
-/* A very basic TLS client, with anonymous authentication.
- */
-
-#define MAX_BUF 1024
-#define MSG "Hello TLS"
-
-/* Connects to the peer and returns a socket
- * descriptor.
- */
-int
-tcp_connect (void)
-{
- const char *PORT = "5556";
- const char *SERVER = "127.0.0.1";
- int err, sd;
- struct sockaddr_in sa;
-
- /* connects to server
- */
- sd = socket (AF_INET, SOCK_STREAM, 0);
-
- memset (&sa, '\0', sizeof (sa));
- sa.sin_family = AF_INET;
- sa.sin_port = htons (atoi (PORT));
- inet_pton (AF_INET, SERVER, &sa.sin_addr);
-
- err = connect (sd, (struct sockaddr *) &sa, sizeof (sa));
- if (err < 0)
- {
- fprintf (stderr, "Connect error\n");
- exit (1);
- }
-
- return sd;
-}
-
-/* closes the given socket descriptor.
- */
-void
-tcp_close (int sd)
-{
- shutdown (sd, SHUT_RDWR); /* no more receptions */
- close (sd);
-}
-
-void
-client (void)
-{
- int ret, sd, ii;
- gnutls_session_t session;
- char buffer[MAX_BUF + 1];
- gnutls_anon_client_credentials_t anoncred;
- /* Need to enable anonymous KX specifically. */
- const int kx_prio[] = { GNUTLS_KX_ANON_DH, 0 };
-
- gnutls_global_init ();
-
- gnutls_global_set_log_function (tls_log_func);
- if (debug)
- gnutls_global_set_log_level (4711);
-
- gnutls_anon_allocate_client_credentials (&anoncred);
-
- /* Initialize TLS session
- */
- gnutls_init (&session, GNUTLS_CLIENT);
-
- /* Use default priorities */
- gnutls_set_default_priority (session);
- gnutls_kx_set_priority (session, kx_prio);
-
- /* put the anonymous credentials to the current session
- */
- gnutls_credentials_set (session, GNUTLS_CRD_ANON, anoncred);
-
- gnutls_oprfi_enable_client (session, 3, "foo");
-
- /* connect to the peer
- */
- sd = tcp_connect ();
-
- gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) sd);
-
- /* Perform the TLS handshake
- */
- ret = gnutls_handshake (session);
-
- if (ret < 0)
- {
- fail ("client: Handshake failed\n");
- gnutls_perror (ret);
- goto end;
- }
- else
- {
- success ("client: Handshake was completed\n");
- }
-
- success ("client: TLS version is: %s\n",
- gnutls_protocol_get_name (gnutls_protocol_get_version (session)));
-
- gnutls_record_send (session, MSG, strlen (MSG));
-
- ret = gnutls_record_recv (session, buffer, MAX_BUF);
- if (ret == 0)
- {
- success ("client: Peer has closed the TLS connection\n");
- goto end;
- }
- else if (ret < 0)
- {
- fail ("client: Error: %s\n", gnutls_strerror (ret));
- goto end;
- }
-
- printf ("- Received %d bytes: ", ret);
- for (ii = 0; ii < ret; ii++)
- {
- fputc (buffer[ii], stdout);
- }
- fputs ("\n", stdout);
-
- gnutls_bye (session, GNUTLS_SHUT_RDWR);
-
-end:
-
- tcp_close (sd);
-
- gnutls_deinit (session);
-
- gnutls_anon_free_client_credentials (anoncred);
-
- gnutls_global_deinit ();
-}
-
-/* This is a sample TLS 1.0 echo server, for anonymous authentication only.
- */
-
-#define SA struct sockaddr
-#define MAX_BUF 1024
-#define PORT 5556 /* listen to 5556 port */
-#define DH_BITS 1024
-
-/* These are global */
-gnutls_anon_server_credentials_t anoncred;
-
-int
-oprfi_callback (gnutls_session_t session,
- void *userdata,
- size_t oprfi_len,
- const unsigned char *in_oprfi, unsigned char *out_oprfi)
-{
- size_t i;
-
- puts ("cb");
-
- for (i = 0; i < oprfi_len; i++)
- printf ("OPRF[%d]: %02x %03d %c\n", i, in_oprfi[i],
- in_oprfi[i], in_oprfi[i]);
-
- memset (out_oprfi, 42, oprfi_len);
-
- return 0;
-}
-
-gnutls_session_t
-initialize_tls_session (void)
-{
- gnutls_session_t session;
- const int kx_prio[] = { GNUTLS_KX_ANON_DH, 0 };
-
- gnutls_init (&session, GNUTLS_SERVER);
-
- /* avoid calling all the priority functions, since the defaults
- * are adequate.
- */
- gnutls_set_default_priority (session);
- gnutls_kx_set_priority (session, kx_prio);
-
- gnutls_credentials_set (session, GNUTLS_CRD_ANON, anoncred);
-
- gnutls_dh_set_prime_bits (session, DH_BITS);
-
- gnutls_oprfi_enable_server (session, oprfi_callback, NULL);
-
- return session;
-}
-
-static gnutls_dh_params_t dh_params;
-
-static int
-generate_dh_params (void)
-{
- const gnutls_datum_t p3 = { pkcs3, strlen (pkcs3) };
- /* Generate Diffie-Hellman parameters - for use with DHE
- * kx algorithms. These should be discarded and regenerated
- * once a day, once a week or once a month. Depending on the
- * security requirements.
- */
- gnutls_dh_params_init (&dh_params);
- return gnutls_dh_params_import_pkcs3 (dh_params, &p3, GNUTLS_X509_FMT_PEM);
-}
-
-int err, listen_sd, i;
-int sd, ret;
-struct sockaddr_in sa_serv;
-struct sockaddr_in sa_cli;
-int client_len;
-char topbuf[512];
-gnutls_session_t session;
-char buffer[MAX_BUF + 1];
-int optval = 1;
-
-void
-server_start (void)
-{
- /* this must be called once in the program
- */
- gnutls_global_init ();
-
- gnutls_global_set_log_function (tls_log_func);
- if (debug)
- gnutls_global_set_log_level (4711);
-
- gnutls_anon_allocate_server_credentials (&anoncred);
-
- success ("Launched, generating DH parameters...\n");
-
- generate_dh_params ();
-
- gnutls_anon_set_server_dh_params (anoncred, dh_params);
-
- /* Socket operations
- */
- listen_sd = socket (AF_INET, SOCK_STREAM, 0);
- if (err == -1)
- {
- perror ("socket");
- fail ("server: socket failed\n");
- return;
- }
-
- memset (&sa_serv, '\0', sizeof (sa_serv));
- sa_serv.sin_family = AF_INET;
- sa_serv.sin_addr.s_addr = INADDR_ANY;
- sa_serv.sin_port = htons (PORT); /* Server Port number */
-
- setsockopt (listen_sd, SOL_SOCKET, SO_REUSEADDR, (void *) &optval,
- sizeof (int));
-
- err = bind (listen_sd, (SA *) & sa_serv, sizeof (sa_serv));
- if (err == -1)
- {
- perror ("bind");
- fail ("server: bind failed\n");
- return;
- }
-
- err = listen (listen_sd, 1024);
- if (err == -1)
- {
- perror ("listen");
- fail ("server: listen failed\n");
- return;
- }
-
- success ("server: ready. Listening to port '%d'.\n", PORT);
-}
-
-void
-server (void)
-{
- client_len = sizeof (sa_cli);
-
- session = initialize_tls_session ();
-
- sd = accept (listen_sd, (SA *) & sa_cli, &client_len);
-
- success ("server: connection from %s, port %d\n",
- inet_ntop (AF_INET, &sa_cli.sin_addr, topbuf,
- sizeof (topbuf)), ntohs (sa_cli.sin_port));
-
- gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) sd);
- ret = gnutls_handshake (session);
- if (ret < 0)
- {
- close (sd);
- gnutls_deinit (session);
- fail ("server: Handshake has failed (%s)\n\n", gnutls_strerror (ret));
- return;
- }
- success ("server: Handshake was completed\n");
-
- success ("server: TLS version is: %s\n",
- gnutls_protocol_get_name (gnutls_protocol_get_version (session)));
-
- /* see the Getting peer's information example */
- /* print_info(session); */
-
- i = 0;
- for (;;)
- {
- memset (buffer, 0, MAX_BUF + 1);
- ret = gnutls_record_recv (session, buffer, MAX_BUF);
-
- if (ret == 0)
- {
- success ("server: Peer has closed the GnuTLS connection\n");
- break;
- }
- else if (ret < 0)
- {
- fail ("server: Received corrupted data(%d). Closing...\n", ret);
- break;
- }
- else if (ret > 0)
- {
- /* echo data back to the client
- */
- gnutls_record_send (session, buffer, strlen (buffer));
- }
- }
- /* do not wait for the peer to close the connection.
- */
- gnutls_bye (session, GNUTLS_SHUT_WR);
-
- close (sd);
- gnutls_deinit (session);
-
- close (listen_sd);
-
- gnutls_anon_free_server_credentials (anoncred);
-
- gnutls_global_deinit ();
-
- success ("server: finished\n");
-}
-
-void
-doit (void)
-{
- pid_t child;
-
- server_start ();
- if (error_count)
- return;
-
- child = fork ();
- if (child < 0)
- {
- perror ("fork");
- fail ("fork");
- return;
- }
-
- if (child)
- {
- int status;
- /* parent */
- server ();
- wait (&status);
- }
- else
- client ();
-}
#define MAX_BUF 1024
#define MSG "Hello TLS"
+static void
+tls_log_func (int level, const char *str)
+{
+ fprintf (stderr, "<%d>| %s", level, str);
+}
+
static int
client_avp (gnutls_session_t session, void *ptr,
const char *last, size_t lastlen, char **new, size_t * newlen)
const int kx_prio[] = { GNUTLS_KX_ANON_DH, 0 };
ret = gnutls_global_init ();
+ gnutls_global_set_log_function (tls_log_func);
+ if (debug)
+ gnutls_global_set_log_level (2);
+
if (ret)
fail ("global_init: %d\n", ret);
ret = gnutls_global_init_extra ();
if (ret)
fail ("global_init_extra: %d\n", ret);
+ gnutls_global_set_log_function (tls_log_func);
+ if (debug)
+ gnutls_global_set_log_level (2);
+
gnutls_anon_allocate_server_credentials (&anoncred);
gnutls_ia_allocate_server_credentials (&iacred);