summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/algorithms.h2
-rw-r--r--lib/algorithms/protocols.c70
-rw-r--r--lib/gnutls_int.h1
-rw-r--r--lib/handshake.c20
-rw-r--r--lib/handshake.h2
-rw-r--r--lib/priority.c5
-rw-r--r--lib/sslv2_compat.c2
7 files changed, 75 insertions, 27 deletions
diff --git a/lib/algorithms.h b/lib/algorithms.h
index ebdef8880f..bb1d4a5a6c 100644
--- a/lib/algorithms.h
+++ b/lib/algorithms.h
@@ -40,7 +40,7 @@
/* Functions for version handling. */
const version_entry_st *version_to_entry(gnutls_protocol_t version);
const version_entry_st *_gnutls_version_lowest(gnutls_session_t session);
-gnutls_protocol_t _gnutls_version_max(gnutls_session_t session);
+gnutls_protocol_t _gnutls_legacy_version_max(gnutls_session_t session);
int _gnutls_version_priority(gnutls_session_t session,
gnutls_protocol_t version);
int _gnutls_version_is_supported(gnutls_session_t session,
diff --git a/lib/algorithms/protocols.c b/lib/algorithms/protocols.c
index a70c3e5815..0b035adddf 100644
--- a/lib/algorithms/protocols.c
+++ b/lib/algorithms/protocols.c
@@ -27,7 +27,7 @@
/* TLS Versions */
static const version_entry_st sup_versions[] = {
- {.name = "SSL3.0",
+ {.name = "SSL3.0",
.id = GNUTLS_SSL3,
.age = 0,
.major = 3,
@@ -39,9 +39,10 @@ static const version_entry_st sup_versions[] = {
.selectable_sighash = 0,
.selectable_prf = 0,
.obsolete = 1,
+ .only_extension = 0,
.false_start = 0
},
- {.name = "TLS1.0",
+ {.name = "TLS1.0",
.id = GNUTLS_TLS1,
.age = 1,
.major = 3,
@@ -53,9 +54,10 @@ static const version_entry_st sup_versions[] = {
.selectable_sighash = 0,
.selectable_prf = 0,
.obsolete = 0,
+ .only_extension = 0,
.false_start = 0
},
- {.name = "TLS1.1",
+ {.name = "TLS1.1",
.id = GNUTLS_TLS1_1,
.age = 2,
.major = 3,
@@ -67,9 +69,10 @@ static const version_entry_st sup_versions[] = {
.selectable_sighash = 0,
.selectable_prf = 0,
.obsolete = 0,
+ .only_extension = 0,
.false_start = 0
},
- {.name = "TLS1.2",
+ {.name = "TLS1.2",
.id = GNUTLS_TLS1_2,
.age = 3,
.major = 3,
@@ -81,8 +84,24 @@ static const version_entry_st sup_versions[] = {
.selectable_sighash = 1,
.selectable_prf = 1,
.obsolete = 0,
+ .only_extension = 0,
.false_start = 1
},
+ {.name = "TLS1.3",
+ .id = GNUTLS_TLS1_3,
+ .age = 4,
+ .major = 3,
+ .minor = 4,
+ .transport = GNUTLS_STREAM,
+ .supported = 1,
+ .explicit_iv = 1,
+ .extensions = 1,
+ .selectable_sighash = 1,
+ .selectable_prf = 1,
+ .obsolete = 0,
+ .only_extension = 1,
+ .false_start = 0 /* doesn't make sense */
+ },
{.name = "DTLS0.9", /* Cisco AnyConnect (based on about OpenSSL 0.9.8e) */
.id = GNUTLS_DTLS0_9,
.age = 200,
@@ -95,9 +114,10 @@ static const version_entry_st sup_versions[] = {
.selectable_sighash = 0,
.selectable_prf = 0,
.obsolete = 0,
+ .only_extension = 0,
.false_start = 0
},
- {.name = "DTLS1.0",
+ {.name = "DTLS1.0",
.id = GNUTLS_DTLS1_0,
.age = 201,
.major = 254,
@@ -109,9 +129,10 @@ static const version_entry_st sup_versions[] = {
.selectable_sighash = 0,
.selectable_prf = 0,
.obsolete = 0,
+ .only_extension = 0,
.false_start = 0
},
- {.name = "DTLS1.2",
+ {.name = "DTLS1.2",
.id = GNUTLS_DTLS1_2,
.age = 202,
.major = 254,
@@ -123,6 +144,7 @@ static const version_entry_st sup_versions[] = {
.selectable_sighash = 1,
.selectable_prf = 1,
.obsolete = 0,
+ .only_extension = 0,
.false_start = 1
},
{0, 0, 0, 0, 0}
@@ -198,9 +220,9 @@ const version_entry_st *_gnutls_version_lowest(gnutls_session_t session)
/* Returns the maximum version in the priorities
*/
-static const version_entry_st *version_max(gnutls_session_t session)
+static const version_entry_st *legacy_version_max(gnutls_session_t session)
{
- int max_proto = _gnutls_version_max(session);
+ int max_proto = _gnutls_legacy_version_max(session);
if (max_proto < 0)
return NULL;
@@ -208,19 +230,41 @@ static const version_entry_st *version_max(gnutls_session_t session)
return version_to_entry(max_proto);
}
-gnutls_protocol_t _gnutls_version_max(gnutls_session_t session)
+gnutls_protocol_t _gnutls_legacy_version_max(gnutls_session_t session)
{
unsigned int i, max = 0x00;
gnutls_protocol_t cur_prot;
+ const version_entry_st *p;
for (i = 0; i < session->internals.priorities->protocol.algorithms;
i++) {
cur_prot =
session->internals.priorities->protocol.priority[i];
- if (cur_prot > max
- && _gnutls_version_is_supported(session, cur_prot))
- max = cur_prot;
+ for (p = sup_versions; p->name != NULL; p++)
+ if(p->id == cur_prot) {
+#ifndef ENABLE_SSL3
+ if (p->obsolete != 0)
+ break;
+#endif
+ if (!p->supported || p->transport != session->internals.transport)
+ break;
+
+ if (p->only_extension != 0) {
+ /* TLS 1.3 or later found */
+ if (p->transport == GNUTLS_STREAM) {
+ return GNUTLS_TLS1_2;
+ } else {
+ return GNUTLS_DTLS1_2;
+ }
+ }
+
+ if (!p->only_extension && cur_prot > max) {
+ max = cur_prot;
+ }
+ break;
+ }
+ }
}
if (max == 0x00)
@@ -235,7 +279,7 @@ unsigned _gnutls_version_is_too_high(gnutls_session_t session, uint8_t major, ui
{
const version_entry_st *e;
- e = version_max(session);
+ e = legacy_version_max(session);
if (e == NULL) /* we don't know; but that means something is unconfigured */
return 1;
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index 17c0486999..8cc8e8c0bc 100644
--- a/lib/gnutls_int.h
+++ b/lib/gnutls_int.h
@@ -519,6 +519,7 @@ typedef struct {
* otherwise it prevents this protocol from being set as record version */
bool obsolete;
bool false_start; /* That version can be used with false start */
+ bool only_extension; /* negotiated only with an extension */
} version_entry_st;
diff --git a/lib/handshake.c b/lib/handshake.c
index 254bf75d48..1804bf5b81 100644
--- a/lib/handshake.c
+++ b/lib/handshake.c
@@ -181,10 +181,9 @@ int _gnutls_set_client_random(gnutls_session_t session, uint8_t * rnd)
resumed_security_parameters.client_random,
GNUTLS_RANDOM_SIZE);
} else {
- ret =
- gnutls_rnd(GNUTLS_RND_NONCE,
- session->security_parameters.client_random,
- GNUTLS_RANDOM_SIZE);
+ ret = gnutls_rnd(GNUTLS_RND_NONCE,
+ session->security_parameters.client_random,
+ GNUTLS_RANDOM_SIZE);
if (ret < 0)
return gnutls_assert_val(ret);
}
@@ -361,12 +360,11 @@ _gnutls_finished(gnutls_session_t session, int type, void *ret,
/* returns the 0 on success or a negative error code.
*/
int
-_gnutls_negotiate_version(gnutls_session_t session,
+_gnutls_negotiate_legacy_version(gnutls_session_t session,
gnutls_protocol_t adv_version, uint8_t major, uint8_t minor)
{
int ret;
-
/* if we do not support that version */
if (adv_version == GNUTLS_VERSION_UNKNOWN || _gnutls_version_is_supported(session, adv_version) == 0) {
/* if we get an unknown/unsupported version, then fail if the version we
@@ -377,7 +375,7 @@ _gnutls_negotiate_version(gnutls_session_t session,
/* If he requested something we do not support
* then we send him the highest we support.
*/
- ret = _gnutls_version_max(session);
+ ret = _gnutls_legacy_version_max(session);
if (ret == GNUTLS_VERSION_UNKNOWN) {
/* this check is not really needed.
*/
@@ -419,7 +417,7 @@ _gnutls_user_hello_func(gnutls_session_t session,
/* Here we need to renegotiate the version since the callee might
* have disabled some TLS versions.
*/
- ret = _gnutls_negotiate_version(session, adv_version, major, minor);
+ ret = _gnutls_negotiate_legacy_version(session, adv_version, major, minor);
if (ret < 0) {
gnutls_assert();
return ret;
@@ -457,7 +455,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_version(session, adv_version, major, minor);
+ neg_version = _gnutls_negotiate_legacy_version(session, adv_version, major, minor);
if (neg_version < 0) {
gnutls_assert();
return neg_version;
@@ -875,7 +873,7 @@ _gnutls_server_select_suite(gnutls_session_t session, uint8_t * data,
/* TLS_FALLBACK_SCSV */
if (data[i] == GNUTLS_FALLBACK_SCSV_MAJOR &&
data[i + 1] == GNUTLS_FALLBACK_SCSV_MINOR) {
- unsigned max = _gnutls_version_max(session);
+ unsigned max = _gnutls_legacy_version_max(session);
_gnutls_handshake_log
("HSK[%p]: Received fallback CS\n",
session);
@@ -1644,7 +1642,7 @@ static int send_client_hello(gnutls_session_t session, int again)
hver = get_version(session);
else /* new handshake. just get the max */
hver =
- version_to_entry(_gnutls_version_max
+ version_to_entry(_gnutls_legacy_version_max
(session));
} else {
/* we are resuming a session */
diff --git a/lib/handshake.h b/lib/handshake.h
index c6b393a205..3f9b55faa0 100644
--- a/lib/handshake.h
+++ b/lib/handshake.h
@@ -40,7 +40,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_version(gnutls_session_t session,
+int _gnutls_negotiate_legacy_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);
diff --git a/lib/priority.c b/lib/priority.c
index ff49875e7b..5a00c3aa7d 100644
--- a/lib/priority.c
+++ b/lib/priority.c
@@ -161,13 +161,18 @@ static const int protocol_priority[] = {
0
};
+/* contains all the supported TLS protocols, intended to be used for eliminating them
+ */
static const int stream_protocol_priority[] = {
+ GNUTLS_TLS1_3,
GNUTLS_TLS1_2,
GNUTLS_TLS1_1,
GNUTLS_TLS1_0,
0
};
+/* contains all the supported DTLS protocols, intended to be used for eliminating them
+ */
static const int dgram_protocol_priority[] = {
GNUTLS_DTLS1_2,
GNUTLS_DTLS1_0,
diff --git a/lib/sslv2_compat.c b/lib/sslv2_compat.c
index c66ad77439..5ec5a0ad34 100644
--- a/lib/sslv2_compat.c
+++ b/lib/sslv2_compat.c
@@ -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_version(session, adv_version, major, minor);
+ ret = _gnutls_negotiate_legacy_version(session, adv_version, major, minor);
if (ret < 0) {
gnutls_assert();
return ret;