Narrow the scope of local variables in tls_construct_client_key_exchange()
[oweals/openssl.git] / ssl / statem / statem_clnt.c
index 8da3e9b622c53830c607d2c999d8c4329971836b..e52bbe3b1bce553bb0969e9506bda9fff63cc9a2 100644 (file)
-/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
- * All rights reserved.
- *
- * This package is an SSL implementation written
- * by Eric Young (eay@cryptsoft.com).
- * The implementation was written so as to conform with Netscapes SSL.
- *
- * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to.  The following conditions
- * apply to all code found in this distribution, be it the RC4, RSA,
- * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
- * included with this distribution is covered by the same copyright terms
- * except that the holder is Tim Hudson (tjh@cryptsoft.com).
- *
- * Copyright remains Eric Young's, and as such any Copyright notices in
- * the code are not to be removed.
- * If this package is used in a product, Eric Young should be given attribution
- * as the author of the parts of the library used.
- * This can be in the form of a textual message at program startup or
- * in documentation (online or textual) provided with the package.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *    "This product includes cryptographic software written by
- *     Eric Young (eay@cryptsoft.com)"
- *    The word 'cryptographic' can be left out if the rouines from the library
- *    being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from
- *    the apps directory (application code) you must include an acknowledgement:
- *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- *
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed.  i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.]
- */
-/* ====================================================================
- * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- *    software must display the following acknowledgment:
- *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
- *
- * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
- *    endorse or promote products derived from this software without
- *    prior written permission. For written permission, please contact
- *    openssl-core@openssl.org.
- *
- * 5. Products derived from this software may not be called "OpenSSL"
- *    nor may "OpenSSL" appear in their names without prior written
- *    permission of the OpenSSL Project.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- *    acknowledgment:
- *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
- *
- * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- *
- * This product includes cryptographic software written by Eric Young
- * (eay@cryptsoft.com).  This product includes software written by Tim
- * Hudson (tjh@cryptsoft.com).
+/*
+ * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
  *
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
  */
+
 /* ====================================================================
  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
  *
@@ -190,7 +90,6 @@ static ossl_inline int cert_req_allowed(SSL *s)
  *  Return values are:
  *  1: Yes
  *  0: No
- * -1: Error
  */
 static int key_exchange_expected(SSL *s)
 {
@@ -274,8 +173,6 @@ int ossl_statem_client_read_transition(SSL *s, int mt)
                 }
             } else {
                 ske_expected = key_exchange_expected(s);
-                if (ske_expected < 0)
-                    return 0;
                 /* SKE is optional for some PSK ciphersuites */
                 if (ske_expected
                         || ((s->s3->tmp.new_cipher->algorithm_mkey & SSL_PSK)
@@ -309,8 +206,6 @@ int ossl_statem_client_read_transition(SSL *s, int mt)
 
     case TLS_ST_CR_CERT_STATUS:
         ske_expected = key_exchange_expected(s);
-        if (ske_expected < 0)
-            return 0;
         /* SKE is optional for some PSK ciphersuites */
         if (ske_expected
                 || ((s->s3->tmp.new_cipher->algorithm_mkey & SSL_PSK)
@@ -319,7 +214,7 @@ int ossl_statem_client_read_transition(SSL *s, int mt)
                 st->hand_state = TLS_ST_CR_KEY_EXCH;
                 return 1;
             }
-            return 0;
+            goto err;
         }
         /* Fall through */
 
@@ -329,7 +224,7 @@ int ossl_statem_client_read_transition(SSL *s, int mt)
                 st->hand_state = TLS_ST_CR_CERT_REQ;
                 return 1;
             }
-            return 0;
+            goto err;
         }
         /* Fall through */
 
@@ -370,7 +265,10 @@ int ossl_statem_client_read_transition(SSL *s, int mt)
         break;
     }
 
+ err:
     /* No valid transition found */
+    ssl3_send_alert(s, SSL3_AL_FATAL, SSL3_AD_UNEXPECTED_MESSAGE);
+    SSLerr(SSL_F_READ_STATE_MACHINE, SSL_R_UNEXPECTED_MESSAGE);
     return 0;
 }
 
