Renamed record layer header files
[openssl.git] / ssl / s3_clnt.c
index 2713129f15b8c1a32655d6d4e5b80d88e837058e..6da125897d35d97db970cf486b188c2fa6e209f6 100644 (file)
@@ -197,8 +197,10 @@ int ssl3_connect(SSL *s)
         cb = s->ctx->info_callback;
 
     s->in_handshake++;
-    if (!SSL_in_init(s) || SSL_in_before(s))
-        SSL_clear(s);
+    if (!SSL_in_init(s) || SSL_in_before(s)) {
+        if(!SSL_clear(s))
+            return -1;
+    }
 
 #ifndef OPENSSL_NO_HEARTBEATS
     /*
@@ -719,50 +721,45 @@ int ssl3_client_hello(SSL *s)
         } else
             i = 1;
 
-        if (i)
-            ssl_fill_hello_random(s, 0, p, sizeof(s->s3->client_random));
+        if (i && ssl_fill_hello_random(s, 0, p,
+                                       sizeof(s->s3->client_random)) <= 0)
+            goto err;
 
         /* Do the message type and length last */
         d = p = ssl_handshake_start(s);
 
-                /*-
-                 * version indicates the negotiated version: for example from
-                 * an SSLv2/v3 compatible client hello). The client_version
-                 * field is the maximum version we permit and it is also
-                 * used in RSA encrypted premaster secrets. Some servers can
-                 * choke if we initially report a higher version then
-                 * renegotiate to a lower one in the premaster secret. This
-                 * didn't happen with TLS 1.0 as most servers supported it
-                 * but it can with TLS 1.1 or later if the server only supports
-                 * 1.0.
-                 *
-                 * Possible scenario with previous logic:
-                 *      1. Client hello indicates TLS 1.2
-                 *      2. Server hello says TLS 1.0
-                 *      3. RSA encrypted premaster secret uses 1.2.
-                 *      4. Handhaked proceeds using TLS 1.0.
-                 *      5. Server sends hello request to renegotiate.
-                 *      6. Client hello indicates TLS v1.0 as we now
-                 *         know that is maximum server supports.
-                 *      7. Server chokes on RSA encrypted premaster secret
-                 *         containing version 1.0.
-                 *
-                 * For interoperability it should be OK to always use the
-                 * maximum version we support in client hello and then rely
-                 * on the checking of version to ensure the servers isn't
-                 * being inconsistent: for example initially negotiating with
-                 * TLS 1.0 and renegotiating with TLS 1.2. We do this by using
-                 * client_version in client hello and not resetting it to
-                 * the negotiated version.
-                 */
-#if 0
-        *(p++) = s->version >> 8;
-        *(p++) = s->version & 0xff;
-        s->client_version = s->version;
-#else
+        /*-
+         * version indicates the negotiated version: for example from
+         * an SSLv2/v3 compatible client hello). The client_version
+         * field is the maximum version we permit and it is also
+         * used in RSA encrypted premaster secrets. Some servers can
+         * choke if we initially report a higher version then
+         * renegotiate to a lower one in the premaster secret. This
+         * didn't happen with TLS 1.0 as most servers supported it
+         * but it can with TLS 1.1 or later if the server only supports
+         * 1.0.
+         *
+         * Possible scenario with previous logic:
+         *      1. Client hello indicates TLS 1.2
+         *      2. Server hello says TLS 1.0
+         *      3. RSA encrypted premaster secret uses 1.2.
+         *      4. Handhaked proceeds using TLS 1.0.
+         *      5. Server sends hello request to renegotiate.
+         *      6. Client hello indicates TLS v1.0 as we now
+         *         know that is maximum server supports.
+         *      7. Server chokes on RSA encrypted premaster secret
+         *         containing version 1.0.
+         *
+         * For interoperability it should be OK to always use the
+         * maximum version we support in client hello and then rely
+         * on the checking of version to ensure the servers isn't
+         * being inconsistent: for example initially negotiating with
+         * TLS 1.0 and renegotiating with TLS 1.2. We do this by using
+         * client_version in client hello and not resetting it to
+         * the negotiated version.
+         */
         *(p++) = s->client_version >> 8;
         *(p++) = s->client_version & 0xff;
-#endif
 
         /* Random stuff */
         memcpy(p, s->s3->client_random, SSL3_RANDOM_SIZE);
@@ -846,7 +843,11 @@ int ssl3_client_hello(SSL *s)
 #endif
 
         l = p - d;
