int ssl3_send_client_key_exchange(SSL *s)
{
    unsigned char *p;
    int n;
#ifndef OPENSSL_NO_PSK
    size_t pskhdrlen = 0;
#endif
    unsigned long alg_k;
#ifndef OPENSSL_NO_RSA
    unsigned char *q;
    EVP_PKEY *pkey = NULL;
#endif
#ifndef OPENSSL_NO_EC
    EC_KEY *clnt_ecdh = NULL;
    const EC_POINT *srvr_ecpoint = NULL;
    EVP_PKEY *srvr_pub_pkey = NULL;
    unsigned char *encodedPoint = NULL;
    int encoded_pt_len = 0;
    BN_CTX *bn_ctx = NULL;
#endif
    unsigned char *pms = NULL;
    size_t pmslen = 0;
    alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
    if (s->state == SSL3_ST_CW_KEY_EXCH_A) {
        p = ssl_handshake_start(s);
#ifndef OPENSSL_NO_PSK
        if (alg_k & SSL_PSK) {
            int psk_err = 1;
            char identity[PSK_MAX_IDENTITY_LEN + 1];
            size_t identitylen;
            unsigned char psk[PSK_MAX_PSK_LEN];
            size_t psklen;
            if (s->psk_client_callback == NULL) {
                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
                       SSL_R_PSK_NO_CLIENT_CB);
                goto err;
            }
            memset(identity, 0, sizeof(identity));
            psklen = s->psk_client_callback(s, s->session->psk_identity_hint,
                                            identity, sizeof(identity) - 1,
                                            psk, sizeof(psk));
            if (psklen > PSK_MAX_PSK_LEN) {
                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
                       ERR_R_INTERNAL_ERROR);
                goto psk_err;
            } else if (psklen == 0) {
                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
                       SSL_R_PSK_IDENTITY_NOT_FOUND);
                goto psk_err;
            }
            OPENSSL_free(s->s3->tmp.psk);
            s->s3->tmp.psk = BUF_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_SSL3_SEND_CLIENT_KEY_EXCHANGE,
                       ERR_R_INTERNAL_ERROR);
                goto psk_err;
            }
            OPENSSL_free(s->session->psk_identity);
            s->session->psk_identity = BUF_strdup(identity);
            if (s->session->psk_identity == NULL) {
                OPENSSL_cleanse(identity, sizeof(identity));
                goto memerr;
            }
            s2n(identitylen, p);
            memcpy(p, identity, identitylen);
            pskhdrlen = 2 + identitylen;
            p += identitylen;
            psk_err = 0;
 psk_err:
            OPENSSL_cleanse(identity, sizeof(identity));
            if (psk_err != 0) {
                ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
                goto err;
            }
        }
        if (alg_k & SSL_kPSK) {
            n = 0;
        } else
#endif
        if (0) {
        }
#ifndef OPENSSL_NO_RSA
        else if (alg_k & (SSL_kRSA | SSL_kRSAPSK)) {
            RSA *rsa;
            pmslen = SSL_MAX_MASTER_KEY_LENGTH;
            pms = OPENSSL_malloc(pmslen);
            if (!pms)
                goto memerr;
            if (s->session->peer == NULL) {
                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
                       ERR_R_INTERNAL_ERROR);
                goto err;
            }
            if (s->s3->peer_rsa_tmp != NULL)
                rsa = s->s3->peer_rsa_tmp;
            else {
                pkey = X509_get_pubkey(s->session->peer);
                if ((pkey == NULL) || (pkey->type != EVP_PKEY_RSA)
                    || (pkey->pkey.rsa == NULL)) {
                    SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
                           ERR_R_INTERNAL_ERROR);
                    EVP_PKEY_free(pkey);
                    goto err;
                }
                rsa = pkey->pkey.rsa;
                EVP_PKEY_free(pkey);
            }
            pms[0] = s->client_version >> 8;
            pms[1] = s->client_version & 0xff;
            if (RAND_bytes(pms + 2, pmslen - 2) <= 0)
                goto err;
            q = p;
            if (s->version > SSL3_VERSION)
                p += 2;
            n = RSA_public_encrypt(pmslen, pms, p, rsa, RSA_PKCS1_PADDING);
