Split out DHE from tls_process_key_exchange()
[openssl.git] / ssl / statem / statem_clnt.c
index 8e48f34f0d0f8dcad98dd6b18cec4ba1102a8b7f..6d937a4c6bc4f16cf0d3eaea464306ad8da476a0 100644 (file)
@@ -268,7 +268,7 @@ int ossl_statem_client_read_transition(SSL *s, int mt)
  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);
+    SSLerr(SSL_F_OSSL_STATEM_CLIENT_READ_TRANSITION, SSL_R_UNEXPECTED_MESSAGE);
     return 0;
 }
 
@@ -1302,210 +1302,239 @@ MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt)
     return ret;
 }
 
-MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
+static int tls_process_ske_psk_preamble(SSL *s, PACKET *pkt, int *al)
 {
-    EVP_MD_CTX *md_ctx;
-    int al, j;
-    long alg_k, alg_a;
-    EVP_PKEY *pkey = NULL;
-    const EVP_MD *md = NULL;
-#ifndef OPENSSL_NO_RSA
-    RSA *rsa = NULL;
-#endif
-#ifndef OPENSSL_NO_EC
-    EVP_PKEY_CTX *pctx = NULL;
+#ifndef OPENSSL_NO_PSK
+    PACKET psk_identity_hint;
+
+    /* PSK ciphersuites are preceded by an identity hint */
+
+    if (!PACKET_get_length_prefixed_2(pkt, &psk_identity_hint)) {
+        *al = SSL_AD_DECODE_ERROR;
+        SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
+        return 0;
+    }
+
+    /*
+     * Store PSK identity hint for later use, hint is used in
+     * tls_construct_client_key_exchange.  Assume that the maximum length of
+     * a PSK identity hint can be as long as the maximum length of a PSK
+     * identity.
+     */
+    if (PACKET_remaining(&psk_identity_hint) > PSK_MAX_IDENTITY_LEN) {
+        *al = SSL_AD_HANDSHAKE_FAILURE;
+        SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_DATA_LENGTH_TOO_LONG);
+        return 0;
+    }
+
+    if (PACKET_remaining(&psk_identity_hint) == 0) {
+        OPENSSL_free(s->session->psk_identity_hint);
+        s->session->psk_identity_hint = NULL;
+    } else if (!PACKET_strndup(&psk_identity_hint,
+                        &s->session->psk_identity_hint)) {
+        *al = SSL_AD_INTERNAL_ERROR;
+        return 0;
+    }
+
+    return 1;
+#else
+    SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+    *al = SSL_AD_INTERNAL_ERROR;
+    return 0;
 #endif
-    PACKET save_param_start, signature;
+}
 
-    md_ctx = EVP_MD_CTX_new();
-    if (md_ctx == NULL) {
-        al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
-        goto f_err;
+static int tls_process_ske_srp(SSL *s, PACKET *pkt, EVP_PKEY **pkey, int *al)
+{
+#ifndef OPENSSL_NO_SRP
+    PACKET prime, generator, salt, server_pub;
+
+    if (!PACKET_get_length_prefixed_2(pkt, &prime)
+        || !PACKET_get_length_prefixed_2(pkt, &generator)
+        || !PACKET_get_length_prefixed_1(pkt, &salt)
+        || !PACKET_get_length_prefixed_2(pkt, &server_pub)) {
+        *al = SSL_AD_DECODE_ERROR;
+        SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
+        return 0;
     }
 
-    alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+    if ((s->srp_ctx.N =
+         BN_bin2bn(PACKET_data(&prime),
+                   PACKET_remaining(&prime), NULL)) == NULL
+        || (s->srp_ctx.g =
+            BN_bin2bn(PACKET_data(&generator),
+                      PACKET_remaining(&generator), NULL)) == NULL
+        || (s->srp_ctx.s =
+            BN_bin2bn(PACKET_data(&salt),
+                      PACKET_remaining(&salt), NULL)) == NULL
+        || (s->srp_ctx.B =
+            BN_bin2bn(PACKET_data(&server_pub),
+                      PACKET_remaining(&server_pub), NULL)) == NULL) {
+        *al = SSL_AD_INTERNAL_ERROR;
+        SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_BN_LIB);
+        return 0;
+    }
 
-    save_param_start = *pkt;
+    if (!srp_verify_server_param(s, al)) {
+        *al = SSL_AD_DECODE_ERROR;
+        SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_BAD_SRP_PARAMETERS);
+        return 0;
+    }
 
-#if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH)
-    EVP_PKEY_free(s->s3->peer_tmp);
-    s->s3->peer_tmp = NULL;
+    /* We must check if there is a certificate */
+    if (s->s3->tmp.new_cipher->algorithm_auth & (SSL_aRSA|SSL_aDSS))
+        *pkey = X509_get0_pubkey(s->session->peer);
+
+    return 1;
+#else
+    SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+    *al = SSL_AD_INTERNAL_ERROR;
+    return 0;
 #endif
