Blame lib/kx.c

Packit Service 4684c1
/*
Packit Service 4684c1
 * Copyright (C) 2000-2012 Free Software Foundation, Inc.
Packit Service 4684c1
 *
Packit Service 4684c1
 * Author: Nikos Mavrogiannopoulos
Packit Service 4684c1
 *
Packit Service 4684c1
 * This file is part of GnuTLS.
Packit Service 4684c1
 *
Packit Service 4684c1
 * The GnuTLS is free software; you can redistribute it and/or
Packit Service 4684c1
 * modify it under the terms of the GNU Lesser General Public License
Packit Service 4684c1
 * as published by the Free Software Foundation; either version 2.1 of
Packit Service 4684c1
 * the License, or (at your option) any later version.
Packit Service 4684c1
 *
Packit Service 4684c1
 * This library is distributed in the hope that it will be useful, but
Packit Service 4684c1
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 4684c1
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 4684c1
 * Lesser General Public License for more details.
Packit Service 4684c1
 *
Packit Service 4684c1
 * You should have received a copy of the GNU Lesser General Public License
Packit Service 4684c1
 * along with this program.  If not, see <https://www.gnu.org/licenses/>
Packit Service 4684c1
 *
Packit Service 4684c1
 */
Packit Service 4684c1
Packit Service 4684c1
/* This file contains functions which are wrappers for the key exchange
Packit Service 4684c1
 * part of TLS. They are called by the handshake functions (gnutls_handshake)
Packit Service 4684c1
 */
Packit Service 4684c1
Packit Service 4684c1
#include "gnutls_int.h"
Packit Service 4684c1
#include "handshake.h"
Packit Service 4684c1
#include "kx.h"
Packit Service 4684c1
#include "dh.h"
Packit Service 4684c1
#include "errors.h"
Packit Service 4684c1
#include "algorithms.h"
Packit Service 4684c1
#include "debug.h"
Packit Service 4684c1
#include "locks.h"
Packit Service 4684c1
#include "mpi.h"
Packit Service 4684c1
#include <state.h>
Packit Service 4684c1
#include <datum.h>
Packit Service 4684c1
#include <mbuffers.h>
Packit Service 4684c1
Packit Service 4684c1
/* This file contains important thing for the TLS handshake procedure.
Packit Service 4684c1
 */
Packit Service 4684c1
Packit Service 4684c1
#define MASTER_SECRET "master secret"
Packit Service 4684c1
#define MASTER_SECRET_SIZE (sizeof(MASTER_SECRET)-1)
Packit Service 4684c1
Packit Service 4684c1
#define EXT_MASTER_SECRET "extended master secret"
Packit Service 4684c1
#define EXT_MASTER_SECRET_SIZE (sizeof(EXT_MASTER_SECRET)-1)
Packit Service 4684c1
Packit Service 4684c1
GNUTLS_STATIC_MUTEX(keylog_mutex);
Packit Service 4684c1
static FILE *keylog;
Packit Service 4684c1
Packit Service 4684c1
static int generate_normal_master(gnutls_session_t session,
Packit Service 4684c1
				  gnutls_datum_t *, int);
