mirror of
https://github.com/openssl/openssl.git
synced 2025-02-17 14:32:04 +08:00
EVP: Add evp_pkey_upgrade_to_provider(), for EVP_PKEY upgrades
This function "upgrades" a key from a legacy key container to a provider side key container. Reviewed-by: Shane Lontis <shane.lontis@oracle.com> (Merged from https://github.com/openssl/openssl/pull/11148)
This commit is contained in:
parent
3c6ed9555c
commit
badf51c869
@ -866,28 +866,40 @@ int EVP_PKEY_up_ref(EVP_PKEY *pkey)
|
||||
return ((i > 1) ? 1 : 0);
|
||||
}
|
||||
|
||||
#ifndef FIPS_MODE
|
||||
static void evp_pkey_free_legacy(EVP_PKEY *x)
|
||||
{
|
||||
if (x->ameth != NULL) {
|
||||
if (x->ameth->pkey_free)
|
||||
x->ameth->pkey_free(x);
|
||||
x->pkey.ptr = NULL;
|
||||
x->ameth = NULL;
|
||||
}
|
||||
# ifndef OPENSSL_NO_ENGINE
|
||||
ENGINE_finish(x->engine);
|
||||
x->engine = NULL;
|
||||
ENGINE_finish(x->pmeth_engine);
|
||||
x->pmeth_engine = NULL;
|
||||
# endif
|
||||
x->type = x->save_type = EVP_PKEY_NONE;
|
||||
}
|
||||
#endif /* FIPS_MODE */
|
||||
|
||||
static void evp_pkey_free_it(EVP_PKEY *x)
|
||||
{
|
||||
/* internal function; x is never NULL */
|
||||
|
||||
evp_keymgmt_util_clear_operation_cache(x);
|
||||
#ifndef FIPS_MODE
|
||||
evp_pkey_free_legacy(x);
|
||||
#endif
|
||||
|
||||
if (x->ameth && x->ameth->pkey_free) {
|
||||
x->ameth->pkey_free(x);
|
||||
x->pkey.ptr = NULL;
|
||||
}
|
||||
if (x->keymgmt != NULL) {
|
||||
evp_keymgmt_freedata(x->keymgmt, x->keydata);
|
||||
EVP_KEYMGMT_free(x->keymgmt);
|
||||
x->keymgmt = NULL;
|
||||
x->keydata = NULL;
|
||||
}
|
||||
#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
|
||||
ENGINE_finish(x->engine);
|
||||
x->engine = NULL;
|
||||
ENGINE_finish(x->pmeth_engine);
|
||||
x->pmeth_engine = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
void EVP_PKEY_free(EVP_PKEY *x)
|
||||
@ -1053,3 +1065,100 @@ void *evp_pkey_export_to_provider(EVP_PKEY *pk, OPENSSL_CTX *libctx,
|
||||
EVP_KEYMGMT_free(allocated_keymgmt);
|
||||
return keydata;
|
||||
}
|
||||
|
||||
#ifndef FIPS_MODE
|
||||
/*
|
||||
* This differs from exporting in that it releases the legacy key and assigns
|
||||
* the export keymgmt and keydata to the "origin" provider side key instead
|
||||
* of the operation cache.
|
||||
*/
|
||||
void *evp_pkey_upgrade_to_provider(EVP_PKEY *pk, OPENSSL_CTX *libctx,
|
||||
EVP_KEYMGMT **keymgmt,
|
||||
const char *propquery)
|
||||
{
|
||||
EVP_KEYMGMT *allocated_keymgmt = NULL;
|
||||
EVP_KEYMGMT *tmp_keymgmt = NULL;
|
||||
void *keydata = NULL;
|
||||
|
||||
if (pk == NULL)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* If this key is already "upgraded", this function shouldn't have been
|
||||
* called.
|
||||
*/
|
||||
if (!ossl_assert(pk->keymgmt == NULL))
|
||||
return NULL;
|
||||
|
||||
if (keymgmt != NULL) {
|
||||
tmp_keymgmt = *keymgmt;
|
||||
*keymgmt = NULL;
|
||||
}
|
||||
|
||||
/* If the key isn't a legacy one, bail out, but with proper values */
|
||||
if (pk->pkey.ptr == NULL) {
|
||||
tmp_keymgmt = pk->keymgmt;
|
||||
keydata = pk->keydata;
|
||||
} else {
|
||||
/* If the legacy key doesn't have an export function, give up */
|
||||
if (pk->ameth->export_to == NULL)
|
||||
return NULL;
|
||||
|
||||
/* If no keymgmt was given, get a default keymgmt */
|
||||
if (tmp_keymgmt == NULL) {
|
||||
EVP_PKEY_CTX *ctx =
|
||||
EVP_PKEY_CTX_new_from_pkey(libctx, pk, propquery);
|
||||
|
||||
if (ctx != NULL && ctx->keytype != NULL)
|
||||
tmp_keymgmt = allocated_keymgmt =
|
||||
EVP_KEYMGMT_fetch(ctx->libctx, ctx->keytype, propquery);
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
}
|
||||
|
||||
/* If we still don't have a keymgmt, give up */
|
||||
if (tmp_keymgmt == NULL)
|
||||
goto end;
|
||||
|
||||
/* Make sure that the keymgmt key type matches the legacy NID */
|
||||
if (!ossl_assert(EVP_KEYMGMT_is_a(tmp_keymgmt, OBJ_nid2sn(pk->type))))
|
||||
goto end;
|
||||
|
||||
if ((keydata = evp_keymgmt_newdata(tmp_keymgmt)) == NULL)
|
||||
goto end;
|
||||
|
||||
if (!pk->ameth->export_to(pk, keydata, tmp_keymgmt)
|
||||
|| !EVP_KEYMGMT_up_ref(tmp_keymgmt)) {
|
||||
evp_keymgmt_freedata(tmp_keymgmt, keydata);
|
||||
keydata = NULL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear the operation cache, all the legacy data, as well as the
|
||||
* dirty counters
|
||||
*/
|
||||
evp_pkey_free_legacy(pk);
|
||||
pk->dirty_cnt_copy = 0;
|
||||
|
||||
evp_keymgmt_util_clear_operation_cache(pk);
|
||||
pk->keymgmt = tmp_keymgmt;
|
||||
pk->keydata = keydata;
|
||||
evp_keymgmt_util_cache_keyinfo(pk);
|
||||
}
|
||||
|
||||
end:
|
||||
/*
|
||||
* If nothing was upgraded, |tmp_keymgmt| might point at a freed
|
||||
* EVP_KEYMGMT, so we clear it to be safe. It shouldn't be useful for
|
||||
* the caller either way in that case.
|
||||
*/
|
||||
if (keydata == NULL)
|
||||
tmp_keymgmt = NULL;
|
||||
|
||||
if (keymgmt != NULL)
|
||||
*keymgmt = tmp_keymgmt;
|
||||
|
||||
EVP_KEYMGMT_free(allocated_keymgmt);
|
||||
return keydata;
|
||||
}
|
||||
#endif /* FIPS_MODE */
|
||||
|
@ -603,6 +603,9 @@ void evp_app_cleanup_int(void);
|
||||
void *evp_pkey_export_to_provider(EVP_PKEY *pk, OPENSSL_CTX *libctx,
|
||||
EVP_KEYMGMT **keymgmt,
|
||||
const char *propquery);
|
||||
void *evp_pkey_upgrade_to_provider(EVP_PKEY *pk, OPENSSL_CTX *libctx,
|
||||
EVP_KEYMGMT **keymgmt,
|
||||
const char *propquery);
|
||||
|
||||
/*
|
||||
* KEYMGMT utility functions
|
||||
|
@ -207,7 +207,8 @@ static int test_pass_rsa(FIXTURE *fixture)
|
||||
|| !TEST_ptr_ne(km1, km2))
|
||||
goto err;
|
||||
|
||||
if (!TEST_ptr(evp_pkey_make_provided(pk, NULL, &km1, NULL))
|
||||
if (!TEST_ptr(evp_pkey_export_to_provider(pk, NULL, &km1, NULL))
|
||||
|| !TEST_ptr(evp_pkey_upgrade_to_provider(pk, NULL, &km1, NULL))
|
||||
|| !TEST_ptr(provkey = evp_keymgmt_util_export_to_provider(pk, km2)))
|
||||
goto err;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user