summaryrefslogtreecommitdiff
path: root/lib/handshake.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/handshake.c')
-rw-r--r--lib/handshake.c434
1 files changed, 268 insertions, 166 deletions
diff --git a/lib/handshake.c b/lib/handshake.c
index 179fcb8009..955fd5dd08 100644
--- a/lib/handshake.c
+++ b/lib/handshake.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2000-2016 Free Software Foundation, Inc.
- * Copyright (C) 2015-2017 Red Hat, Inc.
+ * Copyright (C) 2015-2018 Red Hat, Inc.
*
* Author: Nikos Mavrogiannopoulos
*
@@ -422,14 +422,15 @@ _gnutls_finished(gnutls_session_t session, int type, void *ret,
/* returns the 0 on success or a negative error code.
*/
int
-_gnutls_negotiate_legacy_version(gnutls_session_t session,
+_gnutls_negotiate_version(gnutls_session_t session,
gnutls_protocol_t adv_version, uint8_t major, uint8_t minor)
{
const version_entry_st *vers;
/* if we do not support that version, unless that version is TLS 1.2;
* TLS 1.2 is handled separately because it is always advertized under TLS 1.3 or later */
- if (adv_version == GNUTLS_VERSION_UNKNOWN || _gnutls_version_is_supported(session, adv_version) == 0) {
+ if (adv_version == GNUTLS_VERSION_UNKNOWN ||
+ _gnutls_version_is_supported(session, adv_version) == 0) {
if (adv_version == GNUTLS_TLS1_2) {
vers = _gnutls_version_max(session);
@@ -477,6 +478,7 @@ _gnutls_user_hello_func(gnutls_session_t session,
gnutls_protocol_t adv_version, uint8_t major, uint8_t minor)
{
int ret, sret = 0;
+ const version_entry_st *vers;
if (session->internals.user_hello_func != NULL) {
ret = session->internals.user_hello_func(session);
@@ -489,13 +491,18 @@ _gnutls_user_hello_func(gnutls_session_t session,
return ret;
}
- /* Here we need to renegotiate the version since the callee might
- * have disabled some TLS versions.
- */
- ret = _gnutls_negotiate_legacy_version(session, adv_version, major, minor);
- if (ret < 0) {
- gnutls_assert();
- return ret;
+ vers = get_version(session);
+ if (!vers->tls13_sem) {
+ /* Here we need to renegotiate the version since the callee might
+ * have disabled some TLS versions. We only do it for TLS1.2 or
+ * earlier, as TLS1.3 uses a different set of ciphersuites, and
+ * thus we cannot fallback.
+ */
+ ret = _gnutls_negotiate_version(session, adv_version, major, minor);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
}
}
return sret;
@@ -519,6 +526,7 @@ read_client_hello(gnutls_session_t session, uint8_t * data,
int len = datalen;
uint8_t major, minor;
uint8_t *suite_ptr, *comp_ptr, *session_id, *ext_ptr;
+ const version_entry_st *vers;
DECR_LEN(len, 2);
_gnutls_handshake_log("HSK[%p]: Client's version: %d.%d\n",
@@ -530,7 +538,7 @@ read_client_hello(gnutls_session_t session, uint8_t * data,
minor = data[pos+1];
set_adv_version(session, major, minor);
- neg_version = _gnutls_negotiate_legacy_version(session, adv_version, major, minor);
+ neg_version = _gnutls_negotiate_version(session, adv_version, major, minor);
if (neg_version < 0) {
gnutls_assert();
return neg_version;
@@ -598,46 +606,64 @@ read_client_hello(gnutls_session_t session, uint8_t * data,
ext_ptr = &data[pos];
ext_size = len;
- /* Parse only the mandatory to read extensions for resumption.
- * We don't want to parse any other extensions since
- * we don't want new extension values to override the
- * resumed ones.
- */
+ /* Parse only the mandatory to read extensions for resumption
+ * and version negotiation. We don't want to parse any other
+ * extensions since we don't want new extension values to override
+ * the resumed ones. */
ret =
_gnutls_parse_hello_extensions(session, GNUTLS_EXT_FLAG_CLIENT_HELLO,
- GNUTLS_EXT_MANDATORY,
- ext_ptr, ext_size);
- if (ret < 0) {
- gnutls_assert();
- return ret;
- }
+ GNUTLS_EXT_VERSION_NEG,
+ ext_ptr, ext_size);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
ret =
- _gnutls_server_restore_session(session, session_id,
- session_id_len);
+ _gnutls_parse_hello_extensions(session, GNUTLS_EXT_FLAG_CLIENT_HELLO,
+ GNUTLS_EXT_MANDATORY,
+ ext_ptr, ext_size);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
- if (session_id_len > 0)
- session->internals.resumption_requested = 1;
+ vers = get_version(session);
+ if (unlikely(vers == NULL))
+ return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
- if (ret == 0) { /* resumed using default TLS resumption! */
- ret = _gnutls_server_select_suite(session, suite_ptr, suite_size, 1);
- if (ret < 0)
- return gnutls_assert_val(ret);
+ if (!vers->tls13_sem) {
+ ret =
+ _gnutls_server_restore_session(session, session_id,
+ session_id_len);
- ret = resume_copy_required_values(session);
- if (ret < 0)
- return gnutls_assert_val(ret);
+ if (session_id_len > 0)
+ session->internals.resumption_requested = 1;
- session->internals.resumed = RESUME_TRUE;
+ if (ret == 0) { /* resumed using default TLS resumption! */
+ ret = _gnutls_server_select_suite(session, suite_ptr, suite_size, 1);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
- return _gnutls_user_hello_func(session, adv_version, major, minor);
- } else {
- _gnutls_generate_session_id(session->security_parameters.
- session_id,
- &session->security_parameters.
- session_id_size);
+ ret = resume_copy_required_values(session);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ session->internals.resumed = RESUME_TRUE;
+
+ return _gnutls_user_hello_func(session, adv_version, major, minor);
+ } else {
+ ret = _gnutls_generate_session_id(session->security_parameters.
+ session_id,
+ &session->security_parameters.
+ session_id_size);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
- session->internals.resumed = RESUME_FALSE;
+ session->internals.resumed = RESUME_FALSE;
+ }
+ } else { /* TLS1.3 */
+ /* we echo client's session ID - length was checked previously */
+ assert(session_id_len <= GNUTLS_MAX_SESSION_ID_SIZE);
+ if (session_id_len > 0)
+ memcpy(session->security_parameters.session_id, session_id, session_id_len);
+ session->security_parameters.session_id_size = session_id_len;
}
/* Parse the extensions (if any)
@@ -646,8 +672,8 @@ read_client_hello(gnutls_session_t session, uint8_t * data,
* sslv3 and higher, even though sslv3 doesn't officially support them.
*/
ret = _gnutls_parse_hello_extensions(session, GNUTLS_EXT_FLAG_CLIENT_HELLO,
- GNUTLS_EXT_APPLICATION,
- ext_ptr, ext_size);
+ GNUTLS_EXT_APPLICATION,
+ ext_ptr, ext_size);
/* len is the rest of the parsed length */
if (ret < 0) {
gnutls_assert();
@@ -664,7 +690,7 @@ read_client_hello(gnutls_session_t session, uint8_t * data,
/* Session tickets are parsed in this point */
ret =
_gnutls_parse_hello_extensions(session, GNUTLS_EXT_FLAG_CLIENT_HELLO,
- GNUTLS_EXT_TLS, ext_ptr, ext_size);
+ GNUTLS_EXT_TLS, ext_ptr, ext_size);
if (ret < 0) {
gnutls_assert();
return ret;
@@ -1068,9 +1094,22 @@ inline
if ((session->internals.h_type == type
|| session->internals.h_type == GNUTLS_HANDSHAKE_ANY)
&& (session->internals.h_post == post
- || session->internals.h_post == GNUTLS_HOOK_BOTH))
+ || session->internals.h_post == GNUTLS_HOOK_BOTH)) {
+
+ /* internal API for testing: when we are expected to
+ * wait for GNUTLS_HANDSHAKE_CHANGE_CIPHER_SPEC, we
+ * do so, but not when doing for all messages. The
+ * reason is that change cipher specs are not handshake
+ * messages, and we don't support waiting for them
+ * consistently (only sending is tracked, not receiving).
+ */
+ if (type == GNUTLS_HANDSHAKE_CHANGE_CIPHER_SPEC &&
+ session->internals.h_type != GNUTLS_HANDSHAKE_CHANGE_CIPHER_SPEC)
+ return 0;
+
return session->internals.h_hook(session, type,
post, incoming, &msg);
+ }
}
return 0;
}
@@ -1104,7 +1143,7 @@ _gnutls_send_handshake(gnutls_session_t session, mbuffer_st * bufel,
i_datasize = _mbuffer_get_udata_size(bufel);
datasize = i_datasize + _mbuffer_get_uhead_size(bufel);
- data[pos++] = (uint8_t) type;
+ data[pos++] = (uint8_t) REAL_HSK_TYPE(type);
_gnutls_write_uint24(_mbuffer_get_udata_size(bufel), &data[pos]);
pos += 3;
@@ -1350,7 +1389,7 @@ _gnutls_recv_handshake(gnutls_session_t session,
goto cleanup;
}
- ret = handshake_hash_add_recvd(session, hsk.htype,
+ ret = handshake_hash_add_recvd(session, hsk.rtype,
hsk.header, hsk.header_size,
hsk.data.data,
hsk.data.length);
@@ -1549,11 +1588,11 @@ set_client_ciphersuite(gnutls_session_t session, uint8_t suite[2])
/* This function returns 0 if we are resuming a session or -1 otherwise.
* This also sets the variables in the session. Used only while reading a server
- * hello.
+ * hello. Only applicable to TLS1.2 or earlier.
*/
static int
client_check_if_resuming(gnutls_session_t session,
- uint8_t * session_id, int session_id_len)
+ uint8_t * session_id, int session_id_len)
{
char buf[2 * GNUTLS_MAX_SESSION_ID_SIZE + 1];
int ret;
@@ -1598,13 +1637,6 @@ client_check_if_resuming(gnutls_session_t session,
no_resume:
/* keep the new session id */
session->internals.resumed = RESUME_FALSE; /* we are not resuming */
- session->security_parameters.session_id_size =
- session_id_len;
- if (session_id_len > 0) {
- memcpy(session->security_parameters.session_id, session_id,
- session_id_len);
- }
-
return -1;
}
}
@@ -1619,11 +1651,14 @@ read_server_hello(gnutls_session_t session,
uint8_t * data, int datalen)
{
uint8_t session_id_len = 0;
+ uint8_t *session_id;
+ uint8_t *cs_pos, *comp_pos, *srandom_pos;
+ uint8_t major, minor;
int pos = 0;
int ret = 0;
int len = datalen;
- const version_entry_st *vers;
- gnutls_ext_flags_t ext_parse_flag;
+ unsigned ext_parse_flag = 0;
+ const version_entry_st *vers, *saved_vers;
if (datalen < GNUTLS_RANDOM_SIZE+2) {
gnutls_assert();
@@ -1634,14 +1669,17 @@ read_server_hello(gnutls_session_t session,
session, data[pos], data[pos + 1]);
DECR_LEN(len, 2);
- vers = nversion_to_entry(data[pos], data[pos + 1]);
+ major = data[pos];
+ minor = data[pos+1];
+
+ saved_vers = get_version(session); /* will be non-null if HRR has been received */
+
+ vers = nversion_to_entry(major, minor);
if (unlikely(vers == NULL))
return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
- if (_gnutls_version_is_supported(session, vers->id) == 0) {
- gnutls_assert();
- return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
- }
+ if (vers->tls13_sem) /* that shouldn't have been negotiated here */
+ return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
if (_gnutls_set_current_version(session, vers->id) < 0)
return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
@@ -1649,64 +1687,100 @@ read_server_hello(gnutls_session_t session,
pos += 2;
DECR_LEN(len, GNUTLS_RANDOM_SIZE);
- ret = _gnutls_set_server_random(session, vers, &data[pos]);
+ srandom_pos = &data[pos];
+ pos += GNUTLS_RANDOM_SIZE;
+
+ /* Read session ID
+ */
+ DECR_LEN(len, 1);
+ session_id_len = data[pos++];
+
+ if (len < session_id_len || session_id_len > GNUTLS_MAX_SESSION_ID_SIZE) {
+ gnutls_assert();
+ return GNUTLS_E_ILLEGAL_PARAMETER;
+ }
+ DECR_LEN(len, session_id_len);
+ session_id = &data[pos];
+ pos += session_id_len;
+
+ DECR_LEN(len, 2);
+ cs_pos = &data[pos];
+ pos += 2;
+
+ /* move to compression
+ */
+ DECR_LEN(len, 1);
+ comp_pos = &data[pos];
+ pos++;
+
+ /* parse extensions to figure version */
+ ret =
+ _gnutls_parse_hello_extensions(session, GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO|
+ GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO,
+ GNUTLS_EXT_VERSION_NEG,
+ &data[pos], len);
if (ret < 0)
return gnutls_assert_val(ret);
- pos += GNUTLS_RANDOM_SIZE;
+ vers = get_version(session);
+ if (unlikely(vers == NULL))
+ return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
+ if (vers->tls13_sem) {
+ if (major != 0x03 || minor != 0x03)
+ return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
+ }
- if (!vers->tls13_sem) {
- /* Read session ID
- */
- DECR_LEN(len, 1);
- session_id_len = data[pos++];
+ if (_gnutls_version_is_supported(session, vers->id) == 0)
+ return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
- if (len < session_id_len || session_id_len > GNUTLS_MAX_SESSION_ID_SIZE) {
- gnutls_assert();
- return GNUTLS_E_ILLEGAL_PARAMETER;
- }
- DECR_LEN(len, session_id_len);
+ /* set server random - done after final version is selected */
+ ret = _gnutls_set_server_random(session, vers, srandom_pos);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
- /* check if we are resuming and set the appropriate
- * values;
- */
- if (client_check_if_resuming
- (session, &data[pos], session_id_len) == 0) {
- pos += session_id_len + 2 + 1;
- DECR_LEN(len, 2 + 1);
+ /* check if we are resuming and set the appropriate
+ * values;
+ */
+ if (!vers->tls13_sem &&
+ client_check_if_resuming(session, session_id, session_id_len) == 0) {
- ret =
- _gnutls_parse_hello_extensions(session, GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO,
- GNUTLS_EXT_MANDATORY,
- &data[pos], len);
- if (ret < 0) {
- gnutls_assert();
- return ret;
- }
- return 0;
- }
+ ret =
+ _gnutls_parse_hello_extensions(session, GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO,
+ GNUTLS_EXT_MANDATORY,
+ &data[pos], len);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
- pos += session_id_len;
+ return 0;
+ } else {
+ session->security_parameters.session_id_size = session_id_len;
+ if (session_id_len > 0)
+ memcpy(session->security_parameters.session_id, session_id,
+ session_id_len);
}
/* Check if the given cipher suite is supported and copy
* it to the session.
*/
-
- DECR_LEN(len, 2);
- ret = set_client_ciphersuite(session, &data[pos]);
+ ret = set_client_ciphersuite(session, cs_pos);
if (ret < 0) {
gnutls_assert();
return ret;
}
- pos += 2;
if (session->internals.hsk_flags & HSK_HRR_RECEIVED) {
/* check if ciphersuite matches */
- if (memcmp(session->security_parameters.cs->id, session->internals.hrr_cs, 2) != 0)
+ if (memcmp(cs_pos, session->internals.hrr_cs, 2) != 0)
+ return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
+
+ /* check if HRR version matches this version */
+ if (vers != saved_vers)
return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
}
+ if (*comp_pos != 0)
+ return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
+
if (vers->tls13_sem) {
/* TLS 1.3 Early Secret */
ret = _tls13_init_secret(session, NULL, 0);
@@ -1719,46 +1793,42 @@ read_server_hello(gnutls_session_t session,
if (ret < 0)
return gnutls_assert_val(ret);
- ext_parse_flag = GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO;
+ ext_parse_flag |= GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO;
} else {
- /* move to compression
- */
- DECR_LEN(len, 1);
- pos++;
- ext_parse_flag = GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO;
+ ext_parse_flag |= GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO;
}
/* Parse extensions in order.
*/
ret =
_gnutls_parse_hello_extensions(session,
- ext_parse_flag,
- GNUTLS_EXT_MANDATORY,
- &data[pos], len);
+ ext_parse_flag,
+ GNUTLS_EXT_MANDATORY,
+ &data[pos], len);
if (ret < 0)
return gnutls_assert_val(ret);
ret =
_gnutls_parse_hello_extensions(session,
- ext_parse_flag,
- GNUTLS_EXT_APPLICATION,
- &data[pos], len);
+ ext_parse_flag,
+ GNUTLS_EXT_APPLICATION,
+ &data[pos], len);
if (ret < 0)
return gnutls_assert_val(ret);
ret =
_gnutls_parse_hello_extensions(session,
- ext_parse_flag,
- GNUTLS_EXT_TLS,
- &data[pos], len);
+ ext_parse_flag,
+ GNUTLS_EXT_TLS,
+ &data[pos], len);
if (ret < 0)
return gnutls_assert_val(ret);
ret =
_gnutls_parse_hello_extensions(session,
- ext_parse_flag,
- _GNUTLS_EXT_TLS_POST_CS,
- &data[pos], len);
+ ext_parse_flag,
+ _GNUTLS_EXT_TLS_POST_CS,
+ &data[pos], len);
if (ret < 0)
return gnutls_assert_val(ret);
@@ -1793,7 +1863,7 @@ static int send_client_hello(gnutls_session_t session, int again)
mbuffer_st *bufel = NULL;
int type;
int ret = 0;
- const version_entry_st *hver, *min_ver;
+ const version_entry_st *hver, *min_ver, *max_ver;
uint8_t tver[2];
gnutls_buffer_st extdata;
int rehandshake = 0;
@@ -1829,7 +1899,8 @@ static int send_client_hello(gnutls_session_t session, int again)
if (hver == NULL) {
gnutls_assert();
- return GNUTLS_E_NO_PRIORITIES_WERE_SET;
+ ret = GNUTLS_E_NO_PRIORITIES_WERE_SET;
+ goto cleanup;
}
if (unlikely(session->internals.default_hello_version[0] != 0)) {
@@ -1848,7 +1919,8 @@ static int send_client_hello(gnutls_session_t session, int again)
(unsigned)tver[0], (unsigned)tver[1]);
min_ver = _gnutls_version_lowest(session);
- if (min_ver == NULL) {
+ max_ver = _gnutls_version_max(session);
+ if (min_ver == NULL || max_ver == NULL) {
gnutls_assert();
ret = GNUTLS_E_NO_PRIORITIES_WERE_SET;
goto cleanup;
@@ -1858,8 +1930,10 @@ static int send_client_hello(gnutls_session_t session, int again)
* (RSA uses it).
*/
set_adv_version(session, hver->major, hver->minor);
- if (_gnutls_set_current_version(session, hver->id) < 0)
- return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
+ if (_gnutls_set_current_version(session, hver->id) < 0) {
+ ret = gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
+ goto cleanup;
+ }
if (session->internals.priorities->min_record_version != 0) {
/* Advertize the lowest supported (SSL 3.0) record packet
@@ -1882,24 +1956,43 @@ static int send_client_hello(gnutls_session_t session, int again)
if (!(session->internals.hsk_flags & HSK_HRR_RECEIVED) &&
!(IS_DTLS(session) && session->internals.dtls.hsk_hello_verify_requests == 0)) {
ret = _gnutls_gen_client_random(session);
- if (ret < 0)
- return gnutls_assert_val(ret);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
}
ret = _gnutls_buffer_append_data(&extdata,
- session->security_parameters.client_random,
- GNUTLS_RANDOM_SIZE);
+ session->security_parameters.client_random,
+ GNUTLS_RANDOM_SIZE);
if (ret < 0) {
gnutls_assert();
goto cleanup;
}
- /* Copy the Session ID
+#ifdef TLS13_APPENDIX_D4
+ if (max_ver->tls13_sem &&
+ session->security_parameters.session_id_size == 0) {
+
+ /* Under TLS1.3 we generate a random session ID to make
+ * the TLS1.3 session look like a resumed TLS1.2 session */
+ ret = _gnutls_generate_session_id(session->security_parameters.
+ session_id,
+ &session->security_parameters.
+ session_id_size);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+ }
+#endif
+
+ /* Copy the Session ID - if any
*/
ret = _gnutls_buffer_append_data_prefix(&extdata, 8,
- session->internals.resumed_security_parameters.session_id,
- session_id_len);
+ session->internals.resumed_security_parameters.session_id,
+ session_id_len);
if (ret < 0) {
gnutls_assert();
goto cleanup;
@@ -1957,8 +2050,8 @@ static int send_client_hello(gnutls_session_t session, int again)
ret =
_gnutls_gen_hello_extensions(session, &extdata,
- GNUTLS_EXT_FLAG_CLIENT_HELLO,
- type);
+ GNUTLS_EXT_FLAG_CLIENT_HELLO,
+ type);
if (ret < 0) {
gnutls_assert();
goto cleanup;
@@ -1986,7 +2079,8 @@ int _gnutls_send_server_hello(gnutls_session_t session, int again)
session->security_parameters.session_id_size;
char tmpbuf[2 * GNUTLS_MAX_SESSION_ID_SIZE + 1];
const version_entry_st *vers;
- gnutls_ext_flags_t ext_parse_flag;
+ uint8_t vbytes[2];
+ unsigned extflag = 0;
_gnutls_buffer_init(&buf);
@@ -2001,50 +2095,46 @@ int _gnutls_send_server_hello(gnutls_session_t session, int again)
if (ret < 0)
return gnutls_assert_val(ret);
- ext_parse_flag = GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO;
+ vbytes[0] = 0x03; /* TLS1.2 */
+ vbytes[1] = 0x03;
+ extflag |= GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO;
} else {
- ext_parse_flag = GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO;
+ vbytes[0] = vers->major;
+ vbytes[1] = vers->minor;
+ extflag |= GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO;
}
ret = _gnutls_buffer_init_handshake_mbuffer(&buf);
if (ret < 0)
return gnutls_assert_val(ret);
- ret = _gnutls_buffer_append_data(&buf, &vers->major, 1);
+ ret = _gnutls_buffer_append_data(&buf, vbytes, 2);
if (ret < 0) {
gnutls_assert();
goto fail;
}
- ret = _gnutls_buffer_append_data(&buf, &vers->minor, 1);
+ ret = _gnutls_buffer_append_data(&buf,
+ session->security_parameters.server_random,
+ GNUTLS_RANDOM_SIZE);
if (ret < 0) {
gnutls_assert();
goto fail;
}
- ret = _gnutls_buffer_append_data(&buf,
- session->security_parameters.server_random,
- GNUTLS_RANDOM_SIZE);
+ ret = _gnutls_buffer_append_data_prefix(&buf, 8,
+ session->security_parameters.session_id,
+ session_id_len);
if (ret < 0) {
gnutls_assert();
goto fail;
}
- if (!vers->tls13_sem) {
- ret = _gnutls_buffer_append_data_prefix(&buf, 8,
- session->security_parameters.session_id,
- session_id_len);
- if (ret < 0) {
- gnutls_assert();
- goto fail;
- }
-
- _gnutls_handshake_log("HSK[%p]: SessionID: %s\n", session,
- _gnutls_bin2hex(session->
- security_parameters.session_id,
- session_id_len, tmpbuf,
- sizeof(tmpbuf), NULL));
- }
+ _gnutls_handshake_log("HSK[%p]: SessionID: %s\n", session,
+ _gnutls_bin2hex(session->
+ security_parameters.session_id,
+ session_id_len, tmpbuf,
+ sizeof(tmpbuf), NULL));
ret = _gnutls_buffer_append_data(&buf,
session->security_parameters.cs->id,
@@ -2054,17 +2144,16 @@ int _gnutls_send_server_hello(gnutls_session_t session, int again)
goto fail;
}
- if (!vers->tls13_sem) {
- ret = _gnutls_buffer_append_prefix(&buf, 8, 0);
- if (ret < 0) {
- gnutls_assert();
- goto fail;
- }
+ /* compression */
+ ret = _gnutls_buffer_append_prefix(&buf, 8, 0);
+ if (ret < 0) {
+ gnutls_assert();
+ goto fail;
}
ret =
_gnutls_gen_hello_extensions(session, &buf,
- ext_parse_flag,
+ extflag,
(session->internals.resumed ==
RESUME_TRUE) ?
GNUTLS_EXT_MANDATORY :
@@ -2556,7 +2645,7 @@ static int handshake_client(gnutls_session_t session)
const version_entry_st *ver;
reset:
- if (STATE >= STATE100)
+ if (STATE >= STATE99)
return _gnutls13_handshake_client(session);
switch (STATE) {
@@ -2605,7 +2694,7 @@ static int handshake_client(gnutls_session_t session)
case STATE4:
ver = get_version(session);
if (ver->tls13_sem) { /* TLS 1.3 state machine */
- STATE = STATE100;
+ STATE = STATE99;
goto reset;
}
@@ -2778,7 +2867,7 @@ static int handshake_client(gnutls_session_t session)
/* This function is to be called if the handshake was successfully
* completed. This sends a Change Cipher Spec packet to the peer.
*/
-static ssize_t send_change_cipher_spec(gnutls_session_t session, int again)
+ssize_t _gnutls_send_change_cipher_spec(gnutls_session_t session, int again)
{
uint8_t *data;
mbuffer_st *bufel;
@@ -2786,7 +2875,7 @@ static ssize_t send_change_cipher_spec(gnutls_session_t session, int again)
const version_entry_st *vers;
if (again == 0) {
- bufel = _gnutls_handshake_alloc(session, 1);
+ bufel = _gnutls_handshake_alloc(session, 3); /* max for DTLS0.9 */
if (bufel == NULL)
return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
@@ -2809,6 +2898,13 @@ static ssize_t send_change_cipher_spec(gnutls_session_t session, int again)
session->internals.dtls.hsk_write_seq++;
}
+ ret = call_hook_func(session, GNUTLS_HANDSHAKE_CHANGE_CIPHER_SPEC, GNUTLS_HOOK_PRE, 0,
+ data, 1);
+ if (ret < 0) {
+ _mbuffer_xfree(&bufel);
+ return gnutls_assert_val(ret);
+ }
+
ret =
_gnutls_handshake_io_cache_int(session,
GNUTLS_HANDSHAKE_CHANGE_CIPHER_SPEC,
@@ -2818,6 +2914,12 @@ static ssize_t send_change_cipher_spec(gnutls_session_t session, int again)
return gnutls_assert_val(ret);
}
+ ret = call_hook_func(session, GNUTLS_HANDSHAKE_CHANGE_CIPHER_SPEC, GNUTLS_HOOK_POST, 0,
+ data, 1);
+ if (ret < 0) {
+ return gnutls_assert_val(ret);
+ }
+
_gnutls_handshake_log("REC[%p]: Sent ChangeCipherSpec\n",
session);
}
@@ -2836,7 +2938,7 @@ static int send_handshake_final(gnutls_session_t session, int init)
switch (FINAL_STATE) {
case STATE0:
case STATE1:
- ret = send_change_cipher_spec(session, FAGAIN(STATE1));
+ ret = _gnutls_send_change_cipher_spec(session, FAGAIN(STATE1));
FINAL_STATE = STATE0;
if (ret < 0) {
@@ -3021,7 +3123,7 @@ static int handshake_server(gnutls_session_t session)
ver = get_version(session);
if (ver->tls13_sem) { /* TLS 1.3 state machine */
- STATE = STATE100;
+ STATE = STATE99;
goto reset;
}