Remove SESS_CERT entirely.
[openssl.git] / ssl / s3_clnt.c
index d6f53b0dea846bba4e7e93b37768faea1dfa879f..6b4c860350ff2573ce5a28d98c62c91734eaada3 100644 (file)
@@ -334,7 +334,7 @@ int ssl3_connect(SSL *s)
             if (!
                 (s->s3->tmp.
                  new_cipher->algorithm_auth & (SSL_aNULL | SSL_aSRP))
-&& !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) {
+                    && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) {
                 ret = ssl3_get_server_certificate(s);
                 if (ret <= 0)
                     goto end;
@@ -1036,7 +1036,7 @@ int ssl3_get_server_hello(SSL *s)
             al = SSL_AD_PROTOCOL_VERSION;
             goto f_err;
         }
-        s->version = s->method->version;
+        s->session->ssl_version = s->version = s->method->version;
     } else if ((p[0] != (s->version >> 8)) || (p[1] != (s->version & 0xff))) {
         SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_WRONG_SSL_VERSION);
         s->version = (s->version & 0xff00) | p[1];
@@ -1243,7 +1243,6 @@ int ssl3_get_server_certificate(SSL *s)
     const unsigned char *q, *p;
     unsigned char *d;
     STACK_OF(X509) *sk = NULL;
-    SESS_CERT *sc;
     EVP_PKEY *pkey = NULL;
 
     n = s->method->ssl_get_message(s,
@@ -1322,14 +1321,7 @@ int ssl3_get_server_certificate(SSL *s)
         goto f_err;
     }
 
-    sc = ssl_sess_cert_new();
-    if (sc == NULL)
-        goto err;
-
-    ssl_sess_cert_free(s->session->sess_cert);
-    s->session->sess_cert = sc;
-
-    sc->cert_chain = sk;
+    s->session->peer_chain = sk;
     /*
      * Inconsistency alert: cert_chain does include the peer's certificate,
      * which we don't include in s3_srvr.c
@@ -1367,15 +1359,7 @@ int ssl3_get_server_certificate(SSL *s)
                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? We just created sc a couple
-     * of lines ago.
-     */
-    X509_free(sc->peer_pkeys[i].x509);
-    sc->peer_pkeys[i].x509 = x;
-    sc->peer_key = &(sc->peer_pkeys[i]);
+    s->session->peer_type = i;
 
     X509_free(s->session->peer);
     CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
@@ -1454,7 +1438,6 @@ int ssl3_get_key_exchange(SSL *s)
          * problems later.
          */
         if (alg_k & SSL_kPSK) {
-            s->session->sess_cert = ssl_sess_cert_new();
             OPENSSL_free(s->ctx->psk_identity_hint);
             s->ctx->psk_identity_hint = NULL;
         }
@@ -1464,22 +1447,19 @@ int ssl3_get_key_exchange(SSL *s)
     }
 
     param = p = (unsigned char *)s->init_msg;
-    if (s->session->sess_cert != NULL) {
+
 #ifndef OPENSSL_NO_RSA
-        RSA_free(s->session->sess_cert->peer_rsa_tmp);
-        s->session->sess_cert->peer_rsa_tmp = NULL;
+    RSA_free(s->s3->peer_rsa_tmp);
+    s->s3->peer_rsa_tmp = NULL;
 #endif
 #ifndef OPENSSL_NO_DH
-        DH_free(s->session->sess_cert->peer_dh_tmp);
-        s->session->sess_cert->peer_dh_tmp = NULL;
+    DH_free(s->s3->peer_dh_tmp);
+    s->s3->peer_dh_tmp = NULL;
 #endif
 #ifndef OPENSSL_NO_EC
-        EC_KEY_free(s->session->sess_cert->peer_ecdh_tmp);
-        s->session->sess_cert->peer_ecdh_tmp = NULL;
+    EC_KEY_free(s->s3->peer_ecdh_tmp);
+    s->s3->peer_ecdh_tmp = NULL;
 #endif
-    } else {
-        s->session->sess_cert = ssl_sess_cert_new();
-    }
 
     /* Total length of the parameters including the length prefix */
     param_len = 0;
