From: Dr. Stephen Henson Date: Wed, 26 Dec 2012 16:22:19 +0000 (+0000) Subject: perform sanity checks on server certificate type as soon as it is received instead... X-Git-Tag: OpenSSL_1_0_2-beta1~498 X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff_plain;h=67d9dcf0030fc06b4bb68df0302761123f0d065f perform sanity checks on server certificate type as soon as it is received instead of waiting until server key exchange (backport from HEAD) --- diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c index 0329da2df9..a03da24e2d 100644 --- a/ssl/s3_clnt.c +++ b/ssl/s3_clnt.c @@ -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? diff --git a/ssl/ssl.h b/ssl/ssl.h index 080735a6ea..9d9dafeff9 100644 --- a/ssl/ssl.h +++ b/ssl/ssl.h @@ -2780,6 +2780,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 diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c index f0cc5b1db6..bac2515789 100644 --- a/ssl/ssl_ciph.c +++ b/ssl/ssl_ciph.c @@ -1890,5 +1890,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; + } + diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c index d3c8bdea72..2a8b4bf712 100644 --- a/ssl/ssl_err.c +++ b/ssl/ssl_err.c @@ -608,6 +608,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"}, diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index 71128f5124..6c108aa17e 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -2335,56 +2335,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(const 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(const SSL *s) diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h index 701dac9d12..a4689f745f 100644 --- a/ssl/ssl_locl.h +++ b/ssl/ssl_locl.h @@ -921,7 +921,8 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *meth, void ssl_update_cache(SSL *s, int mode); int ssl_cipher_get_evp(const SSL_SESSION *s,const EVP_CIPHER **enc, const EVP_MD **md,int *mac_pkey_type,int *mac_secret_size, SSL_COMP **comp); -int ssl_get_handshake_digest(int i,long *mask,const EVP_MD **md); +int ssl_get_handshake_digest(int i,long *mask,const EVP_MD **md); +int ssl_cipher_get_cert_index(const SSL_CIPHER *c); int ssl_cert_set0_chain(CERT *c, STACK_OF(X509) *chain); int ssl_cert_set1_chain(CERT *c, STACK_OF(X509) *chain); int ssl_cert_add0_chain_cert(CERT *c, X509 *x);