@@ -491,13 +389,13 @@ WORK_STATE ossl_statem_client_pre_work(SSL *s, WORK_STATE wst)
         s->shutdown = 0;
         if (SSL_IS_DTLS(s)) {
             /* every DTLS ClientHello resets Finished MAC */
-            ssl3_init_finished_mac(s);
+            if (!ssl3_init_finished_mac(s)) {
+                ossl_statem_set_error(s);
+                return WORK_ERROR;
+            }
         }
         break;
 
-    case TLS_ST_CW_CERT:
-        return tls_prepare_client_certificate(s, wst);
-
     case TLS_ST_CW_CHANGE:
         if (SSL_IS_DTLS(s)) {
             if (s->hit) {
@@ -537,20 +435,9 @@ WORK_STATE ossl_statem_client_post_work(SSL *s, WORK_STATE wst)
 
     switch(st->hand_state) {
     case TLS_ST_CW_CLNT_HELLO:
-        if (SSL_IS_DTLS(s) && s->d1->cookie_len > 0 && statem_flush(s) != 1)
+        if (wst == WORK_MORE_A && statem_flush(s) != 1)
             return WORK_MORE_A;
-#ifndef OPENSSL_NO_SCTP
-        /* Disable buffering for SCTP */
-        if (!SSL_IS_DTLS(s) || !BIO_dgram_is_sctp(SSL_get_wbio(s))) {
-#endif
-            /*
-             * turn on buffering for the next lot of output
-             */
-            if (s->bbio != s->wbio)
-                s->wbio = BIO_push(s->bbio, s->wbio);
-#ifndef OPENSSL_NO_SCTP
-            }
-#endif
+
         if (SSL_IS_DTLS(s)) {
             /* Treat the next message as the first packet */
             s->first_packet = 1;
@@ -773,6 +660,9 @@ WORK_STATE ossl_statem_client_post_process_message(SSL *s, WORK_STATE wst)
     OSSL_STATEM *st = &s->statem;
 
     switch(st->hand_state) {
+    case TLS_ST_CR_CERT_REQ:
+        return tls_prepare_client_certificate(s, wst);
+
 #ifndef OPENSSL_NO_SCTP
     case TLS_ST_CR_SRVR_DONE:
         /* We only get here if we are using SCTP and we are renegotiating */
@@ -1124,6 +1014,7 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
          * overwritten if the server refuses resumption.
          */
         if (s->session->session_id_length > 0) {
+            s->ctx->stats.sess_miss++;
             if (!ssl_get_new_session(s, 0)) {
                 goto f_err;
             }
@@ -1352,7 +1243,7 @@ MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt)
     s->session->peer_chain = sk;
     /*
      * Inconsistency alert: cert_chain does include the peer's certificate,
-     * which we don't include in s3_srvr.c
+     * which we don't include in statem_srvr.c
      */
     x = sk_X509_value(sk, 0);
     sk = NULL;
@@ -1568,12 +1459,14 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
             SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_BN_LIB);
             goto dherr;
         }
+        p = g = NULL;
 
         if (!DH_set0_key(dh, bnpub_key, NULL)) {
             al = SSL_AD_INTERNAL_ERROR;
             SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_BN_LIB);
             goto dherr;
         }
+        bnpub_key = NULL;
 
         if (!ssl_security(s, SSL_SECOP_TMP_DH, DH_security_bits(dh), 0, dh)) {
             al = SSL_AD_HANDSHAKE_FAILURE;
@@ -1904,7 +1797,7 @@ MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s, PACKET *pkt)
     s->s3->tmp.ca_names = ca_sk;
     ca_sk = NULL;
 
-    ret = MSG_PROCESS_CONTINUE_READING;
+    ret = MSG_PROCESS_CONTINUE_PROCESSING;
     goto done;
  err:
     ossl_statem_set_error(s);
@@ -1995,9 +1888,12 @@ MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL *s, PACKET *pkt)
      * elsewhere in OpenSSL. The session ID is set to the SHA256 (or SHA1 is
      * SHA256 is disabled) hash of the ticket.
      */
-    EVP_Digest(s->session->tlsext_tick, ticklen,
-               s->session->session_id, &s->session->session_id_length,
-               EVP_sha256(), NULL);
+    if (!EVP_Digest(s->session->tlsext_tick, ticklen,
+                    s->session->session_id, &s->session->session_id_length,
+                    EVP_sha256(), NULL)) {
+        SSLerr(SSL_F_TLS_PROCESS_NEW_SESSION_TICKET, ERR_R_EVP_LIB);
+        goto err;
+    }
     return MSG_PROCESS_CONTINUE_READING;
  f_err:
     ssl3_send_alert(s, SSL3_AL_FATAL, al);
@@ -2124,20 +2020,7 @@ int tls_construct_client_key_exchange(SSL *s)
     size_t pskhdrlen = 0;
 #endif
     unsigned long alg_k;
-#ifndef OPENSSL_NO_RSA
-    unsigned char *q;
-    EVP_PKEY *pkey = NULL;
-    EVP_PKEY_CTX *pctx = NULL;
-#endif
-#if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH)
-    EVP_PKEY *ckey = NULL, *skey = NULL;
-#endif
-#ifndef OPENSSL_NO_EC
-    unsigned char *encodedPoint = NULL;
-    int encoded_pt_len = 0;
-#endif
-    unsigned char *pms = NULL;
-    size_t pmslen = 0;
+
     alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
 
     p = ssl_handshake_start(s);
@@ -2154,6 +2037,8 @@ int tls_construct_client_key_exchange(SSL *s)
         char identity[PSK_MAX_IDENTITY_LEN + 1];
         size_t identitylen;
         unsigned char psk[PSK_MAX_PSK_LEN];
+        unsigned char *tmppsk;
+        char *tmpidentity;
         size_t psklen;
 
         if (s->psk_client_callback == NULL) {
@@ -2177,35 +2062,36 @@ int tls_construct_client_key_exchange(SSL *s)
                    SSL_R_PSK_IDENTITY_NOT_FOUND);
             goto psk_err;
         }