+}
 
-    alg_a = s->s3->tmp.new_cipher->algorithm_auth;
+static int tls_process_ske_dhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey, int *al)
+{
+#ifndef OPENSSL_NO_DH
+    PACKET prime, generator, pub_key;
+    EVP_PKEY *peer_tmp = NULL;
 
-    al = SSL_AD_DECODE_ERROR;
+    DH *dh = NULL;
+    BIGNUM *p = NULL, *g = NULL, *bnpub_key = NULL;
 
-#ifndef OPENSSL_NO_PSK
-    /* PSK ciphersuites are preceded by an identity hint */
-    if (alg_k & SSL_PSK) {
-        PACKET psk_identity_hint;
-        if (!PACKET_get_length_prefixed_2(pkt, &psk_identity_hint)) {
-            SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
-            goto f_err;
-        }
+    if (!PACKET_get_length_prefixed_2(pkt, &prime)
+        || !PACKET_get_length_prefixed_2(pkt, &generator)
+        || !PACKET_get_length_prefixed_2(pkt, &pub_key)) {
+        *al = SSL_AD_DECODE_ERROR;
+        SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
+        return 0;
+    }
 
-        /*
-         * Store PSK identity hint for later use, hint is used in
-         * ssl3_send_client_key_exchange.  Assume that the maximum length of
-         * a PSK identity hint can be as long as the maximum length of a PSK
-         * identity.
-         */
-        if (PACKET_remaining(&psk_identity_hint) > PSK_MAX_IDENTITY_LEN) {
-            al = SSL_AD_HANDSHAKE_FAILURE;
-            SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_DATA_LENGTH_TOO_LONG);
-            goto f_err;
-        }
+    peer_tmp = EVP_PKEY_new();
+    dh = DH_new();
 
-        if (PACKET_remaining(&psk_identity_hint) == 0) {
-            OPENSSL_free(s->session->psk_identity_hint);
-            s->session->psk_identity_hint = NULL;
-        } else if (!PACKET_strndup(&psk_identity_hint,
-                            &s->session->psk_identity_hint)) {
-            al = SSL_AD_INTERNAL_ERROR;
-            goto f_err;
-        }
+    if (peer_tmp == NULL || dh == NULL) {
+        *al = SSL_AD_INTERNAL_ERROR;
+        SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
+        goto err;
     }
 
-    /* Nothing else to do for plain PSK or RSAPSK */
-    if (alg_k & (SSL_kPSK | SSL_kRSAPSK)) {
-    } else
-#endif                          /* !OPENSSL_NO_PSK */
-    /*
-     * Dummy "if" to ensure sane C code in the event of various OPENSSL_NO_*
-     * options
-     */
-    if (0) {
+    p = BN_bin2bn(PACKET_data(&prime), PACKET_remaining(&prime), NULL);
+    g = BN_bin2bn(PACKET_data(&generator), PACKET_remaining(&generator),
+                  NULL);
+    bnpub_key = BN_bin2bn(PACKET_data(&pub_key), PACKET_remaining(&pub_key),
+                          NULL);
+    if (p == NULL || g == NULL || bnpub_key == NULL) {
+        *al = SSL_AD_INTERNAL_ERROR;
+        SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_BN_LIB);
+        goto err;
     }
-#ifndef OPENSSL_NO_SRP
-    else if (alg_k & SSL_kSRP) {
-        PACKET prime, generator, salt, server_pub;
-        if (!PACKET_get_length_prefixed_2(pkt, &prime)
-            || !PACKET_get_length_prefixed_2(pkt, &generator)
-            || !PACKET_get_length_prefixed_1(pkt, &salt)
-            || !PACKET_get_length_prefixed_2(pkt, &server_pub)) {
-            SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
-            goto f_err;
-        }
 
-        if ((s->srp_ctx.N =
-             BN_bin2bn(PACKET_data(&prime),
-                       PACKET_remaining(&prime), NULL)) == NULL
-            || (s->srp_ctx.g =
-                BN_bin2bn(PACKET_data(&generator),
-                          PACKET_remaining(&generator), NULL)) == NULL
-            || (s->srp_ctx.s =
-                BN_bin2bn(PACKET_data(&salt),
-                          PACKET_remaining(&salt), NULL)) == NULL
-            || (s->srp_ctx.B =
-                BN_bin2bn(PACKET_data(&server_pub),
-                          PACKET_remaining(&server_pub), NULL)) == NULL) {
-            SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_BN_LIB);
-            goto err;
-        }
+    if (BN_is_zero(p) || BN_is_zero(g) || BN_is_zero(bnpub_key)) {
+        *al = SSL_AD_DECODE_ERROR;
+        SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_BAD_DH_VALUE);
+        goto err;
+    }
 
