summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/handshake.c42
-rw-r--r--lib/priority.c3
2 files changed, 32 insertions, 13 deletions
diff --git a/lib/handshake.c b/lib/handshake.c
index 08481cca07..b513872ec3 100644
--- a/lib/handshake.c
+++ b/lib/handshake.c
@@ -491,7 +491,8 @@ _gnutls_user_hello_func(gnutls_session_t session,
uint8_t major, uint8_t minor)
{
int ret, sret = 0;
- const version_entry_st *vers;
+ const version_entry_st *vers, *old_vers;
+ const version_entry_st *new_max;
if (session->internals.user_hello_func != NULL) {
ret = session->internals.user_hello_func(session);
@@ -504,17 +505,34 @@ _gnutls_user_hello_func(gnutls_session_t session,
return ret;
}
- vers = get_version(session);
- if (!vers->tls13_sem) {
- /* Here we need to renegotiate the version since the callee might
- * have disabled some TLS versions. We only do it for TLS1.2 or
- * earlier, as TLS1.3 uses a different set of ciphersuites, and
- * thus we cannot fallback.
- */
- ret = _gnutls_negotiate_version(session, major, minor, 0);
- if (ret < 0) {
- gnutls_assert();
- return ret;
+ /* This callback is often used to switch the priority string of the
+ * server, and that includes switching version which we have already
+ * negotiated; note that this doesn't apply when resuming as the version
+ * negotiation is already complete. */
+ if (session->internals.resumed != RESUME_TRUE) {
+ new_max = _gnutls_version_max(session);
+ old_vers = get_version(session);
+
+ if (!old_vers->tls13_sem || (new_max && !new_max->tls13_sem)) {
+#if GNUTLS_TLS_VERSION_MAX != GNUTLS_TLS1_3
+# error "Need to update the following logic"
+#endif
+ /* Here we need to renegotiate the version since the callee might
+ * have disabled some TLS versions. This logic does not cope for
+ * protocols later than TLS1.3 if they have the tls13_sem set */
+ ret = _gnutls_negotiate_version(session, major, minor, 0);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ vers = get_version(session);
+ if (old_vers != vers) {
+ /* at this point we need to regenerate the random value to
+ * avoid the peer detecting this session as a rollback
+ * attempt. */
+ ret = _gnutls_gen_server_random(session, vers->id);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+ }
}
}
}
diff --git a/lib/priority.c b/lib/priority.c
index a9f0403d26..afd4b1a680 100644
--- a/lib/priority.c
+++ b/lib/priority.c
@@ -593,7 +593,8 @@ gnutls_priority_set(gnutls_session_t session, gnutls_priority_t priority)
/* set the current version to the first in the chain.
* This will be overridden later.
*/
- if (session->internals.priorities->protocol.algorithms > 0) {
+ if (session->internals.priorities->protocol.algorithms > 0 &&
+ !session->internals.handshake_in_progress) {
if (_gnutls_set_current_version(session,
session->internals.priorities->
protocol.priority[0]) < 0) {