-        OPENSSL_free(s->s3->tmp.psk);
-        s->s3->tmp.psk = OPENSSL_memdup(psk, psklen);
-        OPENSSL_cleanse(psk, psklen);
-
-        if (s->s3->tmp.psk == NULL) {
-            OPENSSL_cleanse(identity, sizeof(identity));
-            goto memerr;
-        }
 
-        s->s3->tmp.psklen = psklen;
         identitylen = strlen(identity);
         if (identitylen > PSK_MAX_IDENTITY_LEN) {
             SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
                    ERR_R_INTERNAL_ERROR);
             goto psk_err;
         }
-        OPENSSL_free(s->session->psk_identity);
-        s->session->psk_identity = OPENSSL_strdup(identity);
-        if (s->session->psk_identity == NULL) {
+
+        tmppsk = OPENSSL_memdup(psk, psklen);
+        tmpidentity = OPENSSL_strdup(identity);
+        if (tmppsk == NULL || tmpidentity == NULL) {
             OPENSSL_cleanse(identity, sizeof(identity));
+            OPENSSL_cleanse(psk, psklen);
+            OPENSSL_clear_free(tmppsk, psklen);
+            OPENSSL_clear_free(tmpidentity, identitylen);
             goto memerr;
         }
 
+        OPENSSL_free(s->s3->tmp.psk);
+        s->s3->tmp.psk = tmppsk;
+        s->s3->tmp.psklen = psklen;
+        OPENSSL_free(s->session->psk_identity);
+        s->session->psk_identity = tmpidentity;
         s2n(identitylen, p);
         memcpy(p, identity, identitylen);
         pskhdrlen = 2 + identitylen;
         p += identitylen;
         psk_err = 0;
 psk_err:
+        OPENSSL_cleanse(psk, psklen);
         OPENSSL_cleanse(identity, sizeof(identity));
         if (psk_err != 0) {
             ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
@@ -2222,11 +2108,12 @@ psk_err:
     }
 #ifndef OPENSSL_NO_RSA
     else if (alg_k & (SSL_kRSA | SSL_kRSAPSK)) {
+        unsigned char *q;
+        EVP_PKEY *pkey = NULL;
+        EVP_PKEY_CTX *pctx = NULL;
         size_t enclen;
-        pmslen = SSL_MAX_MASTER_KEY_LENGTH;
-        pms = OPENSSL_malloc(pmslen);
-        if (pms == NULL)
-            goto memerr;
+        unsigned char *pms = NULL;
+        size_t pmslen = 0;
 
         if (s->session->peer == NULL) {
             /*
@@ -2244,10 +2131,17 @@ psk_err:
             goto err;
         }
 
+        pmslen = SSL_MAX_MASTER_KEY_LENGTH;
+        pms = OPENSSL_malloc(pmslen);
+        if (pms == NULL)
+            goto memerr;
+
         pms[0] = s->client_version >> 8;
         pms[1] = s->client_version & 0xff;
-        if (RAND_bytes(pms + 2, pmslen - 2) <= 0)
+        if (RAND_bytes(pms + 2, pmslen - 2) <= 0) {
+            OPENSSL_clear_free(pms, pmslen);
             goto err;
+        }
 
         q = p;
         /* Fix buf for TLS and beyond */
@@ -2256,11 +2150,15 @@ psk_err:
         pctx = EVP_PKEY_CTX_new(pkey, NULL);
         if (pctx == NULL || EVP_PKEY_encrypt_init(pctx) <= 0
             || EVP_PKEY_encrypt(pctx, NULL, &enclen, pms, pmslen) <= 0) {
+            OPENSSL_clear_free(pms, pmslen);
+            EVP_PKEY_CTX_free(pctx);
             SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
                    ERR_R_EVP_LIB);
             goto err;
         }
         if (EVP_PKEY_encrypt(pctx, p, &enclen, pms, pmslen) <= 0) {
+            OPENSSL_clear_free(pms, pmslen);
+            EVP_PKEY_CTX_free(pctx);
             SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
                    SSL_R_BAD_RSA_ENCRYPT);
             goto err;
@@ -2280,12 +2178,17 @@ psk_err:
             s2n(n, q);
             n += 2;
         }
+
+        s->s3->tmp.pms = pms;
+        s->s3->tmp.pmslen = pmslen;
     }
 #endif
 #ifndef OPENSSL_NO_DH
     else if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) {
         DH *dh_clnt = NULL;
-        BIGNUM *pub_key;
+        const BIGNUM *pub_key;
+        EVP_PKEY *ckey = NULL, *skey = NULL;
+
         skey = s->s3->peer_tmp;
         if (skey == NULL) {
             SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
@@ -2298,6 +2201,7 @@ psk_err:
         if (dh_clnt == NULL || ssl_derive(s, ckey, skey) == 0) {
             SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
                    ERR_R_INTERNAL_ERROR);
+            EVP_PKEY_free(ckey);
             goto err;
         }
 
@@ -2315,6 +2219,9 @@ psk_err:
 
 #ifndef OPENSSL_NO_EC
     else if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) {
+        unsigned char *encodedPoint = NULL;
+        int encoded_pt_len = 0;
+        EVP_PKEY *ckey = NULL, *skey = NULL;
 
         skey = s->s3->peer_tmp;
         if ((skey == NULL) || EVP_PKEY_get0_EC_KEY(skey) == NULL) {
@@ -2327,6 +2234,7 @@ psk_err:
 
         if (ssl_derive(s, ckey, skey) == 0) {
             SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_EVP_LIB);
+            EVP_PKEY_free(ckey);
             goto err;
         }
 
@@ -2337,6 +2245,7 @@ psk_err:
 
         if (encoded_pt_len == 0) {
             SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_EC_LIB);
+            EVP_PKEY_free(ckey);
             goto err;
         }
 
