static int ssl3_send_client_key_exchange(SSL *s)
	{
	unsigned char *p,*d;
	int n;
	unsigned long l;
#ifndef NO_RSA
	unsigned char *q;
	EVP_PKEY *pkey=NULL;
#endif
#ifndef NO_KRB5
        KSSL_ERR kssl_err;
#endif
	if (s->state == SSL3_ST_CW_KEY_EXCH_A)
		{
		d=(unsigned char *)s->init_buf->data;
		p= &(d[4]);
		l=s->s3->tmp.new_cipher->algorithms;
                if (0) {}
#ifndef NO_RSA
		else if (l & SSL_kRSA)
			{
			RSA *rsa;
			unsigned char tmp_buf[SSL_MAX_MASTER_KEY_LENGTH];
			if (s->session->sess_cert->peer_rsa_tmp != NULL)
				rsa=s->session->sess_cert->peer_rsa_tmp;
			else
				{
				pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
				if ((pkey == NULL) ||
					(pkey->type != EVP_PKEY_RSA) ||
					(pkey->pkey.rsa == NULL))
					{
					SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_INTERNAL_ERROR);
					goto err;
					}
				rsa=pkey->pkey.rsa;
				EVP_PKEY_free(pkey);
				}
			tmp_buf[0]=s->client_version>>8;
			tmp_buf[1]=s->client_version&0xff;
			if (RAND_bytes(&(tmp_buf[2]),SSL_MAX_MASTER_KEY_LENGTH-2) <= 0)
					goto err;
			s->session->master_key_length=SSL_MAX_MASTER_KEY_LENGTH;
			q=p;
			if (s->version > SSL3_VERSION)
				p+=2;
			n=RSA_public_encrypt(SSL_MAX_MASTER_KEY_LENGTH,
				tmp_buf,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;
				}
			s->session->master_key_length=
				s->method->ssl3_enc->generate_master_secret(s,
					s->session->master_key,
					tmp_buf,SSL_MAX_MASTER_KEY_LENGTH);
			memset(tmp_buf,0,SSL_MAX_MASTER_KEY_LENGTH);
			}
#endif
#ifndef NO_KRB5
		else if (l & SSL_kKRB5)
                        {
                        krb5_error_code	krb5rc;
                        KSSL_CTX	*kssl_ctx = s->kssl_ctx;
                        krb5_data	krb5_ap_req;
#ifdef KSSL_DEBUG
                        printf("ssl3_send_client_key_exchange(%lx & %lx)\n",
                                l, SSL_kKRB5);
#endif
                        krb5rc = kssl_cget_tkt(kssl_ctx, &krb5_ap_req,
                                &kssl_err);
#ifdef KSSL_DEBUG
                        {
                        printf("kssl_cget_tkt rtn %d\n", krb5rc);
                        kssl_ctx_show(kssl_ctx);
                        if (krb5rc && kssl_err.text)
                                printf("kssl_cget_tkt kssl_err=%s\n", kssl_err.text);
                        }
#endif
                        if (krb5rc)
                                {
                                ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
                                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, kssl_err.reason);
                                goto err;
                                }
                        n = krb5_ap_req.length;
                        memcpy(p, krb5_ap_req.data, krb5_ap_req.length);
                        if (krb5_ap_req.data)
                                kssl_krb5_free_data_contents(NULL,&krb5_ap_req);
                        s->session->master_key_length=
                                s->method->ssl3_enc->generate_master_secret(s,
                                        s->session->master_key,	kssl_ctx->key,kssl_ctx->length);
                        }
