Commit e469af8d authored by Dr. Stephen Henson's avatar Dr. Stephen Henson
Browse files

Process signature algorithms before deciding on certificate.



The supported signature algorithms extension needs to be processed before
the certificate to use is decided and before a cipher is selected (as the
set of shared signature algorithms supported may impact the choice).
Reviewed-by: default avatarMatt Caswell <matt@openssl.org>

(cherry picked from commit 56e8dc542bd693b2dccea8828b3d8e5fc6932d0c)

Conflicts:
	ssl/ssl.h
	ssl/ssl_err.c
parent bcb245a7
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -1378,6 +1378,11 @@ int ssl3_get_client_hello(SSL *s)
			goto f_err;
			}
		ciphers=NULL;
		if (!tls1_set_server_sigalgs(s))
			{
			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_CLIENTHELLO_TLSEXT);
			goto err;
			}
		/* Let cert callback update server certificates if required */
		retry_cert:		
		if (s->cert->cert_cb)
+1 −1
Original line number Diff line number Diff line
@@ -2682,7 +2682,6 @@ void ERR_load_SSL_strings(void);
#define SSL_F_SSL_CERT_INSTANTIATE			 214
#define SSL_F_SSL_CERT_NEW				 162
#define SSL_F_SSL_CERT_SET0_CHAIN			 340
#define SSL_F_SSL_CHECK_CLIENTHELLO_TLSEXT_LATE		 335
#define SSL_F_SSL_CHECK_PRIVATE_KEY			 163
#define SSL_F_SSL_CHECK_SERVERHELLO_TLSEXT		 280
#define SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG		 279
@@ -2782,6 +2781,7 @@ void ERR_load_SSL_strings(void);
#define SSL_F_TLS1_PREPARE_SERVERHELLO_TLSEXT		 276
#define SSL_F_TLS1_PRF					 284
#define SSL_F_TLS1_SETUP_KEY_BLOCK			 211
#define SSL_F_TLS1_SET_SERVER_SIGALGS			 335
#define SSL_F_WRITE_PENDING				 212

/* Reason codes. */
+1 −1
Original line number Diff line number Diff line
@@ -201,7 +201,6 @@ static ERR_STRING_DATA SSL_str_functs[]=
{ERR_FUNC(SSL_F_SSL_CERT_INSTANTIATE),	"SSL_CERT_INSTANTIATE"},
{ERR_FUNC(SSL_F_SSL_CERT_NEW),	"ssl_cert_new"},
{ERR_FUNC(SSL_F_SSL_CERT_SET0_CHAIN),	"ssl_cert_set0_chain"},
{ERR_FUNC(SSL_F_SSL_CHECK_CLIENTHELLO_TLSEXT_LATE),	"ssl_check_clienthello_tlsext_late"},
{ERR_FUNC(SSL_F_SSL_CHECK_PRIVATE_KEY),	"SSL_check_private_key"},
{ERR_FUNC(SSL_F_SSL_CHECK_SERVERHELLO_TLSEXT),	"SSL_CHECK_SERVERHELLO_TLSEXT"},
{ERR_FUNC(SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG),	"ssl_check_srvr_ecc_cert_and_alg"},
@@ -301,6 +300,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
{ERR_FUNC(SSL_F_TLS1_PREPARE_SERVERHELLO_TLSEXT),	"TLS1_PREPARE_SERVERHELLO_TLSEXT"},
{ERR_FUNC(SSL_F_TLS1_PRF),	"tls1_prf"},
{ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK),	"tls1_setup_key_block"},
{ERR_FUNC(SSL_F_TLS1_SET_SERVER_SIGALGS),	"tls1_set_server_sigalgs"},
{ERR_FUNC(SSL_F_WRITE_PENDING),	"WRITE_PENDING"},
{0,NULL}
	};