@@ -1625,21 +1605,8 @@ int ssl3_get_key_exchange(SSL *s)
         }
 
 /* We must check if there is a certificate */
-# ifndef OPENSSL_NO_RSA
-        if (alg_a & SSL_aRSA)
-            pkey =
-                X509_get_pubkey(s->session->
-                                sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
-# else
-        if (0) ;
-# endif
-# ifndef OPENSSL_NO_DSA
-        else if (alg_a & SSL_aDSS)
-            pkey =
-                X509_get_pubkey(s->session->
-                                sess_cert->peer_pkeys[SSL_PKEY_DSA_SIGN].
-                                x509);
-# endif
+        if (alg_a & (SSL_aRSA|SSL_aDSS))
+            pkey = X509_get_pubkey(s->session->peer);
     } else
 #endif                          /* !OPENSSL_NO_SRP */
 #ifndef OPENSSL_NO_RSA
@@ -1697,14 +1664,19 @@ int ssl3_get_key_exchange(SSL *s)
 
         /* this should be because we are using an export cipher */
         if (alg_a & SSL_aRSA)
-            pkey =
-                X509_get_pubkey(s->session->
-                                sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
+            pkey = X509_get_pubkey(s->session->peer);
         else {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
             goto err;
         }
-        s->session->sess_cert->peer_rsa_tmp = rsa;
+
+        if (EVP_PKEY_bits(pkey) <= SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) {
+            al = SSL_AD_UNEXPECTED_MESSAGE;
+            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_UNEXPECTED_MESSAGE);
+            goto f_err;
+        }
+
+        s->s3->peer_rsa_tmp = rsa;
         rsa = NULL;
     }
 #else                           /* OPENSSL_NO_RSA */
@@ -1782,24 +1754,11 @@ int ssl3_get_key_exchange(SSL *s)
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_DH_KEY_TOO_SMALL);
             goto f_err;
         }
-# ifndef OPENSSL_NO_RSA
-        if (alg_a & SSL_aRSA)
-            pkey =
-                X509_get_pubkey(s->session->
-                                sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
-# else
-        if (0) ;
-# endif
-# ifndef OPENSSL_NO_DSA
-        else if (alg_a & SSL_aDSS)
-            pkey =
-                X509_get_pubkey(s->session->
-                                sess_cert->peer_pkeys[SSL_PKEY_DSA_SIGN].
-                                x509);
-# endif
+        if (alg_a & (SSL_aRSA|SSL_aDSS))
+            pkey = X509_get_pubkey(s->session->peer);
         /* else anonymous DH, so no certificate or pkey. */
 
-        s->session->sess_cert->peer_dh_tmp = dh;
+        s->s3->peer_dh_tmp = dh;
         dh = NULL;
     }
 #endif                          /* !OPENSSL_NO_DH */
@@ -1898,19 +1857,15 @@ int ssl3_get_key_exchange(SSL *s)
         if (0) ;
 # ifndef OPENSSL_NO_RSA
         else if (alg_a & SSL_aRSA)