@@ -2367,15 +2276,13 @@ psk_err:
         unsigned char shared_ukm[32], tmp[256];
         EVP_MD_CTX *ukm_hash;
         int dgst_nid = NID_id_GostR3411_94;
+        unsigned char *pms = NULL;
+        size_t pmslen = 0;
+
         if ((s->s3->tmp.new_cipher->algorithm_auth & SSL_aGOST12) != 0)
             dgst_nid = NID_id_GostR3411_2012_256;
 
 
-        pmslen = 32;
-        pms = OPENSSL_malloc(pmslen);
-        if (pms == NULL)
-            goto memerr;
-
         /*
          * Get server sertificate PKEY and create ctx from it
          */
@@ -2399,12 +2306,17 @@ psk_err:
          */
 
         /* Otherwise, generate ephemeral key pair */
+        pmslen = 32;
+        pms = OPENSSL_malloc(pmslen);
+        if (pms == NULL)
+            goto memerr;
 
         if (pkey_ctx == NULL
                 || EVP_PKEY_encrypt_init(pkey_ctx) <= 0
                 /* Generate session key */
                 || RAND_bytes(pms, pmslen) <= 0) {
             EVP_PKEY_CTX_free(pkey_ctx);
+            OPENSSL_clear_free(pms, pmslen);
             SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
                    ERR_R_INTERNAL_ERROR);
             goto err;
