Skip to content

Commit

Permalink
Instead of global data store it in an OPENSSL_CTX
Browse files Browse the repository at this point in the history
Various core and property related code files used global data. We should
store all of that in an OPENSSL_CTX instead.

Reviewed-by: Richard Levitte <[email protected]>
(Merged from openssl#8857)
  • Loading branch information
mattcaswell committed May 2, 2019
1 parent b8fe36f commit 1aedc35
Show file tree
Hide file tree
Showing 21 changed files with 509 additions and 316 deletions.
159 changes: 130 additions & 29 deletions crypto/context.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,53 +11,105 @@
#include "internal/thread_once.h"

struct openssl_ctx_onfree_list_st {
openssl_ctx_onfree_fn fn;
openssl_ctx_onfree_fn *fn;
struct openssl_ctx_onfree_list_st *next;
};

struct openssl_ctx_st {
CRYPTO_RWLOCK *lock;
CRYPTO_EX_DATA data;
int run_once_done[MAX_OPENSSL_CTX_RUN_ONCE];
int run_once_ret[MAX_OPENSSL_CTX_RUN_ONCE];

/*
* For most data in the OPENSSL_CTX we just use ex_data to store it. But
* that doesn't work for ex_data itself - so we store that directly.
*/
OSSL_EX_DATA_GLOBAL global;

/* Map internal static indexes to dynamically created indexes */
int dyn_indexes[OPENSSL_CTX_MAX_INDEXES];

CRYPTO_RWLOCK *oncelock;
int run_once_done[OPENSSL_CTX_MAX_RUN_ONCE];
int run_once_ret[OPENSSL_CTX_MAX_RUN_ONCE];
struct openssl_ctx_onfree_list_st *onfreelist;
};

static OPENSSL_CTX default_context;
#ifndef FIPS_MODE
static OPENSSL_CTX default_context_int;
#endif

/* Always points at default_context_int if it has been initialised */
static OPENSSL_CTX *default_context = NULL;

static int context_init(OPENSSL_CTX *ctx)
{
return (ctx->lock = CRYPTO_THREAD_lock_new()) != NULL
&& CRYPTO_new_ex_data(CRYPTO_EX_INDEX_OPENSSL_CTX, NULL,
&ctx->data);
size_t i;

ctx->lock = CRYPTO_THREAD_lock_new();
if (ctx->lock == NULL)
return 0;

ctx->oncelock = CRYPTO_THREAD_lock_new();
if (ctx->oncelock == NULL)
goto err;

for (i = 0; i < OPENSSL_CTX_MAX_INDEXES; i++)
ctx->dyn_indexes[i] = -1;

if (!do_ex_data_init(ctx))
goto err;

if (!crypto_new_ex_data_ex(ctx, CRYPTO_EX_INDEX_OPENSSL_CTX, NULL,
&ctx->data)) {
crypto_cleanup_all_ex_data_int(ctx);
goto err;
}

return 1;
err:
CRYPTO_THREAD_lock_free(ctx->oncelock);
CRYPTO_THREAD_lock_free(ctx->lock);
ctx->lock = NULL;
return 0;
}

static int context_deinit(OPENSSL_CTX *ctx)
{
struct openssl_ctx_onfree_list_st *tmp, *onfree = ctx->onfreelist;
struct openssl_ctx_onfree_list_st *tmp, *onfree;

if (ctx == NULL)
return 1;

onfree = ctx->onfreelist;
while (onfree != NULL) {
onfree->fn(ctx);
tmp = onfree;
onfree = onfree->next;
OPENSSL_free(tmp);
}
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_OPENSSL_CTX, NULL, &ctx->data);
crypto_cleanup_all_ex_data_int(ctx);
CRYPTO_THREAD_lock_free(ctx->oncelock);
CRYPTO_THREAD_lock_free(ctx->lock);
ctx->lock = NULL;
return 1;
}

static CRYPTO_ONCE default_context_init = CRYPTO_ONCE_STATIC_INIT;
static void do_default_context_deinit(void)
#ifndef FIPS_MODE
void openssl_ctx_default_deinit(void)
{
context_deinit(&default_context);
context_deinit(default_context);
}

static CRYPTO_ONCE default_context_init = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(do_default_context_init)
{
return OPENSSL_init_crypto(0, NULL)
&& context_init(&default_context)
&& OPENSSL_atexit(do_default_context_deinit);
if (context_init(&default_context_int))
default_context = &default_context_int;

return 1;
}
#endif