# ifdef PKCS1_CHECK
            if (s->options & SSL_OP_PKCS1_CHECK_1)
                p[1]++;
            if (s->options & SSL_OP_PKCS1_CHECK_2)
                tmp_buf[0] = 0x70;
# endif
            if (n <= 0) {
                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
                       SSL_R_BAD_RSA_ENCRYPT);
                goto err;
            }
            if (s->version > SSL3_VERSION) {
                s2n(n, q);
                n += 2;
            }
        }
#endif
#ifndef OPENSSL_NO_DH
        else if (alg_k & (SSL_kDHE | SSL_kDHr | SSL_kDHd | SSL_kDHEPSK)) {
            DH *dh_srvr, *dh_clnt;
            if (s->s3->peer_dh_tmp != NULL)
                dh_srvr = s->s3->peer_dh_tmp;
            else {
                EVP_PKEY *spkey = NULL;
                dh_srvr = NULL;
                spkey = X509_get_pubkey(s->session->peer);
                if (spkey) {
                    dh_srvr = EVP_PKEY_get1_DH(spkey);
                    EVP_PKEY_free(spkey);
                }
                if (dh_srvr == NULL) {
                    SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
                           ERR_R_INTERNAL_ERROR);
                    goto err;
                }
            }
            if (s->s3->flags & TLS1_FLAGS_SKIP_CERT_VERIFY) {
                EVP_PKEY *clkey = s->cert->key->privatekey;
                dh_clnt = NULL;
                if (clkey)
                    dh_clnt = EVP_PKEY_get1_DH(clkey);
                if (dh_clnt == NULL) {
                    SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
                           ERR_R_INTERNAL_ERROR);
                    goto err;
                }
            } else {
                if ((dh_clnt = DHparams_dup(dh_srvr)) == NULL) {
                    SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_DH_LIB);
                    goto err;
                }
                if (!DH_generate_key(dh_clnt)) {
                    SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_DH_LIB);
                    DH_free(dh_clnt);
                    goto err;
                }
            }
            pmslen = DH_size(dh_clnt);
            pms = OPENSSL_malloc(pmslen);
            if (!pms)
                goto memerr;
            n = DH_compute_key(pms, dh_srvr->pub_key, dh_clnt);
            if (s->s3->peer_dh_tmp == NULL)
                DH_free(dh_srvr);
            if (n <= 0) {
                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_DH_LIB);
                DH_free(dh_clnt);
                goto err;
            }
            pmslen = n;
            if (s->s3->flags & TLS1_FLAGS_SKIP_CERT_VERIFY)
                n = 0;
            else {
                n = BN_num_bytes(dh_clnt->pub_key);
                s2n(n, p);
                BN_bn2bin(dh_clnt->pub_key, p);
                n += 2;
            }
            DH_free(dh_clnt);
        }