@@ -2435,6 +2347,7 @@ psk_err:
                                     SSL3_RANDOM_SIZE) <= 0
                 || EVP_DigestFinal_ex(ukm_hash, shared_ukm, &md_len) <= 0) {
             EVP_MD_CTX_free(ukm_hash);
+            OPENSSL_clear_free(pms, pmslen);
             SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
                    ERR_R_INTERNAL_ERROR);
             goto err;
@@ -2443,6 +2356,7 @@ psk_err:
         if (EVP_PKEY_CTX_ctrl
             (pkey_ctx, -1, EVP_PKEY_OP_ENCRYPT, EVP_PKEY_CTRL_SET_IV, 8,
              shared_ukm) < 0) {
+            OPENSSL_clear_free(pms, pmslen);
             SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
                    SSL_R_LIBRARY_BUG);
             goto err;
@@ -2454,6 +2368,7 @@ psk_err:
         *(p++) = V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED;
         msglen = 255;
         if (EVP_PKEY_encrypt(pkey_ctx, tmp, &msglen, pms, pmslen) <= 0) {
+            OPENSSL_clear_free(pms, pmslen);
             SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
                    SSL_R_LIBRARY_BUG);
             goto err;
@@ -2474,7 +2389,8 @@ psk_err:
             s->s3->flags |= TLS1_FLAGS_SKIP_CERT_VERIFY;
         }
         EVP_PKEY_CTX_free(pkey_ctx);
-
+        s->s3->tmp.pms = pms;
+        s->s3->tmp.pmslen = pmslen;
     }
 #endif
 #ifndef OPENSSL_NO_SRP
@@ -2515,27 +2431,13 @@ psk_err:
         goto err;
     }
 
-    if (pms != NULL) {
-        s->s3->tmp.pms = pms;
-        s->s3->tmp.pmslen = pmslen;
-    }
-
     return 1;
  memerr:
     ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
     SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
  err:
-    OPENSSL_clear_free(pms, pmslen);
+    OPENSSL_clear_free(s->s3->tmp.pms, s->s3->tmp.pmslen);
     s->s3->tmp.pms = NULL;
-#ifndef OPENSSL_NO_RSA
-    EVP_PKEY_CTX_free(pctx);
-#endif
-#ifndef OPENSSL_NO_EC
-    OPENSSL_free(encodedPoint);
-#endif
-#if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH)
-    EVP_PKEY_free(ckey);
-#endif
 #ifndef OPENSSL_NO_PSK
     OPENSSL_clear_free(s->s3->tmp.psk, s->s3->tmp.psklen);
     s->s3->tmp.psk = NULL;