Redesign the KEYMGMT libcrypto <-> provider interface - the basics

The KEYMGMT libcrypto <-> provider interface currently makes a few
assumptions:

1.  provider side domain parameters and key data isn't mutable. In
    other words, as soon as a key has been created in any (loaded,
    imported data, ...), it's set in stone.
2.  provider side domain parameters can be strictly separated from the
    key data.

This does work for the most part, but there are places where that's a
bit too rigid for the functionality that the EVP_PKEY API delivers.
Key data needs to be mutable to allow the flexibility that functions
like EVP_PKEY_copy_parameters promise, as well as to provide the
combinations of data that an EVP_PKEY is generally assumed to be able
to hold:

- domain parameters only
- public key only
- public key + private key
- domain parameters + public key
- domain parameters + public key + private key

To remedy all this, we:

1.  let go of the distinction between domain parameters and key
    material proper in the libcrypto <-> provider interface.

    As a consequence, functions that still need it gain a selection
    argument, which is a set of bits that indicate what parts of the
    key object are to be considered in a specific call.  This allows
    a reduction of very similar functions into one.

2.  Rework the libcrypto <-> provider interface so provider side key
    objects are created and destructed with a separate function, and
    get their data filled and extracted in through import and export.

(future work will see other key object constructors and other
functions to fill them with data)

Fixes #10979

squash! Redesign the KEYMGMT libcrypto <-> provider interface - the basics

Remedy 1 needs a rewrite:

Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
Reviewed-by: Paul Dale <paul.dale@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/11006)
master
Richard Levitte 3 years ago
parent 68552cdef7
commit b305452f69

@ -482,51 +482,47 @@ static size_t dh_pkey_dirty_cnt(const EVP_PKEY *pkey)
return pkey->pkey.dh->dirty_cnt;
}
static void *dh_pkey_export_to(const EVP_PKEY *pk, EVP_KEYMGMT *keymgmt,
int want_domainparams)
static int dh_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
EVP_KEYMGMT *to_keymgmt)
{
DH *dh = pk->pkey.dh;
DH *dh = from->pkey.dh;
OSSL_PARAM_BLD tmpl;
const BIGNUM *p = DH_get0_p(dh), *g = DH_get0_g(dh), *q = DH_get0_q(dh);
const BIGNUM *pub_key = DH_get0_pub_key(dh);
const BIGNUM *priv_key = DH_get0_priv_key(dh);
OSSL_PARAM *params;
void *provdata = NULL;
int rv;
if (p == NULL || g == NULL)
return NULL;
return 0;
ossl_param_bld_init(&tmpl);
if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_FFC_P, p)
|| !ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_FFC_G, g))
return NULL;
return 0;
if (q != NULL) {
if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_FFC_Q, q))
return NULL;
return 0;
}
if (!want_domainparams) {
/* A key must at least have a public part. */
if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_DH_PUB_KEY,
pub_key))
return NULL;
if (priv_key != NULL) {
if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_DH_PRIV_KEY,
priv_key))
return NULL;
}
/* A key must at least have a public part. */
if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_DH_PUB_KEY, pub_key))
return 0;
if (priv_key != NULL) {
if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_DH_PRIV_KEY,
priv_key))
return 0;
}
params = ossl_param_bld_to_param(&tmpl);
if ((params = ossl_param_bld_to_param(&tmpl)) == NULL)
return 0;
/* We export, the provider imports */
provdata = want_domainparams
? evp_keymgmt_importdomparams(keymgmt, params)
: evp_keymgmt_importkey(keymgmt, params);
rv = evp_keymgmt_import(to_keymgmt, to_keydata, OSSL_KEYMGMT_SELECT_ALL,
params);
ossl_param_bld_free(params);
return provdata;
return rv;
}
const EVP_PKEY_ASN1_METHOD dh_asn1_meth = {

@ -511,48 +511,44 @@ static size_t dsa_pkey_dirty_cnt(const EVP_PKEY *pkey)
return pkey->pkey.dsa->dirty_cnt;
}
static void *dsa_pkey_export_to(const EVP_PKEY *pk, EVP_KEYMGMT *keymgmt,
int want_domainparams)
static int dsa_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
EVP_KEYMGMT *to_keymgmt)
{
DSA *dsa = pk->pkey.dsa;
DSA *dsa = from->pkey.dsa;
OSSL_PARAM_BLD tmpl;
const BIGNUM *p = DSA_get0_p(dsa), *g = DSA_get0_g(dsa);
const BIGNUM *q = DSA_get0_q(dsa), *pub_key = DSA_get0_pub_key(dsa);
const BIGNUM *priv_key = DSA_get0_priv_key(dsa);
OSSL_PARAM *params;
void *provdata = NULL;
int rv;
if (p == NULL || q == NULL || g == NULL)
return NULL;
return 0;
ossl_param_bld_init(&tmpl);
if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_FFC_P, p)
|| !ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_FFC_Q, q)
|| !ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_FFC_G, g))
return NULL;
if (!want_domainparams) {
/* A key must at least have a public part. */
if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_DSA_PUB_KEY,
pub_key))
return NULL;
if (priv_key != NULL) {
if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_DSA_PRIV_KEY,
priv_key))
return NULL;
}
return 0;
if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_DSA_PUB_KEY,
pub_key))
return 0;
if (priv_key != NULL) {
if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_DSA_PRIV_KEY,
priv_key))
return 0;
}
params = ossl_param_bld_to_param(&tmpl);
if ((params = ossl_param_bld_to_param(&tmpl)) == NULL)
return 0;
/* We export, the provider imports */
provdata = want_domainparams
? evp_keymgmt_importdomparams(keymgmt, params)
: evp_keymgmt_importkey(keymgmt, params);
rv = evp_keymgmt_import(to_keymgmt, to_keydata, OSSL_KEYMGMT_SELECT_ALL,
params);
ossl_param_bld_free(params);
return provdata;
return rv;
}
/* NB these are sorted in pkey_id order, lowest first */

