New function EVP_CIPHER_free()
authorRichard Levitte <levitte@openssl.org>
Tue, 3 Sep 2019 16:11:49 +0000 (18:11 +0200)
committerRichard Levitte <levitte@openssl.org>
Wed, 4 Sep 2019 08:38:13 +0000 (10:38 +0200)
This function re-implements EVP_CIPHER_meth_free(), but has a name that
isn't encumbered by legacy EVP_CIPHER construction functionality.

We also refactor most of EVP_CIPHER_meth_new() into an internal
evp_cipher_new() that's used when creating fetched methods.

EVP_CIPHER_meth_new() and EVP_CIPHER_meth_free() are rewritten in terms of
evp_cipher_new() and EVP_CIPHER_free().  This means that at any time, we can
deprecate all the EVP_CIPHER_meth_ functions with no harmful consequence.

Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/9758)

12 files changed:
apps/list.c
crypto/evp/cmeth_lib.c
crypto/evp/evp_enc.c
crypto/evp/evp_locl.h
crypto/rand/drbg_ctr.c
doc/man3/EVP_CIPHER_meth_new.pod
doc/man3/EVP_EncryptInit.pod
include/openssl/evp.h
providers/common/macs/cmac_prov.c
providers/common/macs/gmac_prov.c
test/evp_extra_test.c
util/libcrypto.num

index f3ef233c84410b3afd29202e6adf45e2eb6d0d1e..3e34228d1e9bee79368e3de3f07d7f3116205d0c 100644 (file)
@@ -80,7 +80,7 @@ static void list_ciphers(void)
                               EVP_CIPHER_CTX_settable_params(c), 4);
         }
     }
-    sk_EVP_CIPHER_pop_free(ciphers, EVP_CIPHER_meth_free);
+    sk_EVP_CIPHER_pop_free(ciphers, EVP_CIPHER_free);
 }
 
 static void list_md_fn(const EVP_MD *m,
index 51c9b6ece20fb37169bcf393c18e4687a3dddfd2..34e85f63664f0badd9dc6f742667a984afb7f5f6 100644 (file)
 
 EVP_CIPHER *EVP_CIPHER_meth_new(int cipher_type, int block_size, int key_len)
 {
-    EVP_CIPHER *cipher = OPENSSL_zalloc(sizeof(EVP_CIPHER));
+    EVP_CIPHER *cipher = evp_cipher_new();
 
     if (cipher != NULL) {
         cipher->nid = cipher_type;
         cipher->block_size = block_size;
         cipher->key_len = key_len;
-        cipher->lock = CRYPTO_THREAD_lock_new();
-        if (cipher->lock == NULL) {
-            OPENSSL_free(cipher);
-            return NULL;
-        }
-        cipher->refcnt = 1;
     }
     return cipher;
 }
 
 EVP_CIPHER *EVP_CIPHER_meth_dup(const EVP_CIPHER *cipher)
 {
-    EVP_CIPHER *to = EVP_CIPHER_meth_new(cipher->nid, cipher->block_size,
-                                         cipher->key_len);
+    EVP_CIPHER *to = NULL;
 
-    if (to != NULL) {
+    /*
+     * Non-legacy EVP_CIPHERs can't be duplicated like this.
+     * Use EVP_CIPHER_up_ref() instead.
+     */
+    if (cipher->prov != NULL)
+        return NULL;
+
+    if ((to = EVP_CIPHER_meth_new(cipher->nid, cipher->block_size,
+                                  cipher->key_len)) == NULL) {
         CRYPTO_RWLOCK *lock = to->lock;
 
         memcpy(to, cipher, sizeof(*to));
@@ -48,25 +49,7 @@ EVP_CIPHER *EVP_CIPHER_meth_dup(const EVP_CIPHER *cipher)
 
 void EVP_CIPHER_meth_free(EVP_CIPHER *cipher)
 {
-    if (cipher != NULL) {
-        int i;
-
-        CRYPTO_DOWN_REF(&cipher->refcnt, &i, cipher->lock);
-        if (i > 0)
-            return;
-        ossl_provider_free(cipher->prov);
-        OPENSSL_free(cipher->name);
-        CRYPTO_THREAD_lock_free(cipher->lock);
-        OPENSSL_free(cipher);
-    }
-}
-
-int EVP_CIPHER_up_ref(EVP_CIPHER *cipher)
-{
-    int ref = 0;
-
-    CRYPTO_UP_REF(&cipher->refcnt, &ref, cipher->lock);
-    return 1;
+    EVP_CIPHER_free(cipher);
 }
 
 int EVP_CIPHER_meth_set_iv_length(EVP_CIPHER *cipher, int iv_len)
index 142ffecfed7ad141f08948071dc4bb3b88423a1f..96dc83b2a009a66d21139d12d83c7f7702f09d74 100644 (file)
@@ -35,7 +35,7 @@ int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *ctx)
         ctx->provctx = NULL;
     }
     if (ctx->fetched_cipher != NULL)
-        EVP_CIPHER_meth_free(ctx->fetched_cipher);
+        EVP_CIPHER_free(ctx->fetched_cipher);
     memset(ctx, 0, sizeof(*ctx));
 
     return 1;
@@ -133,7 +133,7 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
             || impl != NULL) {
         if (ctx->cipher == ctx->fetched_cipher)
             ctx->cipher = NULL;
-        EVP_CIPHER_meth_free(ctx->fetched_cipher);
+        EVP_CIPHER_free(ctx->fetched_cipher);
         ctx->fetched_cipher = NULL;
         goto legacy;
     }
@@ -274,7 +274,7 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
             return 0;
         }
         cipher = provciph;
