mirror of https://github.com/openssl/openssl.git
Instantiate user-added builtin providers when we need them
Previously we created the provider object for builtin providers at the point that OPENSSL_add_builtin() was called. Instead we delay that until the provider is actually loaded. Reviewed-by: Paul Dale <pauli@openssl.org> Reviewed-by: Tomas Mraz <tomas@openssl.org> (Merged from https://github.com/openssl/openssl/pull/15854)
This commit is contained in:
parent
8d4dec0d4b
commit
1d74203cf5
|
@ -94,29 +94,6 @@ int OSSL_PROVIDER_get_capabilities(const OSSL_PROVIDER *prov,
|
||||||
return ossl_provider_get_capabilities(prov, capability, cb, 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_get0_name(const OSSL_PROVIDER *prov)
|
const char *OSSL_PROVIDER_get0_name(const OSSL_PROVIDER *prov)
|
||||||
{
|
{
|
||||||
return ossl_provider_name(prov);
|
return ossl_provider_name(prov);
|
||||||
|
|
|
@ -139,6 +139,9 @@ struct provider_store_st {
|
||||||
CRYPTO_RWLOCK *default_path_lock;
|
CRYPTO_RWLOCK *default_path_lock;
|
||||||
CRYPTO_RWLOCK *lock;
|
CRYPTO_RWLOCK *lock;
|
||||||
char *default_path;
|
char *default_path;
|
||||||
|
struct provider_info_st *provinfo;
|
||||||
|
size_t numprovinfo;
|
||||||
|
size_t provinfosz;
|
||||||
unsigned int use_fallbacks:1;
|
unsigned int use_fallbacks:1;
|
||||||
unsigned int freeing:1;
|
unsigned int freeing:1;
|
||||||
};
|
};
|
||||||
|
@ -166,6 +169,7 @@ static void ossl_provider_child_cb_free(OSSL_PROVIDER_CHILD_CB *cb)
|
||||||
static void provider_store_free(void *vstore)
|
static void provider_store_free(void *vstore)
|
||||||
{
|
{
|
||||||
struct provider_store_st *store = vstore;
|
struct provider_store_st *store = vstore;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
if (store == NULL)
|
if (store == NULL)
|
||||||
return;
|
return;
|
||||||
|
@ -178,6 +182,9 @@ static void provider_store_free(void *vstore)
|
||||||
#endif
|
#endif
|
||||||
CRYPTO_THREAD_lock_free(store->default_path_lock);
|
CRYPTO_THREAD_lock_free(store->default_path_lock);
|
||||||
CRYPTO_THREAD_lock_free(store->lock);
|
CRYPTO_THREAD_lock_free(store->lock);
|
||||||
|
for (i = 0; i < store->numprovinfo; i++)
|
||||||
|
OPENSSL_free(store->provinfo[i].name);
|
||||||
|
OPENSSL_free(store->provinfo);
|
||||||
OPENSSL_free(store);
|
OPENSSL_free(store);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,6 +240,62 @@ int ossl_provider_disable_fallback_loading(OSSL_LIB_CTX *libctx)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define BUILTINS_BLOCK_SIZE 10
|
||||||
|
|
||||||
|
int OSSL_PROVIDER_add_builtin(OSSL_LIB_CTX *libctx, const char *name,
|
||||||
|
OSSL_provider_init_fn *init_fn)
|
||||||
|
{
|
||||||
|
struct provider_store_st *store = get_provider_store(libctx);
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (name == NULL || init_fn == NULL) {
|
||||||
|
ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (store == NULL) {
|
||||||
|
ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CRYPTO_THREAD_write_lock(store->lock))
|
||||||
|
return 0;
|
||||||
|
if (store->provinfosz == 0) {
|
||||||
|
store->provinfo = OPENSSL_zalloc(sizeof(*store->provinfo)
|
||||||
|
* BUILTINS_BLOCK_SIZE);
|
||||||
|
if (store->provinfo == NULL) {
|
||||||
|
ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
store->provinfosz = BUILTINS_BLOCK_SIZE;
|
||||||
|
} else if (store->numprovinfo == store->provinfosz) {
|
||||||
|
struct provider_info_st *tmpbuiltins;
|
||||||
|
size_t newsz = store->provinfosz + BUILTINS_BLOCK_SIZE;
|
||||||
|
|
||||||
|
tmpbuiltins = OPENSSL_realloc(store->provinfo,
|
||||||
|
sizeof(*store->provinfo) * newsz);
|
||||||
|
if (tmpbuiltins == NULL) {
|
||||||
|
ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
store->provinfo = tmpbuiltins;
|
||||||
|
store->provinfosz = newsz;
|
||||||
|
}
|
||||||
|
store->provinfo[store->numprovinfo].name = OPENSSL_strdup(name);
|
||||||
|
if (store->provinfo[store->numprovinfo].name == NULL) {
|
||||||
|
ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
store->provinfo[store->numprovinfo].init = init_fn;
|
||||||
|
store->provinfo[store->numprovinfo].is_fallback = 0;
|
||||||
|
store->numprovinfo++;
|
||||||
|
|
||||||
|
ret = 1;
|
||||||
|
err:
|
||||||
|
CRYPTO_THREAD_unlock(store->lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
OSSL_PROVIDER *ossl_provider_find(OSSL_LIB_CTX *libctx, const char *name,
|
OSSL_PROVIDER *ossl_provider_find(OSSL_LIB_CTX *libctx, const char *name,
|
||||||
int noconfig)
|
int noconfig)
|
||||||
{
|
{
|
||||||
|
@ -354,15 +417,30 @@ OSSL_PROVIDER *ossl_provider_new(OSSL_LIB_CTX *libctx, const char *name,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (init_function == NULL) {
|
if (init_function == NULL) {
|
||||||
const struct predefined_providers_st *p;
|
const struct provider_info_st *p;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
/* Check if this is a built-in provider */
|
/* Check if this is a predefined builtin provider */
|
||||||
for (p = ossl_predefined_providers; p->name != NULL; p++) {
|
for (p = ossl_predefined_providers; p->name != NULL; p++) {
|
||||||
if (strcmp(p->name, name) == 0) {
|
if (strcmp(p->name, name) == 0) {
|
||||||
init_function = p->init;
|
init_function = p->init;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (p->name == NULL) {
|
||||||
|
/* Check if this is a user added builtin provider */
|
||||||
|
if (!CRYPTO_THREAD_read_lock(store->lock))
|
||||||
|
return NULL;
|
||||||
|
for (i = 0, p = store->provinfo; i < store->numprovinfo; p++, i++) {
|
||||||
|
if (strcmp(p->name, name) == 0) {
|
||||||
|
init_function = p->init;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CRYPTO_THREAD_unlock(store->lock);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
template.init = init_function;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* provider_new() generates an error, so no need here */
|
/* provider_new() generates an error, so no need here */
|
||||||
|
@ -930,7 +1008,7 @@ static int provider_activate_fallbacks(struct provider_store_st *store)
|
||||||
int use_fallbacks;
|
int use_fallbacks;
|
||||||
int activated_fallback_count = 0;
|
int activated_fallback_count = 0;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
const struct predefined_providers_st *p;
|
const struct provider_info_st *p;
|
||||||
|
|
||||||
if (!CRYPTO_THREAD_read_lock(store->lock))
|
if (!CRYPTO_THREAD_read_lock(store->lock))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -9,10 +9,10 @@
|
||||||
|
|
||||||
#include <openssl/core.h>
|
#include <openssl/core.h>
|
||||||
|
|
||||||
struct predefined_providers_st {
|
struct provider_info_st {
|
||||||
const char *name;
|
char *name;
|
||||||
OSSL_provider_init_fn *init;
|
OSSL_provider_init_fn *init;
|
||||||
unsigned int is_fallback:1;
|
unsigned int is_fallback:1;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const struct predefined_providers_st ossl_predefined_providers[];
|
extern const struct provider_info_st ossl_predefined_providers[];
|
||||||
|
|
|
@ -17,7 +17,7 @@ OSSL_provider_init_fn ossl_fips_intern_provider_init;
|
||||||
#ifdef STATIC_LEGACY
|
#ifdef STATIC_LEGACY
|
||||||
OSSL_provider_init_fn ossl_legacy_provider_init;
|
OSSL_provider_init_fn ossl_legacy_provider_init;
|
||||||
#endif
|
#endif
|
||||||
const struct predefined_providers_st ossl_predefined_providers[] = {
|
const struct provider_info_st ossl_predefined_providers[] = {
|
||||||
#ifdef FIPS_MODULE
|
#ifdef FIPS_MODULE
|
||||||
{ "fips", ossl_fips_intern_provider_init, 1 },
|
{ "fips", ossl_fips_intern_provider_init, 1 },
|
||||||
#else
|
#else
|
||||||
|
|
Loading…
Reference in New Issue