diff -cr ../openssl-0.9.8l/ssl/d1_both.c ssl/d1_both.c
*** ../openssl-0.9.8l/ssl/d1_both.c	Wed Oct 17 23:17:48 2007
--- ssl/d1_both.c	Mon Dec  7 17:34:33 2009
***************
*** 739,744 ****
--- 739,756 ----
  		p+=i;
  		l=i;
  
+ 		/* memorize verify_data for secure TLS renegotiation */
+ 		if( (s->server) )
+ 			{
+ 			memcpy(s->s3->previous_server_finished, s->s3->tmp.finish_md, i);
+ 			s->s3->previous_server_finished_len=i;
+ 			}
+ 		else
+ 			{
+ 			memcpy(s->s3->previous_client_finished, s->s3->tmp.finish_md, i);
+ 			s->s3->previous_client_finished_len=i;
+ 			}
+ 
  #ifdef OPENSSL_SYS_WIN16
  		/* MSVC 1.5 does not clear the top bytes of the word unless
  		 * I do this.
diff -cr ../openssl-0.9.8l/ssl/s3_both.c ssl/s3_both.c
*** ../openssl-0.9.8l/ssl/s3_both.c	Tue Apr 26 18:02:38 2005
--- ssl/s3_both.c	Mon Dec  7 20:28:43 2009
***************
*** 168,173 ****
--- 168,185 ----
  		p+=i;
  		l=i;
  
+ 		/* memorize verify_data for secure TLS renegotiation */
+ 		if ( (s->server) )
+ 			{
+ 			memcpy(s->s3->previous_server_finished, s->s3->tmp.finish_md, i);
+ 			s->s3->previous_server_finished_len=i;
+ 			}
+ 		else
+ 			{
+ 			memcpy(s->s3->previous_client_finished, s->s3->tmp.finish_md, i);
+ 			s->s3->previous_client_finished_len=i;
+ 			}
+ 
  #ifdef OPENSSL_SYS_WIN16
  		/* MSVC 1.5 does not clear the top bytes of the word unless
  		 * I do this.
***************
*** 232,237 ****
--- 244,263 ----
  		goto f_err;
  		}
  
+ 	/* memorize verify_data for secure TLS renegotiation */
+ 	if( (s->server) )
+ 		{
+ 		memcpy(s->s3->previous_client_finished, s->s3->tmp.peer_finish_md, i);
+ 		s->s3->previous_client_finished_len=i;
+ 		}
+ 	else
+ 		{
+ 		memcpy(s->s3->previous_server_finished, s->s3->tmp.peer_finish_md, i);
+ 		s->s3->previous_server_finished_len=i;
+ 		}
+ 	if ((s->s3->protection_available))
+ 		s->session->allow_old_renego = 0;
+ 
  	return(1);
  f_err:
  	ssl3_send_alert(s,SSL3_AL_FATAL,al);
diff -cr ../openssl-0.9.8l/ssl/s3_clnt.c ssl/s3_clnt.c
*** ../openssl-0.9.8l/ssl/s3_clnt.c	Sat Feb 14 22:50:14 2009
--- ssl/s3_clnt.c	Mon Dec  7 23:17:54 2009
***************
*** 869,876 ****
  				goto err;
  			}
  		}
  #endif
! 
  
  	if (p != (d+n))
  		{
--- 869,883 ----
  				goto err;
  			}
  		}
+ 		else
  #endif
! 	if ( (p+sizeof(tlsext_renego_protection)) == (d+n) &&
! 		!memcmp(p,tlsext_renego_protection,sizeof(tlsext_renego_protection)) )
! 		{
! 		s->s3->protection_available  = 1;
! 		s->session->allow_old_renego = 0;
! 		p += sizeof(tlsext_renego_protection);
! 		}
  
  	if (p != (d+n))
  		{
***************
*** 879,884 ****
--- 886,896 ----
  		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_BAD_PACKET_LENGTH);
  		goto err;
  		}
+ 	if ( ssl3_renego_protection_handshake_update(s, &al) < 0 )
+ 		{
+ 		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
+ 		goto f_err;
+ 		}
  
  	return(1);
  f_err:
