]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
provider: add an unquery function to allow providers to clean up.
authorPauli <paul.dale@oracle.com>
Fri, 25 Sep 2020 00:19:19 +0000 (10:19 +1000)
committerPauli <ppzgs1@gmail.com>
Wed, 24 Feb 2021 11:24:36 +0000 (21:24 +1000)
Without this, a provider  has no way to know that an application
has finished with the array it returned earlier.  A non-caching provider
requires this information.

Fixes #12974

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

13 files changed:
crypto/core_algorithm.c
crypto/provider.c
crypto/provider_core.c
doc/internal/man3/ossl_provider_new.pod
doc/man3/OSSL_PROVIDER.pod
doc/man7/provider-base.pod
include/internal/provider.h
include/openssl/core_dispatch.h
include/openssl/provider.h
test/filterprov.c
test/filterprov.h [new file with mode: 0644]
test/sslapitest.c
util/libcrypto.num

index ddb9e5ae4322fe9a7865f3839503c766f1bffef7..59f6dddb14a5a094c809f44ec0abb1a31309f089 100644 (file)
@@ -65,6 +65,7 @@ static int algorithm_do_this(OSSL_PROVIDER *provider, void *cbdata)
                 data->fn(provider, thismap, no_store, data->data);
             }
         }
+        ossl_provider_unquery_operation(provider, cur_operation, map);
 
         /* Do we fulfill post-conditions? */
         if (data->post == NULL) {
index 90c31f3ac53bd37251d092672fed4f1d9137936c..8eca9d35818ca5415c07066f84b8137de077f6e3 100644 (file)
@@ -76,6 +76,13 @@ const OSSL_ALGORITHM *OSSL_PROVIDER_query_operation(const OSSL_PROVIDER *prov,
     return ossl_provider_query_operation(prov, operation_id, no_cache);
 }
 
+void OSSL_PROVIDER_unquery_operation(const OSSL_PROVIDER *prov,
+                                     int operation_id,
+                                     const OSSL_ALGORITHM *algs)
+{
+    ossl_provider_unquery_operation(prov, operation_id, algs);
+}
+
 void *OSSL_PROVIDER_get0_provider_ctx(const OSSL_PROVIDER *prov)
 {
     return ossl_provider_prov_ctx(prov);
index da751e60cef6525e0e02103d88b8889ad95e317c..d210026e253a1caf78ba1cca019013b7ac66ce33 100644 (file)
@@ -78,6 +78,7 @@ struct ossl_provider_st {
     OSSL_FUNC_provider_get_capabilities_fn *get_capabilities;
     OSSL_FUNC_provider_self_test_fn *self_test;
     OSSL_FUNC_provider_query_operation_fn *query_operation;
+    OSSL_FUNC_provider_unquery_operation_fn *unquery_operation;
 
     /*
      * Cache of bit to indicate of query_operation() has been called on
@@ -571,6 +572,10 @@ static int provider_init(OSSL_PROVIDER *prov)
             prov->query_operation =
                 OSSL_FUNC_provider_query_operation(provider_dispatch);
             break;
+        case OSSL_FUNC_PROVIDER_UNQUERY_OPERATION:
+            prov->unquery_operation =
+                OSSL_FUNC_provider_unquery_operation(provider_dispatch);
+            break;
 #ifndef OPENSSL_NO_ERR
 # ifndef FIPS_MODULE
         case OSSL_FUNC_PROVIDER_GET_REASON_STRINGS:
@@ -929,6 +934,14 @@ const OSSL_ALGORITHM *ossl_provider_query_operation(const OSSL_PROVIDER *prov,
     return res;
 }
 
+void ossl_provider_unquery_operation(const OSSL_PROVIDER *prov,
+                                     int operation_id,
+                                     const OSSL_ALGORITHM *algs)
+{
+    if (prov->unquery_operation != NULL)
+        prov->unquery_operation(prov->provctx, operation_id, algs);
+}
+
 int ossl_provider_set_operation_bit(OSSL_PROVIDER *provider, size_t bitnum)
 {
     size_t byte = bitnum / 8;
index d74ce57fef225502528f7ed49b8ab514f69d00a1..40a2ebe7e3e5e3da660511da1b89bc12b6391bfb 100644 (file)
@@ -13,7 +13,8 @@ ossl_provider_name, ossl_provider_dso,
 ossl_provider_module_name, ossl_provider_module_path,
 ossl_provider_libctx,
 ossl_provider_teardown, ossl_provider_gettable_params,
-ossl_provider_get_params, ossl_provider_query_operation,
+ossl_provider_get_params,
+ossl_provider_query_operation, ossl_provider_unquery_operation,
 ossl_provider_set_operation_bit, ossl_provider_test_operation_bit,
 ossl_provider_get_capabilities
 - internal provider routines
@@ -72,6 +73,9 @@ ossl_provider_get_capabilities
  const OSSL_ALGORITHM *ossl_provider_query_operation(const OSSL_PROVIDER *prov,
                                                      int operation_id,
                                                      int *no_cache);
+ void ossl_provider_unquery_operation(const OSSL_PROVIDER *prov,
+                                      int operation_id,
+                                      const OSSL_ALGORITHM *algs);
 
  int ossl_provider_set_operation_bit(OSSL_PROVIDER *provider, size_t bitnum);
  int ossl_provider_test_operation_bit(OSSL_PROVIDER *provider, size_t bitnum,
@@ -234,6 +238,10 @@ I<query_operation> function, if the provider has one.
 It should return an array of I<OSSL_ALGORITHM> for the given
 I<operation_id>.
 
+ossl_provider_unquery_operation() informs the provider that the result of
+ossl_provider_query_operation() is no longer going to be directly accessed and
+that all relevant information has been copied.
+
 ossl_provider_set_operation_bit() registers a 1 for operation I<bitnum>
 in a bitstring that's internal to I<provider>.
 
index e5c451259a9ee558a4328f132d37e44d5ecc5553..d5317ee3f52f09ead7d3047e1402556eaa3549b9 100644 (file)
@@ -6,8 +6,8 @@ OSSL_PROVIDER_set_default_search_path,
 OSSL_PROVIDER, OSSL_PROVIDER_load, OSSL_PROVIDER_try_load, OSSL_PROVIDER_unload,
 OSSL_PROVIDER_available, OSSL_PROVIDER_do_all,
 OSSL_PROVIDER_gettable_params, OSSL_PROVIDER_get_params,
-OSSL_PROVIDER_query_operation, OSSL_PROVIDER_get0_provider_ctx,
-OSSL_PROVIDER_add_builtin, OSSL_PROVIDER_name,
+OSSL_PROVIDER_query_operation, OSSL_PROVIDER_unquery_operation,
+OSSL_PROVIDER_get0_provider_ctx, OSSL_PROVIDER_add_builtin, OSSL_PROVIDER_name,
 OSSL_PROVIDER_get_capabilities, OSSL_PROVIDER_self_test
 - provider routines
 
@@ -35,6 +35,9 @@ OSSL_PROVIDER_get_capabilities, OSSL_PROVIDER_self_test
  const OSSL_ALGORITHM *OSSL_PROVIDER_query_operation(const OSSL_PROVIDER *prov,
                                                      int operation_id,
                                                      int *no_cache);
+ void OSSL_PROVIDER_unquery_operation(const OSSL_PROVIDER *prov,
+                                      int operation_id,
+                                      const OSSL_ALGORITHM *algs);
  void *OSSL_PROVIDER_get0_provider_ctx(const OSSL_PROVIDER *prov);
 
  int OSSL_PROVIDER_add_builtin(OSSL_LIB_CTX *libctx, const char *name,
@@ -119,6 +122,10 @@ array of I<OSSL_ALGORITHM> for the given I<operation_id> terminated by an all
 NULL OSSL_ALGORITHM entry. This is considered a low-level function that most
 applications should not need to call.
 
+OSSL_PROVIDER_unquery_operation() calls the provider's I<unquery_operation>
+function (see L<provider(7)>), if the provider has one.  This is considered a
+low-level function that most applications should not need to call.
+
 OSSL_PROVIDER_get0_provider_ctx() returns the provider context for the given
 provider. The provider context is an opaque handle set by the provider itself
 and is passed back to the provider by libcrypto in various function calls.
index 8659431437fc0890c6a05af5d915069ca3d6122d..3b4416dac0ef8287db2f9c7eeb8d8916d57d3dd2 100644 (file)
@@ -86,6 +86,8 @@ provider-base
  const OSSL_ALGORITHM *provider_query_operation(void *provctx,
                                                 int operation_id,
                                                 const int *no_store);
+ void provider_unquery_operation(void *provctx, int operation_id,
+                                 const OSSL_ALGORITHM *algs);
  const OSSL_ITEM *provider_get_reason_strings(void *provctx);
  int provider_get_capabilities(void *provctx, const char *capability,
                                OSSL_CALLBACK *cb, void *arg);
@@ -154,6 +156,7 @@ F<libcrypto>):
  provider_gettable_params       OSSL_FUNC_PROVIDER_GETTABLE_PARAMS
  provider_get_params            OSSL_FUNC_PROVIDER_GET_PARAMS
  provider_query_operation       OSSL_FUNC_PROVIDER_QUERY_OPERATION
+ provider_unquery_operation     OSSL_FUNC_PROVIDER_UNQUERY_OPERATION
  provider_get_reason_strings    OSSL_FUNC_PROVIDER_GET_REASON_STRINGS
  provider_get_capabilities      OSSL_FUNC_PROVIDER_GET_CAPABILITIES
  provider_self_test             OSSL_FUNC_PROVIDER_SELF_TEST
@@ -274,6 +277,11 @@ It should indicate if the core may store a reference to this array by
 setting I<*no_store> to 0 (core may store a reference) or 1 (core may
 not store a reference).
 
+provider_unquery_operation() informs the provider that the result of a
+provider_query_operation() is no longer directly required and that the function
+pointers have been copied.  The I<operation_id> should match that passed to
+provider_query_operation() and I<algs> should be its return value.
+
 provider_get_reason_strings() should return a constant B<OSSL_ITEM>
 array that provides reason strings for reason codes the provider may
 use when reporting errors using core_put_error().
index fbe3154b53ca2e752b8c7baf6bca6fee03b2c171..7441bf26f0c856e642e5c9f8c6f6721df2c13350 100644 (file)
@@ -83,6 +83,9 @@ int ossl_provider_self_test(const OSSL_PROVIDER *prov);
 const OSSL_ALGORITHM *ossl_provider_query_operation(const OSSL_PROVIDER *prov,
                                                     int operation_id,
                                                     int *no_cache);
+void ossl_provider_unquery_operation(const OSSL_PROVIDER *prov,
+                                     int operation_id,
+                                     const OSSL_ALGORITHM *algs);
 
 /* Cache of bits to see if we already queried an operation */
 int ossl_provider_set_operation_bit(OSSL_PROVIDER *provider, size_t bitnum);
index 6f12d6fecfb47445c1ff0359d2515f76dec94019..4d1d89ca824ae64e4fb056a7ab00950bc98b546b 100644 (file)
@@ -193,13 +193,16 @@ OSSL_CORE_MAKE_FUNC(int,provider_get_params,(void *provctx,
 # define OSSL_FUNC_PROVIDER_QUERY_OPERATION    1027
 OSSL_CORE_MAKE_FUNC(const OSSL_ALGORITHM *,provider_query_operation,
                     (void *provctx, int operation_id, int *no_store))
-# define OSSL_FUNC_PROVIDER_GET_REASON_STRINGS 1028
+# define OSSL_FUNC_PROVIDER_UNQUERY_OPERATION  1028
+OSSL_CORE_MAKE_FUNC(void, provider_unquery_operation,
+                    (void *provctx, int operation_id, const OSSL_ALGORITHM *))
+# define OSSL_FUNC_PROVIDER_GET_REASON_STRINGS 1029
 OSSL_CORE_MAKE_FUNC(const OSSL_ITEM *,provider_get_reason_strings,
                     (void *provctx))
-# define OSSL_FUNC_PROVIDER_GET_CAPABILITIES   1029
+# define OSSL_FUNC_PROVIDER_GET_CAPABILITIES   1030
 OSSL_CORE_MAKE_FUNC(int, provider_get_capabilities, (void *provctx,
                     const char *capability, OSSL_CALLBACK *cb, void *arg))
-# define OSSL_FUNC_PROVIDER_SELF_TEST          1030
+# define OSSL_FUNC_PROVIDER_SELF_TEST          1031
 OSSL_CORE_MAKE_FUNC(int, provider_self_test, (void *provctx))
 
 /* Operations */
index a8720aaa7ee4904b5ba53f6ceec02392e6350f76..56b430710ffdf3e24540899cd5feb6459a1fe1f2 100644 (file)
@@ -41,6 +41,8 @@ int OSSL_PROVIDER_get_capabilities(const OSSL_PROVIDER *prov,
 const OSSL_ALGORITHM *OSSL_PROVIDER_query_operation(const OSSL_PROVIDER *prov,
                                                     int operation_id,
                                                     int *no_cache);
+void OSSL_PROVIDER_unquery_operation(const OSSL_PROVIDER *prov,
+                                     int operation_id, const OSSL_ALGORITHM *algs);
 void *OSSL_PROVIDER_get0_provider_ctx(const OSSL_PROVIDER *prov);
 
 /* Add a built in providers */
index 71606ecc9375495519753e0a4d92b36bd794cbcd..e14c802b1df6080f80715c205280b18058e6a959 100644 (file)
 
 #include <string.h>
 #include <openssl/core.h>
-#include <openssl/core_dispatch.h>
 #include <openssl/provider.h>
 #include <openssl/crypto.h>
-
-OSSL_provider_init_fn filter_provider_init;
-
-int filter_provider_set_filter(int operation, const char *name);
+#include "testutil.h"
+#include "filterprov.h"
 
 #define MAX_FILTERS     10
 #define MAX_ALG_FILTERS 5
@@ -34,6 +31,8 @@ struct filter_prov_globals_st {
     } dispatch[MAX_FILTERS];
     int num_dispatch;
     int no_cache;
+    unsigned long int query_count;
+    int error;
 };
 
 static struct filter_prov_globals_st ourglobals;
@@ -51,6 +50,7 @@ static struct filter_prov_globals_st *get_globals(void)
 static OSSL_FUNC_provider_gettable_params_fn filter_gettable_params;
 static OSSL_FUNC_provider_get_params_fn filter_get_params;
 static OSSL_FUNC_provider_query_operation_fn filter_query;
+static OSSL_FUNC_provider_unquery_operation_fn filter_unquery;
 static OSSL_FUNC_provider_teardown_fn filter_teardown;
 
 static const OSSL_PARAM *filter_gettable_params(void *provctx)
@@ -82,6 +82,7 @@ static const OSSL_ALGORITHM *filter_query(void *provctx,
     struct filter_prov_globals_st *globs = get_globals();
     int i;
 
+    globs->query_count++;
     for (i = 0; i < globs->num_dispatch; i++) {
         if (globs->dispatch[i].operation == operation_id) {
             *no_cache = globs->no_cache;
@@ -93,12 +94,30 @@ static const OSSL_ALGORITHM *filter_query(void *provctx,
     return OSSL_PROVIDER_query_operation(globs->deflt, operation_id, no_cache);
 }
 
+static void filter_unquery(void *provctx, int operation_id,
+                           const OSSL_ALGORITHM *algs)
+{
+    struct filter_prov_globals_st *globs = get_globals();
+    int i;
+
+    if (!TEST_ulong_gt(globs->query_count, 0))
+        globs->error = 1;
+    else
+        globs->query_count--;
+
+    for (i = 0; i < globs->num_dispatch; i++)
+        if (globs->dispatch[i].alg == algs)
+            return;
+    OSSL_PROVIDER_unquery_operation(globs->deflt, operation_id, algs);
+}
+
 static void filter_teardown(void *provctx)
 {
     struct filter_prov_globals_st *globs = get_globals();
 
     OSSL_PROVIDER_unload(globs->deflt);
     OSSL_LIB_CTX_free(globs->libctx);
+    memset(globs, 0, sizeof(*globs));
 }
 
 /* Functions we provide to the core */
@@ -106,6 +125,7 @@ static const OSSL_DISPATCH filter_dispatch_table[] = {
     { OSSL_FUNC_PROVIDER_GETTABLE_PARAMS, (void (*)(void))filter_gettable_params },
     { OSSL_FUNC_PROVIDER_GET_PARAMS, (void (*)(void))filter_get_params },
     { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))filter_query },
+    { OSSL_FUNC_PROVIDER_UNQUERY_OPERATION, (void (*)(void))filter_unquery },
     { OSSL_FUNC_PROVIDER_GET_CAPABILITIES, (void (*)(void))filter_get_capabilities },
     { OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))filter_teardown },
     { 0, NULL }
@@ -201,6 +221,18 @@ int filter_provider_set_filter(int operation, const char *filterstr)
 
     ret = 1;
  err:
+    OSSL_PROVIDER_unquery_operation(globs->deflt, operation, provalgs);
     OPENSSL_free(filterstrtmp);
     return ret;
 }
+
+/*
+ * Test if a filter provider is in a clean finishing state.
+ * If it is return 1, otherwise return 0.
+ */
+int filter_provider_check_clean_finish(void)
+{
+    struct filter_prov_globals_st *globs = get_globals();
+
+    return TEST_ulong_eq(globs->query_count, 0) && !globs->error;
+}
diff --git a/test/filterprov.h b/test/filterprov.h
new file mode 100644 (file)
index 0000000..3c63071
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/core_dispatch.h>
+
+OSSL_provider_init_fn filter_provider_init;
+int filter_provider_set_filter(int operation, const char *name);
+int filter_provider_check_clean_finish(void);
index 6f30a7efd1ac9f7021b8a2bc283b3fbf13792897..b6eb6c16db997836963594d935fe660b64a376cf 100644 (file)
@@ -38,6 +38,7 @@
 #include "internal/nelem.h"
 #include "internal/ktls.h"
 #include "../ssl/ssl_local.h"
+#include "filterprov.h"
 
 #undef OSSL_NO_USABLE_TLS1_3
 #if defined(OPENSSL_NO_TLS1_3) \
 # define OSSL_NO_USABLE_TLS1_3
 #endif
 
-/* Defined in filterprov.c */
-OSSL_provider_init_fn filter_provider_init;
-int filter_provider_set_filter(int operation, const char *name);
-
 /* Defined in tls-provider.c */
 int tls_provider_init(const OSSL_CORE_HANDLE *handle,
                       const OSSL_DISPATCH *in,
@@ -8058,7 +8055,7 @@ static int test_sigalgs_available(int idx)
                                                  : NID_rsassaPss))
         goto end;
 
-    testresult = 1;
+    testresult = filter_provider_check_clean_finish();
 
  end:
     SSL_free(serverssl);
index 0403a6944bdb6884efe45eeffb5bcb710f8ebcc6..2f04e8115210b6b0a2734cdf0a1044c62ae2dd9b 100644 (file)
@@ -5078,6 +5078,7 @@ X509_PUBKEY_eq                          ? 3_0_0   EXIST::FUNCTION:
 EVP_PKEY_eq                             ?      3_0_0   EXIST::FUNCTION:
 EVP_PKEY_parameters_eq                  ?      3_0_0   EXIST::FUNCTION:
 OSSL_PROVIDER_query_operation           ?      3_0_0   EXIST::FUNCTION:
+OSSL_PROVIDER_unquery_operation         ?      3_0_0   EXIST::FUNCTION:
 OSSL_PROVIDER_get0_provider_ctx         ?      3_0_0   EXIST::FUNCTION:
 OSSL_PROVIDER_get_capabilities          ?      3_0_0   EXIST::FUNCTION:
 EC_GROUP_new_by_curve_name_ex           ?      3_0_0   EXIST::FUNCTION:EC