ossl_provider_upref to ossl_provider_up_ref
[openssl.git] / crypto / provider_core.c
index 837f4b5daf115232a377bc90a199a8f7925c0e92..cb136c421e0c414474a86468721ca5eeb67c4597 100644 (file)
@@ -11,7 +11,7 @@
 #include <openssl/core_numbers.h>
 #include <openssl/params.h>
 #include <openssl/opensslv.h>
-#include "internal/cryptlib.h"
+#include "internal/cryptlib_int.h"
 #include "internal/nelem.h"
 #include "internal/thread_once.h"
 #include "internal/provider.h"
@@ -47,6 +47,7 @@ struct ossl_provider_st {
     DSO *module;
     OSSL_provider_init_fn *init_function;
     STACK_OF(INFOPAIR) *parameters;
+    OPENSSL_CTX *libctx; /* The library context this instance is in */
     struct provider_store_st *store; /* The store this instance belongs to */
 
     /* Provider side functions */
@@ -120,6 +121,7 @@ static void *provider_store_new(OPENSSL_CTX *ctx)
             CRYPTOerr(CRYPTO_F_PROVIDER_STORE_NEW, ERR_R_INTERNAL_ERROR);
             return NULL;
         }
+        prov->libctx = ctx;
         prov->store = store;
         if(p->is_fallback)
             ossl_provider_set_fallback(prov);
@@ -157,7 +159,7 @@ OSSL_PROVIDER *ossl_provider_find(OPENSSL_CTX *libctx, const char *name)
         CRYPTO_THREAD_write_lock(store->lock);
         if ((i = sk_OSSL_PROVIDER_find(store->providers, &tmpl)) == -1
             || (prov = sk_OSSL_PROVIDER_value(store->providers, i)) == NULL
-            || !ossl_provider_upref(prov))
+            || !ossl_provider_up_ref(prov))
             prov = NULL;
         CRYPTO_THREAD_unlock(store->lock);
     }
