]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
handshake: do not negotiate TLS1.3 using the legacy version field
authorNikos Mavrogiannopoulos <nmav@redhat.com>
Fri, 17 Aug 2018 12:02:34 +0000 (14:02 +0200)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Mon, 20 Aug 2018 19:54:30 +0000 (21:54 +0200)
Previously we could end-up with a TLS1.3 connection if the TLS1.3
ID was seen on the wire. We now explicitly fallback to TLS1.2
when we see a protocol with TLS1.3 semantics in an SSL2.0 or
in the legacy version of the client hello.

Signed-off-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
lib/ext/supported_versions.c
lib/handshake.c
lib/handshake.h
lib/sslv2_compat.c

index 3a11b39bd40202800a74d74c337e7fb0bafefd91..b7fe31f75bc2cdd99462e10318714300e751a777 100644 (file)
@@ -133,7 +133,7 @@ supported_versions_recv_params(gnutls_session_t session,
                if (!vers->tls13_sem)
                        return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
 
-               ret = _gnutls_negotiate_version(session, major, minor);
+               ret = _gnutls_negotiate_version(session, major, minor, 1);
                if (ret < 0) {
                        gnutls_assert();
                        return ret;
index ccf829916585e366f9351e38f3d6b04f5d1bdc1f..08481cca076ec4d2ed3e3d489c6e2c2db0009660 100644 (file)
@@ -431,7 +431,7 @@ _gnutls_finished(gnutls_session_t session, int type, void *ret,
  */
 int
 _gnutls_negotiate_version(gnutls_session_t session,
-                         uint8_t major, uint8_t minor)
+                         uint8_t major, uint8_t minor, unsigned allow_tls13)
 {
        const version_entry_st *vers;
        const version_entry_st *aversion = nversion_to_entry(major, minor);
@@ -471,6 +471,12 @@ _gnutls_negotiate_version(gnutls_session_t session,
        } else {
                session->security_parameters.pversion = aversion;
 
+               /* we do not allow TLS1.3 negotiation using this mechanism */
+               if (aversion->tls13_sem && !allow_tls13) {
+                       vers = _gnutls_legacy_version_max(session);
+                       session->security_parameters.pversion = vers;
+               }
+
                return 0;
        }
 }
@@ -505,7 +511,7 @@ _gnutls_user_hello_func(gnutls_session_t session,
                         * earlier, as TLS1.3 uses a different set of ciphersuites, and
                         * thus we cannot fallback.
                         */
-                       ret = _gnutls_negotiate_version(session, major, minor);
+                       ret = _gnutls_negotiate_version(session, major, minor, 0);
                        if (ret < 0) {
                                gnutls_assert();
                                return ret;
@@ -565,11 +571,15 @@ read_client_hello(gnutls_session_t session, uint8_t * data,
 
        set_adv_version(session, major, minor);
 
-       ret = _gnutls_negotiate_version(session, major, minor);
+       ret = _gnutls_negotiate_version(session, major, minor, 0);
        if (ret < 0)
                return gnutls_assert_val(ret);
 
-       neg_version = get_num_version(session);
+       vers = get_version(session);
+       if (vers == NULL)
+               return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
+
+       neg_version = vers->id;
 
        pos += 2;
 
index 0d617213c56dca91909f9a18099a8f1fbf9cf7da..184a349a9104a9d1104b41a901ad8720963bbdcd 100644 (file)
@@ -94,7 +94,8 @@ int _gnutls_server_select_suite(gnutls_session_t session, uint8_t * data,
                                unsigned int datalen, unsigned int scsv_only);
 
 int _gnutls_negotiate_version(gnutls_session_t session,
-                             uint8_t major, uint8_t minor);
+                             uint8_t major, uint8_t minor,
+                             unsigned allow_tls13);
 int _gnutls_user_hello_func(gnutls_session_t session,
                            uint8_t major, uint8_t minor);
 
index de762a5674b4886f2158a31c73d8567e57e815bc..9d8fd91bf40be08dc21a4ec8e30f3c5200d1be4b 100644 (file)
@@ -96,6 +96,7 @@ _gnutls_read_client_hello_v2(gnutls_session_t session, uint8_t * data,
        uint8_t rnd[GNUTLS_RANDOM_SIZE], major, minor;
        int len = datalen;
        int neg_version;
+       const version_entry_st *vers;
        uint16_t challenge;
        uint8_t session_id[GNUTLS_MAX_SESSION_ID_SIZE];
 
@@ -109,12 +110,17 @@ _gnutls_read_client_hello_v2(gnutls_session_t session, uint8_t * data,
        minor = data[pos + 1];
        set_adv_version(session, major, minor);
 
-       ret = _gnutls_negotiate_version(session, major, minor);
+       ret = _gnutls_negotiate_version(session, major, minor, 0);
        if (ret < 0) {
                gnutls_assert();
                return ret;
        }
-       neg_version = ret;
+
+       vers = get_version(session);
+       if (vers == NULL)
+               return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
+
+       neg_version = vers->id;
 
        pos += 2;