Ensure mirroring of properties works for subsequent updates

If the global properties are updated after a provider with a child libctx
has already started we need to make sure those updates are mirrored in
that child.

Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/15242)
This commit is contained in:
Matt Caswell 2021-05-11 16:50:27 +01:00
parent 366bf9aedb
commit b1c053acda
7 changed files with 101 additions and 17 deletions

View File

@ -51,7 +51,7 @@ static int alg_module_init(CONF_IMODULE *md, const CONF *cnf)
return 0;
}
} else if (strcmp(oval->name, "default_properties") == 0) {
if (!evp_set_default_properties_int(cnf->libctx, oval->value, 0)) {
if (!evp_set_default_properties_int(cnf->libctx, oval->value, 0, 0)) {
ERR_raise(ERR_LIB_EVP, EVP_R_SET_DEFAULT_PROPERTY_FAILURE);
return 0;
}

View File

@ -384,15 +384,28 @@ int evp_method_store_flush(OSSL_LIB_CTX *libctx)
static int evp_set_parsed_default_properties(OSSL_LIB_CTX *libctx,
OSSL_PROPERTY_LIST *def_prop,
int loadconfig)
int loadconfig,
int mirrored)
{
OSSL_METHOD_STORE *store = get_evp_method_store(libctx);
OSSL_PROPERTY_LIST **plp = ossl_ctx_global_properties(libctx, loadconfig);
if (plp != NULL && store != NULL) {
#ifndef FIPS_MODULE
char *propstr = NULL;
size_t strsz;
if (mirrored) {
if (ossl_global_properties_no_mirrored(libctx))
return 0;
} else {
/*
* These properties have been explicitly set on this libctx, so
* don't allow any mirroring from a parent libctx.
*/
ossl_global_properties_stop_mirroring(libctx);
}
strsz = ossl_property_list_to_string(libctx, def_prop, NULL, 0);
if (strsz > 0)
propstr = OPENSSL_malloc(strsz);
@ -406,10 +419,11 @@ static int evp_set_parsed_default_properties(OSSL_LIB_CTX *libctx,
ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
return 0;
}
ossl_property_free(*plp);
*plp = def_prop;
ossl_provider_default_props_update(libctx, propstr);
OPENSSL_free(propstr);
#endif
ossl_property_free(*plp);
*plp = def_prop;
if (store != NULL)
return ossl_method_store_flush_cache(store, 0);
}
@ -418,7 +432,7 @@ static int evp_set_parsed_default_properties(OSSL_LIB_CTX *libctx,
}
int evp_set_default_properties_int(OSSL_LIB_CTX *libctx, const char *propq,
int loadconfig)
int loadconfig, int mirrored)
{
OSSL_PROPERTY_LIST *pl = NULL;
@ -426,7 +440,7 @@ int evp_set_default_properties_int(OSSL_LIB_CTX *libctx, const char *propq,
ERR_raise(ERR_LIB_EVP, EVP_R_DEFAULT_QUERY_PARSE_ERROR);
return 0;
}
if (!evp_set_parsed_default_properties(libctx, pl, loadconfig)) {
if (!evp_set_parsed_default_properties(libctx, pl, loadconfig, mirrored)) {
ossl_property_free(pl);
return 0;
}
@ -435,7 +449,7 @@ int evp_set_default_properties_int(OSSL_LIB_CTX *libctx, const char *propq,
int EVP_set_default_properties(OSSL_LIB_CTX *libctx, const char *propq)
{
return evp_set_default_properties_int(libctx, propq, 1);
return evp_set_default_properties_int(libctx, propq, 1, 0);
}
static int evp_default_properties_merge(OSSL_LIB_CTX *libctx, const char *propq)
@ -457,7 +471,7 @@ static int evp_default_properties_merge(OSSL_LIB_CTX *libctx, const char *propq)
ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
return 0;
}
if (!evp_set_parsed_default_properties(libctx, pl2, 0)) {
if (!evp_set_parsed_default_properties(libctx, pl2, 0, 0)) {
ossl_property_free(pl2);
return 0;
}

View File

@ -74,25 +74,31 @@ typedef struct {
DEFINE_SPARSE_ARRAY_OF(ALGORITHM);
typedef struct ossl_global_properties_st {
OSSL_PROPERTY_LIST *list;
#ifndef FIPS_MODULE
unsigned int no_mirrored : 1;
#endif
} OSSL_GLOBAL_PROPERTIES;
static void ossl_method_cache_flush(OSSL_METHOD_STORE *store, int nid);
/* Global properties are stored per library context */
static void ossl_ctx_global_properties_free(void *vstore)
static void ossl_ctx_global_properties_free(void *vglobp)
{
OSSL_PROPERTY_LIST **plp = vstore;
OSSL_GLOBAL_PROPERTIES *globp = vglobp;
if (plp != NULL) {
ossl_property_free(*plp);
OPENSSL_free(plp);
if (globp != NULL) {
ossl_property_free(globp->list);
OPENSSL_free(globp);
}
}
static void *ossl_ctx_global_properties_new(OSSL_LIB_CTX *ctx)
{
return OPENSSL_zalloc(sizeof(OSSL_PROPERTY_LIST **));
return OPENSSL_zalloc(sizeof(OSSL_GLOBAL_PROPERTIES));
}
static const OSSL_LIB_CTX_METHOD ossl_ctx_global_properties_method = {
OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY,
ossl_ctx_global_properties_new,
@ -102,14 +108,38 @@ static const OSSL_LIB_CTX_METHOD ossl_ctx_global_properties_method = {
OSSL_PROPERTY_LIST **ossl_ctx_global_properties(OSSL_LIB_CTX *libctx,
int loadconfig)
{
OSSL_GLOBAL_PROPERTIES *globp;
#ifndef FIPS_MODULE
if (loadconfig && !OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL))
return NULL;
#endif
return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_GLOBAL_PROPERTIES,
&ossl_ctx_global_properties_method);
globp = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_GLOBAL_PROPERTIES,
&ossl_ctx_global_properties_method);
return &globp->list;
}
#ifndef FIPS_MODULE
int ossl_global_properties_no_mirrored(OSSL_LIB_CTX *libctx)
{
OSSL_GLOBAL_PROPERTIES *globp
= ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_GLOBAL_PROPERTIES,
&ossl_ctx_global_properties_method);
return globp->no_mirrored ? 1 : 0;
}
void ossl_global_properties_stop_mirroring(OSSL_LIB_CTX *libctx)
{
OSSL_GLOBAL_PROPERTIES *globp
= ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_GLOBAL_PROPERTIES,
&ossl_ctx_global_properties_method);
globp->no_mirrored = 1;
}
#endif
static int ossl_method_up_ref(METHOD *method)
{
return (*method->up_ref)(method->method);

View File

@ -15,6 +15,7 @@
#include <openssl/evp.h>
#include "internal/provider.h"
#include "internal/cryptlib.h"
#include "crypto/evp.h"
DEFINE_STACK_OF(OSSL_PROVIDER)

View File

@ -68,4 +68,7 @@ size_t ossl_property_list_to_string(OSSL_LIB_CTX *ctx,
const OSSL_PROPERTY_LIST *list, char *buf,
size_t bufsize);
int ossl_global_properties_no_mirrored(OSSL_LIB_CTX *libctx);
void ossl_global_properties_stop_mirroring(OSSL_LIB_CTX *libctx);
#endif

View File

@ -183,6 +183,22 @@ static int p_get_params(void *provctx, OSSL_PARAM params[])
} else {
ok = 0;
}
} else if (strcmp(p->key, "stop-property-mirror") == 0) {
/*
* Setting the default properties explicitly should stop mirroring
* of properties from the parent libctx.
*/
unsigned int stopsuccess = 0;
#ifdef PROVIDER_INIT_FUNCTION_NAME
stopsuccess = EVP_set_default_properties(ctx->libctx, NULL);
#endif
if (p->data_size >= sizeof(stopsuccess)) {
*(unsigned int *)p->data = stopsuccess;
p->return_size = sizeof(stopsuccess);
} else {
ok = 0;
}
}
}
return ok;

View File

@ -26,6 +26,13 @@ static OSSL_PARAM digest_check[] = {
{ NULL, 0, NULL, 0, 0 }
};
static unsigned int stopsuccess = 0;
static OSSL_PARAM stop_property_mirror[] = {
{ "stop-property-mirror", OSSL_PARAM_UNSIGNED_INTEGER, &stopsuccess,
sizeof(stopsuccess) },
{ NULL, 0, NULL, 0, 0 }
};
static int test_provider(OSSL_LIB_CTX **libctx, const char *name,
OSSL_PROVIDER *legacy)
{
@ -66,6 +73,19 @@ static int test_provider(OSSL_LIB_CTX **libctx, const char *name,
if (!TEST_true(OSSL_PROVIDER_get_params(prov, digest_check))
|| !TEST_true(digestsuccess))
goto err;
/*
* Check that a provider can prevent property mirroring if it sets its
* own properties explicitly
*/
if (!TEST_true(OSSL_PROVIDER_get_params(prov, stop_property_mirror))
|| !TEST_true(stopsuccess))
goto err;
EVP_set_default_properties(*libctx, "fips=yes");
if (!TEST_true(OSSL_PROVIDER_get_params(prov, digest_check))
|| !TEST_true(digestsuccess))
goto err;
EVP_set_default_properties(*libctx, "");
}
if (!TEST_true(OSSL_PROVIDER_get_params(prov, greeting_request))
|| !TEST_ptr(greeting = greeting_request[0].data)