@@ -179,7 +181,7 @@ static OSSL_PROVIDER *provider_new(const char *name,
 #ifndef HAVE_ATOMICS
         || (prov->refcnt_lock = CRYPTO_THREAD_lock_new()) == NULL
 #endif
-        || !ossl_provider_upref(prov) /* +1 One reference to be returned */
+        || !ossl_provider_up_ref(prov) /* +1 One reference to be returned */
         || (prov->name = OPENSSL_strdup(name)) == NULL) {
         ossl_provider_free(prov);
         CRYPTOerr(CRYPTO_F_PROVIDER_NEW, ERR_R_MALLOC_FAILURE);
@@ -190,11 +192,12 @@ static OSSL_PROVIDER *provider_new(const char *name,
     return prov;
 }
 
-int ossl_provider_upref(OSSL_PROVIDER *prov)
+int ossl_provider_up_ref(OSSL_PROVIDER *prov)
 {
     int ref = 0;
 
-    CRYPTO_UP_REF(&prov->refcnt, &ref, prov->refcnt_lock);
+    if (CRYPTO_UP_REF(&prov->refcnt, &ref, prov->refcnt_lock) <= 0)
+        return 0;
     return ref;
 }
 
@@ -220,7 +223,7 @@ OSSL_PROVIDER *ossl_provider_new(OPENSSL_CTX *libctx, const char *name,
         return NULL;
 
     CRYPTO_THREAD_write_lock(store->lock);
-    if (!ossl_provider_upref(prov)) { /* +1 One reference for the store */
+    if (!ossl_provider_up_ref(prov)) { /* +1 One reference for the store */
         ossl_provider_free(prov); /* -1 Reference that was to be returned */
         prov = NULL;
     } else if (sk_OSSL_PROVIDER_push(store->providers, prov) == 0) {
@@ -228,6 +231,7 @@ OSSL_PROVIDER *ossl_provider_new(OPENSSL_CTX *libctx, const char *name,
         ossl_provider_free(prov); /* -1 Reference that was to be returned */
         prov = NULL;
     } else {
+        prov->libctx = libctx;
         prov->store = store;
     }
     CRYPTO_THREAD_unlock(store->lock);
@@ -265,6 +269,9 @@ void ossl_provider_free(OSSL_PROVIDER *prov)
          * When that happens, the provider is inactivated.
          */
         if (ref < 2 && prov->flag_initialized) {
+#ifndef FIPS_MODE
+            ossl_init_thread_deregister(prov);
+#endif
             if (prov->teardown != NULL)
                 prov->teardown(prov->provctx);
             prov->flag_initialized = 0;
@@ -340,11 +347,9 @@ static const OSSL_DISPATCH *core_dispatch; /* Define further down */
 /*
  * Internal version that doesn't affect the store flags, and thereby avoid
  * locking.  Direct callers must remember to set the store flags when
- * appropriate. The libctx parameter is only necessary when FIPS_MODE is set
- * (i.e. we are being called from inside the FIPS module) - it is ignored for
- * other uses.
+ * appropriate.
  */
-static int provider_activate(OSSL_PROVIDER *prov, OPENSSL_CTX *libctx)
+static int provider_activate(OSSL_PROVIDER *prov)
 {
     const OSSL_DISPATCH *provider_dispatch = NULL;
 
@@ -399,26 +404,7 @@ static int provider_activate(OSSL_PROVIDER *prov, OPENSSL_CTX *libctx)
 #endif
     }
 
-    /*
-     * We call the initialise function for the provider.
-     *
-     * If FIPS_MODE is defined then we are inside the FIPS module and are about
-     * to recursively initialise ourselves. We need to do this so that we can
-     * get all the provider callback functions set up in order for us to be able
-     * to make EVP calls from within the FIPS module itself. Only algorithms
-     * from the FIPS module itself are available via the FIPS module EVP
-     * interface, i.e. we only ever have one provider available inside the FIPS
-     * module - the FIPS provider itself.
-     *
-     * For modules in general we cannot know what value will be used for the
-     * provctx - it is a "black box". But for the FIPS module we know that the
-     * provctx is really a library context. We default the provctx value to the
-     * same library context as was used for the EVP call that caused this call
-     * to "provider_activate".
-     */
-#ifdef FIPS_MODE
-    prov->provctx = libctx;
-#endif
+    /* Call the initialise function for the provider. */
     if (prov->init_function == NULL
         || !prov->init_function(prov, core_dispatch, &provider_dispatch,
                                 &prov->provctx)) {
@@ -460,7 +446,7 @@ static int provider_activate(OSSL_PROVIDER *prov, OPENSSL_CTX *libctx)
 
 int ossl_provider_activate(OSSL_PROVIDER *prov)
 {
-    if (provider_activate(prov, NULL)) {
+    if (provider_activate(prov)) {
         CRYPTO_THREAD_write_lock(prov->store->lock);
         prov->store->use_fallbacks = 0;
         CRYPTO_THREAD_unlock(prov->store->lock);
@@ -537,7 +523,7 @@ int ossl_provider_forall_loaded(OPENSSL_CTX *ctx,
                  */
                 if (prov->flag_fallback) {
                     activated_fallback_count++;
-                    provider_activate(prov, ctx);
+                    provider_activate(prov);
                 }
             }
 
@@ -617,8 +603,7 @@ const OSSL_ITEM *ossl_provider_get_param_types(const OSSL_PROVIDER *prov)
         ? NULL : prov->get_param_types(prov->provctx);
 }
 
-int ossl_provider_get_params(const OSSL_PROVIDER *prov,
-                             const OSSL_PARAM params[])
+int ossl_provider_get_params(const OSSL_PROVIDER *prov, OSSL_PARAM params[])
 {
     return prov->get_params == NULL
         ? 0 : prov->get_params(prov->provctx, params);
@@ -655,10 +640,10 @@ static const OSSL_ITEM *core_get_param_types(const OSSL_PROVIDER *prov)
     return param_types;
 }
 
-static int core_get_params(const OSSL_PROVIDER *prov, const OSSL_PARAM params[])
+static int core_get_params(const OSSL_PROVIDER *prov, OSSL_PARAM params[])
 {
     int i;
-    const OSSL_PARAM *p;
+    OSSL_PARAM *p;
 
     if ((p = OSSL_PARAM_locate(params, "openssl-version")) != NULL)
         OSSL_PARAM_set_utf8_ptr(p, OPENSSL_VERSION_STR);
@@ -678,9 +663,23 @@ static int core_get_params(const OSSL_PROVIDER *prov, const OSSL_PARAM params[])
     return 1;
 }
 
+static OSSL_core_get_library_context_fn core_get_libctx; /* Check */
+static OPENSSL_CTX *core_get_libctx(const OSSL_PROVIDER *prov)
+{
+    return prov->libctx;
+}
+
+static int core_thread_start(const OSSL_PROVIDER *prov,
+                             OSSL_thread_stop_handler_fn handfn)
+{
+    return ossl_init_thread_start(prov, prov->provctx, handfn);
+}
+
 static const OSSL_DISPATCH core_dispatch_[] = {
     { OSSL_FUNC_CORE_GET_PARAM_TYPES, (void (*)(void))core_get_param_types },
     { OSSL_FUNC_CORE_GET_PARAMS, (void (*)(void))core_get_params },
+    { OSSL_FUNC_CORE_GET_LIBRARY_CONTEXT, (void (*)(void))core_get_libctx },
+    { OSSL_FUNC_CORE_THREAD_START, (void (*)(void))core_thread_start },
     { OSSL_FUNC_CORE_PUT_ERROR, (void (*)(void))ERR_put_error },
     { OSSL_FUNC_CORE_ADD_ERROR_VDATA, (void (*)(void))ERR_add_error_vdata },
     { 0, NULL }