CVE-2015-1792 (published 2015-06-12T19:59Z)

The do_free_upto function in crypto/cms/cms_smime.c in OpenSSL before 0.9.8zg, 1.0.0 before 1.0.0s, 1.0.1 before 1.0.1n, and 1.0.2 before 1.0.2b allows remote attackers to cause a denial of service (infinite loop) via vectors that trigger a NULL value of a BIO data structure, as demonstrated by an unrecognized X.660 OID for a hash function.

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

Weakness information:
cwe_id: CWE-399
cwe_name: Resource Management Errors
description: Weaknesses in this category are related to improper management of system resources.

Fix information:
repo_url: https://github.com/openssl/openssl
commit_details: repo_url: https://github.com/openssl/openssl
author: Dr. Stephen Henson
author_date: 2013-12-22 00:35:29+00:00
msg: Canonicalise input in CMS_verify.

If content is detached and not binary mode translate the input to
CRLF format. Before this change the input was verified verbatim
which lead to a discrepancy between sign and verify.
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: cms_smime.c
change_type: ModificationType.MODIFY
diff: @@ -60,21 +60,28 @@
 #include "cms_lcl.h"
 #include "asn1_locl.h"
 
-static int cms_copy_content(BIO *out, BIO *in, unsigned int flags)
+static BIO *cms_get_text_bio(BIO *out, unsigned int flags)
 	{
-	unsigned char buf[4096];
-	int r = 0, i;
-	BIO *tmpout = NULL;
-
+	BIO *rbio;
 	if (out == NULL)
-		tmpout = BIO_new(BIO_s_null());
+		rbio = BIO_new(BIO_s_null());
 	else if (flags & CMS_TEXT)
 		{
-		tmpout = BIO_new(BIO_s_mem());
-		BIO_set_mem_eof_return(tmpout, 0);
+		rbio = BIO_new(BIO_s_mem());
+		BIO_set_mem_eof_return(rbio, 0);
 		}
 	else
-		tmpout = out;
+		rbio = out;
+	return rbio;
+	}
+
+static int cms_copy_content(BIO *out, BIO *in, unsigned int flags)
+	{
+	unsigned char buf[4096];
+	int r = 0, i;
+	BIO *tmpout;
+
+	tmpout = cms_get_text_bio(out, flags);
 
 	if(!tmpout)
 		{
@@ -142,7 +149,7 @@ static void do_free_upto(BIO *f, BIO *upto)
 			BIO_free(f);
 			f = tbio;
 			}
-		while (f != upto);
+		while (f && f != upto);
 		}
 	else
 		BIO_free_all(f);
@@ -323,7 +330,7 @@ int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
 	STACK_OF(X509_CRL) *crls = NULL;
 	X509 *signer;
 	int i, scount = 0, ret = 0;
-	BIO *cmsbio = NULL, *tmpin = NULL;
+	BIO *cmsbio = NULL, *tmpin = NULL, *tmpout = NULL;
 
 	if (!dcont && !check_content(cms))
 		return 0;
@@ -406,15 +413,48 @@ int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
 		}
 	else
 		tmpin = dcont;
-		
+	/* If not binary mode and detached generate digests by *writing*
+	 * through the BIO. That makes it possible to canonicalise the
+	 * input.
+	 */
+	if (!(flags & SMIME_BINARY) && dcont)
+		{
+		/* Create output BIO so we can either handle text or to
+		 * ensure included content doesn't override detached content.
+		 */
+		tmpout = cms_get_text_bio(out, flags);
+		if(!tmpout)
+			{
+			CMSerr(CMS_F_CMS_VERIFY,ERR_R_MALLOC_FAILURE);
+			goto err;
+			}
+		cmsbio = CMS_dataInit(cms, tmpout);
+		if (!cmsbio)
+			goto err;
+		/* Don't use SMIME_TEXT for verify: it adds headers and
+		 * we want to remove them.
+		 */
+		SMIME_crlf_copy(dcont, cmsbio, flags & ~SMIME_TEXT);
 
-	cmsbio=CMS_dataInit(cms, tmpin);
-	if (!cmsbio)
-		goto err;
+		if(flags & CMS_TEXT)
+			{
+			if (!SMIME_text(tmpout, out))
+				{
+				CMSerr(CMS_F_CMS_VERIFY,CMS_R_SMIME_TEXT_ERROR);
+				goto err;
+				}
+			}
+		}
+	else
+		{
+		cmsbio=CMS_dataInit(cms, tmpin);
+		if (!cmsbio)
+			goto err;
 
-	if (!cms_copy_content(out, cmsbio, flags))
-		goto err;
+		if (!cms_copy_content(out, cmsbio, flags))
+			goto err;
 
+		}
 	if (!(flags & CMS_NO_CONTENT_VERIFY))
 		{
 		for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++)
@@ -432,11 +472,23 @@ int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
 	ret = 1;
 
 	err:
-	
-	if (dcont && (tmpin == dcont))
-		do_free_upto(cmsbio, dcont);
+	if (!(flags & SMIME_BINARY) && dcont)
+		{
+		do_free_upto(cmsbio, tmpout);
+		if (tmpin != dcont)
+			BIO_free(tmpin);
+		}
 	else
-		BIO_free_all(cmsbio);
+		{
+
+		if (dcont && (tmpin == dcont))
+			do_free_upto(cmsbio, dcont);
+		else
+			BIO_free_all(cmsbio);
+		}
+
+	if (tmpout && out != tmpout)
+		BIO_free_all(tmpout);
 
 	if (cms_certs)
 		sk_X509_pop_free(cms_certs, X509_free);

programming_language: C