diff options
-rw-r--r-- | lib/algorithms.h | 2 | ||||
-rw-r--r-- | lib/algorithms/protocols.c | 70 | ||||
-rw-r--r-- | lib/gnutls_int.h | 1 | ||||
-rw-r--r-- | lib/handshake.c | 20 | ||||
-rw-r--r-- | lib/handshake.h | 2 | ||||
-rw-r--r-- | lib/priority.c | 5 | ||||
-rw-r--r-- | lib/sslv2_compat.c | 2 |
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; |