#endif
#ifndef NO_DH
		else if (l & (SSL_kEDH|SSL_kDHr|SSL_kDHd))
			{
			DH *dh_srvr,*dh_clnt;
			if (s->session->sess_cert->peer_dh_tmp != NULL)
				dh_srvr=s->session->sess_cert->peer_dh_tmp;
			else
				{
				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_UNABLE_TO_FIND_DH_PARAMETERS);
				goto err;
				}
			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);
				goto err;
				}
			n=DH_compute_key(p,dh_srvr->pub_key,dh_clnt);
			if (n <= 0)
				{
				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB);
				goto err;
				}
			s->session->master_key_length=
				s->method->ssl3_enc->generate_master_secret(s,
					s->session->master_key,p,n);
			memset(p,0,n);
			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
		else
			{
			ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
			SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_INTERNAL_ERROR);
			goto err;
			}
		*(d++)=SSL3_MT_CLIENT_KEY_EXCHANGE;
		l2n3(n,d);
		s->state=SSL3_ST_CW_KEY_EXCH_B;
		s->init_num=n+4;
		s->init_off=0;
		}
	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
err:
	return(-1);
	}
['static int ssl3_send_client_key_exchange(SSL *s)\n\t{\n\tunsigned char *p,*d;\n\tint n;\n\tunsigned long l;\n#ifndef NO_RSA\n\tunsigned char *q;\n\tEVP_PKEY *pkey=NULL;\n#endif\n#ifndef NO_KRB5\n        KSSL_ERR kssl_err;\n#endif\n\tif (s->state == SSL3_ST_CW_KEY_EXCH_A)\n\t\t{\n\t\td=(unsigned char *)s->init_buf->data;\n\t\tp= &(d[4]);\n\t\tl=s->s3->tmp.new_cipher->algorithms;\n                if (0) {}\n#ifndef NO_RSA\n\t\telse if (l & SSL_kRSA)\n\t\t\t{\n\t\t\tRSA *rsa;\n\t\t\tunsigned char tmp_buf[SSL_MAX_MASTER_KEY_LENGTH];\n\t\t\tif (s->session->sess_cert->peer_rsa_tmp != NULL)\n\t\t\t\trsa=s->session->sess_cert->peer_rsa_tmp;\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tpkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);\n\t\t\t\tif ((pkey == NULL) ||\n\t\t\t\t\t(pkey->type != EVP_PKEY_RSA) ||\n\t\t\t\t\t(pkey->pkey.rsa == NULL))\n\t\t\t\t\t{\n\t\t\t\t\tSSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_INTERNAL_ERROR);\n\t\t\t\t\tgoto err;\n\t\t\t\t\t}\n\t\t\t\trsa=pkey->pkey.rsa;\n\t\t\t\tEVP_PKEY_free(pkey);\n\t\t\t\t}\n\t\t\ttmp_buf[0]=s->client_version>>8;\n\t\t\ttmp_buf[1]=s->client_version&0xff;\n\t\t\tif (RAND_bytes(&(tmp_buf[2]),SSL_MAX_MASTER_KEY_LENGTH-2) <= 0)\n\t\t\t\t\tgoto err;\n\t\t\ts->session->master_key_length=SSL_MAX_MASTER_KEY_LENGTH;\n\t\t\tq=p;\n\t\t\tif (s->version > SSL3_VERSION)\n\t\t\t\tp+=2;\n\t\t\tn=RSA_public_encrypt(SSL_MAX_MASTER_KEY_LENGTH,\n\t\t\t\ttmp_buf,p,rsa,RSA_PKCS1_PADDING);\n#ifdef PKCS1_CHECK\n\t\t\tif (s->options & SSL_OP_PKCS1_CHECK_1) p[1]++;\n\t\t\tif (s->options & SSL_OP_PKCS1_CHECK_2) tmp_buf[0]=0x70;\n#endif\n\t\t\tif (n <= 0)\n\t\t\t\t{\n\t\t\t\tSSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_BAD_RSA_ENCRYPT);\n\t\t\t\tgoto err;\n\t\t\t\t}\n\t\t\tif (s->version > SSL3_VERSION)\n\t\t\t\t{\n\t\t\t\ts2n(n,q);\n\t\t\t\tn+=2;\n\t\t\t\t}\n\t\t\ts->session->master_key_length=\n\t\t\t\ts->method->ssl3_enc->generate_master_secret(s,\n\t\t\t\t\ts->session->master_key,\n\t\t\t\t\ttmp_buf,SSL_MAX_MASTER_KEY_LENGTH);\n\t\t\tmemset(tmp_buf,0,SSL_MAX_MASTER_KEY_LENGTH);\n\t\t\t}\n#endif\n#ifndef NO_KRB5\n\t\telse if (l & SSL_kKRB5)\n                        {\n                        krb5_error_code\tkrb5rc;\n                        KSSL_CTX\t*kssl_ctx = s->kssl_ctx;\n                        krb5_data\tkrb5_ap_req;\n#ifdef KSSL_DEBUG\n                        printf("ssl3_send_client_key_exchange(%lx & %lx)\\n",\n                                l, SSL_kKRB5);\n#endif\n                        krb5rc = kssl_cget_tkt(kssl_ctx, &krb5_ap_req,\n                                &kssl_err);\n#ifdef KSSL_DEBUG\n                        {\n                        printf("kssl_cget_tkt rtn %d\\n", krb5rc);\n                        kssl_ctx_show(kssl_ctx);\n                        if (krb5rc && kssl_err.text)\n                                printf("kssl_cget_tkt kssl_err=%s\\n", kssl_err.text);\n                        }\n#endif\n                        if (krb5rc)\n                                {\n                                ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);\n                                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, kssl_err.reason);\n                                goto err;\n                                }\n                        n = krb5_ap_req.length;\n                        memcpy(p, krb5_ap_req.data, krb5_ap_req.length);\n                        if (krb5_ap_req.data)\n                                kssl_krb5_free_data_contents(NULL,&krb5_ap_req);\n                        s->session->master_key_length=\n                                s->method->ssl3_enc->generate_master_secret(s,\n                                        s->session->master_key,\tkssl_ctx->key,kssl_ctx->length);\n                        }\n#endif\n#ifndef NO_DH\n\t\telse if (l & (SSL_kEDH|SSL_kDHr|SSL_kDHd))\n\t\t\t{\n\t\t\tDH *dh_srvr,*dh_clnt;\n\t\t\tif (s->session->sess_cert->peer_dh_tmp != NULL)\n\t\t\t\tdh_srvr=s->session->sess_cert->peer_dh_tmp;\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);\n\t\t\t\tSSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_UNABLE_TO_FIND_DH_PARAMETERS);\n\t\t\t\tgoto err;\n\t\t\t\t}\n\t\t\tif ((dh_clnt=DHparams_dup(dh_srvr)) == NULL)\n\t\t\t\t{\n\t\t\t\tSSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB);\n\t\t\t\tgoto err;\n\t\t\t\t}\n\t\t\tif (!DH_generate_key(dh_clnt))\n\t\t\t\t{\n\t\t\t\tSSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB);\n\t\t\t\tgoto err;\n\t\t\t\t}\n\t\t\tn=DH_compute_key(p,dh_srvr->pub_key,dh_clnt);\n\t\t\tif (n <= 0)\n\t\t\t\t{\n\t\t\t\tSSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB);\n\t\t\t\tgoto err;\n\t\t\t\t}\n\t\t\ts->session->master_key_length=\n\t\t\t\ts->method->ssl3_enc->generate_master_secret(s,\n\t\t\t\t\ts->session->master_key,p,n);\n\t\t\tmemset(p,0,n);\n\t\t\tn=BN_num_bytes(dh_clnt->pub_key);\n\t\t\ts2n(n,p);\n\t\t\tBN_bn2bin(dh_clnt->pub_key,p);\n\t\t\tn+=2;\n\t\t\tDH_free(dh_clnt);\n\t\t\t}\n#endif\n\t\telse\n\t\t\t{\n\t\t\tssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);\n\t\t\tSSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_INTERNAL_ERROR);\n\t\t\tgoto err;\n\t\t\t}\n\t\t*(d++)=SSL3_MT_CLIENT_KEY_EXCHANGE;\n\t\tl2n3(n,d);\n\t\ts->state=SSL3_ST_CW_KEY_EXCH_B;\n\t\ts->init_num=n+4;\n\t\ts->init_off=0;\n\t\t}\n\treturn(ssl3_do_write(s,SSL3_RT_HANDSHAKE));\nerr:\n\treturn(-1);\n\t}']