diff -cr ../openssl-0.9.8l/ssl/s3_enc.c ssl/s3_enc.c
*** ../openssl-0.9.8l/ssl/s3_enc.c	Mon Jun 16 18:56:40 2008
--- ssl/s3_enc.c	Mon Dec  7 23:18:01 2009
***************
*** 523,528 ****
--- 523,529 ----
  		EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
  	EVP_DigestInit_ex(&(s->s3->finish_dgst1),s->ctx->md5, NULL);
  	EVP_DigestInit_ex(&(s->s3->finish_dgst2),s->ctx->sha1, NULL);
+ 	s->s3->protection_available = 0;
  	}
  
  void ssl3_finish_mac(SSL *s, const unsigned char *buf, int len)
diff -cr ../openssl-0.9.8l/ssl/s3_lib.c ssl/s3_lib.c
*** ../openssl-0.9.8l/ssl/s3_lib.c	Thu Nov  5 16:51:52 2009
--- ssl/s3_lib.c	Mon Dec  7 21:03:50 2009
***************
*** 2592,2598 ****
  	if (s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)
  		return(0);
  
! 	if (!(s->s3->flags & SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION))
  		return(0);
  
  	s->s3->renegotiate=1;
--- 2592,2599 ----
  	if (s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)
  		return(0);
  
! 	if (!((s->s3->protection_available) || (NULL == s->enc_read_ctx) ||
! 	      ((NULL != s->session) && (s->session->allow_old_renego))) )
  		return(0);
  
  	s->s3->renegotiate=1;