-        if (!srp_verify_server_param(s, &al)) {
-            SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_BAD_SRP_PARAMETERS);
-            goto f_err;
-        }
+    if (!DH_set0_pqg(dh, p, NULL, g)) {
+        *al = SSL_AD_INTERNAL_ERROR;
+        SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_BN_LIB);
+        goto err;
+    }
+    p = g = NULL;
 
-/* We must check if there is a certificate */
-        if (alg_a & (SSL_aRSA|SSL_aDSS))
-            pkey = X509_get0_pubkey(s->session->peer);
+    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 err;
     }
-#endif                          /* !OPENSSL_NO_SRP */
-#ifndef OPENSSL_NO_DH
-    else if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) {
-        PACKET prime, generator, pub_key;
-        EVP_PKEY *peer_tmp = NULL;
+    bnpub_key = NULL;
 
-        DH *dh = NULL;
-        BIGNUM *p = NULL, *g = NULL, *bnpub_key = NULL;
+    if (!ssl_security(s, SSL_SECOP_TMP_DH, DH_security_bits(dh), 0, dh)) {
+        *al = SSL_AD_HANDSHAKE_FAILURE;
+        SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_DH_KEY_TOO_SMALL);
+        goto err;
+    }
 
-        if (!PACKET_get_length_prefixed_2(pkt, &prime)
-            || !PACKET_get_length_prefixed_2(pkt, &generator)
-            || !PACKET_get_length_prefixed_2(pkt, &pub_key)) {
-            SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
-            goto f_err;
-        }
+    if (EVP_PKEY_assign_DH(peer_tmp, dh) == 0) {
+        *al = SSL_AD_INTERNAL_ERROR;
+        SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_EVP_LIB);
+        goto err;
+    }
 
-        peer_tmp = EVP_PKEY_new();
-        dh = DH_new();
+    s->s3->peer_tmp = peer_tmp;
 
-        if (peer_tmp == NULL || dh == NULL) {
-            al = SSL_AD_INTERNAL_ERROR;
-            SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
-            goto dherr;
-        }
+    /*
+     * FIXME: This makes assumptions about which ciphersuites come with
+     * public keys. We should have a less ad-hoc way of doing this
+     */
+    if (s->s3->tmp.new_cipher->algorithm_auth & (SSL_aRSA|SSL_aDSS))
+        *pkey = X509_get0_pubkey(s->session->peer);
+    /* else anonymous DH, so no certificate or pkey. */
 
-        p = BN_bin2bn(PACKET_data(&prime), PACKET_remaining(&prime), NULL);
-        g = BN_bin2bn(PACKET_data(&generator), PACKET_remaining(&generator),
-                      NULL);
-        bnpub_key = BN_bin2bn(PACKET_data(&pub_key), PACKET_remaining(&pub_key),
-                              NULL);
-        if (p == NULL || g == NULL || bnpub_key == NULL) {
-            SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_BN_LIB);
-            goto dherr;
-        }
+    return 1;
 
-        if (BN_is_zero(p) || BN_is_zero(g) || BN_is_zero(bnpub_key)) {
-            SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_BAD_DH_VALUE);
-            goto dherr;
-        }
+ err:
+    BN_free(p);
+    BN_free(g);
+    BN_free(bnpub_key);
+    DH_free(dh);
+    EVP_PKEY_free(peer_tmp);
 
-        if (!DH_set0_pqg(dh, p, NULL, g)) {
-            al = SSL_AD_INTERNAL_ERROR;
-            SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_BN_LIB);
-            goto dherr;
-        }
-        p = g = NULL;
+    return 0;
+#else
+    SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+    *al = SSL_AD_INTERNAL_ERROR;
+    return 0;
+#endif
+}
 
-        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;
+MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
+{
+    EVP_MD_CTX *md_ctx;
+    int al = -1;
+    long alg_k, alg_a;
+    EVP_PKEY *pkey = NULL;
+    PACKET save_param_start, signature;
 
-        if (!ssl_security(s, SSL_SECOP_TMP_DH, DH_security_bits(dh), 0, dh)) {
-            al = SSL_AD_HANDSHAKE_FAILURE;
-            SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_DH_KEY_TOO_SMALL);
-            goto dherr;
-        }
+    md_ctx = EVP_MD_CTX_new();
+    if (md_ctx == NULL) {
+        al = SSL_AD_INTERNAL_ERROR;
+        SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
+        goto f_err;
+    }
 
-        if (EVP_PKEY_assign_DH(peer_tmp, dh) == 0) {
-            al = SSL_AD_INTERNAL_ERROR;
-            SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_EVP_LIB);
-            goto dherr;
-        }
+    alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
 