+1 −0
Original line number Diff line number Diff line
@@ -1329,6 +1329,7 @@ int tls1_shared_list(SSL *s,
unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, unsigned char *limit, int *al);
unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, unsigned char *limit, int *al);
int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **data, unsigned char *d, int n);
int tls1_set_server_sigalgs(SSL *s);
int ssl_check_clienthello_tlsext_late(SSL *s);
int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **data, unsigned char *d, int n);
int ssl_prepare_clienthello_tlsext(SSL *s);
+44 −38
Original line number Diff line number Diff line
@@ -2967,11 +2967,54 @@ static int ssl_check_clienthello_tlsext_early(SSL *s)
		}
	}

int tls1_set_server_sigalgs(SSL *s)
	{
	int al;
	size_t i;
	/* Clear any shared sigtnature algorithms */
	if (s->cert->shared_sigalgs)
		{
		OPENSSL_free(s->cert->shared_sigalgs);
		s->cert->shared_sigalgs = NULL;
		}
	/* Clear certificate digests and validity flags */
	for (i = 0; i < SSL_PKEY_NUM; i++)
		{
		s->cert->pkeys[i].digest = NULL;
		s->cert->pkeys[i].valid_flags = 0;
		}

	/* If sigalgs received process it. */
	if (s->cert->peer_sigalgs)
		{
		if (!tls1_process_sigalgs(s))
			{
			SSLerr(SSL_F_TLS1_SET_SERVER_SIGALGS,
					ERR_R_MALLOC_FAILURE);
			al = SSL_AD_INTERNAL_ERROR;
			goto err;
			}
		/* Fatal error is no shared signature algorithms */
		if (!s->cert->shared_sigalgs)
			{
			SSLerr(SSL_F_TLS1_SET_SERVER_SIGALGS,
					SSL_R_NO_SHARED_SIGATURE_ALGORITHMS);
			al = SSL_AD_ILLEGAL_PARAMETER;
			goto err;
			}
		}
	else
		ssl_cert_set_default_md(s->cert);
	return 1;
	err:
	ssl3_send_alert(s, SSL3_AL_FATAL, al);
	return 0;
	}

int ssl_check_clienthello_tlsext_late(SSL *s)
	{
	int ret = SSL_TLSEXT_ERR_OK;
	int al;
	size_t i;

	/* If status request then ask callback what to do.
 	 * Note: this must be called after servername callbacks in case
@@ -3017,43 +3060,6 @@ int ssl_check_clienthello_tlsext_late(SSL *s)
	else
		s->tlsext_status_expected = 0;

	/* Clear any shared sigtnature algorithms */
	if (s->cert->shared_sigalgs)
		{
		OPENSSL_free(s->cert->shared_sigalgs);
		s->cert->shared_sigalgs = NULL;
		}
	/* Clear certificate digests and validity flags */
	for (i = 0; i < SSL_PKEY_NUM; i++)
		{
		s->cert->pkeys[i].digest = NULL;
		s->cert->pkeys[i].valid_flags = 0;
		}

	/* If sigalgs received process it. */
	if (s->cert->peer_sigalgs)
		{
		if (!tls1_process_sigalgs(s))
			{
			SSLerr(SSL_F_SSL_CHECK_CLIENTHELLO_TLSEXT_LATE,
					ERR_R_MALLOC_FAILURE);
			ret = SSL_TLSEXT_ERR_ALERT_FATAL;
			al = SSL_AD_INTERNAL_ERROR;
			goto err;
			}
		/* Fatal error is no shared signature algorithms */
		if (!s->cert->shared_sigalgs)
			{
			SSLerr(SSL_F_SSL_CHECK_CLIENTHELLO_TLSEXT_LATE,
					SSL_R_NO_SHARED_SIGATURE_ALGORITHMS);
			ret = SSL_TLSEXT_ERR_ALERT_FATAL;
			al = SSL_AD_ILLEGAL_PARAMETER;
			goto err;
			}
		}
	else
		ssl_cert_set_default_md(s->cert);

 err:
	switch (ret)
		{