diff -cr ../openssl-0.9.8l/ssl/s3_pkt.c ssl/s3_pkt.c
*** ../openssl-0.9.8l/ssl/s3_pkt.c	Thu Nov  5 16:52:52 2009
--- ssl/s3_pkt.c	Mon Dec  7 20:46:57 2009
***************
*** 985,991 ****
  
  		if (SSL_is_init_finished(s) &&
  			!(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) &&
- 			(s->s3->flags & SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION) &&
  			!s->s3->renegotiate)
  			{
  			ssl3_renegotiate(s);
--- 985,990 ----
***************
*** 1118,1125 ****
  	if ((s->s3->handshake_fragment_len >= 4) &&	!s->in_handshake)
  		{
  		if (((s->state&SSL_ST_MASK) == SSL_ST_OK) &&
! 			!(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) &&
! 			(s->s3->flags & SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION))
  			{
  #if 0 /* worked only because C operator preferences are not as expected (and
         * because this is not really needed for clients except for detecting
--- 1117,1123 ----
  	if ((s->s3->handshake_fragment_len >= 4) &&	!s->in_handshake)
  		{
  		if (((s->state&SSL_ST_MASK) == SSL_ST_OK) &&
! 			!(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) )
  			{
  #if 0 /* worked only because C operator preferences are not as expected (and
         * because this is not really needed for clients except for detecting
diff -cr ../openssl-0.9.8l/ssl/s3_srvr.c ssl/s3_srvr.c
*** ../openssl-0.9.8l/ssl/s3_srvr.c	Thu Nov  5 16:52:10 2009
--- ssl/s3_srvr.c	Mon Dec  7 23:18:09 2009
***************
*** 718,731 ****
  #endif
  	STACK_OF(SSL_CIPHER) *ciphers=NULL;
  
- 	if (s->new_session
- 	    && !(s->s3->flags&SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION))
- 		{
- 		al=SSL_AD_HANDSHAKE_FAILURE;
- 		SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
- 		goto f_err;
- 		}
- 
  	/* We do this so that we will respond with our native type.
  	 * If we are TLSv1 and we get SSLv3, we will respond with TLSv1,
  	 * This down switching should be handled by a different method.
--- 718,723 ----
***************
*** 1106,1117 ****
--- 1098,1145 ----
  	return(ret);
  	}
  
+ unsigned char tlsext_renego_protection[6] =
+ 	{
+ 	0, 4, ((TLSEXT_TYPE_renego_protection>>8)&0xff), (TLSEXT_TYPE_renego_protection&0xff), 0, 0
+ 	};
+ 
+ int ssl3_renego_protection_handshake_update( SSL *s, int *al)
+ 	{
+ 	if ( (s->s3->protection_available) )
+ 		{
+ 		if ( (NULL == s->enc_read_ctx) )
+ 			{
+ 			ssl3_finish_mac(s, TLS_RENEGO_PROTECTION_PREFIX_INITIAL, TLS_RENEGO_PROTECTION_PREFIX_LEN);
+ 			}
+ 		else
+ 			{
+ 			ssl3_finish_mac(s, TLS_RENEGO_PROTECTION_PREFIX_RENEGO, TLS_RENEGO_PROTECTION_PREFIX_LEN);
+ 			ssl3_finish_mac(s, s->s3->previous_client_finished, s->s3->previous_client_finished_len);
+ 			ssl3_finish_mac(s, s->s3->previous_server_finished, s->s3->previous_server_finished_len);
+ 			}
+ 		}
+ 	else
+ 		{
+ 		if ( (NULL != s->enc_read_ctx) )
+ 			{
+ 			if ( !(s->session->allow_old_renego) )
+ 				{
+ 				(*al) = SSL_AD_HANDSHAKE_FAILURE;
+ 				return -1;
+ 				}
+ 			}
+ 		}
+ 	return 1;
+ 	}
+ 
  int ssl3_send_server_hello(SSL *s)
  	{
  	unsigned char *buf;
  	unsigned char *p,*d;
  	int i,sl;
  	unsigned long l,Time;
+ 	int ret = -1;
+ 	int al;
  
  	if (s->state == SSL3_ST_SW_SRVR_HELLO_A)
  		{
***************
*** 1179,1184 ****
--- 1207,1223 ----
  			SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO,ERR_R_INTERNAL_ERROR);
  			return -1;
  			}
+ #else
+ 		if ( (s->s3->protection_available) )
+ 			{
+ 			if ((p+sizeof(tlsext_renego_protection)) > (buf+SSL3_RT_MAX_PLAIN_LENGTH))
+ 				{
+ 				SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO,ERR_R_INTERNAL_ERROR);
+ 				return -1;
+ 				}   
+ 			memcpy(p, tlsext_renego_protection, sizeof(tlsext_renego_protection));
+ 			p += sizeof(tlsext_renego_protection);
+ 			}
  #endif
  		/* do the header */
  		l=(p-d);
***************
*** 1193,1199 ****
  		}
  
  	/* SSL3_ST_SW_SRVR_HELLO_B */
! 	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
  	}
  
  int ssl3_send_server_done(SSL *s)
--- 1232,1246 ----
  		}
  
  	/* SSL3_ST_SW_SRVR_HELLO_B */
! 	ret = ssl3_do_write(s,SSL3_RT_HANDSHAKE);
! 	if ((ret > 0) && (ssl3_renego_protection_handshake_update(s, &al) < 0))
! 		{
! 		SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO, SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
! 		ssl3_send_alert(s,SSL3_AL_FATAL,al);
! 		ret = -1;
! 		}
! 
! 	return(ret);
  	}
  
  int ssl3_send_server_done(SSL *s)
diff -cr ../openssl-0.9.8l/ssl/ssl.h ssl/ssl.h
*** ../openssl-0.9.8l/ssl/ssl.h	Thu Nov  5 13:15:40 2009
--- ssl/ssl.h	Mon Dec  7 17:44:20 2009
***************
*** 480,485 ****
--- 480,486 ----
  	size_t	tlsext_ticklen;		/* Session ticket length */	
  	long tlsext_tick_lifetime_hint;	/* Session lifetime hint in seconds */
  #endif
+ 	int  allow_old_renego;
  	} SSL_SESSION;
  
  
***************
*** 492,497 ****
--- 493,499 ----
  #define SSL_OP_SSLEAY_080_CLIENT_DH_BUG			0x00000080L
  #define SSL_OP_TLS_D5_BUG				0x00000100L
  #define SSL_OP_TLS_BLOCK_PADDING_BUG			0x00000200L
+ #define SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION	0x00000400L
  
  /* Disable SSL 3.0/TLS 1.0 CBC vulnerability workaround that was added
   * in OpenSSL 0.9.6d.  Usually (depending on the application protocol)
***************
*** 502,508 ****
  
  /* SSL_OP_ALL: various bug workarounds that should be rather harmless.
   *             This used to be 0x000FFFFFL before 0.9.7. */
! #define SSL_OP_ALL					0x00000FFFL
  
  /* DTLS options */
  #define SSL_OP_NO_QUERY_MTU                 0x00001000L
--- 504,510 ----
  
  /* SSL_OP_ALL: various bug workarounds that should be rather harmless.
   *             This used to be 0x000FFFFFL before 0.9.7. */
! #define SSL_OP_ALL					(0x00000FFFL & ~SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)
  
  /* DTLS options */
  #define SSL_OP_NO_QUERY_MTU                 0x00001000L
