summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@redhat.com>2017-06-19 11:57:22 +0200
committerNikos Mavrogiannopoulos <nmav@redhat.com>2017-08-23 09:39:55 +0200
commit93c1488255a20111cc7e3643deda4ff41660a08c (patch)
treeeecab10fedc7294f4ebbb49d8dc98052f0348aed
parent6a3dfd4614e76184224d807ab53556a7010b7947 (diff)
downloadgnutls-93c1488255a20111cc7e3643deda4ff41660a08c.tar.gz
Added TLS 1.3 Hello message random generation
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>
-rw-r--r--lib/handshake.c99
-rw-r--r--lib/handshake.h2
-rw-r--r--lib/includes/gnutls/gnutls.h.in2
-rw-r--r--lib/sslv2_compat.c4
4 files changed, 54 insertions, 53 deletions
diff --git a/lib/handshake.c b/lib/handshake.c
index 9a38cf8242..af6e0a25b6 100644
--- a/lib/handshake.c
+++ b/lib/handshake.c
@@ -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);
@@ -1510,7 +1507,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);
diff --git a/lib/handshake.h b/lib/handshake.h
index 3e24c2aeb2..106a6f4742 100644
--- a/lib/handshake.h
+++ b/lib/handshake.h
@@ -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);
diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in
index d65318bbbc..c59c8abf21 100644
--- a/lib/includes/gnutls/gnutls.h.in
+++ b/lib/includes/gnutls/gnutls.h.in
@@ -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 */
diff --git a/lib/sslv2_compat.c b/lib/sslv2_compat.c
index 4f4b8f39fa..cfe76c1728 100644
--- a/lib/sslv2_compat.c
+++ b/lib/sslv2_compat.c
@@ -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);