summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@redhat.com>2017-06-19 11:57:22 +0200
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2017-09-11 11:08:54 +0200
commit40894ecd211c32120911d6d39a47f406d408b7a5 (patch)
treef2735cba531736356c7a0d429e29bc6ce06a6383
parentcf7e5a29864a84f47a5638530bb4f661957282b2 (diff)
downloadgnutls-40894ecd211c32120911d6d39a47f406d408b7a5.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 f96f949a3e..b7aa008f7c 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);
@@ -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);
diff --git a/lib/handshake.h b/lib/handshake.h
index 41a2e9d32a..c6b393a205 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 2887550255..c66ad77439 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);