OPENSSL_CTX *OPENSSL_CTX_new(void)
{
Expand All @@ -82,7 +134,7 @@ static void openssl_ctx_generic_new(void *parent_ign, void *ptr_ign,
long argl_ign, void *argp)
{
const OPENSSL_CTX_METHOD *meth = argp;
void *ptr = meth->new_func();
void *ptr = meth->new_func(crypto_ex_data_get_openssl_ctx(ad));

if (ptr != NULL)
CRYPTO_set_ex_data(ad, index, ptr);
Expand All @@ -95,37 +147,86 @@ static void openssl_ctx_generic_free(void *parent_ign, void *ptr,

meth->free_func(ptr);
}
int openssl_ctx_new_index(const OPENSSL_CTX_METHOD *meth)

/* Non-static so we can use it in context_internal_test */
static int openssl_ctx_init_index(OPENSSL_CTX *ctx, int static_index,
const OPENSSL_CTX_METHOD *meth)
{
return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_OPENSSL_CTX, 0, (void *)meth,
openssl_ctx_generic_new, NULL,
openssl_ctx_generic_free);
int idx;

#ifndef FIPS_MODE
if (ctx == NULL) {
if (!RUN_ONCE(&default_context_init, do_default_context_init))
return 0;
ctx = default_context;
}
#endif
if (ctx == NULL)
return 0;

idx = crypto_get_ex_new_index_ex(ctx, CRYPTO_EX_INDEX_OPENSSL_CTX, 0,
(void *)meth,
openssl_ctx_generic_new,
NULL, openssl_ctx_generic_free);
if (idx < 0)
return 0;

ctx->dyn_indexes[static_index] = idx;
return 1;
}

void *openssl_ctx_get_data(OPENSSL_CTX *ctx, int index)
void *openssl_ctx_get_data(OPENSSL_CTX *ctx, int index,
const OPENSSL_CTX_METHOD *meth)
{
void *data = NULL;

#ifndef FIPS_MODE
if (ctx == NULL) {
if (!RUN_ONCE(&default_context_init, do_default_context_init))
return NULL;
ctx = &default_context;
ctx = default_context;
}
#endif
if (ctx == NULL)
return NULL;

CRYPTO_THREAD_read_lock(ctx->lock);

if (ctx->dyn_indexes[index] == -1
&& !openssl_ctx_init_index(ctx, index, meth)) {
CRYPTO_THREAD_unlock(ctx->lock);
return NULL;
}

/* The alloc call ensures there's a value there */
if (CRYPTO_alloc_ex_data(CRYPTO_EX_INDEX_OPENSSL_CTX, NULL,
&ctx->data, index))
data = CRYPTO_get_ex_data(&ctx->data, index);
&ctx->data, ctx->dyn_indexes[index]))
data = CRYPTO_get_ex_data(&ctx->data, ctx->dyn_indexes[index]);

CRYPTO_THREAD_unlock(ctx->lock);

return data;
}

OSSL_EX_DATA_GLOBAL *openssl_ctx_get_ex_data_global(OPENSSL_CTX *ctx)
{
/*
* The default context code is not needed in FIPS_MODE and ctx should never
* be NULL in the FIPS provider. However we compile this code out to ensure
* we fail immediately if ctx == NULL in FIPS_MODE
*/
#ifndef FIPS_MODE
if (ctx == NULL) {
if (!RUN_ONCE(&default_context_init, do_default_context_init))
return NULL;
ctx = default_context;
}
#endif
if (ctx == NULL)
return NULL;
return &ctx->global;
}