@ -75,31 +75,6 @@ DH *DSA_dup_DH(const DSA *r)
}
# endif /* OPENSSL_NO_DH */
const BIGNUM *DSA_get0_p(const DSA *d)
{
return d->params.p;
}
const BIGNUM *DSA_get0_q(const DSA *d)
{
return d->params.q;
}
const BIGNUM *DSA_get0_g(const DSA *d)
{
return d->params.g;
}
const BIGNUM *DSA_get0_pub_key(const DSA *d)
{
return d->pub_key;
}
const BIGNUM *DSA_get0_priv_key(const DSA *d)
{
return d->priv_key;
}
void DSA_clear_flags(DSA *d, int flags)
{
d->flags &= ~flags;
@ -278,6 +253,31 @@ int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g)
return 1;
}
const BIGNUM *DSA_get0_p(const DSA *d)
{
return d->params.p;
}
const BIGNUM *DSA_get0_q(const DSA *d)
{
return d->params.q;
}
const BIGNUM *DSA_get0_g(const DSA *d)
{
return d->params.g;
}
const BIGNUM *DSA_get0_pub_key(const DSA *d)
{
return d->pub_key;
}
const BIGNUM *DSA_get0_priv_key(const DSA *d)
{
return d->priv_key;
}
void DSA_get0_key(const DSA *d,
const BIGNUM **pub_key, const BIGNUM **priv_key)
{

@ -73,39 +73,24 @@ struct evp_keymgmt_st {
CRYPTO_REF_COUNT refcnt;
CRYPTO_RWLOCK *lock;
/* Domain parameter routines */
OSSL_OP_keymgmt_importdomparams_fn *importdomparams;
OSSL_OP_keymgmt_gendomparams_fn *gendomparams;
OSSL_OP_keymgmt_freedomparams_fn *freedomparams;
OSSL_OP_keymgmt_exportdomparams_fn *exportdomparams;
OSSL_OP_keymgmt_importdomparam_types_fn *importdomparam_types;
OSSL_OP_keymgmt_exportdomparam_types_fn *exportdomparam_types;
OSSL_OP_keymgmt_get_domparam_params_fn *get_domparam_params;
OSSL_OP_keymgmt_gettable_domparam_params_fn *gettable_domparam_params;
OSSL_OP_keymgmt_validate_domparams_fn *validatedomparams;
/* Key routines */
OSSL_OP_keymgmt_importkey_fn *importkey;
OSSL_OP_keymgmt_genkey_fn *genkey;
OSSL_OP_keymgmt_loadkey_fn *loadkey;
OSSL_OP_keymgmt_freekey_fn *freekey;
OSSL_OP_keymgmt_exportkey_fn *exportkey;
OSSL_OP_keymgmt_importkey_types_fn *importkey_types;
OSSL_OP_keymgmt_exportkey_types_fn *exportkey_types;
OSSL_OP_keymgmt_get_key_params_fn *get_key_params;
OSSL_OP_keymgmt_gettable_key_params_fn *gettable_key_params;
/* Constructor(s), destructor, information */
OSSL_OP_keymgmt_new_fn *new;
OSSL_OP_keymgmt_free_fn *free;
OSSL_OP_keymgmt_get_params_fn *get_params;
OSSL_OP_keymgmt_gettable_params_fn *gettable_params;
/* Key object checking */
OSSL_OP_keymgmt_query_operation_name_fn *query_operation_name;
OSSL_OP_keymgmt_validate_public_fn *validatepublic;
OSSL_OP_keymgmt_validate_private_fn *validateprivate;
OSSL_OP_keymgmt_validate_pairwise_fn *validatepairwise;
OSSL_OP_keymgmt_has_fn *has;
OSSL_OP_keymgmt_validate_fn *validate;
/* Import and export routines */
OSSL_OP_keymgmt_import_fn *import;
OSSL_OP_keymgmt_import_types_fn *import_types;
OSSL_OP_keymgmt_export_fn *export;
OSSL_OP_keymgmt_export_types_fn *export_types;
} /* EVP_KEYMGMT */ ;
struct keymgmt_data_st {
OPENSSL_CTX *ctx;
const char *properties;
};
struct evp_keyexch_st {
int name_id;
OSSL_PROVIDER *prov;
@ -286,5 +271,4 @@ void evp_names_do_all(OSSL_PROVIDER *prov, int number,
void *data);
int evp_cipher_cache_constants(EVP_CIPHER *cipher);
void *evp_pkey_make_provided(EVP_PKEY *pk, OPENSSL_CTX *libctx,
EVP_KEYMGMT **keymgmt, const char *propquery,
int domainparams);
EVP_KEYMGMT **keymgmt, const char *propquery);

@ -187,7 +187,7 @@ int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx)
/* Ensure that the key is provided. If not, go legacy */
tmp_keymgmt = ctx->keymgmt;
provkey = evp_pkey_make_provided(ctx->pkey, ctx->libctx,
&tmp_keymgmt, ctx->propquery, 0);
&tmp_keymgmt, ctx->propquery);
if (provkey == NULL)
goto legacy;
if (!EVP_KEYMGMT_up_ref(tmp_keymgmt)) {
@ -293,7 +293,7 @@ int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer)
return -2;
}
provkey = evp_keymgmt_util_export_to_provider(peer, ctx->keymgmt, 0);
provkey = evp_keymgmt_util_export_to_provider(peer, ctx->keymgmt);
/* If export failed, legacy may be able to pick it up */
if (provkey == NULL)
goto legacy;

