Latest update

This commit is contained in:
2019-04-01 00:21:15 +09:00
parent c03e0c45f8
commit 48ec086472
209 changed files with 7552 additions and 2495 deletions
+175 -37
View File
@@ -11,9 +11,14 @@
#include <openssl/core_numbers.h>
#include <openssl/opensslv.h>
#include "internal/cryptlib.h"
#include "internal/nelem.h"
#include "internal/thread_once.h"
#include "internal/provider.h"
#include "internal/refcount.h"
#include "provider_local.h"
static OSSL_PROVIDER *provider_new(const char *name,
OSSL_provider_init_fn *init_function);
/*-
* Provider Object structure
@@ -25,6 +30,7 @@ struct provider_store_st; /* Forward declaration */
struct ossl_provider_st {
/* Flag bits */
unsigned int flag_initialized:1;
unsigned int flag_fallback:1;
/* OpenSSL library side data */
CRYPTO_REF_COUNT refcnt;
@@ -32,6 +38,7 @@ struct ossl_provider_st {
char *name;
DSO *module;
OSSL_provider_init_fn *init_function;
struct provider_store_st *store; /* The store this instance belongs to */
/* Provider side functions */
OSSL_provider_teardown_fn *teardown;
@@ -58,6 +65,7 @@ static int ossl_provider_cmp(const OSSL_PROVIDER * const *a,
struct provider_store_st {
STACK_OF(OSSL_PROVIDER) *providers;
CRYPTO_RWLOCK *lock;
unsigned int use_fallbacks:1;
};
static int provider_store_index = -1;
@@ -75,13 +83,37 @@ static void provider_store_free(void *vstore)
static void *provider_store_new(void)
{
struct provider_store_st *store = OPENSSL_zalloc(sizeof(*store));
const struct predefined_providers_st *p = NULL;
if (store == NULL
|| (store->providers = sk_OSSL_PROVIDER_new(ossl_provider_cmp)) == NULL
|| (store->lock = CRYPTO_THREAD_lock_new()) == NULL) {
provider_store_free(store);
store = NULL;
return NULL;
}
store->use_fallbacks = 1;
for (p = predefined_providers; p->name != NULL; p++) {
OSSL_PROVIDER *prov = NULL;
/*
* We use the internal constructor directly here,
* otherwise we get a call loop
*/
prov = provider_new(p->name, p->init);
if (prov == NULL
|| sk_OSSL_PROVIDER_push(store->providers, prov) == 0) {
ossl_provider_free(prov);
provider_store_free(store);
CRYPTOerr(CRYPTO_F_PROVIDER_STORE_NEW, ERR_R_INTERNAL_ERROR);
return NULL;
}
prov->store = store;
if(p->is_fallback)
ossl_provider_set_fallback(prov);
}
return store;
}
@@ -112,20 +144,6 @@ static struct provider_store_st *get_provider_store(OPENSSL_CTX *libctx)
return store;
}
/*-
* Provider Object methods
* =======================
*/
int ossl_provider_upref(OSSL_PROVIDER *prov)
{
int ref = 0;
CRYPTO_UP_REF(&prov->refcnt, &ref, prov->refcnt_lock);
return ref;
}
/* Finder, constructor and destructor */
OSSL_PROVIDER *ossl_provider_find(OPENSSL_CTX *libctx, const char *name)
{
struct provider_store_st *store = NULL;
@@ -147,6 +165,39 @@ OSSL_PROVIDER *ossl_provider_find(OPENSSL_CTX *libctx, const char *name)
return prov;
}
/*-
* Provider Object methods
* =======================
*/
static OSSL_PROVIDER *provider_new(const char *name,
OSSL_provider_init_fn *init_function)
{
OSSL_PROVIDER *prov = NULL;
if ((prov = OPENSSL_zalloc(sizeof(*prov))) == NULL
#ifndef HAVE_ATOMICS
|| (prov->refcnt_lock = CRYPTO_THREAD_lock_new()) == NULL
#endif
|| !ossl_provider_upref(prov) /* +1 One reference to be returned */
|| (prov->name = OPENSSL_strdup(name)) == NULL) {
ossl_provider_free(prov);
CRYPTOerr(CRYPTO_F_PROVIDER_NEW, ERR_R_MALLOC_FAILURE);
return NULL;
}
prov->init_function = init_function;
return prov;
}
int ossl_provider_upref(OSSL_PROVIDER *prov)
{
int ref = 0;
CRYPTO_UP_REF(&prov->refcnt, &ref, prov->refcnt_lock);
return ref;
}
OSSL_PROVIDER *ossl_provider_new(OPENSSL_CTX *libctx, const char *name,
OSSL_provider_init_fn *init_function)
{
@@ -164,18 +215,9 @@ OSSL_PROVIDER *ossl_provider_new(OPENSSL_CTX *libctx, const char *name,
return NULL;
}
if ((prov = OPENSSL_zalloc(sizeof(*prov))) == NULL
#ifndef HAVE_ATOMICS
|| (prov->refcnt_lock = CRYPTO_THREAD_lock_new()) == NULL
#endif
|| !ossl_provider_upref(prov) /* +1 One reference to be returned */
|| (prov->name = OPENSSL_strdup(name)) == NULL) {
ossl_provider_free(prov);
CRYPTOerr(CRYPTO_F_OSSL_PROVIDER_NEW, ERR_R_MALLOC_FAILURE);
/* provider_new() generates an error, so no need here */
if ((prov = provider_new(name, init_function)) == NULL)
return NULL;
}
prov->init_function = init_function;
CRYPTO_THREAD_write_lock(store->lock);
if (!ossl_provider_upref(prov)) { /* +1 One reference for the store */
@@ -185,6 +227,8 @@ OSSL_PROVIDER *ossl_provider_new(OPENSSL_CTX *libctx, const char *name,
ossl_provider_free(prov); /* -1 Store reference */
ossl_provider_free(prov); /* -1 Reference that was to be returned */
prov = NULL;
} else {
prov->store = store;
}
CRYPTO_THREAD_unlock(store->lock);
@@ -207,11 +251,13 @@ void ossl_provider_free(OSSL_PROVIDER *prov)
CRYPTO_DOWN_REF(&prov->refcnt, &ref, prov->refcnt_lock);
/*
* When the refcount drops down to one, there is only one reference,
* the store.
* When the refcount drops below two, the store is the only
* possible reference, or it has already been taken away from
* the store (this may happen if a provider was activated
* because it's a fallback, but isn't currently used)
* When that happens, the provider is inactivated.
*/
if (ref == 1 && prov->flag_initialized) {
if (ref < 2 && prov->flag_initialized) {
if (prov->teardown != NULL)
prov->teardown();
prov->flag_initialized = 0;
@@ -246,7 +292,12 @@ void ossl_provider_free(OSSL_PROVIDER *prov)
*/
static const OSSL_DISPATCH *core_dispatch; /* Define further down */
int ossl_provider_activate(OSSL_PROVIDER *prov)
/*
* Internal version that doesn't affect the store flags, and thereby avoid
* locking. Direct callers must remember to set the store flags when
* appropriate
*/
static int provider_activate(OSSL_PROVIDER *prov)
{
const OSSL_DISPATCH *provider_dispatch = NULL;
@@ -295,7 +346,7 @@ int ossl_provider_activate(OSSL_PROVIDER *prov)
if (prov->init_function == NULL
|| !prov->init_function(prov, core_dispatch, &provider_dispatch)) {
CRYPTOerr(CRYPTO_F_OSSL_PROVIDER_ACTIVATE, ERR_R_INIT_FAIL);
CRYPTOerr(CRYPTO_F_PROVIDER_ACTIVATE, ERR_R_INIT_FAIL);
ERR_add_error_data(2, "name=", prov->name);
DSO_free(prov->module);
prov->module = NULL;
@@ -329,6 +380,46 @@ int ossl_provider_activate(OSSL_PROVIDER *prov)
return 1;
}
int ossl_provider_activate(OSSL_PROVIDER *prov)
{
if (provider_activate(prov)) {
CRYPTO_THREAD_write_lock(prov->store->lock);
prov->store->use_fallbacks = 0;
CRYPTO_THREAD_unlock(prov->store->lock);
return 1;
}
return 0;
}
static int provider_forall_loaded(struct provider_store_st *store,
int *found_activated,
int (*cb)(OSSL_PROVIDER *provider,
void *cbdata),
void *cbdata)
{
int i;
int ret = 1;
int num_provs = sk_OSSL_PROVIDER_num(store->providers);
if (found_activated != NULL)
*found_activated = 0;
for (i = 0; i < num_provs; i++) {
OSSL_PROVIDER *prov =
sk_OSSL_PROVIDER_value(store->providers, i);
if (prov->flag_initialized) {
if (found_activated != NULL)
*found_activated = 1;
if (!(ret = cb(prov, cbdata)))
break;
}
}
return ret;
}
int ossl_provider_forall_loaded(OPENSSL_CTX *ctx,
int (*cb)(OSSL_PROVIDER *provider,
void *cbdata),
@@ -339,13 +430,50 @@ int ossl_provider_forall_loaded(OPENSSL_CTX *ctx,
struct provider_store_st *store = get_provider_store(ctx);
if (store != NULL) {
CRYPTO_THREAD_read_lock(store->lock);
for (i = 0; i < sk_OSSL_PROVIDER_num(store->providers); i++) {
OSSL_PROVIDER *prov = sk_OSSL_PROVIDER_value(store->providers, i);
int found_activated = 0;
if (prov->flag_initialized
&& !(ret = cb(prov, cbdata)))
break;
CRYPTO_THREAD_read_lock(store->lock);
ret = provider_forall_loaded(store, &found_activated, cb, cbdata);
/*
* If there's nothing activated ever in this store, try to activate
* all fallbacks.
*/
if (!found_activated && store->use_fallbacks) {
int num_provs = sk_OSSL_PROVIDER_num(store->providers);
int activated_fallback_count = 0;
for (i = 0; i < num_provs; i++) {
OSSL_PROVIDER *prov =
sk_OSSL_PROVIDER_value(store->providers, i);
/*
* Note that we don't care if the activation succeeds or
* not. If it doesn't succeed, then the next loop will
* fail anyway.
*/
if (prov->flag_fallback) {
activated_fallback_count++;
provider_activate(prov);
}
}
if (activated_fallback_count > 0) {
/*
* We assume that all fallbacks have been added to the store
* before any fallback is activated.
* TODO: We may have to reconsider this, IF we find ourselves
* adding fallbacks after any previous fallback has been
* activated.
*/
store->use_fallbacks = 0;
/*
* Now that we've activated available fallbacks, try a
* second sweep
*/
ret = provider_forall_loaded(store, NULL, cb, cbdata);
}
}
CRYPTO_THREAD_unlock(store->lock);
}
@@ -353,6 +481,16 @@ int ossl_provider_forall_loaded(OPENSSL_CTX *ctx,
return ret;
}
/* Setters of Provider Object data */
int ossl_provider_set_fallback(OSSL_PROVIDER *prov)
{
if (prov == NULL)
return 0;
prov->flag_fallback = 1;
return 1;
}
/* Getters of Provider Object data */
const char *ossl_provider_name(OSSL_PROVIDER *prov)
{