gbl->c_provider_deregister_child_cb(gbl->handle);
}
+/*
+ * ossl_provider_up_ref_parent() and ossl_provider_free_parent() do
+ * nothing in "self-referencing" child providers, i.e. when the parent
+ * of the child provider is the same as the provider where this child
+ * provider was created.
+ * This allows the teardown function in the parent provider to be called
+ * at the correct moment.
+ * For child providers in other providers, the reference count is done to
+ * ensure that cross referencing is recorded. These should be cleared up
+ * through that providers teardown, as part of freeing its child libctx.
+ */
+
int ossl_provider_up_ref_parent(OSSL_PROVIDER *prov, int activate)
{
struct child_prov_globals *gbl;
+ const OSSL_CORE_HANDLE *parent_handle;
gbl = ossl_lib_ctx_get_data(ossl_provider_libctx(prov),
OSSL_LIB_CTX_CHILD_PROVIDER_INDEX);
if (gbl == NULL)
return 0;
- return gbl->c_prov_up_ref(ossl_provider_get_parent(prov), activate);
+ parent_handle = ossl_provider_get_parent(prov);
+ if (parent_handle == gbl->handle)
+ return 1;
+ return gbl->c_prov_up_ref(parent_handle, activate);
}
int ossl_provider_free_parent(OSSL_PROVIDER *prov, int deactivate)
{
struct child_prov_globals *gbl;
+ const OSSL_CORE_HANDLE *parent_handle;
gbl = ossl_lib_ctx_get_data(ossl_provider_libctx(prov),
OSSL_LIB_CTX_CHILD_PROVIDER_INDEX);
if (gbl == NULL)
return 0;
+ parent_handle = ossl_provider_get_parent(prov);
+ if (parent_handle == gbl->handle)
+ return 1;
return gbl->c_prov_free(ossl_provider_get_parent(prov), deactivate);
}