-        ssl_set_handshake_header(s, SSL3_MT_CLIENT_HELLO, l);
+        if(!ssl_set_handshake_header(s, SSL3_MT_CLIENT_HELLO, l)) {
+            ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+            SSLerr(SSL_F_SSL3_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
+            goto err;
+        }
         s->state = SSL3_ST_CW_CLNT_HELLO_B;
     }
 
@@ -1036,16 +1037,10 @@ int ssl3_get_server_hello(SSL *s)
     if (s->session->cipher)
         s->session->cipher_id = s->session->cipher->id;
     if (s->hit && (s->session->cipher_id != c->id)) {
-/* Workaround is now obsolete */
-#if 0
-        if (!(s->options & SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG))
-#endif
-        {
-            al = SSL_AD_ILLEGAL_PARAMETER;
-            SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,
-                   SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED);
-            goto f_err;
-        }
+        al = SSL_AD_ILLEGAL_PARAMETER;
+        SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,
+               SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED);
+        goto f_err;
     }
     s->s3->tmp.new_cipher = c;
     /*
@@ -1332,7 +1327,7 @@ int ssl3_get_key_exchange(SSL *s)
 #ifndef OPENSSL_NO_DH
     DH *dh = NULL;
 #endif
-#ifndef OPENSSL_NO_ECDH
+#ifndef OPENSSL_NO_EC
     EC_KEY *ecdh = NULL;
     BN_CTX *bn_ctx = NULL;
     EC_POINT *srvr_ecpoint = NULL;
@@ -1385,22 +1380,16 @@ int ssl3_get_key_exchange(SSL *s)
     param = p = (unsigned char *)s->init_msg;
     if (s->session->sess_cert != NULL) {
 #ifndef OPENSSL_NO_RSA
-        if (s->session->sess_cert->peer_rsa_tmp != NULL) {
-            RSA_free(s->session->sess_cert->peer_rsa_tmp);
-            s->session->sess_cert->peer_rsa_tmp = NULL;
-        }
+        RSA_free(s->session->sess_cert->peer_rsa_tmp);
+        s->session->sess_cert->peer_rsa_tmp = NULL;
 #endif
 #ifndef OPENSSL_NO_DH
-        if (s->session->sess_cert->peer_dh_tmp) {
-            DH_free(s->session->sess_cert->peer_dh_tmp);
-            s->session->sess_cert->peer_dh_tmp = NULL;
-        }
+        DH_free(s->session->sess_cert->peer_dh_tmp);
+        s->session->sess_cert->peer_dh_tmp = NULL;
 #endif
-#ifndef OPENSSL_NO_ECDH
-        if (s->session->sess_cert->peer_ecdh_tmp) {
-            EC_KEY_free(s->session->sess_cert->peer_ecdh_tmp);
-            s->session->sess_cert->peer_ecdh_tmp = NULL;
-        }
+#ifndef OPENSSL_NO_EC
+        EC_KEY_free(s->session->sess_cert->peer_ecdh_tmp);
+        s->session->sess_cert->peer_ecdh_tmp = NULL;
 #endif
     } else {
         s->session->sess_cert = ssl_sess_cert_new();
@@ -1727,15 +1716,10 @@ int ssl3_get_key_exchange(SSL *s)
 
         s->session->sess_cert->peer_dh_tmp = dh;
         dh = NULL;
-    } else if ((alg_k & SSL_kDHr) || (alg_k & SSL_kDHd)) {
-        al = SSL_AD_ILLEGAL_PARAMETER;
-        SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
-               SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER);
-        goto f_err;
     }
 #endif                          /* !OPENSSL_NO_DH */
 
