Replumbing: offer a core upcall to get the provider object's library context
[openssl.git] / crypto / provider_core.c
index 36af52717fdce42007e5296bf6d79ebeb97452ab..62b5bd413ffd1af3f23e9ec1a4726959fa8e2a81 100644 (file)
@@ -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);
@@ -194,7 +196,8 @@ int ossl_provider_upref(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;
 }
 
@@ -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);
@@ -275,7 +279,9 @@ void ossl_provider_free(OSSL_PROVIDER *prov)
          * the store.  All we have to do here is clean it out.
          */
         if (ref == 0) {
+#ifndef FIPS_MODE
             DSO_free(prov->module);
+#endif
             OPENSSL_free(prov->name);
             OPENSSL_free(prov->path);
             sk_INFOPAIR_pop_free(prov->parameters, free_infopair);
@@ -338,7 +344,7 @@ 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
+ * appropriate.
  */
 static int provider_activate(OSSL_PROVIDER *prov)
 {
@@ -352,6 +358,9 @@ static int provider_activate(OSSL_PROVIDER *prov)
      * a loadable module.
      */
     if (prov->init_function == NULL) {
+#ifdef FIPS_MODE
+        return 0;
+#else
         if (prov->module == NULL) {
             char *allocated_path = NULL;
             const char *module_path = NULL;
@@ -389,15 +398,19 @@ static int provider_activate(OSSL_PROVIDER *prov)
         if (prov->module != NULL)
             prov->init_function = (OSSL_provider_init_fn *)
                 DSO_bind_func(prov->module, "OSSL_provider_init");
+#endif
     }
 
+    /* Call the initialise function for the provider. */
     if (prov->init_function == NULL
         || !prov->init_function(prov, core_dispatch, &provider_dispatch,
                                 &prov->provctx)) {
         CRYPTOerr(CRYPTO_F_PROVIDER_ACTIVATE, ERR_R_INIT_FAIL);
         ERR_add_error_data(2, "name=", prov->name);
+#ifndef FIPS_MODE
         DSO_free(prov->module);
         prov->module = NULL;
+#endif
         return 0;
     }
 
@@ -545,25 +558,33 @@ int ossl_provider_set_fallback(OSSL_PROVIDER *prov)
 }
 
 /* Getters of Provider Object data */
-const char *ossl_provider_name(OSSL_PROVIDER *prov)
+const char *ossl_provider_name(const OSSL_PROVIDER *prov)
 {
     return prov->name;
 }
 
-const DSO *ossl_provider_dso(OSSL_PROVIDER *prov)
+const DSO *ossl_provider_dso(const OSSL_PROVIDER *prov)
 {
     return prov->module;
 }
 
-const char *ossl_provider_module_name(OSSL_PROVIDER *prov)
+const char *ossl_provider_module_name(const OSSL_PROVIDER *prov)
 {
+#ifdef FIPS_MODE
+    return NULL;
+#else
     return DSO_get_filename(prov->module);
+#endif
 }
 
-const char *ossl_provider_module_path(OSSL_PROVIDER *prov)
+const char *ossl_provider_module_path(const OSSL_PROVIDER *prov)
 {
+#ifdef FIPS_MODE
+    return NULL;
+#else
     /* FIXME: Ensure it's a full path */
     return DSO_get_filename(prov->module);
+#endif
 }
 
 /* Wrappers around calls to the provider */
@@ -640,9 +661,18 @@ 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 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_PUT_ERROR, (void (*)(void))ERR_put_error },
+    { OSSL_FUNC_CORE_ADD_ERROR_VDATA, (void (*)(void))ERR_add_error_vdata },
     { 0, NULL }
 };
 static const OSSL_DISPATCH *core_dispatch = core_dispatch_;