-            pkey =
-                X509_get_pubkey(s->session->
-                                sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
+            pkey = X509_get_pubkey(s->session->peer);
 # endif
 # ifndef OPENSSL_NO_EC
         else if (alg_a & SSL_aECDSA)
-            pkey =
-                X509_get_pubkey(s->session->
-                                sess_cert->peer_pkeys[SSL_PKEY_ECC].x509);
+            pkey = X509_get_pubkey(s->session->peer);
 # endif
         /* else anonymous ECDH, so no certificate or pkey. */
         EC_KEY_set_public_key(ecdh, srvr_ecpoint);
-        s->session->sess_cert->peer_ecdh_tmp = ecdh;
+        s->s3->peer_ecdh_tmp = ecdh;
         ecdh = NULL;
         BN_CTX_free(bn_ctx);
         bn_ctx = NULL;
@@ -2430,7 +2385,7 @@ int ssl3_send_client_key_exchange(SSL *s)
             if (!pms)
                 goto memerr;
 
-            if (s->session->sess_cert == NULL) {
+            if (s->session->peer == NULL) {
                 /*
                  * We should always have a server certificate with SSL_kRSA.
                  */
@@ -2439,13 +2394,10 @@ int ssl3_send_client_key_exchange(SSL *s)
                 goto err;
             }
 
-            if (s->session->sess_cert->peer_rsa_tmp != NULL)
-                rsa = s->session->sess_cert->peer_rsa_tmp;
+            if (s->s3->peer_rsa_tmp != NULL)
+                rsa = s->s3->peer_rsa_tmp;
             else {
-                pkey =
-                    X509_get_pubkey(s->session->
-                                    sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].
-                                    x509);
+                pkey = X509_get_pubkey(s->session->peer);
                 if ((pkey == NULL) || (pkey->type != EVP_PKEY_RSA)
                     || (pkey->pkey.rsa == NULL)) {
                     SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
@@ -2488,24 +2440,13 @@ int ssl3_send_client_key_exchange(SSL *s)
 #ifndef OPENSSL_NO_DH
         else if (alg_k & (SSL_kDHE | SSL_kDHr | SSL_kDHd)) {
             DH *dh_srvr, *dh_clnt;
-            SESS_CERT *scert = s->session->sess_cert;
-
-            if (scert == NULL) {
-                ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
-                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
-                       SSL_R_UNEXPECTED_MESSAGE);
-                goto err;
-            }
-
-            if (scert->peer_dh_tmp != NULL)
-                dh_srvr = scert->peer_dh_tmp;
+            if (s->s3->peer_dh_tmp != NULL)
+                dh_srvr = s->s3->peer_dh_tmp;
             else {
                 /* we get them from the cert */
-                int idx = scert->peer_cert_type;
                 EVP_PKEY *spkey = NULL;
                 dh_srvr = NULL;
-                if (idx >= 0)
-                    spkey = X509_get_pubkey(scert->peer_pkeys[idx].x509);
+                spkey = X509_get_pubkey(s->session->peer);
                 if (spkey) {
                     dh_srvr = EVP_PKEY_get1_DH(spkey);
                     EVP_PKEY_free(spkey);
@@ -2551,7 +2492,7 @@ int ssl3_send_client_key_exchange(SSL *s)
              */
 
             n = DH_compute_key(pms, dh_srvr->pub_key, dh_clnt);
-            if (scert->peer_dh_tmp == NULL)
+            if (s->s3->peer_dh_tmp == NULL)
                 DH_free(dh_srvr);
 
             if (n <= 0) {
@@ -2572,8 +2513,6 @@ int ssl3_send_client_key_exchange(SSL *s)
             }
 
             DH_free(dh_clnt);
-
-            /* perhaps clean things up a bit EAY EAY EAY EAY */
         }
 #endif
 
@@ -2583,14 +2522,6 @@ int ssl3_send_client_key_exchange(SSL *s)
             EC_KEY *tkey;
             int ecdh_clnt_cert = 0;
             int field_size = 0;
-
-            if (s->session->sess_cert == NULL) {
-                ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
-                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
-                       SSL_R_UNEXPECTED_MESSAGE);
-                goto err;
-            }
-
             /*
              * Did we send out the client's ECDH share for use in premaster
              * computation as part of client certificate? If so, set
@@ -2619,13 +2550,11 @@ int ssl3_send_client_key_exchange(SSL *s)
                  */
             }
 
-            if (s->session->sess_cert->peer_ecdh_tmp != NULL) {
-                tkey = s->session->sess_cert->peer_ecdh_tmp;
+            if (s->s3->peer_ecdh_tmp != NULL) {
+                tkey = s->s3->peer_ecdh_tmp;
             } else {
                 /* Get the Server Public Key from Cert */
-                srvr_pub_pkey =
-                    X509_get_pubkey(s->session->
-                                    sess_cert->peer_pkeys[SSL_PKEY_ECC].x509);
+                srvr_pub_pkey = X509_get_pubkey(s->session->peer);
                 if ((srvr_pub_pkey == NULL)
                     || (srvr_pub_pkey->type != EVP_PKEY_EC)
                     || (srvr_pub_pkey->pkey.ec == NULL)) {
@@ -2753,7 +2682,6 @@ int ssl3_send_client_key_exchange(SSL *s)
             X509 *peer_cert;
             size_t msglen;
             unsigned int md_len;
-            int keytype;
             unsigned char shared_ukm[32], tmp[256];
             EVP_MD_CTX *ukm_hash;
             EVP_PKEY *pub_key;
@@ -2766,13 +2694,7 @@ int ssl3_send_client_key_exchange(SSL *s)
             /*
              * Get server sertificate PKEY and create ctx from it
              */
-            peer_cert =
-                s->session->
-                sess_cert->peer_pkeys[(keytype = SSL_PKEY_GOST01)].x509;
-            if (!peer_cert)
-                peer_cert =
-                    s->session->
-                    sess_cert->peer_pkeys[(keytype = SSL_PKEY_GOST94)].x509;
+            peer_cert = s->session->peer;
             if (!peer_cert) {
                 SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
                        SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER);
@@ -3213,15 +3135,14 @@ static int ssl3_check_client_certificate(SSL *s)
     alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
     /* See if we can use client certificate for fixed DH */
     if (alg_k & (SSL_kDHr | SSL_kDHd)) {
-        SESS_CERT *scert = s->session->sess_cert;
-        int i = scert->peer_cert_type;
+        int i = s->session->peer_type;
         EVP_PKEY *clkey = NULL, *spkey = NULL;
         clkey = s->cert->key->privatekey;
         /* If client key not DH assume it can be used */
         if (EVP_PKEY_id(clkey) != EVP_PKEY_DH)
             return 1;
         if (i >= 0)
-            spkey = X509_get_pubkey(scert->peer_pkeys[i].x509);
+            spkey = X509_get_pubkey(s->session->peer);
         if (spkey) {
             /* Compare server and client parameters */
             i = EVP_PKEY_cmp_parameters(clkey, spkey);
@@ -3330,13 +3251,13 @@ int ssl3_check_cert_and_algorithm(SSL *s)
     long alg_k, alg_a;
     EVP_PKEY *pkey = NULL;
     int pkey_bits;
-    SESS_CERT *sc;
 #ifndef OPENSSL_NO_RSA
     RSA *rsa;
 #endif
 #ifndef OPENSSL_NO_DH
     DH *dh;
 #endif
+    int al = SSL_AD_HANDSHAKE_FAILURE;
 
     alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
     alg_a = s->s3->tmp.new_cipher->algorithm_auth;
@@ -3344,25 +3265,19 @@ int ssl3_check_cert_and_algorithm(SSL *s)
     /* we don't have a certificate */
     if ((alg_a & SSL_aNULL) || (alg_k & SSL_kPSK))
         return (1);
-
-    sc = s->session->sess_cert;
-    if (sc == NULL) {
-        SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, ERR_R_INTERNAL_ERROR);
-        goto err;
-    }
 #ifndef OPENSSL_NO_RSA
-    rsa = s->session->sess_cert->peer_rsa_tmp;
+    rsa = s->s3->peer_rsa_tmp;
 #endif
 #ifndef OPENSSL_NO_DH
-    dh = s->session->sess_cert->peer_dh_tmp;
+    dh = s->s3->peer_dh_tmp;
 #endif
 
     /* This is the passed certificate */
 
-    idx = sc->peer_cert_type;
+    idx = s->session->peer_type;
 #ifndef OPENSSL_NO_EC
     if (idx == SSL_PKEY_ECC) {
-        if (ssl_check_srvr_ecc_cert_and_alg(sc->peer_pkeys[idx].x509, s) == 0) {
+        if (ssl_check_srvr_ecc_cert_and_alg(s->session->peer, s) == 0) {
             /* check failed */
             SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, SSL_R_BAD_ECC_CERT);
             goto f_err;
@@ -3378,9 +3293,9 @@ int ssl3_check_cert_and_algorithm(SSL *s)
         goto f_err;
     }
 #endif
-    pkey = X509_get_pubkey(sc->peer_pkeys[idx].x509);
+    pkey = X509_get_pubkey(s->session->peer);
     pkey_bits = EVP_PKEY_bits(pkey);
-    i = X509_certificate_type(sc->peer_pkeys[idx].x509, pkey);
+    i = X509_certificate_type(s->session->peer, pkey);
     EVP_PKEY_free(pkey);
 
     /* Check that we have a certificate if we require one */
@@ -3397,17 +3312,33 @@ int ssl3_check_cert_and_algorithm(SSL *s)
     }
 #endif
 #ifndef OPENSSL_NO_RSA
-    if ((alg_k & SSL_kRSA) &&
-        !(has_bits(i, EVP_PK_RSA | EVP_PKT_ENC) || (rsa != NULL))) {
-        SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
-               SSL_R_MISSING_RSA_ENCRYPTING_CERT);
-        goto f_err;
+    if (alg_k & SSL_kRSA) {
+        if (!SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) &&
+            !has_bits(i, EVP_PK_RSA | EVP_PKT_ENC)) {
+            SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
+                   SSL_R_MISSING_RSA_ENCRYPTING_CERT);
+            goto f_err;
+        } else if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher)) {
+            if (pkey_bits <= SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) {
+                if (!has_bits(i, EVP_PK_RSA | EVP_PKT_ENC)) {
+                    SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
+                           SSL_R_MISSING_RSA_ENCRYPTING_CERT);
+                    goto f_err;
+                }
+                if (rsa != NULL) {
+                    /* server key exchange is not allowed. */
+                    al = SSL_AD_INTERNAL_ERROR;
+                    SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, ERR_R_INTERNAL_ERROR);
+                    goto f_err;
+                }
+            }
+        }
     }
 #endif
 #ifndef OPENSSL_NO_DH
