(unsigned int)s->s2->key_material_length);
s->s2->key_material_length);
static int client_certificate(SSL *s)	{	unsigned char *buf;	unsigned char *p,*d;	int i;	unsigned int n;	int cert_ch_len;	unsigned char *cert_ch;	buf=(unsigned char *)s->init_buf->data;	/* We have a cert associated with the SSL, so attach it to	 * the session if it does not have one */	if (s->state == SSL2_ST_SEND_CLIENT_CERTIFICATE_A)		{		i=ssl2_read(s,(char *)&(buf[s->init_num]),			SSL2_MAX_CERT_CHALLENGE_LENGTH+1-s->init_num);		if (i<(SSL2_MIN_CERT_CHALLENGE_LENGTH+1-s->init_num))			return(ssl2_part_read(s,SSL_F_CLIENT_CERTIFICATE,i));		s->init_num += i;		if (s->msg_callback)			s->msg_callback(0, s->version, 0, buf, (size_t)s->init_num, s, s->msg_callback_arg); /* REQUEST-CERTIFICATE */		/* type=buf[0]; */		/* type eq x509 */		if (buf[1] != SSL2_AT_MD5_WITH_RSA_ENCRYPTION)			{			ssl2_return_error(s,SSL2_PE_UNSUPPORTED_CERTIFICATE_TYPE);			SSLerr(SSL_F_CLIENT_CERTIFICATE,SSL_R_BAD_AUTHENTICATION_TYPE);			return(-1);			}		if ((s->cert == NULL) ||			(s->cert->key->x509 == NULL) ||			(s->cert->key->privatekey == NULL))			{			s->state=SSL2_ST_X509_GET_CLIENT_CERTIFICATE;			}		else			s->state=SSL2_ST_SEND_CLIENT_CERTIFICATE_C;		}	cert_ch = buf + 2;	cert_ch_len = s->init_num - 2;	if (s->state == SSL2_ST_X509_GET_CLIENT_CERTIFICATE)		{		X509 *x509=NULL;		EVP_PKEY *pkey=NULL;		/* If we get an error we need to		 * ssl->rwstate=SSL_X509_LOOKUP;		 * return(error);		 * We should then be retried when things are ok and we		 * can get a cert or not */		i=0;		if (s->ctx->client_cert_cb != NULL)			{			i=s->ctx->client_cert_cb(s,&(x509),&(pkey));			}		if (i < 0)			{			s->rwstate=SSL_X509_LOOKUP;			return(-1);			}		s->rwstate=SSL_NOTHING;		if ((i == 1) && (pkey != NULL) && (x509 != NULL))			{			s->state=SSL2_ST_SEND_CLIENT_CERTIFICATE_C;			if (	!SSL_use_certificate(s,x509) || 				!SSL_use_PrivateKey(s,pkey))				{				i=0;				}			X509_free(x509);			EVP_PKEY_free(pkey);			}		else if (i == 1)			{			if (x509 != NULL) X509_free(x509);			if (pkey != NULL) EVP_PKEY_free(pkey);			SSLerr(SSL_F_CLIENT_CERTIFICATE,SSL_R_BAD_DATA_RETURNED_BY_CALLBACK);			i=0;			}		if (i == 0)			{			/* We have no client certificate to respond with			 * so send the correct error message back */			s->state=SSL2_ST_SEND_CLIENT_CERTIFICATE_B;			p=buf;			*(p++)=SSL2_MT_ERROR;			s2n(SSL2_PE_NO_CERTIFICATE,p);			s->init_off=0;			s->init_num=3;			/* Write is done at the end */			}		}	if (s->state == SSL2_ST_SEND_CLIENT_CERTIFICATE_B)		{		return(ssl2_do_write(s));		}	if (s->state == SSL2_ST_SEND_CLIENT_CERTIFICATE_C)		{		EVP_MD_CTX ctx;		/* ok, now we calculate the checksum		 * do it first so we can reuse buf :-) */		p=buf;		EVP_MD_CTX_init(&ctx);		EVP_SignInit_ex(&ctx,s->ctx->rsa_md5, NULL);		EVP_SignUpdate(&ctx,s->s2->key_material,			(unsigned int)s->s2->key_material_length);		EVP_SignUpdate(&ctx,cert_ch,(unsigned int)cert_ch_len);		n=i2d_X509(s->session->sess_cert->peer_key->x509,&p);		EVP_SignUpdate(&ctx,buf,(unsigned int)n);		p=buf;		d=p+6;		*(p++)=SSL2_MT_CLIENT_CERTIFICATE;		*(p++)=SSL2_CT_X509_CERTIFICATE;		n=i2d_X509(s->cert->key->x509,&d);		s2n(n,p);		if (!EVP_SignFinal(&ctx,d,&n,s->cert->key->privatekey))			{			/* this is not good.  If things have failed it			 * means there so something wrong with the key.			 * We will continue with a 0 length signature			 */			}		EVP_MD_CTX_cleanup(&ctx);		s2n(n,p);		d+=n;		s->state=SSL2_ST_SEND_CLIENT_CERTIFICATE_D;		s->init_num=d-buf;		s->init_off=0;		}	/* if (s->state == SSL2_ST_SEND_CLIENT_CERTIFICATE_D) */	return(ssl2_do_write(s));	}