-        s->s3->peer_tmp = peer_tmp;
+    save_param_start = *pkt;
 
-        goto dhend;
- dherr:
-        BN_free(p);
-        BN_free(g);
-        BN_free(bnpub_key);
-        DH_free(dh);
-        EVP_PKEY_free(peer_tmp);
-        goto f_err;
- dhend:
-        /*
-         * FIXME: This makes assumptions about which ciphersuites come with
-         * public keys. We should have a less ad-hoc way of doing this
-         */
-        if (alg_a & (SSL_aRSA|SSL_aDSS))
-            pkey = X509_get0_pubkey(s->session->peer);
-        /* else anonymous DH, so no certificate or pkey. */
+#if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH)
+    EVP_PKEY_free(s->s3->peer_tmp);
+    s->s3->peer_tmp = NULL;
+#endif
+
+    alg_a = s->s3->tmp.new_cipher->algorithm_auth;
+
+    if (alg_k & SSL_PSK) {
+        if (!tls_process_ske_psk_preamble(s, pkt, &al))
+            goto err;
     }
-#endif                          /* !OPENSSL_NO_DH */
 
+    /* Nothing else to do for plain PSK or RSAPSK */
+    if (alg_k & (SSL_kPSK | SSL_kRSAPSK)) {
+    } else if (alg_k & SSL_kSRP) {
+        if (!tls_process_ske_srp(s, pkt, &pkey, &al))
+            goto err;
+    } else if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) {
+        if (!tls_process_ske_dhe(s, pkt, &pkey, &al))
+            goto err;
+    }
 #ifndef OPENSSL_NO_EC
     else if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) {
         PACKET encoded_pt;
         const unsigned char *ecparams;
         int curve_nid;
+        EVP_PKEY_CTX *pctx = NULL;
 
         /*
          * Extract elliptic curve parameters and the server's ephemeral ECDH
@@ -1541,6 +1570,7 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
             || EVP_PKEY_paramgen(pctx, &s->s3->peer_tmp) <= 0) {
             al = SSL_AD_INTERNAL_ERROR;
             SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_EVP_LIB);
+            EVP_PKEY_CTX_free(pctx);
             goto f_err;
         }
         EVP_PKEY_CTX_free(pctx);
@@ -1583,6 +1613,8 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
     /* if it was signed, check the signature */
     if (pkey != NULL) {
         PACKET params;
+        int maxsig;
+        const EVP_MD *md = NULL;
         /*
          * |pkt| now points to the beginning of the signature, so the difference
          * equals the length of the parameters.
@@ -1622,8 +1654,8 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
             SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
             goto f_err;
         }
-        j = EVP_PKEY_size(pkey);
-        if (j < 0) {
+        maxsig = EVP_PKEY_size(pkey);
+        if (maxsig < 0) {
             SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
             goto f_err;
         }
@@ -1631,7 +1663,7 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
         /*
          * Check signature length
          */
-        if (PACKET_remaining(&signature) > (size_t)j) {
+        if (PACKET_remaining(&signature) > (size_t)maxsig) {
             /* wrong packet length */
             SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_WRONG_SIGNATURE_LENGTH);
             goto f_err;
@@ -1672,14 +1704,11 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
     EVP_MD_CTX_free(md_ctx);
     return MSG_PROCESS_CONTINUE_READING;
  f_err:
-    ssl3_send_alert(s, SSL3_AL_FATAL, al);
+    if (al == -1)
+        al = SSL_AD_DECODE_ERROR;
  err:
-#ifndef OPENSSL_NO_RSA
-    RSA_free(rsa);
-#endif
-#ifndef OPENSSL_NO_EC
-    EVP_PKEY_CTX_free(pctx);
-#endif
+    if (al != -1)
+        ssl3_send_alert(s, SSL3_AL_FATAL, al);
     EVP_MD_CTX_free(md_ctx);
     ossl_statem_set_error(s);
     return MSG_PROCESS_ERROR;
@@ -1839,16 +1868,9 @@ MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL *s, PACKET *pkt)
          */
         if (i & SSL_SESS_CACHE_CLIENT) {
             /*
-             * Remove the old session from the cache
+             * Remove the old session from the cache. We carry on if this fails
              */
-            if (i & SSL_SESS_CACHE_NO_INTERNAL_STORE) {
-                if (s->session_ctx->remove_session_cb != NULL)
-                    s->session_ctx->remove_session_cb(s->session_ctx,
-                                                      s->session);
-            } else {
-                /* We carry on if this fails */
-                SSL_CTX_remove_session(s->session_ctx, s->session);
-            }
+            SSL_CTX_remove_session(s->session_ctx, s->session);
         }
 
         if ((new_sess = ssl_session_dup(s->session, 0)) == 0) {
@@ -2030,8 +2052,7 @@ static int tls_construct_cke_psk_preamble(SSL *s, unsigned char **p,
     size_t psklen = 0;
 
     if (s->psk_client_callback == NULL) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
-               SSL_R_PSK_NO_CLIENT_CB);
+        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE, SSL_R_PSK_NO_CLIENT_CB);
         *al = SSL_AD_INTERNAL_ERROR;
         goto err;
     }
@@ -2043,12 +2064,11 @@ static int tls_construct_cke_psk_preamble(SSL *s, unsigned char **p,
                                     psk, sizeof(psk));
 
     if (psklen > PSK_MAX_PSK_LEN) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
-               ERR_R_INTERNAL_ERROR);
+        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE, ERR_R_INTERNAL_ERROR);
         *al = SSL_AD_HANDSHAKE_FAILURE;
         goto err;
     } else if (psklen == 0) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
