Blame lib/handshake.c

Packit 549fdc
/*
Packit 549fdc
 * Copyright (C) 2000-2016 Free Software Foundation, Inc.
Packit 549fdc
 * Copyright (C) 2015-2017 Red Hat, Inc.
Packit 549fdc
 *
Packit 549fdc
 * Author: Nikos Mavrogiannopoulos
Packit 549fdc
 *
Packit 549fdc
 * This file is part of GnuTLS.
Packit 549fdc
 *
Packit 549fdc
 * The GnuTLS is free software; you can redistribute it and/or
Packit 549fdc
 * modify it under the terms of the GNU Lesser General Public License
Packit 549fdc
 * as published by the Free Software Foundation; either version 2.1 of
Packit 549fdc
 * the License, or (at your option) any later version.
Packit 549fdc
 *
Packit 549fdc
 * This library is distributed in the hope that it will be useful, but
Packit 549fdc
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 549fdc
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 549fdc
 * Lesser General Public License for more details.
Packit 549fdc
 *
Packit 549fdc
 * You should have received a copy of the GNU Lesser General Public License
Packit 549fdc
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
Packit 549fdc
 *
Packit 549fdc
 */
Packit 549fdc
Packit 549fdc
/* Functions that relate to the TLS handshake procedure.
Packit 549fdc
 */
Packit 549fdc
Packit 549fdc
#include "gnutls_int.h"
Packit 549fdc
#include "errors.h"
Packit 549fdc
#include "dh.h"
Packit 549fdc
#include "debug.h"
Packit 549fdc
#include "algorithms.h"
Packit 549fdc
#include "cipher.h"
Packit 549fdc
#include "buffers.h"
Packit 549fdc
#include "mbuffers.h"
Packit 549fdc
#include "kx.h"
Packit 549fdc
#include "handshake.h"
Packit 549fdc
#include "num.h"
Packit 549fdc
#include "hash_int.h"
Packit 549fdc
#include "db.h"
Packit 549fdc
#include "extensions.h"
Packit 549fdc
#include "supplemental.h"
Packit 549fdc
#include "auth.h"
Packit 549fdc
#include "sslv2_compat.h"
Packit 549fdc
#include <auth/cert.h>
Packit 549fdc
#include "constate.h"
Packit 549fdc
#include <record.h>
Packit 549fdc
#include <state.h>
Packit 549fdc
#include <ext/srp.h>
Packit 549fdc
#include <ext/session_ticket.h>
Packit 549fdc
#include <ext/status_request.h>
Packit 549fdc
#include <ext/safe_renegotiation.h>
Packit 549fdc
#include <auth/anon.h>		/* for gnutls_anon_server_credentials_t */
Packit 549fdc
#include <auth/psk.h>		/* for gnutls_psk_server_credentials_t */
Packit 549fdc
#include <random.h>
Packit 549fdc
#include <dtls.h>
Packit 549fdc
Packit 549fdc
#define TRUE 1
Packit 549fdc
#define FALSE 0
Packit 549fdc
Packit 549fdc
static int check_if_null_comp_present(gnutls_session_t session,
Packit 549fdc
					     uint8_t * data, int datalen);
Packit 549fdc
static int handshake_client(gnutls_session_t session);
Packit 549fdc
static int handshake_server(gnutls_session_t session);
Packit 549fdc
Packit 549fdc
static int
Packit 549fdc
read_server_hello(gnutls_session_t session,
Packit 549fdc
		  uint8_t * data, int datalen);
Packit 549fdc
Packit 549fdc
static int
Packit 549fdc
recv_handshake_final(gnutls_session_t session, int init);
Packit 549fdc
static int
Packit 549fdc
send_handshake_final(gnutls_session_t session, int init);
Packit 549fdc
Packit 549fdc
/* Empties but does not free the buffer
Packit 549fdc
 */
