Blame lib/ext/supported_versions.c

Packit aea12f
/*
Packit aea12f
 * Copyright (C) 2001-2012 Free Software Foundation, Inc.
Packit aea12f
 * Copyright (C) 2017-2018 Red Hat, Inc.
Packit aea12f
 *
Packit aea12f
 * Author: Nikos Mavrogiannopoulos
Packit aea12f
 *
Packit aea12f
 * This file is part of GnuTLS.
Packit aea12f
 *
Packit aea12f
 * The GnuTLS is free software; you can redistribute it and/or
Packit aea12f
 * modify it under the terms of the GNU Lesser General Public License
Packit aea12f
 * as published by the Free Software Foundation; either version 2.1 of
Packit aea12f
 * the License, or (at your option) any later version.
Packit aea12f
 *
Packit aea12f
 * This library is distributed in the hope that it will be useful, but
Packit aea12f
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit aea12f
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit aea12f
 * Lesser General Public License for more details.
Packit aea12f
 *
Packit aea12f
 * You should have received a copy of the GNU Lesser General Public License
Packit aea12f
 * along with this program.  If not, see <https://www.gnu.org/licenses/>
Packit aea12f
 *
Packit aea12f
 */
Packit aea12f
Packit aea12f
/* This file contains the code for the Max Record Size TLS extension.
Packit aea12f
 */
Packit aea12f
Packit aea12f
#include "gnutls_int.h"
Packit aea12f
#include "errors.h"
Packit aea12f
#include "num.h"
Packit aea12f
#include <hello_ext.h>
Packit aea12f
#include <ext/supported_versions.h>
Packit aea12f
#include "handshake.h"
Packit aea12f
Packit aea12f
static int supported_versions_recv_params(gnutls_session_t session,
Packit aea12f
					  const uint8_t * data,
Packit aea12f
					  size_t data_size);
Packit aea12f
static int supported_versions_send_params(gnutls_session_t session,
Packit aea12f
					  gnutls_buffer_st * extdata);
Packit aea12f
Packit aea12f
const hello_ext_entry_st ext_mod_supported_versions = {
Packit aea12f
	.name = "Supported Versions",
Packit aea12f
	.tls_id = 43,
Packit aea12f
	.gid = GNUTLS_EXTENSION_SUPPORTED_VERSIONS,
Packit aea12f
	.validity = GNUTLS_EXT_FLAG_CLIENT_HELLO | GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO |
Packit aea12f
		    GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO | GNUTLS_EXT_FLAG_HRR|GNUTLS_EXT_FLAG_TLS,
Packit aea12f
	.parse_type = GNUTLS_EXT_VERSION_NEG, /* force parsing prior to EXT_TLS extensions */
Packit aea12f
	.recv_func = supported_versions_recv_params,
Packit aea12f
	.send_func = supported_versions_send_params,
Packit aea12f
	.pack_func = NULL,
Packit aea12f
	.unpack_func = NULL,
Packit aea12f
	.deinit_func = NULL,
Packit aea12f
	.cannot_be_overriden = 1
Packit aea12f
};
Packit aea12f
Packit aea12f
static int
Packit aea12f
supported_versions_recv_params(gnutls_session_t session,
Packit 5407aa
			       const uint8_t * data, size_t data_size)
Packit aea12f
{
Packit aea12f
	const version_entry_st *vers;
Packit aea12f
	uint8_t major, minor;
Packit 5407aa
	size_t bytes;
Packit aea12f
	int ret;
Packit aea12f
Packit aea12f
	if (session->security_parameters.entity == GNUTLS_SERVER) {
Packit aea12f
		const version_entry_st *old_vers;
Packit aea12f
Packit aea12f
		vers = _gnutls_version_max(session);
Packit aea12f
		old_vers = get_version(session);
Packit aea12f
Packit aea12f
		/* do not parse this extension when we haven't TLS1.3
Packit aea12f
		 * enabled. That is because we cannot handle earlier protocol
Packit aea12f
		 * negotiotation (such as SSL3.0) with this */
Packit aea12f
		if (vers && !vers->tls13_sem)
Packit aea12f
			return 0;
Packit aea12f
Packit aea12f
		DECR_LEN(data_size, 1);
Packit aea12f
		bytes = data[0];
Packit aea12f
		data++;
Packit aea12f
Packit aea12f
		if (bytes % 2 == 1)
Packit aea12f
			return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
Packit aea12f
Packit aea12f
		DECR_LEN(data_size, bytes);
Packit aea12f
Packit aea12f
		if (data_size != 0)
Packit aea12f
			return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
Packit aea12f
Packit aea12f
		while (bytes > 0) {
Packit aea12f
			major = data[0];
Packit aea12f
			minor = data[1];
Packit aea12f
			data += 2;
Packit aea12f
			bytes -= 2;
Packit aea12f
Packit aea12f
			_gnutls_handshake_log("EXT[%p]: Found version: %d.%d\n",
Packit aea12f
					      session, (int)major, (int)minor);
Packit aea12f
Packit aea12f
			if (_gnutls_nversion_is_supported(session, major, minor)) {
Packit aea12f
				session->security_parameters.pversion = nversion_to_entry(major, minor);
Packit aea12f
Packit aea12f
				_gnutls_handshake_log("EXT[%p]: Negotiated version: %d.%d\n",
Packit aea12f
						      session, (int)major, (int)minor);
Packit aea12f
Packit aea12f
				vers = get_version(session);
Packit aea12f
				if (old_vers != vers) {
Packit aea12f
					/* regenerate the random value to set
Packit aea12f
					 * downgrade sentinel if necessary
Packit aea12f
					 */
Packit aea12f
					ret = _gnutls_gen_server_random(session,
Packit aea12f
									vers->id);
Packit aea12f
					if (ret < 0)
Packit aea12f
						return gnutls_assert_val(ret);
Packit aea12f
				}
Packit aea12f
Packit aea12f
				return 0;
Packit aea12f
			}
Packit aea12f
		}
Packit aea12f
Packit aea12f
		/* if we are here, none of the versions were acceptable */
Packit aea12f
		return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
Packit aea12f
	} else { /* client */
Packit aea12f
Packit aea12f
		if (!have_creds_for_tls13(session)) {
Packit aea12f
			/* if we don't have certificate or PSK (which work under TLS1.3)
Packit aea12f
			 * don't try to negotiate version using the extension. We fallback
Packit aea12f
			 * instead to the normal TLS negotiation which has a cap on TLS1.2.
Packit aea12f
			 */
Packit aea12f
			return 0;
Packit aea12f
		}
Packit aea12f
Packit aea12f
		DECR_LEN(data_size, 2);
Packit aea12f
Packit aea12f
		if (data_size != 0)
Packit aea12f
			return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
Packit aea12f
Packit aea12f
		major = data[0];
Packit aea12f
		minor = data[1];
Packit aea12f
Packit aea12f
		vers = nversion_to_entry(major, minor);
Packit aea12f
		if (!vers)
Packit aea12f
			return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
Packit aea12f
Packit aea12f
		set_adv_version(session, major, minor);
Packit aea12f
Packit aea12f
		_gnutls_handshake_log("EXT[%p]: Negotiated version: %d.%d\n",
Packit aea12f
				      session, (int)major, (int)minor);
Packit aea12f
Packit aea12f
		if (!vers->tls13_sem)
Packit aea12f
			return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
Packit aea12f
Packit aea12f
		ret = _gnutls_negotiate_version(session, major, minor, 1);
Packit aea12f
		if (ret < 0) {
Packit aea12f
			gnutls_assert();
Packit aea12f
			return ret;
Packit aea12f
		}
Packit aea12f
	}
Packit aea12f
Packit aea12f
	return 0;
Packit aea12f
}
Packit aea12f
Packit aea12f
/* returns data_size or a negative number on failure
Packit aea12f
 */