***************
*** 2053,2058 ****
--- 2055,2061 ----
  #define SSL_R_UNKNOWN_REMOTE_ERROR_TYPE			 253
  #define SSL_R_UNKNOWN_SSL_VERSION			 254
  #define SSL_R_UNKNOWN_STATE				 255
+ #define SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED	 323
  #define SSL_R_UNSUPPORTED_CIPHER			 256
  #define SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM		 257
  #define SSL_R_UNSUPPORTED_ELLIPTIC_CURVE		 315
diff -cr ../openssl-0.9.8l/ssl/ssl3.h ssl/ssl3.h
*** ../openssl-0.9.8l/ssl/ssl3.h	Thu Nov  5 16:52:02 2009
--- ssl/ssl3.h	Mon Dec  7 20:47:11 2009
***************
*** 441,446 ****
--- 441,452 ----
  		int cert_request;
  		} tmp;
  
+ 	/* additional session state for secure TLS renegotiation */
+ 	unsigned char previous_client_finished[EVP_MAX_MD_SIZE*2];
+ 	unsigned char previous_client_finished_len;
+ 	unsigned char previous_server_finished[EVP_MAX_MD_SIZE*2];
+ 	unsigned char previous_server_finished_len;
+ 	int protection_available;
  	} SSL3_STATE;
  
  
diff -cr ../openssl-0.9.8l/ssl/ssl_lib.c ssl/ssl_lib.c
*** ../openssl-0.9.8l/ssl/ssl_lib.c	Mon Feb 23 17:02:46 2009
--- ssl/ssl_lib.c	Mon Dec  7 21:37:22 2009
***************
*** 1285,1290 ****
--- 1285,1297 ----
  		j = put_cb ? put_cb(c,p) : ssl_put_cipher_by_char(s,c,p);
  		p+=j;
  		}
+ 	if (p > q)
+ 		{
+ 		if ( (j>2) )
+ 			*(p++) = 0x00;
+ 		*(p++) = ((TLS1_CK_RENEGO_PROTECTION_REQUEST>>8) & 0xff);
+ 		*(p++) =  (TLS1_CK_RENEGO_PROTECTION_REQUEST     & 0xff);
+ 		}
  	return(p-q);
  	}
  