-#ifndef OPENSSL_NO_ECDH
+#ifndef OPENSSL_NO_EC
     else if (alg_k & SSL_kECDHE) {
         EC_GROUP *ngroup;
         const EC_GROUP *group;
@@ -1833,7 +1817,7 @@ int ssl3_get_key_exchange(SSL *s)
                 X509_get_pubkey(s->session->
                                 sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
 # endif
-# ifndef OPENSSL_NO_ECDSA
+# ifndef OPENSSL_NO_EC
         else if (alg_a & SSL_aECDSA)
             pkey =
                 X509_get_pubkey(s->session->
@@ -1852,7 +1836,7 @@ int ssl3_get_key_exchange(SSL *s)
         SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_UNEXPECTED_MESSAGE);
         goto f_err;
     }
-#endif                          /* !OPENSSL_NO_ECDH */
+#endif                          /* !OPENSSL_NO_EC */
 
     /* p points to the next byte, there are 'n' bytes left */
 
@@ -1965,18 +1949,15 @@ int ssl3_get_key_exchange(SSL *s)
  err:
     EVP_PKEY_free(pkey);
 #ifndef OPENSSL_NO_RSA
-    if (rsa != NULL)
-        RSA_free(rsa);
+    RSA_free(rsa);
 #endif
 #ifndef OPENSSL_NO_DH
-    if (dh != NULL)
-        DH_free(dh);
+    DH_free(dh);
 #endif
-#ifndef OPENSSL_NO_ECDH
+#ifndef OPENSSL_NO_EC
     BN_CTX_free(bn_ctx);
     EC_POINT_free(srvr_ecpoint);
-    if (ecdh != NULL)
-        EC_KEY_free(ecdh);
+    EC_KEY_free(ecdh);
 #endif
     EVP_MD_CTX_cleanup(&md_ctx);
     return (-1);
@@ -2091,14 +2072,6 @@ int ssl3_get_certificate_request(SSL *s)
 
     /* get the CA RDNs */
     n2s(p, llen);
-#if 0
-    {
-        FILE *out;
-        out = fopen("/tmp/vsign.der", "w");
-        fwrite(p, 1, llen, out);
-        fclose(out);
-    }
-#endif
 
     if ((unsigned long)(p - d + llen) != n) {
         ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
@@ -2109,8 +2082,6 @@ int ssl3_get_certificate_request(SSL *s)
     for (nc = 0; nc < llen;) {
         n2s(p, l);
         if ((l + nc + 2) > llen) {
-            if ((s->options & SSL_OP_NETSCAPE_CA_DN_BUG))
-                goto cont;      /* netscape bugs */
             ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
             SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST, SSL_R_CA_DN_TOO_LONG);
             goto err;
@@ -2119,14 +2090,9 @@ int ssl3_get_certificate_request(SSL *s)
         q = p;
 
         if ((xn = d2i_X509_NAME(NULL, &q, l)) == NULL) {
-            /* If netscape tolerance is on, ignore errors */
-            if (s->options & SSL_OP_NETSCAPE_CA_DN_BUG)
-                goto cont;
-            else {
-                ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
-                SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST, ERR_R_ASN1_LIB);
-                goto err;
-            }
+            ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+            SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST, ERR_R_ASN1_LIB);
+            goto err;
         }
 
         if (q != (p + l)) {
@@ -2144,11 +2110,6 @@ int ssl3_get_certificate_request(SSL *s)
         nc += l + 2;
     }
 
-    if (0) {
- cont:
-        ERR_clear_error();
-    }
-
     /* we should setup a certificate to return.... */
     s->s3->tmp.cert_req = 1;
     s->s3->tmp.ctype_num = ctype_num;
@@ -2225,11 +2186,7 @@ int ssl3_get_new_session_ticket(SSL *s)
      */
     EVP_Digest(p, ticklen,
                s->session->session_id, &s->session->session_id_length,
-# ifndef OPENSSL_NO_SHA256
                EVP_sha256(), NULL);
-# else
-               EVP_sha1(), NULL);
-# endif
     ret = 1;
     return (ret);
  f_err:
@@ -2334,7 +2291,7 @@ int ssl3_send_client_key_exchange(SSL *s)
 #ifndef OPENSSL_NO_KRB5
     KSSL_ERR kssl_err;
 #endif                          /* OPENSSL_NO_KRB5 */
-#ifndef OPENSSL_NO_ECDH
+#ifndef OPENSSL_NO_EC
     EC_KEY *clnt_ecdh = NULL;
     const EC_POINT *srvr_ecpoint = NULL;
     EVP_PKEY *srvr_pub_pkey = NULL;
@@ -2342,6 +2299,8 @@ int ssl3_send_client_key_exchange(SSL *s)
     int encoded_pt_len = 0;
     BN_CTX *bn_ctx = NULL;
 #endif
