_gnutls_negotiate_legacy_version(gnutls_session_t session,
gnutls_protocol_t adv_version, uint8_t major, uint8_t minor)
{
- int ret;
+ const version_entry_st *vers;
- /* if we do not support that version */
+ /* if we do not support that version, unless that version is TLS 1.2;
+ * TLS 1.2 is handled separately because it is always advertized under TLS 1.3 or later */
if (adv_version == GNUTLS_VERSION_UNKNOWN || _gnutls_version_is_supported(session, adv_version) == 0) {
+
+ if (adv_version == GNUTLS_TLS1_2) {
+ vers = _gnutls_version_max(session);
+ if (vers->id >= GNUTLS_TLS1_2) {
+ if (_gnutls_set_current_version(session, adv_version) < 0)
+ return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
+ return adv_version;
+ }
+ }
+
/* if we get an unknown/unsupported version, then fail if the version we
* got is too low to be supported */
if (!_gnutls_version_is_too_high(session, major, minor))
/* If he requested something we do not support
* then we send him the highest we support.
*/
- ret = _gnutls_legacy_version_max(session);
- if (ret == GNUTLS_VERSION_UNKNOWN) {
+ vers = _gnutls_legacy_version_max(session);
+ if (vers == NULL) {
/* this check is not really needed.
*/
gnutls_assert();
return GNUTLS_E_UNKNOWN_CIPHER_SUITE;
}
- } else {
- ret = adv_version;
- }
- if (_gnutls_set_current_version(session, ret) < 0)
- return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
+ session->security_parameters.pversion = vers;
- return ret;
+ return vers->id;
+ } else {
+ if (_gnutls_set_current_version(session, adv_version) < 0)
+ return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
+
+ return adv_version;
+ }
}
/* This function returns:
/* TLS_FALLBACK_SCSV */
if (data[i] == GNUTLS_FALLBACK_SCSV_MAJOR &&
data[i + 1] == GNUTLS_FALLBACK_SCSV_MINOR) {
- unsigned max = _gnutls_legacy_version_max(session);
+ const version_entry_st *vers = get_version(session);
+ const version_entry_st *max = _gnutls_version_max(session);
+
_gnutls_handshake_log
("HSK[%p]: Received fallback CS\n",
session);
- if (gnutls_protocol_get_version(session) != max)
+ if (vers != max)
return gnutls_assert_val(GNUTLS_E_INAPPROPRIATE_FALLBACK);
} else if (!scsv_only) {
if (peer_clist.size < MAX_CIPHERSUITE_SIZE) {
if (rehandshake) /* already negotiated version thus version_max == negotiated version */
hver = get_version(session);
else /* new handshake. just get the max */
- hver =
- version_to_entry(_gnutls_legacy_version_max
- (session));
+ hver = _gnutls_legacy_version_max(session);
} else {
/* we are resuming a session */
hver =