Packit 549fdc
static inline void
Packit 549fdc
handshake_hash_buffer_empty(gnutls_session_t session)
Packit 549fdc
{
Packit 549fdc
Packit 549fdc
	_gnutls_buffers_log("BUF[HSK]: Emptied buffer\n");
Packit 549fdc
Packit 549fdc
	session->internals.used_exts_size = 0;
Packit 549fdc
	session->internals.handshake_hash_buffer_prev_len = 0;
Packit 549fdc
	session->internals.handshake_hash_buffer.length = 0;
Packit 549fdc
	return;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
static int
Packit 549fdc
handshake_hash_add_recvd(gnutls_session_t session,
Packit 549fdc
				 gnutls_handshake_description_t recv_type,
Packit 549fdc
				 uint8_t * header, uint16_t header_size,
Packit 549fdc
				 uint8_t * dataptr, uint32_t datalen);
Packit 549fdc
Packit 549fdc
static int
Packit 549fdc
handshake_hash_add_sent(gnutls_session_t session,
Packit 549fdc
				gnutls_handshake_description_t type,
Packit 549fdc
				uint8_t * dataptr, uint32_t datalen);
Packit 549fdc
Packit 549fdc
static int
Packit 549fdc
recv_hello_verify_request(gnutls_session_t session,
Packit 549fdc
				  uint8_t * data, int datalen);
Packit 549fdc
Packit 549fdc
Packit 549fdc
/* Clears the handshake hash buffers and handles.
Packit 549fdc
 */
Packit 549fdc
void _gnutls_handshake_hash_buffers_clear(gnutls_session_t session)
Packit 549fdc
{
Packit 549fdc
	session->internals.handshake_hash_buffer_prev_len = 0;
Packit 549fdc
	session->internals.handshake_hash_buffer_client_kx_len = 0;
Packit 549fdc
	_gnutls_buffer_clear(&session->internals.handshake_hash_buffer);
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/* this will copy the required values for resuming to
Packit 549fdc
 * internals, and to security_parameters.
Packit 549fdc
 * this will keep as less data to security_parameters.
Packit 549fdc
 */
Packit 549fdc
static int resume_copy_required_values(gnutls_session_t session)
Packit 549fdc
{
Packit 549fdc
	int ret;
Packit 549fdc
Packit 549fdc
	/* get the new random values */
Packit 549fdc
	memcpy(session->internals.resumed_security_parameters.
Packit 549fdc
	       server_random, session->security_parameters.server_random,
Packit 549fdc
	       GNUTLS_RANDOM_SIZE);
Packit 549fdc
	memcpy(session->internals.resumed_security_parameters.
Packit 549fdc
	       client_random, session->security_parameters.client_random,
Packit 549fdc
	       GNUTLS_RANDOM_SIZE);
Packit 549fdc
Packit 549fdc
	/* keep the ciphersuite and compression 
Packit 549fdc
	 * That is because the client must see these in our
Packit 549fdc
	 * hello message.
Packit 549fdc
	 */
Packit 549fdc
	ret = _gnutls_set_cipher_suite2(session,
Packit 549fdc
				       session->internals.
Packit 549fdc
				       resumed_security_parameters.
Packit 549fdc
				       cs);
Packit 549fdc
	if (ret < 0)
Packit 549fdc
		return gnutls_assert_val(ret);
Packit 549fdc
Packit 549fdc
	/* or write_compression_algorithm
Packit 549fdc
	 * they are the same
Packit 549fdc
	 */
Packit 549fdc
Packit 549fdc
	session->security_parameters.entity =
Packit 549fdc
	    session->internals.resumed_security_parameters.entity;
Packit 549fdc
Packit 549fdc
	if (session->internals.resumed_security_parameters.pversion ==
Packit 549fdc
	    NULL)
Packit 549fdc
		return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
Packit 549fdc
Packit 549fdc
	if (_gnutls_set_current_version(session,
Packit 549fdc
				    session->internals.
Packit 549fdc
				    resumed_security_parameters.pversion->
Packit 549fdc
				    id) < 0)
Packit 549fdc
		return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
Packit 549fdc
Packit 549fdc
	session->security_parameters.cert_type =
Packit 549fdc
	    session->internals.resumed_security_parameters.cert_type;
Packit 549fdc
Packit 549fdc
	memcpy(session->security_parameters.session_id,
Packit 549fdc
	       session->internals.resumed_security_parameters.session_id,
Packit 549fdc
	       sizeof(session->security_parameters.session_id));
Packit 549fdc
	session->security_parameters.session_id_size =
Packit 549fdc
	    session->internals.resumed_security_parameters.session_id_size;
Packit 549fdc
Packit 549fdc
	return 0;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
Packit 549fdc
/* this function will produce GNUTLS_RANDOM_SIZE==32 bytes of random data
Packit 549fdc
 * and put it to dst.
Packit 549fdc
 */
Packit 549fdc
static int create_tls_random(uint8_t * dst)
Packit 549fdc
{
Packit 549fdc
	int ret;
Packit 549fdc
Packit 549fdc
	/* Use nonce rng level for the most of the
Packit 549fdc
	 * buffer except for the first 4 that are the
Packit 549fdc
	 * system's time.
Packit 549fdc
	 */
Packit 549fdc
Packit 549fdc
#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
Packit 549fdc
	/* When fuzzying avoid timing dependencies */
Packit 549fdc
	memset(dst, 1, 4);
Packit 549fdc
#else
Packit 549fdc
	uint32_t tim;
Packit 549fdc
Packit 549fdc
	tim = gnutls_time(NULL);
Packit 549fdc
	/* generate server random value */
Packit 549fdc
	_gnutls_write_uint32(tim, dst);
Packit 549fdc
#endif
Packit 549fdc
Packit 549fdc
	ret =
Packit 549fdc
	    gnutls_rnd(GNUTLS_RND_NONCE, &dst[3], GNUTLS_RANDOM_SIZE - 3);
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return ret;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	return 0;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
int _gnutls_set_client_random(gnutls_session_t session, uint8_t * rnd)
Packit 549fdc
{
Packit 549fdc
	int ret;
Packit 549fdc
Packit 549fdc
	if (rnd != NULL)
Packit 549fdc
		memcpy(session->security_parameters.client_random, rnd,
Packit 549fdc
		       GNUTLS_RANDOM_SIZE);
Packit 549fdc
	else {
Packit 549fdc
		/* no random given, we generate. */
Packit 549fdc
		if (session->internals.sc_random_set != 0) {
Packit 549fdc
			memcpy(session->security_parameters.client_random,
Packit 549fdc
			       session->internals.
Packit 549fdc
			       resumed_security_parameters.client_random,
Packit 549fdc
			       GNUTLS_RANDOM_SIZE);
Packit 549fdc
		} else {
Packit 549fdc
			ret =
Packit 549fdc
			    create_tls_random(session->
Packit 549fdc
					      security_parameters.
Packit 549fdc
					      client_random);
Packit 549fdc
			if (ret < 0)
Packit 549fdc
				return gnutls_assert_val(ret);
Packit 549fdc
		}
Packit 549fdc
	}
Packit 549fdc
	return 0;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
int _gnutls_set_server_random(gnutls_session_t session, uint8_t * rnd)
Packit 549fdc
{
Packit 549fdc
	int ret;
Packit 549fdc
Packit 549fdc
	if (rnd != NULL)
Packit 549fdc
		memcpy(session->security_parameters.server_random, rnd,
Packit 549fdc
		       GNUTLS_RANDOM_SIZE);
Packit 549fdc
	else {
Packit 549fdc
		/* no random given, we generate. */
Packit 549fdc
		if (session->internals.sc_random_set != 0) {
Packit 549fdc
			memcpy(session->security_parameters.server_random,
Packit 549fdc
			       session->internals.
Packit 549fdc
			       resumed_security_parameters.server_random,
Packit 549fdc
			       GNUTLS_RANDOM_SIZE);
Packit 549fdc
		} else {
Packit 549fdc
			ret =
Packit 549fdc
			    create_tls_random(session->
Packit 549fdc
					      security_parameters.
Packit 549fdc
					      server_random);
Packit 549fdc
			if (ret < 0)
Packit 549fdc
				return gnutls_assert_val(ret);
Packit 549fdc
		}
Packit 549fdc
	}
Packit 549fdc
	return 0;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
#ifdef ENABLE_SSL3
Packit 549fdc
/* Calculate The SSL3 Finished message
Packit 549fdc
 */
Packit 549fdc
#define SSL3_CLIENT_MSG "CLNT"
Packit 549fdc
#define SSL3_SERVER_MSG "SRVR"
Packit 549fdc
#define SSL_MSG_LEN 4
Packit 549fdc
static int
Packit 549fdc
_gnutls_ssl3_finished(gnutls_session_t session, int type, uint8_t * ret,
Packit 549fdc
		      int sending)
Packit 549fdc
{
Packit 549fdc
	digest_hd_st td_md5;
Packit 549fdc
	digest_hd_st td_sha;
Packit 549fdc
	const char *mesg;
Packit 549fdc
	int rc, len;
Packit 549fdc
Packit 549fdc
	if (sending)
Packit 549fdc
		len = session->internals.handshake_hash_buffer.length;
Packit 549fdc
	else
Packit 549fdc
		len = session->internals.handshake_hash_buffer_prev_len;
Packit 549fdc
Packit 549fdc
	rc = _gnutls_hash_init(&td_sha, hash_to_entry(GNUTLS_DIG_SHA1));
Packit 549fdc
	if (rc < 0)
Packit 549fdc
		return gnutls_assert_val(rc);
Packit 549fdc
Packit 549fdc
	rc = _gnutls_hash_init(&td_md5, hash_to_entry(GNUTLS_DIG_MD5));
Packit 549fdc
	if (rc < 0) {
Packit 549fdc
		_gnutls_hash_deinit(&td_sha, NULL);
Packit 549fdc
		return gnutls_assert_val(rc);
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	_gnutls_hash(&td_sha,
Packit 549fdc
		     session->internals.handshake_hash_buffer.data, len);
Packit 549fdc
	_gnutls_hash(&td_md5,
Packit 549fdc
		     session->internals.handshake_hash_buffer.data, len);
Packit 549fdc
Packit 549fdc
	if (type == GNUTLS_SERVER)
Packit 549fdc
		mesg = SSL3_SERVER_MSG;
Packit 549fdc
	else
Packit 549fdc
		mesg = SSL3_CLIENT_MSG;
Packit 549fdc
Packit 549fdc
	_gnutls_hash(&td_md5, mesg, SSL_MSG_LEN);
Packit 549fdc
	_gnutls_hash(&td_sha, mesg, SSL_MSG_LEN);
Packit 549fdc
Packit 549fdc
	rc = _gnutls_mac_deinit_ssl3_handshake(&td_md5, ret,
Packit 549fdc
					       session->security_parameters.
Packit 549fdc
					       master_secret,
Packit 549fdc
					       GNUTLS_MASTER_SIZE);
Packit 549fdc
	if (rc < 0) {
Packit 549fdc
		_gnutls_hash_deinit(&td_md5, NULL);
Packit 549fdc
		_gnutls_hash_deinit(&td_sha, NULL);
Packit 549fdc
		return gnutls_assert_val(rc);
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	rc = _gnutls_mac_deinit_ssl3_handshake(&td_sha, &ret[16],
Packit 549fdc
					       session->security_parameters.
Packit 549fdc
					       master_secret,
Packit 549fdc
					       GNUTLS_MASTER_SIZE);
Packit 549fdc
	if (rc < 0) {
Packit 549fdc
		_gnutls_hash_deinit(&td_sha, NULL);
Packit 549fdc
		return gnutls_assert_val(rc);
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	return 0;
Packit 549fdc
}
Packit 549fdc
#endif
Packit 549fdc
Packit 549fdc
/* Hash the handshake messages as required by TLS 1.0
Packit 549fdc
 */
Packit 549fdc
#define SERVER_MSG "server finished"
Packit 549fdc
#define CLIENT_MSG "client finished"
Packit 549fdc
#define TLS_MSG_LEN 15
Packit 549fdc
static int
Packit 549fdc
_gnutls_finished(gnutls_session_t session, int type, void *ret,
Packit 549fdc
		 int sending)
Packit 549fdc
{
Packit 549fdc
	const int siz = TLS_MSG_LEN;
Packit 549fdc
	uint8_t concat[MAX_HASH_SIZE];
Packit 549fdc
	size_t hash_len;
Packit 549fdc
	const char *mesg;
Packit 549fdc
	int rc, len, algorithm;
Packit 549fdc
Packit 549fdc
	if (sending)
Packit 549fdc
		len = session->internals.handshake_hash_buffer.length;
Packit 549fdc
	else
Packit 549fdc
		len = session->internals.handshake_hash_buffer_prev_len;
Packit 549fdc
Packit 549fdc
	algorithm = session->security_parameters.prf_mac;
Packit 549fdc
	rc = _gnutls_hash_fast(algorithm,
Packit 549fdc
			       session->internals.
Packit 549fdc
			       handshake_hash_buffer.data, len,
Packit 549fdc
			       concat);
Packit 549fdc
	if (rc < 0)
Packit 549fdc
		return gnutls_assert_val(rc);
Packit 549fdc
Packit 549fdc
	hash_len = _gnutls_hash_get_algo_len(mac_to_entry(algorithm));
Packit 549fdc
Packit 549fdc
	if (type == GNUTLS_SERVER) {
Packit 549fdc
		mesg = SERVER_MSG;
Packit 549fdc
	} else {
Packit 549fdc
		mesg = CLIENT_MSG;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	return _gnutls_PRF(session,
Packit 549fdc
			   session->security_parameters.master_secret,
Packit 549fdc
			   GNUTLS_MASTER_SIZE, mesg, siz, concat, hash_len,
Packit 549fdc
			   12, ret);
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
Packit 549fdc
/* returns the 0 on success or a negative error code.
Packit 549fdc
 */
Packit 549fdc
int
Packit 549fdc
_gnutls_negotiate_version(gnutls_session_t session,
Packit 549fdc
			  gnutls_protocol_t adv_version, uint8_t major, uint8_t minor)
Packit 549fdc
{
Packit 549fdc
	int ret;
Packit 549fdc
Packit 549fdc
Packit 549fdc
	/* if we do not support that version  */
Packit 549fdc
	if (adv_version == GNUTLS_VERSION_UNKNOWN || _gnutls_version_is_supported(session, adv_version) == 0) {
Packit 549fdc
		/* if we get an unknown/unsupported version, then fail if the version we
Packit 549fdc
		 * got is too low to be supported */
Packit 549fdc
		if (!_gnutls_version_is_too_high(session, major, minor))
Packit 549fdc
			return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
Packit 549fdc
Packit 549fdc
		/* If he requested something we do not support
Packit 549fdc
		 * then we send him the highest we support.
Packit 549fdc
		 */
Packit 549fdc
		ret = _gnutls_version_max(session);
Packit 549fdc
		if (ret == GNUTLS_VERSION_UNKNOWN) {
Packit 549fdc
			/* this check is not really needed.
Packit 549fdc
			 */
Packit 549fdc
			gnutls_assert();
Packit 549fdc
			return GNUTLS_E_UNKNOWN_CIPHER_SUITE;
Packit 549fdc
		}
Packit 549fdc
	} else {
Packit 549fdc
		ret = adv_version;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	if (_gnutls_set_current_version(session, ret) < 0)
Packit 549fdc
		return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
Packit 549fdc
Packit 549fdc
	return ret;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/* This function returns:
Packit 549fdc
 *  - zero on success
Packit 549fdc
 *  - GNUTLS_E_INT_RET_0 if GNUTLS_E_AGAIN || GNUTLS_E_INTERRUPTED were returned by the callback
Packit 549fdc
 *  - a negative error code on other error
Packit 549fdc
 */
Packit 549fdc
int
Packit 549fdc
_gnutls_user_hello_func(gnutls_session_t session,
Packit 549fdc
			gnutls_protocol_t adv_version, uint8_t major, uint8_t minor)
Packit 549fdc
{
Packit 549fdc
	int ret, sret = 0;
Packit 549fdc
Packit 549fdc
	if (session->internals.user_hello_func != NULL) {
Packit 549fdc
		ret = session->internals.user_hello_func(session);
Packit 549fdc
Packit 549fdc
		if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) {
Packit 549fdc
			gnutls_assert();
Packit 549fdc
			sret = GNUTLS_E_INT_RET_0;
Packit 549fdc
		} else if (ret < 0) {
Packit 549fdc
			gnutls_assert();
Packit 549fdc
			return ret;
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
		/* Here we need to renegotiate the version since the callee might
Packit 549fdc
		 * have disabled some TLS versions.
Packit 549fdc
		 */
Packit 549fdc
		ret = _gnutls_negotiate_version(session, adv_version, major, minor);
Packit 549fdc
		if (ret < 0) {
Packit 549fdc
			gnutls_assert();
Packit 549fdc
			return ret;
Packit 549fdc
		}
Packit 549fdc
	}
Packit 549fdc
	return sret;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/* Read a client hello packet. 
Packit 549fdc
 * A client hello must be a known version client hello
Packit 549fdc
 * or version 2.0 client hello (only for compatibility
Packit 549fdc
 * since SSL version 2.0 is not supported).
Packit 549fdc
 */
Packit 549fdc
static int
Packit 549fdc
read_client_hello(gnutls_session_t session, uint8_t * data,
Packit 549fdc
			  int datalen)
Packit 549fdc
{
Packit 549fdc
	uint8_t session_id_len;
Packit 549fdc
	int pos = 0, ret;
Packit 549fdc
	uint16_t suite_size, comp_size;
Packit 549fdc
	int ext_size;
Packit 549fdc
	gnutls_protocol_t adv_version;
Packit 549fdc
	int neg_version, sret = 0;
Packit 549fdc
	int len = datalen;
Packit 549fdc
	uint8_t major, minor;
Packit 549fdc
	uint8_t *suite_ptr, *comp_ptr, *session_id, *ext_ptr;
Packit 549fdc
Packit 549fdc
	DECR_LEN(len, 2);
Packit 549fdc
	_gnutls_handshake_log("HSK[%p]: Client's version: %d.%d\n",
Packit 549fdc
			      session, data[pos], data[pos + 1]);
Packit 549fdc
Packit 549fdc
	adv_version = _gnutls_version_get(data[pos], data[pos + 1]);
Packit 549fdc
Packit 549fdc
	major = data[pos];
Packit 549fdc
	minor = data[pos+1];
Packit 549fdc
	set_adv_version(session, major, minor);
Packit 549fdc
Packit 549fdc
	neg_version = _gnutls_negotiate_version(session, adv_version, major, minor);
Packit 549fdc
	if (neg_version < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return neg_version;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	pos += 2;
Packit 549fdc
Packit 549fdc
	_gnutls_handshake_log("HSK[%p]: Selected version %s\n",
Packit 549fdc
		     session, gnutls_protocol_get_name(neg_version));
Packit 549fdc
Packit 549fdc
	/* Read client random value.
Packit 549fdc
	 */
Packit 549fdc
	DECR_LEN(len, GNUTLS_RANDOM_SIZE);
Packit 549fdc
	ret = _gnutls_set_client_random(session, &data[pos]);
Packit 549fdc
	if (ret < 0)
Packit 549fdc
		return gnutls_assert_val(ret);
Packit 549fdc
Packit 549fdc
	pos += GNUTLS_RANDOM_SIZE;
Packit 549fdc
Packit 549fdc
	ret = _gnutls_set_server_random(session, NULL);
Packit 549fdc
	if (ret < 0)
Packit 549fdc
		return gnutls_assert_val(ret);
Packit 549fdc
Packit 549fdc
	session->security_parameters.timestamp = gnutls_time(NULL);
Packit 549fdc
Packit 549fdc
	DECR_LEN(len, 1);
Packit 549fdc
	session_id_len = data[pos++];
Packit 549fdc
Packit 549fdc
	/* RESUME SESSION 
Packit 549fdc
	 */
Packit 549fdc
	if (session_id_len > GNUTLS_MAX_SESSION_ID_SIZE) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
Packit 549fdc
	}
Packit 549fdc
	DECR_LEN(len, session_id_len);
Packit 549fdc
	session_id = &data[pos];
Packit 549fdc
	pos += session_id_len;
Packit 549fdc
Packit 549fdc
	if (IS_DTLS(session)) {
Packit 549fdc
		int cookie_size;
Packit 549fdc
Packit 549fdc
		DECR_LEN(len, 1);
Packit 549fdc
		cookie_size = data[pos++];
Packit 549fdc
		DECR_LEN(len, cookie_size);
Packit 549fdc
		pos += cookie_size;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	/* move forward to extensions and store other vals */
Packit 549fdc
	DECR_LEN(len, 2);
Packit 549fdc
	suite_size = _gnutls_read_uint16(&data[pos]);
Packit 549fdc
	pos += 2;
Packit 549fdc
Packit 549fdc
	if (suite_size == 0 || (suite_size % 2) != 0)
Packit 549fdc
		return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
Packit 549fdc
Packit 549fdc
	suite_ptr = &data[pos];
Packit 549fdc
	DECR_LEN(len, suite_size);
Packit 549fdc
	pos += suite_size;
Packit 549fdc
Packit 549fdc
	DECR_LEN(len, 1);
Packit 549fdc
	comp_size = data[pos++]; /* the number of compression methods */
Packit 549fdc
Packit 549fdc
	if (comp_size == 0)
Packit 549fdc
		return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
Packit 549fdc
Packit 549fdc
	comp_ptr = &data[pos];
Packit 549fdc
	DECR_LEN(len, comp_size);
Packit 549fdc
	pos += comp_size;
Packit 549fdc
Packit 549fdc
	ext_ptr = &data[pos];
Packit 549fdc
	ext_size = len;
Packit 549fdc
Packit 549fdc
	/* Parse only the mandatory to read extensions for resumption.
Packit 549fdc
	 * We don't want to parse any other extensions since
Packit 549fdc
	 * we don't want new extension values to override the
Packit 549fdc
	 * resumed ones.
Packit 549fdc
	 */
Packit 549fdc
	ret =
Packit 549fdc
	    _gnutls_parse_extensions(session, GNUTLS_EXT_MANDATORY,
Packit 549fdc
				     ext_ptr, ext_size);
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return ret;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	ret =
Packit 549fdc
	    _gnutls_server_restore_session(session, session_id,
Packit 549fdc
					   session_id_len);
Packit 549fdc
Packit 549fdc
	if (session_id_len > 0)
Packit 549fdc
		session->internals.resumption_requested = 1;
Packit 549fdc
Packit 549fdc
	if (ret == 0) {		/* resumed using default TLS resumption! */
Packit 549fdc
		ret = _gnutls_server_select_suite(session, suite_ptr, suite_size, 1);
Packit 549fdc
		if (ret < 0)
Packit 549fdc
			return gnutls_assert_val(ret);
Packit 549fdc
Packit 549fdc
		ret = resume_copy_required_values(session);
Packit 549fdc
		if (ret < 0)
Packit 549fdc
			return gnutls_assert_val(ret);
Packit 549fdc
Packit 549fdc
		session->internals.resumed = RESUME_TRUE;
Packit 549fdc
Packit 549fdc
		return _gnutls_user_hello_func(session, adv_version, major, minor);
Packit 549fdc
	} else {
Packit 549fdc
		_gnutls_generate_session_id(session->security_parameters.
Packit 549fdc
					    session_id,
Packit 549fdc
					    &session->security_parameters.
Packit 549fdc
					    session_id_size);
Packit 549fdc
Packit 549fdc
		session->internals.resumed = RESUME_FALSE;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	/* Parse the extensions (if any)
Packit 549fdc
	 *
Packit 549fdc
	 * Unconditionally try to parse extensions; safe renegotiation uses them in
Packit 549fdc
	 * sslv3 and higher, even though sslv3 doesn't officially support them.
Packit 549fdc
	 */
Packit 549fdc
	ret = _gnutls_parse_extensions(session, GNUTLS_EXT_APPLICATION,
Packit 549fdc
				       ext_ptr, ext_size);
Packit 549fdc
	/* len is the rest of the parsed length */
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return ret;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	/* we cache this error code */
Packit 549fdc
	sret = _gnutls_user_hello_func(session, adv_version, major, minor);
Packit 549fdc
	if (sret < 0 && sret != GNUTLS_E_INT_RET_0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return sret;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	/* Session tickets are parsed in this point */
Packit 549fdc
	ret =
Packit 549fdc
	    _gnutls_parse_extensions(session, GNUTLS_EXT_TLS, ext_ptr, ext_size);
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return ret;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	/* resumed by session_ticket extension */
Packit 549fdc
	if (session->internals.resumed != RESUME_FALSE) {
Packit 549fdc
		/* to indicate the client that the current session is resumed */
Packit 549fdc
		memcpy(session->internals.resumed_security_parameters.
Packit 549fdc
		       session_id, session_id, session_id_len);
Packit 549fdc
		session->internals.resumed_security_parameters.
Packit 549fdc
		    session_id_size = session_id_len;
Packit 549fdc
Packit 549fdc
		session->internals.resumed_security_parameters.
Packit 549fdc
		    max_record_recv_size =
Packit 549fdc
		    session->security_parameters.max_record_recv_size;
Packit 549fdc
		session->internals.resumed_security_parameters.
Packit 549fdc
		    max_record_send_size =
Packit 549fdc
		    session->security_parameters.max_record_send_size;
Packit 549fdc
Packit 549fdc
		ret = _gnutls_server_select_suite(session, suite_ptr, suite_size, 1);
Packit 549fdc
		if (ret < 0)
Packit 549fdc
			return gnutls_assert_val(ret);
Packit 549fdc
Packit 549fdc
		ret = resume_copy_required_values(session);
Packit 549fdc
		if (ret < 0)
Packit 549fdc
			return gnutls_assert_val(ret);
Packit 549fdc
Packit 549fdc
		return 0;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	/* select an appropriate cipher suite (as well as certificate)
Packit 549fdc
	 */
Packit 549fdc
	ret = _gnutls_server_select_suite(session, suite_ptr, suite_size, 0);
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return ret;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	/* select appropriate compression method */
Packit 549fdc
	ret =
Packit 549fdc
	    check_if_null_comp_present(session, comp_ptr,
Packit 549fdc
					      comp_size);
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return ret;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	/* call extensions that are intended to be parsed after the ciphersuite/cert
Packit 549fdc
	 * are known. */
Packit 549fdc
	ret =
Packit 549fdc
	    _gnutls_parse_extensions(session, _GNUTLS_EXT_TLS_POST_CS, ext_ptr, ext_size);
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return ret;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	return sret;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/* This is to be called after sending CHANGE CIPHER SPEC packet
Packit 549fdc
 * and initializing encryption. This is the first encrypted message
Packit 549fdc
 * we send.
Packit 549fdc
 */
Packit 549fdc
static int _gnutls_send_finished(gnutls_session_t session, int again)
Packit 549fdc
{
Packit 549fdc
	mbuffer_st *bufel;
Packit 549fdc
	uint8_t *data;
Packit 549fdc
	int ret;
Packit 549fdc
	size_t vdata_size = 0;
Packit 549fdc
	const version_entry_st *vers;
Packit 549fdc
Packit 549fdc
	if (again == 0) {
Packit 549fdc
		bufel =
Packit 549fdc
		    _gnutls_handshake_alloc(session, 
Packit 549fdc
					    MAX_VERIFY_DATA_SIZE);
Packit 549fdc
		if (bufel == NULL) {
Packit 549fdc
			gnutls_assert();
Packit 549fdc
			return GNUTLS_E_MEMORY_ERROR;
Packit 549fdc
		}
Packit 549fdc
		data = _mbuffer_get_udata_ptr(bufel);
Packit 549fdc
Packit 549fdc
		vers = get_version(session);
Packit 549fdc
		if (unlikely(vers == NULL))
Packit 549fdc
			return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
Packit 549fdc
Packit 549fdc
#ifdef ENABLE_SSL3
Packit 549fdc
		if (vers->id == GNUTLS_SSL3) {
Packit 549fdc
			ret =
Packit 549fdc
			    _gnutls_ssl3_finished(session,
Packit 549fdc
						  session->
Packit 549fdc
						  security_parameters.
Packit 549fdc
						  entity, data, 1);
Packit 549fdc
			_mbuffer_set_udata_size(bufel, 36);
Packit 549fdc
		} else {	/* TLS 1.0+ */
Packit 549fdc
#endif
Packit 549fdc
			ret = _gnutls_finished(session,
Packit 549fdc
					       session->
Packit 549fdc
					       security_parameters.entity,
Packit 549fdc
					       data, 1);
Packit 549fdc
			_mbuffer_set_udata_size(bufel, 12);
Packit 549fdc
#ifdef ENABLE_SSL3
Packit 549fdc
		}
Packit 549fdc
#endif
Packit 549fdc
Packit 549fdc
		if (ret < 0) {
Packit 549fdc
			gnutls_assert();
Packit 549fdc
			return ret;
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
		vdata_size = _mbuffer_get_udata_size(bufel);
Packit 549fdc
Packit 549fdc
		ret =
Packit 549fdc
		    _gnutls_ext_sr_finished(session, data, vdata_size, 0);
Packit 549fdc
		if (ret < 0) {
Packit 549fdc
			gnutls_assert();
Packit 549fdc
			return ret;
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
		if ((session->internals.resumed == RESUME_FALSE
Packit 549fdc
		     && session->security_parameters.entity ==
Packit 549fdc
		     GNUTLS_CLIENT)
Packit 549fdc
		    || (session->internals.resumed != RESUME_FALSE
Packit 549fdc
			&& session->security_parameters.entity ==
Packit 549fdc
			GNUTLS_SERVER)) {
Packit 549fdc
			/* if we are a client not resuming - or we are a server resuming */
Packit 549fdc
			_gnutls_handshake_log
Packit 549fdc
			    ("HSK[%p]: recording tls-unique CB (send)\n",
Packit 549fdc
			     session);
Packit 549fdc
			memcpy(session->internals.cb_tls_unique, data,
Packit 549fdc
			       vdata_size);
Packit 549fdc
			session->internals.cb_tls_unique_len = vdata_size;
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
		ret =
Packit 549fdc
		    _gnutls_send_handshake(session, bufel,
Packit 549fdc
					   GNUTLS_HANDSHAKE_FINISHED);
Packit 549fdc
	} else {
Packit 549fdc
		ret =
Packit 549fdc
		    _gnutls_send_handshake(session, NULL,
Packit 549fdc
					   GNUTLS_HANDSHAKE_FINISHED);
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	return ret;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/* This is to be called after sending our finished message. If everything
Packit 549fdc
 * went fine we have negotiated a secure connection 
Packit 549fdc
 */
Packit 549fdc
static int _gnutls_recv_finished(gnutls_session_t session)
Packit 549fdc
{
Packit 549fdc
	uint8_t data[MAX_VERIFY_DATA_SIZE], *vrfy;
Packit 549fdc
	gnutls_buffer_st buf;
Packit 549fdc
	int data_size;
Packit 549fdc
	int ret;
Packit 549fdc
	int vrfy_size;
Packit 549fdc
	const version_entry_st *vers = get_version(session);
Packit 549fdc
Packit 549fdc
	if (unlikely(vers == NULL))
Packit 549fdc
		return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
Packit 549fdc
Packit 549fdc
	ret =
Packit 549fdc
	    _gnutls_recv_handshake(session, GNUTLS_HANDSHAKE_FINISHED,
Packit 549fdc
				   0, &buf;;
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return ret;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	vrfy = buf.data;
Packit 549fdc
	vrfy_size = buf.length;
Packit 549fdc
Packit 549fdc
#ifdef ENABLE_SSL3
Packit 549fdc
	if (vers->id == GNUTLS_SSL3)
Packit 549fdc
		data_size = 36;
Packit 549fdc
	else
Packit 549fdc
#endif
Packit 549fdc
		data_size = 12;
Packit 549fdc
Packit 549fdc
	if (vrfy_size != data_size) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		ret = GNUTLS_E_ERROR_IN_FINISHED_PACKET;
Packit 549fdc
		goto cleanup;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
#ifdef ENABLE_SSL3
Packit 549fdc
	if (vers->id == GNUTLS_SSL3) {
Packit 549fdc
		ret =
Packit 549fdc
		    _gnutls_ssl3_finished(session,
Packit 549fdc
					  (session->security_parameters.
Packit 549fdc
					   entity + 1) % 2, data, 0);
Packit 549fdc
	} else /* TLS 1.0+ */
Packit 549fdc
#endif
Packit 549fdc
		ret =
Packit 549fdc
		    _gnutls_finished(session,
Packit 549fdc
				     (session->security_parameters.entity +
Packit 549fdc
				      1) % 2, data, 0);
Packit 549fdc
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		goto cleanup;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
Packit 549fdc
	/* When fuzzying allow to proceed without verifying the handshake
Packit 549fdc
	 * consistency */
Packit 549fdc
# warning This is unsafe for production builds
Packit 549fdc
Packit 549fdc
#else
Packit 549fdc
	if (memcmp(vrfy, data, data_size) != 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		ret = GNUTLS_E_ERROR_IN_FINISHED_PACKET;
Packit 549fdc
		goto cleanup;
Packit 549fdc
	}
Packit 549fdc
#endif
Packit 549fdc
Packit 549fdc
	ret = _gnutls_ext_sr_finished(session, data, data_size, 1);
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		goto cleanup;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	if ((session->internals.resumed != RESUME_FALSE
Packit 549fdc
	     && session->security_parameters.entity == GNUTLS_CLIENT)
Packit 549fdc
	    || (session->internals.resumed == RESUME_FALSE
Packit 549fdc
		&& session->security_parameters.entity == GNUTLS_SERVER)) {
Packit 549fdc
		/* if we are a client resuming - or we are a server not resuming */
Packit 549fdc
		_gnutls_handshake_log
Packit 549fdc
		    ("HSK[%p]: recording tls-unique CB (recv)\n", session);
Packit 549fdc
		memcpy(session->internals.cb_tls_unique, data, data_size);
Packit 549fdc
		session->internals.cb_tls_unique_len = data_size;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
Packit 549fdc
	session->internals.initial_negotiation_completed = 1;
Packit 549fdc
Packit 549fdc
      cleanup:
Packit 549fdc
	_gnutls_buffer_clear(&buf;;
Packit 549fdc
Packit 549fdc
	return ret;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/* This selects the best supported ciphersuite from the given ones. Then
Packit 549fdc
 * it adds the suite to the session and performs some checks.
Packit 549fdc
 *
Packit 549fdc
 * When @scsv_only is non-zero only the available SCSVs are parsed
Packit 549fdc
 * and acted upon.
Packit 549fdc
 */
Packit 549fdc
int
Packit 549fdc
_gnutls_server_select_suite(gnutls_session_t session, uint8_t * data,
Packit 549fdc
			    unsigned int datalen, unsigned scsv_only)
Packit 549fdc
{
Packit 549fdc
	int ret;
Packit 549fdc
	unsigned int i;
Packit 549fdc
	ciphersuite_list_st peer_clist;
Packit 549fdc
	const gnutls_cipher_suite_entry_st *selected;
Packit 549fdc
	int retval;
Packit 549fdc
Packit 549fdc
	peer_clist.size = 0;
Packit 549fdc
Packit 549fdc
	for (i = 0; i < datalen; i += 2) {
Packit 549fdc
		/* we support the TLS renegotiation SCSV, even if we are
Packit 549fdc
		 * not under SSL 3.0, because openssl sends this SCSV
Packit 549fdc
		 * on resumption unconditionally. */
Packit 549fdc
		/* TLS_RENEGO_PROTECTION_REQUEST = { 0x00, 0xff } */
Packit 549fdc
		if (session->internals.priorities->sr != SR_DISABLED &&
Packit 549fdc
		    data[i] == GNUTLS_RENEGO_PROTECTION_REQUEST_MAJOR &&
Packit 549fdc
		    data[i + 1] == GNUTLS_RENEGO_PROTECTION_REQUEST_MINOR) {
Packit 549fdc
			_gnutls_handshake_log
Packit 549fdc
			    ("HSK[%p]: Received safe renegotiation CS\n",
Packit 549fdc
			     session);
Packit 549fdc
			retval = _gnutls_ext_sr_recv_cs(session);
Packit 549fdc
			if (retval < 0) {
Packit 549fdc
				gnutls_assert();
Packit 549fdc
				return retval;
Packit 549fdc
			}
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
		/* TLS_FALLBACK_SCSV */
Packit 549fdc
		if (data[i] == GNUTLS_FALLBACK_SCSV_MAJOR &&
Packit 549fdc
		    data[i + 1] == GNUTLS_FALLBACK_SCSV_MINOR) {
Packit 549fdc
			unsigned max = _gnutls_version_max(session);
Packit 549fdc
			_gnutls_handshake_log
Packit 549fdc
			    ("HSK[%p]: Received fallback CS\n",
Packit 549fdc
			     session);
Packit 549fdc
Packit 549fdc
			if (gnutls_protocol_get_version(session) != max)
Packit 549fdc
				return gnutls_assert_val(GNUTLS_E_INAPPROPRIATE_FALLBACK);
Packit 549fdc
		} else if (!scsv_only) {
Packit 549fdc
			if (peer_clist.size < MAX_CIPHERSUITE_SIZE) {
Packit 549fdc
				peer_clist.entry[peer_clist.size] = ciphersuite_to_entry(&data[i]);
Packit 549fdc
				if (peer_clist.entry[peer_clist.size] != NULL)
Packit 549fdc
					peer_clist.size++;
Packit 549fdc
			}
Packit 549fdc
		}
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	if (scsv_only)
Packit 549fdc
		return 0;
Packit 549fdc
Packit 549fdc
	ret = _gnutls_figure_common_ciphersuite(session, &peer_clist, &selected);
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		return gnutls_assert_val(ret);
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	_gnutls_handshake_log
Packit 549fdc
		    ("HSK[%p]: Selected cipher suite: %s\n", session, selected->name);
Packit 549fdc
Packit 549fdc
	ret = _gnutls_set_cipher_suite2(session, selected);
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return ret;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	/* check if the credentials (username, public key etc.) are ok
Packit 549fdc
	 */
Packit 549fdc
	if (_gnutls_get_kx_cred(session, selected->kx_algorithm) == NULL) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
Packit 549fdc
	/* set the mod_auth_st to the appropriate struct
Packit 549fdc
	 * according to the KX algorithm. This is needed since all the
Packit 549fdc
	 * handshake functions are read from there;
Packit 549fdc
	 */
Packit 549fdc
	session->internals.auth_struct = _gnutls_kx_auth_struct(selected->kx_algorithm);
Packit 549fdc
	if (session->internals.auth_struct == NULL) {
Packit 549fdc
		_gnutls_handshake_log
Packit 549fdc
		    ("HSK[%p]: Cannot find the appropriate handler for the KX algorithm\n",
Packit 549fdc
		     session);
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return GNUTLS_E_INTERNAL_ERROR;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	return 0;
Packit 549fdc
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
Packit 549fdc
/* This checks whether the null compression method is present.
Packit 549fdc
 */
Packit 549fdc
static int
Packit 549fdc
check_if_null_comp_present(gnutls_session_t session,
Packit 549fdc
			  uint8_t * data, int datalen)
Packit 549fdc
{
Packit 549fdc
	int j;
Packit 549fdc
Packit 549fdc
	for (j = 0; j < datalen; j++) {
Packit 549fdc
		if (data[j] == 0)
Packit 549fdc
			return 0;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	/* we were not able to find a the NULL compression
Packit 549fdc
	 * algorithm
Packit 549fdc
	 */
Packit 549fdc
	gnutls_assert();
Packit 549fdc
	return GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM;
Packit 549fdc
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/* This function sends an empty handshake packet. (like hello request).
Packit 549fdc
 * If the previous _gnutls_send_empty_handshake() returned
Packit 549fdc
 * GNUTLS_E_AGAIN or GNUTLS_E_INTERRUPTED, then it must be called again 
Packit 549fdc
 * (until it returns ok), with NULL parameters.
Packit 549fdc
 */
Packit 549fdc
static int
Packit 549fdc
_gnutls_send_empty_handshake(gnutls_session_t session,
Packit 549fdc
			     gnutls_handshake_description_t type,
Packit 549fdc
			     int again)
Packit 549fdc
{
Packit 549fdc
	mbuffer_st *bufel;
Packit 549fdc
Packit 549fdc
	if (again == 0) {
Packit 549fdc
		bufel = _gnutls_handshake_alloc(session, 0);
Packit 549fdc
		if (bufel == NULL) {
Packit 549fdc
			gnutls_assert();
Packit 549fdc
			return GNUTLS_E_MEMORY_ERROR;
Packit 549fdc
		}
Packit 549fdc
	} else
Packit 549fdc
		bufel = NULL;
Packit 549fdc
Packit 549fdc
	return _gnutls_send_handshake(session, bufel, type);
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
inline
Packit 549fdc
    static int call_hook_func(gnutls_session_t session,
Packit 549fdc
			      gnutls_handshake_description_t type,
Packit 549fdc
			      int post, unsigned incoming,
Packit 549fdc
			      const uint8_t *data, unsigned data_size)
Packit 549fdc
{
Packit 549fdc
	gnutls_datum_t msg = {(void*)data, data_size};
Packit 549fdc
Packit 549fdc
	if (session->internals.h_hook != NULL) {
Packit 549fdc
		if ((session->internals.h_type == type
Packit 549fdc
		     || session->internals.h_type == GNUTLS_HANDSHAKE_ANY)
Packit 549fdc
		    && (session->internals.h_post == post
Packit 549fdc
			|| session->internals.h_post == GNUTLS_HOOK_BOTH))
Packit 549fdc
			return session->internals.h_hook(session, type,
Packit 549fdc
							 post, incoming, &msg;;
Packit 549fdc
	}
Packit 549fdc
	return 0;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/* This function sends a handshake message of type 'type' containing the
Packit 549fdc
 * data specified here. If the previous _gnutls_send_handshake() returned
Packit 549fdc
 * GNUTLS_E_AGAIN or GNUTLS_E_INTERRUPTED, then it must be called again 
Packit 549fdc
 * (until it returns ok), with NULL parameters.
Packit 549fdc
 */
Packit 549fdc
int
Packit 549fdc
_gnutls_send_handshake(gnutls_session_t session, mbuffer_st * bufel,
Packit 549fdc
		       gnutls_handshake_description_t type)
Packit 549fdc
{
Packit 549fdc
	int ret;
Packit 549fdc
	uint8_t *data;
Packit 549fdc
	uint32_t datasize, i_datasize;
Packit 549fdc
	int pos = 0;
Packit 549fdc
Packit 549fdc
	if (bufel == NULL) {
Packit 549fdc
		/* we are resuming a previously interrupted
Packit 549fdc
		 * send.
Packit 549fdc
		 */
Packit 549fdc
		ret = _gnutls_handshake_io_write_flush(session);
Packit 549fdc
		return ret;
Packit 549fdc
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	/* first run */
Packit 549fdc
	data = _mbuffer_get_uhead_ptr(bufel);
Packit 549fdc
	i_datasize = _mbuffer_get_udata_size(bufel);
Packit 549fdc
	datasize = i_datasize + _mbuffer_get_uhead_size(bufel);
Packit 549fdc
Packit 549fdc
	data[pos++] = (uint8_t) type;
Packit 549fdc
	_gnutls_write_uint24(_mbuffer_get_udata_size(bufel), &data[pos]);
Packit 549fdc
	pos += 3;
Packit 549fdc
Packit 549fdc
	/* Add DTLS handshake fragment headers.  The message will be
Packit 549fdc
	 * fragmented later by the fragmentation sub-layer. All fields must
Packit 549fdc
	 * be set properly for HMAC. The HMAC requires we pretend that the
Packit 549fdc
	 * message was sent in a single fragment. */
Packit 549fdc
	if (IS_DTLS(session)) {
Packit 549fdc
		_gnutls_write_uint16(session->internals.dtls.
Packit 549fdc
				     hsk_write_seq++, &data[pos]);
Packit 549fdc
		pos += 2;
Packit 549fdc
Packit 549fdc
		/* Fragment offset */
Packit 549fdc
		_gnutls_write_uint24(0, &data[pos]);
Packit 549fdc
		pos += 3;
Packit 549fdc
Packit 549fdc
		/* Fragment length */
Packit 549fdc
		_gnutls_write_uint24(i_datasize, &data[pos]);
Packit 549fdc
		/* pos += 3; */
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	_gnutls_handshake_log("HSK[%p]: %s was queued [%ld bytes]\n",
Packit 549fdc
			      session, _gnutls_handshake2str(type),
Packit 549fdc
			      (long) datasize);
Packit 549fdc
Packit 549fdc
	/* Here we keep the handshake messages in order to hash them...
Packit 549fdc
	 */
Packit 549fdc
	if (type != GNUTLS_HANDSHAKE_HELLO_REQUEST)
Packit 549fdc
		if ((ret =
Packit 549fdc
		     handshake_hash_add_sent(session, type, data,
Packit 549fdc
						     datasize)) < 0) {
Packit 549fdc
			gnutls_assert();
Packit 549fdc
			_mbuffer_xfree(&bufel);
Packit 549fdc
			return ret;
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
	ret = call_hook_func(session, type, GNUTLS_HOOK_PRE, 0,
Packit 549fdc
			     _mbuffer_get_udata_ptr(bufel), _mbuffer_get_udata_size(bufel));
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		_mbuffer_xfree(&bufel);
Packit 549fdc
		return ret;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	session->internals.last_handshake_out = type;
Packit 549fdc
Packit 549fdc
	ret = _gnutls_handshake_io_cache_int(session, type, bufel);
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		_mbuffer_xfree(&bufel);
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return ret;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	ret = call_hook_func(session, type, GNUTLS_HOOK_POST, 0, 
Packit 549fdc
			      _mbuffer_get_udata_ptr(bufel), _mbuffer_get_udata_size(bufel));
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return ret;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	/* The messages which are followed by another are not sent by default
Packit 549fdc
	 * but are cached instead */
Packit 549fdc
	switch (type) {
Packit 549fdc
	case GNUTLS_HANDSHAKE_CERTIFICATE_PKT:	/* this one is followed by ServerHelloDone
Packit 549fdc
						 * or ClientKeyExchange always.
Packit 549fdc
						 */
Packit 549fdc
	case GNUTLS_HANDSHAKE_CERTIFICATE_STATUS:
Packit 549fdc
	case GNUTLS_HANDSHAKE_SERVER_KEY_EXCHANGE:	/* as above */
Packit 549fdc
	case GNUTLS_HANDSHAKE_SERVER_HELLO:	/* as above */
Packit 549fdc
	case GNUTLS_HANDSHAKE_CERTIFICATE_REQUEST:	/* as above */
Packit 549fdc
	case GNUTLS_HANDSHAKE_NEW_SESSION_TICKET:	/* followed by ChangeCipherSpec */
Packit 549fdc
Packit 549fdc
		/* now for client Certificate, ClientKeyExchange and
Packit 549fdc
		 * CertificateVerify are always followed by ChangeCipherSpec
Packit 549fdc
		 */
Packit 549fdc
	case GNUTLS_HANDSHAKE_CERTIFICATE_VERIFY:
Packit 549fdc
	case GNUTLS_HANDSHAKE_CLIENT_KEY_EXCHANGE:
Packit 549fdc
		ret = 0;
Packit 549fdc
		break;
Packit 549fdc
	default:
Packit 549fdc
		/* send cached messages */
Packit 549fdc
		ret = _gnutls_handshake_io_write_flush(session);
Packit 549fdc
		break;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	return ret;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
#define CHECK_SIZE(ll) \
Packit 549fdc
  if ((session->internals.max_handshake_data_buffer_size > 0) && \
Packit 549fdc
      (((ll) + session->internals.handshake_hash_buffer.length) > \
Packit 549fdc
       session->internals.max_handshake_data_buffer_size)) { \
Packit 549fdc
    _gnutls_debug_log("Handshake buffer length is %u (max: %u)\n", (unsigned)((ll) + session->internals.handshake_hash_buffer.length), (unsigned)session->internals.max_handshake_data_buffer_size); \
Packit 549fdc
    return gnutls_assert_val(GNUTLS_E_HANDSHAKE_TOO_LARGE); \
Packit 549fdc
    }
Packit 549fdc
Packit 549fdc
/* This function add the handshake headers and the
Packit 549fdc
 * handshake data to the handshake hash buffers. Needed
Packit 549fdc
 * for the finished messages calculations.
Packit 549fdc
 */
Packit 549fdc
static int
Packit 549fdc
handshake_hash_add_recvd(gnutls_session_t session,
Packit 549fdc
				 gnutls_handshake_description_t recv_type,
Packit 549fdc
				 uint8_t * header, uint16_t header_size,
Packit 549fdc
				 uint8_t * dataptr, uint32_t datalen)
Packit 549fdc
{
Packit 549fdc
	int ret;
Packit 549fdc
	const version_entry_st *vers = get_version(session);
Packit 549fdc
Packit 549fdc
	if (unlikely(vers == NULL))
Packit 549fdc
		return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
Packit 549fdc
Packit 549fdc
	if ((vers->id != GNUTLS_DTLS0_9 &&
Packit 549fdc
	     recv_type == GNUTLS_HANDSHAKE_HELLO_VERIFY_REQUEST) ||
Packit 549fdc
	    recv_type == GNUTLS_HANDSHAKE_HELLO_REQUEST)
Packit 549fdc
		return 0;
Packit 549fdc
Packit 549fdc
	CHECK_SIZE(header_size + datalen);
Packit 549fdc
Packit 549fdc
	session->internals.handshake_hash_buffer_prev_len =
Packit 549fdc
	    session->internals.handshake_hash_buffer.length;
Packit 549fdc
Packit 549fdc
	if (vers->id != GNUTLS_DTLS0_9) {
Packit 549fdc
		ret =
Packit 549fdc
		    _gnutls_buffer_append_data(&session->internals.
Packit 549fdc
					       handshake_hash_buffer,
Packit 549fdc
					       header, header_size);
Packit 549fdc
		if (ret < 0)
Packit 549fdc
			return gnutls_assert_val(ret);
Packit 549fdc
	}
Packit 549fdc
	if (datalen > 0) {
Packit 549fdc
		ret =
Packit 549fdc
		    _gnutls_buffer_append_data(&session->internals.
Packit 549fdc
					       handshake_hash_buffer,
Packit 549fdc
					       dataptr, datalen);
Packit 549fdc
		if (ret < 0)
Packit 549fdc
			return gnutls_assert_val(ret);
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	/* save the size until client KX. That is because the TLS
Packit 549fdc
	 * session hash is calculated up to this message.
Packit 549fdc
	 */
Packit 549fdc
	if (recv_type == GNUTLS_HANDSHAKE_CLIENT_KEY_EXCHANGE)
Packit 549fdc
		session->internals.handshake_hash_buffer_client_kx_len =
Packit 549fdc
			session->internals.handshake_hash_buffer.length;
Packit 549fdc
Packit 549fdc
	return 0;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/* This function will store the handshake message we sent.
Packit 549fdc
 */
Packit 549fdc
static int
Packit 549fdc
handshake_hash_add_sent(gnutls_session_t session,
Packit 549fdc
				gnutls_handshake_description_t type,
Packit 549fdc
				uint8_t * dataptr, uint32_t datalen)
Packit 549fdc
{
Packit 549fdc
	int ret;
Packit 549fdc
	const version_entry_st *vers = get_version(session);
Packit 549fdc
Packit 549fdc
	if (unlikely(vers == NULL))
Packit 549fdc
		return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
Packit 549fdc
Packit 549fdc
	/* We don't check for GNUTLS_HANDSHAKE_HELLO_VERIFY_REQUEST because it
Packit 549fdc
	 * is not sent via that channel.
Packit 549fdc
	 */
Packit 549fdc
	if (type != GNUTLS_HANDSHAKE_HELLO_REQUEST) {
Packit 549fdc
		CHECK_SIZE(datalen);
Packit 549fdc
Packit 549fdc
		if (vers->id == GNUTLS_DTLS0_9) {
Packit 549fdc
			/* Old DTLS doesn't include the header in the MAC */
Packit 549fdc
			if (datalen < 12) {
Packit 549fdc
				gnutls_assert();
Packit 549fdc
				return GNUTLS_E_INTERNAL_ERROR;
Packit 549fdc
			}
Packit 549fdc
			dataptr += 12;
Packit 549fdc
			datalen -= 12;
Packit 549fdc
Packit 549fdc
			if (datalen == 0)
Packit 549fdc
				return 0;
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
		ret =
Packit 549fdc
		    _gnutls_buffer_append_data(&session->internals.
Packit 549fdc
					       handshake_hash_buffer,
Packit 549fdc
					       dataptr, datalen);
Packit 549fdc
		if (ret < 0)
Packit 549fdc
			return gnutls_assert_val(ret);
Packit 549fdc
Packit 549fdc
		if (type == GNUTLS_HANDSHAKE_CLIENT_KEY_EXCHANGE)
Packit 549fdc
			session->internals.handshake_hash_buffer_client_kx_len =
Packit 549fdc
				session->internals.handshake_hash_buffer.length;
Packit 549fdc
Packit 549fdc
		return 0;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	return 0;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/* This function will receive handshake messages of the given types,
Packit 549fdc
 * and will pass the message to the right place in order to be processed.
Packit 549fdc
 * E.g. for the SERVER_HELLO message (if it is expected), it will be
Packit 549fdc
 * passed to _gnutls_recv_hello().
Packit 549fdc
 */
Packit 549fdc
int
Packit 549fdc
_gnutls_recv_handshake(gnutls_session_t session,
Packit 549fdc
		       gnutls_handshake_description_t type,
Packit 549fdc
		       unsigned int optional, gnutls_buffer_st * buf)
Packit 549fdc
{
Packit 549fdc
	int ret, ret2;
Packit 549fdc
	handshake_buffer_st hsk;
Packit 549fdc
Packit 549fdc
	ret = _gnutls_handshake_io_recv_int(session, type, &hsk, optional);
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		if (optional != 0
Packit 549fdc
		    && ret == GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET) {
Packit 549fdc
			if (buf)
Packit 549fdc
				_gnutls_buffer_init(buf);
Packit 549fdc
			return 0;
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
		return gnutls_assert_val_fatal(ret);
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	session->internals.last_handshake_in = hsk.htype;
Packit 549fdc
Packit 549fdc
	ret = call_hook_func(session, hsk.htype, GNUTLS_HOOK_PRE, 1, hsk.data.data, hsk.data.length);
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		goto cleanup;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	ret = handshake_hash_add_recvd(session, hsk.htype,
Packit 549fdc
				       hsk.header, hsk.header_size,
Packit 549fdc
				       hsk.data.data,
Packit 549fdc
				       hsk.data.length);
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		goto cleanup;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	switch (hsk.htype) {
Packit 549fdc
	case GNUTLS_HANDSHAKE_CLIENT_HELLO_V2:
Packit 549fdc
	case GNUTLS_HANDSHAKE_CLIENT_HELLO:
Packit 549fdc
#ifdef ENABLE_SSL2
Packit 549fdc
		if (hsk.htype == GNUTLS_HANDSHAKE_CLIENT_HELLO_V2)
Packit 549fdc
			ret =
Packit 549fdc
			    _gnutls_read_client_hello_v2(session,
Packit 549fdc
							 hsk.data.data,
Packit 549fdc
							 hsk.data.length);
Packit 549fdc
		else
Packit 549fdc
#endif
Packit 549fdc
			ret = read_client_hello(session, hsk.data.data,
Packit 549fdc
						hsk.data.length);
Packit 549fdc
Packit 549fdc
		if (ret < 0) {
Packit 549fdc
			gnutls_assert();
Packit 549fdc
			goto cleanup;
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
		break;
Packit 549fdc
Packit 549fdc
	case GNUTLS_HANDSHAKE_SERVER_HELLO:
Packit 549fdc
		ret = read_server_hello(session, hsk.data.data,
Packit 549fdc
					hsk.data.length);
Packit 549fdc
Packit 549fdc
		if (ret < 0) {
Packit 549fdc
			gnutls_assert();
Packit 549fdc
			goto cleanup;
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
		break;
Packit 549fdc
	case GNUTLS_HANDSHAKE_HELLO_VERIFY_REQUEST:
Packit 549fdc
		ret =
Packit 549fdc
		    recv_hello_verify_request(session,
Packit 549fdc
					      hsk.data.data,
Packit 549fdc
					      hsk.data.length);
Packit 549fdc
		if (ret < 0) {
Packit 549fdc
			gnutls_assert();
Packit 549fdc
			goto cleanup;
Packit 549fdc
		} else {
Packit 549fdc
			/* Signal our caller we have received a verification cookie
Packit 549fdc
			   and ClientHello needs to be sent again. */
Packit 549fdc
			ret = 1;
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
		break;
Packit 549fdc
	case GNUTLS_HANDSHAKE_SERVER_HELLO_DONE:
Packit 549fdc
		if (hsk.data.length == 0)
Packit 549fdc
			ret = 0;
Packit 549fdc
		else {
Packit 549fdc
			gnutls_assert();
Packit 549fdc
			ret = GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
Packit 549fdc
			goto cleanup;
Packit 549fdc
		}
Packit 549fdc
		break;
Packit 549fdc
	case GNUTLS_HANDSHAKE_CERTIFICATE_PKT:
Packit 549fdc
	case GNUTLS_HANDSHAKE_CERTIFICATE_STATUS:
Packit 549fdc
	case GNUTLS_HANDSHAKE_FINISHED:
Packit 549fdc
	case GNUTLS_HANDSHAKE_SERVER_KEY_EXCHANGE:
Packit 549fdc
	case GNUTLS_HANDSHAKE_CLIENT_KEY_EXCHANGE:
Packit 549fdc
	case GNUTLS_HANDSHAKE_CERTIFICATE_REQUEST:
Packit 549fdc
	case GNUTLS_HANDSHAKE_CERTIFICATE_VERIFY:
Packit 549fdc
	case GNUTLS_HANDSHAKE_SUPPLEMENTAL:
Packit 549fdc
	case GNUTLS_HANDSHAKE_NEW_SESSION_TICKET:
Packit 549fdc
		ret = hsk.data.length;
Packit 549fdc
		break;
Packit 549fdc
	default:
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		/* we shouldn't actually arrive here in any case .
Packit 549fdc
		 * unexpected messages should be catched after _gnutls_handshake_io_recv_int()
Packit 549fdc
		 */
Packit 549fdc
		ret = GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET;
Packit 549fdc
		goto cleanup;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	ret2 = call_hook_func(session, hsk.htype, GNUTLS_HOOK_POST, 1, hsk.data.data, hsk.data.length);
Packit 549fdc
	if (ret2 < 0) {
Packit 549fdc
		ret = ret2;
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		goto cleanup;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	if (buf) {
Packit 549fdc
		*buf = hsk.data;
Packit 549fdc
		return ret;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
      cleanup:
Packit 549fdc
	_gnutls_handshake_buffer_clear(&hsk;;
Packit 549fdc
	return ret;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/* This function checks if the given cipher suite is supported, and sets it
Packit 549fdc
 * to the session;
Packit 549fdc
 */
Packit 549fdc
static int
Packit 549fdc
set_client_ciphersuite(gnutls_session_t session, uint8_t suite[2])
Packit 549fdc
{
Packit 549fdc
	unsigned j;
Packit 549fdc
	int ret;
Packit 549fdc
	const gnutls_cipher_suite_entry_st *selected = NULL;
Packit 549fdc
Packit 549fdc
	for (j = 0; j < session->internals.priorities->cs.size; j++) {
Packit 549fdc
		if (suite[0] == session->internals.priorities->cs.entry[j]->id[0] &&
Packit 549fdc
		    suite[1] == session->internals.priorities->cs.entry[j]->id[1]) {
Packit 549fdc
			selected = session->internals.priorities->cs.entry[j];
Packit 549fdc
			break;
Packit 549fdc
		}
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	if (!selected) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		_gnutls_handshake_log
Packit 549fdc
		    ("HSK[%p]: unsupported cipher suite %.2X.%.2X was negotiated\n",
Packit 549fdc
		     session, (unsigned int) suite[0],
Packit 549fdc
		     (unsigned int) suite[1]);
Packit 549fdc
		return GNUTLS_E_UNKNOWN_CIPHER_SUITE;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	ret = _gnutls_set_cipher_suite2(session, selected);
Packit 549fdc
	if (ret < 0)
Packit 549fdc
		return gnutls_assert_val(ret);
Packit 549fdc
Packit 549fdc
	_gnutls_handshake_log("HSK[%p]: Selected cipher suite: %s\n",
Packit 549fdc
			      session,
Packit 549fdc
			      selected->name);
Packit 549fdc
Packit 549fdc
	/* check if the credentials (username, public key etc.) are ok.
Packit 549fdc
	 * Actually checks if they exist.
Packit 549fdc
	 */
Packit 549fdc
	if (!session->internals.premaster_set &&
Packit 549fdc
	    _gnutls_get_kx_cred
Packit 549fdc
	    (session, selected->kx_algorithm) == NULL) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
Packit 549fdc
	/* set the mod_auth_st to the appropriate struct
Packit 549fdc
	 * according to the KX algorithm. This is needed since all the
Packit 549fdc
	 * handshake functions are read from there;
Packit 549fdc
	 */
Packit 549fdc
	session->internals.auth_struct =
Packit 549fdc
	    _gnutls_kx_auth_struct(selected->kx_algorithm);
Packit 549fdc
Packit 549fdc
	if (session->internals.auth_struct == NULL) {
Packit 549fdc
Packit 549fdc
		_gnutls_handshake_log
Packit 549fdc
		    ("HSK[%p]: Cannot find the appropriate handler for the KX algorithm\n",
Packit 549fdc
		     session);
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return GNUTLS_E_INTERNAL_ERROR;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	return 0;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/* This function returns 0 if we are resuming a session or -1 otherwise.
Packit 549fdc
 * This also sets the variables in the session. Used only while reading a server
Packit 549fdc
 * hello.
Packit 549fdc
 */
Packit 549fdc
static int
Packit 549fdc
client_check_if_resuming(gnutls_session_t session,
Packit 549fdc
				 uint8_t * session_id, int session_id_len)
Packit 549fdc
{
Packit 549fdc
	char buf[2 * GNUTLS_MAX_SESSION_ID_SIZE + 1];
Packit 549fdc
	int ret;
Packit 549fdc
Packit 549fdc
	_gnutls_handshake_log("HSK[%p]: SessionID length: %d\n", session,
Packit 549fdc
			      session_id_len);
Packit 549fdc
	_gnutls_handshake_log("HSK[%p]: SessionID: %s\n", session,
Packit 549fdc
			      _gnutls_bin2hex(session_id, session_id_len,
Packit 549fdc
					      buf, sizeof(buf), NULL));
Packit 549fdc
Packit 549fdc
	if ((session->internals.resumption_requested != 0 ||
Packit 549fdc
	     session->internals.premaster_set != 0) &&
Packit 549fdc
	    session_id_len > 0 &&
Packit 549fdc
	    session->internals.resumed_security_parameters.
Packit 549fdc
	    session_id_size == session_id_len
Packit 549fdc
	    && memcmp(session_id,
Packit 549fdc
		      session->internals.resumed_security_parameters.
Packit 549fdc
		      session_id, session_id_len) == 0) {
Packit 549fdc
		/* resume session */
Packit 549fdc
		memcpy(session->internals.resumed_security_parameters.
Packit 549fdc
		       server_random,
Packit 549fdc
		       session->security_parameters.server_random,
Packit 549fdc
		       GNUTLS_RANDOM_SIZE);
Packit 549fdc
		memcpy(session->internals.resumed_security_parameters.
Packit 549fdc
		       client_random,
Packit 549fdc
		       session->security_parameters.client_random,
Packit 549fdc
		       GNUTLS_RANDOM_SIZE);
Packit 549fdc
Packit 549fdc
		ret = _gnutls_set_cipher_suite2
Packit 549fdc
		    (session,
Packit 549fdc
		     session->internals.resumed_security_parameters.
Packit 549fdc
		     cs);
Packit 549fdc
		if (ret < 0) {
Packit 549fdc
			gnutls_assert();
Packit 549fdc
			goto no_resume;
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
		session->internals.resumed = RESUME_TRUE;	/* we are resuming */
Packit 549fdc
Packit 549fdc
		return 0;
Packit 549fdc
	} else {
Packit 549fdc
no_resume:
Packit 549fdc
		/* keep the new session id */
Packit 549fdc
		session->internals.resumed = RESUME_FALSE;	/* we are not resuming */
Packit 549fdc
		session->security_parameters.session_id_size =
Packit 549fdc
		    session_id_len;
Packit 549fdc
		if (session_id_len > 0) {
Packit 549fdc
			memcpy(session->security_parameters.session_id, session_id,
Packit 549fdc
			       session_id_len);
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
		return -1;
Packit 549fdc
	}
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
Packit 549fdc
/* This function reads and parses the server hello handshake message.
Packit 549fdc
 * This function also restores resumed parameters if we are resuming a
Packit 549fdc
 * session.
Packit 549fdc
 */
Packit 549fdc
static int
Packit 549fdc
read_server_hello(gnutls_session_t session,
Packit 549fdc
		  uint8_t * data, int datalen)
Packit 549fdc
{
Packit 549fdc
	uint8_t session_id_len = 0;
Packit 549fdc
	int pos = 0;
Packit 549fdc
	int ret = 0;
Packit 549fdc
	gnutls_protocol_t version;
Packit 549fdc
	int len = datalen;
Packit 549fdc
Packit 549fdc
	if (datalen < 38) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	_gnutls_handshake_log("HSK[%p]: Server's version: %d.%d\n",
Packit 549fdc
			      session, data[pos], data[pos + 1]);
Packit 549fdc
Packit 549fdc
	DECR_LEN(len, 2);
Packit 549fdc
	version = _gnutls_version_get(data[pos], data[pos + 1]);
Packit 549fdc
	if (_gnutls_version_is_supported(session, version) == 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	if (_gnutls_set_current_version(session, version) < 0)
Packit 549fdc
		return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
Packit 549fdc
Packit 549fdc
	pos += 2;
Packit 549fdc
Packit 549fdc
	DECR_LEN(len, GNUTLS_RANDOM_SIZE);
Packit 549fdc
	ret = _gnutls_set_server_random(session, &data[pos]);
Packit 549fdc
	if (ret < 0)
Packit 549fdc
		return gnutls_assert_val(ret);
Packit 549fdc
Packit 549fdc
	pos += GNUTLS_RANDOM_SIZE;
Packit 549fdc
Packit 549fdc
Packit 549fdc
	/* Read session ID
Packit 549fdc
	 */
Packit 549fdc
	DECR_LEN(len, 1);
Packit 549fdc
	session_id_len = data[pos++];
Packit 549fdc
Packit 549fdc
	if (len < session_id_len || session_id_len > GNUTLS_MAX_SESSION_ID_SIZE) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return GNUTLS_E_ILLEGAL_PARAMETER;
Packit 549fdc
	}
Packit 549fdc
	DECR_LEN(len, session_id_len);
Packit 549fdc
Packit 549fdc
	/* check if we are resuming and set the appropriate
Packit 549fdc
	 * values;
Packit 549fdc
	 */
Packit 549fdc
	if (client_check_if_resuming
Packit 549fdc
	    (session, &data[pos], session_id_len) == 0) {
Packit 549fdc
		pos += session_id_len + 2 + 1;
Packit 549fdc
		DECR_LEN(len, 2 + 1);
Packit 549fdc
Packit 549fdc
		ret =
Packit 549fdc
		    _gnutls_parse_extensions(session, GNUTLS_EXT_MANDATORY,
Packit 549fdc
					     &data[pos], len);
Packit 549fdc
		if (ret < 0) {
Packit 549fdc
			gnutls_assert();
Packit 549fdc
			return ret;
Packit 549fdc
		}
Packit 549fdc
		return 0;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	pos += session_id_len;
Packit 549fdc
Packit 549fdc
	/* Check if the given cipher suite is supported and copy
Packit 549fdc
	 * it to the session.
Packit 549fdc
	 */
Packit 549fdc
Packit 549fdc
	DECR_LEN(len, 2);
Packit 549fdc
	ret = set_client_ciphersuite(session, &data[pos]);
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return ret;
Packit 549fdc
	}
Packit 549fdc
	pos += 2;
Packit 549fdc
Packit 549fdc
	/* move to compression 
Packit 549fdc
	 */
Packit 549fdc
	DECR_LEN(len, 1);
Packit 549fdc
	pos++;
Packit 549fdc
Packit 549fdc
	/* Parse extensions.
Packit 549fdc
	 */
Packit 549fdc
	ret =
Packit 549fdc
	    _gnutls_parse_extensions(session, GNUTLS_EXT_ANY, &data[pos],
Packit 549fdc
				     len);
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return ret;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	return ret;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/* This function copies the appropriate compression methods, to a locally allocated buffer 
Packit 549fdc
 * Needed in hello messages. Returns the new data length.
Packit 549fdc
 */
Packit 549fdc
static int
Packit 549fdc
append_null_comp(gnutls_session_t session,
Packit 549fdc
			  gnutls_buffer_st * cdata)
Packit 549fdc
{
Packit 549fdc
	uint8_t compression_methods[2] = {0x01, 0x00};
Packit 549fdc
	size_t init_length = cdata->length;
Packit 549fdc
	int ret;
Packit 549fdc
Packit 549fdc
	ret =
Packit 549fdc
	    _gnutls_buffer_append_data(cdata, compression_methods, 2);
Packit 549fdc
	if (ret < 0)
Packit 549fdc
		return gnutls_assert_val(ret);
Packit 549fdc
Packit 549fdc
	ret = cdata->length - init_length;
Packit 549fdc
Packit 549fdc
	return ret;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/* This function sends the client hello handshake message.
Packit 549fdc
 */
Packit 549fdc
static int send_client_hello(gnutls_session_t session, int again)
Packit 549fdc
{
Packit 549fdc
	mbuffer_st *bufel = NULL;
Packit 549fdc
	int type;
Packit 549fdc
	int ret = 0;
Packit 549fdc
	const version_entry_st *hver, *min_ver;
Packit 549fdc
	uint8_t tver[2];
Packit 549fdc
	gnutls_buffer_st extdata;
Packit 549fdc
	int rehandshake = 0;
Packit 549fdc
	unsigned add_sr_scsv = 0;
Packit 549fdc
	uint8_t session_id_len =
Packit 549fdc
	    session->internals.resumed_security_parameters.session_id_size;
Packit 549fdc
Packit 549fdc
	_gnutls_buffer_init(&extdata);
Packit 549fdc
Packit 549fdc
Packit 549fdc
	/* note that rehandshake is different than resuming
Packit 549fdc
	 */
Packit 549fdc
	if (session->security_parameters.session_id_size)
Packit 549fdc
		rehandshake = 1;
Packit 549fdc
Packit 549fdc
	if (again == 0) {
Packit 549fdc
		/* if we are resuming a session then we set the
Packit 549fdc
		 * version number to the previously established.
Packit 549fdc
		 */
Packit 549fdc
		if (session->internals.resumption_requested == 0 &&
Packit 549fdc
		    session->internals.premaster_set == 0) {
Packit 549fdc
			if (rehandshake)	/* already negotiated version thus version_max == negotiated version */
Packit 549fdc
				hver = get_version(session);
Packit 549fdc
			else	/* new handshake. just get the max */
Packit 549fdc
				hver =
Packit 549fdc
				    version_to_entry(_gnutls_version_max
Packit 549fdc
						     (session));
Packit 549fdc
		} else {
Packit 549fdc
			/* we are resuming a session */
Packit 549fdc
			hver =
Packit 549fdc
			    session->internals.resumed_security_parameters.
Packit 549fdc
			    pversion;
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
		if (hver == NULL) {
Packit 549fdc
			gnutls_assert();
Packit 549fdc
			return GNUTLS_E_NO_PRIORITIES_WERE_SET;
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
		if (unlikely(session->internals.default_hello_version[0] != 0)) {
Packit 549fdc
			tver[0] = session->internals.default_hello_version[0];
Packit 549fdc
			tver[1] = session->internals.default_hello_version[1];
Packit 549fdc
		} else {
Packit 549fdc
			tver[0] = hver->major;
Packit 549fdc
			tver[1] = hver->minor;
Packit 549fdc
		}
Packit 549fdc
		ret = _gnutls_buffer_append_data(&extdata, tver, 2);
Packit 549fdc
		if (ret < 0) {
Packit 549fdc
			gnutls_assert();
Packit 549fdc
			goto cleanup;
Packit 549fdc
		}
Packit 549fdc
		_gnutls_handshake_log("HSK[%p]: Adv. version: %u.%u\n", session,
Packit 549fdc
				      (unsigned)tver[0], (unsigned)tver[1]);
Packit 549fdc
Packit 549fdc
		min_ver = _gnutls_version_lowest(session);
Packit 549fdc
		if (min_ver == NULL) {
Packit 549fdc
			gnutls_assert();
Packit 549fdc
			ret = GNUTLS_E_NO_PRIORITIES_WERE_SET;
Packit 549fdc
			goto cleanup;
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
		/* Set the version we advertized as maximum 
Packit 549fdc
		 * (RSA uses it).
Packit 549fdc
		 */
Packit 549fdc
		set_adv_version(session, hver->major, hver->minor);
Packit 549fdc
		if (_gnutls_set_current_version(session, hver->id) < 0)
Packit 549fdc
			return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
Packit 549fdc
Packit 549fdc
		if (session->internals.priorities->min_record_version != 0) {
Packit 549fdc
			/* Advertize the lowest supported (SSL 3.0) record packet
Packit 549fdc
			 * version in record packets during the handshake.
Packit 549fdc
			 * That is to avoid confusing implementations
Packit 549fdc
			 * that do not support TLS 1.2 and don't know
Packit 549fdc
			 * how 3,3 version of record packets look like.
Packit 549fdc
			 */
Packit 549fdc
			_gnutls_record_set_default_version(session,
Packit 549fdc
							   min_ver->major, min_ver->minor);
Packit 549fdc
		} else {
Packit 549fdc
			_gnutls_record_set_default_version(session,
Packit 549fdc
							   hver->major, hver->minor);
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
		/* In order to know when this session was initiated.
Packit 549fdc
		 */
Packit 549fdc
		session->security_parameters.timestamp = gnutls_time(NULL);
Packit 549fdc
Packit 549fdc
		/* Generate random data 
Packit 549fdc
		 */
Packit 549fdc
		if (!IS_DTLS(session)
Packit 549fdc
		    || session->internals.dtls.hsk_hello_verify_requests ==
Packit 549fdc
		    0) {
Packit 549fdc
			ret = _gnutls_set_client_random(session, NULL);
Packit 549fdc
			if (ret < 0)
Packit 549fdc
				return gnutls_assert_val(ret);
Packit 549fdc
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
		ret = _gnutls_buffer_append_data(&extdata,
Packit 549fdc
					session->security_parameters.client_random,
Packit 549fdc
					GNUTLS_RANDOM_SIZE);
Packit 549fdc
		if (ret < 0) {
Packit 549fdc
			gnutls_assert();
Packit 549fdc
			goto cleanup;
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
		/* Copy the Session ID 
Packit 549fdc
		 */
Packit 549fdc
		ret = _gnutls_buffer_append_data_prefix(&extdata, 8, 
Packit 549fdc
						session->internals.resumed_security_parameters.session_id,
Packit 549fdc
						session_id_len);
Packit 549fdc
		if (ret < 0) {
Packit 549fdc
			gnutls_assert();
Packit 549fdc
			goto cleanup;
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
		/* Copy the DTLS cookie
Packit 549fdc
		 */
Packit 549fdc
		if (IS_DTLS(session)) {
Packit 549fdc
			ret = _gnutls_buffer_append_data_prefix(&extdata, 8, session->internals.dtls.cookie,
Packit 549fdc
				session->internals.dtls.cookie_len);
Packit 549fdc
			if (ret < 0) {
Packit 549fdc
				gnutls_assert();
Packit 549fdc
				goto cleanup;
Packit 549fdc
			}
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
		/* Copy the ciphersuites.
Packit 549fdc
		 */
Packit 549fdc
#ifdef ENABLE_SSL3
Packit 549fdc
		/* If using SSLv3 Send TLS_RENEGO_PROTECTION_REQUEST SCSV for MITM
Packit 549fdc
		 * prevention on initial negotiation (but not renegotiation; that's
Packit 549fdc
		 * handled with the RI extension below).
Packit 549fdc
		 */
Packit 549fdc
		if (!session->internals.initial_negotiation_completed &&
Packit 549fdc
		    session->security_parameters.entity == GNUTLS_CLIENT &&
Packit 549fdc
		    (hver->id == GNUTLS_SSL3 &&
Packit 549fdc
		     session->internals.priorities->no_extensions != 0)) {
Packit 549fdc
			add_sr_scsv = 1;
Packit 549fdc
		}
Packit 549fdc
#endif
Packit 549fdc
		ret = _gnutls_get_client_ciphersuites(session, &extdata, min_ver, hver, add_sr_scsv);
Packit 549fdc
		if (ret < 0) {
Packit 549fdc
			gnutls_assert();
Packit 549fdc
			goto cleanup;
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
		/* Copy the compression methods.
Packit 549fdc
		 */
Packit 549fdc
		ret = append_null_comp(session, &extdata);
Packit 549fdc
		if (ret < 0) {
Packit 549fdc
			gnutls_assert();
Packit 549fdc
			goto cleanup;
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
		/* Generate and copy TLS extensions.
Packit 549fdc
		 */
Packit 549fdc
		if (session->internals.priorities->no_extensions == 0) {
Packit 549fdc
			if (_gnutls_version_has_extensions(hver)) {
Packit 549fdc
				type = GNUTLS_EXT_ANY;
Packit 549fdc
			} else {
Packit 549fdc
				type = GNUTLS_EXT_MANDATORY;
Packit 549fdc
			}
Packit 549fdc
Packit 549fdc
			ret =
Packit 549fdc
			    _gnutls_gen_extensions(session, &extdata,
Packit 549fdc
						   type);
Packit 549fdc
			if (ret < 0) {
Packit 549fdc
				gnutls_assert();
Packit 549fdc
				goto cleanup;
Packit 549fdc
			}
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
		bufel =
Packit 549fdc
		    _gnutls_handshake_alloc(session, extdata.length);
Packit 549fdc
		if (bufel == NULL) {
Packit 549fdc
			gnutls_assert();
Packit 549fdc
			ret = GNUTLS_E_MEMORY_ERROR;
Packit 549fdc
			goto cleanup; 
Packit 549fdc
		}
Packit 549fdc
		_mbuffer_set_udata_size(bufel, 0);
Packit 549fdc
Packit 549fdc
		ret =
Packit 549fdc
		    _mbuffer_append_data(bufel, extdata.data,
Packit 549fdc
					 extdata.length);
Packit 549fdc
		if (ret < 0) {
Packit 549fdc
			gnutls_assert();
Packit 549fdc
			goto cleanup;
Packit 549fdc
		}
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	_gnutls_buffer_clear(&extdata);
Packit 549fdc
Packit 549fdc
	return
Packit 549fdc
	    _gnutls_send_handshake(session, bufel,
Packit 549fdc
				   GNUTLS_HANDSHAKE_CLIENT_HELLO);
Packit 549fdc
Packit 549fdc
      cleanup:
Packit 549fdc
	_mbuffer_xfree(&bufel);
Packit 549fdc
	_gnutls_buffer_clear(&extdata);
Packit 549fdc
	return ret;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
static int send_server_hello(gnutls_session_t session, int again)
Packit 549fdc
{
Packit 549fdc
	mbuffer_st *bufel = NULL;
Packit 549fdc
	uint8_t *data = NULL;
Packit 549fdc
	gnutls_buffer_st extdata;
Packit 549fdc
	int pos = 0;
Packit 549fdc
	int datalen, ret = 0;
Packit 549fdc
	uint8_t session_id_len =
Packit 549fdc
	    session->security_parameters.session_id_size;
Packit 549fdc
	char buf[2 * GNUTLS_MAX_SESSION_ID_SIZE + 1];
Packit 549fdc
	const version_entry_st *vers;
Packit 549fdc
Packit 549fdc
	_gnutls_buffer_init(&extdata);
Packit 549fdc
Packit 549fdc
	if (again == 0) {
Packit 549fdc
		datalen = 2 + session_id_len + 1 + GNUTLS_RANDOM_SIZE + 3;
Packit 549fdc
		ret =
Packit 549fdc
		    _gnutls_gen_extensions(session, &extdata,
Packit 549fdc
					   (session->internals.resumed ==
Packit 549fdc
					    RESUME_TRUE) ?
Packit 549fdc
					   GNUTLS_EXT_MANDATORY :
Packit 549fdc
					   GNUTLS_EXT_ANY);
Packit 549fdc
		if (ret < 0) {
Packit 549fdc
			gnutls_assert();
Packit 549fdc
			goto fail;
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
		bufel =
Packit 549fdc
		    _gnutls_handshake_alloc(session,
Packit 549fdc
					    datalen + extdata.length);
Packit 549fdc
		if (bufel == NULL) {
Packit 549fdc
			gnutls_assert();
Packit 549fdc
			ret = GNUTLS_E_MEMORY_ERROR;
Packit 549fdc
			goto fail;
Packit 549fdc
		}
Packit 549fdc
		data = _mbuffer_get_udata_ptr(bufel);
Packit 549fdc
Packit 549fdc
		vers = get_version(session);
Packit 549fdc
		if (unlikely(vers == NULL))
Packit 549fdc
			return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
Packit 549fdc
Packit 549fdc
		data[pos++] = vers->major;
Packit 549fdc
		data[pos++] = vers->minor;
Packit 549fdc
Packit 549fdc
		memcpy(&data[pos],
Packit 549fdc
		       session->security_parameters.server_random,
Packit 549fdc
		       GNUTLS_RANDOM_SIZE);
Packit 549fdc
		pos += GNUTLS_RANDOM_SIZE;
Packit 549fdc
Packit 549fdc
		data[pos++] = session_id_len;
Packit 549fdc
		if (session_id_len > 0) {
Packit 549fdc
			memcpy(&data[pos],
Packit 549fdc
			       session->security_parameters.session_id,
Packit 549fdc
			       session_id_len);
Packit 549fdc
		}
Packit 549fdc
		pos += session_id_len;
Packit 549fdc
Packit 549fdc
		_gnutls_handshake_log("HSK[%p]: SessionID: %s\n", session,
Packit 549fdc
				      _gnutls_bin2hex(session->
Packit 549fdc
						      security_parameters.session_id,
Packit 549fdc
						      session_id_len, buf,
Packit 549fdc
						      sizeof(buf), NULL));
Packit 549fdc
Packit 549fdc
		memcpy(&data[pos],
Packit 549fdc
		       session->security_parameters.cs->id, 2);
Packit 549fdc
		pos += 2;
Packit 549fdc
Packit 549fdc
		data[pos++] = 0x00;
Packit 549fdc
Packit 549fdc
		if (extdata.length > 0) {
Packit 549fdc
			memcpy(&data[pos], extdata.data, extdata.length);
Packit 549fdc
		}
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	ret =
Packit 549fdc
	    _gnutls_send_handshake(session, bufel,
Packit 549fdc
				   GNUTLS_HANDSHAKE_SERVER_HELLO);
Packit 549fdc
Packit 549fdc
      fail:
Packit 549fdc
	_gnutls_buffer_clear(&extdata);
Packit 549fdc
	return ret;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
static int
Packit 549fdc
recv_hello_verify_request(gnutls_session_t session,
Packit 549fdc
				  uint8_t * data, int datalen)
Packit 549fdc
{
Packit 549fdc
	ssize_t len = datalen;
Packit 549fdc
	size_t pos = 0;
Packit 549fdc
	uint8_t cookie_len;
Packit 549fdc
	unsigned int nb_verifs;
Packit 549fdc
Packit 549fdc
	if (!IS_DTLS(session)
Packit 549fdc
	    || session->security_parameters.entity == GNUTLS_SERVER) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return GNUTLS_E_INTERNAL_ERROR;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	nb_verifs = ++session->internals.dtls.hsk_hello_verify_requests;
Packit 549fdc
	if (nb_verifs >= MAX_HANDSHAKE_HELLO_VERIFY_REQUESTS) {
Packit 549fdc
		/* The server is either buggy, malicious or changing cookie
Packit 549fdc
		   secrets _way_ too fast. */
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return GNUTLS_E_UNEXPECTED_PACKET;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	/* TODO: determine if we need to do anything with the server version field */
Packit 549fdc
	DECR_LEN(len, 2);
Packit 549fdc
	pos += 2;
Packit 549fdc
Packit 549fdc
	DECR_LEN(len, 1);
Packit 549fdc
	cookie_len = data[pos];
Packit 549fdc
	pos++;
Packit 549fdc
Packit 549fdc
	if (cookie_len > DTLS_MAX_COOKIE_SIZE) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	DECR_LEN(len, cookie_len);
Packit 549fdc
Packit 549fdc
	session->internals.dtls.cookie_len = cookie_len;
Packit 549fdc
	memcpy(session->internals.dtls.cookie, &data[pos], cookie_len);
Packit 549fdc
Packit 549fdc
	if (len != 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	/* reset handshake hash buffers */
Packit 549fdc
	handshake_hash_buffer_empty(session);
Packit 549fdc
Packit 549fdc
	return 0;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/* The packets in gnutls_handshake (it's more broad than original TLS handshake)
Packit 549fdc
 *
Packit 549fdc
 *     Client					       Server
Packit 549fdc
 *
Packit 549fdc
 *     ClientHello		  -------->
Packit 549fdc
 *				  <--------	 ServerHello
Packit 549fdc
 *
Packit 549fdc
 *						    Certificate*
Packit 549fdc
 *					      ServerKeyExchange*
Packit 549fdc
 *				  <--------   CertificateRequest*
Packit 549fdc
 *
Packit 549fdc
 *				  <--------      ServerHelloDone
Packit 549fdc
 *     Certificate*
Packit 549fdc
 *     ClientKeyExchange
Packit 549fdc
 *     CertificateVerify*
Packit 549fdc
 *     [ChangeCipherSpec]
Packit 549fdc
 *     Finished		     -------->
Packit 549fdc
 *						NewSessionTicket
Packit 549fdc
 *					      [ChangeCipherSpec]
Packit 549fdc
 *				  <--------	     Finished
Packit 549fdc
 *
Packit 549fdc
 * (*): means optional packet.
Packit 549fdc
 */
Packit 549fdc
Packit 549fdc
/* Handshake when resumming session:
Packit 549fdc
 *      Client						Server
Packit 549fdc
 *
Packit 549fdc
 *      ClientHello		   -------->
Packit 549fdc
 *						      ServerHello
Packit 549fdc
 *					       [ChangeCipherSpec]
Packit 549fdc
 *				   <--------	     Finished
Packit 549fdc
 *     [ChangeCipherSpec]
Packit 549fdc
 *     Finished		      -------->
Packit 549fdc
 * 
Packit 549fdc
 */
Packit 549fdc
Packit 549fdc
/**
Packit 549fdc
 * gnutls_rehandshake:
Packit 549fdc
 * @session: is a #gnutls_session_t type.
Packit 549fdc
 *
Packit 549fdc
 * This function will renegotiate security parameters with the
Packit 549fdc
 * client.  This should only be called in case of a server.
Packit 549fdc
 *
Packit 549fdc
 * This message informs the peer that we want to renegotiate
Packit 549fdc
 * parameters (perform a handshake).
Packit 549fdc
 *
Packit 549fdc
 * If this function succeeds (returns 0), you must call the
Packit 549fdc
 * gnutls_handshake() function in order to negotiate the new
Packit 549fdc
 * parameters.
Packit 549fdc
 *
Packit 549fdc
 * Since TLS is full duplex some application data might have been
Packit 549fdc
 * sent during peer's processing of this message. In that case
Packit 549fdc
 * one should call gnutls_record_recv() until GNUTLS_E_REHANDSHAKE
Packit 549fdc
 * is returned to clear any pending data. Care must be taken, if
Packit 549fdc
 * rehandshake is mandatory, to terminate if it does not start after
Packit 549fdc
 * some threshold.
Packit 549fdc
 *
Packit 549fdc
 * If the client does not wish to renegotiate parameters he 
Packit 549fdc
 * should reply with an alert message, thus the return code will be
Packit 549fdc
 * %GNUTLS_E_WARNING_ALERT_RECEIVED and the alert will be
Packit 549fdc
 * %GNUTLS_A_NO_RENEGOTIATION.  A client may also choose to ignore
Packit 549fdc
 * this message.
Packit 549fdc
 *
Packit 549fdc
 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
Packit 549fdc
 **/
Packit 549fdc
int gnutls_rehandshake(gnutls_session_t session)
Packit 549fdc
{
Packit 549fdc
	int ret;
Packit 549fdc
Packit 549fdc
	/* only server sends that handshake packet */
Packit 549fdc
	if (session->security_parameters.entity == GNUTLS_CLIENT)
Packit 549fdc
		return GNUTLS_E_INVALID_REQUEST;
Packit 549fdc
Packit 549fdc
	_dtls_async_timer_delete(session);
Packit 549fdc
Packit 549fdc
	ret =
Packit 549fdc
	    _gnutls_send_empty_handshake(session,
Packit 549fdc
					 GNUTLS_HANDSHAKE_HELLO_REQUEST,
Packit 549fdc
					 AGAIN(STATE50));
Packit 549fdc
	STATE = STATE50;
Packit 549fdc
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return ret;
Packit 549fdc
	}
Packit 549fdc
	STATE = STATE0;
Packit 549fdc
Packit 549fdc
	return 0;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
inline static int
Packit 549fdc
_gnutls_abort_handshake(gnutls_session_t session, int ret)
Packit 549fdc
{
Packit 549fdc
	if (((ret == GNUTLS_E_WARNING_ALERT_RECEIVED) &&
Packit 549fdc
	     (gnutls_alert_get(session) == GNUTLS_A_NO_RENEGOTIATION))
Packit 549fdc
	    || ret == GNUTLS_E_GOT_APPLICATION_DATA)
Packit 549fdc
		return 0;
Packit 549fdc
Packit 549fdc
	/* this doesn't matter */
Packit 549fdc
	return GNUTLS_E_INTERNAL_ERROR;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
Packit 549fdc
Packit 549fdc
static int _gnutls_send_supplemental(gnutls_session_t session, int again)
Packit 549fdc
{
Packit 549fdc
	mbuffer_st *bufel;
Packit 549fdc
	int ret = 0;
Packit 549fdc
Packit 549fdc
	_gnutls_debug_log("EXT[%p]: Sending supplemental data\n", session);
Packit 549fdc
Packit 549fdc
	if (again)
Packit 549fdc
		ret =
Packit 549fdc
		    _gnutls_send_handshake(session, NULL,
Packit 549fdc
					   GNUTLS_HANDSHAKE_SUPPLEMENTAL);
Packit 549fdc
	else {
Packit 549fdc
		gnutls_buffer_st buf;
Packit 549fdc
		_gnutls_buffer_init(&buf;;
Packit 549fdc
Packit 549fdc
		ret = _gnutls_gen_supplemental(session, &buf;;
Packit 549fdc
		if (ret < 0) {
Packit 549fdc
			gnutls_assert();
Packit 549fdc
			return ret;
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
		bufel =
Packit 549fdc
		    _gnutls_handshake_alloc(session, 
Packit 549fdc
					    buf.length);
Packit 549fdc
		if (bufel == NULL) {
Packit 549fdc
			gnutls_assert();
Packit 549fdc
			return GNUTLS_E_MEMORY_ERROR;
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
		_mbuffer_set_udata(bufel, buf.data, buf.length);
Packit 549fdc
		_gnutls_buffer_clear(&buf;;
Packit 549fdc
Packit 549fdc
		ret = _gnutls_send_handshake(session, bufel,
Packit 549fdc
					     GNUTLS_HANDSHAKE_SUPPLEMENTAL);
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	return ret;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
static int _gnutls_recv_supplemental(gnutls_session_t session)
Packit 549fdc
{
Packit 549fdc
	gnutls_buffer_st buf;
Packit 549fdc
	int ret;
Packit 549fdc
Packit 549fdc
	_gnutls_debug_log("EXT[%p]: Expecting supplemental data\n",
Packit 549fdc
			  session);
Packit 549fdc
Packit 549fdc
	ret =
Packit 549fdc
	    _gnutls_recv_handshake(session, GNUTLS_HANDSHAKE_SUPPLEMENTAL,
Packit 549fdc
				   1, &buf;;
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return ret;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	ret = _gnutls_parse_supplemental(session, buf.data, buf.length);
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		goto cleanup;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
      cleanup:
Packit 549fdc
	_gnutls_buffer_clear(&buf;;
Packit 549fdc
Packit 549fdc
	return ret;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/**
Packit 549fdc
 * gnutls_handshake:
Packit 549fdc
 * @session: is a #gnutls_session_t type.
Packit 549fdc
 *
Packit 549fdc
 * This function does the handshake of the TLS/SSL protocol, and
Packit 549fdc
 * initializes the TLS connection.
Packit 549fdc
 *
Packit 549fdc
 * This function will fail if any problem is encountered, and will
Packit 549fdc
 * return a negative error code. In case of a client, if the client
Packit 549fdc
 * has asked to resume a session, but the server couldn't, then a
Packit 549fdc
 * full handshake will be performed.
Packit 549fdc
 *
Packit 549fdc
 * The non-fatal errors expected by this function are:
Packit 549fdc
 * %GNUTLS_E_INTERRUPTED, %GNUTLS_E_AGAIN, 
Packit 549fdc
 * %GNUTLS_E_WARNING_ALERT_RECEIVED, and %GNUTLS_E_GOT_APPLICATION_DATA,
Packit 549fdc
 * the latter only in a case of rehandshake.
Packit 549fdc
 *
Packit 549fdc
 * The former two interrupt the handshake procedure due to the lower
Packit 549fdc
 * layer being interrupted, and the latter because of an alert that
Packit 549fdc
 * may be sent by a server (it is always a good idea to check any
Packit 549fdc
 * received alerts). On these errors call this function again, until it
Packit 549fdc
 * returns 0; cf.  gnutls_record_get_direction() and
Packit 549fdc
 * gnutls_error_is_fatal(). In DTLS sessions the non-fatal error
Packit 549fdc
 * %GNUTLS_E_LARGE_PACKET is also possible, and indicates that
Packit 549fdc
 * the MTU should be adjusted.
Packit 549fdc
 *
Packit 549fdc
 * If this function is called by a server after a rehandshake request
Packit 549fdc
 * then %GNUTLS_E_GOT_APPLICATION_DATA or
Packit 549fdc
 * %GNUTLS_E_WARNING_ALERT_RECEIVED may be returned.  Note that these
Packit 549fdc
 * are non fatal errors, only in the specific case of a rehandshake.
Packit 549fdc
 * Their meaning is that the client rejected the rehandshake request or
Packit 549fdc
 * in the case of %GNUTLS_E_GOT_APPLICATION_DATA it could also mean that
Packit 549fdc
 * some data were pending. A client may receive that error code if
Packit 549fdc
 * it initiates the handshake and the server doesn't agreed.
Packit 549fdc
 *
Packit 549fdc
 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
Packit 549fdc
 **/
Packit 549fdc
int gnutls_handshake(gnutls_session_t session)
Packit 549fdc
{
Packit 549fdc
	int ret;
Packit 549fdc
Packit 549fdc
	/* sanity check. Verify that there are priorities setup.
Packit 549fdc
	 */
Packit 549fdc
Packit 549fdc
	if (STATE == STATE0) {
Packit 549fdc
		/* first call */
Packit 549fdc
		if (session->internals.priorities == NULL ||
Packit 549fdc
		    session->internals.priorities->cs.size == 0)
Packit 549fdc
			return gnutls_assert_val(GNUTLS_E_NO_PRIORITIES_WERE_SET);
Packit 549fdc
Packit 549fdc
		ret =
Packit 549fdc
		    _gnutls_epoch_new(session, 0, NULL);
Packit 549fdc
		if (ret < 0)
Packit 549fdc
			return gnutls_assert_val(ret);
Packit 549fdc
Packit 549fdc
		session->internals.used_exts_size = 0;
Packit 549fdc
		session->internals.crt_requested = 0;
Packit 549fdc
		session->internals.handshake_in_progress = 1;
Packit 549fdc
		session->internals.vc_status = -1;
Packit 549fdc
		gettime(&session->internals.handshake_start_time);
Packit 549fdc
		if (session->internals.handshake_timeout_ms &&
Packit 549fdc
		    session->internals.handshake_endtime == 0)
Packit 549fdc
			    session->internals.handshake_endtime = session->internals.handshake_start_time.tv_sec +
Packit 549fdc
			    session->internals.handshake_timeout_ms / 1000;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	if (session->internals.recv_state == RECV_STATE_FALSE_START) {
Packit 549fdc
		session_invalidate(session);
Packit 549fdc
		return gnutls_assert_val(GNUTLS_E_HANDSHAKE_DURING_FALSE_START);
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	if (session->security_parameters.entity == GNUTLS_CLIENT) {
Packit 549fdc
		do {
Packit 549fdc
			ret = handshake_client(session);
Packit 549fdc
		} while (ret == 1);
Packit 549fdc
	} else {
Packit 549fdc
		ret = handshake_server(session);
Packit 549fdc
	}
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		/* In the case of a rehandshake abort
Packit 549fdc
		 * we should reset the handshake's internal state.
Packit 549fdc
		 */
Packit 549fdc
		if (_gnutls_abort_handshake(session, ret) == 0)
Packit 549fdc
			STATE = STATE0;
Packit 549fdc
Packit 549fdc
		return ret;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	/* clear handshake buffer */
Packit 549fdc
	if (session->security_parameters.entity != GNUTLS_CLIENT ||
Packit 549fdc
	    !(session->internals.flags & GNUTLS_ENABLE_FALSE_START) ||
Packit 549fdc
	    session->internals.recv_state != RECV_STATE_FALSE_START) {
Packit 549fdc
Packit 549fdc
		_gnutls_handshake_hash_buffers_clear(session);
Packit 549fdc
Packit 549fdc
		if (IS_DTLS(session) == 0) {
Packit 549fdc
			_gnutls_handshake_io_buffer_clear(session);
Packit 549fdc
		} else {
Packit 549fdc
			_dtls_async_timer_init(session);
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
		_gnutls_handshake_internal_state_clear(session);
Packit 549fdc
Packit 549fdc
		_gnutls_epoch_bump(session);
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	return 0;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/**
Packit 549fdc
 * gnutls_handshake_set_timeout:
Packit 549fdc
 * @session: is a #gnutls_session_t type.
Packit 549fdc
 * @ms: is a timeout value in milliseconds
Packit 549fdc
 *
Packit 549fdc
 * This function sets the timeout for the TLS handshake process
Packit 549fdc
 * to the provided value. Use an @ms value of zero to disable
Packit 549fdc
 * timeout, or %GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT for a reasonable
Packit 549fdc
 * default value. For the DTLS protocol, the more detailed
Packit 549fdc
 * gnutls_dtls_set_timeouts() is provided.
Packit 549fdc
 *
Packit 549fdc
 * This function requires to set a pull timeout callback. See
Packit 549fdc
 * gnutls_transport_set_pull_timeout_function().
Packit 549fdc
 *
Packit 549fdc
 * Since: 3.1.0
Packit 549fdc
 **/
Packit 549fdc
void
Packit 549fdc
gnutls_handshake_set_timeout(gnutls_session_t session, unsigned int ms)
Packit 549fdc
{
Packit 549fdc
	if (ms == GNUTLS_INDEFINITE_TIMEOUT) {
Packit 549fdc
		session->internals.handshake_timeout_ms = 0;
Packit 549fdc
		return;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	if (ms == GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT)
Packit 549fdc
		ms = DEFAULT_HANDSHAKE_TIMEOUT_MS;
Packit 549fdc
Packit 549fdc
	if (IS_DTLS(session)) {
Packit 549fdc
		gnutls_dtls_set_timeouts(session, DTLS_RETRANS_TIMEOUT, ms);
Packit 549fdc
		return;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	session->internals.handshake_timeout_ms = ms;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
Packit 549fdc
#define IMED_RET( str, ret, allow_alert) do { \
Packit 549fdc
	if (ret < 0) { \
Packit 549fdc
		/* EAGAIN and INTERRUPTED are always non-fatal */ \
Packit 549fdc
		if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) \
Packit 549fdc
			return ret; \
Packit 549fdc
		if (ret == GNUTLS_E_GOT_APPLICATION_DATA && session->internals.initial_negotiation_completed != 0) \
Packit 549fdc
			return ret; \
Packit 549fdc
		if (session->internals.handshake_suspicious_loops < 16) { \
Packit 549fdc
			if (ret == GNUTLS_E_LARGE_PACKET) { \
Packit 549fdc
				session->internals.handshake_suspicious_loops++; \
Packit 549fdc
				return ret; \
Packit 549fdc
			} \
Packit 549fdc
			/* a warning alert might interrupt handshake */ \
Packit 549fdc
			if (allow_alert != 0 && ret==GNUTLS_E_WARNING_ALERT_RECEIVED) { \
Packit 549fdc
				session->internals.handshake_suspicious_loops++; \
Packit 549fdc
				return ret; \
Packit 549fdc
			} \
Packit 549fdc
		} \
Packit 549fdc
		gnutls_assert(); \
Packit 549fdc
		/* do not allow non-fatal errors at this point */ \
Packit 549fdc
		if (gnutls_error_is_fatal(ret) == 0) ret = gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); \
Packit 549fdc
		session_invalidate(session); \
Packit 549fdc
		_gnutls_handshake_hash_buffers_clear(session); \
Packit 549fdc
		return ret; \
Packit 549fdc
	} } while (0)
Packit 549fdc
Packit 549fdc
Packit 549fdc
/* Runs the certificate verification callback.
Packit 549fdc
 * side is either GNUTLS_CLIENT or GNUTLS_SERVER.
Packit 549fdc
 */
Packit 549fdc
static int run_verify_callback(gnutls_session_t session, unsigned int side)
Packit 549fdc
{
Packit 549fdc
	gnutls_certificate_credentials_t cred;
Packit 549fdc
	int ret, type;
Packit 549fdc
Packit 549fdc
	cred =
Packit 549fdc
	    (gnutls_certificate_credentials_t) _gnutls_get_cred(session,
Packit 549fdc
								GNUTLS_CRD_CERTIFICATE);
Packit 549fdc
Packit 549fdc
	if (side == GNUTLS_CLIENT)
Packit 549fdc
		type = gnutls_auth_server_get_type(session);
Packit 549fdc
	else
Packit 549fdc
		type = gnutls_auth_client_get_type(session);
Packit 549fdc
Packit 549fdc
	if (type != GNUTLS_CRD_CERTIFICATE)
Packit 549fdc
		return 0;
Packit 549fdc
Packit 549fdc
	/* verify whether the certificate of the peer remained the same
Packit 549fdc
	 * as with any previous handshakes */
Packit 549fdc
	if (cred != NULL) {
Packit 549fdc
		ret = _gnutls_check_if_cert_hash_is_same(session, cred);
Packit 549fdc
		if (ret < 0) {
Packit 549fdc
			return gnutls_assert_val(ret);
Packit 549fdc
		}
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	if (cred != NULL &&
Packit 549fdc
	    (cred->verify_callback != NULL || session->internals.verify_callback != NULL) &&
Packit 549fdc
	    (session->security_parameters.entity == GNUTLS_CLIENT ||
Packit 549fdc
	     session->internals.send_cert_req != GNUTLS_CERT_IGNORE)) {
Packit 549fdc
		if (session->internals.verify_callback)
Packit 549fdc
			ret = session->internals.verify_callback(session);
Packit 549fdc
		else
Packit 549fdc
			ret = cred->verify_callback(session);
Packit 549fdc
		if (ret < -1)
Packit 549fdc
			return gnutls_assert_val(ret);
Packit 549fdc
		else if (ret != 0)
Packit 549fdc
			return gnutls_assert_val(GNUTLS_E_CERTIFICATE_ERROR);
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	return 0;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
static bool can_send_false_start(gnutls_session_t session)
Packit 549fdc
{
Packit 549fdc
	const version_entry_st *vers;
Packit 549fdc
Packit 549fdc
	vers = get_version(session);
Packit 549fdc
	if (unlikely(vers == NULL || !vers->false_start))
Packit 549fdc
		return 0;
Packit 549fdc
Packit 549fdc
	if (session->internals.selected_cert_list != NULL)
Packit 549fdc
		return 0;
Packit 549fdc
Packit 549fdc
	if (!_gnutls_kx_allows_false_start(session))
Packit 549fdc
		return 0;
Packit 549fdc
Packit 549fdc
	return 1;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/*
Packit 549fdc
 * handshake_client 
Packit 549fdc
 * This function performs the client side of the handshake of the TLS/SSL protocol.
Packit 549fdc
 */
Packit 549fdc
static int handshake_client(gnutls_session_t session)
Packit 549fdc
{
Packit 549fdc
	int ret = 0;
Packit 549fdc
Packit 549fdc
	switch (STATE) {
Packit 549fdc
	case STATE0:
Packit 549fdc
	case STATE1:
Packit 549fdc
		ret = send_client_hello(session, AGAIN(STATE1));
Packit 549fdc
		STATE = STATE1;
Packit 549fdc
		IMED_RET("send hello", ret, 1);
Packit 549fdc
		/* fall through */
Packit 549fdc
	case STATE2:
Packit 549fdc
		if (IS_DTLS(session)) {
Packit 549fdc
			ret =
Packit 549fdc
			    _gnutls_recv_handshake(session,
Packit 549fdc
						   GNUTLS_HANDSHAKE_HELLO_VERIFY_REQUEST,
Packit 549fdc
						   1, NULL);
Packit 549fdc
			STATE = STATE2;
Packit 549fdc
			IMED_RET("recv hello verify", ret, 1);
Packit 549fdc
Packit 549fdc
			if (ret == 1) {
Packit 549fdc
				STATE = STATE0;
Packit 549fdc
				return 1;
Packit 549fdc
			}
Packit 549fdc
		}
Packit 549fdc
		/* fall through */
Packit 549fdc
	case STATE3:
Packit 549fdc
		/* receive the server hello */
Packit 549fdc
		ret =
Packit 549fdc
		    _gnutls_recv_handshake(session,
Packit 549fdc
					   GNUTLS_HANDSHAKE_SERVER_HELLO,
Packit 549fdc
					   0, NULL);
Packit 549fdc
		STATE = STATE3;
Packit 549fdc
		IMED_RET("recv hello", ret, 1);
Packit 549fdc
		/* fall through */
Packit 549fdc
	case STATE4:
Packit 549fdc
		ret = _gnutls_ext_sr_verify(session);
Packit 549fdc
		STATE = STATE4;
Packit 549fdc
		IMED_RET("recv hello", ret, 0);
Packit 549fdc
		/* fall through */
Packit 549fdc
	case STATE5:
Packit 549fdc
		if (session->security_parameters.do_recv_supplemental) {
Packit 549fdc
			ret = _gnutls_recv_supplemental(session);
Packit 549fdc
			STATE = STATE5;
Packit 549fdc
			IMED_RET("recv supplemental", ret, 1);
Packit 549fdc
		}
Packit 549fdc
		/* fall through */
Packit 549fdc
	case STATE6:
Packit 549fdc
		/* RECV CERTIFICATE */
Packit 549fdc
		if (session->internals.resumed == RESUME_FALSE)	/* if we are not resuming */
Packit 549fdc
			ret = _gnutls_recv_server_certificate(session);
Packit 549fdc
		STATE = STATE6;
Packit 549fdc
		IMED_RET("recv server certificate", ret, 1);
Packit 549fdc
		/* fall through */
Packit 549fdc
	case STATE7:
Packit 549fdc
#ifdef ENABLE_OCSP
Packit 549fdc
		/* RECV CERTIFICATE STATUS */
Packit 549fdc
		if (session->internals.resumed == RESUME_FALSE)	/* if we are not resuming */
Packit 549fdc
			ret =
Packit 549fdc
			    _gnutls_recv_server_certificate_status
Packit 549fdc
			    (session);
Packit 549fdc
		STATE = STATE7;
Packit 549fdc
		IMED_RET("recv server certificate", ret, 1);
Packit 549fdc
#endif
Packit 549fdc
		/* fall through */
Packit 549fdc
	case STATE8:
Packit 549fdc
		ret = run_verify_callback(session, GNUTLS_CLIENT);
Packit 549fdc
		STATE = STATE8;
Packit 549fdc
		if (ret < 0)
Packit 549fdc
			return gnutls_assert_val(ret);
Packit 549fdc
Packit 549fdc
		FALLTHROUGH;
Packit 549fdc
	case STATE9:
Packit 549fdc
		/* receive the server key exchange */
Packit 549fdc
		if (session->internals.resumed == RESUME_FALSE)	/* if we are not resuming */
Packit 549fdc
			ret = _gnutls_recv_server_kx_message(session);
Packit 549fdc
		STATE = STATE9;
Packit 549fdc
		IMED_RET("recv server kx message", ret, 1);
Packit 549fdc
		/* fall through */
Packit 549fdc
	case STATE10:
Packit 549fdc
		/* receive the server certificate request - if any 
Packit 549fdc
		 */
Packit 549fdc
Packit 549fdc
		if (session->internals.resumed == RESUME_FALSE)	/* if we are not resuming */
Packit 549fdc
			ret = _gnutls_recv_server_crt_request(session);
Packit 549fdc
		STATE = STATE10;
Packit 549fdc
		IMED_RET("recv server certificate request message", ret,
Packit 549fdc
			 1);
Packit 549fdc
		/* fall through */
Packit 549fdc
	case STATE11:
Packit 549fdc
		/* receive the server hello done */
Packit 549fdc
		if (session->internals.resumed == RESUME_FALSE)	/* if we are not resuming */
Packit 549fdc
			ret =
Packit 549fdc
			    _gnutls_recv_handshake(session,
Packit 549fdc
						   GNUTLS_HANDSHAKE_SERVER_HELLO_DONE,
Packit 549fdc
						   0, NULL);
Packit 549fdc
		STATE = STATE11;
Packit 549fdc
		IMED_RET("recv server hello done", ret, 1);
Packit 549fdc
		/* fall through */
Packit 549fdc
	case STATE12:
Packit 549fdc
		if (session->security_parameters.do_send_supplemental) {
Packit 549fdc
			ret =
Packit 549fdc
			    _gnutls_send_supplemental(session,
Packit 549fdc
						      AGAIN(STATE12));
Packit 549fdc
			STATE = STATE12;
Packit 549fdc
			IMED_RET("send supplemental", ret, 0);
Packit 549fdc
		}
Packit 549fdc
		/* fall through */
Packit 549fdc
	case STATE13:
Packit 549fdc
		/* send our certificate - if any and if requested
Packit 549fdc
		 */
Packit 549fdc
		if (session->internals.resumed == RESUME_FALSE)	/* if we are not resuming */
Packit 549fdc
			ret =
Packit 549fdc
			    _gnutls_send_client_certificate(session,
Packit 549fdc
							    AGAIN
Packit 549fdc
							    (STATE13));
Packit 549fdc
		STATE = STATE13;
Packit 549fdc
		IMED_RET("send client certificate", ret, 0);
Packit 549fdc
		/* fall through */
Packit 549fdc
	case STATE14:
Packit 549fdc
		if (session->internals.resumed == RESUME_FALSE)	/* if we are not resuming */
Packit 549fdc
			ret =
Packit 549fdc
			    _gnutls_send_client_kx_message(session,
Packit 549fdc
							   AGAIN(STATE14));
Packit 549fdc
		STATE = STATE14;
Packit 549fdc
		IMED_RET("send client kx", ret, 0);
Packit 549fdc
		/* fall through */
Packit 549fdc
	case STATE15:
Packit 549fdc
		/* send client certificate verify */
Packit 549fdc
		if (session->internals.resumed == RESUME_FALSE)	/* if we are not resuming */
Packit 549fdc
			ret =
Packit 549fdc
			    _gnutls_send_client_certificate_verify(session,
Packit 549fdc
								   AGAIN
Packit 549fdc
								   (STATE15));
Packit 549fdc
		STATE = STATE15;
Packit 549fdc
		IMED_RET("send client certificate verify", ret, 1);
Packit 549fdc
		/* fall through */
Packit 549fdc
	case STATE16:
Packit 549fdc
		STATE = STATE16;
Packit 549fdc
		if (session->internals.resumed == RESUME_FALSE) {
Packit 549fdc
			ret = send_handshake_final(session, TRUE);
Packit 549fdc
			IMED_RET("send handshake final 2", ret, 1);
Packit 549fdc
#ifdef ENABLE_SESSION_TICKETS
Packit 549fdc
		} else {
Packit 549fdc
			ret = _gnutls_recv_new_session_ticket(session);
Packit 549fdc
			IMED_RET("recv handshake new session ticket", ret,
Packit 549fdc
				 1);
Packit 549fdc
#endif
Packit 549fdc
		}
Packit 549fdc
		/* fall through */
Packit 549fdc
	case STATE17:
Packit 549fdc
		STATE = STATE17;
Packit 549fdc
		if (session->internals.resumed == RESUME_FALSE && (session->internals.flags & GNUTLS_ENABLE_FALSE_START) && can_send_false_start(session)) {
Packit 549fdc
			session->internals.false_start_used = 1;
Packit 549fdc
			session->internals.recv_state = RECV_STATE_FALSE_START;
Packit 549fdc
			/* complete this phase of the handshake. We
Packit 549fdc
			 * should be called again by gnutls_record_recv()
Packit 549fdc
			 */
Packit 549fdc
			STATE = STATE18;
Packit 549fdc
			gnutls_assert();
Packit 549fdc
Packit 549fdc
			return 0;
Packit 549fdc
		} else {
Packit 549fdc
			session->internals.false_start_used = 0;
Packit 549fdc
		}
Packit 549fdc
		/* fall through */
Packit 549fdc
	case STATE18:
Packit 549fdc
		STATE = STATE18;
Packit 549fdc
Packit 549fdc
		if (session->internals.resumed == RESUME_FALSE) {
Packit 549fdc
#ifdef ENABLE_SESSION_TICKETS
Packit 549fdc
			ret = _gnutls_recv_new_session_ticket(session);
Packit 549fdc
			IMED_RET("recv handshake new session ticket", ret,
Packit 549fdc
				 1);
Packit 549fdc
#endif
Packit 549fdc
		} else {
Packit 549fdc
			ret = recv_handshake_final(session, TRUE);
Packit 549fdc
			IMED_RET("recv handshake final", ret, 1);
Packit 549fdc
		}
Packit 549fdc
		/* fall through */
Packit 549fdc
	case STATE19:
Packit 549fdc
		STATE = STATE19;
Packit 549fdc
		if (session->internals.resumed == RESUME_FALSE) {
Packit 549fdc
			ret = recv_handshake_final(session, FALSE);
Packit 549fdc
			IMED_RET("recv handshake final 2", ret, 1);
Packit 549fdc
		} else {
Packit 549fdc
			ret = send_handshake_final(session, FALSE);
Packit 549fdc
			IMED_RET("send handshake final", ret, 1);
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
		STATE = STATE0;
Packit 549fdc
		/* fall through */
Packit 549fdc
	default:
Packit 549fdc
		break;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	/* explicitly reset any false start flags */
Packit 549fdc
	session->internals.recv_state = RECV_STATE_0;
Packit 549fdc
Packit 549fdc
	return 0;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
Packit 549fdc
Packit 549fdc
/* This function is to be called if the handshake was successfully 
Packit 549fdc
 * completed. This sends a Change Cipher Spec packet to the peer.
Packit 549fdc
 */
Packit 549fdc
static ssize_t send_change_cipher_spec(gnutls_session_t session, int again)
Packit 549fdc
{
Packit 549fdc
	uint8_t *data;
Packit 549fdc
	mbuffer_st *bufel;
Packit 549fdc
	int ret;
Packit 549fdc
	const version_entry_st *vers;
Packit 549fdc
Packit 549fdc
	if (again == 0) {
Packit 549fdc
		bufel = _gnutls_handshake_alloc(session, 1);
Packit 549fdc
		if (bufel == NULL)
Packit 549fdc
			return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
Packit 549fdc
Packit 549fdc
		vers = get_version(session);
Packit 549fdc
		if (unlikely(vers == NULL))
Packit 549fdc
			return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
Packit 549fdc
Packit 549fdc
		if (vers->id == GNUTLS_DTLS0_9)
Packit 549fdc
			_mbuffer_set_uhead_size(bufel, 3);
Packit 549fdc
		else
Packit 549fdc
			_mbuffer_set_uhead_size(bufel, 1);
Packit 549fdc
		_mbuffer_set_udata_size(bufel, 0);
Packit 549fdc
Packit 549fdc
		data = _mbuffer_get_uhead_ptr(bufel);
Packit 549fdc
Packit 549fdc
		data[0] = 1;
Packit 549fdc
		if (vers->id == GNUTLS_DTLS0_9) {
Packit 549fdc
			_gnutls_write_uint16(session->internals.dtls.
Packit 549fdc
					     hsk_write_seq, &data[1]);
Packit 549fdc
			session->internals.dtls.hsk_write_seq++;
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
		ret =
Packit 549fdc
		    _gnutls_handshake_io_cache_int(session,
Packit 549fdc
						   GNUTLS_HANDSHAKE_CHANGE_CIPHER_SPEC,
Packit 549fdc
						   bufel);
Packit 549fdc
		if (ret < 0) {
Packit 549fdc
			_mbuffer_xfree(&bufel);
Packit 549fdc
			return gnutls_assert_val(ret);
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
		_gnutls_handshake_log("REC[%p]: Sent ChangeCipherSpec\n",
Packit 549fdc
				      session);
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	return 0;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/* This function sends the final handshake packets and initializes connection 
Packit 549fdc
 */
Packit 549fdc
static int send_handshake_final(gnutls_session_t session, int init)
Packit 549fdc
{
Packit 549fdc
	int ret = 0;
Packit 549fdc
Packit 549fdc
	/* Send the CHANGE CIPHER SPEC PACKET */
Packit 549fdc
Packit 549fdc
	switch (FINAL_STATE) {
Packit 549fdc
	case STATE0:
Packit 549fdc
	case STATE1:
Packit 549fdc
		ret = send_change_cipher_spec(session, FAGAIN(STATE1));
Packit 549fdc
		FINAL_STATE = STATE0;
Packit 549fdc
Packit 549fdc
		if (ret < 0) {
Packit 549fdc
			gnutls_assert();
Packit 549fdc
			return ret;
Packit 549fdc
		}
Packit 549fdc
		/* Initialize the connection session (start encryption) - in case of client 
Packit 549fdc
		 */
Packit 549fdc
		if (init == TRUE) {
Packit 549fdc
			ret = _gnutls_connection_state_init(session);
Packit 549fdc
			if (ret < 0) {
Packit 549fdc
				gnutls_assert();
Packit 549fdc
				return ret;
Packit 549fdc
			}
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
		ret = _gnutls_write_connection_state_init(session);
Packit 549fdc
		if (ret < 0) {
Packit 549fdc
			gnutls_assert();
Packit 549fdc
			return ret;
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
		/* fall through */
Packit 549fdc
	case STATE2:
Packit 549fdc
		/* send the finished message */
Packit 549fdc
		ret = _gnutls_send_finished(session, FAGAIN(STATE2));
Packit 549fdc
		FINAL_STATE = STATE2;
Packit 549fdc
		if (ret < 0) {
Packit 549fdc
			gnutls_assert();
Packit 549fdc
			return ret;
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
		FINAL_STATE = STATE0;
Packit 549fdc
		/* fall through */
Packit 549fdc
	default:
Packit 549fdc
		break;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	return 0;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/* This function receives the final handshake packets 
Packit 549fdc
 * And executes the appropriate function to initialize the
Packit 549fdc
 * read session.
Packit 549fdc
 */
Packit 549fdc
static int recv_handshake_final(gnutls_session_t session, int init)
Packit 549fdc
{
Packit 549fdc
	int ret = 0;
Packit 549fdc
	uint8_t ccs[3];
Packit 549fdc
	unsigned int ccs_len = 1;
Packit 549fdc
	unsigned int tleft;
Packit 549fdc
	const version_entry_st *vers;
Packit 549fdc
Packit 549fdc
	ret = handshake_remaining_time(session);
Packit 549fdc
	if (ret < 0)
Packit 549fdc
		return gnutls_assert_val(ret);
Packit 549fdc
	tleft = ret;
Packit 549fdc
Packit 549fdc
	switch (FINAL_STATE) {
Packit 549fdc
	case STATE0:
Packit 549fdc
	case STATE30:
Packit 549fdc
		FINAL_STATE = STATE30;
Packit 549fdc
Packit 549fdc
		/* This is the last flight and peer cannot be sure
Packit 549fdc
		 * we have received it unless we notify him. So we
Packit 549fdc
		 * wait for a message and retransmit if needed. */
Packit 549fdc
		if (IS_DTLS(session) && !_dtls_is_async(session) &&
Packit 549fdc
		    (gnutls_record_check_pending(session) +
Packit 549fdc
		     record_check_unprocessed(session)) == 0) {
Packit 549fdc
			ret = _dtls_wait_and_retransmit(session);
Packit 549fdc
			if (ret < 0)
Packit 549fdc
				return gnutls_assert_val(ret);
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
		vers = get_version(session);
Packit 549fdc
		if (unlikely(vers == NULL))
Packit 549fdc
			return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
Packit 549fdc
Packit 549fdc
		if (vers->id == GNUTLS_DTLS0_9)
Packit 549fdc
			ccs_len = 3;
Packit 549fdc
Packit 549fdc
		ret =
Packit 549fdc
		    _gnutls_recv_int(session, GNUTLS_CHANGE_CIPHER_SPEC,
Packit 549fdc
				     ccs, ccs_len, NULL, tleft);
Packit 549fdc
		if (ret <= 0) {
Packit 549fdc
			gnutls_assert();
Packit 549fdc
			return (ret<0)?ret:GNUTLS_E_UNEXPECTED_PACKET;
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
		if (vers->id == GNUTLS_DTLS0_9)
Packit 549fdc
			session->internals.dtls.hsk_read_seq++;
Packit 549fdc
Packit 549fdc
		/* Initialize the connection session (start encryption) - in case of server */
Packit 549fdc
		if (init == TRUE) {
Packit 549fdc
			ret = _gnutls_connection_state_init(session);
Packit 549fdc
			if (ret < 0) {
Packit 549fdc
				gnutls_assert();
Packit 549fdc
				return ret;
Packit 549fdc
			}
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
		ret = _gnutls_read_connection_state_init(session);
Packit 549fdc
		if (ret < 0) {
Packit 549fdc
			gnutls_assert();
Packit 549fdc
			return ret;
Packit 549fdc
		}
Packit 549fdc
		/* fall through */
Packit 549fdc
	case STATE31:
Packit 549fdc
		FINAL_STATE = STATE31;
Packit 549fdc
Packit 549fdc
		if (IS_DTLS(session) && !_dtls_is_async(session) &&
Packit 549fdc
		    (gnutls_record_check_pending(session) +
Packit 549fdc
		     record_check_unprocessed(session)) == 0) {
Packit 549fdc
			ret = _dtls_wait_and_retransmit(session);
Packit 549fdc
			if (ret < 0)
Packit 549fdc
				return gnutls_assert_val(ret);
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
		ret = _gnutls_recv_finished(session);
Packit 549fdc
		if (ret < 0) {
Packit 549fdc
			gnutls_assert();
Packit 549fdc
			return ret;
Packit 549fdc
		}
Packit 549fdc
		FINAL_STATE = STATE0;
Packit 549fdc
		/* fall through */
Packit 549fdc
	default:
Packit 549fdc
		break;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
Packit 549fdc
	return 0;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/*
Packit 549fdc
 * handshake_server
Packit 549fdc
 * This function does the server stuff of the handshake protocol.
Packit 549fdc
 */
Packit 549fdc
static int handshake_server(gnutls_session_t session)
Packit 549fdc
{
Packit 549fdc
	int ret = 0;
Packit 549fdc
Packit 549fdc
	switch (STATE) {
Packit 549fdc
	case STATE0:
Packit 549fdc
	case STATE1:
Packit 549fdc
		ret =
Packit 549fdc
		    _gnutls_recv_handshake(session,
Packit 549fdc
					   GNUTLS_HANDSHAKE_CLIENT_HELLO,
Packit 549fdc
					   0, NULL);
Packit 549fdc
		if (ret == GNUTLS_E_INT_RET_0) {
Packit 549fdc
			/* this is triggered by post_client_hello, and instructs the
Packit 549fdc
			 * handshake to proceed but be put on hold */
Packit 549fdc
			ret = GNUTLS_E_INTERRUPTED;
Packit 549fdc
			STATE = STATE2; /* hello already parsed -> move on */
Packit 549fdc
		} else {
Packit 549fdc
			STATE = STATE1;
Packit 549fdc
		}
Packit 549fdc
		IMED_RET("recv hello", ret, 1);
Packit 549fdc
		/* fall through */
Packit 549fdc
	case STATE2:
Packit 549fdc
		ret = _gnutls_ext_sr_verify(session);
Packit 549fdc
		STATE = STATE2;
Packit 549fdc
		IMED_RET("recv hello", ret, 0);
Packit 549fdc
		/* fall through */
Packit 549fdc
	case STATE3:
Packit 549fdc
		ret = send_server_hello(session, AGAIN(STATE3));
Packit 549fdc
		STATE = STATE3;
Packit 549fdc
		IMED_RET("send hello", ret, 1);
Packit 549fdc
		/* fall through */
Packit 549fdc
	case STATE4:
Packit 549fdc
		if (session->security_parameters.do_send_supplemental) {
Packit 549fdc
			ret =
Packit 549fdc
			    _gnutls_send_supplemental(session,
Packit 549fdc
						      AGAIN(STATE4));
Packit 549fdc
			STATE = STATE4;
Packit 549fdc
			IMED_RET("send supplemental data", ret, 0);
Packit 549fdc
		}
Packit 549fdc
		/* SEND CERTIFICATE + KEYEXCHANGE + CERTIFICATE_REQUEST */
Packit 549fdc
		/* fall through */
Packit 549fdc
	case STATE5:
Packit 549fdc
		/* NOTE: these should not be send if we are resuming */
Packit 549fdc
Packit 549fdc
		if (session->internals.resumed == RESUME_FALSE)
Packit 549fdc
			ret =
Packit 549fdc
			    _gnutls_send_server_certificate(session,
Packit 549fdc
							    AGAIN(STATE5));
Packit 549fdc
		STATE = STATE5;
Packit 549fdc
		IMED_RET("send server certificate", ret, 0);
Packit 549fdc
		/* fall through */
Packit 549fdc
	case STATE6:
Packit 549fdc
#ifdef ENABLE_OCSP
Packit 549fdc
		if (session->internals.resumed == RESUME_FALSE)
Packit 549fdc
			ret =
Packit 549fdc
			    _gnutls_send_server_certificate_status(session,
Packit 549fdc
								   AGAIN
Packit 549fdc
								   (STATE6));
Packit 549fdc
		STATE = STATE6;
Packit 549fdc
		IMED_RET("send server certificate status", ret, 0);
Packit 549fdc
#endif
Packit 549fdc
		/* fall through */
Packit 549fdc
	case STATE7:
Packit 549fdc
		/* send server key exchange (A) */
Packit 549fdc
		if (session->internals.resumed == RESUME_FALSE)
Packit 549fdc
			ret =
Packit 549fdc
			    _gnutls_send_server_kx_message(session,
Packit 549fdc
							   AGAIN(STATE7));
Packit 549fdc
		STATE = STATE7;
Packit 549fdc
		IMED_RET("send server kx", ret, 0);
Packit 549fdc
		/* fall through */
Packit 549fdc
	case STATE8:
Packit 549fdc
		/* Send certificate request - if requested to */
Packit 549fdc
		if (session->internals.resumed == RESUME_FALSE)
Packit 549fdc
			ret =
Packit 549fdc
			    _gnutls_send_server_crt_request(session,
Packit 549fdc
							    AGAIN(STATE8));
Packit 549fdc
		STATE = STATE8;
Packit 549fdc
		IMED_RET("send server cert request", ret, 0);
Packit 549fdc
		/* fall through */
Packit 549fdc
	case STATE9:
Packit 549fdc
		/* send the server hello done */
Packit 549fdc
		if (session->internals.resumed == RESUME_FALSE)	/* if we are not resuming */
Packit 549fdc
			ret =
Packit 549fdc
			    _gnutls_send_empty_handshake(session,
Packit 549fdc
							 GNUTLS_HANDSHAKE_SERVER_HELLO_DONE,
Packit 549fdc
							 AGAIN(STATE9));
Packit 549fdc
		STATE = STATE9;
Packit 549fdc
		IMED_RET("send server hello done", ret, 1);
Packit 549fdc
		/* fall through */
Packit 549fdc
	case STATE10:
Packit 549fdc
		if (session->security_parameters.do_recv_supplemental) {
Packit 549fdc
			ret = _gnutls_recv_supplemental(session);
Packit 549fdc
			STATE = STATE10;
Packit 549fdc
			IMED_RET("recv client supplemental", ret, 1);
Packit 549fdc
		}
Packit 549fdc
		/* RECV CERTIFICATE + KEYEXCHANGE + CERTIFICATE_VERIFY */
Packit 549fdc
		/* fall through */
Packit 549fdc
	case STATE11:
Packit 549fdc
		/* receive the client certificate message */
Packit 549fdc
		if (session->internals.resumed == RESUME_FALSE)	/* if we are not resuming */
Packit 549fdc
			ret = _gnutls_recv_client_certificate(session);
Packit 549fdc
		STATE = STATE11;
Packit 549fdc
		IMED_RET("recv client certificate", ret, 1);
Packit 549fdc
		/* fall through */
Packit 549fdc
	case STATE12:
Packit 549fdc
		ret = run_verify_callback(session, GNUTLS_SERVER);
Packit 549fdc
		STATE = STATE12;
Packit 549fdc
		if (ret < 0)
Packit 549fdc
			return gnutls_assert_val(ret);
Packit 549fdc
		/* fall through */
Packit 549fdc
	case STATE13:
Packit 549fdc
		/* receive the client key exchange message */
Packit 549fdc
		if (session->internals.resumed == RESUME_FALSE)	/* if we are not resuming */
Packit 549fdc
			ret = _gnutls_recv_client_kx_message(session);
Packit 549fdc
		STATE = STATE13;
Packit 549fdc
		IMED_RET("recv client kx", ret, 1);
Packit 549fdc
		/* fall through */
Packit 549fdc
	case STATE14:
Packit 549fdc
		/* receive the client certificate verify message */
Packit 549fdc
		if (session->internals.resumed == RESUME_FALSE)	/* if we are not resuming */
Packit 549fdc
			ret =
Packit 549fdc
			    _gnutls_recv_client_certificate_verify_message
Packit 549fdc
			    (session);
Packit 549fdc
		STATE = STATE14;
Packit 549fdc
		IMED_RET("recv client certificate verify", ret, 1);
Packit 549fdc
		/* fall through */
Packit 549fdc
	case STATE15:
Packit 549fdc
		STATE = STATE15;
Packit 549fdc
		if (session->internals.resumed == RESUME_FALSE) {	/* if we are not resuming */
Packit 549fdc
			ret = recv_handshake_final(session, TRUE);
Packit 549fdc
			IMED_RET("recv handshake final", ret, 1);
Packit 549fdc
		} else {
Packit 549fdc
			ret = send_handshake_final(session, TRUE);
Packit 549fdc
			IMED_RET("send handshake final 2", ret, 1);
Packit 549fdc
		}
Packit 549fdc
		/* fall through */
Packit 549fdc
	case STATE16:
Packit 549fdc
#ifdef ENABLE_SESSION_TICKETS
Packit 549fdc
		ret =
Packit 549fdc
		    _gnutls_send_new_session_ticket(session,
Packit 549fdc
						    AGAIN(STATE16));
Packit 549fdc
		STATE = STATE16;
Packit 549fdc
		IMED_RET("send handshake new session ticket", ret, 0);
Packit 549fdc
#endif
Packit 549fdc
		/* fall through */
Packit 549fdc
	case STATE17:
Packit 549fdc
		STATE = STATE17;
Packit 549fdc
		if (session->internals.resumed == RESUME_FALSE) {	/* if we are not resuming */
Packit 549fdc
			ret = send_handshake_final(session, FALSE);
Packit 549fdc
			IMED_RET("send handshake final", ret, 1);
Packit 549fdc
Packit 549fdc
			if (session->security_parameters.entity ==
Packit 549fdc
			    GNUTLS_SERVER
Packit 549fdc
			    && session->internals.ticket_sent == 0) {
Packit 549fdc
				/* if no ticket, save session data */
Packit 549fdc
				_gnutls_server_register_current_session
Packit 549fdc
				    (session);
Packit 549fdc
			}
Packit 549fdc
		} else {
Packit 549fdc
			ret = recv_handshake_final(session, FALSE);
Packit 549fdc
			IMED_RET("recv handshake final 2", ret, 1);
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
		STATE = STATE0;
Packit 549fdc
		/* fall through */
Packit 549fdc
	default:
Packit 549fdc
		break;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	return _gnutls_check_id_for_change(session);
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
int _gnutls_generate_session_id(uint8_t * session_id, uint8_t * len)
Packit 549fdc
{
Packit 549fdc
	int ret;
Packit 549fdc
Packit 549fdc
	*len = GNUTLS_MAX_SESSION_ID_SIZE;
Packit 549fdc
Packit 549fdc
	ret =
Packit 549fdc
	    gnutls_rnd(GNUTLS_RND_NONCE, session_id,
Packit 549fdc
			GNUTLS_MAX_SESSION_ID_SIZE);
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return ret;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	return 0;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
int
Packit 549fdc
_gnutls_recv_hello_request(gnutls_session_t session, void *data,
Packit 549fdc
			   uint32_t data_size)
Packit 549fdc
{
Packit 549fdc
	uint8_t type;
Packit 549fdc
Packit 549fdc
	if (session->security_parameters.entity == GNUTLS_SERVER) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return GNUTLS_E_UNEXPECTED_PACKET;
Packit 549fdc
	}
Packit 549fdc
	if (data_size < 1) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
Packit 549fdc
	}
Packit 549fdc
	type = ((uint8_t *) data)[0];
Packit 549fdc
	if (type == GNUTLS_HANDSHAKE_HELLO_REQUEST) {
Packit 549fdc
		if (IS_DTLS(session))
Packit 549fdc
			session->internals.dtls.hsk_read_seq++;
Packit 549fdc
		return GNUTLS_E_REHANDSHAKE;
Packit 549fdc
	} else {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return GNUTLS_E_UNEXPECTED_PACKET;
Packit 549fdc
	}
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/**
Packit 549fdc
 * gnutls_handshake_set_max_packet_length:
Packit 549fdc
 * @session: is a #gnutls_session_t type.
Packit 549fdc
 * @max: is the maximum number.
Packit 549fdc
 *
Packit 549fdc
 * This function will set the maximum size of all handshake messages.
Packit 549fdc
 * Handshakes over this size are rejected with
Packit 549fdc
 * %GNUTLS_E_HANDSHAKE_TOO_LARGE error code.  The default value is
Packit 549fdc
 * 128kb which is typically large enough.  Set this to 0 if you do not
Packit 549fdc
 * want to set an upper limit.
Packit 549fdc
 *
Packit 549fdc
 * The reason for restricting the handshake message sizes are to
Packit 549fdc
 * limit Denial of Service attacks.
Packit 549fdc
 *
Packit 549fdc
 * Note that the maximum handshake size was increased to 128kb
Packit 549fdc
 * from 48kb in GnuTLS 3.5.5.
Packit 549fdc
 **/
Packit 549fdc
void
Packit 549fdc
gnutls_handshake_set_max_packet_length(gnutls_session_t session,
Packit 549fdc
				       size_t max)
Packit 549fdc
{
Packit 549fdc
	session->internals.max_handshake_data_buffer_size = max;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/**
Packit 549fdc
 * gnutls_handshake_get_last_in:
Packit 549fdc
 * @session: is a #gnutls_session_t type.
Packit 549fdc
 *
Packit 549fdc
 * This function is only useful to check where the last performed
Packit 549fdc
 * handshake failed.  If the previous handshake succeed or was not
Packit 549fdc
 * performed at all then no meaningful value will be returned.
Packit 549fdc
 *
Packit 549fdc
 * Check %gnutls_handshake_description_t in gnutls.h for the
Packit 549fdc
 * available handshake descriptions.
Packit 549fdc
 *
Packit 549fdc
 * Returns: the last handshake message type received, a
Packit 549fdc
 * %gnutls_handshake_description_t.
Packit 549fdc
 **/
Packit 549fdc
gnutls_handshake_description_t
Packit 549fdc
gnutls_handshake_get_last_in(gnutls_session_t session)
Packit 549fdc
{
Packit 549fdc
	return session->internals.last_handshake_in;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/**
Packit 549fdc
 * gnutls_handshake_get_last_out:
Packit 549fdc
 * @session: is a #gnutls_session_t type.
Packit 549fdc
 *
Packit 549fdc
 * This function is only useful to check where the last performed
Packit 549fdc
 * handshake failed.  If the previous handshake succeed or was not
Packit 549fdc
 * performed at all then no meaningful value will be returned.
Packit 549fdc
 *
Packit 549fdc
 * Check %gnutls_handshake_description_t in gnutls.h for the
Packit 549fdc
 * available handshake descriptions.
Packit 549fdc
 *
Packit 549fdc
 * Returns: the last handshake message type sent, a
Packit 549fdc
 * %gnutls_handshake_description_t.
Packit 549fdc
 **/
Packit 549fdc
gnutls_handshake_description_t
Packit 549fdc
gnutls_handshake_get_last_out(gnutls_session_t session)
Packit 549fdc
{
Packit 549fdc
	return session->internals.last_handshake_out;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/* This returns the session hash as in draft-ietf-tls-session-hash-02.
Packit 549fdc
 *
Packit 549fdc
 * FIXME: It duplicates some of the actions in _gnutls_handshake_sign_crt_vrfy*.
Packit 549fdc
 * See whether they can be merged.
Packit 549fdc
 */
Packit 549fdc
int _gnutls_handshake_get_session_hash(gnutls_session_t session, gnutls_datum_t *shash)
Packit 549fdc
{
Packit 549fdc
	const version_entry_st *ver = get_version(session);
Packit 549fdc
	int ret;
Packit 549fdc
	const mac_entry_st *me;
Packit 549fdc
	uint8_t concat[2*MAX_HASH_SIZE];
Packit 549fdc
Packit 549fdc
	if (unlikely(ver == NULL))
Packit 549fdc
		return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
Packit 549fdc
Packit 549fdc
	if (session->internals.handshake_hash_buffer_client_kx_len == 0 ||
Packit 549fdc
	    (session->internals.handshake_hash_buffer.length <
Packit 549fdc
	    session->internals.handshake_hash_buffer_client_kx_len)) {
Packit 549fdc
			return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	me = mac_to_entry(session->security_parameters.prf_mac);
Packit 549fdc
	if (me == NULL)
Packit 549fdc
		return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
Packit 549fdc
Packit 549fdc
	ret =
Packit 549fdc
	    _gnutls_hash_fast((gnutls_digest_algorithm_t)me->id,
Packit 549fdc
			      session->internals.handshake_hash_buffer.
Packit 549fdc
			      data,
Packit 549fdc
			      session->internals.handshake_hash_buffer_client_kx_len,
Packit 549fdc
			      concat);
Packit 549fdc
	if (ret < 0)
Packit 549fdc
		return gnutls_assert_val(ret);
Packit 549fdc
Packit 549fdc
	return _gnutls_set_datum(shash, concat, me->output_size);
Packit 549fdc
}