+    unsigned char *pms = NULL;
+    size_t pmslen = 0;
 
     if (s->state == SSL3_ST_CW_KEY_EXCH_A) {
         p = ssl_handshake_start(s);
@@ -2354,7 +2313,10 @@ int ssl3_send_client_key_exchange(SSL *s)
 #ifndef OPENSSL_NO_RSA
         else if (alg_k & SSL_kRSA) {
             RSA *rsa;
-            unsigned char tmp_buf[SSL_MAX_MASTER_KEY_LENGTH];
+            pmslen = SSL_MAX_MASTER_KEY_LENGTH;
+            pms = OPENSSL_malloc(pmslen);
+            if (!pms)
+                goto memerr;
 
             if (s->session->sess_cert == NULL) {
                 /*
@@ -2382,19 +2344,16 @@ int ssl3_send_client_key_exchange(SSL *s)
                 EVP_PKEY_free(pkey);
             }
 
-            tmp_buf[0] = s->client_version >> 8;
-            tmp_buf[1] = s->client_version & 0xff;
-            if (RAND_bytes(&(tmp_buf[2]), sizeof tmp_buf - 2) <= 0)
+            pms[0] = s->client_version >> 8;
+            pms[1] = s->client_version & 0xff;
+            if (RAND_bytes(pms + 2, pmslen - 2) <= 0)
                 goto err;
 
-            s->session->master_key_length = sizeof tmp_buf;
-
             q = p;
             /* Fix buf for TLS and beyond */
             if (s->version > SSL3_VERSION)
                 p += 2;
-            n = RSA_public_encrypt(sizeof tmp_buf,
-                                   tmp_buf, p, rsa, RSA_PKCS1_PADDING);
+            n = RSA_public_encrypt(pmslen, pms, p, rsa, RSA_PKCS1_PADDING);
 # ifdef PKCS1_CHECK
             if (s->options & SSL_OP_PKCS1_CHECK_1)
                 p[1]++;
@@ -2412,14 +2371,6 @@ int ssl3_send_client_key_exchange(SSL *s)
                 s2n(n, q);
                 n += 2;
             }
-
-            s->session->master_key_length =
-                s->method->ssl3_enc->generate_master_secret(s,
-                                                            s->
-                                                            session->master_key,
-                                                            tmp_buf,
-                                                            sizeof tmp_buf);
-            OPENSSL_cleanse(tmp_buf, sizeof tmp_buf);
         }
 #endif
 #ifndef OPENSSL_NO_KRB5
@@ -2468,25 +2419,25 @@ int ssl3_send_client_key_exchange(SSL *s)
                 goto err;
             }
 
-                        /*-
-                         * 20010406 VRS - Earlier versions used KRB5 AP_REQ
-                         * in place of RFC 2712 KerberosWrapper, as in:
-                         *
-                         * Send ticket (copy to *p, set n = length)
-                         * n = krb5_ap_req.length;
-                         * memcpy(p, krb5_ap_req.data, krb5_ap_req.length);
-                         * if (krb5_ap_req.data)
-                         *   kssl_krb5_free_data_contents(NULL,&krb5_ap_req);
-                         *
-                         * Now using real RFC 2712 KerberosWrapper
-                         * (Thanks to Simon Wilkinson <sxw@sxw.org.uk>)
-                         * Note: 2712 "opaque" types are here replaced
-                         * with a 2-byte length followed by the value.
-                         * Example:
-                         * KerberosWrapper= xx xx asn1ticket 0 0 xx xx encpms
-                         * Where "xx xx" = length bytes.  Shown here with
-                         * optional authenticator omitted.
-                         */
+            /*-
+             * 20010406 VRS - Earlier versions used KRB5 AP_REQ
+             * in place of RFC 2712 KerberosWrapper, as in:
+             *
+             * Send ticket (copy to *p, set n = length)
+             * n = krb5_ap_req.length;
+             * memcpy(p, krb5_ap_req.data, krb5_ap_req.length);
+             * if (krb5_ap_req.data)
+             *   kssl_krb5_free_data_contents(NULL,&krb5_ap_req);
+             *
+             * Now using real RFC 2712 KerberosWrapper
+             * (Thanks to Simon Wilkinson <sxw@sxw.org.uk>)
+             * Note: 2712 "opaque" types are here replaced
+             * with a 2-byte length followed by the value.
+             * Example:
+             * KerberosWrapper= xx xx asn1ticket 0 0 xx xx encpms
+             * Where "xx xx" = length bytes.  Shown here with
+             * optional authenticator omitted.
+             */
 
             /*  KerberosWrapper.Ticket              */
             s2n(enc_ticket->length, p);
@@ -2509,23 +2460,27 @@ int ssl3_send_client_key_exchange(SSL *s)
                 n += 2;
             }
 
-            tmp_buf[0] = s->client_version >> 8;
-            tmp_buf[1] = s->client_version & 0xff;
-            if (RAND_bytes(&(tmp_buf[2]), sizeof tmp_buf - 2) <= 0)
+            pmslen = SSL_MAX_MASTER_KEY_LENGTH;
+            pms = OPENSSL_malloc(pmslen);
+            if (!pms)
+                goto memerr;
+
+            pms[0] = s->client_version >> 8;
+            pms[1] = s->client_version & 0xff;
+            if (RAND_bytes(pms + 2, pmslen - 2) <= 0)
                 goto err;
 
