mirror of
https://github.com/openssl/openssl.git
synced 2025-03-19 19:50:42 +08:00
provider: flush the store cache when providers are loaded/unloaded.
When the providers change, the method cache needs to be flushed. This also impacts the cache is full partial flushes and the algorithm flushing by ID. A new function is introduced to clear all of the operation bits in all providers in a library context. Fixes #15032 Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/15042)
This commit is contained in:
parent
43d7856499
commit
0090e50890
@ -12,7 +12,9 @@
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include "internal/core.h"
|
||||
#include "internal/property.h"
|
||||
#include "internal/provider.h"
|
||||
#include "crypto/ctype.h"
|
||||
#include <openssl/lhash.h>
|
||||
#include <openssl/rand.h>
|
||||
@ -425,6 +427,7 @@ static void ossl_method_cache_flush(OSSL_METHOD_STORE *store, int nid)
|
||||
ALGORITHM *alg = ossl_method_store_retrieve(store, nid);
|
||||
|
||||
if (alg != NULL) {
|
||||
ossl_provider_clear_all_operation_bits(store->ctx);
|
||||
store->nelem -= lh_QUERY_num_items(alg->cache);
|
||||
impl_cache_flush_alg(0, alg, NULL);
|
||||
}
|
||||
@ -436,6 +439,7 @@ int ossl_method_store_flush_cache(OSSL_METHOD_STORE *store, int all)
|
||||
|
||||
if (!ossl_property_write_lock(store))
|
||||
return 0;
|
||||
ossl_provider_clear_all_operation_bits(store->ctx);
|
||||
ossl_sa_ALGORITHM_doall_arg(store->algs, &impl_cache_flush_alg, arg);
|
||||
store->nelem = 0;
|
||||
ossl_property_unlock(store);
|
||||
@ -500,6 +504,7 @@ static void ossl_method_cache_flush_some(OSSL_METHOD_STORE *store)
|
||||
state.nelem = 0;
|
||||
if ((state.seed = OPENSSL_rdtsc()) == 0)
|
||||
state.seed = 1;
|
||||
ossl_provider_clear_all_operation_bits(store->ctx);
|
||||
store->need_flush = 0;
|
||||
ossl_sa_ALGORITHM_doall_arg(store->algs, &impl_cache_flush_one_alg, &state);
|
||||
store->nelem = state.nelem;
|
||||
|
@ -116,6 +116,7 @@ struct provider_store_st {
|
||||
CRYPTO_RWLOCK *lock;
|
||||
char *default_path;
|
||||
unsigned int use_fallbacks:1;
|
||||
unsigned int freeing:1;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -137,6 +138,7 @@ static void provider_store_free(void *vstore)
|
||||
|
||||
if (store == NULL)
|
||||
return;
|
||||
store->freeing = 1;
|
||||
OPENSSL_free(store->default_path);
|
||||
sk_OSSL_PROVIDER_pop_free(store->providers, provider_deactivate_free);
|
||||
CRYPTO_THREAD_lock_free(store->default_path_lock);
|
||||
@ -676,44 +678,76 @@ static int provider_init(OSSL_PROVIDER *prov, int flag_lock)
|
||||
return ok;
|
||||
}
|
||||
|
||||
/*
|
||||
* Deactivate a provider.
|
||||
* Return -1 on failure and the activation count on success
|
||||
*/
|
||||
static int provider_deactivate(OSSL_PROVIDER *prov)
|
||||
{
|
||||
int count;
|
||||
|
||||
if (!ossl_assert(prov != NULL))
|
||||
return 0;
|
||||
return -1;
|
||||
|
||||
if (!CRYPTO_THREAD_write_lock(prov->flag_lock))
|
||||
return 0;
|
||||
return -1;
|
||||
|
||||
if (--prov->activatecnt < 1)
|
||||
if ((count = --prov->activatecnt) < 1)
|
||||
prov->flag_activated = 0;
|
||||
|
||||
CRYPTO_THREAD_unlock(prov->flag_lock);
|
||||
|
||||
/* We don't deinit here, that's done in ossl_provider_free() */
|
||||
return 1;
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* Activate a provider.
|
||||
* Return -1 on failure and the activation count on success
|
||||
*/
|
||||
static int provider_activate(OSSL_PROVIDER *prov, int flag_lock)
|
||||
{
|
||||
int count;
|
||||
|
||||
if (provider_init(prov, flag_lock)) {
|
||||
if (flag_lock && !CRYPTO_THREAD_write_lock(prov->flag_lock))
|
||||
return 0;
|
||||
prov->activatecnt++;
|
||||
return -1;
|
||||
count = ++prov->activatecnt;
|
||||
prov->flag_activated = 1;
|
||||
if (flag_lock)
|
||||
CRYPTO_THREAD_unlock(prov->flag_lock);
|
||||
|
||||
return 1;
|
||||
return count;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int provider_flush_store_cache(const OSSL_PROVIDER *prov)
|
||||
{
|
||||
struct provider_store_st *store;
|
||||
int freeing;
|
||||
|
||||
if ((store = get_provider_store(prov->libctx)) == NULL)
|
||||
return 0;
|
||||
|
||||
if (!CRYPTO_THREAD_read_lock(store->lock))
|
||||
return 0;
|
||||
freeing = store->freeing;
|
||||
CRYPTO_THREAD_unlock(store->lock);
|
||||
|
||||
if (!freeing)
|
||||
return evp_method_store_flush(prov->libctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ossl_provider_activate(OSSL_PROVIDER *prov, int retain_fallbacks)
|
||||
{
|
||||
int count;
|
||||
|
||||
if (prov == NULL)
|
||||
return 0;
|
||||
if (provider_activate(prov, 1)) {
|
||||
if ((count = provider_activate(prov, 1)) > 0) {
|
||||
if (!retain_fallbacks) {
|
||||
if (!CRYPTO_THREAD_write_lock(prov->store->lock)) {
|
||||
provider_deactivate(prov);
|
||||
@ -722,16 +756,18 @@ int ossl_provider_activate(OSSL_PROVIDER *prov, int retain_fallbacks)
|
||||
prov->store->use_fallbacks = 0;
|
||||
CRYPTO_THREAD_unlock(prov->store->lock);
|
||||
}
|
||||
return 1;
|
||||
return count == 1 ? provider_flush_store_cache(prov) : 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ossl_provider_deactivate(OSSL_PROVIDER *prov)
|
||||
{
|
||||
if (prov == NULL)
|
||||
int count;
|
||||
|
||||
if (prov == NULL || (count = provider_deactivate(prov)) < 0)
|
||||
return 0;
|
||||
return provider_deactivate(prov);
|
||||
return count == 0 ? provider_flush_store_cache(prov) : 1;
|
||||
}
|
||||
|
||||
void *ossl_provider_ctx(const OSSL_PROVIDER *prov)
|
||||
@ -773,7 +809,7 @@ static void provider_activate_fallbacks(struct provider_store_st *store)
|
||||
|
||||
if (ossl_provider_up_ref(prov)) {
|
||||
if (prov->flag_fallback) {
|
||||
if (provider_activate(prov, 1))
|
||||
if (provider_activate(prov, 1) > 0)
|
||||
activated_fallback_count++;
|
||||
}
|
||||
ossl_provider_free(prov);
|
||||
@ -843,7 +879,7 @@ int ossl_provider_doall_activated(OSSL_LIB_CTX *ctx,
|
||||
* It's already activated, but we up the activated count to ensure
|
||||
* it remains activated until after we've called the user callback.
|
||||
*/
|
||||
if (!provider_activate(prov, 0)) {
|
||||
if (provider_activate(prov, 0) < 0) {
|
||||
ossl_provider_free(prov);
|
||||
CRYPTO_THREAD_unlock(prov->flag_lock);
|
||||
goto err_unlock;
|
||||
@ -984,7 +1020,7 @@ int ossl_provider_self_test(const OSSL_PROVIDER *prov)
|
||||
return 1;
|
||||
ret = prov->self_test(prov->provctx);
|
||||
if (ret == 0)
|
||||
(void)evp_method_store_flush(ossl_provider_libctx(prov));
|
||||
(void)provider_flush_store_cache(prov);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1022,6 +1058,33 @@ void ossl_provider_unquery_operation(const OSSL_PROVIDER *prov,
|
||||
prov->unquery_operation(prov->provctx, operation_id, algs);
|
||||
}
|
||||
|
||||
int ossl_provider_clear_all_operation_bits(OSSL_LIB_CTX *libctx)
|
||||
{
|
||||
struct provider_store_st *store;
|
||||
OSSL_PROVIDER *provider;
|
||||
int i, num, res = 1;
|
||||
|
||||
if ((store = get_provider_store(libctx)) != NULL) {
|
||||
if (!CRYPTO_THREAD_read_lock(store->lock))
|
||||
return 0;
|
||||
num = sk_OSSL_PROVIDER_num(store->providers);
|
||||
for (i = 0; i < num; i++) {
|
||||
provider = sk_OSSL_PROVIDER_value(store->providers, i);
|
||||
if (!CRYPTO_THREAD_write_lock(provider->opbits_lock)) {
|
||||
res = 0;
|
||||
continue;
|
||||
}
|
||||
if (provider->operation_bits != NULL)
|
||||
memset(provider->operation_bits, 0,
|
||||
provider->operation_bits_sz);
|
||||
CRYPTO_THREAD_unlock(provider->opbits_lock);
|
||||
}
|
||||
CRYPTO_THREAD_unlock(store->lock);
|
||||
return res;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ossl_provider_set_operation_bit(OSSL_PROVIDER *provider, size_t bitnum)
|
||||
{
|
||||
size_t byte = bitnum / 8;
|
||||
|
@ -91,6 +91,7 @@ void ossl_provider_unquery_operation(const OSSL_PROVIDER *prov,
|
||||
int ossl_provider_set_operation_bit(OSSL_PROVIDER *provider, size_t bitnum);
|
||||
int ossl_provider_test_operation_bit(OSSL_PROVIDER *provider, size_t bitnum,
|
||||
int *result);
|
||||
int ossl_provider_clear_all_operation_bits(OSSL_LIB_CTX *libctx);
|
||||
|
||||
/* Configuration */
|
||||
void ossl_provider_add_conf_module(void);
|
||||
|
Loading…
x
Reference in New Issue
Block a user