That is performed implicitly unless GNUTLS_NO_EXTENSIONS is specified.
The implementation follows draft-ietf-tls-session-hash-02.
max_record.h cert_type.h server_name.h srp.h \
session_ticket.h signature.h safe_renegotiation.h \
session_ticket.c srp.c ecc.c ecc.h heartbeat.c heartbeat.h \
- status_request.h status_request.c \
- dumbfw.c dumbfw.h
+ status_request.h status_request.c dumbfw.c dumbfw.h \
+ ext_master_secret.c ext_master_secret.h
if ENABLE_ALPN
libgnutls_ext_la_SOURCES += alpn.c alpn.h
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * 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 program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+/* This file contains the code for the Max Record Size TLS extension.
+ */
+
+#include "gnutls_int.h"
+#include "gnutls_errors.h"
+#include "gnutls_num.h"
+#include <gnutls_extensions.h>
+#include <ext/ext_master_secret.h>
+
+static int _gnutls_ext_master_secret_recv_params(gnutls_session_t session,
+ const uint8_t * data,
+ size_t data_size);
+static int _gnutls_ext_master_secret_send_params(gnutls_session_t session,
+ gnutls_buffer_st * extdata);
+
+extension_entry_st ext_mod_ext_master_secret = {
+ .name = "EXT MASTER SECRET",
+ .type = GNUTLS_EXTENSION_EXT_MASTER_SECRET,
+ .parse_type = GNUTLS_EXT_TLS,
+
+ .recv_func = _gnutls_ext_master_secret_recv_params,
+ .send_func = _gnutls_ext_master_secret_send_params,
+ .pack_func = NULL,
+ .unpack_func = NULL,
+ .deinit_func = NULL
+};
+
+/*
+ * In case of a server: if an EXT_MASTER_SECRET extension type is received then it
+ * sets a flag into the session security parameters.
+ *
+ */
+static int
+_gnutls_ext_master_secret_recv_params(gnutls_session_t session,
+ const uint8_t * data, size_t _data_size)
+{
+ ssize_t data_size = _data_size;
+
+ if (session->internals.try_ext_master_secret == 0) {
+ return 0;
+ }
+
+ if (data_size != 0) {
+ return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
+ }
+ session->security_parameters.ext_master_secret = 1;
+
+ return 0;
+}
+
+/* returns data_size or a negative number on failure
+ */
+static int
+_gnutls_ext_master_secret_send_params(gnutls_session_t session,
+ gnutls_buffer_st * extdata)
+{
+ if (session->internals.try_ext_master_secret == 0) {
+ return 0;
+ }
+
+ /* this function sends the client extension data */
+ if (session->security_parameters.entity == GNUTLS_CLIENT) {
+ return GNUTLS_E_INT_RET_0;
+ } else { /* server side */
+ if (session->security_parameters.ext_master_secret != 0)
+ return GNUTLS_E_INT_RET_0;
+ }
+
+ return 0;
+}
+
+/**
+ * gnutls_session_ext_master_secret_status:
+ * @session: is a #gnutls_session_t structure.
+ *
+ * Get the status of the extended master secret extension negotiation.
+ * This is in accordance to draft-ietf-tls-session-hash-01
+ *
+ * Returns: Non-zero if the negotiation was successful or zero otherwise.
+ **/
+unsigned gnutls_session_ext_master_secret_status(gnutls_session_t session)
+{
+ return session->security_parameters.ext_master_secret;
+}
+
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * 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 program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef EXT_EXT_MASTER_SECRET_H
+#define EXT_EXT_MASTER_SECRET_H
+
+#include <gnutls_extensions.h>
+
+extern extension_entry_st ext_mod_ext_master_secret;
+
+#endif
dst->cert_type = src->cert_type; \
dst->compression_method = src->compression_method; \
dst->timestamp = src->timestamp; \
+ dst->ext_master_secret = src->ext_master_secret; \
dst->max_record_recv_size = src->max_record_recv_size; \
dst->max_record_send_size = src->max_record_send_size
#include <ext/safe_renegotiation.h>
#include <ext/ecc.h>
#include <ext/status_request.h>
+#include <ext/ext_master_secret.h>
#include <ext/srtp.h>
#include <ext/alpn.h>
#include <ext/dumbfw.h>
if (ret != GNUTLS_E_SUCCESS)
return ret;
+ ret = _gnutls_ext_register(&ext_mod_ext_master_secret);
+ if (ret != GNUTLS_E_SUCCESS)
+ return ret;
+
#ifdef ENABLE_OCSP
ret = _gnutls_ext_register(&ext_mod_status_request);
if (ret != GNUTLS_E_SUCCESS)
{
return session->internals.last_handshake_out;
}
+
+/* This returns the session hash as in draft-ietf-tls-session-hash-02.
+ *
+ * FIXME: It duplicates some of the actions in _gnutls_handshake_sign_crt_vrfy*.
+ * See whether they can be merged.
+ */
+int _gnutls_handshake_get_session_hash(gnutls_session_t session, gnutls_datum_t *shash)
+{
+ const version_entry_st *ver = get_version(session);
+ int ret;
+ const mac_entry_st *me;
+ uint8_t concat[2*MAX_HASH_SIZE];
+ digest_hd_st td_md5;
+ digest_hd_st td_sha;
+
+ if (unlikely(ver == NULL))
+ return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+
+ if (_gnutls_version_has_selectable_prf(ver)) { /* TLS 1.2+ */
+ gnutls_mac_algorithm_t prf;
+
+ prf = _gnutls_cipher_suite_get_prf(session->security_parameters.cipher_suite);
+ if (prf == GNUTLS_MAC_UNKNOWN)
+ return gnutls_assert_val(GNUTLS_E_UNKNOWN_PK_ALGORITHM);
+
+ me = mac_to_entry(prf);
+
+ ret =
+ _gnutls_hash_fast((gnutls_digest_algorithm_t)me->id,
+ session->internals.handshake_hash_buffer.
+ data,
+ session->internals.handshake_hash_buffer.
+ length, concat);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ return _gnutls_set_datum(shash, concat, me->output_size);
+ } else {
+ ret = _gnutls_hash_init(&td_sha, hash_to_entry(GNUTLS_DIG_SHA1));
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ _gnutls_hash(&td_sha,
+ session->internals.handshake_hash_buffer.data,
+ session->internals.handshake_hash_buffer.length);
+
+ _gnutls_hash_deinit(&td_sha, &concat[16]);
+
+ ret =
+ _gnutls_hash_init(&td_md5,
+ hash_to_entry(GNUTLS_DIG_MD5));
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ _gnutls_hash(&td_md5,
+ session->internals.handshake_hash_buffer.data,
+ session->internals.handshake_hash_buffer.
+ length);
+
+ _gnutls_hash_deinit(&td_md5, concat);
+
+ return _gnutls_set_datum(shash, concat, 36);
+ }
+}
return 0;
}
+int _gnutls_handshake_get_session_hash(gnutls_session_t session, gnutls_datum_t *shash);
+
#endif
GNUTLS_EXTENSION_HEARTBEAT = 15,
GNUTLS_EXTENSION_ALPN = 16,
GNUTLS_EXTENSION_DUMBFW = 21,
+ GNUTLS_EXTENSION_EXT_MASTER_SECRET = 23,
GNUTLS_EXTENSION_SESSION_TICKET = 35,
- GNUTLS_EXTENSION_NEW_RECORD_PADDING = 48015, /* aka: 0xbeaf */
GNUTLS_EXTENSION_SAFE_RENEGOTIATION = 65281 /* aka: 0xff01 */
} extensions_t;
* session.
*/
-/* if you add anything in Security_Parameters struct, then
- * also modify CPY_COMMON in gnutls_constate.c.
- */
-
/* Note that the security parameters structure is set up after the
* handshake has finished. The only value you may depend on while
* the handshake is in progress is the cipher suite value.
/* Holds the signature algorithm used in this session - If any */
gnutls_sign_algorithm_t server_sign_algo;
gnutls_sign_algorithm_t client_sign_algo;
-
- /* FIXME: The following are not saved in the session storage
- * for session resumption.
+
+ /* Whether the master secret negotiation will be according to
+ * draft-ietf-tls-session-hash-01
+ */
+ uint8_t ext_master_secret;
+
+ /* Note: if you add anything in Security_Parameters struct, then
+ * also modify CPY_COMMON in gnutls_constate.c, and gnutls_session_pack.c,
+ * in order to save it in the session storage.
*/
/* Used by extensions that enable supplemental data: Which ones
bool sc_random_set;
bool no_replay_protection; /* DTLS replay protection */
+ bool try_ext_master_secret; /* whether to try negotiating the ext master secret */
/* If you add anything here, check _gnutls_handshake_internal_state_clear().
*/
#define MASTER_SECRET "master secret"
#define MASTER_SECRET_SIZE (sizeof(MASTER_SECRET)-1)
+
+#define EXT_MASTER_SECRET "extended master secret"
+#define EXT_MASTER_SECRET_SIZE (sizeof(EXT_MASTER_SECRET)-1)
+
static int generate_normal_master(gnutls_session_t session,
gnutls_datum_t *, int);
server_random, 32, buf,
sizeof(buf), NULL));
- if (get_num_version(session) == GNUTLS_SSL3) {
+ if (session->security_parameters.ext_master_secret == 0) {
uint8_t rnd[2 * GNUTLS_RANDOM_SIZE + 1];
-
memcpy(rnd, session->security_parameters.client_random,
GNUTLS_RANDOM_SIZE);
memcpy(&rnd[GNUTLS_RANDOM_SIZE],
session->security_parameters.server_random,
GNUTLS_RANDOM_SIZE);
- ret =
- _gnutls_ssl3_generate_random(premaster->data,
- premaster->size, rnd,
- 2 * GNUTLS_RANDOM_SIZE,
- GNUTLS_MASTER_SIZE,
- session->security_parameters.
- master_secret);
-
+ if (get_num_version(session) == GNUTLS_SSL3) {
+ ret =
+ _gnutls_ssl3_generate_random(premaster->data,
+ premaster->size, rnd,
+ 2 * GNUTLS_RANDOM_SIZE,
+ GNUTLS_MASTER_SIZE,
+ session->security_parameters.
+ master_secret);
+ } else {
+ ret =
+ _gnutls_PRF(session, premaster->data, premaster->size,
+ MASTER_SECRET, MASTER_SECRET_SIZE,
+ rnd, 2 * GNUTLS_RANDOM_SIZE,
+ GNUTLS_MASTER_SIZE,
+ session->security_parameters.
+ master_secret);
+ }
} else {
- uint8_t rnd[2 * GNUTLS_RANDOM_SIZE + 1];
-
- memcpy(rnd, session->security_parameters.client_random,
- GNUTLS_RANDOM_SIZE);
- memcpy(&rnd[GNUTLS_RANDOM_SIZE],
- session->security_parameters.server_random,
- GNUTLS_RANDOM_SIZE);
+ gnutls_datum_t shash = {NULL, 0};
- ret =
- _gnutls_PRF(session, premaster->data, premaster->size,
- MASTER_SECRET, MASTER_SECRET_SIZE,
- rnd, 2 * GNUTLS_RANDOM_SIZE,
- GNUTLS_MASTER_SIZE,
- session->security_parameters.
- master_secret);
+ /* draft-ietf-tls-session-hash-02 */
+ ret = _gnutls_handshake_get_session_hash(session, &shash);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+ if (get_num_version(session) == GNUTLS_SSL3) {
+ ret =
+ _gnutls_ssl3_generate_random(premaster->data,
+ premaster->size, shash.data, shash.size,
+ GNUTLS_MASTER_SIZE,
+ session->security_parameters.
+ master_secret);
+ } else {
+ ret =
+ _gnutls_PRF(session, premaster->data, premaster->size,
+ EXT_MASTER_SECRET, EXT_MASTER_SECRET_SIZE,
+ shash.data, shash.size,
+ GNUTLS_MASTER_SIZE,
+ session->security_parameters.
+ master_secret);
+ }
+ gnutls_free(shash.data);
}
if (!keep_premaster)
session->security_parameters.server_sign_algo);
BUFFER_APPEND_NUM(ps,
session->security_parameters.client_sign_algo);
+ BUFFER_APPEND_NUM(ps,
+ session->security_parameters.ext_master_secret);
_gnutls_write_uint32(ps->length - cur_size,
ps->data + size_offset);
BUFFER_POP_NUM(ps,
session->internals.resumed_security_parameters.
client_sign_algo);
+ BUFFER_POP_NUM(ps,
+ session->internals.resumed_security_parameters.
+ ext_master_secret);
if (session->internals.resumed_security_parameters.
max_record_recv_size == 0
#endif
}
+ if (!(flags & GNUTLS_NO_EXTENSIONS))
+ (*session)->internals.try_ext_master_secret = 1;
+
if (flags & GNUTLS_NO_REPLAY_PROTECTION)
(*session)->internals.no_replay_protection = 1;
/* Safe renegotiation */
int gnutls_safe_renegotiation_status(gnutls_session_t session);
+unsigned gnutls_session_ext_master_secret_status(gnutls_session_t session);
/**
* gnutls_supplemental_data_format_type_t:
gnutls_x509_crq_get_signature_algorithm;
gnutls_privkey_import_ext3;
gnutls_record_discard_queued;
+ gnutls_session_ext_master_secret_status;
} GNUTLS_3_0_0;
GNUTLS_FIPS140 {