Commit 1aedc35f authored by Matt Caswell's avatar Matt Caswell
Browse files

Instead of global data store it in an OPENSSL_CTX



Various core and property related code files used global data. We should
store all of that in an OPENSSL_CTX instead.

Reviewed-by: default avatarRichard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/8857)
parent b8fe36fe
Loading
Loading
Loading
Loading
+130 −29
Original line number Diff line number Diff line
@@ -11,31 +11,76 @@
#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;
@@ -43,21 +88,28 @@ static int context_deinit(OPENSSL_CTX *ctx)
        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)
{
@@ -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);
@@ -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;

void *openssl_ctx_get_data(OPENSSL_CTX *ctx, int index)
    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,
                           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)
{
@@ -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;
}
+1 −1
Original line number Diff line number Diff line
@@ -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;
+6 −2
Original line number Diff line number Diff line
@@ -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),
@@ -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),
+2 −0
Original line number Diff line number Diff line
@@ -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
+6 −26
Original line number Diff line number Diff line
@@ -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);
}


@@ -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;
@@ -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)
@@ -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,
Loading