-                        /*-
-                         * 20010420 VRS.  Tried it this way; failed.
-                         *      EVP_EncryptInit_ex(&ciph_ctx,enc, NULL,NULL);
-                         *      EVP_CIPHER_CTX_set_key_length(&ciph_ctx,
-                         *                              kssl_ctx->length);
-                         *      EVP_EncryptInit_ex(&ciph_ctx,NULL, key,iv);
-                         */
+            /*-
+             * 20010420 VRS.  Tried it this way; failed.
+             *      EVP_EncryptInit_ex(&ciph_ctx,enc, NULL,NULL);
+             *      EVP_CIPHER_CTX_set_key_length(&ciph_ctx,
+             *                              kssl_ctx->length);
+             *      EVP_EncryptInit_ex(&ciph_ctx,NULL, key,iv);
+             */
 
             memset(iv, 0, sizeof iv); /* per RFC 1510 */
             EVP_EncryptInit_ex(&ciph_ctx, enc, NULL, kssl_ctx->key, iv);
-            EVP_EncryptUpdate(&ciph_ctx, epms, &outl, tmp_buf,
-                              sizeof tmp_buf);
+            EVP_EncryptUpdate(&ciph_ctx, epms, &outl, pms, pmslen);
             EVP_EncryptFinal_ex(&ciph_ctx, &(epms[outl]), &padl);
             outl += padl;
             if (outl > (int)sizeof epms) {
@@ -2540,15 +2495,6 @@ int ssl3_send_client_key_exchange(SSL *s)
             memcpy(p, epms, outl);
             p += outl;
             n += outl + 2;
-
-            s->session->master_key_length =
-                s->method->ssl3_enc->generate_master_secret(s,
-                                                            s->
-                                                            session->master_key,
-                                                            tmp_buf,
-                                                            sizeof tmp_buf);
-
-            OPENSSL_cleanse(tmp_buf, sizeof tmp_buf);
             OPENSSL_cleanse(epms, outl);
         }
 #endif
@@ -2607,12 +2553,17 @@ int ssl3_send_client_key_exchange(SSL *s)
                 }
             }
 
+            pmslen = DH_size(dh_clnt);
+            pms = OPENSSL_malloc(pmslen);
+            if (!pms)
+                goto memerr;
+
             /*
              * use the 'p' output buffer for the DH key, but make sure to
              * clear it out afterwards
              */
 
-            n = DH_compute_key(p, dh_srvr->pub_key, dh_clnt);
+            n = DH_compute_key(pms, dh_srvr->pub_key, dh_clnt);
             if (scert->peer_dh_tmp == NULL)
                 DH_free(dh_srvr);
 
@@ -2621,15 +2572,7 @@ int ssl3_send_client_key_exchange(SSL *s)
                 DH_free(dh_clnt);
                 goto err;
             }
-
-            /* generate master key from the result */
-            s->session->master_key_length =
-                s->method->ssl3_enc->generate_master_secret(s,
-                                                            s->
-                                                            session->master_key,
-                                                            p, n);
-            /* clean up */
-            memset(p, 0, n);
+            pmslen = n;
 
             if (s->s3->flags & TLS1_FLAGS_SKIP_CERT_VERIFY)
                 n = 0;
@@ -2647,7 +2590,7 @@ int ssl3_send_client_key_exchange(SSL *s)
         }
 #endif
 
