mirror of
https://github.com/openssl/openssl.git
synced 2024-11-27 05:21:51 +08:00
390f9bad69
This introduces a separate activation counter, and the function ossl_provider_deactivate() for provider deactivation. Something to be noted is that if the reference count goes down to zero, we don't care if the activation count is non-zero (i.e. someone forgot to call ossl_provider_deactivate()). Since there are no more references to the provider, it doesn't matter. The important thing is that deactivation doesn't remove the provider as long as there are references to it, for example because there are live methods associated with that provider, but still makes the provider unavailable to create new methods from. Fixes #13503 Fixes #12157 Reviewed-by: Tomas Mraz <tmraz@fedoraproject.org> (Merged from https://github.com/openssl/openssl/pull/13661)
131 lines
3.6 KiB
C
131 lines
3.6 KiB
C
/*
|
|
* Copyright 2019-2020 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/err.h>
|
|
#include <openssl/cryptoerr.h>
|
|
#include <openssl/provider.h>
|
|
#include <openssl/core_names.h>
|
|
#include "internal/provider.h"
|
|
|
|
OSSL_PROVIDER *OSSL_PROVIDER_try_load(OSSL_LIB_CTX *libctx, const char *name)
|
|
{
|
|
OSSL_PROVIDER *prov = NULL;
|
|
|
|
/* Find it or create it */
|
|
if ((prov = ossl_provider_find(libctx, name, 0)) == NULL
|
|
&& (prov = ossl_provider_new(libctx, name, NULL, 0)) == NULL)
|
|
return NULL;
|
|
|
|
if (!ossl_provider_activate(prov)) {
|
|
ossl_provider_free(prov);
|
|
return NULL;
|
|
}
|
|
|
|
return prov;
|
|
}
|
|
|
|
OSSL_PROVIDER *OSSL_PROVIDER_load(OSSL_LIB_CTX *libctx, const char *name)
|
|
{
|
|
/* Any attempt to load a provider disables auto-loading of defaults */
|
|
if (ossl_provider_disable_fallback_loading(libctx))
|
|
return OSSL_PROVIDER_try_load(libctx, name);
|
|
return NULL;
|
|
}
|
|
|
|
int OSSL_PROVIDER_unload(OSSL_PROVIDER *prov)
|
|
{
|
|
if (!ossl_provider_deactivate(prov))
|
|
return 0;
|
|
ossl_provider_free(prov);
|
|
return 1;
|
|
}
|
|
|
|
int OSSL_PROVIDER_available(OSSL_LIB_CTX *libctx, const char *name)
|
|
{
|
|
OSSL_PROVIDER *prov = NULL;
|
|
int available = 0;
|
|
|
|
/* Find it or create it */
|
|
prov = ossl_provider_find(libctx, name, 0);
|
|
available = ossl_provider_available(prov);
|
|
ossl_provider_free(prov);
|
|
return available;
|
|
}
|
|
|
|
const OSSL_PARAM *OSSL_PROVIDER_gettable_params(const OSSL_PROVIDER *prov)
|
|
{
|
|
return ossl_provider_gettable_params(prov);
|
|
}
|
|
|
|
int OSSL_PROVIDER_get_params(const OSSL_PROVIDER *prov, OSSL_PARAM params[])
|
|
{
|
|
return ossl_provider_get_params(prov, params);
|
|
}
|
|
|
|
const OSSL_ALGORITHM *OSSL_PROVIDER_query_operation(const OSSL_PROVIDER *prov,
|
|
int operation_id,
|
|
int *no_cache)
|
|
{
|
|
return ossl_provider_query_operation(prov, operation_id, no_cache);
|
|
}
|
|
|
|
void *OSSL_PROVIDER_get0_provider_ctx(const OSSL_PROVIDER *prov)
|
|
{
|
|
return ossl_provider_prov_ctx(prov);
|
|
}
|
|
|
|
int OSSL_PROVIDER_self_test(const OSSL_PROVIDER *prov)
|
|
{
|
|
return ossl_provider_self_test(prov);
|
|
}
|
|
|
|
int OSSL_PROVIDER_get_capabilities(const OSSL_PROVIDER *prov,
|
|
const char *capability,
|
|
OSSL_CALLBACK *cb,
|
|
void *arg)
|
|
{
|
|
return ossl_provider_get_capabilities(prov, capability, cb, arg);
|
|
}
|
|
|
|
int OSSL_PROVIDER_add_builtin(OSSL_LIB_CTX *libctx, const char *name,
|
|
OSSL_provider_init_fn *init_fn)
|
|
{
|
|
OSSL_PROVIDER *prov = NULL;
|
|
|
|
if (name == NULL || init_fn == NULL) {
|
|
ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
|
|
return 0;
|
|
}
|
|
|
|
/* Create it */
|
|
if ((prov = ossl_provider_new(libctx, name, init_fn, 0)) == NULL)
|
|
return 0;
|
|
|
|
/*
|
|
* It's safely stored in the internal store at this point,
|
|
* free the returned extra reference
|
|
*/
|
|
ossl_provider_free(prov);
|
|
|
|
return 1;
|
|
}
|
|
|
|
const char *OSSL_PROVIDER_name(const OSSL_PROVIDER *prov)
|
|
{
|
|
return ossl_provider_name(prov);
|
|
}
|
|
|
|
int OSSL_PROVIDER_do_all(OSSL_LIB_CTX *ctx,
|
|
int (*cb)(OSSL_PROVIDER *provider,
|
|
void *cbdata),
|
|
void *cbdata)
|
|
{
|
|
return ossl_provider_forall_loaded(ctx, cb, cbdata);
|
|
}
|