+        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE,
                SSL_R_PSK_IDENTITY_NOT_FOUND);
         *al = SSL_AD_HANDSHAKE_FAILURE;
         goto err;
@@ -2056,8 +2076,7 @@ static int tls_construct_cke_psk_preamble(SSL *s, unsigned char **p,
 
     identitylen = strlen(identity);
     if (identitylen > PSK_MAX_IDENTITY_LEN) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
-               ERR_R_INTERNAL_ERROR);
+        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE, ERR_R_INTERNAL_ERROR);
         *al = SSL_AD_HANDSHAKE_FAILURE;
         goto err;
     }
@@ -2065,7 +2084,7 @@ static int tls_construct_cke_psk_preamble(SSL *s, unsigned char **p,
     tmppsk = OPENSSL_memdup(psk, psklen);
     tmpidentity = OPENSSL_strdup(identity);
     if (tmppsk == NULL || tmpidentity == NULL) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
+        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE, ERR_R_MALLOC_FAILURE);
         *al = SSL_AD_INTERNAL_ERROR;
         goto err;
     }
@@ -2092,7 +2111,7 @@ static int tls_construct_cke_psk_preamble(SSL *s, unsigned char **p,
 
     return ret;
 #else
-    SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+    SSLerr(SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE, ERR_R_INTERNAL_ERROR);
     *al = SSL_AD_INTERNAL_ERROR;
     return 0;
 #endif
@@ -2112,23 +2131,20 @@ static int tls_construct_cke_rsa(SSL *s, unsigned char **p, int *len, int *al)
         /*
          * We should always have a server certificate with SSL_kRSA.
          */
-        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
-               ERR_R_INTERNAL_ERROR);
+        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_RSA, ERR_R_INTERNAL_ERROR);
         return 0;
     }
 
     pkey = X509_get0_pubkey(s->session->peer);
     if (EVP_PKEY_get0_RSA(pkey) == NULL) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
-               ERR_R_INTERNAL_ERROR);
+        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_RSA, ERR_R_INTERNAL_ERROR);
         return 0;
     }
 
     pmslen = SSL_MAX_MASTER_KEY_LENGTH;
     pms = OPENSSL_malloc(pmslen);
     if (pms == NULL) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
-               ERR_R_MALLOC_FAILURE);
+        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_RSA, ERR_R_MALLOC_FAILURE);
         *al = SSL_AD_INTERNAL_ERROR;
         return 0;
     }
@@ -2146,13 +2162,11 @@ static int tls_construct_cke_rsa(SSL *s, unsigned char **p, int *len, int *al)
     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) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
-               ERR_R_EVP_LIB);
+        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_RSA, ERR_R_EVP_LIB);
         goto err;
     }
     if (EVP_PKEY_encrypt(pctx, *p, &enclen, pms, pmslen) <= 0) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
-               SSL_R_BAD_RSA_ENCRYPT);
+        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_RSA, SSL_R_BAD_RSA_ENCRYPT);
         goto err;
     }
     *len = enclen;
@@ -2181,7 +2195,7 @@ static int tls_construct_cke_rsa(SSL *s, unsigned char **p, int *len, int *al)
 
     return 0;
 #else
-    SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+    SSLerr(SSL_F_TLS_CONSTRUCT_CKE_RSA, ERR_R_INTERNAL_ERROR);
     *al = SSL_AD_INTERNAL_ERROR;
     return 0;
 #endif
@@ -2196,16 +2210,14 @@ static int tls_construct_cke_dhe(SSL *s, unsigned char **p, int *len, int *al)
 
     skey = s->s3->peer_tmp;
     if (skey == NULL) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
-               ERR_R_INTERNAL_ERROR);
+        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_DHE, ERR_R_INTERNAL_ERROR);
         return 0;
     }
     ckey = ssl_generate_pkey(skey, NID_undef);
     dh_clnt = EVP_PKEY_get0_DH(ckey);
 
     if (dh_clnt == NULL || ssl_derive(s, ckey, skey) == 0) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