@ -17,25 +17,23 @@
#include "evp_local.h"
struct import_data_st {
void *provctx;
void *(*importfn)(const EVP_KEYMGMT *keymgmt, const OSSL_PARAM params[]);
EVP_KEYMGMT *keymgmt;
void *keydata;
/* Result */
void *provdata;
int selection;
};
static int try_import(const OSSL_PARAM params[], void *arg)
{
struct import_data_st *data = arg;
data->provdata = data->importfn(data->provctx, params);
return data->provdata != NULL;
return evp_keymgmt_import(data->keymgmt, data->keydata, data->selection,
params);
}
void *evp_keymgmt_util_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt,
int want_domainparams)
void *evp_keymgmt_util_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt)
{
void *provdata = NULL;
void *keydata = NULL;
size_t i, j;
/*
@ -61,25 +59,28 @@ void *evp_keymgmt_util_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt,
for (i = 0;
i < OSSL_NELEM(pk->pkeys) && pk->pkeys[i].keymgmt != NULL;
i++) {
if (keymgmt == pk->pkeys[i].keymgmt
&& want_domainparams == pk->pkeys[i].domainparams)
return pk->pkeys[i].provdata;
if (keymgmt == pk->pkeys[i].keymgmt)
return pk->pkeys[i].keydata;
}
if ((keydata = evp_keymgmt_newdata(keymgmt)) == NULL)
return NULL;
if (pk->pkey.ptr != NULL) {
/* There is a legacy key, try to export that one to the provider */
/* If the legacy key doesn't have an export function, give up */
if (pk->ameth->export_to == NULL)
/*
* If the legacy key doesn't have an export function or the export
* function fails, give up
*/
if (pk->ameth->export_to == NULL
|| !pk->ameth->export_to(pk, keydata, keymgmt)) {
evp_keymgmt_freedata(keymgmt, keydata);
return NULL;
}
/* Otherwise, simply use it. */
provdata = pk->ameth->export_to(pk, keymgmt, want_domainparams);
/* Synchronize the dirty count, but only if we exported successfully */
if (provdata != NULL)
pk->dirty_cnt_copy = pk->ameth->dirty_cnt(pk);
/* Synchronize the dirty count */
pk->dirty_cnt_copy = pk->ameth->dirty_cnt(pk);
} else {
/*
* Here, there is no legacy key, so we look at the already cached
@ -91,42 +92,33 @@ void *evp_keymgmt_util_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt,
/* Setup for the export callback */
struct import_data_st import_data;
import_data.importfn =
want_domainparams
? evp_keymgmt_importdomparams
: evp_keymgmt_importkey;
import_data.provdata = NULL;
/*
* If the given keymgmt doesn't have an import function, give up
*/
if (import_data.importfn == NULL)
return NULL;
import_data.keydata = keydata;
import_data.keymgmt = keymgmt;
import_data.selection = OSSL_KEYMGMT_SELECT_ALL;
for (j = 0; j < i && pk->pkeys[j].keymgmt != NULL; j++) {
int (*exportfn)(const EVP_KEYMGMT *keymgmt, void *provdata,
OSSL_CALLBACK *cb, void *cbarg) =
want_domainparams
? evp_keymgmt_exportdomparams
: evp_keymgmt_exportkey;
if (exportfn != NULL) {
import_data.provctx =
ossl_provider_ctx(EVP_KEYMGMT_provider(keymgmt));
/*
* The export function calls the callback (try_import), which
* does the import for us.
* Even though we got a success return, we double check that
* we actually got something, just in case some implementation
* forgets to check the return value.
*/
if (exportfn(pk->pkeys[j].keymgmt, pk->pkeys[j].provdata,
&try_import, &import_data)
&& (provdata = import_data.provdata) != NULL)
break;
}
EVP_KEYMGMT *exp_keymgmt = pk->pkeys[i].keymgmt;
void *exp_keydata = pk->pkeys[i].keydata;
/*
* TODO(3.0) consider an evp_keymgmt_export() return value that
* indicates that the method is unsupported.
*/
if (exp_keymgmt->export == NULL)
continue;
/*
* The export function calls the callback (try_import), which
* does the import for us. If successful, we're done.
*/
if (evp_keymgmt_export(exp_keymgmt, exp_keydata,
OSSL_KEYMGMT_SELECT_ALL,
&try_import, &import_data))
break;
/* If there was an error, bail out */
evp_keymgmt_freedata(keymgmt, keydata);
return NULL;
}
}
@ -138,9 +130,9 @@ void *evp_keymgmt_util_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt,
if (!ossl_assert(i < OSSL_NELEM(pk->pkeys)))
return NULL;
evp_keymgmt_util_cache_pkey(pk, i, keymgmt, provdata, want_domainparams);
evp_keymgmt_util_cache_pkey(pk, i, keymgmt, keydata);
return provdata;
return keydata;
}
void evp_keymgmt_util_clear_pkey_cache(EVP_PKEY *pk)
@ -152,14 +144,11 @@ void evp_keymgmt_util_clear_pkey_cache(EVP_PKEY *pk)
i < OSSL_NELEM(pk->pkeys) && pk->pkeys[i].keymgmt != NULL;
i++) {
EVP_KEYMGMT *keymgmt = pk->pkeys[i].keymgmt;
void *provdata = pk->pkeys[i].provdata;
void *keydata = pk->pkeys[i].keydata;
pk->pkeys[i].keymgmt = NULL;
pk->pkeys[i].provdata = NULL;
if (pk->pkeys[i].domainparams)
evp_keymgmt_freedomparams(keymgmt, provdata);
else
evp_keymgmt_freekey(keymgmt, provdata);
pk->pkeys[i].keydata = NULL;
evp_keymgmt_freedata(keymgmt, keydata);
EVP_KEYMGMT_free(keymgmt);
}
@ -170,23 +159,20 @@ void evp_keymgmt_util_clear_pkey_cache(EVP_PKEY *pk)
}
void evp_keymgmt_util_cache_pkey(EVP_PKEY *pk, size_t index,
EVP_KEYMGMT *keymgmt, void *provdata,
int domainparams)
EVP_KEYMGMT *keymgmt, void *keydata)
{
if (provdata != NULL) {
if (keydata != NULL) {
EVP_KEYMGMT_up_ref(keymgmt);
pk->pkeys[index].keydata = keydata;
pk->pkeys[index].keymgmt = keymgmt;
pk->pkeys[index].provdata = provdata;
pk->pkeys[index].domainparams = domainparams;
/*
* Cache information about the domain parameters or key. Only needed
* for the "original" provider side key.
* Cache information about the key object. Only needed for the
* "original" provider side key.
*
* This services functions like EVP_PKEY_size, EVP_PKEY_bits, etc
*/
if (index == 0) {
int ok;
int bits = 0;
int security_bits = 0;
int size = 0;
@ -198,10 +184,7 @@ void evp_keymgmt_util_cache_pkey(EVP_PKEY *pk, size_t index,
params[2] = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_MAX_SIZE,
&size);
params[3] = OSSL_PARAM_construct_end();
ok = domainparams
? evp_keymgmt_get_domparam_params(keymgmt, provdata, params)
: evp_keymgmt_get_key_params(keymgmt, provdata, params);
if (ok) {
if (evp_keymgmt_get_params(keymgmt, keydata, params)) {
pk->cache.size = size;
pk->cache.bits = bits;
pk->cache.security_bits = security_bits;
@ -211,14 +194,20 @@ void evp_keymgmt_util_cache_pkey(EVP_PKEY *pk, size_t index,
}
void *evp_keymgmt_util_fromdata(EVP_PKEY *target, EVP_KEYMGMT *keymgmt,
const OSSL_PARAM params[], int domainparams)
int selection, const OSSL_PARAM params[])
{
void *provdata = domainparams
? evp_keymgmt_importdomparams(keymgmt, params)
: evp_keymgmt_importkey(keymgmt, params);
void *keydata = evp_keymgmt_newdata(keymgmt);
evp_keymgmt_util_clear_pkey_cache(target);
evp_keymgmt_util_cache_pkey(target, 0, keymgmt, provdata, domainparams);
if (keydata != NULL) {
if (!evp_keymgmt_import(keymgmt, keydata, selection, params)) {
evp_keymgmt_freedata(keymgmt, keydata);
return NULL;
}
evp_keymgmt_util_clear_pkey_cache(target);
evp_keymgmt_util_cache_pkey(target, 0, keymgmt, keydata);
}
return provdata;
return keydata;
}

@ -47,154 +47,71 @@ static void *keymgmt_from_dispatch(int name_id,
for (; fns->function_id != 0; fns++) {
switch (fns->function_id) {
case OSSL_FUNC_KEYMGMT_IMPORTDOMPARAMS:
if (keymgmt->importdomparams != NULL)
break;
keymgmt->importdomparams =
OSSL_get_OP_keymgmt_importdomparams(fns);
case OSSL_FUNC_KEYMGMT_NEW:
if (keymgmt->new == NULL)
keymgmt->new = OSSL_get_OP_keymgmt_new(fns);
break;
case OSSL_FUNC_KEYMGMT_GENDOMPARAMS:
if (keymgmt->gendomparams != NULL)
break;
keymgmt->gendomparams = OSSL_get_OP_keymgmt_gendomparams(fns);
case OSSL_FUNC_KEYMGMT_FREE:
if (keymgmt->free == NULL)
keymgmt->free = OSSL_get_OP_keymgmt_free(fns);
break;
case OSSL_FUNC_KEYMGMT_FREEDOMPARAMS:
if (keymgmt->freedomparams != NULL)
break;
keymgmt->freedomparams = OSSL_get_OP_keymgmt_freedomparams(fns);
case OSSL_FUNC_KEYMGMT_GET_PARAMS:
if (keymgmt->get_params == NULL)
keymgmt->get_params = OSSL_get_OP_keymgmt_get_params(fns);
break;
case OSSL_FUNC_KEYMGMT_EXPORTDOMPARAMS:
if (keymgmt->exportdomparams != NULL)
break;
keymgmt->exportdomparams =
OSSL_get_OP_keymgmt_exportdomparams(fns);
case OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS:
if (keymgmt->gettable_params == NULL)
keymgmt->gettable_params =
OSSL_get_OP_keymgmt_gettable_params(fns);
break;
case OSSL_FUNC_KEYMGMT_IMPORTDOMPARAM_TYPES:
if (keymgmt->importdomparam_types != NULL)
break;
keymgmt->importdomparam_types =
OSSL_get_OP_keymgmt_importdomparam_types(fns);
break;
case OSSL_FUNC_KEYMGMT_EXPORTDOMPARAM_TYPES:
if (keymgmt->exportdomparam_types != NULL)
break;
keymgmt->exportdomparam_types =
OSSL_get_OP_keymgmt_exportdomparam_types(fns);
break;
case OSSL_FUNC_KEYMGMT_GET_DOMPARAM_PARAMS:
if (keymgmt->get_domparam_params == NULL)
keymgmt->get_domparam_params =
OSSL_get_OP_keymgmt_get_domparam_params(fns);
break;
case OSSL_FUNC_KEYMGMT_GETTABLE_DOMPARAM_PARAMS:
if (keymgmt->gettable_domparam_params == NULL)
keymgmt->gettable_domparam_params =
OSSL_get_OP_keymgmt_gettable_domparam_params(fns);
break;
case OSSL_FUNC_KEYMGMT_IMPORTKEY:
if (keymgmt->importkey != NULL)
break;
keymgmt->importkey = OSSL_get_OP_keymgmt_importkey(fns);
break;
case OSSL_FUNC_KEYMGMT_GENKEY:
if (keymgmt->genkey != NULL)
break;
keymgmt->genkey = OSSL_get_OP_keymgmt_genkey(fns);
break;
case OSSL_FUNC_KEYMGMT_LOADKEY:
if (keymgmt->loadkey != NULL)
break;
keymgmt->loadkey = OSSL_get_OP_keymgmt_loadkey(fns);
break;
case OSSL_FUNC_KEYMGMT_FREEKEY:
if (keymgmt->freekey != NULL)
break;
keymgmt->freekey = OSSL_get_OP_keymgmt_freekey(fns);
break;
case OSSL_FUNC_KEYMGMT_EXPORTKEY:
if (keymgmt->exportkey != NULL)
break;
keymgmt->exportkey = OSSL_get_OP_keymgmt_exportkey(fns);
break;
case OSSL_FUNC_KEYMGMT_IMPORTKEY_TYPES:
if (keymgmt->importkey_types != NULL)
break;
keymgmt->importkey_types =
OSSL_get_OP_keymgmt_importkey_types(fns);
break;
case OSSL_FUNC_KEYMGMT_EXPORTKEY_TYPES:
if (keymgmt->exportkey_types != NULL)
break;
keymgmt->exportkey_types =
OSSL_get_OP_keymgmt_exportkey_types(fns);
break;
case OSSL_FUNC_KEYMGMT_GET_KEY_PARAMS:
if (keymgmt->get_key_params == NULL)
keymgmt->get_key_params =
OSSL_get_OP_keymgmt_get_key_params(fns);
case OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME:
if (keymgmt->query_operation_name == NULL)
keymgmt->query_operation_name =
OSSL_get_OP_keymgmt_query_operation_name(fns);
break;
case OSSL_FUNC_KEYMGMT_GETTABLE_KEY_PARAMS:
if (keymgmt->gettable_key_params == NULL)
keymgmt->gettable_key_params =
OSSL_get_OP_keymgmt_gettable_key_params(fns);
case OSSL_FUNC_KEYMGMT_HAS:
if (keymgmt->has == NULL)
keymgmt->has = OSSL_get_OP_keymgmt_has(fns);
break;
case OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME:
if (keymgmt->query_operation_name != NULL)
break;
keymgmt->query_operation_name =
OSSL_get_OP_keymgmt_query_operation_name(fns);
case OSSL_FUNC_KEYMGMT_VALIDATE:
if (keymgmt->validate == NULL)
keymgmt->validate = OSSL_get_OP_keymgmt_validate(fns);
break;
case OSSL_FUNC_KEYMGMT_VALIDATE_DOMPARAMS:
if (keymgmt->validatedomparams != NULL)
break;
keymgmt->validatedomparams =
OSSL_get_OP_keymgmt_validate_domparams(fns);
case OSSL_FUNC_KEYMGMT_IMPORT:
if (keymgmt->import == NULL)
keymgmt->import = OSSL_get_OP_keymgmt_import(fns);
break;
case OSSL_FUNC_KEYMGMT_VALIDATE_PUBLIC:
if (keymgmt->validatepublic != NULL)
break;
keymgmt->validatepublic =
OSSL_get_OP_keymgmt_validate_public(fns);
case OSSL_FUNC_KEYMGMT_IMPORT_TYPES:
if (keymgmt->import_types == NULL)
keymgmt->import_types = OSSL_get_OP_keymgmt_import_types(fns);
break;
case OSSL_FUNC_KEYMGMT_VALIDATE_PRIVATE:
if (keymgmt->validateprivate != NULL)
break;
keymgmt->validateprivate =
OSSL_get_OP_keymgmt_validate_private(fns);
case OSSL_FUNC_KEYMGMT_EXPORT:
if (keymgmt->export == NULL)
keymgmt->export = OSSL_get_OP_keymgmt_export(fns);
break;
case OSSL_FUNC_KEYMGMT_VALIDATE_PAIRWISE:
if (keymgmt->validatepairwise != NULL)
break;
keymgmt->validatepairwise =
OSSL_get_OP_keymgmt_validate_pairwise(fns);
case OSSL_FUNC_KEYMGMT_EXPORT_TYPES:
if (keymgmt->export_types == NULL)
keymgmt->export_types = OSSL_get_OP_keymgmt_export_types(fns);
break;
}
}
/*
* Try to check that the method is sensible.
* At least one constructor and the destructor are MANDATORY
* The functions 'has' is MANDATORY
* It makes no sense being able to free stuff if you can't create it.
* It makes no sense providing OSSL_PARAM descriptors for import and
* export if you can't import or export.
*/
if ((keymgmt->freedomparams != NULL
&& (keymgmt->importdomparams == NULL
&& keymgmt->gendomparams == NULL))
|| (keymgmt->freekey != NULL
&& (keymgmt->importkey == NULL
&& keymgmt->genkey == NULL
&& keymgmt->loadkey == NULL))
|| (keymgmt->importdomparam_types != NULL
&& keymgmt->importdomparams == NULL)
|| (keymgmt->exportdomparam_types != NULL
&& keymgmt->exportdomparams == NULL)
|| (keymgmt->gettable_domparam_params != NULL
&& keymgmt->get_domparam_params == NULL)
|| (keymgmt->importkey_types != NULL
&& keymgmt->importkey == NULL)
|| (keymgmt->exportkey_types != NULL
&& keymgmt->exportkey == NULL)
|| (keymgmt->gettable_key_params != NULL
&& keymgmt->get_key_params == NULL)) {
if (keymgmt->free == NULL
|| keymgmt->new == NULL
|| keymgmt->has == NULL
|| (keymgmt->gettable_params != NULL
&& keymgmt->get_params == NULL)
|| (keymgmt->import_types != NULL
&& keymgmt->import == NULL)
|| (keymgmt->export_types != NULL
&& keymgmt->export == NULL)) {
EVP_KEYMGMT_free(keymgmt);
EVPerr(0, EVP_R_INVALID_PROVIDER_FUNCTIONS);
return NULL;
@ -284,149 +201,84 @@ void EVP_KEYMGMT_names_do_all(const EVP_KEYMGMT *keymgmt,
/*
* Internal API that interfaces with the method function pointers
*/
void *evp_keymgmt_importdomparams(const EVP_KEYMGMT *keymgmt,
const OSSL_PARAM params[])
void *evp_keymgmt_newdata(const EVP_KEYMGMT *keymgmt)
{
void *provctx = ossl_provider_ctx(EVP_KEYMGMT_provider(keymgmt));
return keymgmt->importdomparams(provctx, params);
}
void *evp_keymgmt_gendomparams(const EVP_KEYMGMT *keymgmt,
const OSSL_PARAM params[])
{
void *provctx = ossl_provider_ctx(EVP_KEYMGMT_provider(keymgmt));
return keymgmt->gendomparams(provctx, params);
}
void evp_keymgmt_freedomparams(const EVP_KEYMGMT *keymgmt,
void *provdomparams)
{
keymgmt->freedomparams(provdomparams);
}
int evp_keymgmt_exportdomparams(const EVP_KEYMGMT *keymgmt,
void *provdomparams,
OSSL_CALLBACK *param_cb, void *cbarg)
{
return keymgmt->exportdomparams(provdomparams, param_cb, cbarg);
}
const OSSL_PARAM *evp_keymgmt_importdomparam_types(const EVP_KEYMGMT *keymgmt)
{
return keymgmt->importdomparam_types();
/*
* TODO(3.0) 'new' is currently mandatory on its own, but when new
* constructors appear, it won't be quite as mandatory, so we have
* a check for future cases.
*/
if (keymgmt->new == NULL)
return NULL;
return keymgmt->new(provctx);
}
/*
* TODO(v3.0) investigate if we need this function. 'openssl provider' may
* be a caller...
*/
const OSSL_PARAM *evp_keymgmt_exportdomparam_types(const EVP_KEYMGMT *keymgmt)
void evp_keymgmt_freedata(const EVP_KEYMGMT *keymgmt, void *keydata)
{
return keymgmt->exportdomparam_types();
/* This is mandatory, no need to check for its presence */
keymgmt->free(keydata);
}
int evp_keymgmt_get_domparam_params(const EVP_KEYMGMT *keymgmt,
void *provdomparams, OSSL_PARAM params[])
int evp_keymgmt_get_params(const EVP_KEYMGMT *keymgmt, void *keydata,
OSSL_PARAM params[])
{
if (keymgmt->get_domparam_params == NULL)
if (keymgmt->get_params == NULL)
return 1;
return keymgmt->get_domparam_params(provdomparams, params);
return keymgmt->get_params(keydata, params);
}
const OSSL_PARAM *
evp_keymgmt_gettable_domparam_params(const EVP_KEYMGMT *keymgmt)
const OSSL_PARAM *evp_keymgmt_gettable_params(const EVP_KEYMGMT *keymgmt)
{
if (keymgmt->gettable_domparam_params == NULL)
if (keymgmt->gettable_params == NULL)
return NULL;
return keymgmt->gettable_domparam_params();
}
void *evp_keymgmt_importkey(const EVP_KEYMGMT *keymgmt,
const OSSL_PARAM params[])
{
void *provctx = ossl_provider_ctx(EVP_KEYMGMT_provider(keymgmt));
return keymgmt->importkey(provctx, params);
return keymgmt->gettable_params();
}
void *evp_keymgmt_genkey(const EVP_KEYMGMT *keymgmt, void *domparams,
const OSSL_PARAM params[])
int evp_keymgmt_has(const EVP_KEYMGMT *keymgmt, void *keydata, int selection)
{
void *provctx = ossl_provider_ctx(EVP_KEYMGMT_provider(keymgmt));
return keymgmt->genkey(provctx, domparams, params);
/* This is mandatory, no need to check for its presence */
return keymgmt->has(keydata, selection);
}
void *evp_keymgmt_loadkey(const EVP_KEYMGMT *keymgmt,
void *id, size_t idlen)
int evp_keymgmt_validate(const EVP_KEYMGMT *keymgmt, void *keydata,
int selection)
{
void *provctx = ossl_provider_ctx(EVP_KEYMGMT_provider(keymgmt));
return keymgmt->loadkey(provctx, id, idlen);
}
void evp_keymgmt_freekey(const EVP_KEYMGMT *keymgmt, void *provkey)
{
keymgmt->freekey(provkey);
}
int evp_keymgmt_exportkey(const EVP_KEYMGMT *keymgmt, void *provkey,
OSSL_CALLBACK *param_cb, void *cbarg)
{
return keymgmt->exportkey(provkey, param_cb, cbarg);
}
const OSSL_PARAM *evp_keymgmt_importkey_types(const EVP_KEYMGMT *keymgmt)
{
return keymgmt->importkey_types();
}
/*
* TODO(v3.0) investigate if we need this function. 'openssl provider' may
* be a caller...
*/
const OSSL_PARAM *evp_keymgmt_exportkey_types(const EVP_KEYMGMT *keymgmt)
{
return keymgmt->exportkey_types();
}
int evp_keymgmt_get_key_params(const EVP_KEYMGMT *keymgmt,
void *provkey, OSSL_PARAM params[])
{
if (keymgmt->get_key_params == NULL)
/* We assume valid if the implementation doesn't have a function */
if (keymgmt->validate == NULL)
return 1;
return keymgmt->get_key_params(provkey, params);
}
const OSSL_PARAM *evp_keymgmt_gettable_key_params(const EVP_KEYMGMT *keymgmt)
{
if (keymgmt->gettable_key_params == NULL)
return NULL;
return keymgmt->gettable_key_params();
return keymgmt->validate(keydata, selection);
}
int evp_keymgmt_validate_domparams(const EVP_KEYMGMT *keymgmt, void *provkey)
int evp_keymgmt_import(const EVP_KEYMGMT *keymgmt, void *keydata,
int selection, const OSSL_PARAM params[])
{
/* if domainparams are not supported - then pass */
if (keymgmt->validatedomparams == NULL)
return 1;
return keymgmt->validatedomparams(provkey);
if (keymgmt->import == NULL)
return 0;
return keymgmt->import(keydata, selection, params);
}
int evp_keymgmt_validate_public(const EVP_KEYMGMT *keymgmt, void *provkey)
const OSSL_PARAM *evp_keymgmt_import_types(const EVP_KEYMGMT *keymgmt,
int selection)
{
return keymgmt->validatepublic(provkey);
if (keymgmt->import_types == NULL)
return NULL;
return keymgmt->import_types(selection);
}
int evp_keymgmt_validate_private(const EVP_KEYMGMT *keymgmt, void *provkey)
int evp_keymgmt_export(const EVP_KEYMGMT *keymgmt, void *keydata,
int selection, OSSL_CALLBACK *param_cb, void *cbarg)
{
return keymgmt->validateprivate(provkey);
if (keymgmt->export == NULL)
return 0;
return keymgmt->export(keydata, selection, param_cb, cbarg);
}
int evp_keymgmt_validate_pairwise(const EVP_KEYMGMT *keymgmt, void *provkey)
const OSSL_PARAM *evp_keymgmt_export_types(const EVP_KEYMGMT *keymgmt,
int selection)
{
return keymgmt->validatepairwise(provkey);
if (keymgmt->export_types == NULL)
return NULL;
return keymgmt->export_types(selection);
}

@ -67,7 +67,7 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
/* Ensure that the key is provided. If not, go legacy */
tmp_keymgmt = locpctx->keymgmt;
provkey = evp_pkey_make_provided(locpctx->pkey, locpctx->libctx,
&tmp_keymgmt, locpctx->propquery, 0);
&tmp_keymgmt, locpctx->propquery);
if (provkey == NULL)
goto legacy;
if (!EVP_KEYMGMT_up_ref(tmp_keymgmt)) {

@ -760,9 +760,9 @@ int EVP_PKEY_get_default_digest_name(EVP_PKEY *pkey,
mdmandatory,
sizeof(mdmandatory));
params[2] = OSSL_PARAM_construct_end();
if (!evp_keymgmt_get_key_params(pkey->pkeys[0].keymgmt,
pkey->pkeys[0].provdata,
params))
if (!evp_keymgmt_get_params(pkey->pkeys[0].keymgmt,
pkey->pkeys[0].keydata,
params))
return 0;
if (mdmandatory[0] != '\0') {
OPENSSL_strlcpy(mdname, mdmandatory, mdname_sz);
@ -910,12 +910,11 @@ int EVP_PKEY_size(const EVP_PKEY *pkey)
}
void *evp_pkey_make_provided(EVP_PKEY *pk, OPENSSL_CTX *libctx,
EVP_KEYMGMT **keymgmt, const char *propquery,
int domainparams)
EVP_KEYMGMT **keymgmt, const char *propquery)
{
EVP_KEYMGMT *allocated_keymgmt = NULL;
EVP_KEYMGMT *tmp_keymgmt = NULL;
void *provdata = NULL;
void *keydata = NULL;
if (pk == NULL)
return NULL;
@ -935,20 +934,20 @@ void *evp_pkey_make_provided(EVP_PKEY *pk, OPENSSL_CTX *libctx,
}
if (tmp_keymgmt != NULL)
provdata =
evp_keymgmt_util_export_to_provider(pk, tmp_keymgmt, domainparams);
keydata =
evp_keymgmt_util_export_to_provider(pk, tmp_keymgmt);
/*
* If nothing was exported, |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 (provdata == NULL)
if (keydata == NULL)
tmp_keymgmt = NULL;
if (keymgmt != NULL)
*keymgmt = tmp_keymgmt;
EVP_KEYMGMT_free(allocated_keymgmt);
return provdata;
return keydata;
}

@ -29,10 +29,11 @@ int EVP_PKEY_public_check(EVP_PKEY_CTX *ctx)
}
keymgmt = pkey->pkeys[0].keymgmt;
key = pkey->pkeys[0].provdata;
key = pkey->pkeys[0].keydata;
if (key != NULL && keymgmt != NULL)
return evp_keymgmt_validate_public(keymgmt, key);
return evp_keymgmt_validate(keymgmt, key,
OSSL_KEYMGMT_SELECT_PUBLIC_KEY);
/* legacy */
/* call customized public key check function first */
@ -61,10 +62,11 @@ int EVP_PKEY_param_check(EVP_PKEY_CTX *ctx)
}
keymgmt = pkey->pkeys[0].keymgmt;
key = pkey->pkeys[0].provdata;
key = pkey->pkeys[0].keydata;
if (key != NULL && keymgmt != NULL)
return evp_keymgmt_validate_domparams(keymgmt, key);
return evp_keymgmt_validate(keymgmt, key,
OSSL_KEYMGMT_SELECT_ALL_PARAMETERS);
/* call customized param check function first */
if (ctx->pmeth->param_check != NULL)
@ -93,10 +95,11 @@ int EVP_PKEY_private_check(EVP_PKEY_CTX *ctx)
}
keymgmt = pkey->pkeys[0].keymgmt;
key = pkey->pkeys[0].provdata;
key = pkey->pkeys[0].keydata;
if (key != NULL && keymgmt != NULL)
return evp_keymgmt_validate_private(keymgmt, key);
return evp_keymgmt_validate(keymgmt, key,
OSSL_KEYMGMT_SELECT_PRIVATE_KEY);
/* not supported for legacy keys */
return -2;
}
@ -113,10 +116,10 @@ int EVP_PKEY_pairwise_check(EVP_PKEY_CTX *ctx)
}
keymgmt = pkey->pkeys[0].keymgmt;
key = pkey->pkeys[0].provdata;
key = pkey->pkeys[0].keydata;
if (key != NULL && keymgmt != NULL)
return evp_keymgmt_validate_pairwise(keymgmt, key);
return evp_keymgmt_validate(keymgmt, key, OSSL_KEYMGMT_SELECT_KEYPAIR);
/* not supported for legacy keys */
return -2;
}
@ -133,14 +136,11 @@ int EVP_PKEY_check(EVP_PKEY_CTX *ctx)
}
keymgmt = pkey->pkeys[0].keymgmt;
key = pkey->pkeys[0].provdata;
key = pkey->pkeys[0].keydata;
if (key != NULL && keymgmt != NULL)
return evp_keymgmt_validate(keymgmt, key, OSSL_KEYMGMT_SELECT_ALL);
if (key != NULL && keymgmt != NULL) {
return evp_keymgmt_validate_domparams(keymgmt, key)
&& evp_keymgmt_validate_public(keymgmt, key)
&& evp_keymgmt_validate_private(keymgmt, key)
&& evp_keymgmt_validate_pairwise(keymgmt, key);
}
/* legacy */
/* call customized check function first */
if (ctx->pmeth->check != NULL)

@ -44,7 +44,7 @@ static int evp_pkey_asym_cipher_init(EVP_PKEY_CTX *ctx, int operation)
/* Ensure that the key is provided. If not, go legacy */
tmp_keymgmt = ctx->keymgmt;
provkey = evp_pkey_make_provided(ctx->pkey, ctx->libctx,
&tmp_keymgmt, ctx->propquery, 0);
&tmp_keymgmt, ctx->propquery);
if (provkey == NULL)
goto legacy;
if (!EVP_KEYMGMT_up_ref(tmp_keymgmt)) {

@ -208,7 +208,8 @@ int EVP_PKEY_key_fromdata_init(EVP_PKEY_CTX *ctx)
int EVP_PKEY_fromdata(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey, OSSL_PARAM params[])
{
void *provdata = NULL;
void *keydata = NULL;
int selection;
if (ctx == NULL || (ctx->operation & EVP_PKEY_OP_TYPE_FROMDATA) == 0) {
ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
@ -226,13 +227,16 @@ int EVP_PKEY_fromdata(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey, OSSL_PARAM params[])
return -1;
}
provdata =
evp_keymgmt_util_fromdata(*ppkey, ctx->keymgmt, params,
ctx->operation == EVP_PKEY_OP_PARAMFROMDATA);
if (ctx->operation == EVP_PKEY_OP_PARAMFROMDATA)
selection = OSSL_KEYMGMT_SELECT_ALL_PARAMETERS;
else
selection = OSSL_KEYMGMT_SELECT_KEYPAIR;
keydata = evp_keymgmt_util_fromdata(*ppkey, ctx->keymgmt, selection,
params);
if (provdata == NULL)
if (keydata == NULL)
return 0;
/* provdata is cached in *ppkey, so we need not bother with it further */
/* keydata is cached in *ppkey, so we need not bother with it further */
return 1;
}
@ -247,7 +251,8 @@ const OSSL_PARAM *EVP_PKEY_param_fromdata_settable(EVP_PKEY_CTX *ctx)
{
/* We call fromdata_init to get ctx->keymgmt populated */
if (fromdata_init(ctx, EVP_PKEY_OP_UNDEFINED))
return evp_keymgmt_importdomparam_types(ctx->keymgmt);
return evp_keymgmt_import_types(ctx->keymgmt,
OSSL_KEYMGMT_SELECT_ALL_PARAMETERS);
return NULL;
}
@ -255,6 +260,7 @@ const OSSL_PARAM *EVP_PKEY_key_fromdata_settable(EVP_PKEY_CTX *ctx)
{
/* We call fromdata_init to get ctx->keymgmt populated */
if (fromdata_init(ctx, EVP_PKEY_OP_UNDEFINED))
return evp_keymgmt_importdomparam_types(ctx->keymgmt);
return evp_keymgmt_import_types(ctx->keymgmt,
OSSL_KEYMGMT_SELECT_KEYPAIR);
return NULL;
}

@ -345,7 +345,7 @@ static int evp_pkey_signature_init(EVP_PKEY_CTX *ctx, int operation)
/* Ensure that the key is provided. If not, go legacy */
tmp_keymgmt = ctx->keymgmt;
provkey = evp_pkey_make_provided(ctx->pkey, ctx->libctx,
&tmp_keymgmt, ctx->propquery, 0);
&tmp_keymgmt, ctx->propquery);
if (provkey == NULL)
goto legacy;
if (!EVP_KEYMGMT_up_ref(tmp_keymgmt)) {

@ -1074,40 +1074,42 @@ static size_t rsa_pkey_dirty_cnt(const EVP_PKEY *pkey)
DEFINE_SPECIAL_STACK_OF_CONST(BIGNUM_const, BIGNUM)
static void *rsa_pkey_export_to(const EVP_PKEY *pk, EVP_KEYMGMT *keymgmt,
int want_domainparams)
static int rsa_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
EVP_KEYMGMT *to_keymgmt)
{
RSA *rsa = pk->pkey.rsa;
RSA *rsa = from->pkey.rsa;
OSSL_PARAM_BLD tmpl;
const BIGNUM *n = RSA_get0_n(rsa), *e = RSA_get0_e(rsa);
const BIGNUM *d = RSA_get0_d(rsa);
STACK_OF(BIGNUM_const) *primes = NULL, *exps = NULL, *coeffs = NULL;
int numprimes = 0, numexps = 0, numcoeffs = 0;
OSSL_PARAM *params = NULL;
void *provkey = NULL;
int rv = 0;
/*
* There are no domain parameters for RSA keys, or rather, they are
* included in the key data itself.
*/
if (want_domainparams)
/* Public parameters must always be present */
if (n == NULL || e == NULL)
goto err;
/* Get all the primes and CRT params */
if ((primes = sk_BIGNUM_const_new_null()) == NULL
|| (exps = sk_BIGNUM_const_new_null()) == NULL
|| (coeffs = sk_BIGNUM_const_new_null()) == NULL)
goto err;
ossl_param_bld_init(&tmpl);
if (!rsa_get0_all_params(rsa, primes, exps, coeffs))
/* |e| and |n| are always present */
if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_RSA_E, e))
goto err;
/* Public parameters must always be present */
if (n == NULL || e == NULL)
if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_RSA_N, n))
goto err;
if (d != NULL) {
/* It's a private key, so we should have everything else too */
int i;
/* Get all the primes and CRT params */
if ((primes = sk_BIGNUM_const_new_null()) == NULL
|| (exps = sk_BIGNUM_const_new_null()) == NULL
|| (coeffs = sk_BIGNUM_const_new_null()) == NULL)
goto err;
if (!rsa_get0_all_params(rsa, primes, exps, coeffs))
goto err;
numprimes = sk_BIGNUM_const_num(primes);
numexps = sk_BIGNUM_const_num(exps);
numcoeffs = sk_BIGNUM_const_num(coeffs);
@ -1120,15 +1122,6 @@ static void *rsa_pkey_export_to(const EVP_PKEY *pk, EVP_KEYMGMT *keymgmt,
+ numprimes + numexps + numcoeffs
<= OSSL_PARAM_BLD_MAX))
goto err;
}
ossl_param_bld_init(&tmpl);
if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_RSA_N, n)
|| !ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_RSA_E, e))
goto err;
if (d != NULL) {
int i;
if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_RSA_D, d))
goto err;
@ -1162,14 +1155,15 @@ static void *rsa_pkey_export_to(const EVP_PKEY *pk, EVP_KEYMGMT *keymgmt,
goto err;
/* We export, the provider imports */
provkey = evp_keymgmt_importkey(keymgmt, params);
rv = evp_keymgmt_import(to_keymgmt, to_keydata, OSSL_KEYMGMT_SELECT_ALL,
params);
err:
sk_BIGNUM_const_free(primes);
sk_BIGNUM_const_free(exps);
sk_BIGNUM_const_free(coeffs);
ossl_param_bld_free(params);
return provkey;
return rv;
}
const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[2] = {

@ -32,6 +32,8 @@ struct ossl_serializer_ctx_st {
OSSL_SERIALIZER *ser;
void *serctx;
int selection;
/*
* |object| is the libcrypto object to handle.
* |do_output| must have intimate knowledge of this object.

@ -96,13 +96,6 @@ struct selected_serializer_st {
const OSSL_PROVIDER *desired_provider;
const char *propquery;
/*
* When selecting serializers, we need to check the intended use.
* This is governed by the |domainparams| flag in the EVP_PKEY,
* we must just make sure to filter on 'type=domainparams' accordingly.
*/
int want_domainparams;
/*
* Serializers offer two functions, one that handles object data in
* the form of a OSSL_PARAM array, and one that directly handles a
@ -122,36 +115,12 @@ static void select_serializer(const char *name, void *data)
{
struct selected_serializer_st *d = data;
OSSL_SERIALIZER *s = NULL;
OSSL_PROPERTY_LIST *check =
d->want_domainparams
? ossl_parse_query(d->libctx, "type=domainparams")
: NULL;
/* No need to look further if we already have the more desirable option */
if (d->desired != NULL)
return;
if ((s = OSSL_SERIALIZER_fetch(d->libctx, name, d->propquery)) != NULL) {
/*
* Extra check if domain parameters are explicitly specified:
* only accept serializers that have the "type=domainparams"
* property.
*
* For data that isn't marked as domain parameters, a domain
* parameters serializer is still acceptable, because a key
* may hold domain parameters too.
*/
if (d->want_domainparams) {
OSSL_PROPERTY_LIST *current_props =
ossl_parse_property(d->libctx, OSSL_SERIALIZER_properties(s));
int check_cnt = ossl_property_match_count(check, current_props);
if (check_cnt == 0) {
OSSL_SERIALIZER_free(s);
return;
}
}
if (d->first == NULL && s->serialize_data != NULL) {
d->first = s;
} else if (OSSL_SERIALIZER_provider(s) == d->desired_provider
@ -298,8 +267,7 @@ static int serializer_write_cb(const OSSL_PARAM params[], void *arg)
static int serializer_EVP_PKEY_to_bio(OSSL_SERIALIZER_CTX *ctx, BIO *out)
{
const EVP_PKEY *pkey = ctx->object;
void *provdata = pkey->pkeys[0].provdata;
int domainparams = pkey->pkeys[0].domainparams;
void *keydata = pkey->pkeys[0].keydata;
EVP_KEYMGMT *keymgmt = pkey->pkeys[0].keymgmt;
/*
@ -319,15 +287,11 @@ static int serializer_EVP_PKEY_to_bio(OSSL_SERIALIZER_CTX *ctx, BIO *out)
write_data.ctx = ctx;
write_data.out = out;
if (domainparams)
return evp_keymgmt_exportdomparams(keymgmt, provdata,
serializer_write_cb,
&write_data);
return evp_keymgmt_exportkey(keymgmt, provdata,
serializer_write_cb, &write_data);
return evp_keymgmt_export(keymgmt, keydata, ctx->selection,
&serializer_write_cb, &write_data);
}
return ctx->ser->serialize_object(ctx->serctx, provdata, out,
return ctx->ser->serialize_object(ctx->serctx, keydata, out,
serializer_passphrase_out_cb, ctx);
}
@ -343,6 +307,7 @@ OSSL_SERIALIZER_CTX *OSSL_SERIALIZER_CTX_new_by_EVP_PKEY(const EVP_PKEY *pkey,
OSSL_SERIALIZER_CTX *ctx = NULL;
OSSL_SERIALIZER *ser = NULL;
EVP_KEYMGMT *keymgmt = pkey->pkeys[0].keymgmt;
int selection = OSSL_KEYMGMT_SELECT_ALL;
if (!ossl_assert(pkey != NULL && propquery != NULL)) {
ERR_raise(ERR_LIB_OSSL_SERIALIZER, ERR_R_PASSED_NULL_PARAMETER);
@ -353,12 +318,14 @@ OSSL_SERIALIZER_CTX *OSSL_SERIALIZER_CTX_new_by_EVP_PKEY(const EVP_PKEY *pkey,
const OSSL_PROVIDER *desired_prov = EVP_KEYMGMT_provider(keymgmt);
OPENSSL_CTX *libctx = ossl_provider_library_context(desired_prov);
struct selected_serializer_st sel_data;
OSSL_PROPERTY_LIST *check =
ossl_parse_query(libctx, "type=parameters");