SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_INTERNAL_ERROR);
SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
static int ssl3_send_client_key_exchange(SSL *s)	{	unsigned char *p,*d;	int n;	unsigned long l;#ifndef OPENSSL_NO_RSA	unsigned char *q;	EVP_PKEY *pkey=NULL;#endif#ifndef OPENSSL_NO_KRB5        KSSL_ERR kssl_err;#endif /* OPENSSL_NO_KRB5 */	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;                /* Fool emacs indentation */                if (0) {}#ifndef OPENSSL_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;			/* Fix buf for TLS and beyond */			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;				}			/* Fix buf for TLS and beyond */			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 OPENSSL_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	/* KSSL_DEBUG */                        /*                        **	Tried to send random tmp_buf[] as PMS in Kerberos ticket                        **	by passing  krb5_mk_req_extended(ctx,authctx,opts, tmp_buf, ...)                        **	but: I can't retrieve the PMS on the other side!  There is                        **	some indication in the krb5 source that this is only used                        **	to generate a checksum.  OTOH, the Tung book shows data                        **	("GET widget01.txt") being passed in krb5_mk_req_extended()                        **	by way of krb5_sendauth().  I don't get it.                        **	Until Kerberos goes 3DES, the big PMS secret would only be                        **	encrypted in 1-DES anyway.  So losing the PMS shouldn't be                        **	a big deal.                        */                        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	/* KSSL_DEBUG */                        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;                                }                        /*	Send ticket (copy to *p, set n = length)                         */                        n = krb5_ap_req.length;                        memcpy(p, krb5_ap_req.data, krb5_ap_req.length);                        if (krb5_ap_req.data)                                  kssl_krb5_free_data_contents(NULL,&krb5_ap_req);                        /*	19991013 VRS -	3DES is kind of bogus here,                        **	at least until Kerberos supports 3DES.  The only                        **	real secret is the 8-byte Kerberos session key;                        **	the other key material ((s->) client_random, server_random)                        **	could be sniffed.  Mixing in these nonces should help                        **	protect against replay attacks, however.                        **                        **	Alternate code for Kerberos Purists:                        **                        **	memcpy(s->session->master_key, kssl_ctx->key, kssl_ctx->length);                        **	s->session->master_key_length = kssl_ctx->length;                        */                        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 OPENSSL_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				{				/* we get them from the cert */				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;				}						/* generate a new random key */			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;				}			/* use the 'p' output buffer for the DH key, but			 * make sure to clear it out afterwards */			n=DH_compute_key(p,dh_srvr->pub_key,dh_clnt);			if (n <= 0)				{				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB);				goto err;				}			/* generate master key from the result */			s->session->master_key_length=				s->method->ssl3_enc->generate_master_secret(s,					s->session->master_key,p,n);			/* clean up */			memset(p,0,n);			/* send off the data */			n=BN_num_bytes(dh_clnt->pub_key);			s2n(n,p);			BN_bn2bin(dh_clnt->pub_key,p);			n+=2;			DH_free(dh_clnt);			/* perhaps clean things up a bit EAY EAY EAY EAY*/			}#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;		/* number of bytes to write */		s->init_num=n+4;		s->init_off=0;		}	/* SSL3_ST_CW_KEY_EXCH_B */	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));err:	return(-1);	}