]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Added TLS 1.3 Hello message random generation
authorNikos Mavrogiannopoulos <nmav@redhat.com>
Mon, 19 Jun 2017 09:57:22 +0000 (11:57 +0200)
committerNikos Mavrogiannopoulos <nmav@redhat.com>
Mon, 19 Feb 2018 14:29:33 +0000 (15:29 +0100)
That is, added check for TLS 1.3 random value requirements in client side,
and generation according to TLS 1.3 requirements for server and
client side.

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

index a9b1f80881565a33ce22c07735fac8ed8d4b40b8..254bf75d4879f7d58063ca202aa28f4914615c54 100644 (file)
@@ -166,48 +166,14 @@ static int resume_copy_required_values(gnutls_session_t session)
        return 0;
 }
 
-
-/* this function will produce GNUTLS_RANDOM_SIZE==32 bytes of random data
- * and put it to dst.
- */
-static int create_tls_random(uint8_t * dst)
-{
-       int ret;
-
-       /* Use nonce rng level for the most of the
-        * buffer except for the first 4 that are the
-        * system's time.
-        */
-
-#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
-       /* When fuzzying avoid timing dependencies */
-       memset(dst, 1, 4);
-#else
-       uint32_t tim;
-
-       tim = gnutls_time(NULL);
-       /* generate server random value */
-       _gnutls_write_uint32(tim, dst);
-#endif
-
-       ret =
-           gnutls_rnd(GNUTLS_RND_NONCE, &dst[3], GNUTLS_RANDOM_SIZE - 3);
-       if (ret < 0) {
-               gnutls_assert();
-               return ret;
-       }
-
-       return 0;
-}
-
 int _gnutls_set_client_random(gnutls_session_t session, uint8_t * rnd)
 {
        int ret;
 
-       if (rnd != NULL)
+       if (rnd != NULL) { /* server */
                memcpy(session->security_parameters.client_random, rnd,
                       GNUTLS_RANDOM_SIZE);
-       else {
+       } else { /* client */
                /* no random given, we generate. */
                if (session->internals.sc_random_set != 0) {
                        memcpy(session->security_parameters.client_random,
@@ -216,9 +182,9 @@ int _gnutls_set_client_random(gnutls_session_t session, uint8_t * rnd)
                               GNUTLS_RANDOM_SIZE);
                } else {
                        ret =
-                           create_tls_random(session->
-                                             security_parameters.
-                                             client_random);
+                           gnutls_rnd(GNUTLS_RND_NONCE,
+                                       session->security_parameters.client_random,
+                                       GNUTLS_RANDOM_SIZE);
                        if (ret < 0)
                                return gnutls_assert_val(ret);
                }
@@ -226,27 +192,58 @@ int _gnutls_set_client_random(gnutls_session_t session, uint8_t * rnd)
        return 0;
 }
 
-int _gnutls_set_server_random(gnutls_session_t session, uint8_t * rnd)
+int _gnutls_set_server_random(gnutls_session_t session, int version, uint8_t * rnd)
 {
        int ret;
 
-       if (rnd != NULL)
+       if (rnd != NULL) { /* client */
                memcpy(session->security_parameters.server_random, rnd,
                       GNUTLS_RANDOM_SIZE);
-       else {
-               /* no random given, we generate. */
+
+               /* check whether the server random value is set according to
+                * to TLS 1.3. p4.1.3 requirements */
+               if (version <= GNUTLS_TLS1_2 && _gnutls_version_is_supported(session, GNUTLS_TLS1_3)) {
+                       if (version == GNUTLS_TLS1_2 &&
+                           memcmp(&session->security_parameters.server_random[GNUTLS_RANDOM_SIZE-8-1],
+                           "\x44\x4F\x57\x4E\x47\x52\x44\x01", 8) == 0) {
+                               _gnutls_audit_log(session,
+                                         "Detected downgrade to TLS 1.2 from TLS 1.3\n");
+                               return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
+                       } else if (version <= GNUTLS_TLS1_1 &&
+                                  memcmp(&session->security_parameters.server_random[GNUTLS_RANDOM_SIZE-8-1],
+                                  "\x44\x4F\x57\x4E\x47\x52\x44\x00", 8) == 0) {
+                               _gnutls_audit_log(session,
+                                         "Detected downgrade to TLS 1.1 or earlier from TLS 1.3\n");
+                               return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
+                       }
+               }
+
+       } else { /* server */
                if (session->internals.sc_random_set != 0) {
                        memcpy(session->security_parameters.server_random,
                               session->internals.
                               resumed_security_parameters.server_random,
                               GNUTLS_RANDOM_SIZE);
                } else {
-                       ret =
-                           create_tls_random(session->
-                                             security_parameters.
-                                             server_random);
-                       if (ret < 0)
-                               return gnutls_assert_val(ret);
+                       if (version == GNUTLS_TLS1_2) {
+                               memcpy(&session->security_parameters.server_random[GNUTLS_RANDOM_SIZE-8-1],
+                                       "\x44\x4F\x57\x4E\x47\x52\x44\x01", 8);
+                               ret =
+                                   gnutls_rnd(GNUTLS_RND_NONCE, session->security_parameters.server_random, GNUTLS_RANDOM_SIZE-8);
+                       } else if (version <= GNUTLS_TLS1_1) {
+                               memcpy(&session->security_parameters.server_random[GNUTLS_RANDOM_SIZE-8-1],
+                                       "\x44\x4F\x57\x4E\x47\x52\x44\x00", 8);
+                               ret =
+                                   gnutls_rnd(GNUTLS_RND_NONCE, session->security_parameters.server_random, GNUTLS_RANDOM_SIZE-8);
+                       } else {
+                               ret =
+                                   gnutls_rnd(GNUTLS_RND_NONCE, session->security_parameters.server_random, GNUTLS_RANDOM_SIZE);
+                       }
+
+                       if (ret < 0) {
+                               gnutls_assert();
+                               return ret;
+                       }
                }
        }
        return 0;
@@ -480,7 +477,7 @@ read_client_hello(gnutls_session_t session, uint8_t * data,
 
        pos += GNUTLS_RANDOM_SIZE;
 
-       ret = _gnutls_set_server_random(session, NULL);
+       ret = _gnutls_set_server_random(session, neg_version, NULL);
        if (ret < 0)
                return gnutls_assert_val(ret);
 
@@ -1525,7 +1522,7 @@ read_server_hello(gnutls_session_t session,
        pos += 2;
 
        DECR_LEN(len, GNUTLS_RANDOM_SIZE);
-       ret = _gnutls_set_server_random(session, &data[pos]);
+       ret = _gnutls_set_server_random(session, version, &data[pos]);
        if (ret < 0)
                return gnutls_assert_val(ret);
 
index 41a2e9d32a824397aa76b241ed0f62745ff386d4..c6b393a2052b101e5fccbc06cf03323a594f7808 100644 (file)
@@ -33,7 +33,7 @@ int _gnutls_recv_handshake(gnutls_session_t session,
                           gnutls_handshake_description_t type,
                           unsigned int optional, gnutls_buffer_st * buf);
 int _gnutls_generate_session_id(uint8_t * session_id, uint8_t * len);
-int _gnutls_set_server_random(gnutls_session_t session, uint8_t * rnd);
+int _gnutls_set_server_random(gnutls_session_t session, int version, uint8_t * rnd);
 int _gnutls_set_client_random(gnutls_session_t session, uint8_t * rnd);
 
 int _gnutls_find_pk_algos_in_ciphersuites(uint8_t * data, int datalen);
index a199e420bc87056ccba7d5e881d00463fa8e84b6..0b9daf35908afe4206400b20be5538db4db6aac5 100644 (file)
@@ -624,6 +624,7 @@ typedef enum {
  * @GNUTLS_TLS1: Same as %GNUTLS_TLS1_0.
  * @GNUTLS_TLS1_1: TLS version 1.1.
  * @GNUTLS_TLS1_2: TLS version 1.2.
+ * @GNUTLS_TLS1_3: TLS version 1.3.
  * @GNUTLS_DTLS1_0: DTLS version 1.0.
  * @GNUTLS_DTLS1_2: DTLS version 1.2.
  * @GNUTLS_DTLS0_9: DTLS version 0.9 (Cisco AnyConnect / OpenSSL 0.9.8e).
@@ -638,6 +639,7 @@ typedef enum {
        GNUTLS_TLS1 = GNUTLS_TLS1_0,
        GNUTLS_TLS1_1 = 3,
        GNUTLS_TLS1_2 = 4,
+       GNUTLS_TLS1_3 = 5,
 
        GNUTLS_DTLS0_9 = 200,
        GNUTLS_DTLS1_0 = 201,   /* 201 */
index 2887550255611e2fca897d82f94e8a435c0b64b2..c66ad7743958682aa524e7993d117d6f513406c7 100644 (file)
@@ -96,6 +96,7 @@ _gnutls_read_client_hello_v2(gnutls_session_t session, uint8_t * data,
        gnutls_protocol_t adv_version;
        uint8_t rnd[GNUTLS_RANDOM_SIZE], major, minor;
        int len = datalen;
+       int neg_version;
        uint16_t challenge;
        uint8_t session_id[GNUTLS_MAX_SESSION_ID_SIZE];
 
@@ -116,6 +117,7 @@ _gnutls_read_client_hello_v2(gnutls_session_t session, uint8_t * data,
                gnutls_assert();
                return ret;
        }
+       neg_version = ret;
 
        pos += 2;
 
@@ -211,7 +213,7 @@ _gnutls_read_client_hello_v2(gnutls_session_t session, uint8_t * data,
                return gnutls_assert_val(ret);
 
        /* generate server random value */
-       ret = _gnutls_set_server_random(session, NULL);
+       ret = _gnutls_set_server_random(session, neg_version, NULL);
        if (ret < 0)
                return gnutls_assert_val(ret);