-    if ((alg_k & SSL_kDHE) &&
-        !(has_bits(i, EVP_PK_DH | EVP_PKT_EXCH) || (dh != NULL))) {
-        SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, SSL_R_MISSING_DH_KEY);
+    if ((alg_k & SSL_kDHE) && (dh == NULL)) {
+        al = SSL_AD_INTERNAL_ERROR;
+        SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, ERR_R_INTERNAL_ERROR);
         goto f_err;
     } else if ((alg_k & SSL_kDHr) && !SSL_USE_SIGALGS(s) &&
                !has_bits(i, EVP_PK_DH | EVP_PKS_RSA)) {
@@ -3429,9 +3360,14 @@ int ssl3_check_cert_and_algorithm(SSL *s)
         pkey_bits > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) {
 #ifndef OPENSSL_NO_RSA
         if (alg_k & SSL_kRSA) {
-            if (rsa == NULL
-                || RSA_size(rsa) * 8 >
+            if (rsa == NULL) {
+                SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
+                       SSL_R_MISSING_EXPORT_TMP_RSA_KEY);
+                goto f_err;
+            } else if (RSA_bits(rsa) >
                 SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) {
+                /* We have a temporary RSA key but it's too large. */
+                al = SSL_AD_EXPORT_RESTRICTION;
                 SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
                        SSL_R_MISSING_EXPORT_TMP_RSA_KEY);
                 goto f_err;
@@ -3439,14 +3375,21 @@ int ssl3_check_cert_and_algorithm(SSL *s)
         } else
 #endif
 #ifndef OPENSSL_NO_DH
-        if (alg_k & (SSL_kDHE | SSL_kDHr | SSL_kDHd)) {
-            if (dh == NULL
-                || DH_size(dh) * 8 >
+        if (alg_k & SSL_kDHE) {
+            if (DH_bits(dh) >
                 SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) {
+                /* We have a temporary DH key but it's too large. */
+                al = SSL_AD_EXPORT_RESTRICTION;
                 SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
                        SSL_R_MISSING_EXPORT_TMP_DH_KEY);
                 goto f_err;
             }
+        } else if (alg_k & (SSL_kDHr | SSL_kDHd)) {
+            /* The cert should have had an export DH key. */
+            al = SSL_AD_EXPORT_RESTRICTION;
+            SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
+                   SSL_R_MISSING_EXPORT_TMP_DH_KEY);
+                goto f_err;
         } else
 #endif
         {
@@ -3457,8 +3400,7 @@ int ssl3_check_cert_and_algorithm(SSL *s)
     }
     return (1);
  f_err:
-    ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
- err:
+    ssl3_send_alert(s, SSL3_AL_FATAL, al);
     return (0);
 }