***************
*** 1311,1317 ****
  
  	for (i=0; i<num; i+=n)
  		{
! 		c=ssl_get_cipher_by_char(s,p);
  		p+=n;
  		if (c != NULL)
  			{
--- 1318,1333 ----
  
  	for (i=0; i<num; i+=n)
  		{
! 		/* (mrex) Check for magic cipher suite value (MCSV) */
! 		if ((NULL != s->s3) &&
!                     ((TLS1_CK_RENEGO_PROTECTION_REQUEST&0xffff) == ((p[n-2]<<8)+p[n-1])))
! 			{
! 			s->s3->protection_available  = 1;
! 			s->session->allow_old_renego = 0;
! 			c = NULL;
! 			}
! 		else
! 			c=ssl_get_cipher_by_char(s,p);
  		p+=n;
  		if (c != NULL)
  			{
diff -cr ../openssl-0.9.8l/ssl/ssl_locl.h ssl/ssl_locl.h
*** ../openssl-0.9.8l/ssl/ssl_locl.h	Mon Jan  5 15:43:06 2009
--- ssl/ssl_locl.h	Mon Dec  7 02:53:59 2009
***************
*** 979,982 ****
--- 979,985 ----
  void ssl_clear_hash_ctx(EVP_MD_CTX **hash);
  #endif
  
+ extern unsigned char tlsext_renego_protection[6];
+ int ssl3_renego_protection_handshake_update(SSL *s, int *al);
+ 
  #endif
diff -cr ../openssl-0.9.8l/ssl/ssl_sess.c ssl/ssl_sess.c
*** ../openssl-0.9.8l/ssl/ssl_sess.c	Wed Jun  4 20:35:26 2008
--- ssl/ssl_sess.c	Mon Dec  7 17:35:00 2009
***************
*** 181,186 ****
--- 181,187 ----
  	GEN_SESSION_CB cb = def_generate_session_id;
  
  	if ((ss=SSL_SESSION_new()) == NULL) return(0);
+ 	ss->allow_old_renego = (s->ctx->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION) ? 1 : 0;
  
  	/* If the context has a default timeout, use it */
  	if (s->ctx->session_timeout == 0)
***************
*** 190,195 ****
--- 191,198 ----
  
  	if (s->session != NULL)
  		{
+ 		if ((NULL != s->enc_read_ctx) && !(s->session->allow_old_renego))
+ 		    ss->allow_old_renego = 0;
  		SSL_SESSION_free(s->session);
  		s->session=NULL;
  		}
***************
*** 451,457 ****
--- 454,464 ----
  	 * if it is the same session, we have just incremented and
  	 * then decremented the reference count :-) */
  	if (s->session != NULL)
+ 		{
+ 		if ((NULL!=s->enc_read_ctx) && !(s->session->allow_old_renego))
+ 		    ret->allow_old_renego = 0;
  		SSL_SESSION_free(s->session);
+ 		}
  	s->session=ret;
  	s->verify_result = s->session->verify_result;
  	return(1);
***************
*** 641,647 ****
--- 648,658 ----
  		/* CRYPTO_w_lock(CRYPTO_LOCK_SSL);*/
  		CRYPTO_add(&session->references,1,CRYPTO_LOCK_SSL_SESSION);
  		if (s->session != NULL)
+ 			{
+ 			if ((NULL!=s->enc_read_ctx) && !(s->session->allow_old_renego))
+ 			    session->allow_old_renego = 0;
  			SSL_SESSION_free(s->session);
+ 			}
  		s->session=session;
  		s->verify_result = s->session->verify_result;
  		/* CRYPTO_w_unlock(CRYPTO_LOCK_SSL);*/
diff -cr ../openssl-0.9.8l/ssl/t1_lib.c ssl/t1_lib.c
*** ../openssl-0.9.8l/ssl/t1_lib.c	Thu Sep  4 00:13:04 2008
--- ssl/t1_lib.c	Mon Dec  7 17:30:41 2009
***************
*** 251,258 ****
--- 251,270 ----
  	int extdatalen=0;
  	unsigned char *ret = p;
  
+ 	if ((SSL3_VERSION == s->version) && !(s->s3->protection_available))
+ 		return p;
+ 
  	ret+=2;
  	if (ret>=limit) return NULL; /* this really never occurs, but ... */
+ 	if ((s->s3->protection_available))
+ 		{
+ 		if (limit - ret - 4 < 0) return NULL;
+ 
+ 		s2n(TLSEXT_TYPE_renego_protection,ret);
+ 		s2n(0,ret);
+ 		}
+ 	if (s->version == SSL3_VERSION)
+ 		goto finalize_extensions;
  
  	if (!s->hit && s->servername_done == 1 && s->session->tlsext_hostname != NULL)
  		{ 
***************
*** 277,282 ****
--- 289,295 ----
  		s2n(0,ret);
  		}
  
+ finalize_extensions:
  	if ((extdatalen = ret-p-2)== 0) 
  		return p;
  
***************
*** 574,579 ****
--- 587,597 ----
  			/* Set flag to expect CertificateStatus message */
  			s->tlsext_status_expected = 1;
  			}
+ 		else if (type == TLSEXT_TYPE_renego_protection)
+ 			{
+ 			s->s3->protection_available  = 1;
+ 			s->session->allow_old_renego = 0;
+ 			}
  
  		data+=size;		
  		}
diff -cr ../openssl-0.9.8l/ssl/tls1.h ssl/tls1.h
*** ../openssl-0.9.8l/ssl/tls1.h	Wed Apr 30 18:11:32 2008
--- ssl/tls1.h	Mon Dec  7 00:14:39 2009
***************
*** 184,189 ****
--- 184,196 ----
  
  #endif
  
+ /* mrex secure TLS renegotiation */
+ #define TLS_RENEGO_PROTECTION_PREFIX_INITIAL			"\x14\x00\x00\x0b"
+ #define TLS_RENEGO_PROTECTION_PREFIX_RENEGO				"\x14\xff\xff\xff"
+ #define TLS_RENEGO_PROTECTION_PREFIX_LEN				4
+ #define TLS1_CK_RENEGO_PROTECTION_REQUEST				0x0300BFFF
+ #define TLSEXT_TYPE_renego_protection					0xff02
+ 
  /* Additional TLS ciphersuites from draft-ietf-tls-56-bit-ciphersuites-00.txt
   * (available if TLS1_ALLOW_EXPERIMENTAL_CIPHERSUITES is defined, see
   * s3_lib.c).  We actually treat them like SSL 3.0 ciphers, which we probably
