perform sanity checks on server certificate type as soon as it is received instead...
authorDr. Stephen Henson <steve@openssl.org>
Wed, 26 Dec 2012 16:22:19 +0000 (16:22 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Wed, 26 Dec 2012 16:22:19 +0000 (16:22 +0000)
(backport from HEAD)

ssl/s3_clnt.c
ssl/ssl.h
ssl/ssl_ciph.c
ssl/ssl_err.c
ssl/ssl_lib.c
ssl/ssl_locl.h

index 0329da2df9545ec30bd51040b21eb97e1f306cc9..a03da24e2d81adb3bbe2117569594f6a33713d18 100644 (file)
@@ -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?
index 080735a6ea358cd9ac62735f5abf7f9937413a1b..9d9dafeff92259bfb2c8eb39eacdc8bafa3f460a 100644 (file)
--- 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
index f0cc5b1db68e3c33a61937766e5b805a3f4fc74b..bac2515789ba965648a9aa6770c134452c44a32d 100644 (file)
@@ -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;
+       }
+
index d3c8bdea7276ff2860591a595bdb67166f51a4d7..2a8b4bf712d8ed6a8e291c7fe095ac1bee86ed44 100644 (file)
@@ -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"},
index 71128f512410f4998cb90f8ef0b6d216139a797c..6c108aa17e636b2422b8ec9a49b7d79ae6c2cd9f 100644 (file)
@@ -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)
index 701dac9d12a02f4cf1ce341b6af5468e0ae6bb75..a4689f745fe3c6df7ec1db2c4c5961ca111f173e 100644 (file)
@@ -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);