Packit Service 4684c1
Packit Service 4684c1
int _gnutls_generate_master(gnutls_session_t session, int keep_premaster)
Packit Service 4684c1
{
Packit Service 4684c1
	if (session->internals.resumed == RESUME_FALSE)
Packit Service 4684c1
		return generate_normal_master(session, &session->key.key,
Packit Service 4684c1
					      keep_premaster);
Packit Service 4684c1
	else if (session->internals.premaster_set) {
Packit Service 4684c1
		gnutls_datum_t premaster;
Packit Service 4684c1
		premaster.size =
Packit Service 4684c1
		    sizeof(session->internals.resumed_security_parameters.
Packit Service 4684c1
			   master_secret);
Packit Service 4684c1
		premaster.data =
Packit Service 4684c1
		    session->internals.resumed_security_parameters.
Packit Service 4684c1
		    master_secret;
Packit Service 4684c1
		return generate_normal_master(session, &premaster, 1);
Packit Service 4684c1
	}
Packit Service 4684c1
	return 0;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
/**
Packit Service 4684c1
 * gnutls_session_get_keylog_function:
Packit Service 4684c1
 * @session: is #gnutls_session_t type
Packit Service 4684c1
 *
Packit Service 4684c1
 * This function will return the callback function set using
Packit Service 4684c1
 * gnutls_session_set_keylog_function().
Packit Service 4684c1
 *
Packit Service 4684c1
 * Returns: The function set or %NULL otherwise.
Packit Service 4684c1
 *
Packit Service 4684c1
 * Since: 3.6.13
Packit Service 4684c1
 */
Packit Service 4684c1
gnutls_keylog_func
Packit Service 4684c1
gnutls_session_get_keylog_function(const gnutls_session_t session)
Packit Service 4684c1
{
Packit Service 4684c1
	return session->internals.keylog_func;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
/**
Packit Service 4684c1
 * gnutls_session_set_keylog_function:
Packit Service 4684c1
 * @session: is #gnutls_session_t type
Packit Service 4684c1
 * @func: is the function to be called
Packit Service 4684c1
 *
Packit Service 4684c1
 * This function will set a callback to be called when a new secret is
Packit Service 4684c1
 * derived and installed during handshake.
Packit Service 4684c1
 *
Packit Service 4684c1
 * Since: 3.6.13
Packit Service 4684c1
 */
Packit Service 4684c1
void
Packit Service 4684c1
gnutls_session_set_keylog_function(gnutls_session_t session,
Packit Service 4684c1
				   gnutls_keylog_func func)
Packit Service 4684c1
{
Packit Service 4684c1
	session->internals.keylog_func = func;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
int
Packit Service 4684c1
_gnutls_call_keylog_func(gnutls_session_t session,
Packit Service 4684c1
			 const char *label,
Packit Service 4684c1
			 const uint8_t *data,
Packit Service 4684c1
			 unsigned size)
Packit Service 4684c1
{
Packit Service 4684c1
	if (session->internals.keylog_func) {
Packit Service 4684c1
		gnutls_datum_t secret = {(void*)data, size};
Packit Service 4684c1
		return session->internals.keylog_func(session, label, &secret);
Packit Service 4684c1
	}
Packit Service 4684c1
	return 0;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
int
Packit Service 4684c1
_gnutls_nss_keylog_func(gnutls_session_t session,
Packit Service 4684c1
			const char *label,
Packit Service 4684c1
			const gnutls_datum_t *secret)
Packit Service 4684c1
{
Packit Service 4684c1
	/* ignore subsequent traffic secrets that are calculated from
Packit Service 4684c1
	 * the previous traffic secret
Packit Service 4684c1
	 */
Packit Service 4684c1
	if (!session->internals.handshake_in_progress)
Packit Service 4684c1
		return 0;
Packit Service 4684c1
Packit Service 4684c1
	_gnutls_nss_keylog_write(session, label, secret->data, secret->size);
Packit Service 4684c1
	return 0;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
void _gnutls_nss_keylog_write(gnutls_session_t session,
Packit Service 4684c1
			      const char *label,
Packit Service 4684c1
			      const uint8_t *secret, size_t secret_size)
Packit Service 4684c1
{
Packit Service 4684c1
	static const char *keylogfile = NULL;
Packit Service 4684c1
	static unsigned checked_env = 0;
Packit Service 4684c1
Packit Service 4684c1
	if (!checked_env) {
Packit Service 4684c1
		checked_env = 1;
Packit Service 4684c1
		keylogfile = secure_getenv("SSLKEYLOGFILE");
Packit Service 4684c1
		if (keylogfile != NULL)
Packit Service 4684c1
			keylog = fopen(keylogfile, "ae");
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	if (keylog) {
Packit Service 4684c1
		char client_random_hex[2*GNUTLS_RANDOM_SIZE+1];
Packit Service 4684c1
		char secret_hex[2*MAX_HASH_SIZE+1];
Packit Service 4684c1
Packit Service 4684c1
		GNUTLS_STATIC_MUTEX_LOCK(keylog_mutex);
Packit Service 4684c1
		fprintf(keylog, "%s %s %s\n",
Packit Service 4684c1
			label,
Packit Service 4684c1
			_gnutls_bin2hex(session->security_parameters.
Packit Service 4684c1
					client_random, GNUTLS_RANDOM_SIZE,
Packit Service 4684c1
					client_random_hex,
Packit Service 4684c1
					sizeof(client_random_hex), NULL),
Packit Service 4684c1
			_gnutls_bin2hex(secret, secret_size,
Packit Service 4684c1
					secret_hex, sizeof(secret_hex), NULL));
Packit Service 4684c1
		fflush(keylog);
Packit Service 4684c1
		GNUTLS_STATIC_MUTEX_UNLOCK(keylog_mutex);
Packit Service 4684c1
	}
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
void _gnutls_nss_keylog_deinit(void)
Packit Service 4684c1
{
Packit Service 4684c1
	if (keylog) {
Packit Service 4684c1
		fclose(keylog);
Packit Service 4684c1
		keylog = NULL;
Packit Service 4684c1
	}
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
/* here we generate the TLS Master secret.
Packit Service 4684c1
 */
Packit Service 4684c1
static int
Packit Service 4684c1
generate_normal_master(gnutls_session_t session,
Packit Service 4684c1
		       gnutls_datum_t * premaster, int keep_premaster)
Packit Service 4684c1
{
Packit Service 4684c1
	int ret = 0;
Packit Service 4684c1
	char buf[512];
Packit Service 4684c1
Packit Service 4684c1
	_gnutls_hard_log("INT: PREMASTER SECRET[%d]: %s\n",
Packit Service 4684c1
			 premaster->size, _gnutls_bin2hex(premaster->data,
Packit Service 4684c1
							  premaster->size,
Packit Service 4684c1
							  buf, sizeof(buf),
Packit Service 4684c1
							  NULL));
Packit Service 4684c1
	_gnutls_hard_log("INT: CLIENT RANDOM[%d]: %s\n", 32,
Packit Service 4684c1
			 _gnutls_bin2hex(session->security_parameters.
Packit Service 4684c1
					 client_random, 32, buf,
Packit Service 4684c1
					 sizeof(buf), NULL));
Packit Service 4684c1
	_gnutls_hard_log("INT: SERVER RANDOM[%d]: %s\n", 32,
Packit Service 4684c1
			 _gnutls_bin2hex(session->security_parameters.
Packit Service 4684c1
					 server_random, 32, buf,
Packit Service 4684c1
					 sizeof(buf), NULL));
Packit Service 4684c1
Packit Service 4684c1
	if (session->security_parameters.ext_master_secret == 0) {
Packit Service 4684c1
		uint8_t rnd[2 * GNUTLS_RANDOM_SIZE + 1];
Packit Service 4684c1
		memcpy(rnd, session->security_parameters.client_random,
Packit Service 4684c1
		       GNUTLS_RANDOM_SIZE);
Packit Service 4684c1
		memcpy(&rnd[GNUTLS_RANDOM_SIZE],
Packit Service 4684c1
		       session->security_parameters.server_random,
Packit Service 4684c1
		       GNUTLS_RANDOM_SIZE);
Packit Service 4684c1
Packit Service 4684c1
#ifdef ENABLE_SSL3
Packit Service 4684c1
		if (get_num_version(session) == GNUTLS_SSL3) {
Packit Service 4684c1
			ret =
Packit Service 4684c1
			    _gnutls_ssl3_generate_random(premaster->data,
Packit Service 4684c1
							 premaster->size, rnd,
Packit Service 4684c1
							 2 * GNUTLS_RANDOM_SIZE,
Packit Service 4684c1
							 GNUTLS_MASTER_SIZE,
Packit Service 4684c1
							 session->security_parameters.
Packit Service 4684c1
							 master_secret);
Packit Service 4684c1
		} else
Packit Service 4684c1
#endif
Packit Service 4684c1
			ret =
Packit Service 4684c1
			    _gnutls_PRF(session, premaster->data, premaster->size,
Packit Service 4684c1
					MASTER_SECRET, MASTER_SECRET_SIZE,
Packit Service 4684c1
					rnd, 2 * GNUTLS_RANDOM_SIZE,
Packit Service 4684c1
					GNUTLS_MASTER_SIZE,
Packit Service 4684c1
					session->security_parameters.
Packit Service 4684c1
					master_secret);
Packit Service 4684c1
	} else {
Packit Service 4684c1
		gnutls_datum_t shash = {NULL, 0};
Packit Service 4684c1
Packit Service 4684c1
		/* draft-ietf-tls-session-hash-02 */
Packit Service 4684c1
		ret = _gnutls_handshake_get_session_hash(session, &shash);
Packit Service 4684c1
		if (ret < 0)
Packit Service 4684c1
			return gnutls_assert_val(ret);
Packit Service 4684c1
#ifdef ENABLE_SSL3
Packit Service 4684c1
		if (get_num_version(session) == GNUTLS_SSL3)
Packit Service 4684c1
			return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
Packit Service 4684c1
#endif
Packit Service 4684c1
Packit Service 4684c1
		ret =
Packit Service 4684c1
		    _gnutls_PRF(session, premaster->data, premaster->size,
Packit Service 4684c1
				EXT_MASTER_SECRET, EXT_MASTER_SECRET_SIZE,
Packit Service 4684c1
				shash.data, shash.size,
Packit Service 4684c1
				GNUTLS_MASTER_SIZE,
Packit Service 4684c1
				session->security_parameters.
Packit Service 4684c1
				master_secret);
Packit Service 4684c1
Packit Service 4684c1
		gnutls_free(shash.data);
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	if (!keep_premaster)
Packit Service 4684c1
		_gnutls_free_temp_key_datum(premaster);
Packit Service 4684c1
Packit Service 4684c1
	if (ret < 0)
Packit Service 4684c1
		return ret;
Packit Service 4684c1
Packit Service 4684c1
	ret = _gnutls_call_keylog_func(session, "CLIENT_RANDOM",
Packit Service 4684c1
				       session->security_parameters.master_secret,
Packit Service 4684c1
				       GNUTLS_MASTER_SIZE);
Packit Service 4684c1
	if (ret < 0)
Packit Service 4684c1
		return gnutls_assert_val(ret);
Packit Service 4684c1
Packit Service 4684c1
	_gnutls_hard_log("INT: MASTER SECRET[%d]: %s\n",
Packit Service 4684c1
			 GNUTLS_MASTER_SIZE,
Packit Service 4684c1
			 _gnutls_bin2hex(session->security_parameters.
Packit Service 4684c1
					 master_secret, GNUTLS_MASTER_SIZE,
Packit Service 4684c1
					 buf, sizeof(buf), NULL));
Packit Service 4684c1
Packit Service 4684c1
	return ret;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
/* This is called when we want to receive the key exchange message of the
Packit Service 4684c1
 * server. It does nothing if this type of message is not required
Packit Service 4684c1
 * by the selected ciphersuite. 
Packit Service 4684c1
 */
Packit Service 4684c1
int _gnutls_send_server_kx_message(gnutls_session_t session, int again)
Packit Service 4684c1
{
Packit Service 4684c1
	gnutls_buffer_st buf;
Packit Service 4684c1
	int ret = 0;
Packit Service 4684c1
	mbuffer_st *bufel = NULL;
Packit Service 4684c1
Packit Service 4684c1
	if (session->internals.auth_struct->gnutls_generate_server_kx ==
Packit Service 4684c1
	    NULL)
Packit Service 4684c1
		return 0;
Packit Service 4684c1
Packit Service 4684c1
Packit Service 4684c1
	if (again == 0) {
Packit Service 4684c1
		ret = _gnutls_buffer_init_handshake_mbuffer(&buf;;
Packit Service 4684c1
		if (ret < 0)
Packit Service 4684c1
			return gnutls_assert_val(ret);
Packit Service 4684c1
Packit Service 4684c1
		ret =
Packit Service 4684c1
		    session->internals.auth_struct->
Packit Service 4684c1
		    gnutls_generate_server_kx(session, &buf;;
Packit Service 4684c1
Packit Service 4684c1
		if (ret == GNUTLS_E_INT_RET_0) {
Packit Service 4684c1
			gnutls_assert();
Packit Service 4684c1
			ret = 0;
Packit Service 4684c1
			goto cleanup;
Packit Service 4684c1
		}
Packit Service 4684c1
Packit Service 4684c1
		if (ret < 0) {
Packit Service 4684c1
			gnutls_assert();
Packit Service 4684c1
			goto cleanup;
Packit Service 4684c1
		}
Packit Service 4684c1
Packit Service 4684c1
		bufel = _gnutls_buffer_to_mbuffer(&buf;;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	return _gnutls_send_handshake(session, bufel, GNUTLS_HANDSHAKE_SERVER_KEY_EXCHANGE);
Packit Service 4684c1
Packit Service 4684c1
 cleanup:
Packit Service 4684c1
	_gnutls_buffer_clear(&buf;;
Packit Service 4684c1
	return ret;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
/* This function sends a certificate request message to the
Packit Service 4684c1
 * client.
Packit Service 4684c1
 */
Packit Service 4684c1
int _gnutls_send_server_crt_request(gnutls_session_t session, int again)
Packit Service 4684c1
{
Packit Service 4684c1
	gnutls_buffer_st buf;
Packit Service 4684c1
	int ret = 0;
Packit Service 4684c1
	mbuffer_st *bufel = NULL;
Packit Service 4684c1
Packit Service 4684c1
	if (session->internals.auth_struct->
Packit Service 4684c1
	    gnutls_generate_server_crt_request == NULL)
Packit Service 4684c1
		return 0;
Packit Service 4684c1
Packit Service 4684c1
	if (session->internals.send_cert_req <= 0)
Packit Service 4684c1
		return 0;
Packit Service 4684c1
Packit Service 4684c1
Packit Service 4684c1
	if (again == 0) {
Packit Service 4684c1
		ret = _gnutls_buffer_init_handshake_mbuffer(&buf;;
Packit Service 4684c1
		if (ret < 0)
Packit Service 4684c1
			return gnutls_assert_val(ret);
Packit Service 4684c1
Packit Service 4684c1
		ret =
Packit Service 4684c1
		    session->internals.auth_struct->
Packit Service 4684c1
		    gnutls_generate_server_crt_request(session, &buf;;
Packit Service 4684c1
Packit Service 4684c1
		if (ret < 0) {
Packit Service 4684c1
			gnutls_assert();
Packit Service 4684c1
			goto cleanup;
Packit Service 4684c1
		}
Packit Service 4684c1
Packit Service 4684c1
		bufel = _gnutls_buffer_to_mbuffer(&buf;;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	return _gnutls_send_handshake(session, bufel, GNUTLS_HANDSHAKE_CERTIFICATE_REQUEST);
Packit Service 4684c1
Packit Service 4684c1
 cleanup:
Packit Service 4684c1
	_gnutls_buffer_clear(&buf;;
Packit Service 4684c1
	return ret;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
Packit Service 4684c1
/* This is the function for the client to send the key
Packit Service 4684c1
 * exchange message 
Packit Service 4684c1
 */
Packit Service 4684c1
int _gnutls_send_client_kx_message(gnutls_session_t session, int again)
Packit Service 4684c1
{
Packit Service 4684c1
	gnutls_buffer_st buf;
Packit Service 4684c1
	int ret = 0;
Packit Service 4684c1
	mbuffer_st *bufel = NULL;
Packit Service 4684c1
Packit Service 4684c1
	if (session->internals.auth_struct->gnutls_generate_client_kx ==
Packit Service 4684c1
	    NULL)
Packit Service 4684c1
		return 0;
Packit Service 4684c1
Packit Service 4684c1
	if (again == 0) {
Packit Service 4684c1
		ret = _gnutls_buffer_init_handshake_mbuffer(&buf;;
Packit Service 4684c1
		if (ret < 0)
Packit Service 4684c1
			return gnutls_assert_val(ret);
Packit Service 4684c1
Packit Service 4684c1
		ret =
Packit Service 4684c1
		    session->internals.auth_struct->
Packit Service 4684c1
		    gnutls_generate_client_kx(session, &buf;;
Packit Service 4684c1
		if (ret < 0) {
Packit Service 4684c1
			gnutls_assert();
Packit Service 4684c1
			goto cleanup;
Packit Service 4684c1
		}
Packit Service 4684c1
Packit Service 4684c1
		bufel = _gnutls_buffer_to_mbuffer(&buf;;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	return _gnutls_send_handshake(session, bufel, GNUTLS_HANDSHAKE_CLIENT_KEY_EXCHANGE);
Packit Service 4684c1
Packit Service 4684c1
 cleanup:
Packit Service 4684c1
	_gnutls_buffer_clear(&buf;;
Packit Service 4684c1
	return ret;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
Packit Service 4684c1
/* This is the function for the client to send the certificate
Packit Service 4684c1
 * verify message
Packit Service 4684c1
 */
Packit Service 4684c1
int
Packit Service 4684c1
_gnutls_send_client_certificate_verify(gnutls_session_t session, int again)
Packit Service 4684c1
{
Packit Service 4684c1
	gnutls_buffer_st buf;
Packit Service 4684c1
	int ret = 0;
Packit Service 4684c1
	mbuffer_st *bufel = NULL;
Packit Service 4684c1
Packit Service 4684c1
	/* This is a packet that is only sent by the client
Packit Service 4684c1
	 */
Packit Service 4684c1
	if (session->security_parameters.entity == GNUTLS_SERVER)
Packit Service 4684c1
		return 0;
Packit Service 4684c1
Packit Service 4684c1
	/* if certificate verify is not needed just exit 
Packit Service 4684c1
	 */
Packit Service 4684c1
	if (!(session->internals.hsk_flags & HSK_CRT_ASKED))
Packit Service 4684c1
		return 0;
Packit Service 4684c1
Packit Service 4684c1
Packit Service 4684c1
	if (session->internals.auth_struct->
Packit Service 4684c1
	    gnutls_generate_client_crt_vrfy == NULL) {
Packit Service 4684c1
		gnutls_assert();
Packit Service 4684c1
		return 0;	/* this algorithm does not support cli_crt_vrfy 
Packit Service 4684c1
				 */
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	if (again == 0) {
Packit Service 4684c1
		ret = _gnutls_buffer_init_handshake_mbuffer(&buf;;
Packit Service 4684c1
		if (ret < 0)
Packit Service 4684c1
			return gnutls_assert_val(ret);
Packit Service 4684c1
Packit Service 4684c1
		ret =
Packit Service 4684c1
		    session->internals.auth_struct->
Packit Service 4684c1
		    gnutls_generate_client_crt_vrfy(session, &buf;;
Packit Service 4684c1
		if (ret < 0) {
Packit Service 4684c1
			gnutls_assert();
Packit Service 4684c1
			goto cleanup;
Packit Service 4684c1
		}
Packit Service 4684c1
Packit Service 4684c1
		if (ret == 0)
Packit Service 4684c1
			goto cleanup;
Packit Service 4684c1
Packit Service 4684c1
Packit Service 4684c1
		bufel = _gnutls_buffer_to_mbuffer(&buf;;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	return _gnutls_send_handshake(session, bufel, GNUTLS_HANDSHAKE_CERTIFICATE_VERIFY);
Packit Service 4684c1
Packit Service 4684c1
 cleanup:
Packit Service 4684c1
	_gnutls_buffer_clear(&buf;;
Packit Service 4684c1
	return ret;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
/* This is called when we want send our certificate
Packit Service 4684c1
 */
Packit Service 4684c1
int _gnutls_send_client_certificate(gnutls_session_t session, int again)
Packit Service 4684c1
{
Packit Service 4684c1
	gnutls_buffer_st buf;
Packit Service 4684c1
	int ret = 0;
Packit Service 4684c1
	mbuffer_st *bufel = NULL;
Packit Service 4684c1
Packit Service 4684c1
	if (!(session->internals.hsk_flags & HSK_CRT_ASKED))
Packit Service 4684c1
		return 0;
Packit Service 4684c1
Packit Service 4684c1
	if (session->internals.auth_struct->
Packit Service 4684c1
	    gnutls_generate_client_certificate == NULL)
Packit Service 4684c1
		return 0;
Packit Service 4684c1
Packit Service 4684c1
	if (again == 0) {
Packit Service 4684c1
		ret = _gnutls_buffer_init_handshake_mbuffer(&buf;;
Packit Service 4684c1
		if (ret < 0)
Packit Service 4684c1
			return gnutls_assert_val(ret);
Packit Service 4684c1
Packit Service 4684c1
#ifdef ENABLE_SSL3
Packit Service 4684c1
		if (get_num_version(session) != GNUTLS_SSL3 ||
Packit Service 4684c1
		    session->internals.selected_cert_list_length > 0)
Packit Service 4684c1
#endif
Packit Service 4684c1
		{
Packit Service 4684c1
			/* TLS 1.x or SSL 3.0 with a valid certificate 
Packit Service 4684c1
			 */
Packit Service 4684c1
			ret =
Packit Service 4684c1
			    session->internals.auth_struct->
Packit Service 4684c1
			    gnutls_generate_client_certificate(session,
Packit Service 4684c1
							       &buf;;
Packit Service 4684c1
Packit Service 4684c1
			if (ret < 0) {
Packit Service 4684c1
				gnutls_assert();
Packit Service 4684c1
				goto cleanup;
Packit Service 4684c1
			}
Packit Service 4684c1
		}
Packit Service 4684c1
Packit Service 4684c1
		bufel = _gnutls_buffer_to_mbuffer(&buf;;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
#ifdef ENABLE_SSL3
Packit Service 4684c1
	/* In the SSL 3.0 protocol we need to send a
Packit Service 4684c1
	 * no certificate alert instead of an
Packit Service 4684c1
	 * empty certificate.
Packit Service 4684c1
	 */
Packit Service 4684c1
	if (get_num_version(session) == GNUTLS_SSL3 &&
Packit Service 4684c1
	    session->internals.selected_cert_list_length == 0) {
Packit Service 4684c1
		_mbuffer_xfree(&bufel);
Packit Service 4684c1
		return
Packit Service 4684c1
		    gnutls_alert_send(session, GNUTLS_AL_WARNING,
Packit Service 4684c1
				      GNUTLS_A_SSL3_NO_CERTIFICATE);
Packit Service 4684c1
Packit Service 4684c1
	} else		/* TLS 1.0 or SSL 3.0 with a valid certificate 
Packit Service 4684c1
			 */
Packit Service 4684c1
#endif
Packit Service 4684c1
		return _gnutls_send_handshake(session, bufel, GNUTLS_HANDSHAKE_CERTIFICATE_PKT);
Packit Service 4684c1
Packit Service 4684c1
 cleanup:
Packit Service 4684c1
	_gnutls_buffer_clear(&buf;;
Packit Service 4684c1
	return ret;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
Packit Service 4684c1
/* This is called when we want send our certificate
Packit Service 4684c1
 */
Packit Service 4684c1
int _gnutls_send_server_certificate(gnutls_session_t session, int again)
Packit Service 4684c1
{
Packit Service 4684c1
	gnutls_buffer_st buf;
Packit Service 4684c1
	int ret = 0;
Packit Service 4684c1
	mbuffer_st *bufel = NULL;
Packit Service 4684c1
Packit Service 4684c1
	if (session->internals.auth_struct->
Packit Service 4684c1
	    gnutls_generate_server_certificate == NULL)
Packit Service 4684c1
		return 0;
Packit Service 4684c1
Packit Service 4684c1
	if (again == 0) {
Packit Service 4684c1
		ret = _gnutls_buffer_init_handshake_mbuffer(&buf;;
Packit Service 4684c1
		if (ret < 0)
Packit Service 4684c1
			return gnutls_assert_val(ret);
Packit Service 4684c1
Packit Service 4684c1
		ret =
Packit Service 4684c1
		    session->internals.auth_struct->
Packit Service 4684c1
		    gnutls_generate_server_certificate(session, &buf;;
Packit Service 4684c1
Packit Service 4684c1
		if (ret < 0) {
Packit Service 4684c1
			gnutls_assert();
Packit Service 4684c1
			goto cleanup;
Packit Service 4684c1
		}
Packit Service 4684c1
Packit Service 4684c1
		bufel = _gnutls_buffer_to_mbuffer(&buf;;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	return _gnutls_send_handshake(session, bufel, GNUTLS_HANDSHAKE_CERTIFICATE_PKT);
Packit Service 4684c1
Packit Service 4684c1
 cleanup:
Packit Service 4684c1
	_gnutls_buffer_clear(&buf;;
Packit Service 4684c1
	return ret;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
Packit Service 4684c1
int _gnutls_recv_server_kx_message(gnutls_session_t session)
Packit Service 4684c1
{
Packit Service 4684c1
	gnutls_buffer_st buf;
Packit Service 4684c1
	int ret = 0;
Packit Service 4684c1
	unsigned int optflag = 0;
Packit Service 4684c1
Packit Service 4684c1
	if (session->internals.auth_struct->gnutls_process_server_kx !=
Packit Service 4684c1
	    NULL) {
Packit Service 4684c1
		/* Server key exchange packet is optional for PSK. */
Packit Service 4684c1
		if (_gnutls_session_is_psk(session))
Packit Service 4684c1
			optflag = 1;
Packit Service 4684c1
Packit Service 4684c1
		ret =
Packit Service 4684c1
		    _gnutls_recv_handshake(session,
Packit Service 4684c1
					   GNUTLS_HANDSHAKE_SERVER_KEY_EXCHANGE,
Packit Service 4684c1
					   optflag, &buf;;
Packit Service 4684c1
		if (ret < 0) {
Packit Service 4684c1
			gnutls_assert();
Packit Service 4684c1
			return ret;
Packit Service 4684c1
		}
Packit Service 4684c1
Packit Service 4684c1
		ret =
Packit Service 4684c1
		    session->internals.auth_struct->
Packit Service 4684c1
		    gnutls_process_server_kx(session, buf.data,
Packit Service 4684c1
					     buf.length);
Packit Service 4684c1
		_gnutls_buffer_clear(&buf;;
Packit Service 4684c1
Packit Service 4684c1
		if (ret < 0) {
Packit Service 4684c1
			gnutls_assert();
Packit Service 4684c1
			return ret;
Packit Service 4684c1
		}
Packit Service 4684c1
Packit Service 4684c1
	}
Packit Service 4684c1
	return ret;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
int _gnutls_recv_server_crt_request(gnutls_session_t session)
Packit Service 4684c1
{
Packit Service 4684c1
	gnutls_buffer_st buf;
Packit Service 4684c1
	int ret = 0;
Packit Service 4684c1
Packit Service 4684c1
	if (session->internals.auth_struct->
Packit Service 4684c1
	    gnutls_process_server_crt_request != NULL) {
Packit Service 4684c1
Packit Service 4684c1
		ret =
Packit Service 4684c1
		    _gnutls_recv_handshake(session,
Packit Service 4684c1
					   GNUTLS_HANDSHAKE_CERTIFICATE_REQUEST,
Packit Service 4684c1
					   1, &buf;;
Packit Service 4684c1
		if (ret < 0)
Packit Service 4684c1
			return ret;
Packit Service 4684c1
Packit Service 4684c1
		if (ret == 0 && buf.length == 0) {
Packit Service 4684c1
			_gnutls_buffer_clear(&buf;;
Packit Service 4684c1
			return 0;	/* ignored */
Packit Service 4684c1
		}
Packit Service 4684c1
Packit Service 4684c1
		ret =
Packit Service 4684c1
		    session->internals.auth_struct->
Packit Service 4684c1
		    gnutls_process_server_crt_request(session, buf.data,
Packit Service 4684c1
						      buf.length);
Packit Service 4684c1
		_gnutls_buffer_clear(&buf;;
Packit Service 4684c1
		if (ret < 0)
Packit Service 4684c1
			return ret;
Packit Service 4684c1
Packit Service 4684c1
	}
Packit Service 4684c1
	return ret;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
int _gnutls_recv_client_kx_message(gnutls_session_t session)
Packit Service 4684c1
{
Packit Service 4684c1
	gnutls_buffer_st buf;
Packit Service 4684c1
	int ret = 0;
Packit Service 4684c1
Packit Service 4684c1
Packit Service 4684c1
	/* Do key exchange only if the algorithm permits it */
Packit Service 4684c1
	if (session->internals.auth_struct->gnutls_process_client_kx !=
Packit Service 4684c1
	    NULL) {
Packit Service 4684c1
Packit Service 4684c1
		ret =
Packit Service 4684c1
		    _gnutls_recv_handshake(session,
Packit Service 4684c1
					   GNUTLS_HANDSHAKE_CLIENT_KEY_EXCHANGE,
Packit Service 4684c1
					   0, &buf;;
Packit Service 4684c1
		if (ret < 0)
Packit Service 4684c1
			return ret;
Packit Service 4684c1
Packit Service 4684c1
		ret =
Packit Service 4684c1
		    session->internals.auth_struct->
Packit Service 4684c1
		    gnutls_process_client_kx(session, buf.data,
Packit Service 4684c1
					     buf.length);
Packit Service 4684c1
		_gnutls_buffer_clear(&buf;;
Packit Service 4684c1
		if (ret < 0)
Packit Service 4684c1
			return ret;
Packit Service 4684c1
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	return ret;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
Packit Service 4684c1
int _gnutls_recv_client_certificate(gnutls_session_t session)
Packit Service 4684c1
{
Packit Service 4684c1
	gnutls_buffer_st buf;
Packit Service 4684c1
	int ret = 0;
Packit Service 4684c1
	int optional;
Packit Service 4684c1
Packit Service 4684c1
	if (session->internals.auth_struct->
Packit Service 4684c1
	    gnutls_process_client_certificate == NULL)
Packit Service 4684c1
		return 0;
Packit Service 4684c1
Packit Service 4684c1
	/* if we have not requested a certificate then just return
Packit Service 4684c1
	 */
Packit Service 4684c1
	if (session->internals.send_cert_req == 0) {
Packit Service 4684c1
		return 0;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	if (session->internals.send_cert_req == GNUTLS_CERT_REQUIRE)
Packit Service 4684c1
		optional = 0;
Packit Service 4684c1
	else
Packit Service 4684c1
		optional = 1;
Packit Service 4684c1
Packit Service 4684c1
	ret =
Packit Service 4684c1
	    _gnutls_recv_handshake(session,
Packit Service 4684c1
				   GNUTLS_HANDSHAKE_CERTIFICATE_PKT,
Packit Service 4684c1
				   optional, &buf;;
Packit Service 4684c1
Packit Service 4684c1
	if (ret < 0) {
Packit Service 4684c1
		/* Handle the case of old SSL3 clients who send
Packit Service 4684c1
		 * a warning alert instead of an empty certificate to indicate
Packit Service 4684c1
		 * no certificate.
Packit Service 4684c1
		 */
Packit Service 4684c1
#ifdef ENABLE_SSL3
Packit Service 4684c1
		if (optional != 0 &&
Packit Service 4684c1
		    ret == GNUTLS_E_WARNING_ALERT_RECEIVED &&
Packit Service 4684c1
		    get_num_version(session) == GNUTLS_SSL3 &&
Packit Service 4684c1
		    gnutls_alert_get(session) ==
Packit Service 4684c1
		    GNUTLS_A_SSL3_NO_CERTIFICATE) {
Packit Service 4684c1
Packit Service 4684c1
			/* SSL3 does not send an empty certificate,
Packit Service 4684c1
			 * but this alert. So we just ignore it.
Packit Service 4684c1
			 */
Packit Service 4684c1
			gnutls_assert();
Packit Service 4684c1
			return 0;
Packit Service 4684c1
		}
Packit Service 4684c1
#endif
Packit Service 4684c1
Packit Service 4684c1
		/* certificate was required 
Packit Service 4684c1
		 */
Packit Service 4684c1
		if ((ret == GNUTLS_E_WARNING_ALERT_RECEIVED
Packit Service 4684c1
		     || ret == GNUTLS_E_FATAL_ALERT_RECEIVED)
Packit Service 4684c1
		    && optional == 0) {
Packit Service 4684c1
			gnutls_assert();
Packit Service 4684c1
			return GNUTLS_E_NO_CERTIFICATE_FOUND;
Packit Service 4684c1
		}
Packit Service 4684c1
Packit Service 4684c1
		return ret;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	if (ret == 0 && buf.length == 0 && optional != 0) {
Packit Service 4684c1
		/* Client has not sent the certificate message.
Packit Service 4684c1
		 * well I'm not sure we should accept this
Packit Service 4684c1
		 * behaviour.
Packit Service 4684c1
		 */
Packit Service 4684c1
		gnutls_assert();
Packit Service 4684c1
		ret = 0;
Packit Service 4684c1
		goto cleanup;
Packit Service 4684c1
	}
Packit Service 4684c1
	ret =
Packit Service 4684c1
	    session->internals.auth_struct->
Packit Service 4684c1
	    gnutls_process_client_certificate(session, buf.data,
Packit Service 4684c1
					      buf.length);
Packit Service 4684c1
Packit Service 4684c1
	if (ret < 0 && ret != GNUTLS_E_NO_CERTIFICATE_FOUND) {
Packit Service 4684c1
		gnutls_assert();
Packit Service 4684c1
		goto cleanup;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	/* ok we should expect a certificate verify message now 
Packit Service 4684c1
	 */
Packit Service 4684c1
	if (ret == GNUTLS_E_NO_CERTIFICATE_FOUND && optional != 0)
Packit Service 4684c1
		ret = 0;
Packit Service 4684c1
	else
Packit Service 4684c1
		session->internals.hsk_flags |= HSK_CRT_VRFY_EXPECTED;
Packit Service 4684c1
Packit Service 4684c1
      cleanup:
Packit Service 4684c1
	_gnutls_buffer_clear(&buf;;
Packit Service 4684c1
	return ret;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
int _gnutls_recv_server_certificate(gnutls_session_t session)
Packit Service 4684c1
{
Packit Service 4684c1
	gnutls_buffer_st buf;
Packit Service 4684c1
	int ret = 0;
Packit Service 4684c1
Packit Service 4684c1
	if (session->internals.auth_struct->
Packit Service 4684c1
	    gnutls_process_server_certificate != NULL) {
Packit Service 4684c1
Packit Service 4684c1
		ret =
Packit Service 4684c1
		    _gnutls_recv_handshake(session,
Packit Service 4684c1
					   GNUTLS_HANDSHAKE_CERTIFICATE_PKT,
Packit Service 4684c1
					   0, &buf;;
Packit Service 4684c1
		if (ret < 0) {
Packit Service 4684c1
			gnutls_assert();
Packit Service 4684c1
			return ret;
Packit Service 4684c1
		}
Packit Service 4684c1
Packit Service 4684c1
		ret =
Packit Service 4684c1
		    session->internals.auth_struct->
Packit Service 4684c1
		    gnutls_process_server_certificate(session, buf.data,
Packit Service 4684c1
						      buf.length);
Packit Service 4684c1
		_gnutls_buffer_clear(&buf;;
Packit Service 4684c1
		if (ret < 0) {
Packit Service 4684c1
			gnutls_assert();
Packit Service 4684c1
			return ret;
Packit Service 4684c1
		}
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	return ret;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
Packit Service 4684c1
/* Recv the client certificate verify. This packet may not
Packit Service 4684c1
 * arrive if the peer did not send us a certificate.
Packit Service 4684c1
 */
Packit Service 4684c1
int
Packit Service 4684c1
_gnutls_recv_client_certificate_verify_message(gnutls_session_t session)
Packit Service 4684c1
{
Packit Service 4684c1
	gnutls_buffer_st buf;
Packit Service 4684c1
	int ret = 0;
Packit Service 4684c1
Packit Service 4684c1
Packit Service 4684c1
	if (session->internals.auth_struct->
Packit Service 4684c1
	    gnutls_process_client_crt_vrfy == NULL)
Packit Service 4684c1
		return 0;
Packit Service 4684c1
Packit Service 4684c1
	if (session->internals.send_cert_req == 0 ||
Packit Service 4684c1
	    (!(session->internals.hsk_flags & HSK_CRT_VRFY_EXPECTED))) {
Packit Service 4684c1
		return 0;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	ret =
Packit Service 4684c1
	    _gnutls_recv_handshake(session,
Packit Service 4684c1
				   GNUTLS_HANDSHAKE_CERTIFICATE_VERIFY,
Packit Service 4684c1
				   1, &buf;;
Packit Service 4684c1
	if (ret < 0)
Packit Service 4684c1
		return ret;
Packit Service 4684c1
Packit Service 4684c1
	if (ret == 0 && buf.length == 0
Packit Service 4684c1
	    && session->internals.send_cert_req == GNUTLS_CERT_REQUIRE) {
Packit Service 4684c1
		/* certificate was required */
Packit Service 4684c1
		gnutls_assert();
Packit Service 4684c1
		ret = GNUTLS_E_NO_CERTIFICATE_FOUND;
Packit Service 4684c1
		goto cleanup;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	ret =
Packit Service 4684c1
	    session->internals.auth_struct->
Packit Service 4684c1
	    gnutls_process_client_crt_vrfy(session, buf.data, buf.length);
Packit Service 4684c1
Packit Service 4684c1
      cleanup:
Packit Service 4684c1
	_gnutls_buffer_clear(&buf;;
Packit Service 4684c1
	return ret;
Packit Service 4684c1
}