Make EVP_CIPHER_CTX_copy work in GCM mode.
PR#3272
(Imported from upstream's 14183e50e75f54c44df6be69670180860ac19550 and
802fdcda1ebc4241a8e02af0046ba2f5264f71f6)
Change-Id: Ied6183d938e320f953a18f6616890d88b74def3f
diff --git a/crypto/cipher/cipher.c b/crypto/cipher/cipher.c
index bf5c559..c6572b8 100644
--- a/crypto/cipher/cipher.c
+++ b/crypto/cipher/cipher.c
@@ -140,6 +140,10 @@
memcpy(out->cipher_data, in->cipher_data, in->cipher->ctx_size);
}
+ if (in->cipher->flags & EVP_CIPH_CUSTOM_COPY) {
+ return in->cipher->ctrl((EVP_CIPHER_CTX *)in, EVP_CTRL_COPY, 0, out);
+ }
+
return 1;
}
diff --git a/crypto/cipher/e_aes.c b/crypto/cipher/e_aes.c
index 6e3fafb..8caac70 100644
--- a/crypto/cipher/e_aes.c
+++ b/crypto/cipher/e_aes.c
@@ -480,6 +480,27 @@
gctx->iv_set = 1;
return 1;
+ case EVP_CTRL_COPY: {
+ EVP_CIPHER_CTX *out = ptr;
+ EVP_AES_GCM_CTX *gctx_out = out->cipher_data;
+ if (gctx->gcm.key) {
+ if (gctx->gcm.key != &gctx->ks) {
+ return 0;
+ }
+ gctx_out->gcm.key = &gctx_out->ks;
+ }
+ 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;
}
@@ -775,7 +796,7 @@
NID_aes_256_gcm, 1 /* block_size */, 32 /* key_size */, 12 /* iv_len */,
sizeof(EVP_AES_GCM_CTX),
EVP_CIPH_GCM_MODE | 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 |
EVP_CIPH_FLAG_AEAD_CIPHER,
NULL /* app_data */, aesni_gcm_init_key, aes_gcm_cipher, aes_gcm_cleanup,
aes_gcm_ctrl};
diff --git a/include/openssl/cipher.h b/include/openssl/cipher.h
index 191d44a..19988aa 100644
--- a/include/openssl/cipher.h
+++ b/include/openssl/cipher.h
@@ -325,6 +325,11 @@
* one. */
#define EVP_CIPH_FLAG_AEAD_CIPHER 0x800
+/* EVP_CIPH_CUSTOM_COPY indicates that the |ctrl| callback should be called
+ * with |EVP_CTRL_COPY| at the end of normal |EVP_CIPHER_CTX_copy|
+ * processing. */
+#define EVP_CIPH_CUSTOM_COPY 0x1000
+
/* Private functions. */