-#ifndef OPENSSL_NO_ECDH
+#ifndef OPENSSL_NO_EC
         else if (alg_k & (SSL_kECDHE | SSL_kECDHr | SSL_kECDHe)) {
             const EC_GROUP *srvr_group = NULL;
             EC_KEY *tkey;
@@ -2667,26 +2610,26 @@ int ssl3_send_client_key_exchange(SSL *s)
              * ecdh_clnt_cert to 1.
              */
             if ((alg_k & (SSL_kECDHr | SSL_kECDHe)) && (s->cert != NULL)) {
-                                /*-
-                                 * XXX: For now, we do not support client
-                                 * authentication using ECDH certificates.
-                                 * To add such support, one needs to add
-                                 * code that checks for appropriate
-                                 * conditions and sets ecdh_clnt_cert to 1.
-                                 * For example, the cert have an ECC
-                                 * key on the same curve as the server's
-                                 * and the key should be authorized for
-                                 * key agreement.
-                                 *
-                                 * One also needs to add code in ssl3_connect
-                                 * to skip sending the certificate verify
-                                 * message.
-                                 *
-                                 * if ((s->cert->key->privatekey != NULL) &&
-                                 *     (s->cert->key->privatekey->type ==
-                                 *      EVP_PKEY_EC) && ...)
-                                 * ecdh_clnt_cert = 1;
-                                 */
+                /*-
+                 * XXX: For now, we do not support client
+                 * authentication using ECDH certificates.
+                 * To add such support, one needs to add
+                 * code that checks for appropriate
+                 * conditions and sets ecdh_clnt_cert to 1.
+                 * For example, the cert have an ECC
+                 * key on the same curve as the server's
+                 * and the key should be authorized for
+                 * key agreement.
+                 *
+                 * One also needs to add code in ssl3_connect
+                 * to skip sending the certificate verify
+                 * message.
+                 *
+                 * if ((s->cert->key->privatekey != NULL) &&
+                 *     (s->cert->key->privatekey->type ==
+                 *      EVP_PKEY_EC) && ...)
+                 * ecdh_clnt_cert = 1;
+                 */
             }
 
             if (s->session->sess_cert->peer_ecdh_tmp != NULL) {
@@ -2762,22 +2705,16 @@ int ssl3_send_client_key_exchange(SSL *s)
                 SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_ECDH_LIB);
                 goto err;
             }
-            n = ECDH_compute_key(p, (field_size + 7) / 8, srvr_ecpoint,
-                                 clnt_ecdh, NULL);
-            if (n <= 0) {
+            pmslen = (field_size + 7) / 8;
+            pms = OPENSSL_malloc(pmslen);
+            if (!pms)
+                goto memerr;
+            n = ECDH_compute_key(pms, pmslen, srvr_ecpoint, clnt_ecdh, NULL);
+            if (n <= 0 || pmslen != (size_t)n) {
                 SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_ECDH_LIB);
                 goto err;
             }
 
-            /* generate master key from the result */
-            s->session->master_key_length =
-                s->method->ssl3_enc->generate_master_secret(s,
-                                                            s->
-                                                            session->master_key,
-                                                            p, n);
-
-            memset(p, 0, n);    /* clean up */
-
             if (ecdh_clnt_cert) {
                 /* Send empty client key exch message */
                 n = 0;
@@ -2820,11 +2757,10 @@ int ssl3_send_client_key_exchange(SSL *s)
             BN_CTX_free(bn_ctx);
             if (encodedPoint != NULL)
                 OPENSSL_free(encodedPoint);
-            if (clnt_ecdh != NULL)
-                EC_KEY_free(clnt_ecdh);
+            EC_KEY_free(clnt_ecdh);
             EVP_PKEY_free(srvr_pub_pkey);
         }
-#endif                          /* !OPENSSL_NO_ECDH */
+#endif                          /* !OPENSSL_NO_EC */
         else if (alg_k & SSL_kGOST) {
             /* GOST key exchange message creation */
             EVP_PKEY_CTX *pkey_ctx;
@@ -2832,10 +2768,15 @@ int ssl3_send_client_key_exchange(SSL *s)
             size_t msglen;
             unsigned int md_len;
             int keytype;
-            unsigned char premaster_secret[32], shared_ukm[32], tmp[256];
+            unsigned char shared_ukm[32], tmp[256];
             EVP_MD_CTX *ukm_hash;
             EVP_PKEY *pub_key;
 
+            pmslen = 32;
+            pms = OPENSSL_malloc(pmslen);
+            if (!pms)
+                goto memerr;
+
             /*
              * Get server sertificate PKEY and create ctx from it
              */
@@ -2865,7 +2806,12 @@ int ssl3_send_client_key_exchange(SSL *s)
 
             EVP_PKEY_encrypt_init(pkey_ctx);
             /* Generate session key */
-            RAND_bytes(premaster_secret, 32);
+            if (RAND_bytes(pms, pmslen) <= 0) {
+                EVP_PKEY_CTX_free(pkey_ctx);
+                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+                       ERR_R_INTERNAL_ERROR);
+                goto err;
+            };
             /*
              * If we have client certificate, use its secret as peer key
              */
@@ -2905,8 +2851,7 @@ int ssl3_send_client_key_exchange(SSL *s)
              */
             *(p++) = V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED;
             msglen = 255;
