Commit a39eb840 authored by Richard Levitte's avatar Richard Levitte
Browse files

Replumbing: give the possibility for the provider to create a context



OSSL_provider_init() gets another output parameter, holding a pointer
to a provider side context.  It's entirely up to the provider to
define the context and what it's being used for.  This pointer is
passed back to other provider functions, typically the provider global
get_params and set_params functions, and also the diverse algorithm
context creators, and of course, the teardown function.

With this, a provider can be instantiated more than once, or be
re-loaded as the case may be, while maintaining instance state.

Reviewed-by: default avatarMatt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/8848)
parent f79858ac
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -172,7 +172,7 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)

    ctx->digest = type;
    if (ctx->provctx == NULL) {
        ctx->provctx = ctx->digest->newctx();
        ctx->provctx = ctx->digest->newctx(ossl_provider_ctx(type->prov));
        if (ctx->provctx == NULL) {
            EVPerr(EVP_F_EVP_DIGESTINIT_EX, EVP_R_INITIALIZATION_ERROR);
            return 0;
+1 −1
Original line number Diff line number Diff line
@@ -206,7 +206,7 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,

    ctx->cipher = cipher;
    if (ctx->provctx == NULL) {
        ctx->provctx = ctx->cipher->newctx();
        ctx->provctx = ctx->cipher->newctx(ossl_provider_ctx(cipher->prov));
        if (ctx->provctx == NULL) {
            EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR);
            return 0;
+17 −6
Original line number Diff line number Diff line
@@ -54,6 +54,9 @@ struct ossl_provider_st {
    OSSL_provider_get_param_types_fn *get_param_types;
    OSSL_provider_get_params_fn *get_params;
    OSSL_provider_query_operation_fn *query_operation;

    /* Provider side data */
    void *provctx;
};
DEFINE_STACK_OF(OSSL_PROVIDER)

@@ -275,7 +278,7 @@ void ossl_provider_free(OSSL_PROVIDER *prov)
         */
        if (ref < 2 && prov->flag_initialized) {
            if (prov->teardown != NULL)
                prov->teardown();
                prov->teardown(prov->provctx);
            prov->flag_initialized = 0;
        }

@@ -401,7 +404,8 @@ static int provider_activate(OSSL_PROVIDER *prov)
    }

    if (prov->init_function == NULL
        || !prov->init_function(prov, core_dispatch, &provider_dispatch)) {
        || !prov->init_function(prov, core_dispatch, &provider_dispatch,
                                &prov->provctx)) {
        CRYPTOerr(CRYPTO_F_PROVIDER_ACTIVATE, ERR_R_INIT_FAIL);
        ERR_add_error_data(2, "name=", prov->name);
        DSO_free(prov->module);
@@ -448,6 +452,11 @@ int ossl_provider_activate(OSSL_PROVIDER *prov)
    return 0;
}

void *ossl_provider_ctx(const OSSL_PROVIDER *prov)
{
    return prov->provctx;
}


static int provider_forall_loaded(struct provider_store_st *store,
                                  int *found_activated,
@@ -573,18 +582,20 @@ const char *ossl_provider_module_path(OSSL_PROVIDER *prov)
void ossl_provider_teardown(const OSSL_PROVIDER *prov)
{
    if (prov->teardown != NULL)
        prov->teardown();
        prov->teardown(prov->provctx);
}

const OSSL_ITEM *ossl_provider_get_param_types(const OSSL_PROVIDER *prov)
{
    return prov->get_param_types == NULL ? NULL : prov->get_param_types(prov);
    return prov->get_param_types == NULL
        ? NULL : prov->get_param_types(prov->provctx);
}

int ossl_provider_get_params(const OSSL_PROVIDER *prov,
                             const OSSL_PARAM params[])
{
    return prov->get_params == NULL ? 0 : prov->get_params(prov, params);
    return prov->get_params == NULL
        ? 0 : prov->get_params(prov->provctx, params);
}


@@ -592,7 +603,7 @@ const OSSL_ALGORITHM *ossl_provider_query_operation(const OSSL_PROVIDER *prov,
                                                    int operation_id,
                                                    int *no_cache)
{
    return prov->query_operation(prov, operation_id, no_cache);
    return prov->query_operation(prov->provctx, operation_id, no_cache);
}

/*-
+8 −1
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@
ossl_provider_find, ossl_provider_new, ossl_provider_upref,
ossl_provider_free, ossl_provider_add_module_location,
ossl_provider_set_fallback, ossl_provider_activate,
ossl_provider_forall_loaded,
ossl_provider_ctx, ossl_provider_forall_loaded,
ossl_provider_name, ossl_provider_dso,
ossl_provider_module_name, ossl_provider_module_path,
ossl_provider_teardown, ossl_provider_get_param_types,
@@ -29,6 +29,9 @@ ossl_provider_get_params, ossl_provider_query_operation
 /* Load and initialize the Provider */
 int ossl_provider_activate(OSSL_PROVIDER *prov);

 /* Return pointer to the provider's context */
 void *ossl_provider_ctx(const OSSL_PROVIDER *prov);

 /* Iterate over all loaded providers */
 int ossl_provider_forall_loaded(OPENSSL_CTX *,
                                 int (*cb)(OSSL_PROVIDER *provider,
@@ -121,6 +124,10 @@ be located in that module, and called.

=back

ossl_provider_ctx() returns a context created by the provider.
Outside of the provider, it's completely opaque, but it needs to be
passed back to some of the provider functions.

ossl_provider_forall_loaded() iterates over all the currently
"activated" providers, and calls C<cb> for each of them.
If no providers have been "activated" yet, it tries to activate all
+3 −0
Original line number Diff line number Diff line
@@ -45,6 +45,9 @@ int ossl_provider_add_parameter(OSSL_PROVIDER *prov, const char *name,
 */
int ossl_provider_activate(OSSL_PROVIDER *prov);

/* Return pointer to the provider's context */
void *ossl_provider_ctx(const OSSL_PROVIDER *prov);

/* Iterate over all loaded providers */
int ossl_provider_forall_loaded(OPENSSL_CTX *,
                                int (*cb)(OSSL_PROVIDER *provider,
Loading