-               ERR_R_INTERNAL_ERROR);
+        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_DHE, ERR_R_INTERNAL_ERROR);
         EVP_PKEY_free(ckey);
         return 0;
     }
@@ -2220,7 +2232,7 @@ static int tls_construct_cke_dhe(SSL *s, unsigned char **p, int *len, int *al)
 
     return 1;
 #else
-    SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+    SSLerr(SSL_F_TLS_CONSTRUCT_CKE_DHE, ERR_R_INTERNAL_ERROR);
     *al = SSL_AD_INTERNAL_ERROR;
     return 0;
 #endif
@@ -2235,15 +2247,14 @@ static int tls_construct_cke_ecdhe(SSL *s, unsigned char **p, int *len, int *al)
 
     skey = s->s3->peer_tmp;
     if ((skey == NULL) || EVP_PKEY_get0_EC_KEY(skey) == NULL) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
-                   ERR_R_INTERNAL_ERROR);
+        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_ECDHE, ERR_R_INTERNAL_ERROR);
         return 0;
     }
 
     ckey = ssl_generate_pkey(skey, NID_undef);
 
     if (ssl_derive(s, ckey, skey) == 0) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_EVP_LIB);
+        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_ECDHE, ERR_R_EVP_LIB);
         goto err;
     }
 
@@ -2253,7 +2264,7 @@ static int tls_construct_cke_ecdhe(SSL *s, unsigned char **p, int *len, int *al)
                                     &encodedPoint, NULL);
 
     if (encoded_pt_len == 0) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_EC_LIB);
+        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_ECDHE, ERR_R_EC_LIB);
         goto err;
     }
 
@@ -2277,7 +2288,171 @@ static int tls_construct_cke_ecdhe(SSL *s, unsigned char **p, int *len, int *al)
     EVP_PKEY_free(ckey);
     return 0;
 #else
