One can duplicate the entire EVP_CIPHER_CTX with a call to
EVP_CIPHER_CTX_copy.
By default the state (cipher_data) is duplicated bytewize (malloc+memcpy).
Since AES
gcm has pointers in its state this naive copy method leads to crashes.

diff -ur /tmp/openssl/crypto/evp/e_aes.c /home/test/openssl/crypto/evp/e_aes.c
--- /tmp/openssl/crypto/evp/e_aes.c	2014-02-28 19:26:02.105531053 +0400
+++ /home/test/openssl/crypto/evp/e_aes.c	2014-02-28 17:53:07.545605738 +0400
@@ -1231,6 +1231,22 @@
 		/* Extra padding: tag appended to record */
 		return EVP_GCM_TLS_TAG_LEN;
 
+	case EVP_CTRL_COPY:
+		{
+			EVP_CIPHER_CTX *out = ptr;
+			EVP_AES_GCM_CTX *gctx_out = out->cipher_data;
+			if (gctx->iv == c->iv)
+				gctx_out->iv = out->iv;
+			else
+			{
+				gctx_out->iv = OPENSSL_malloc(gctx->ivlen);
+				if (!gctx_out->iv)
+					return 0;
+				memcpy(gctx_out->iv, gctx->iv, gctx->ivlen);
+			}
+			return 1;
+		}
+
 	default:
 		return -1;
 
@@ -1605,7 +1621,8 @@
 
 #define CUSTOM_FLAGS	(EVP_CIPH_FLAG_DEFAULT_ASN1 \
 		| EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER \
-		| EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT)
+		| EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT \
+		| EVP_CIPH_CUSTOM_COPY)
 
 BLOCK_CIPHER_custom(NID_aes,128,1,12,gcm,GCM,
 		EVP_CIPH_FLAG_FIPS|EVP_CIPH_FLAG_AEAD_CIPHER|CUSTOM_FLAGS)

Reply via email to