PKCS7_verify() performance optimization. When the content is large and a
memory BIO (for example from SMIME_read_PKCS7 and detached data) avoid lots
of slow memory copies from the memory BIO by saving the content in a
temporary read only memory BIO.
diff --git a/crypto/pkcs7/pk7_smime.c b/crypto/pkcs7/pk7_smime.c
index 6aca022..f22c07f 100644
--- a/crypto/pkcs7/pk7_smime.c
+++ b/crypto/pkcs7/pk7_smime.c
@@ -157,7 +157,7 @@
 	char buf[4096];
 	int i, j=0, k, ret = 0;
 	BIO *p7bio;
-	BIO *tmpout;
+	BIO *tmpin, *tmpout;
 
 	if(!p7) {
 		PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_INVALID_NULL_POINTER);
@@ -232,7 +232,30 @@
 		/* Check for revocation status here */
 	}
 
-	p7bio=PKCS7_dataInit(p7,indata);
+	/* Performance optimization: if the content is a memory BIO then
+	 * store its contents in a temporary read only memory BIO. This
+	 * avoids potentially large numbers of slow copies of data which will
+	 * occur when reading from a read write memory BIO when signatures
+	 * are calculated.
+	 */
+
+	if (indata && (BIO_method_type(indata) == BIO_TYPE_MEM))
+		{
+		char *ptr;
+		long len;
+		len = BIO_get_mem_data(indata, &ptr);
+		tmpin = BIO_new_mem_buf(ptr, len);
+		if (tmpin == NULL)
+			{
+			PKCS7err(PKCS7_F_PKCS7_VERIFY,ERR_R_MALLOC_FAILURE);
+			return 0;
+			}
+		}
+	else
+		tmpin = indata;
+		
+
+	p7bio=PKCS7_dataInit(p7,tmpin);
 
 	if(flags & PKCS7_TEXT) {
 		if(!(tmpout = BIO_new(BIO_s_mem()))) {
@@ -274,9 +297,15 @@
 	ret = 1;
 
 	err:
+	
+	if (tmpin == indata)
+		{
+		if(indata) BIO_pop(p7bio);
+		BIO_free_all(p7bio);
+		}
+	else
+		BIO_free_all(tmpin);
 
-	if(indata) BIO_pop(p7bio);
-	BIO_free_all(p7bio);
 	sk_X509_free(signers);
 
 	return ret;