#endif
#ifndef OPENSSL_NO_EC
        else if (alg_k & (SSL_kECDHE | SSL_kECDHr | SSL_kECDHe | SSL_kECDHEPSK)) {
            const EC_GROUP *srvr_group = NULL;
            EC_KEY *tkey;
            int ecdh_clnt_cert = 0;
            int field_size = 0;
            if ((alg_k & (SSL_kECDHr | SSL_kECDHe)) && (s->cert != NULL)) {
            }
            if (s->s3->peer_ecdh_tmp != NULL) {
                tkey = s->s3->peer_ecdh_tmp;
            } else {
                srvr_pub_pkey = X509_get_pubkey(s->session->peer);
                if ((srvr_pub_pkey == NULL)
                    || (srvr_pub_pkey->type != EVP_PKEY_EC)
                    || (srvr_pub_pkey->pkey.ec == NULL)) {
                    SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
                           ERR_R_INTERNAL_ERROR);
                    goto err;
                }
                tkey = srvr_pub_pkey->pkey.ec;
            }
            srvr_group = EC_KEY_get0_group(tkey);
            srvr_ecpoint = EC_KEY_get0_public_key(tkey);
            if ((srvr_group == NULL) || (srvr_ecpoint == NULL)) {
                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
                       ERR_R_INTERNAL_ERROR);
                goto err;
            }
            if ((clnt_ecdh = EC_KEY_new()) == NULL) {
                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
                       ERR_R_MALLOC_FAILURE);
                goto err;
            }
            if (!EC_KEY_set_group(clnt_ecdh, srvr_group)) {
                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_EC_LIB);
                goto err;
            }
            if (ecdh_clnt_cert) {
                const BIGNUM *priv_key;
                tkey = s->cert->key->privatekey->pkey.ec;
                priv_key = EC_KEY_get0_private_key(tkey);
                if (priv_key == NULL) {
                    SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
                           ERR_R_MALLOC_FAILURE);
                    goto err;
                }
                if (!EC_KEY_set_private_key(clnt_ecdh, priv_key)) {
                    SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_EC_LIB);
                    goto err;
                }
            } else {
                if (!(EC_KEY_generate_key(clnt_ecdh))) {
                    SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
                           ERR_R_ECDH_LIB);
                    goto err;
                }
            }
            field_size = EC_GROUP_get_degree(srvr_group);
            if (field_size <= 0) {
                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_ECDH_LIB);
                goto err;
            }
            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;
            }
            if (ecdh_clnt_cert) {
                n = 0;
            } else {
                encoded_pt_len =
                    EC_POINT_point2oct(srvr_group,
                                       EC_KEY_get0_public_key(clnt_ecdh),
                                       POINT_CONVERSION_UNCOMPRESSED,
                                       NULL, 0, NULL);
                encodedPoint = (unsigned char *)
                    OPENSSL_malloc(encoded_pt_len * sizeof(unsigned char));
                bn_ctx = BN_CTX_new();
                if ((encodedPoint == NULL) || (bn_ctx == NULL)) {
                    SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
                           ERR_R_MALLOC_FAILURE);
                    goto err;
                }
                n = EC_POINT_point2oct(srvr_group,
                                       EC_KEY_get0_public_key(clnt_ecdh),
                                       POINT_CONVERSION_UNCOMPRESSED,
                                       encodedPoint, encoded_pt_len, bn_ctx);
                *p = n;
                p += 1;
                memcpy(p, encodedPoint, n);
                n += 1;
            }
            BN_CTX_free(bn_ctx);
            OPENSSL_free(encodedPoint);
            EC_KEY_free(clnt_ecdh);
            EVP_PKEY_free(srvr_pub_pkey);
        }
#endif
        else if (alg_k & SSL_kGOST) {
            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;
            EVP_PKEY *pub_key;
            pmslen = 32;
            pms = OPENSSL_malloc(pmslen);
            if (!pms)
                goto memerr;
            peer_cert = s->session->peer;
            if (!peer_cert) {
                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
                       SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER);
                goto err;
            }
            pkey_ctx = EVP_PKEY_CTX_new(pub_key =
                                        X509_get_pubkey(peer_cert), NULL);
            EVP_PKEY_encrypt_init(pkey_ctx);
            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 (s->s3->tmp.cert_req && s->cert->key->privatekey) {
                if (EVP_PKEY_derive_set_peer
                    (pkey_ctx, s->cert->key->privatekey) <= 0) {
                    ERR_clear_error();
                }
            }
            ukm_hash = EVP_MD_CTX_create();
            EVP_DigestInit(ukm_hash,
                           EVP_get_digestbynid(NID_id_GostR3411_94));
            EVP_DigestUpdate(ukm_hash, s->s3->client_random,
                             SSL3_RANDOM_SIZE);
            EVP_DigestUpdate(ukm_hash, s->s3->server_random,
                             SSL3_RANDOM_SIZE);
            EVP_DigestFinal_ex(ukm_hash, shared_ukm, &md_len);
            EVP_MD_CTX_destroy(ukm_hash);
            if (EVP_PKEY_CTX_ctrl
                (pkey_ctx, -1, EVP_PKEY_OP_ENCRYPT, EVP_PKEY_CTRL_SET_IV, 8,
                 shared_ukm) < 0) {
                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
                       SSL_R_LIBRARY_BUG);
                goto err;
            }
            *(p++) = V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED;
            msglen = 255;
            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;
            }
            if (msglen >= 0x80) {
                *(p++) = 0x81;
                *(p++) = msglen & 0xff;
                n = msglen + 3;
            } else {
                *(p++) = msglen & 0xff;
                n = msglen + 2;
            }
            memcpy(p, tmp, msglen);
            if (EVP_PKEY_CTX_ctrl
                (pkey_ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 2, NULL) > 0) {
                s->s3->flags |= TLS1_FLAGS_SKIP_CERT_VERIFY;
            }
            EVP_PKEY_CTX_free(pkey_ctx);
            EVP_PKEY_free(pub_key);
        }
