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

perform sanity checks on server certificate type as soon as it is received...

perform sanity checks on server certificate type as soon as it is received instead of waiting until server key exchange
parent ef6b34be
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -1225,6 +1225,15 @@ int ssl3_get_server_certificate(SSL *s)

	if (need_cert)
		{
		int exp_idx = ssl_cipher_get_cert_index(s->s3->tmp.new_cipher);
		if (exp_idx >= 0 && i != exp_idx)
			{
			x=NULL;
			al=SSL_AD_ILLEGAL_PARAMETER;
			SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,
				SSL_R_WRONG_CERTIFICATE_TYPE);
			goto f_err;
			}
		sc->peer_cert_type=i;
		CRYPTO_add(&x->references,1,CRYPTO_LOCK_X509);
		/* Why would the following ever happen?
+1 −0
Original line number Diff line number Diff line
@@ -2800,6 +2800,7 @@ void ERR_load_SSL_strings(void);
#define SSL_R_UNSUPPORTED_STATUS_TYPE			 329
#define SSL_R_USE_SRTP_NOT_NEGOTIATED			 369
#define SSL_R_WRITE_BIO_NOT_SET				 260
#define SSL_R_WRONG_CERTIFICATE_TYPE			 383
#define SSL_R_WRONG_CIPHER_RETURNED			 261
#define SSL_R_WRONG_CURVE				 378
#define SSL_R_WRONG_MESSAGE_TYPE			 262
+43 −1
Original line number Diff line number Diff line
@@ -1889,5 +1889,47 @@ const char *SSL_COMP_get_name(const COMP_METHOD *comp)
		return comp->name;
	return NULL;
	}

#endif
/* For a cipher return the index corresponding to the certificate type */
int ssl_cipher_get_cert_index(const SSL_CIPHER *c)
	{
 	unsigned long alg_k, alg_a;

	alg_k = c->algorithm_mkey;
	alg_a = c->algorithm_auth;

	if (alg_k & (SSL_kECDHr|SSL_kECDHe))
		{
		/* we don't need to look at SSL_kEECDH
		 * since no certificate is needed for
		 * anon ECDH and for authenticated
		 * EECDH, the check for the auth
		 * algorithm will set i correctly
		 * NOTE: For ECDH-RSA, we need an ECC
		 * not an RSA cert but for EECDH-RSA
		 * we need an RSA cert. Placing the
		 * checks for SSL_kECDH before RSA
		 * checks ensures the correct cert is chosen.
		 */
		return SSL_PKEY_ECC;
		}
	else if (alg_a & SSL_aECDSA)
		return SSL_PKEY_ECC;
	else if (alg_k & SSL_kDHr)
		return SSL_PKEY_DH_RSA;
	else if (alg_k & SSL_kDHd)
		return SSL_PKEY_DH_DSA;
	else if (alg_a & SSL_aDSS)
		return SSL_PKEY_DSA_SIGN;
	else if (alg_a & SSL_aRSA)
		return SSL_PKEY_RSA_ENC;
	else if (alg_a & SSL_aKRB5)
		/* VRS something else here? */
		return -1;
	else if (alg_a & SSL_aGOST94) 
		return SSL_PKEY_GOST94;
	else if (alg_a & SSL_aGOST01)
		return SSL_PKEY_GOST01;
	return -1;
	}
+1 −0
Original line number Diff line number Diff line
@@ -607,6 +607,7 @@ static ERR_STRING_DATA SSL_str_reasons[]=
{ERR_REASON(SSL_R_UNSUPPORTED_STATUS_TYPE),"unsupported status type"},
{ERR_REASON(SSL_R_USE_SRTP_NOT_NEGOTIATED),"use srtp not negotiated"},
{ERR_REASON(SSL_R_WRITE_BIO_NOT_SET)     ,"write bio not set"},
{ERR_REASON(SSL_R_WRONG_CERTIFICATE_TYPE),"wrong certificate type"},
{ERR_REASON(SSL_R_WRONG_CIPHER_RETURNED) ,"wrong cipher returned"},
{ERR_REASON(SSL_R_WRONG_CURVE)           ,"wrong curve"},
{ERR_REASON(SSL_R_WRONG_MESSAGE_TYPE)    ,"wrong message type"},
+6 −47
Original line number Diff line number Diff line
@@ -2336,56 +2336,15 @@ int ssl_check_srvr_ecc_cert_and_alg(X509 *x, SSL *s)

#endif

/* THIS NEEDS CLEANING UP */
static int ssl_get_server_cert_index(SSL *s)
	{
 	unsigned long alg_k, alg_a;

	alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
	alg_a = s->s3->tmp.new_cipher->algorithm_auth;

	if (alg_k & (SSL_kECDHr|SSL_kECDHe))
		{
		/* we don't need to look at SSL_kEECDH
		 * since no certificate is needed for
		 * anon ECDH and for authenticated
		 * EECDH, the check for the auth
		 * algorithm will set i correctly
		 * NOTE: For ECDH-RSA, we need an ECC
		 * not an RSA cert but for EECDH-RSA
		 * we need an RSA cert. Placing the
		 * checks for SSL_kECDH before RSA
		 * checks ensures the correct cert is chosen.
		 */
		return SSL_PKEY_ECC;
		}
	else if (alg_a & SSL_aECDSA)
		return SSL_PKEY_ECC;
	else if (alg_k & SSL_kDHr)
		return SSL_PKEY_DH_RSA;
	else if (alg_k & SSL_kDHd)
		return SSL_PKEY_DH_DSA;
	else if (alg_a & SSL_aDSS)
		return SSL_PKEY_DSA_SIGN;
	else if (alg_a & SSL_aRSA)
		{
		if (s->cert->pkeys[SSL_PKEY_RSA_ENC].x509 == NULL)
			return SSL_PKEY_RSA_SIGN;
		else
			return SSL_PKEY_RSA_ENC;
		}
	else if (alg_a & SSL_aKRB5)
		/* VRS something else here? */
		return -1;
	else if (alg_a & SSL_aGOST94) 
		return SSL_PKEY_GOST94;
	else if (alg_a & SSL_aGOST01)
		return SSL_PKEY_GOST01;
	else /* if (alg_a & SSL_aNULL) */
		{
	int idx;
	idx = ssl_cipher_get_cert_index(s->s3->tmp.new_cipher);
	if (idx == SSL_PKEY_RSA_ENC && !s->cert->pkeys[SSL_PKEY_RSA_ENC].x509)
		idx = SSL_PKEY_RSA_SIGN;
	if (idx == -1)
		SSLerr(SSL_F_SSL_GET_SERVER_CERT_INDEX,ERR_R_INTERNAL_ERROR);
		return -1;
		}
	return idx;
	}

CERT_PKEY *ssl_get_server_send_pkey(SSL *s)
Loading