Packit aea12f
static int
Packit aea12f
supported_versions_send_params(gnutls_session_t session,
Packit aea12f
			       gnutls_buffer_st * extdata)
Packit aea12f
{
Packit aea12f
	uint8_t versions[32];
Packit aea12f
	size_t versions_size;
Packit aea12f
	const version_entry_st *vers;
Packit aea12f
	int ret;
Packit aea12f
Packit aea12f
	/* this function sends the client extension data (dnsname) */
Packit aea12f
	if (session->security_parameters.entity == GNUTLS_CLIENT) {
Packit aea12f
		vers = _gnutls_version_max(session);
Packit aea12f
Packit aea12f
		/* Do not advertise this extension if we are not doing certificate
Packit aea12f
		 * or PSK authentication; i.e., do not try to do TLS1.3 if we have
Packit aea12f
		 * credentials which do not fit it. */
Packit aea12f
		if (!have_creds_for_tls13(session)) {
Packit aea12f
			/* if we don't have certificate or PSK (which work under TLS1.3)
Packit aea12f
			 * don't try to negotiate version using the extension. We fallback
Packit aea12f
			 * instead to the normal TLS negotiation which has a cap on TLS1.2.
Packit aea12f
			 */
Packit aea12f
			return 0;
Packit aea12f
		}
Packit aea12f
Packit aea12f
		/* do not advertise this extension when we haven't TLS1.3
Packit aea12f
		 * enabled. */
Packit aea12f
		if (vers && !vers->tls13_sem)
Packit aea12f
			return 0;
Packit aea12f
Packit aea12f
		ret = _gnutls_write_supported_versions(session, versions, sizeof(versions));
Packit aea12f
		if (ret <= 0) /* if this function doesn't succeed do not send anything */
Packit aea12f
			return 0;
Packit aea12f
Packit aea12f
		versions_size = ret;
Packit aea12f
Packit aea12f
		ret = _gnutls_buffer_append_data_prefix(extdata, 8, versions, versions_size);
Packit aea12f
		if (ret < 0)
Packit aea12f
			return gnutls_assert_val(ret);
Packit aea12f
Packit aea12f
		return versions_size+2;
Packit aea12f
	} else {
Packit aea12f
		vers = get_version(session);
Packit aea12f
		if (unlikely(vers == NULL))
Packit aea12f
			return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
Packit aea12f
Packit aea12f
		/* don't use this extension to negotiate versions <= 1.2,
Packit aea12f
		 * pretend we don't support it, so that we use a single
Packit aea12f
		 * code path to negotiate these protocols. */
Packit aea12f
		if (!vers->tls13_sem)
Packit aea12f
			return 0;
Packit aea12f
Packit aea12f
		ret = _gnutls_buffer_append_data(extdata, &vers->major, 1);
Packit aea12f
		if (ret < 0)
Packit aea12f
			return gnutls_assert_val(ret);
Packit aea12f
Packit aea12f
		ret = _gnutls_buffer_append_data(extdata, &vers->minor, 1);
Packit aea12f
		if (ret < 0)
Packit aea12f
			return gnutls_assert_val(ret);
Packit aea12f
Packit aea12f
		return 2;
Packit aea12f
	}
Packit aea12f
Packit aea12f
	return 0;
Packit aea12f
}