diff options
author | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2018-02-28 12:41:40 +0100 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2018-03-08 12:56:32 +0100 |
commit | 02354f173e66df3dad4ac9447e4965aecfad65e8 (patch) | |
tree | f608358522d46cd12484f0a0fa71e19ad4f6acef | |
parent | 90c4f5c1c4a4ec7bce1db01447df2727407cba3f (diff) | |
download | gnutls-02354f173e66df3dad4ac9447e4965aecfad65e8.tar.gz |
Server hello format follows TLS1.2 format
Also version negotiation was moved to supported_versions extension,
and session ID is set by client following appendix D.4.
This is a draft-ietf-tls-tls13-22 change.
Resolves #393, #389, #397
Signed-off-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
-rw-r--r-- | lib/ext/supported_versions.c | 63 | ||||
-rw-r--r-- | lib/handshake.c | 378 | ||||
-rw-r--r-- | lib/handshake.h | 2 | ||||
-rw-r--r-- | lib/includes/gnutls/gnutls.h.in | 21 | ||||
-rw-r--r-- | lib/sslv2_compat.c | 2 | ||||
-rw-r--r-- | tests/tls13/ext-parse.h | 20 | ||||
-rw-r--r-- | tests/tls13/prf.c | 12 | ||||
-rw-r--r-- | tests/tls13/supported_versions.c | 10 |
8 files changed, 307 insertions, 201 deletions
diff --git a/lib/ext/supported_versions.c b/lib/ext/supported_versions.c index deca74039d..c7fc82d8d9 100644 --- a/lib/ext/supported_versions.c +++ b/lib/ext/supported_versions.c @@ -29,6 +29,7 @@ #include "num.h" #include <hello_ext.h> #include <ext/supported_versions.h> +#include "handshake.h" static int supported_versions_recv_params(gnutls_session_t session, const uint8_t * data, @@ -40,8 +41,8 @@ const hello_ext_entry_st ext_mod_supported_versions = { .name = "Supported Versions", .tls_id = 43, .gid = GNUTLS_EXTENSION_SUPPORTED_VERSIONS, - .validity = GNUTLS_EXT_FLAG_CLIENT_HELLO, - .parse_type = GNUTLS_EXT_MANDATORY, /* force parsing prior to EXT_TLS extensions */ + .validity = GNUTLS_EXT_FLAG_CLIENT_HELLO|GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO|GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO, + .parse_type = GNUTLS_EXT_VERSION_NEG, /* force parsing prior to EXT_TLS extensions */ .recv_func = supported_versions_recv_params, .send_func = supported_versions_send_params, @@ -99,10 +100,32 @@ supported_versions_recv_params(gnutls_session_t session, /* if we are here, none of the versions were acceptable */ return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET); - } else { - /* a server should never send this message */ - gnutls_assert(); - return GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION; + } else { /* client */ + const version_entry_st *vers; + + DECR_LEN(data_size, 2); + + if (data_size != 0) + return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + + major = data[0]; + minor = data[1]; + + vers = nversion_to_entry(major, minor); + if (!vers) + return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET); + + set_adv_version(session, major, minor); + proto = _gnutls_version_get(major, minor); + + _gnutls_handshake_log("EXT[%p]: Negotiated version: %d.%d\n", + session, (int)major, (int)minor); + + ret = _gnutls_negotiate_version(session, proto, major, minor); + if (ret < 0) { + gnutls_assert(); + return ret; + } } return 0; @@ -116,10 +139,18 @@ supported_versions_send_params(gnutls_session_t session, { uint8_t versions[32]; size_t versions_size; + const version_entry_st *vers; int ret; /* this function sends the client extension data (dnsname) */ if (session->security_parameters.entity == GNUTLS_CLIENT) { + vers = _gnutls_version_max(session); + + /* do not advertise this extension when we haven't TLS1.3 + * enabled. */ + if (vers && !vers->tls13_sem) + return 0; + ret = _gnutls_write_supported_versions(session, versions, sizeof(versions)); if (ret <= 0) /* if this function doesn't succeed do not send anything */ return 0; @@ -131,6 +162,26 @@ supported_versions_send_params(gnutls_session_t session, return gnutls_assert_val(ret); return versions_size+2; + } else { + vers = get_version(session); + if (unlikely(vers == NULL)) + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + + /* don't use this extension to negotiate versions <= 1.2, + * pretend we don't support it, so that we use a single + * code path to negotiate these protocols. */ + if (!vers->tls13_sem) + return 0; + + ret = _gnutls_buffer_append_data(extdata, &vers->major, 1); + if (ret < 0) + return gnutls_assert_val(ret); + + ret = _gnutls_buffer_append_data(extdata, &vers->minor, 1); + if (ret < 0) + return gnutls_assert_val(ret); + + return 2; } return 0; diff --git a/lib/handshake.c b/lib/handshake.c index 9b3fe6f648..d96d21cce6 100644 --- a/lib/handshake.c +++ b/lib/handshake.c @@ -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; + + 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); - session->internals.resumed = RESUME_TRUE; + ret = resume_copy_required_values(session); + 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); + session->internals.resumed = RESUME_TRUE; - session->internals.resumed = RESUME_FALSE; + 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; + } + } 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; @@ -1562,7 +1588,7 @@ 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, @@ -1611,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; } } @@ -1632,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; + unsigned ext_parse_flag = 0; const version_entry_st *vers; - gnutls_ext_flags_t ext_parse_flag; if (datalen < GNUTLS_RANDOM_SIZE+2) { gnutls_assert(); @@ -1647,14 +1669,15 @@ 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]; + + 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); @@ -1662,64 +1685,96 @@ 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); } + 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); @@ -1732,46 +1787,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); @@ -1806,7 +1857,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; @@ -1842,7 +1893,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)) { @@ -1861,7 +1913,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; @@ -1871,8 +1924,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 @@ -1895,24 +1950,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; @@ -1970,8 +2044,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; @@ -1999,7 +2073,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); @@ -2014,50 +2089,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, @@ -2067,17 +2138,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 : diff --git a/lib/handshake.h b/lib/handshake.h index 0084789bcd..1096226410 100644 --- a/lib/handshake.h +++ b/lib/handshake.h @@ -72,7 +72,7 @@ int _gnutls_find_pk_algos_in_ciphersuites(uint8_t * data, int datalen); int _gnutls_server_select_suite(gnutls_session_t session, uint8_t * data, unsigned int datalen, unsigned int scsv_only); -int _gnutls_negotiate_legacy_version(gnutls_session_t session, +int _gnutls_negotiate_version(gnutls_session_t session, gnutls_protocol_t adv_version, uint8_t major, uint8_t minor); int _gnutls_user_hello_func(gnutls_session_t session, gnutls_protocol_t adv_version, uint8_t major, uint8_t minor); diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in index b9142519aa..37d90adfcf 100644 --- a/lib/includes/gnutls/gnutls.h.in +++ b/lib/includes/gnutls/gnutls.h.in @@ -2715,25 +2715,24 @@ int gnutls_ext_raw_parse(void *ctx, gnutls_ext_raw_process_func cb, /** * gnutls_ext_parse_type_t: - * @GNUTLS_EXT_NONE: Never parsed - * @GNUTLS_EXT_ANY: Any extension type (internal use only). - * @GNUTLS_EXT_APPLICATION: Application extension. - * @GNUTLS_EXT_TLS: TLS-internal extension. - * @GNUTLS_EXT_MANDATORY: Extension parsed even if resuming (or extensions are disabled). + * @GNUTLS_EXT_NONE: Never to be parsed + * @GNUTLS_EXT_ANY: Any extension type (should not be used as it is used only internally). + * @GNUTLS_EXT_VERSION_NEG: Extensions to be parsed first for TLS version negotiation. + * @GNUTLS_EXT_MANDATORY: Parsed after @GNUTLS_EXT_VERSION_NEG and even when resuming. + * @GNUTLS_EXT_APPLICATION: Parsed after @GNUTLS_EXT_MANDATORY + * @GNUTLS_EXT_TLS: TLS-internal extensions, parsed after @GNUTLS_EXT_APPLICATION. * - * Enumeration of different TLS extension parsing types. This type is - * to indicate whether an extension is useful to application - * level or TLS level only. This is used to decide the appropriate time - * each extension is parsed at during the server or client hello parsing. + * Enumeration of different TLS extension parsing phases. The @gnutls_ext_parse_type_t + * indicates the time/phase an extension is parsed during Client or Server hello parsing. * - * This applies to TLS 1.2 and earlier versions. */ typedef enum { GNUTLS_EXT_ANY = 0, GNUTLS_EXT_APPLICATION = 1, GNUTLS_EXT_TLS = 2, GNUTLS_EXT_MANDATORY = 3, - GNUTLS_EXT_NONE = 4 + GNUTLS_EXT_NONE = 4, + GNUTLS_EXT_VERSION_NEG = 5 } gnutls_ext_parse_type_t; /** diff --git a/lib/sslv2_compat.c b/lib/sslv2_compat.c index 882cbd628d..d466cc30f1 100644 --- a/lib/sslv2_compat.c +++ b/lib/sslv2_compat.c @@ -112,7 +112,7 @@ _gnutls_read_client_hello_v2(gnutls_session_t session, uint8_t * data, adv_version = _gnutls_version_get(major, minor); - ret = _gnutls_negotiate_legacy_version(session, adv_version, major, minor); + ret = _gnutls_negotiate_version(session, adv_version, major, minor); if (ret < 0) { gnutls_assert(); return ret; diff --git a/tests/tls13/ext-parse.h b/tests/tls13/ext-parse.h index 5b9f5b868f..ff8a200768 100644 --- a/tests/tls13/ext-parse.h +++ b/tests/tls13/ext-parse.h @@ -107,39 +107,29 @@ static unsigned find_client_extension(const gnutls_datum_t *msg, unsigned extnr, static unsigned find_server_extension(const gnutls_datum_t *msg, unsigned extnr, void *priv, ext_parse_func cb) { - unsigned tls13 = 0; unsigned pos = 0; success("server hello of %d bytes\n", msg->size); /* we expect the legacy version to be present */ /* ProtocolVersion legacy_version = 0x0303 */ -#ifdef TLS13_FINAL_VERSION - if (msg->data[0] != 0x03) { -#else - if (msg->data[0] != 0x7f) { -#endif + if (msg->data[0] != 0x03 || msg->data[1] != 0x03) { fail("ProtocolVersion contains %d.%d\n", (int)msg->data[0], (int)msg->data[1]); } if (msg->data[1] >= 0x04) { success("assuming TLS 1.3 or better hello format (seen %d.%d)\n", (int)msg->data[0], (int)msg->data[1]); - tls13 = 1; } pos += 2+TLS_RANDOM_SIZE; - if (!tls13) { - /* legacy_session_id */ - SKIP8(pos, msg->size); - } + /* legacy_session_id */ + SKIP8(pos, msg->size); /* CipherSuite */ pos += 2; - if (!tls13) { - /* legacy_compression_methods */ - SKIP8(pos, msg->size); - } + /* legacy_compression_methods */ + SKIP8(pos, msg->size); pos += 2; diff --git a/tests/tls13/prf.c b/tests/tls13/prf.c index 52b88851b8..762dddc15c 100644 --- a/tests/tls13/prf.c +++ b/tests/tls13/prf.c @@ -131,13 +131,13 @@ static void check_prfs(gnutls_session_t session) unsigned char key_material[512]; int ret; - TRY_OLD(13, "key expansion", 34, (uint8_t*)"\xd9\x09\xfa\x31\x2e\x2b\x79\x58\x3f\xde\x89\xd4\x41\xec\x2e\x62\xfd\x31\xaf\x7f\x62\xc4\x1c\xcc\x17\x6d\x0b\x30\x80\x62\x20\xb1\x52\x07"); - TRY_OLD(6, "hello", 31, (uint8_t*)"\x37\xa3\xba\xd9\x7d\x2a\x2b\xd0\x7a\x7a\x01\xde\x0a\x95\xe8\x88\x1a\xbb\x21\xa2\x7d\xa8\x12\xeb\xfd\x22\xed\x32\xc5\xa0\x19"); + TRY_OLD(13, "key expansion", 34, (uint8_t*)"\xac\x43\xa8\x49\x8f\x36\x3b\xbd\xcb\x3f\x45\x20\xac\xd5\x99\xf5\x4c\x92\x2a\x4d\xd6\x0b\xc2\x3f\xc2\xfe\xf3\xc7\x9e\x04\x70\xd3\xe1\x92"); + TRY_OLD(6, "hello", 31, (uint8_t*)"\x49\x74\x07\x6f\x2c\xed\xfa\xff\xda\xe8\x20\x1f\xc7\xce\xe7\x78\x66\xb9\x75\x3f\x5d\x6e\xb0\xa9\xb8\xb2\x46\xd1\xa1\xd6\x39"); - TRY(13, "key expansion", 0, NULL, 34, (uint8_t*)"\xd9\x09\xfa\x31\x2e\x2b\x79\x58\x3f\xde\x89\xd4\x41\xec\x2e\x62\xfd\x31\xaf\x7f\x62\xc4\x1c\xcc\x17\x6d\x0b\x30\x80\x62\x20\xb1\x52\x07"); - TRY(6, "hello", 0, NULL, 31, (uint8_t*)"\x37\xa3\xba\xd9\x7d\x2a\x2b\xd0\x7a\x7a\x01\xde\x0a\x95\xe8\x88\x1a\xbb\x21\xa2\x7d\xa8\x12\xeb\xfd\x22\xed\x32\xc5\xa0\x19"); - TRY(7, "context", 5, "abcd\xfa", 31, (uint8_t*)"\xac\x1a\x0f\x82\xd2\x97\xac\xc1\xd0\x2e\x90\xda\xcd\x70\x27\x97\xc0\x00\xf8\x8f\x9b\xa3\x0f\x22\x62\xee\x83\x55\xd9\x19\xa2"); - TRY(12, "null-context", 0, "", 31, (uint8_t*)"\x0d\xe3\xec\xd7\x82\x69\xe8\x38\xc5\xb9\x6d\x6f\xa8\x8b\xb7\xe8\x35\xd8\xfd\xfd\x63\x9d\x86\xfc\xf0\x49\x73\x0d\x26\xc9\xd7"); + TRY(13, "key expansion", 0, NULL, 34, (uint8_t*)"\xac\x43\xa8\x49\x8f\x36\x3b\xbd\xcb\x3f\x45\x20\xac\xd5\x99\xf5\x4c\x92\x2a\x4d\xd6\x0b\xc2\x3f\xc2\xfe\xf3\xc7\x9e\x04\x70\xd3\xe1\x92"); + TRY(6, "hello", 0, NULL, 31, (uint8_t*)"\x49\x74\x07\x6f\x2c\xed\xfa\xff\xda\xe8\x20\x1f\xc7\xce\xe7\x78\x66\xb9\x75\x3f\x5d\x6e\xb0\xa9\xb8\xb2\x46\xd1\xa1\xd6\x39"); + TRY(7, "context", 5, "abcd\xfa", 31, (uint8_t*)"\x0a\xa9\x28\xc7\x00\xf9\x49\xe8\x5a\xd0\xb8\x68\xba\x49\xd6\x04\x78\x61\x0b\xac\x45\xe3\xfb\x9c\x82\x94\x23\x24\xa4\x02\x8e"); + TRY(12, "null-context", 0, "", 31, (uint8_t*)"\xb1\xfa\x57\x28\x1a\x57\x20\xfd\x73\xed\xdd\xda\xf4\xf8\x9b\xec\x4d\xf5\x2d\x23\xd5\xe3\xd3\x77\x89\xeb\x54\xdd\x0e\x17\x49"); /* Try whether calling gnutls_prf() with non-null context or server-first * param, will fail */ diff --git a/tests/tls13/supported_versions.c b/tests/tls13/supported_versions.c index 31eb4ddbb6..ca55cf9862 100644 --- a/tests/tls13/supported_versions.c +++ b/tests/tls13/supported_versions.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 Red Hat, Inc. + * Copyright (C) 2017-2018 Red Hat, Inc. * * Author: Nikos Mavrogiannopoulos * @@ -152,12 +152,8 @@ static int client_hello_callback(gnutls_session_t session, unsigned int htype, success("server hello:\n\t%d.%d\n", (int)msg->data[pos], (int)msg->data[pos+1]); -#ifdef TLS13_FINAL_VERSION - if (msg->data[pos] != 0x03 || msg->data[pos+1] != 0x04) { -#else - if (msg->data[pos] != 0x7f || msg->data[pos+1] != 21) { -#endif - fail("fail expected TLS 1.3 in server hello, got %d.%d\n", (int)msg->data[pos], (int)msg->data[pos+1]); + if (msg->data[pos] != 0x03 || msg->data[pos+1] != 0x03) { + fail("fail expected TLS 1.2 in server hello, got %d.%d\n", (int)msg->data[pos], (int)msg->data[pos+1]); } server_hello_ok = 1; |