-        EVP_CIPHER_meth_free(ctx->fetched_cipher);
+        EVP_CIPHER_free(ctx->fetched_cipher);
         ctx->fetched_cipher = provciph;
 #endif
     }
@@ -1244,6 +1244,21 @@ int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in)
     return 1;
 }
 
+EVP_CIPHER *evp_cipher_new(void)
+{
+    EVP_CIPHER *cipher = OPENSSL_zalloc(sizeof(EVP_CIPHER));
+
+    if (cipher != NULL) {
+        cipher->lock = CRYPTO_THREAD_lock_new();
+        if (cipher->lock == NULL) {
+            OPENSSL_free(cipher);
+            return NULL;
+        }
+        cipher->refcnt = 1;
+    }
+    return cipher;
+}
+
 static void *evp_cipher_from_dispatch(const char *name,
                                       const OSSL_DISPATCH *fns,
                                       OSSL_PROVIDER *prov,
@@ -1252,9 +1267,9 @@ static void *evp_cipher_from_dispatch(const char *name,
     EVP_CIPHER *cipher = NULL;
     int fnciphcnt = 0, fnctxcnt = 0;
 
-    if ((cipher = EVP_CIPHER_meth_new(0, 0, 0)) == NULL
+    if ((cipher = evp_cipher_new()) == NULL
         || (cipher->name = OPENSSL_strdup(name)) == NULL) {
-        EVP_CIPHER_meth_free(cipher);
+        EVP_CIPHER_free(cipher);
         EVPerr(0, ERR_R_MALLOC_FAILURE);
         return NULL;
     }
@@ -1361,7 +1376,7 @@ static void *evp_cipher_from_dispatch(const char *name,
          * functions, or a single "cipher" function. In all cases we need both
          * the "newctx" and "freectx" functions.
          */
-        EVP_CIPHER_meth_free(cipher);
+        EVP_CIPHER_free(cipher);
         EVPerr(EVP_F_EVP_CIPHER_FROM_DISPATCH, EVP_R_INVALID_PROVIDER_FUNCTIONS);
         return NULL;
     }
@@ -1379,7 +1394,7 @@ static int evp_cipher_up_ref(void *cipher)
 
 static void evp_cipher_free(void *cipher)
 {
-    EVP_CIPHER_meth_free(cipher);
+    EVP_CIPHER_free(cipher);
 }
 
 EVP_CIPHER *EVP_CIPHER_fetch(OPENSSL_CTX *ctx, const char *algorithm,
@@ -1393,6 +1408,30 @@ EVP_CIPHER *EVP_CIPHER_fetch(OPENSSL_CTX *ctx, const char *algorithm,
     return cipher;
 }
 
+int EVP_CIPHER_up_ref(EVP_CIPHER *cipher)
+{
+    int ref = 0;
+
+    CRYPTO_UP_REF(&cipher->refcnt, &ref, cipher->lock);
+    return 1;
+}
+
+void EVP_CIPHER_free(EVP_CIPHER *cipher)
+{
+    int i;
+
+    if (cipher == NULL)
+        return;
+
+    CRYPTO_DOWN_REF(&cipher->refcnt, &i, cipher->lock);
+    if (i > 0)
+        return;
+    ossl_provider_free(cipher->prov);
+    OPENSSL_free(cipher->name);
+    CRYPTO_THREAD_lock_free(cipher->lock);
+    OPENSSL_free(cipher);
+}
+
 void EVP_CIPHER_do_all_ex(OPENSSL_CTX *libctx,
                           void (*fn)(EVP_CIPHER *mac, void *arg),
                           void *arg)
index 434295653197d21288a7bb11de19a832c40279f4..87f54bdc5facd69cd67cccc9e34f9d315f6d2195 100644 (file)
@@ -158,6 +158,7 @@ void evp_generic_do_all(OPENSSL_CTX *libctx, int operation_id,
 
 /* Internal structure constructors for fetched methods */
 EVP_MD *evp_md_new(void);
+EVP_CIPHER *evp_cipher_new(void);
 
 /* Helper functions to avoid duplicating code */
 
index 23e504bfaca2e80d4767afa9a38877c7cb02be13..28db4eed7f046e585ab8693577ffb8c569b44582 100644 (file)
@@ -354,7 +354,7 @@ static int drbg_ctr_uninstantiate(RAND_DRBG *drbg)
 {
     EVP_CIPHER_CTX_free(drbg->data.ctr.ctx);
     EVP_CIPHER_CTX_free(drbg->data.ctr.ctx_df);
-    EVP_CIPHER_meth_free(drbg->data.ctr.cipher);
+    EVP_CIPHER_free(drbg->data.ctr.cipher);
     OPENSSL_cleanse(&drbg->data.ctr, sizeof(drbg->data.ctr));
     return 1;
 }
@@ -392,7 +392,7 @@ int drbg_ctr_init(RAND_DRBG *drbg)
     if (cipher == NULL)
         return 0;
 
-    EVP_CIPHER_meth_free(ctr->cipher);
+    EVP_CIPHER_free(ctr->cipher);
     ctr->cipher = cipher;
 
     drbg->meth = &drbg_ctr_meth;
index 3d4da9c04ea5fd77c9f5e86388ae3e8137e9e77e..8a6a4b99de8234ff4b6155363d6a38c65732807e 100644 (file)
@@ -10,7 +10,7 @@ EVP_CIPHER_meth_set_set_asn1_params, EVP_CIPHER_meth_set_get_asn1_params,
 EVP_CIPHER_meth_set_ctrl, EVP_CIPHER_meth_get_init,
 EVP_CIPHER_meth_get_do_cipher, EVP_CIPHER_meth_get_cleanup,
 EVP_CIPHER_meth_get_set_asn1_params, EVP_CIPHER_meth_get_get_asn1_params,
-EVP_CIPHER_meth_get_ctrl, EVP_CIPHER_up_ref
+EVP_CIPHER_meth_get_ctrl
 - Routines to build up EVP_CIPHER methods
 
 =head1 SYNOPSIS
@@ -63,8 +63,6 @@ EVP_CIPHER_meth_get_ctrl, EVP_CIPHER_up_ref
                                                            int type, int arg,
                                                            void *ptr);
 
- int EVP_CIPHER_up_ref(EVP_CIPHER *cipher);
-
 =head1 DESCRIPTION
 
 The B<EVP_CIPHER> type is a structure for symmetric cipher method
@@ -226,8 +224,6 @@ EVP_CIPHER_meth_get_get_asn1_params() and EVP_CIPHER_meth_get_ctrl()
 are all used to retrieve the method data given with the
 EVP_CIPHER_meth_set_*() functions above.
 
-EVP_CIPHER_up_ref() increments the reference count for an EVP_CIPHER structure.
-
 =head1 RETURN VALUES
 
 EVP_CIPHER_meth_new() and EVP_CIPHER_meth_dup() return a pointer to a
@@ -236,8 +232,6 @@ All EVP_CIPHER_meth_set_*() functions return 1.
 All EVP_CIPHER_meth_get_*() functions return pointers to their
 respective B<cipher> function.
 
-EVP_CIPHER_up_ref() returns 1 for success or 0 otherwise.
-
 =head1 SEE ALSO
 
 L<EVP_EncryptInit>
@@ -245,6 +239,8 @@ L<EVP_EncryptInit>
 =head1 HISTORY
 
 The functions described here were added in OpenSSL 1.1.0.
+The B<EVP_CIPHER> structure created with these functions became reference
+counted in OpenSSL 3.0.
 
 =head1 COPYRIGHT
 
index 7f69a23dd77653d9ab837e81789d4645e08ab39a..11d0250a0d0e0738cece4f2c0f2a2d36aa26f0df 100644 (file)
@@ -3,6 +3,8 @@
 =head1 NAME
 
 EVP_CIPHER_fetch,
+EVP_CIPHER_up_ref,
+EVP_CIPHER_free,
 EVP_CIPHER_CTX_new,
 EVP_CIPHER_CTX_reset,
 EVP_CIPHER_CTX_free,
@@ -67,6 +69,8 @@ EVP_CIPHER_do_all_ex
 
  EVP_CIPHER *EVP_CIPHER_fetch(OPENSSL_CTX *ctx, const char *algorithm,
                               const char *properties);
+ int EVP_CIPHER_up_ref(EVP_CIPHER *cipher);
+ void EVP_CIPHER_free(EVP_CIPHER *cipher);
  EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void);
  int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *ctx);
  void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx);
@@ -150,13 +154,21 @@ EVP_CIPHER_do_all_ex
 The EVP cipher routines are a high level interface to certain
 symmetric ciphers.
 
+The B<EVP_CIPHER> type is a structure for cipher method implementation.
+
 EVP_CIPHER_fetch() fetches the cipher implementation for the given
 B<algorithm> from any provider offering it, within the criteria given
 by the B<properties>.
 See L<provider(7)/Fetching algorithms> for further information.
 
-The returned value must eventually be freed with
-L<EVP_CIPHER_meth_free(3)>.
+The returned value must eventually be freed with EVP_CIPHER_free().
+
+EVP_CIPHER_up_ref() increments the reference count for an B<EVP_CIPHER>
+structure.
+
+EVP_CIPHER_free() decrements the reference count for the B<EVP_CIPHER>
+structure.
+If the reference count drops to 0 then the structure is freed.
 
 EVP_CIPHER_CTX_new() creates a cipher context.
 
@@ -351,6 +363,8 @@ and the given I<arg> as argument.
 EVP_CIPHER_fetch() returns a pointer to a B<EVP_CIPHER> for success
 and B<NULL> for failure.
 
+EVP_CIPHER_up_ref() returns 1 for success or 0 otherwise.
+
 EVP_CIPHER_CTX_new() returns a pointer to a newly created
 B<EVP_CIPHER_CTX> for success and B<NULL> for failure.
 
@@ -757,6 +771,10 @@ EVP_CIPHER_CTX_reset() appeared and EVP_CIPHER_CTX_cleanup()
 disappeared.  EVP_CIPHER_CTX_init() remains as an alias for
 EVP_CIPHER_CTX_reset().
 
+The EVP_CIPHER_fetch(), EVP_CIPHER_free(), EVP_CIPHER_up_ref(),
+EVP_CIPHER_CTX_set_params() and EVP_CIPHER_CTX_get_params() functions
+were added in 3.0.
+
 =head1 COPYRIGHT
 
 Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
index 6c59aae701da510b5f20e88cf1ed6541e7423920..a0733b9697f01cf6f1cf5b71cda9dfe0bc3c268f 100644 (file)
@@ -191,7 +191,6 @@ int (*EVP_MD_meth_get_ctrl(const EVP_MD *md))(EVP_MD_CTX *ctx, int cmd,
 EVP_CIPHER *EVP_CIPHER_meth_new(int cipher_type, int block_size, int key_len);
 EVP_CIPHER *EVP_CIPHER_meth_dup(const EVP_CIPHER *cipher);
 void EVP_CIPHER_meth_free(EVP_CIPHER *cipher);
-int EVP_CIPHER_up_ref(EVP_CIPHER *cipher);
 
 int EVP_CIPHER_meth_set_iv_length(EVP_CIPHER *cipher, int iv_len);
 int EVP_CIPHER_meth_set_flags(EVP_CIPHER *cipher, unsigned long flags);
@@ -485,6 +484,8 @@ unsigned long EVP_CIPHER_flags(const EVP_CIPHER *cipher);
 int EVP_CIPHER_mode(const EVP_CIPHER *cipher);
 EVP_CIPHER *EVP_CIPHER_fetch(OPENSSL_CTX *ctx, const char *algorithm,
                              const char *properties);
+int EVP_CIPHER_up_ref(EVP_CIPHER *cipher);
+void EVP_CIPHER_free(EVP_CIPHER *cipher);
 
 const EVP_CIPHER *EVP_CIPHER_CTX_cipher(const EVP_CIPHER_CTX *ctx);
 int EVP_CIPHER_CTX_encrypting(const EVP_CIPHER_CTX *ctx);
index 4dcdea6ebe668414baa7b3fe568f9b5fd09dabaf..7c15bc77b061a2ddf268f1582da4a4f3e6e7a774 100644 (file)
@@ -76,7 +76,7 @@ static void cmac_free(void *vmacctx)
 
     if (macctx != NULL) {
         CMAC_CTX_free(macctx->ctx);
-        EVP_CIPHER_meth_free(macctx->alloc_cipher);
+        EVP_CIPHER_free(macctx->alloc_cipher);
         OPENSSL_free(macctx);
     }
 }
@@ -208,7 +208,7 @@ static int cmac_set_ctx_params(void *vmacctx, const OSSL_PARAM params[])
                 propquery = p->data;
             }
 
