CVE-2014-3572 (published 2015-01-09T02:59Z)

The ssl3_get_key_exchange function in s3_clnt.c in OpenSSL before 0.9.8zd, 1.0.0 before 1.0.0p, and 1.0.1 before 1.0.1k allows remote SSL servers to conduct ECDHE-to-ECDH downgrade attacks and trigger a loss of forward secrecy by omitting the ServerKeyExchange message.

Severity: MEDIUM
CVSS v2 base score: 5.0 (AV:N/AC:L/Au:N/C:N/I:P/A:N)

Weakness information:
cwe_id: CWE-310
cwe_name: Cryptographic Issues
description: Weaknesses in this category are related to the design and implementation of data confidentiality and integrity. Frequently these deal with the use of encoding techniques, encryption libraries, and hashing algorithms. The weaknesses in this category could lead to a degradation of the quality data if they are not addressed.

Fix information:
repo_url: https://github.com/openssl/openssl
commit_details: repo_url: https://github.com/openssl/openssl
author: Dr. Stephen Henson
author_date: 2014-10-24 12:30:33+01:00
msg: ECDH downgrade bug fix.

Fix bug where an OpenSSL client would accept a handshake using an
ephemeral ECDH ciphersuites with the server key exchange message omitted.

Thanks to Karthikeyan Bhargavan for reporting this issue.

CVE-2014-3572
Reviewed-by: Matt Caswell <matt@openssl.org>
repository: repo_url: https://github.com/openssl/openssl
repo_name: openssl/openssl
description: TLS/SSL and crypto library
repo_language: C
owner: openssl
file_changes: filename: CHANGES
change_type: ModificationType.MODIFY
diff: @@ -659,6 +659,13 @@
 
  Changes between 1.0.1j and 1.0.1k [xx XXX xxxx]
 
+  *) Abort handshake if server key exchange message is omitted for ephemeral
+     ECDH ciphersuites.
+
+     Thanks to Karthikeyan Bhargavan for reporting this issue.
+     (CVE-2014-3572)
+     [Steve Henson]
+
   *) Ensure that the session ID context of an SSL is updated when its
      SSL_CTX is updated via SSL_set_SSL_CTX.
 

programming_language: Markdown
filename: s3_clnt.c
change_type: ModificationType.MODIFY
diff: @@ -1376,6 +1376,8 @@ int ssl3_get_key_exchange(SSL *s)
 	int encoded_pt_len = 0;
 #endif
 
+	EVP_MD_CTX_init(&md_ctx);
+
 	/* use same message size as in ssl3_get_certificate_request()
 	 * as ServerKeyExchange message may be skipped */
 	n=s->method->ssl_get_message(s,
@@ -1386,14 +1388,26 @@ int ssl3_get_key_exchange(SSL *s)
 		&ok);
 	if (!ok) return((int)n);
 
+	alg_k=s->s3->tmp.new_cipher->algorithm_mkey;
+
 	if (s->s3->tmp.message_type != SSL3_MT_SERVER_KEY_EXCHANGE)
 		{
+		/*
+		 * Can't skip server key exchange if this is an ephemeral
+		 * ciphersuite.
+		 */
+		if (alg_k & (SSL_kDHE|SSL_kECDHE))
+			{
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_UNEXPECTED_MESSAGE);
+			al = SSL_AD_UNEXPECTED_MESSAGE;
+			goto f_err;
+			}
 #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)
+		if (alg_k & SSL_kPSK)
 			{
 			s->session->sess_cert=ssl_sess_cert_new();
 			if (s->ctx->psk_identity_hint)
@@ -1438,9 +1452,7 @@ int ssl3_get_key_exchange(SSL *s)
 	/* Total length of the parameters including the length prefix */
 	param_len=0;
 
-	alg_k=s->s3->tmp.new_cipher->algorithm_mkey;
 	alg_a=s->s3->tmp.new_cipher->algorithm_auth;
-	EVP_MD_CTX_init(&md_ctx);
 
 	al=SSL_AD_DECODE_ERROR;
 

programming_language: C