#ifndef OPENSSL_NO_SRP
        else if (alg_k & SSL_kSRP) {
            if (s->srp_ctx.A != NULL) {
                n = BN_num_bytes(s->srp_ctx.A);
                s2n(n, p);
                BN_bn2bin(s->srp_ctx.A, p);
                n += 2;
            } else {
                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
                       ERR_R_INTERNAL_ERROR);
                goto err;
            }
            OPENSSL_free(s->session->srp_username);
            s->session->srp_username = BUF_strdup(s->srp_ctx.login);
            if (s->session->srp_username == NULL) {
                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
                       ERR_R_MALLOC_FAILURE);
                goto err;
            }
        }
#endif
        else {
            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;
        }
#ifndef OPENSSL_NO_PSK
        n += pskhdrlen;
#endif
        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;
    }
    n = ssl_do_write(s);
#ifndef OPENSSL_NO_SRP
    if (alg_k & SSL_kSRP) {
        if (n > 0) {
            if (!srp_generate_client_master_secret(s)) {
                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
                       ERR_R_INTERNAL_ERROR);
                goto err;
            }
        }
    } else
#endif
    if (n <= 0) {
        s->s3->tmp.pms = pms;
        s->s3->tmp.pmslen = pmslen;
    } else {
        if (pms == NULL) {
            pms = s->s3->tmp.pms;
            pmslen = s->s3->tmp.pmslen;
        }
        if (pms == NULL && !(alg_k & SSL_kPSK)) {
            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;
        }
        if (!ssl_generate_master_secret(s, pms, pmslen, 1)) {
            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:
    OPENSSL_clear_free(pms, pmslen);
    s->s3->tmp.pms = NULL;
#ifndef OPENSSL_NO_EC
    BN_CTX_free(bn_ctx);
    OPENSSL_free(encodedPoint);
    EC_KEY_free(clnt_ecdh);
    EVP_PKEY_free(srvr_pub_pkey);
#endif
#ifndef OPENSSL_NO_PSK
    OPENSSL_clear_free(s->s3->tmp.psk, s->s3->tmp.psklen);
    s->s3->tmp.psk = NULL;
#endif
    s->state = SSL_ST_ERR;
    return (-1);
}
['int ssl3_send_client_key_exchange(SSL *s)\n{\n    unsigned char *p;\n    int n;\n#ifndef OPENSSL_NO_PSK\n    size_t pskhdrlen = 0;\n#endif\n    unsigned long alg_k;\n#ifndef OPENSSL_NO_RSA\n    unsigned char *q;\n    EVP_PKEY *pkey = NULL;\n#endif\n#ifndef OPENSSL_NO_EC\n    EC_KEY *clnt_ecdh = NULL;\n    const EC_POINT *srvr_ecpoint = NULL;\n    EVP_PKEY *srvr_pub_pkey = NULL;\n    unsigned char *encodedPoint = NULL;\n    int encoded_pt_len = 0;\n    BN_CTX *bn_ctx = NULL;\n#endif\n    unsigned char *pms = NULL;\n    size_t pmslen = 0;\n    alg_k = s->s3->tmp.new_cipher->algorithm_mkey;\n    if (s->state == SSL3_ST_CW_KEY_EXCH_A) {\n        p = ssl_handshake_start(s);\n#ifndef OPENSSL_NO_PSK\n        if (alg_k & SSL_PSK) {\n            int psk_err = 1;\n            char identity[PSK_MAX_IDENTITY_LEN + 1];\n            size_t identitylen;\n            unsigned char psk[PSK_MAX_PSK_LEN];\n            size_t psklen;\n            if (s->psk_client_callback == NULL) {\n                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,\n                       SSL_R_PSK_NO_CLIENT_CB);\n                goto err;\n            }\n            memset(identity, 0, sizeof(identity));\n            psklen = s->psk_client_callback(s, s->session->psk_identity_hint,\n                                            identity, sizeof(identity) - 1,\n                                            psk, sizeof(psk));\n            if (psklen > PSK_MAX_PSK_LEN) {\n                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,\n                       ERR_R_INTERNAL_ERROR);\n                goto psk_err;\n            } else if (psklen == 0) {\n                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,\n                       SSL_R_PSK_IDENTITY_NOT_FOUND);\n                goto psk_err;\n            }\n            OPENSSL_free(s->s3->tmp.psk);\n            s->s3->tmp.psk = BUF_memdup(psk, psklen);\n            OPENSSL_cleanse(psk, psklen);\n            if (s->s3->tmp.psk == NULL) {\n                OPENSSL_cleanse(identity, sizeof(identity));\n                goto memerr;\n            }\n            s->s3->tmp.psklen = psklen;\n            identitylen = strlen(identity);\n            if (identitylen > PSK_MAX_IDENTITY_LEN) {\n                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,\n                       ERR_R_INTERNAL_ERROR);\n                goto psk_err;\n            }\n            OPENSSL_free(s->session->psk_identity);\n            s->session->psk_identity = BUF_strdup(identity);\n            if (s->session->psk_identity == NULL) {\n                OPENSSL_cleanse(identity, sizeof(identity));\n                goto memerr;\n            }\n            s2n(identitylen, p);\n            memcpy(p, identity, identitylen);\n            pskhdrlen = 2 + identitylen;\n            p += identitylen;\n            psk_err = 0;\n psk_err:\n            OPENSSL_cleanse(identity, sizeof(identity));\n            if (psk_err != 0) {\n                ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);\n                goto err;\n            }\n        }\n        if (alg_k & SSL_kPSK) {\n            n = 0;\n        } else\n#endif\n        if (0) {\n        }\n#ifndef OPENSSL_NO_RSA\n        else if (alg_k & (SSL_kRSA | SSL_kRSAPSK)) {\n            RSA *rsa;\n            pmslen = SSL_MAX_MASTER_KEY_LENGTH;\n            pms = OPENSSL_malloc(pmslen);\n            if (!pms)\n                goto memerr;\n            if (s->session->peer == NULL) {\n                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,\n                       ERR_R_INTERNAL_ERROR);\n                goto err;\n            }\n            if (s->s3->peer_rsa_tmp != NULL)\n                rsa = s->s3->peer_rsa_tmp;\n            else {\n                pkey = X509_get_pubkey(s->session->peer);\n                if ((pkey == NULL) || (pkey->type != EVP_PKEY_RSA)\n                    || (pkey->pkey.rsa == NULL)) {\n                    SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,\n                           ERR_R_INTERNAL_ERROR);\n                    EVP_PKEY_free(pkey);\n                    goto err;\n                }\n                rsa = pkey->pkey.rsa;\n                EVP_PKEY_free(pkey);\n            }\n            pms[0] = s->client_version >> 8;\n            pms[1] = s->client_version & 0xff;\n            if (RAND_bytes(pms + 2, pmslen - 2) <= 0)\n                goto err;\n            q = p;\n            if (s->version > SSL3_VERSION)\n                p += 2;\n            n = RSA_public_encrypt(pmslen, pms, p, rsa, RSA_PKCS1_PADDING);\n# ifdef PKCS1_CHECK\n            if (s->options & SSL_OP_PKCS1_CHECK_1)\n                p[1]++;\n            if (s->options & SSL_OP_PKCS1_CHECK_2)\n                tmp_buf[0] = 0x70;\n# endif\n            if (n <= 0) {\n                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,\n                       SSL_R_BAD_RSA_ENCRYPT);\n                goto err;\n            }\n            if (s->version > SSL3_VERSION) {\n                s2n(n, q);\n                n += 2;\n            }\n        }\n#endif\n#ifndef OPENSSL_NO_DH\n        else if (alg_k & (SSL_kDHE | SSL_kDHr | SSL_kDHd | SSL_kDHEPSK)) {\n            DH *dh_srvr, *dh_clnt;\n            if (s->s3->peer_dh_tmp != NULL)\n                dh_srvr = s->s3->peer_dh_tmp;\n            else {\n                EVP_PKEY *spkey = NULL;\n                dh_srvr = NULL;\n                spkey = X509_get_pubkey(s->session->peer);\n                if (spkey) {\n                    dh_srvr = EVP_PKEY_get1_DH(spkey);\n                    EVP_PKEY_free(spkey);\n                }\n                if (dh_srvr == NULL) {\n                    SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,\n                           ERR_R_INTERNAL_ERROR);\n                    goto err;\n                }\n            }\n            if (s->s3->flags & TLS1_FLAGS_SKIP_CERT_VERIFY) {\n                EVP_PKEY *clkey = s->cert->key->privatekey;\n                dh_clnt = NULL;\n                if (clkey)\n                    dh_clnt = EVP_PKEY_get1_DH(clkey);\n                if (dh_clnt == NULL) {\n                    SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,\n                           ERR_R_INTERNAL_ERROR);\n                    goto err;\n                }\n            } else {\n                if ((dh_clnt = DHparams_dup(dh_srvr)) == NULL) {\n                    SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_DH_LIB);\n                    goto err;\n                }\n                if (!DH_generate_key(dh_clnt)) {\n                    SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_DH_LIB);\n                    DH_free(dh_clnt);\n                    goto err;\n                }\n            }\n            pmslen = DH_size(dh_clnt);\n            pms = OPENSSL_malloc(pmslen);\n            if (!pms)\n                goto memerr;\n            n = DH_compute_key(pms, dh_srvr->pub_key, dh_clnt);\n            if (s->s3->peer_dh_tmp == NULL)\n                DH_free(dh_srvr);\n            if (n <= 0) {\n                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_DH_LIB);\n                DH_free(dh_clnt);\n                goto err;\n            }\n            pmslen = n;\n            if (s->s3->flags & TLS1_FLAGS_SKIP_CERT_VERIFY)\n                n = 0;\n            else {\n                n = BN_num_bytes(dh_clnt->pub_key);\n                s2n(n, p);\n                BN_bn2bin(dh_clnt->pub_key, p);\n                n += 2;\n            }\n            DH_free(dh_clnt);\n        }\n#endif\n#ifndef OPENSSL_NO_EC\n        else if (alg_k & (SSL_kECDHE | SSL_kECDHr | SSL_kECDHe | SSL_kECDHEPSK)) {\n            const EC_GROUP *srvr_group = NULL;\n            EC_KEY *tkey;\n            int ecdh_clnt_cert = 0;\n            int field_size = 0;\n            if ((alg_k & (SSL_kECDHr | SSL_kECDHe)) && (s->cert != NULL)) {\n            }\n            if (s->s3->peer_ecdh_tmp != NULL) {\n                tkey = s->s3->peer_ecdh_tmp;\n            } else {\n                srvr_pub_pkey = X509_get_pubkey(s->session->peer);\n                if ((srvr_pub_pkey == NULL)\n                    || (srvr_pub_pkey->type != EVP_PKEY_EC)\n                    || (srvr_pub_pkey->pkey.ec == NULL)) {\n                    SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,\n                           ERR_R_INTERNAL_ERROR);\n                    goto err;\n                }\n                tkey = srvr_pub_pkey->pkey.ec;\n            }\n            srvr_group = EC_KEY_get0_group(tkey);\n            srvr_ecpoint = EC_KEY_get0_public_key(tkey);\n            if ((srvr_group == NULL) || (srvr_ecpoint == NULL)) {\n                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,\n                       ERR_R_INTERNAL_ERROR);\n                goto err;\n            }\n            if ((clnt_ecdh = EC_KEY_new()) == NULL) {\n                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,\n                       ERR_R_MALLOC_FAILURE);\n                goto err;\n            }\n            if (!EC_KEY_set_group(clnt_ecdh, srvr_group)) {\n                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_EC_LIB);\n                goto err;\n            }\n            if (ecdh_clnt_cert) {\n                const BIGNUM *priv_key;\n                tkey = s->cert->key->privatekey->pkey.ec;\n                priv_key = EC_KEY_get0_private_key(tkey);\n                if (priv_key == NULL) {\n                    SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,\n                           ERR_R_MALLOC_FAILURE);\n                    goto err;\n                }\n                if (!EC_KEY_set_private_key(clnt_ecdh, priv_key)) {\n                    SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_EC_LIB);\n                    goto err;\n                }\n            } else {\n                if (!(EC_KEY_generate_key(clnt_ecdh))) {\n                    SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,\n                           ERR_R_ECDH_LIB);\n                    goto err;\n                }\n            }\n            field_size = EC_GROUP_get_degree(srvr_group);\n            if (field_size <= 0) {\n                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_ECDH_LIB);\n                goto err;\n            }\n            pmslen = (field_size + 7) / 8;\n            pms = OPENSSL_malloc(pmslen);\n            if (!pms)\n                goto memerr;\n            n = ECDH_compute_key(pms, pmslen, srvr_ecpoint, clnt_ecdh, NULL);\n            if (n <= 0 || pmslen != (size_t)n) {\n                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_ECDH_LIB);\n                goto err;\n            }\n            if (ecdh_clnt_cert) {\n                n = 0;\n            } else {\n                encoded_pt_len =\n                    EC_POINT_point2oct(srvr_group,\n                                       EC_KEY_get0_public_key(clnt_ecdh),\n                                       POINT_CONVERSION_UNCOMPRESSED,\n                                       NULL, 0, NULL);\n                encodedPoint = (unsigned char *)\n                    OPENSSL_malloc(encoded_pt_len * sizeof(unsigned char));\n                bn_ctx = BN_CTX_new();\n                if ((encodedPoint == NULL) || (bn_ctx == NULL)) {\n                    SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,\n                           ERR_R_MALLOC_FAILURE);\n                    goto err;\n                }\n                n = EC_POINT_point2oct(srvr_group,\n                                       EC_KEY_get0_public_key(clnt_ecdh),\n                                       POINT_CONVERSION_UNCOMPRESSED,\n                                       encodedPoint, encoded_pt_len, bn_ctx);\n                *p = n;\n                p += 1;\n                memcpy(p, encodedPoint, n);\n                n += 1;\n            }\n            BN_CTX_free(bn_ctx);\n            OPENSSL_free(encodedPoint);\n            EC_KEY_free(clnt_ecdh);\n            EVP_PKEY_free(srvr_pub_pkey);\n        }\n#endif\n        else if (alg_k & SSL_kGOST) {\n            EVP_PKEY_CTX *pkey_ctx;\n            X509 *peer_cert;\n            size_t msglen;\n            unsigned int md_len;\n            unsigned char shared_ukm[32], tmp[256];\n            EVP_MD_CTX *ukm_hash;\n            EVP_PKEY *pub_key;\n            pmslen = 32;\n            pms = OPENSSL_malloc(pmslen);\n            if (!pms)\n                goto memerr;\n            peer_cert = s->session->peer;\n            if (!peer_cert) {\n                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,\n                       SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER);\n                goto err;\n            }\n            pkey_ctx = EVP_PKEY_CTX_new(pub_key =\n                                        X509_get_pubkey(peer_cert), NULL);\n            EVP_PKEY_encrypt_init(pkey_ctx);\n            if (RAND_bytes(pms, pmslen) <= 0) {\n                EVP_PKEY_CTX_free(pkey_ctx);\n                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,\n                       ERR_R_INTERNAL_ERROR);\n                goto err;\n            };\n            if (s->s3->tmp.cert_req && s->cert->key->privatekey) {\n                if (EVP_PKEY_derive_set_peer\n                    (pkey_ctx, s->cert->key->privatekey) <= 0) {\n                    ERR_clear_error();\n                }\n            }\n            ukm_hash = EVP_MD_CTX_create();\n            EVP_DigestInit(ukm_hash,\n                           EVP_get_digestbynid(NID_id_GostR3411_94));\n            EVP_DigestUpdate(ukm_hash, s->s3->client_random,\n                             SSL3_RANDOM_SIZE);\n            EVP_DigestUpdate(ukm_hash, s->s3->server_random,\n                             SSL3_RANDOM_SIZE);\n            EVP_DigestFinal_ex(ukm_hash, shared_ukm, &md_len);\n            EVP_MD_CTX_destroy(ukm_hash);\n            if (EVP_PKEY_CTX_ctrl\n                (pkey_ctx, -1, EVP_PKEY_OP_ENCRYPT, EVP_PKEY_CTRL_SET_IV, 8,\n                 shared_ukm) < 0) {\n                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,\n                       SSL_R_LIBRARY_BUG);\n                goto err;\n            }\n            *(p++) = V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED;\n            msglen = 255;\n            if (EVP_PKEY_encrypt(pkey_ctx, tmp, &msglen, pms, pmslen) < 0) {\n                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,\n                       SSL_R_LIBRARY_BUG);\n                goto err;\n            }\n            if (msglen >= 0x80) {\n                *(p++) = 0x81;\n                *(p++) = msglen & 0xff;\n                n = msglen + 3;\n            } else {\n                *(p++) = msglen & 0xff;\n                n = msglen + 2;\n            }\n            memcpy(p, tmp, msglen);\n            if (EVP_PKEY_CTX_ctrl\n                (pkey_ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 2, NULL) > 0) {\n                s->s3->flags |= TLS1_FLAGS_SKIP_CERT_VERIFY;\n            }\n            EVP_PKEY_CTX_free(pkey_ctx);\n            EVP_PKEY_free(pub_key);\n        }\n#ifndef OPENSSL_NO_SRP\n        else if (alg_k & SSL_kSRP) {\n            if (s->srp_ctx.A != NULL) {\n                n = BN_num_bytes(s->srp_ctx.A);\n                s2n(n, p);\n                BN_bn2bin(s->srp_ctx.A, p);\n                n += 2;\n            } else {\n                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,\n                       ERR_R_INTERNAL_ERROR);\n                goto err;\n            }\n            OPENSSL_free(s->session->srp_username);\n            s->session->srp_username = BUF_strdup(s->srp_ctx.login);\n            if (s->session->srp_username == NULL) {\n                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,\n                       ERR_R_MALLOC_FAILURE);\n                goto err;\n            }\n        }\n#endif\n        else {\n            ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);\n            SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);\n            goto err;\n        }\n#ifndef OPENSSL_NO_PSK\n        n += pskhdrlen;\n#endif\n        if (!ssl_set_handshake_header(s, SSL3_MT_CLIENT_KEY_EXCHANGE, n)) {\n            ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);\n            SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);\n            goto err;\n        }\n        s->state = SSL3_ST_CW_KEY_EXCH_B;\n    }\n    n = ssl_do_write(s);\n#ifndef OPENSSL_NO_SRP\n    if (alg_k & SSL_kSRP) {\n        if (n > 0) {\n            if (!srp_generate_client_master_secret(s)) {\n                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,\n                       ERR_R_INTERNAL_ERROR);\n                goto err;\n            }\n        }\n    } else\n#endif\n    if (n <= 0) {\n        s->s3->tmp.pms = pms;\n        s->s3->tmp.pmslen = pmslen;\n    } else {\n        if (pms == NULL) {\n            pms = s->s3->tmp.pms;\n            pmslen = s->s3->tmp.pmslen;\n        }\n        if (pms == NULL && !(alg_k & SSL_kPSK)) {\n            ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);\n            SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);\n            goto err;\n        }\n        if (!ssl_generate_master_secret(s, pms, pmslen, 1)) {\n            ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);\n            SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);\n            goto err;\n        }\n    }\n    return n;\n memerr:\n    ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);\n    SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);\n err:\n    OPENSSL_clear_free(pms, pmslen);\n    s->s3->tmp.pms = NULL;\n#ifndef OPENSSL_NO_EC\n    BN_CTX_free(bn_ctx);\n    OPENSSL_free(encodedPoint);\n    EC_KEY_free(clnt_ecdh);\n    EVP_PKEY_free(srvr_pub_pkey);\n#endif\n#ifndef OPENSSL_NO_PSK\n    OPENSSL_clear_free(s->s3->tmp.psk, s->s3->tmp.psklen);\n    s->s3->tmp.psk = NULL;\n#endif\n    s->state = SSL_ST_ERR;\n    return (-1);\n}']