-            if (EVP_PKEY_encrypt(pkey_ctx, tmp, &msglen, premaster_secret, 32)
-                < 0) {
+            if (EVP_PKEY_encrypt(pkey_ctx, tmp, &msglen, pms, pmslen) < 0) {
                 SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
                        SSL_R_LIBRARY_BUG);
                 goto err;
@@ -2927,12 +2872,6 @@ int ssl3_send_client_key_exchange(SSL *s)
                 s->s3->flags |= TLS1_FLAGS_SKIP_CERT_VERIFY;
             }
             EVP_PKEY_CTX_free(pkey_ctx);
-            s->session->master_key_length =
-                s->method->ssl3_enc->generate_master_secret(s,
-                                                            s->
-                                                            session->master_key,
-                                                            premaster_secret,
-                                                            32);
             EVP_PKEY_free(pub_key);
 
         }
@@ -2957,15 +2896,6 @@ int ssl3_send_client_key_exchange(SSL *s)
                        ERR_R_MALLOC_FAILURE);
                 goto err;
             }
-
-            if ((s->session->master_key_length =
-                 SRP_generate_client_master_secret(s,
-                                                   s->session->master_key)) <
-                0) {
-                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
-                       ERR_R_INTERNAL_ERROR);
-                goto err;
-            }
         }
 #endif
 #ifndef OPENSSL_NO_PSK
@@ -2978,8 +2908,7 @@ int ssl3_send_client_key_exchange(SSL *s)
             char identity[PSK_MAX_IDENTITY_LEN + 2];
             size_t identity_len;
             unsigned char *t = NULL;
-            unsigned char psk_or_pre_ms[PSK_MAX_PSK_LEN * 2 + 4];
-            unsigned int pre_ms_len = 0, psk_len = 0;
+            unsigned int psk_len = 0;
             int psk_err = 1;
 
             n = 0;
@@ -2990,10 +2919,15 @@ int ssl3_send_client_key_exchange(SSL *s)
             }
 
             memset(identity, 0, sizeof(identity));
+            /* Allocate maximum size buffer */
+            pmslen = PSK_MAX_PSK_LEN * 2 + 4;
+            pms = OPENSSL_malloc(pmslen);
+            if (!pms)
+                goto memerr;
+
             psk_len = s->psk_client_callback(s, s->ctx->psk_identity_hint,
                                              identity, sizeof(identity) - 1,
-                                             psk_or_pre_ms,
-                                             sizeof(psk_or_pre_ms));
+                                             pms, pmslen);
             if (psk_len > PSK_MAX_PSK_LEN) {
                 SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
                        ERR_R_INTERNAL_ERROR);
@@ -3003,6 +2937,8 @@ int ssl3_send_client_key_exchange(SSL *s)
                        SSL_R_PSK_IDENTITY_NOT_FOUND);
                 goto psk_err;
             }
+            /* Change pmslen to real length */
+            pmslen = 2 + psk_len + 2 + psk_len;
             identity[PSK_MAX_IDENTITY_LEN + 1] = '\0';
             identity_len = strlen(identity);
             if (identity_len > PSK_MAX_IDENTITY_LEN) {
@@ -3011,9 +2947,8 @@ int ssl3_send_client_key_exchange(SSL *s)
                 goto psk_err;
             }
             /* create PSK pre_master_secret */
-            pre_ms_len = 2 + psk_len + 2 + psk_len;
-            t = psk_or_pre_ms;
-            memmove(psk_or_pre_ms + psk_len + 4, psk_or_pre_ms, psk_len);
+            t = pms;
+            memmove(pms + psk_len + 4, pms, psk_len);
             s2n(psk_len, t);
             memset(t, 0, psk_len);
             t += psk_len;
@@ -3039,19 +2974,12 @@ int ssl3_send_client_key_exchange(SSL *s)
                 goto psk_err;
             }
 
-            s->session->master_key_length =
-                s->method->ssl3_enc->generate_master_secret(s,
-                                                            s->
-                                                            session->master_key,
-                                                            psk_or_pre_ms,
-                                                            pre_ms_len);
             s2n(identity_len, p);
             memcpy(p, identity, identity_len);
             n = 2 + identity_len;
             psk_err = 0;
  psk_err:
             OPENSSL_cleanse(identity, sizeof(identity));
-            OPENSSL_cleanse(psk_or_pre_ms, sizeof(psk_or_pre_ms));
             if (psk_err != 0) {
                 ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
                 goto err;
@@ -3064,19 +2992,80 @@ int ssl3_send_client_key_exchange(SSL *s)
             goto err;
         }
 