int openssl_ctx_run_once(OPENSSL_CTX *ctx, unsigned int idx,
openssl_ctx_run_once_fn run_once_fn)
{
Expand All @@ -135,32 +236,32 @@ int openssl_ctx_run_once(OPENSSL_CTX *ctx, unsigned int idx,
if (ctx == NULL) {
if (!RUN_ONCE(&default_context_init, do_default_context_init))
return 0;
ctx = &default_context;
ctx = default_context;
}
#endif
if (ctx == NULL)
return 0;

CRYPTO_THREAD_read_lock(ctx->lock);
CRYPTO_THREAD_read_lock(ctx->oncelock);
done = ctx->run_once_done[idx];
if (done)
ret = ctx->run_once_ret[idx];
CRYPTO_THREAD_unlock(ctx->lock);
CRYPTO_THREAD_unlock(ctx->oncelock);

if (done)
return ret;

CRYPTO_THREAD_write_lock(ctx->lock);
CRYPTO_THREAD_write_lock(ctx->oncelock);
if (ctx->run_once_done[idx]) {
ret = ctx->run_once_ret[idx];
CRYPTO_THREAD_unlock(ctx->lock);
CRYPTO_THREAD_unlock(ctx->oncelock);
return ret;
}

ret = run_once_fn(ctx);
ctx->run_once_done[idx] = 1;
ctx->run_once_ret[idx] = ret;
CRYPTO_THREAD_unlock(ctx->lock);
CRYPTO_THREAD_unlock(ctx->oncelock);

return ret;
}
Expand Down
2 changes: 1 addition & 1 deletion crypto/core_fetch.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ void *ossl_method_construct(OPENSSL_CTX *libctx, int operation_id,
* We have a temporary store to be able to easily search among new
* items, or items that should find themselves in the global store.
*/
if ((cbdata.store = mcm->alloc_tmp_store()) == NULL)
if ((cbdata.store = mcm->alloc_tmp_store(libctx)) == NULL)
goto fin;

cbdata.libctx = libctx;
Expand Down
8 changes: 6 additions & 2 deletions crypto/cpt_err.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,13 @@ static const ERR_STRING_DATA CRYPTO_str_functs[] = {
"CRYPTO_free_ex_data"},
{ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX, 0),
"CRYPTO_get_ex_new_index"},
{ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX_EX, 0),
"CRYPTO_get_ex_new_index_ex"},
{ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_CRYPTO_MEMDUP, 0), "CRYPTO_memdup"},
{ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_CRYPTO_NEW_EX_DATA, 0),
"CRYPTO_new_ex_data"},
{ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_CRYPTO_NEW_EX_DATA_EX, 0),
"crypto_new_ex_data_ex"},
{ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_CRYPTO_OCB128_COPY_CTX, 0),
"CRYPTO_ocb128_copy_ctx"},
{ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_CRYPTO_OCB128_INIT, 0),
Expand All @@ -46,10 +50,10 @@ static const ERR_STRING_DATA CRYPTO_str_functs[] = {
{ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_OPENSSL_SK_DEEP_COPY, 0),
"OPENSSL_sk_deep_copy"},
{ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_OPENSSL_SK_DUP, 0), "OPENSSL_sk_dup"},
{ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_OSSL_PROVIDER_ADD_BUILTIN, 0),
"OSSL_PROVIDER_add_builtin"},
{ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_OSSL_PROVIDER_ACTIVATE, 0),
"ossl_provider_activate"},
{ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_OSSL_PROVIDER_ADD_BUILTIN, 0),
"OSSL_PROVIDER_add_builtin"},
{ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_OSSL_PROVIDER_ADD_PARAMETER, 0),
"ossl_provider_add_parameter"},
{ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_OSSL_PROVIDER_NEW, 0),
Expand Down
2 changes: 2 additions & 0 deletions crypto/err/openssl.txt
Original file line number Diff line number Diff line change
Expand Up @@ -374,8 +374,10 @@ CRYPTO_F_CMAC_CTX_NEW:120:CMAC_CTX_new
CRYPTO_F_CRYPTO_DUP_EX_DATA:110:CRYPTO_dup_ex_data
CRYPTO_F_CRYPTO_FREE_EX_DATA:111:CRYPTO_free_ex_data
CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX:100:CRYPTO_get_ex_new_index
CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX_EX:141:crypto_get_ex_new_index_ex
CRYPTO_F_CRYPTO_MEMDUP:115:CRYPTO_memdup
CRYPTO_F_CRYPTO_NEW_EX_DATA:112:CRYPTO_new_ex_data
CRYPTO_F_CRYPTO_NEW_EX_DATA_EX:142:crypto_new_ex_data_ex
CRYPTO_F_CRYPTO_OCB128_COPY_CTX:121:CRYPTO_ocb128_copy_ctx
CRYPTO_F_CRYPTO_OCB128_INIT:122:CRYPTO_ocb128_init
CRYPTO_F_CRYPTO_SET_EX_DATA:102:CRYPTO_set_ex_data
Expand Down
32 changes: 6 additions & 26 deletions crypto/evp/evp_fetch.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,14 @@
#include "internal/evp_int.h" /* evp_locl.h needs it */
#include "evp_locl.h"

/* The OpenSSL library context index for the default method store */
static int default_method_store_index = -1;

static void default_method_store_free(void *vstore)
{
ossl_method_store_free(vstore);
}

static void *default_method_store_new(void)
static void *default_method_store_new(OPENSSL_CTX *ctx)
{
return ossl_method_store_new();
return ossl_method_store_new(ctx);
}


Expand All @@ -38,21 +35,6 @@ static const OPENSSL_CTX_METHOD default_method_store_method = {
default_method_store_free,
};

static int default_method_store_init(void)
{
default_method_store_index =
openssl_ctx_new_index(&default_method_store_method);

return default_method_store_index != -1;
}

static CRYPTO_ONCE default_method_store_init_flag = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(do_default_method_store_init)
{
return OPENSSL_init_crypto(0, NULL)
&& default_method_store_init();
}

/* Data to be passed through ossl_method_construct() */
struct method_data_st {
const char *name;
Expand All @@ -68,9 +50,9 @@ struct method_data_st {
/*
* Generic routines to fetch / create EVP methods with ossl_method_construct()
*/
static void *alloc_tmp_method_store(void)
static void *alloc_tmp_method_store(OPENSSL_CTX *ctx)
{
return ossl_method_store_new();
return ossl_method_store_new(ctx);
}

static void dealloc_tmp_method_store(void *store)
Expand All @@ -81,10 +63,8 @@ static void *alloc_tmp_method_store(void)

static OSSL_METHOD_STORE *get_default_method_store(OPENSSL_CTX *libctx)
{
if (!RUN_ONCE(&default_method_store_init_flag,
do_default_method_store_init))
return NULL;
return openssl_ctx_get_data(libctx, default_method_store_index);
return openssl_ctx_get_data(libctx, OPENSSL_CTX_DEFAULT_METHOD_STORE_INDEX,
&default_method_store_method);
}

static void *get_method_from_store(OPENSSL_CTX *libctx, void *store,
Expand Down
Loading

0 comments on commit 1aedc35

Please sign in to comment.