-    SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+    SSLerr(SSL_F_TLS_CONSTRUCT_CKE_ECDHE, ERR_R_INTERNAL_ERROR);
+    *al = SSL_AD_INTERNAL_ERROR;
+    return 0;
+#endif
+}
+
+static int tls_construct_cke_gost(SSL *s, unsigned char **p, int *len, int *al)
+{
+#ifndef OPENSSL_NO_GOST
+    /* GOST key exchange message creation */
+    EVP_PKEY_CTX *pkey_ctx = NULL;
+    X509 *peer_cert;
+    size_t msglen;
+    unsigned int md_len;
+    unsigned char shared_ukm[32], tmp[256];
+    EVP_MD_CTX *ukm_hash = NULL;
+    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;
+
+    /*
+     * Get server sertificate PKEY and create ctx from it
+     */
+    peer_cert = s->session->peer;
+    if (!peer_cert) {
+        *al = SSL_AD_HANDSHAKE_FAILURE;
+        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_GOST,
+               SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER);
+        return 0;
+    }
+
+    pkey_ctx = EVP_PKEY_CTX_new(X509_get0_pubkey(peer_cert), NULL);
+    if (pkey_ctx == NULL) {
+        *al = SSL_AD_INTERNAL_ERROR;
+        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_GOST, ERR_R_MALLOC_FAILURE);
+        return 0;
+    }
+    /*
+     * If we have send a certificate, and certificate key
+     * parameters match those of server certificate, use
+     * certificate key for key exchange
+     */
+
+    /* Otherwise, generate ephemeral key pair */
+    pmslen = 32;
+    pms = OPENSSL_malloc(pmslen);
+    if (pms == NULL) {
+        *al = SSL_AD_INTERNAL_ERROR;
+        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_GOST, ERR_R_MALLOC_FAILURE);
+        return 0;
+    }
+
+    if (EVP_PKEY_encrypt_init(pkey_ctx) <= 0
+            /* Generate session key */
+            || RAND_bytes(pms, pmslen) <= 0) {
+        *al = SSL_AD_INTERNAL_ERROR;
+        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_GOST, ERR_R_INTERNAL_ERROR);
+        goto err;
+    };
+    /*
+     * If we have client certificate, use its secret as peer key
+     */
+    if (s->s3->tmp.cert_req && s->cert->key->privatekey) {
+        if (EVP_PKEY_derive_set_peer
+            (pkey_ctx, s->cert->key->privatekey) <= 0) {
+            /*
+             * If there was an error - just ignore it. Ephemeral key
+             * * would be used
+             */
+            ERR_clear_error();
+        }
+    }
+    /*
+     * Compute shared IV and store it in algorithm-specific context
+     * data
+     */
+    ukm_hash = EVP_MD_CTX_new();
+    if (ukm_hash == NULL
+            || EVP_DigestInit(ukm_hash, EVP_get_digestbynid(dgst_nid)) <= 0
+            || EVP_DigestUpdate(ukm_hash, s->s3->client_random,
+                                SSL3_RANDOM_SIZE) <= 0
+            || EVP_DigestUpdate(ukm_hash, s->s3->server_random,
+                                SSL3_RANDOM_SIZE) <= 0
+            || EVP_DigestFinal_ex(ukm_hash, shared_ukm, &md_len) <= 0) {
+        *al = SSL_AD_INTERNAL_ERROR;
+        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_GOST, ERR_R_INTERNAL_ERROR);
+        goto err;
+    }
+    EVP_MD_CTX_free(ukm_hash);
+    ukm_hash = NULL;
+    if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, EVP_PKEY_OP_ENCRYPT,
+                          EVP_PKEY_CTRL_SET_IV, 8, shared_ukm) < 0) {
+        *al = SSL_AD_INTERNAL_ERROR;
+        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_GOST, SSL_R_LIBRARY_BUG);
+        goto err;
+    }
+    /* Make GOST keytransport blob message */
+    /*
+     * Encapsulate it into sequence
+     */
+    *((*p)++) = V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED;
+    msglen = 255;
+    if (EVP_PKEY_encrypt(pkey_ctx, tmp, &msglen, pms, pmslen) <= 0) {
+        *al = SSL_AD_INTERNAL_ERROR;
+        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_GOST, SSL_R_LIBRARY_BUG);
+        goto err;
+    }
+    if (msglen >= 0x80) {
+        *((*p)++) = 0x81;
+        *((*p)++) = msglen & 0xff;
+        *len = msglen + 3;
+    } else {
+        *((*p)++) = msglen & 0xff;
+        *len = msglen + 2;
+    }
+    memcpy(*p, tmp, msglen);
+    /* Check if pubkey from client certificate was used */
+    if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 2,
+                          NULL) > 0) {
+        /* Set flag "skip certificate verify" */
+        s->s3->flags |= TLS1_FLAGS_SKIP_CERT_VERIFY;
+    }
+    EVP_PKEY_CTX_free(pkey_ctx);
+    s->s3->tmp.pms = pms;
+    s->s3->tmp.pmslen = pmslen;
+
+    return 1;
+ err:
+    EVP_PKEY_CTX_free(pkey_ctx);
+    OPENSSL_clear_free(pms, pmslen);
+    EVP_MD_CTX_free(ukm_hash);
+    return 0;
+#else
+    SSLerr(SSL_F_TLS_CONSTRUCT_CKE_GOST, ERR_R_INTERNAL_ERROR);
+    *al = SSL_AD_INTERNAL_ERROR;
+    return 0;
+#endif
+}
+
+static int tls_construct_cke_srp(SSL *s, unsigned char **p, int *len, int *al)
+{
+#ifndef OPENSSL_NO_SRT
+    if (s->srp_ctx.A != NULL) {
+        /* send off the data */
+        *len = BN_num_bytes(s->srp_ctx.A);
+        s2n(*len, *p);
+        BN_bn2bin(s->srp_ctx.A, *p);
+        *len += 2;
+    } else {
+        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_SRP, ERR_R_INTERNAL_ERROR);
+        return 0;
+    }
+    OPENSSL_free(s->session->srp_username);
+    s->session->srp_username = OPENSSL_strdup(s->srp_ctx.login);
+    if (s->session->srp_username == NULL) {
+        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_SRP, ERR_R_MALLOC_FAILURE);
+        return 0;
+    }
+
+    return 1;
+#else
+    SSLerr(SSL_F_TLS_CONSTRUCT_CKE_SRP, ERR_R_INTERNAL_ERROR);
     *al = SSL_AD_INTERNAL_ERROR;
     return 0;
 #endif