-        ssl_set_handshake_header(s, SSL3_MT_CLIENT_KEY_EXCHANGE, n);
+        if(!ssl_set_handshake_header(s, SSL3_MT_CLIENT_KEY_EXCHANGE, n)) {
+            ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+            SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+            goto err;
+        }
+
         s->state = SSL3_ST_CW_KEY_EXCH_B;
     }
 
     /* SSL3_ST_CW_KEY_EXCH_B */
-    return ssl_do_write(s);
+    n = ssl_do_write(s);
+#ifndef OPENSSL_NO_SRP
+    /* Check for SRP */
+    if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kSRP) {
+        /*
+         * If everything written generate master key: no need to save PMS as
+         * SRP_generate_client_master_secret generates it internally.
+         */
+        if (n > 0) {
+            if ((s->session->master_key_length =
+                 SRP_generate_client_master_secret(s,
+                                                   s->session->master_key)) <
+                0) {
+                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+                       ERR_R_INTERNAL_ERROR);
+                goto err;
+            }
+        }
+    } else
+#endif
+        /* If we haven't written everything save PMS */
+    if (n <= 0) {
+        s->cert->pms = pms;
+        s->cert->pmslen = pmslen;
+    } else {
+        /* If we don't have a PMS restore */
+        if (pms == NULL) {
+            pms = s->cert->pms;
+            pmslen = s->cert->pmslen;
+        }
+        if (pms == NULL) {
+            ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+            SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
+            goto err;
+        }
+        s->session->master_key_length =
+            s->method->ssl3_enc->generate_master_secret(s,
+                                                        s->
+                                                        session->master_key,
+                                                        pms, pmslen);
+        OPENSSL_cleanse(pms, pmslen);
+        OPENSSL_free(pms);
+        s->cert->pms = NULL;
+        if(s->session->master_key_length < 0) {
+            ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+            SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+            goto err;
+        }
+    }
+    return n;
+ memerr:
+    ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+    SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
  err:
-#ifndef OPENSSL_NO_ECDH
+    if (pms) {
+        OPENSSL_cleanse(pms, pmslen);
+        OPENSSL_free(pms);
+        s->cert->pms = NULL;
+    }
+#ifndef OPENSSL_NO_EC
     BN_CTX_free(bn_ctx);
     if (encodedPoint != NULL)
         OPENSSL_free(encodedPoint);
-    if (clnt_ecdh != NULL)
-        EC_KEY_free(clnt_ecdh);
+    EC_KEY_free(clnt_ecdh);
     EVP_PKEY_free(srvr_pub_pkey);
 #endif
     return (-1);
@@ -3136,7 +3125,15 @@ int ssl3_send_client_verify(SSL *s)
             }
             s2n(u, p);
             n = u + 4;
-            if (!ssl3_digest_cached_records(s))
+            /*
+             * For extended master secret we've already digested cached
+             * records.
+             */
+            if (s->session->flags & SSL_SESS_FLAG_EXTMS) {
+                BIO_free(s->s3->handshake_buffer);
+                s->s3->handshake_buffer = NULL;
+                s->s3->flags &= ~TLS1_FLAGS_KEEP_HANDSHAKE;
+            } else if (!ssl3_digest_cached_records(s))
                 goto err;
         } else
 #ifndef OPENSSL_NO_RSA
@@ -3165,7 +3162,7 @@ int ssl3_send_client_verify(SSL *s)
             n = j + 2;
         } else
 #endif
-#ifndef OPENSSL_NO_ECDSA
+#ifndef OPENSSL_NO_EC
         if (pkey->type == EVP_PKEY_EC) {
             if (!ECDSA_sign(pkey->save_type,
                             &(data[MD5_DIGEST_LENGTH]),
@@ -3198,7 +3195,10 @@ int ssl3_send_client_verify(SSL *s)
             SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY, ERR_R_INTERNAL_ERROR);
             goto err;
         }
-        ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE_VERIFY, n);
+        if(!ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE_VERIFY, n)) {
+            SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY, ERR_R_INTERNAL_ERROR);
+            goto err;
+        }
         s->state = SSL3_ST_CW_CERT_VRFY_B;
     }
     EVP_MD_CTX_cleanup(&mctx);
@@ -3374,7 +3374,7 @@ int ssl3_check_cert_and_algorithm(SSL *s)
     /* This is the passed certificate */
 
     idx = sc->peer_cert_type;
-#ifndef OPENSSL_NO_ECDH
+#ifndef OPENSSL_NO_EC
     if (idx == SSL_PKEY_ECC) {
         if (ssl_check_srvr_ecc_cert_and_alg(sc->peer_pkeys[idx].x509, s) == 0) {
             /* check failed */