-            EVP_CIPHER_meth_free(macctx->alloc_cipher);
+            EVP_CIPHER_free(macctx->alloc_cipher);
 
             macctx->tmpcipher = macctx->alloc_cipher =
                 EVP_CIPHER_fetch(PROV_LIBRARY_CONTEXT_OF(macctx->provctx),
index abd5baa1066ce3dfce90b2026c66f082a5a90553..22c8c955506017f18752d36e165fc3352251f5b2 100644 (file)
@@ -64,7 +64,7 @@ static void gmac_free(void *vmacctx)
 
     if (macctx != NULL) {
         EVP_CIPHER_CTX_free(macctx->ctx);
-        EVP_CIPHER_meth_free(macctx->alloc_cipher);
+        EVP_CIPHER_free(macctx->alloc_cipher);
         OPENSSL_free(macctx);
     }
 }
@@ -222,7 +222,7 @@ static int gmac_set_ctx_params(void *vmacctx, const OSSL_PARAM params[])
                 propquery = p->data;
             }
 
-            EVP_CIPHER_meth_free(macctx->alloc_cipher);
+            EVP_CIPHER_free(macctx->alloc_cipher);
             macctx->cipher = macctx->alloc_cipher = NULL;
 
             macctx->cipher = macctx->alloc_cipher =