@@ -2286,7 +2461,7 @@ static int tls_construct_cke_ecdhe(SSL *s, unsigned char **p, int *len, int *al)
 int tls_construct_client_key_exchange(SSL *s)
 {
     unsigned char *p;
-    int n;
+    int len;
     size_t pskhdrlen = 0;
     unsigned long alg_k;
     int al = -1;
@@ -2295,191 +2470,42 @@ int tls_construct_client_key_exchange(SSL *s)
 
     p = ssl_handshake_start(s);
 
-
-
     if ((alg_k & SSL_PSK)
             && !tls_construct_cke_psk_preamble(s, &p, &pskhdrlen, &al))
         goto err;
 
     if (alg_k & SSL_kPSK) {
-        n = 0;
+        len = 0;
     } else if (alg_k & (SSL_kRSA | SSL_kRSAPSK)) {
-        if (!tls_construct_cke_rsa(s, &p, &n, &al))
+        if (!tls_construct_cke_rsa(s, &p, &len, &al))
             goto err;
     } else if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) {
-        if (!tls_construct_cke_dhe(s, &p, &n, &al))
+        if (!tls_construct_cke_dhe(s, &p, &len, &al))
             goto err;
     } else if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) {
-        if (!tls_construct_cke_ecdhe(s, &p, &n, &al))
+        if (!tls_construct_cke_ecdhe(s, &p, &len, &al))
             goto err;
-    }
-#ifndef OPENSSL_NO_GOST
-    else if (alg_k & SSL_kGOST) {
-        /* GOST key exchange message creation */
-        EVP_PKEY_CTX *pkey_ctx;
-        X509 *peer_cert;
-        size_t msglen;
-        unsigned int md_len;
-        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;
-
-
-        /*
-         * Get server sertificate PKEY and create ctx from it
-         */
-        peer_cert = s->session->peer;
-        if (!peer_cert) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
-                   SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER);
+    } else if (alg_k & SSL_kGOST) {
+        if (!tls_construct_cke_gost(s, &p, &len, &al))
             goto err;
-        }
-
-        pkey_ctx = EVP_PKEY_CTX_new(X509_get0_pubkey(peer_cert), NULL);
-        if (pkey_ctx == NULL) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
-                   ERR_R_MALLOC_FAILURE);
+    } else if (alg_k & SSL_kSRP) {
+        if (!tls_construct_cke_srp(s, &p, &len, &al))
             goto err;
-        }
-        /*
-         * If we have send a certificate, and certificate key
-         * parameters match those of server certificate, use
-         * certificate key for key exchange
-         */
-
-        /* 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;
-        };
-        /*
-         * If we have client certificate, use its secret as peer key
-         */
-        if (s->s3->tmp.cert_req && s->cert->key->privatekey) {
-            if (EVP_PKEY_derive_set_peer
-                (pkey_ctx, s->cert->key->privatekey) <= 0) {
-                /*
-                 * If there was an error - just ignore it. Ephemeral key
-                 * * would be used
-                 */
-                ERR_clear_error();
-            }
-        }
-        /*
-         * Compute shared IV and store it in algorithm-specific context
-         * data
-         */
-        ukm_hash = EVP_MD_CTX_new();
-        if (EVP_DigestInit(ukm_hash,
-                           EVP_get_digestbynid(dgst_nid)) <= 0
-                || EVP_DigestUpdate(ukm_hash, s->s3->client_random,
-                                    SSL3_RANDOM_SIZE) <= 0
-                || EVP_DigestUpdate(ukm_hash, s->s3->server_random,
-                                    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;
-        }
-        EVP_MD_CTX_free(ukm_hash);
-        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;
-        }
-        /* Make GOST keytransport blob message */
-        /*
-         * Encapsulate it into sequence
-         */
-        *(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;
-        }
-        if (msglen >= 0x80) {
-            *(p++) = 0x81;
-            *(p++) = msglen & 0xff;
-            n = msglen + 3;
-        } else {
-            *(p++) = msglen & 0xff;
-            n = msglen + 2;
-        }
-        memcpy(p, tmp, msglen);
-        /* Check if pubkey from client certificate was used */
-        if (EVP_PKEY_CTX_ctrl
-            (pkey_ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 2, NULL) > 0) {
-            /* Set flag "skip certificate verify" */
-            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
-    else if (alg_k & SSL_kSRP) {
-        if (s->srp_ctx.A != NULL) {
-            /* send off the data */
-            n = BN_num_bytes(s->srp_ctx.A);
-            s2n(n, p);
-            BN_bn2bin(s->srp_ctx.A, p);
-            n += 2;
-        } else {
-            SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
-                   ERR_R_INTERNAL_ERROR);
-            goto err;
-        }
-        OPENSSL_free(s->session->srp_username);
-        s->session->srp_username = OPENSSL_strdup(s->srp_ctx.login);
-        if (s->session->srp_username == NULL) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
-                   ERR_R_MALLOC_FAILURE);
-            goto err;
-        }
-    }
-#endif
-    else {
+    } else {
         ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
         SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
         goto err;
     }
 
-    n += pskhdrlen;
+    len += pskhdrlen;
 
-    if (!ssl_set_handshake_header(s, SSL3_MT_CLIENT_KEY_EXCHANGE, n)) {
+    if (!ssl_set_handshake_header(s, SSL3_MT_CLIENT_KEY_EXCHANGE, len)) {
         ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
         SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
         goto err;
     }
 
     return 1;
- memerr:
-    SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
-    al = SSL_AD_INTERNAL_ERROR;
  err:
     if (al != -1)
         ssl3_send_alert(s, SSL3_AL_FATAL, al);