[patch] OpenSSL in base: fix CVE-2009-3555

Eygene Ryabinkin rea-fbsd at codelabs.ru
Sat Nov 7 13:43:50 UTC 2009


>Submitter-Id:	current-users
>Originator:	Eygene Ryabinkin
>Organization:	Code Labs
>Confidential:	no 
>Synopsis:	[patch] OpenSSL in base: fix CVE-2009-3555
>Severity:	critical
>Priority:	high
>Category:	bin
>Class:		sw-bug
>Release:	FreeBSD 8.0-BETA2 amd64
>Environment:

System: FreeBSD 8.0-BETA2 amd64

>Description:

See [1] (not much information just now) and [2].

>How-To-Repeat:

[1] http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2009-3555
[2] http://cvs.openssl.org/fileview?f=openssl-web/news/announce.txt&v=1.52

>Fix:

The following patch applies to OpenSSL both from HEAD and 8-STABLE.

It completely disables renegotiation inside TLS/SSL sessions and I had
verified that no renegotiations will take place with s_client and
s_server.

--- fix-cve-2009-3555.diff begins here ---
>From 01c641ca1a88d08fea282f79ff0f1a86d5319ba7 Mon Sep 17 00:00:00 2001
From: Eygene Ryabinkin <rea-fbsd at codelabs.ru>
Date: Sat, 7 Nov 2009 15:45:32 +0300

Obtained-From: http://cvs.openssl.org/chngview?cn=18791
Obtained-From: http://cvs.openssl.org/chngview?cn=18794

Signed-off-by: Eygene Ryabinkin <rea-fbsd at codelabs.ru>
---
 crypto/openssl/CHANGES       |    9 +++++++++
 crypto/openssl/ssl/s3_lib.c  |    3 +++
 crypto/openssl/ssl/s3_pkt.c  |    4 +++-
 crypto/openssl/ssl/s3_srvr.c |    8 ++++++++
 crypto/openssl/ssl/ssl.h     |    1 +
 crypto/openssl/ssl/ssl3.h    |    9 +++++----
 crypto/openssl/ssl/ssl_err.c |    1 +
 7 files changed, 30 insertions(+), 5 deletions(-)

diff --git a/crypto/openssl/CHANGES b/crypto/openssl/CHANGES
index 04d332e..cd445c9 100644
--- a/crypto/openssl/CHANGES
+++ b/crypto/openssl/CHANGES
@@ -2,6 +2,15 @@
  OpenSSL CHANGES
  _______________
 
+ Changes between 0.9.8k and 0.9.8l  [5 Nov 2009]
+
+  *) Disable renegotiation completely - this fixes a severe security
+     problem at the cost of breaking all renegotiation. Renegotiation
+     can be re-enabled by setting
+     OPENSSL_ENABLE_UNSAFE_LEGACY_SESSION_RENEGOTATION at
+     compile-time. This is really not recommended.
+     [Ben Laurie]
+
  Changes between 0.9.8j and 0.9.8k  [25 Mar 2009]
 
   *) Don't set val to NULL when freeing up structures, it is freed up by
diff --git a/crypto/openssl/ssl/s3_lib.c b/crypto/openssl/ssl/s3_lib.c
index 8916a0b..5aa7bb2 100644
--- a/crypto/openssl/ssl/s3_lib.c
+++ b/crypto/openssl/ssl/s3_lib.c
@@ -2592,6 +2592,9 @@ int ssl3_renegotiate(SSL *s)
 	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;
 	return(1);
 	}
diff --git a/crypto/openssl/ssl/s3_pkt.c b/crypto/openssl/ssl/s3_pkt.c
index 9476dcd..b98b840 100644
--- a/crypto/openssl/ssl/s3_pkt.c
+++ b/crypto/openssl/ssl/s3_pkt.c
@@ -985,6 +985,7 @@ start:
 
 		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);
@@ -1117,7 +1118,8 @@ start:
 	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_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
diff --git a/crypto/openssl/ssl/s3_srvr.c b/crypto/openssl/ssl/s3_srvr.c
index 80b45eb..79f3706 100644
--- a/crypto/openssl/ssl/s3_srvr.c
+++ b/crypto/openssl/ssl/s3_srvr.c
@@ -718,6 +718,14 @@ int ssl3_get_client_hello(SSL *s)
 #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.
diff --git a/crypto/openssl/ssl/ssl.h b/crypto/openssl/ssl/ssl.h
index ff8a128..5ef11a3 100644
--- a/crypto/openssl/ssl/ssl.h
+++ b/crypto/openssl/ssl/ssl.h
@@ -1952,6 +1952,7 @@ void ERR_load_SSL_strings(void);
 #define SSL_R_NO_PRIVATE_KEY_ASSIGNED			 190
 #define SSL_R_NO_PROTOCOLS_AVAILABLE			 191
 #define SSL_R_NO_PUBLICKEY				 192
+#define SSL_R_NO_RENEGOTIATION				 318
 #define SSL_R_NO_SHARED_CIPHER				 193
 #define SSL_R_NO_VERIFY_CALLBACK			 194
 #define SSL_R_NULL_SSL_CTX				 195
diff --git a/crypto/openssl/ssl/ssl3.h b/crypto/openssl/ssl/ssl3.h
index 4b1e2e9..a1a19cb 100644
--- a/crypto/openssl/ssl/ssl3.h
+++ b/crypto/openssl/ssl/ssl3.h
@@ -326,10 +326,11 @@ typedef struct ssl3_buffer_st
 #define SSL3_CT_NUMBER			7
 
 
-#define SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS	0x0001
-#define SSL3_FLAGS_DELAY_CLIENT_FINISHED	0x0002
-#define SSL3_FLAGS_POP_BUFFER			0x0004
-#define TLS1_FLAGS_TLS_PADDING_BUG		0x0008
+#define SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS		0x0001
+#define SSL3_FLAGS_DELAY_CLIENT_FINISHED		0x0002
+#define SSL3_FLAGS_POP_BUFFER				0x0004
+#define TLS1_FLAGS_TLS_PADDING_BUG			0x0008
+#define SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION	0x0010
 
 typedef struct ssl3_state_st
 	{
diff --git a/crypto/openssl/ssl/ssl_err.c b/crypto/openssl/ssl/ssl_err.c
index 24a994f..ce2a555 100644
--- a/crypto/openssl/ssl/ssl_err.c
+++ b/crypto/openssl/ssl/ssl_err.c
@@ -384,6 +384,7 @@ static ERR_STRING_DATA SSL_str_reasons[]=
 {ERR_REASON(SSL_R_NO_PRIVATE_KEY_ASSIGNED),"no private key assigned"},
 {ERR_REASON(SSL_R_NO_PROTOCOLS_AVAILABLE),"no protocols available"},
 {ERR_REASON(SSL_R_NO_PUBLICKEY)          ,"no publickey"},
+{ERR_REASON(SSL_R_NO_RENEGOTIATION)      ,"no renegotiation"},
 {ERR_REASON(SSL_R_NO_SHARED_CIPHER)      ,"no shared cipher"},
 {ERR_REASON(SSL_R_NO_VERIFY_CALLBACK)    ,"no verify callback"},
 {ERR_REASON(SSL_R_NULL_SSL_CTX)          ,"null ssl ctx"},
-- 
1.6.3.1
--- fix-cve-2009-3555.diff ends here ---

It will be very good if __FreeBSD_version will be bumped after this
update, because there are some fixes for the ports that use OpenSSL,
but disable renegotiation by themselves.  These fixes shouldn't be
applied when system OpenSSL will be updated (port was already
updated to 0.9.8k).


More information about the freebsd-security mailing list