index eba7f64babf30efc98293ec8a97e168f457611ba..1ad62d2f791ae3565936a932a704f61b9fdbdc37 100644 (file)
@@ -1317,8 +1317,8 @@ static int test_EVP_CIPHER_fetch(int tst)
     if (!TEST_true(EVP_CIPHER_up_ref(cipher)))
         goto err;
     /* Ref count should now be 2. Release both */
-    EVP_CIPHER_meth_free(cipher);
-    EVP_CIPHER_meth_free(cipher);
+    EVP_CIPHER_free(cipher);
+    EVP_CIPHER_free(cipher);
     cipher = NULL;
 
     /*
@@ -1336,7 +1336,7 @@ static int test_EVP_CIPHER_fetch(int tst)
             goto err;
     }
 
-    EVP_CIPHER_meth_free(cipher);
+    EVP_CIPHER_free(cipher);
     cipher = NULL;
 
     /*
@@ -1355,7 +1355,7 @@ static int test_EVP_CIPHER_fetch(int tst)
             goto err;
     }
 
-    EVP_CIPHER_meth_free(cipher);
+    EVP_CIPHER_free(cipher);
     cipher = NULL;
 
     /*
@@ -1381,7 +1381,7 @@ static int test_EVP_CIPHER_fetch(int tst)
     ret = 1;
 
  err:
-    EVP_CIPHER_meth_free(cipher);
+    EVP_CIPHER_free(cipher);
     OSSL_PROVIDER_unload(defltprov);
     OSSL_PROVIDER_unload(fipsprov);
     /* Not normally needed, but we would like to test that
index 3ace3ad1b9d9c950fdf1306c6ff11e3e316aeb17..9f7b0fd7c6c091ccfe09304368a1adde22f9bc2b 100644 (file)
@@ -4733,3 +4733,4 @@ EVP_MAC_gettable_params                 4842      3_0_0   EXIST::FUNCTION:
 EVP_MAC_provider                        4843   3_0_0   EXIST::FUNCTION:
 EVP_MAC_do_all_ex                       4844   3_0_0   EXIST::FUNCTION:
 EVP_MD_free                             4845   3_0_0   EXIST::FUNCTION:
+EVP_CIPHER_free                         4846   3_0_0   EXIST::FUNCTION: