]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Server hello format follows TLS1.2 format
authorNikos Mavrogiannopoulos <nmav@redhat.com>
Wed, 28 Feb 2018 11:41:40 +0000 (12:41 +0100)
committerNikos Mavrogiannopoulos <nmav@redhat.com>
Thu, 8 Mar 2018 11:56:32 +0000 (12:56 +0100)
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>
lib/ext/supported_versions.c
lib/handshake.c
lib/handshake.h
lib/includes/gnutls/gnutls.h.in
lib/sslv2_compat.c
tests/tls13/ext-parse.h
tests/tls13/prf.c
tests/tls13/supported_versions.c

index deca74039d3cfee55b1b071b34d772a4940d4efd..c7fc82d8d9ffc19062776a953b3a51378dfdb1b9 100644 (file)
@@ -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;
index 9b3fe6f648547094cda8737be313f319c771d913..d96d21cce64f31e3e4169db5fa9506030bd3449d 100644 (file)
@@ -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 :
index 0084789bcd6dee1c72094520b6e1cb1bc370555d..1096226410a964b98185dd881ba8dbd66507cc87 100644 (file)
@@ -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);
index b9142519aad74be124bc57c144de6388132cbe53..37d90adfcf093aa8a5feca45ed371cd5a31bfb1f 100644 (file)
@@ -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;
 
 /**
index 882cbd628db27ffc0cefb8d59684213ecf6811e5..d466cc30f1575c80cb3969a4789a7bd5f4226c8d 100644 (file)
@@ -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;
index 5b9f5b868fd510ce3312442b3ac56dc2f72a4e36..ff8a200768a77befcca125cb64a2b0beae81b0b0 100644 (file)
@@ -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;
 
index 52b88851b8cf152ee0306d0cfce9d9761c8e8158..762dddc15c4214c7b68f864f649a0c8af21639da 100644 (file)
@@ -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 */
index 31eb4ddbb60178bcc2b6b841865acdfa3b705a77..ca55cf9862fc54146ed1affeba44f23c262211a9 100644 (file)
@@ -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;