| Index: openssl/ssl/s3_clnt.c | 
| =================================================================== | 
| --- openssl/ssl/s3_clnt.c	(revision 105093) | 
| +++ openssl/ssl/s3_clnt.c	(working copy) | 
| @@ -56,7 +56,7 @@ | 
| * [including the GNU Public Licence.] | 
| */ | 
| /* ==================================================================== | 
| - * Copyright (c) 1998-2003 The OpenSSL Project.  All rights reserved. | 
| + * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved. | 
| * | 
| * Redistribution and use in source and binary forms, with or without | 
| * modification, are permitted provided that the following conditions | 
| @@ -121,6 +121,32 @@ | 
| * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories. | 
| * | 
| */ | 
| +/* ==================================================================== | 
| + * Copyright 2005 Nokia. All rights reserved. | 
| + * | 
| + * The portions of the attached software ("Contribution") is developed by | 
| + * Nokia Corporation and is licensed pursuant to the OpenSSL open source | 
| + * license. | 
| + * | 
| + * The Contribution, originally written by Mika Kousa and Pasi Eronen of | 
| + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites | 
| + * support (see RFC 4279) to OpenSSL. | 
| + * | 
| + * No patent licenses or other rights except those expressly stated in | 
| + * the OpenSSL open source license shall be deemed granted or received | 
| + * expressly, by implication, estoppel, or otherwise. | 
| + * | 
| + * No assurances are provided by Nokia that the Contribution does not | 
| + * infringe the patent or other intellectual property rights of any third | 
| + * party or that the license provides you with all the necessary rights | 
| + * to make use of the Contribution. | 
| + * | 
| + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN | 
| + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA | 
| + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY | 
| + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR | 
| + * OTHERWISE. | 
| + */ | 
|  | 
| #include <stdio.h> | 
| #include "ssl_locl.h" | 
| @@ -130,10 +156,6 @@ | 
| #include <openssl/objects.h> | 
| #include <openssl/evp.h> | 
| #include <openssl/md5.h> | 
| -#ifdef OPENSSL_FIPS | 
| -#include <openssl/fips.h> | 
| -#endif | 
| - | 
| #ifndef OPENSSL_NO_DH | 
| #include <openssl/dh.h> | 
| #endif | 
| @@ -142,15 +164,10 @@ | 
| #include <openssl/engine.h> | 
| #endif | 
|  | 
| -static SSL_METHOD *ssl3_get_client_method(int ver); | 
| +static const SSL_METHOD *ssl3_get_client_method(int ver); | 
| static int ca_dn_cmp(const X509_NAME * const *a,const X509_NAME * const *b); | 
|  | 
| -#ifndef OPENSSL_NO_ECDH | 
| -static int curve_id2nid(int curve_id); | 
| -int check_srvr_ecc_cert_and_alg(X509 *x, SSL_CIPHER *cs); | 
| -#endif | 
| - | 
| -static SSL_METHOD *ssl3_get_client_method(int ver) | 
| +static const SSL_METHOD *ssl3_get_client_method(int ver) | 
| { | 
| if (ver == SSL3_VERSION) | 
| return(SSLv3_client_method()); | 
| @@ -166,7 +183,7 @@ | 
| int ssl3_connect(SSL *s) | 
| { | 
| BUF_MEM *buf=NULL; | 
| -	unsigned long Time=(unsigned long)time(NULL),l; | 
| +	unsigned long Time=(unsigned long)time(NULL); | 
| void (*cb)(const SSL *ssl,int type,int val)=NULL; | 
| int ret= -1; | 
| int new_state,state,skip=0; | 
| @@ -182,11 +199,18 @@ | 
|  | 
| s->in_handshake++; | 
| if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); | 
| +#if 0	/* Send app data in separate packet, otherwise, some particular site | 
| +	 * (only one site so far) closes the socket. | 
| +	 * Note: there is a very small chance that two TCP packets | 
| +	 * could be arriving at server combined into a single TCP packet, | 
| +	 * then trigger that site to break. We haven't encounter that though. | 
| +	 */ | 
| if (SSL_get_mode(s) & SSL_MODE_HANDSHAKE_CUTTHROUGH) | 
| { | 
| /* Send app data along with CCS/Finished */ | 
| s->s3->flags |= SSL3_FLAGS_DELAY_CLIENT_FINISHED; | 
| } | 
| +#endif | 
|  | 
| for (;;) | 
| { | 
| @@ -266,6 +290,7 @@ | 
| case SSL3_ST_CR_SRVR_HELLO_B: | 
| ret=ssl3_get_server_hello(s); | 
| if (ret <= 0) goto end; | 
| + | 
| if (s->hit) | 
| s->state=SSL3_ST_CR_FINISHED_A; | 
| else | 
| @@ -290,7 +315,9 @@ | 
| } | 
| #endif | 
| /* Check if it is anon DH/ECDH */ | 
| -			if (!(s->s3->tmp.new_cipher->algorithms & SSL_aNULL)) | 
| +			/* or PSK */ | 
| +			if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) && | 
| +			    !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) | 
| { | 
| ret=ssl3_get_server_certificate(s); | 
| if (ret <= 0) goto end; | 
| @@ -365,7 +392,6 @@ | 
| case SSL3_ST_CW_KEY_EXCH_B: | 
| ret=ssl3_send_client_key_exchange(s); | 
| if (ret <= 0) goto end; | 
| -			l=s->s3->tmp.new_cipher->algorithms; | 
| /* EAY EAY EAY need to check for DH fix cert | 
| * sent back */ | 
| /* For TLS, cert_req is set to 2, so a cert chain | 
| @@ -386,6 +412,11 @@ | 
| s->state=SSL3_ST_CW_CHANGE_A; | 
| s->s3->change_cipher_spec=0; | 
| } | 
| +			if (s->s3->flags & TLS1_FLAGS_SKIP_CERT_VERIFY) | 
| +				{ | 
| +				s->state=SSL3_ST_CW_CHANGE_A; | 
| +				s->s3->change_cipher_spec=0; | 
| +				} | 
|  | 
| s->init_num=0; | 
| break; | 
| @@ -405,10 +436,15 @@ | 
| SSL3_ST_CW_CHANGE_A,SSL3_ST_CW_CHANGE_B); | 
| if (ret <= 0) goto end; | 
|  | 
| +#if defined(OPENSSL_NO_TLSEXT) || defined(OPENSSL_NO_NEXTPROTONEG) | 
| +			s->state=SSL3_ST_CW_FINISHED_A; | 
| +#else | 
| if (s->next_proto_negotiated) | 
| s->state=SSL3_ST_CW_NEXT_PROTO_A; | 
| else | 
| s->state=SSL3_ST_CW_FINISHED_A; | 
| +#endif | 
| + | 
| s->init_num=0; | 
|  | 
| s->session->cipher=s->s3->tmp.new_cipher; | 
| @@ -436,12 +472,14 @@ | 
|  | 
| break; | 
|  | 
| +#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) | 
| case SSL3_ST_CW_NEXT_PROTO_A: | 
| case SSL3_ST_CW_NEXT_PROTO_B: | 
| ret=ssl3_send_next_proto(s); | 
| if (ret <= 0) goto end; | 
| s->state=SSL3_ST_CW_FINISHED_A; | 
| break; | 
| +#endif | 
|  | 
| case SSL3_ST_CW_FINISHED_A: | 
| case SSL3_ST_CW_FINISHED_B: | 
| @@ -648,6 +686,12 @@ | 
| #endif | 
| (sess->not_resumable)) | 
| { | 
| +		        if (!s->session_creation_enabled) | 
| +				{ | 
| +				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE); | 
| +				SSLerr(SSL_F_SSL3_CLIENT_HELLO,SSL_R_SESSION_MAY_NOT_BE_CREATED); | 
| +				goto err; | 
| +				} | 
| if (!ssl_get_new_session(s,0)) | 
| goto err; | 
| } | 
| @@ -701,7 +745,9 @@ | 
| #ifdef OPENSSL_NO_COMP | 
| *(p++)=1; | 
| #else | 
| -		if (s->ctx->comp_methods == NULL) | 
| + | 
| +		if ((s->options & SSL_OP_NO_COMPRESSION) | 
| +					|| !s->ctx->comp_methods) | 
| j=0; | 
| else | 
| j=sk_SSL_COMP_num(s->ctx->comp_methods); | 
| @@ -713,13 +759,21 @@ | 
| } | 
| #endif | 
| *(p++)=0; /* Add the NULL method */ | 
| + | 
| #ifndef OPENSSL_NO_TLSEXT | 
| +		/* TLS extensions*/ | 
| +		if (ssl_prepare_clienthello_tlsext(s) <= 0) | 
| +			{ | 
| +			SSLerr(SSL_F_SSL3_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT); | 
| +			goto err; | 
| +			} | 
| if ((p = ssl_add_clienthello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL) | 
| { | 
| SSLerr(SSL_F_SSL3_CLIENT_HELLO,ERR_R_INTERNAL_ERROR); | 
| goto err; | 
| } | 
| -#endif | 
| +#endif | 
| + | 
| l=(p-d); | 
| d=buf; | 
| *(d++)=SSL3_MT_CLIENT_HELLO; | 
| @@ -740,7 +794,7 @@ | 
| int ssl3_get_server_hello(SSL *s) | 
| { | 
| STACK_OF(SSL_CIPHER) *sk; | 
| -	SSL_CIPHER *c; | 
| +	const SSL_CIPHER *c; | 
| unsigned char *p,*d; | 
| int i,al,ok; | 
| unsigned int j; | 
| @@ -809,6 +863,23 @@ | 
| goto f_err; | 
| } | 
|  | 
| +#ifndef OPENSSL_NO_TLSEXT | 
| +	/* check if we want to resume the session based on external pre-shared secret */ | 
| +	if (s->version >= TLS1_VERSION && s->tls_session_secret_cb) | 
| +		{ | 
| +		SSL_CIPHER *pref_cipher=NULL; | 
| +		s->session->master_key_length=sizeof(s->session->master_key); | 
| +		if (s->tls_session_secret_cb(s, s->session->master_key, | 
| +					     &s->session->master_key_length, | 
| +					     NULL, &pref_cipher, | 
| +					     s->tls_session_secret_cb_arg)) | 
| +			{ | 
| +			s->session->cipher = pref_cipher ? | 
| +				pref_cipher : ssl_get_cipher_by_char(s, p+j); | 
| +			} | 
| +		} | 
| +#endif /* OPENSSL_NO_TLSEXT */ | 
| + | 
| if (j != 0 && j == s->session->session_id_length | 
| && memcmp(p,s->session->session_id,j) == 0) | 
| { | 
| @@ -829,6 +900,12 @@ | 
| s->hit=0; | 
| if (s->session->session_id_length > 0) | 
| { | 
| +		        if (!s->session_creation_enabled) | 
| +				{ | 
| +				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE); | 
| +				SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_SESSION_MAY_NOT_BE_CREATED); | 
| +				goto err; | 
| +				} | 
| if (!ssl_get_new_session(s,0)) | 
| { | 
| al=SSL_AD_INTERNAL_ERROR; | 
| @@ -866,8 +943,11 @@ | 
| s->session->cipher_id = s->session->cipher->id; | 
| if (s->hit && (s->session->cipher_id != c->id)) | 
| { | 
| +/* Workaround is now obsolete */ | 
| +#if 0 | 
| if (!(s->options & | 
| SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG)) | 
| +#endif | 
| { | 
| al=SSL_AD_ILLEGAL_PARAMETER; | 
| SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED); | 
| @@ -875,6 +955,8 @@ | 
| } | 
| } | 
| s->s3->tmp.new_cipher=c; | 
| +	if (!ssl3_digest_cached_records(s)) | 
| +		goto f_err; | 
|  | 
| /* lets get the compression algorithm */ | 
| /* COMPRESSION */ | 
| @@ -885,10 +967,31 @@ | 
| SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM); | 
| goto f_err; | 
| } | 
| +	/* If compression is disabled we'd better not try to resume a session | 
| +	 * using compression. | 
| +	 */ | 
| +	if (s->session->compress_meth != 0) | 
| +		{ | 
| +		al=SSL_AD_INTERNAL_ERROR; | 
| +		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_INCONSISTENT_COMPRESSION); | 
| +		goto f_err; | 
| +		} | 
| #else | 
| j= *(p++); | 
| +	if (s->hit && j != s->session->compress_meth) | 
| +		{ | 
| +		al=SSL_AD_ILLEGAL_PARAMETER; | 
| +		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED); | 
| +		goto f_err; | 
| +		} | 
| if (j == 0) | 
| comp=NULL; | 
| +	else if (s->options & SSL_OP_NO_COMPRESSION) | 
| +		{ | 
| +		al=SSL_AD_ILLEGAL_PARAMETER; | 
| +		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_COMPRESSION_DISABLED); | 
| +		goto f_err; | 
| +		} | 
| else | 
| comp=ssl3_comp_find(s->ctx->comp_methods,j); | 
|  | 
| @@ -903,6 +1006,7 @@ | 
| s->s3->tmp.new_compression=comp; | 
| } | 
| #endif | 
| + | 
| #ifndef OPENSSL_NO_TLSEXT | 
| /* TLS extensions*/ | 
| if (s->version >= SSL3_VERSION) | 
| @@ -921,13 +1025,12 @@ | 
| } | 
| #endif | 
|  | 
| - | 
| if (p != (d+n)) | 
| { | 
| /* wrong packet length */ | 
| al=SSL_AD_DECODE_ERROR; | 
| SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_BAD_PACKET_LENGTH); | 
| -		goto err; | 
| +		goto f_err; | 
| } | 
|  | 
| return(1); | 
| @@ -959,7 +1062,7 @@ | 
| if (!ok) return((int)n); | 
|  | 
| if ((s->s3->tmp.message_type == SSL3_MT_SERVER_KEY_EXCHANGE) || | 
| -		((s->s3->tmp.new_cipher->algorithms & SSL_aKRB5) && | 
| +		((s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5) && | 
| (s->s3->tmp.message_type == SSL3_MT_SERVER_DONE))) | 
| { | 
| s->s3->tmp.reuse_message=1; | 
| @@ -1024,10 +1127,10 @@ | 
| i=ssl_verify_cert_chain(s,sk); | 
| if ((s->verify_mode != SSL_VERIFY_NONE) && (i <= 0) | 
| #ifndef OPENSSL_NO_KRB5 | 
| -	        && (s->s3->tmp.new_cipher->algorithms & (SSL_MKEY_MASK|SSL_AUTH_MASK)) | 
| -	        != (SSL_aKRB5|SSL_kKRB5) | 
| +	    && !((s->s3->tmp.new_cipher->algorithm_mkey & SSL_kKRB5) && | 
| +		 (s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5)) | 
| #endif /* OPENSSL_NO_KRB5 */ | 
| -	        ) | 
| +		) | 
| { | 
| al=ssl_verify_alarm_type(s->verify_result); | 
| SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_CERTIFICATE_VERIFY_FAILED); | 
| @@ -1051,15 +1154,15 @@ | 
| pkey=X509_get_pubkey(x); | 
|  | 
| /* VRS: allow null cert if auth == KRB5 */ | 
| -	need_cert =	((s->s3->tmp.new_cipher->algorithms | 
| -	                 & (SSL_MKEY_MASK|SSL_AUTH_MASK)) | 
| -	                 == (SSL_aKRB5|SSL_kKRB5))? 0: 1; | 
| +	need_cert = ((s->s3->tmp.new_cipher->algorithm_mkey & SSL_kKRB5) && | 
| +	            (s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5)) | 
| +	            ? 0 : 1; | 
|  | 
| #ifdef KSSL_DEBUG | 
| -	printf("pkey,x = %p, %p\n", (void *)pkey,(void *)x); | 
| +	printf("pkey,x = %p, %p\n", pkey,x); | 
| printf("ssl_cert_type(x,pkey) = %d\n", ssl_cert_type(x,pkey)); | 
| -	printf("cipher, alg, nc = %s, %lx, %d\n", s->s3->tmp.new_cipher->name, | 
| -	        s->s3->tmp.new_cipher->algorithms, need_cert); | 
| +	printf("cipher, alg, nc = %s, %lx, %lx, %d\n", s->s3->tmp.new_cipher->name, | 
| +		s->s3->tmp.new_cipher->algorithm_mkey, s->s3->tmp.new_cipher->algorithm_auth, need_cert); | 
| #endif    /* KSSL_DEBUG */ | 
|  | 
| if (need_cert && ((pkey == NULL) || EVP_PKEY_missing_parameters(pkey))) | 
| @@ -1131,7 +1234,7 @@ | 
| EVP_MD_CTX md_ctx; | 
| unsigned char *param,*p; | 
| int al,i,j,param_len,ok; | 
| -	long n,alg; | 
| +	long n,alg_k,alg_a; | 
| EVP_PKEY *pkey=NULL; | 
| #ifndef OPENSSL_NO_RSA | 
| RSA *rsa=NULL; | 
| @@ -1155,17 +1258,28 @@ | 
| -1, | 
| s->max_cert_list, | 
| &ok); | 
| - | 
| if (!ok) return((int)n); | 
|  | 
| if (s->s3->tmp.message_type != SSL3_MT_SERVER_KEY_EXCHANGE) | 
| { | 
| +#ifndef OPENSSL_NO_PSK | 
| +		/* In plain PSK ciphersuite, ServerKeyExchange can be | 
| +		   omitted if no identity hint is sent. Set | 
| +		   session->sess_cert anyway to avoid problems | 
| +		   later.*/ | 
| +		if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK) | 
| +			{ | 
| +			s->session->sess_cert=ssl_sess_cert_new(); | 
| +			if (s->ctx->psk_identity_hint) | 
| +				OPENSSL_free(s->ctx->psk_identity_hint); | 
| +			s->ctx->psk_identity_hint = NULL; | 
| +			} | 
| +#endif | 
| s->s3->tmp.reuse_message=1; | 
| return(1); | 
| } | 
|  | 
| param=p=(unsigned char *)s->init_msg; | 
| - | 
| if (s->session->sess_cert != NULL) | 
| { | 
| #ifndef OPENSSL_NO_RSA | 
| @@ -1196,11 +1310,57 @@ | 
| } | 
|  | 
| param_len=0; | 
| -	alg=s->s3->tmp.new_cipher->algorithms; | 
| +	alg_k=s->s3->tmp.new_cipher->algorithm_mkey; | 
| +	alg_a=s->s3->tmp.new_cipher->algorithm_auth; | 
| EVP_MD_CTX_init(&md_ctx); | 
|  | 
| +#ifndef OPENSSL_NO_PSK | 
| +	if (alg_k & SSL_kPSK) | 
| +		{ | 
| +		char tmp_id_hint[PSK_MAX_IDENTITY_LEN+1]; | 
| + | 
| +		al=SSL_AD_HANDSHAKE_FAILURE; | 
| +		n2s(p,i); | 
| +		param_len=i+2; | 
| +		/* 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 (i > PSK_MAX_IDENTITY_LEN) | 
| +			{ | 
| +			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, | 
| +				SSL_R_DATA_LENGTH_TOO_LONG); | 
| +			goto f_err; | 
| +			} | 
| +		if (param_len > n) | 
| +			{ | 
| +			al=SSL_AD_DECODE_ERROR; | 
| +			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, | 
| +				SSL_R_BAD_PSK_IDENTITY_HINT_LENGTH); | 
| +			goto f_err; | 
| +			} | 
| +		/* If received PSK identity hint contains NULL | 
| +		 * characters, the hint is truncated from the first | 
| +		 * NULL. p may not be ending with NULL, so create a | 
| +		 * NULL-terminated string. */ | 
| +		memcpy(tmp_id_hint, p, i); | 
| +		memset(tmp_id_hint+i, 0, PSK_MAX_IDENTITY_LEN+1-i); | 
| +		if (s->ctx->psk_identity_hint != NULL) | 
| +			OPENSSL_free(s->ctx->psk_identity_hint); | 
| +		s->ctx->psk_identity_hint = BUF_strdup(tmp_id_hint); | 
| +		if (s->ctx->psk_identity_hint == NULL) | 
| +			{ | 
| +			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE); | 
| +			goto f_err; | 
| +			} | 
| + | 
| +		p+=i; | 
| +		n-=param_len; | 
| +		} | 
| +	else | 
| +#endif /* !OPENSSL_NO_PSK */ | 
| #ifndef OPENSSL_NO_RSA | 
| -	if (alg & SSL_kRSA) | 
| +	if (alg_k & SSL_kRSA) | 
| { | 
| if ((rsa=RSA_new()) == NULL) | 
| { | 
| @@ -1239,7 +1399,7 @@ | 
| n-=param_len; | 
|  | 
| /* this should be because we are using an export cipher */ | 
| -		if (alg & SSL_aRSA) | 
| +		if (alg_a & SSL_aRSA) | 
| pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509); | 
| else | 
| { | 
| @@ -1254,7 +1414,7 @@ | 
| ; | 
| #endif | 
| #ifndef OPENSSL_NO_DH | 
| -	else if (alg & SSL_kEDH) | 
| +	else if (alg_k & SSL_kEDH) | 
| { | 
| if ((dh=DH_new()) == NULL) | 
| { | 
| @@ -1308,14 +1468,14 @@ | 
| n-=param_len; | 
|  | 
| #ifndef OPENSSL_NO_RSA | 
| -		if (alg & SSL_aRSA) | 
| +		if (alg_a & SSL_aRSA) | 
| pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509); | 
| #else | 
| if (0) | 
| ; | 
| #endif | 
| #ifndef OPENSSL_NO_DSA | 
| -		else if (alg & SSL_aDSS) | 
| +		else if (alg_a & SSL_aDSS) | 
| pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_DSA_SIGN].x509); | 
| #endif | 
| /* else anonymous DH, so no certificate or pkey. */ | 
| @@ -1323,7 +1483,7 @@ | 
| s->session->sess_cert->peer_dh_tmp=dh; | 
| dh=NULL; | 
| } | 
| -	else if ((alg & SSL_kDHr) || (alg & SSL_kDHd)) | 
| +	else if ((alg_k & SSL_kDHr) || (alg_k & SSL_kDHd)) | 
| { | 
| al=SSL_AD_ILLEGAL_PARAMETER; | 
| SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER); | 
| @@ -1332,7 +1492,7 @@ | 
| #endif /* !OPENSSL_NO_DH */ | 
|  | 
| #ifndef OPENSSL_NO_ECDH | 
| -	else if (alg & SSL_kECDHE) | 
| +	else if (alg_k & SSL_kEECDH) | 
| { | 
| EC_GROUP *ngroup; | 
| const EC_GROUP *group; | 
| @@ -1355,7 +1515,7 @@ | 
| param_len=3; | 
| if ((param_len > n) || | 
| (*p != NAMED_CURVE_TYPE) || | 
| -		    ((curve_nid = curve_id2nid(*(p + 2))) == 0)) | 
| +		    ((curve_nid = tls1_ec_curve_id2nid(*(p + 2))) == 0)) | 
| { | 
| al=SSL_AD_INTERNAL_ERROR; | 
| SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS); | 
| @@ -1416,11 +1576,11 @@ | 
| */ | 
| if (0) ; | 
| #ifndef OPENSSL_NO_RSA | 
| -		else if (alg & SSL_aRSA) | 
| +		else if (alg_a & SSL_aRSA) | 
| pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509); | 
| #endif | 
| #ifndef OPENSSL_NO_ECDSA | 
| -		else if (alg & SSL_aECDSA) | 
| +		else if (alg_a & SSL_aECDSA) | 
| pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_ECC].x509); | 
| #endif | 
| /* else anonymous ECDH, so no certificate or pkey. */ | 
| @@ -1428,22 +1588,17 @@ | 
| s->session->sess_cert->peer_ecdh_tmp=ecdh; | 
| ecdh=NULL; | 
| BN_CTX_free(bn_ctx); | 
| +		bn_ctx = NULL; | 
| EC_POINT_free(srvr_ecpoint); | 
| srvr_ecpoint = NULL; | 
| } | 
| -	else if (alg & SSL_kECDH) | 
| +	else if (alg_k) | 
| { | 
| al=SSL_AD_UNEXPECTED_MESSAGE; | 
| SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_UNEXPECTED_MESSAGE); | 
| goto f_err; | 
| } | 
| #endif /* !OPENSSL_NO_ECDH */ | 
| -	if (alg & SSL_aFZA) | 
| -		{ | 
| -		al=SSL_AD_HANDSHAKE_FAILURE; | 
| -		SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER); | 
| -		goto f_err; | 
| -		} | 
|  | 
|  | 
| /* p points to the next byte, there are 'n' bytes left */ | 
| @@ -1472,8 +1627,6 @@ | 
| q=md_buf; | 
| for (num=2; num > 0; num--) | 
| { | 
| -				EVP_MD_CTX_set_flags(&md_ctx, | 
| -					EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); | 
| EVP_DigestInit_ex(&md_ctx,(num == 2) | 
| ?s->ctx->md5:s->ctx->sha1, NULL); | 
| EVP_DigestUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE); | 
| @@ -1544,12 +1697,13 @@ | 
| } | 
| else | 
| { | 
| -		/* still data left over */ | 
| -		if (!(alg & SSL_aNULL)) | 
| +		if (!(alg_a & SSL_aNULL) && !(alg_k & SSL_kPSK)) | 
| +			/* aNULL or kPSK do not need public keys */ | 
| { | 
| SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR); | 
| goto err; | 
| } | 
| +		/* still data left over */ | 
| if (n != 0) | 
| { | 
| al=SSL_AD_DECODE_ERROR; | 
| @@ -1619,8 +1773,7 @@ | 
| /* TLS does not like anon-DH with client cert */ | 
| if (s->version > SSL3_VERSION) | 
| { | 
| -		l=s->s3->tmp.new_cipher->algorithms; | 
| -		if (l & SSL_aNULL) | 
| +		if (s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) | 
| { | 
| ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_UNEXPECTED_MESSAGE); | 
| SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER); | 
| @@ -1761,7 +1914,7 @@ | 
| if (n < 6) | 
| { | 
| /* need at least ticket_lifetime_hint + ticket length */ | 
| -		al = SSL3_AL_FATAL,SSL_AD_DECODE_ERROR; | 
| +		al = SSL_AD_DECODE_ERROR; | 
| SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,SSL_R_LENGTH_MISMATCH); | 
| goto f_err; | 
| } | 
| @@ -1772,7 +1925,7 @@ | 
| /* ticket_lifetime_hint + ticket_length + ticket */ | 
| if (ticklen + 6 != n) | 
| { | 
| -		al = SSL3_AL_FATAL,SSL_AD_DECODE_ERROR; | 
| +		al = SSL_AD_DECODE_ERROR; | 
| SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,SSL_R_LENGTH_MISMATCH); | 
| goto f_err; | 
| } | 
| @@ -1822,8 +1975,7 @@ | 
| int ssl3_get_cert_status(SSL *s) | 
| { | 
| int ok, al; | 
| -	unsigned long resplen; | 
| -	long n; | 
| +	unsigned long resplen,n; | 
| const unsigned char *p; | 
|  | 
| n=s->method->ssl_get_message(s, | 
| @@ -1849,7 +2001,7 @@ | 
| goto f_err; | 
| } | 
| n2l3(p, resplen); | 
| -	if (resplen + 4 != (unsigned long)n) | 
| +	if (resplen + 4 != n) | 
| { | 
| al = SSL_AD_DECODE_ERROR; | 
| SSLerr(SSL_F_SSL3_GET_CERT_STATUS,SSL_R_LENGTH_MISMATCH); | 
| @@ -1918,7 +2070,7 @@ | 
| { | 
| unsigned char *p,*d; | 
| int n; | 
| -	unsigned long l; | 
| +	unsigned long alg_k; | 
| #ifndef OPENSSL_NO_RSA | 
| unsigned char *q; | 
| EVP_PKEY *pkey=NULL; | 
| @@ -1940,12 +2092,12 @@ | 
| d=(unsigned char *)s->init_buf->data; | 
| p= &(d[4]); | 
|  | 
| -		l=s->s3->tmp.new_cipher->algorithms; | 
| +		alg_k=s->s3->tmp.new_cipher->algorithm_mkey; | 
|  | 
| /* Fool emacs indentation */ | 
| if (0) {} | 
| #ifndef OPENSSL_NO_RSA | 
| -		else if (l & SSL_kRSA) | 
| +		else if (alg_k & SSL_kRSA) | 
| { | 
| RSA *rsa; | 
| unsigned char tmp_buf[SSL_MAX_MASTER_KEY_LENGTH]; | 
| @@ -2004,7 +2156,7 @@ | 
| } | 
| #endif | 
| #ifndef OPENSSL_NO_KRB5 | 
| -		else if (l & SSL_kKRB5) | 
| +		else if (alg_k & SSL_kKRB5) | 
| { | 
| krb5_error_code	krb5rc; | 
| KSSL_CTX	*kssl_ctx = s->kssl_ctx; | 
| @@ -2012,7 +2164,7 @@ | 
| krb5_data	*enc_ticket; | 
| krb5_data	authenticator, *authp = NULL; | 
| EVP_CIPHER_CTX	ciph_ctx; | 
| -			EVP_CIPHER	*enc = NULL; | 
| +			const EVP_CIPHER *enc = NULL; | 
| unsigned char	iv[EVP_MAX_IV_LENGTH]; | 
| unsigned char	tmp_buf[SSL_MAX_MASTER_KEY_LENGTH]; | 
| unsigned char	epms[SSL_MAX_MASTER_KEY_LENGTH | 
| @@ -2023,7 +2175,7 @@ | 
|  | 
| #ifdef KSSL_DEBUG | 
| printf("ssl3_send_client_key_exchange(%lx & %lx)\n", | 
| -			        l, SSL_kKRB5); | 
| +				alg_k, SSL_kKRB5); | 
| #endif	/* KSSL_DEBUG */ | 
|  | 
| authp = NULL; | 
| @@ -2115,7 +2267,7 @@ | 
| sizeof tmp_buf); | 
| EVP_EncryptFinal_ex(&ciph_ctx,&(epms[outl]),&padl); | 
| outl += padl; | 
| -			if (outl > sizeof epms) | 
| +			if (outl > (int)sizeof epms) | 
| { | 
| SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); | 
| goto err; | 
| @@ -2129,7 +2281,7 @@ | 
| n+=outl + 2; | 
|  | 
| s->session->master_key_length= | 
| -			        s->method->ssl3_enc->generate_master_secret(s, | 
| +				s->method->ssl3_enc->generate_master_secret(s, | 
| s->session->master_key, | 
| tmp_buf, sizeof tmp_buf); | 
|  | 
| @@ -2138,7 +2290,7 @@ | 
| } | 
| #endif | 
| #ifndef OPENSSL_NO_DH | 
| -		else if (l & (SSL_kEDH|SSL_kDHr|SSL_kDHd)) | 
| +		else if (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd)) | 
| { | 
| DH *dh_srvr,*dh_clnt; | 
|  | 
| @@ -2147,7 +2299,7 @@ | 
| ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_UNEXPECTED_MESSAGE); | 
| SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_UNEXPECTED_MESSAGE); | 
| goto err; | 
| -			        } | 
| +				} | 
|  | 
| if (s->session->sess_cert->peer_dh_tmp != NULL) | 
| dh_srvr=s->session->sess_cert->peer_dh_tmp; | 
| @@ -2168,6 +2320,7 @@ | 
| if (!DH_generate_key(dh_clnt)) | 
| { | 
| SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB); | 
| +				DH_free(dh_clnt); | 
| goto err; | 
| } | 
|  | 
| @@ -2179,6 +2332,7 @@ | 
| if (n <= 0) | 
| { | 
| SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB); | 
| +				DH_free(dh_clnt); | 
| goto err; | 
| } | 
|  | 
| @@ -2202,7 +2356,7 @@ | 
| #endif | 
|  | 
| #ifndef OPENSSL_NO_ECDH | 
| -		else if ((l & SSL_kECDH) || (l & SSL_kECDHE)) | 
| +		else if (alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe)) | 
| { | 
| const EC_GROUP *srvr_group = NULL; | 
| EC_KEY *tkey; | 
| @@ -2214,7 +2368,7 @@ | 
| * computation as part of client certificate? | 
| * If so, set ecdh_clnt_cert to 1. | 
| */ | 
| -			if ((l & SSL_kECDH) && (s->cert != NULL)) | 
| +			if ((alg_k & (SSL_kECDHr|SSL_kECDHe)) && (s->cert != NULL)) | 
| { | 
| /* XXX: For now, we do not support client | 
| * authentication using ECDH certificates. | 
| @@ -2386,6 +2540,178 @@ | 
| EVP_PKEY_free(srvr_pub_pkey); | 
| } | 
| #endif /* !OPENSSL_NO_ECDH */ | 
| +		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; | 
| +			int keytype; | 
| +			unsigned char premaster_secret[32],shared_ukm[32], tmp[256]; | 
| +			EVP_MD_CTX *ukm_hash; | 
| +			EVP_PKEY *pub_key; | 
| + | 
| +			/* Get server sertificate PKEY and create ctx from it */ | 
| +			peer_cert=s->session->sess_cert->peer_pkeys[(keytype=SSL_PKEY_GOST01)].x509; | 
| +			if (!peer_cert) | 
| +				peer_cert=s->session->sess_cert->peer_pkeys[(keytype=SSL_PKEY_GOST94)].x509; | 
| +			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); | 
| +			/* 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 */ | 
| + | 
| +			EVP_PKEY_encrypt_init(pkey_ctx); | 
| +			  /* Generate session key */ | 
| +		    RAND_bytes(premaster_secret,32); | 
| +			/* 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_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; | 
| +				} | 
| +			/* 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,premaster_secret,32)<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); | 
| +			/* 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->session->master_key_length= | 
| +				s->method->ssl3_enc->generate_master_secret(s, | 
| +					s->session->master_key,premaster_secret,32); | 
| +			EVP_PKEY_free(pub_key); | 
| + | 
| +			} | 
| +#ifndef OPENSSL_NO_PSK | 
| +		else if (alg_k & SSL_kPSK) | 
| +			{ | 
| +			char identity[PSK_MAX_IDENTITY_LEN]; | 
| +			unsigned char *t = NULL; | 
| +			unsigned char psk_or_pre_ms[PSK_MAX_PSK_LEN*2+4]; | 
| +			unsigned int pre_ms_len = 0, psk_len = 0; | 
| +			int psk_err = 1; | 
| + | 
| +			n = 0; | 
| +			if (s->psk_client_callback == NULL) | 
| +				{ | 
| +				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, | 
| +					SSL_R_PSK_NO_CLIENT_CB); | 
| +				goto err; | 
| +				} | 
| + | 
| +			psk_len = s->psk_client_callback(s, s->ctx->psk_identity_hint, | 
| +				identity, PSK_MAX_IDENTITY_LEN, | 
| +				psk_or_pre_ms, sizeof(psk_or_pre_ms)); | 
| +			if (psk_len > PSK_MAX_PSK_LEN) | 
| +				{ | 
| +				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, | 
| +					ERR_R_INTERNAL_ERROR); | 
| +				goto psk_err; | 
| +				} | 
| +			else if (psk_len == 0) | 
| +				{ | 
| +				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, | 
| +					SSL_R_PSK_IDENTITY_NOT_FOUND); | 
| +				goto psk_err; | 
| +				} | 
| + | 
| +			/* create PSK pre_master_secret */ | 
| +			pre_ms_len = 2+psk_len+2+psk_len; | 
| +			t = psk_or_pre_ms; | 
| +			memmove(psk_or_pre_ms+psk_len+4, psk_or_pre_ms, psk_len); | 
| +			s2n(psk_len, t); | 
| +			memset(t, 0, psk_len); | 
| +			t+=psk_len; | 
| +			s2n(psk_len, t); | 
| + | 
| +			if (s->session->psk_identity_hint != NULL) | 
| +				OPENSSL_free(s->session->psk_identity_hint); | 
| +			s->session->psk_identity_hint = BUF_strdup(s->ctx->psk_identity_hint); | 
| +			if (s->ctx->psk_identity_hint != NULL && | 
| +				s->session->psk_identity_hint == NULL) | 
| +				{ | 
| +				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, | 
| +					ERR_R_MALLOC_FAILURE); | 
| +				goto psk_err; | 
| +				} | 
| + | 
| +			if (s->session->psk_identity != NULL) | 
| +				OPENSSL_free(s->session->psk_identity); | 
| +			s->session->psk_identity = BUF_strdup(identity); | 
| +			if (s->session->psk_identity == NULL) | 
| +				{ | 
| +				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, | 
| +					ERR_R_MALLOC_FAILURE); | 
| +				goto psk_err; | 
| +				} | 
| + | 
| +			s->session->master_key_length = | 
| +				s->method->ssl3_enc->generate_master_secret(s, | 
| +					s->session->master_key, | 
| +					psk_or_pre_ms, pre_ms_len); | 
| +			n = strlen(identity); | 
| +			s2n(n, p); | 
| +			memcpy(p, identity, n); | 
| +			n+=2; | 
| +			psk_err = 0; | 
| +		psk_err: | 
| +			OPENSSL_cleanse(identity, PSK_MAX_IDENTITY_LEN); | 
| +			OPENSSL_cleanse(psk_or_pre_ms, sizeof(psk_or_pre_ms)); | 
| +			if (psk_err != 0) | 
| +				{ | 
| +				ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); | 
| +				goto err; | 
| +				} | 
| +			} | 
| +#endif | 
| else | 
| { | 
| ssl3_send_alert(s, SSL3_AL_FATAL, | 
| @@ -2422,28 +2748,37 @@ | 
| unsigned char *p,*d; | 
| unsigned char data[MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH]; | 
| EVP_PKEY *pkey; | 
| +	EVP_PKEY_CTX *pctx=NULL; | 
| #ifndef OPENSSL_NO_RSA | 
| unsigned u=0; | 
| #endif | 
| unsigned long n; | 
| -#if !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_ECDSA) | 
| int j; | 
| -#endif | 
|  | 
| if (s->state == SSL3_ST_CW_CERT_VRFY_A) | 
| { | 
| d=(unsigned char *)s->init_buf->data; | 
| p= &(d[4]); | 
| pkey=s->cert->key->privatekey; | 
| - | 
| -		s->method->ssl3_enc->cert_verify_mac(s,&(s->s3->finish_dgst2), | 
| -			&(data[MD5_DIGEST_LENGTH])); | 
| - | 
| +/* Create context from key and test if sha1 is allowed as digest */ | 
| +		pctx = EVP_PKEY_CTX_new(pkey,NULL); | 
| +		EVP_PKEY_sign_init(pctx); | 
| +		if (EVP_PKEY_CTX_set_signature_md(pctx, EVP_sha1())>0) | 
| +			{ | 
| +			s->method->ssl3_enc->cert_verify_mac(s, | 
| +						NID_sha1, | 
| +						&(data[MD5_DIGEST_LENGTH])); | 
| +			} | 
| +		else | 
| +			{ | 
| +			ERR_clear_error(); | 
| +			} | 
| #ifndef OPENSSL_NO_RSA | 
| if (pkey->type == EVP_PKEY_RSA) | 
| { | 
| s->method->ssl3_enc->cert_verify_mac(s, | 
| -				&(s->s3->finish_dgst1),&(data[0])); | 
| +				NID_md5, | 
| +			 	&(data[0])); | 
| if (RSA_sign(NID_md5_sha1, data, | 
| MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH, | 
| &(p[2]), &u, pkey->pkey.rsa) <= 0 ) | 
| @@ -2489,10 +2824,30 @@ | 
| } | 
| else | 
| #endif | 
| -			{ | 
| +		if (pkey->type == NID_id_GostR3410_94 || pkey->type == NID_id_GostR3410_2001) | 
| +		{ | 
| +		unsigned char signbuf[64]; | 
| +		int i; | 
| +		size_t sigsize=64; | 
| +		s->method->ssl3_enc->cert_verify_mac(s, | 
| +			NID_id_GostR3411_94, | 
| +			data); | 
| +		if (EVP_PKEY_sign(pctx, signbuf, &sigsize, data, 32) <= 0) { | 
| +			SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY, | 
| +			ERR_R_INTERNAL_ERROR); | 
| +			goto err; | 
| +		} | 
| +		for (i=63,j=0; i>=0; j++, i--) { | 
| +			p[2+j]=signbuf[i]; | 
| +		} | 
| +		s2n(j,p); | 
| +		n=j+2; | 
| +		} | 
| +		else | 
| +		{ | 
| SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,ERR_R_INTERNAL_ERROR); | 
| goto err; | 
| -			} | 
| +		} | 
| *(d++)=SSL3_MT_CERTIFICATE_VERIFY; | 
| l2n3(n,d); | 
|  | 
| @@ -2500,8 +2855,10 @@ | 
| s->init_num=(int)n+4; | 
| s->init_off=0; | 
| } | 
| +	EVP_PKEY_CTX_free(pctx); | 
| return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); | 
| err: | 
| +	EVP_PKEY_CTX_free(pctx); | 
| return(-1); | 
| } | 
|  | 
| @@ -2586,7 +2943,7 @@ | 
| int ssl3_check_cert_and_algorithm(SSL *s) | 
| { | 
| int i,idx; | 
| -	long algs; | 
| +	long alg_k,alg_a; | 
| EVP_PKEY *pkey=NULL; | 
| SESS_CERT *sc; | 
| #ifndef OPENSSL_NO_RSA | 
| @@ -2596,14 +2953,14 @@ | 
| DH *dh; | 
| #endif | 
|  | 
| -	sc=s->session->sess_cert; | 
| +	alg_k=s->s3->tmp.new_cipher->algorithm_mkey; | 
| +	alg_a=s->s3->tmp.new_cipher->algorithm_auth; | 
|  | 
| -	algs=s->s3->tmp.new_cipher->algorithms; | 
| - | 
| /* we don't have a certificate */ | 
| -	if (algs & (SSL_aDH|SSL_aNULL|SSL_aKRB5)) | 
| +	if ((alg_a & (SSL_aDH|SSL_aNULL|SSL_aKRB5)) || (alg_k & SSL_kPSK)) | 
| return(1); | 
|  | 
| +	sc=s->session->sess_cert; | 
| if (sc == NULL) | 
| { | 
| SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,ERR_R_INTERNAL_ERROR); | 
| @@ -2623,11 +2980,11 @@ | 
| #ifndef OPENSSL_NO_ECDH | 
| if (idx == SSL_PKEY_ECC) | 
| { | 
| -		if (check_srvr_ecc_cert_and_alg(sc->peer_pkeys[idx].x509, | 
| +		if (ssl_check_srvr_ecc_cert_and_alg(sc->peer_pkeys[idx].x509, | 
| s->s3->tmp.new_cipher) == 0) | 
| { /* check failed */ | 
| SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_BAD_ECC_CERT); | 
| -			goto f_err; | 
| +			goto f_err; | 
| } | 
| else | 
| { | 
| @@ -2641,20 +2998,20 @@ | 
|  | 
|  | 
| /* Check that we have a certificate if we require one */ | 
| -	if ((algs & SSL_aRSA) && !has_bits(i,EVP_PK_RSA|EVP_PKT_SIGN)) | 
| +	if ((alg_a & SSL_aRSA) && !has_bits(i,EVP_PK_RSA|EVP_PKT_SIGN)) | 
| { | 
| SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_RSA_SIGNING_CERT); | 
| goto f_err; | 
| } | 
| #ifndef OPENSSL_NO_DSA | 
| -	else if ((algs & SSL_aDSS) && !has_bits(i,EVP_PK_DSA|EVP_PKT_SIGN)) | 
| +	else if ((alg_a & SSL_aDSS) && !has_bits(i,EVP_PK_DSA|EVP_PKT_SIGN)) | 
| { | 
| SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DSA_SIGNING_CERT); | 
| goto f_err; | 
| } | 
| #endif | 
| #ifndef OPENSSL_NO_RSA | 
| -	if ((algs & SSL_kRSA) && | 
| +	if ((alg_k & SSL_kRSA) && | 
| !(has_bits(i,EVP_PK_RSA|EVP_PKT_ENC) || (rsa != NULL))) | 
| { | 
| SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_RSA_ENCRYPTING_CERT); | 
| @@ -2662,19 +3019,19 @@ | 
| } | 
| #endif | 
| #ifndef OPENSSL_NO_DH | 
| -	if ((algs & SSL_kEDH) && | 
| +	if ((alg_k & SSL_kEDH) && | 
| !(has_bits(i,EVP_PK_DH|EVP_PKT_EXCH) || (dh != NULL))) | 
| { | 
| SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DH_KEY); | 
| goto f_err; | 
| } | 
| -	else if ((algs & SSL_kDHr) && !has_bits(i,EVP_PK_DH|EVP_PKS_RSA)) | 
| +	else if ((alg_k & SSL_kDHr) && !has_bits(i,EVP_PK_DH|EVP_PKS_RSA)) | 
| { | 
| SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DH_RSA_CERT); | 
| goto f_err; | 
| } | 
| #ifndef OPENSSL_NO_DSA | 
| -	else if ((algs & SSL_kDHd) && !has_bits(i,EVP_PK_DH|EVP_PKS_DSA)) | 
| +	else if ((alg_k & SSL_kDHd) && !has_bits(i,EVP_PK_DH|EVP_PKS_DSA)) | 
| { | 
| SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DH_DSA_CERT); | 
| goto f_err; | 
| @@ -2685,7 +3042,7 @@ | 
| if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && !has_bits(i,EVP_PKT_EXP)) | 
| { | 
| #ifndef OPENSSL_NO_RSA | 
| -		if (algs & SSL_kRSA) | 
| +		if (alg_k & SSL_kRSA) | 
| { | 
| if (rsa == NULL | 
| || RSA_size(rsa)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) | 
| @@ -2697,7 +3054,7 @@ | 
| else | 
| #endif | 
| #ifndef OPENSSL_NO_DH | 
| -			if (algs & (SSL_kEDH|SSL_kDHr|SSL_kDHd)) | 
| +			if (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd)) | 
| { | 
| if (dh == NULL | 
| || DH_size(dh)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) | 
| @@ -2720,49 +3077,13 @@ | 
| return(0); | 
| } | 
|  | 
| +/* Check to see if handshake is full or resumed. Usually this is just a | 
| + * case of checking to see if a cache hit has occurred. In the case of | 
| + * session tickets we have to check the next message to be sure. | 
| + */ | 
|  | 
| -#ifndef OPENSSL_NO_ECDH | 
| -/* This is the complement of nid2curve_id in s3_srvr.c. */ | 
| -static int curve_id2nid(int curve_id) | 
| -{ | 
| -	/* ECC curves from draft-ietf-tls-ecc-01.txt (Mar 15, 2001) | 
| -	 * (no changes in draft-ietf-tls-ecc-03.txt [June 2003]) */ | 
| -	static int nid_list[26] = | 
| -	{ | 
| -		0, | 
| -		NID_sect163k1, /* sect163k1 (1) */ | 
| -		NID_sect163r1, /* sect163r1 (2) */ | 
| -		NID_sect163r2, /* sect163r2 (3) */ | 
| -		NID_sect193r1, /* sect193r1 (4) */ | 
| -		NID_sect193r2, /* sect193r2 (5) */ | 
| -		NID_sect233k1, /* sect233k1 (6) */ | 
| -		NID_sect233r1, /* sect233r1 (7) */ | 
| -		NID_sect239k1, /* sect239k1 (8) */ | 
| -		NID_sect283k1, /* sect283k1 (9) */ | 
| -		NID_sect283r1, /* sect283r1 (10) */ | 
| -		NID_sect409k1, /* sect409k1 (11) */ | 
| -		NID_sect409r1, /* sect409r1 (12) */ | 
| -		NID_sect571k1, /* sect571k1 (13) */ | 
| -		NID_sect571r1, /* sect571r1 (14) */ | 
| -		NID_secp160k1, /* secp160k1 (15) */ | 
| -		NID_secp160r1, /* secp160r1 (16) */ | 
| -		NID_secp160r2, /* secp160r2 (17) */ | 
| -		NID_secp192k1, /* secp192k1 (18) */ | 
| -		NID_X9_62_prime192v1, /* secp192r1 (19) */ | 
| -		NID_secp224k1, /* secp224k1 (20) */ | 
| -		NID_secp224r1, /* secp224r1 (21) */ | 
| -		NID_secp256k1, /* secp256k1 (22) */ | 
| -		NID_X9_62_prime256v1, /* secp256r1 (23) */ | 
| -		NID_secp384r1, /* secp384r1 (24) */ | 
| -		NID_secp521r1  /* secp521r1 (25) */ | 
| -	}; | 
| - | 
| -	if ((curve_id < 1) || (curve_id > 25)) return 0; | 
| - | 
| -	return nid_list[curve_id]; | 
| -} | 
| -#endif | 
| - | 
| +#ifndef OPENSSL_NO_TLSEXT | 
| +# ifndef OPENSSL_NO_NEXTPROTONEG | 
| int ssl3_send_next_proto(SSL *s) | 
| { | 
| unsigned int len, padding_len; | 
| @@ -2785,23 +3106,15 @@ | 
| } | 
|  | 
| return ssl3_do_write(s, SSL3_RT_HANDSHAKE); | 
| -} | 
| +	} | 
| +# endif | 
|  | 
| -/* Check to see if handshake is full or resumed. Usually this is just a | 
| - * case of checking to see if a cache hit has occurred. In the case of | 
| - * session tickets we have to check the next message to be sure. | 
| - */ | 
| - | 
| -#ifndef OPENSSL_NO_TLSEXT | 
| int ssl3_check_finished(SSL *s) | 
| { | 
| int ok; | 
| long n; | 
| -	/* If we have no ticket or session ID is non-zero length (a match of | 
| -	 * a non-zero session length would never reach here) it cannot be a | 
| -	 * resumed session. | 
| -	 */ | 
| -	if (!s->session->tlsext_tick || s->session->session_id_length) | 
| +	/* If we have no ticket it cannot be a resumed session. */ | 
| +	if (!s->session->tlsext_tick) | 
| return 1; | 
| /* this function is called when we really expect a Certificate | 
| * message, so permit appropriate message length */ | 
|  |