}
return ret;
}
- if (a->pkeys[0].keymgmt != NULL) {
+ if (a->keymgmt != NULL) {
const char *serprop = OSSL_SERIALIZER_PrivateKey_TO_DER_PQ;
OSSL_SERIALIZER_CTX *ctx =
OSSL_SERIALIZER_CTX_new_by_EVP_PKEY(a, serprop);
if (ctx->engine != NULL || ctx->keytype == NULL)
goto legacy;
- /* Ensure that the key is provided. If not, go legacy */
+ /*
+ * Ensure that the key is provided, either natively, or as a cached export.
+ * If not, go legacy
+ */
tmp_keymgmt = ctx->keymgmt;
- provkey = evp_pkey_make_provided(ctx->pkey, ctx->libctx,
- &tmp_keymgmt, ctx->propquery);
+ provkey = evp_pkey_export_to_provider(ctx->pkey, ctx->libctx,
+ &tmp_keymgmt, ctx->propquery);
if (provkey == NULL)
goto legacy;
if (!EVP_KEYMGMT_up_ref(tmp_keymgmt)) {
return -2;
}
- provkey = evp_pkey_make_provided(peer, ctx->libctx, &ctx->keymgmt,
- ctx->propquery);
+ provkey = evp_pkey_export_to_provider(peer, ctx->libctx, &ctx->keymgmt,
+ ctx->propquery);
/*
* If making the key provided wasn't possible, legacy may be able to pick
* it up
{
void *keydata = NULL;
struct import_data_st import_data;
- size_t i, j;
+ size_t i = 0;
/* Export to where? */
if (keymgmt == NULL)
return NULL;
/* If we have an unassigned key, give up */
- if (pk->pkeys[0].keymgmt == NULL)
+ if (pk->keymgmt == NULL)
return NULL;
+ /* If |keymgmt| matches the "origin" |keymgmt|, no more to do */
+ if (pk->keymgmt == keymgmt)
+ return pk->keydata;
+
+ /* If this key is already exported to |keymgmt|, no more to do */
+ i = evp_keymgmt_util_find_operation_cache_index(pk, keymgmt);
+ if (i < OSSL_NELEM(pk->operation_cache)
+ && pk->operation_cache[i].keymgmt != NULL)
+ return pk->operation_cache[i].keydata;
+
+ /* If the "origin" |keymgmt| doesn't support exporting, give up */
/*
- * See if we have exported to this provider already.
- * If we have, return immediately.
+ * TODO(3.0) consider an evp_keymgmt_export() return value that indicates
+ * that the method is unsupported.
*/
- i = evp_keymgmt_util_find_pkey_cache_index(pk, keymgmt);
+ if (pk->keymgmt->export == NULL)
+ return NULL;
- /* If we're already exported to the given keymgmt, no more to do */
- if (keymgmt == pk->pkeys[i].keymgmt)
- return pk->pkeys[i].keydata;
+ /* Check that we have found an empty slot in the export cache */
+ /*
+ * TODO(3.0) Right now, we assume we have ample space. We will have to
+ * think about a cache aging scheme, though, if |i| indexes outside the
+ * array.
+ */
+ if (!ossl_assert(i < OSSL_NELEM(pk->operation_cache)))
+ return NULL;
/*
* Make sure that the type of the keymgmt to export to matches the type
- * of already cached keymgmt
+ * of the "origin"
*/
- if (!ossl_assert(match_type(pk->pkeys[0].keymgmt, keymgmt)))
+ if (!ossl_assert(match_type(pk->keymgmt, keymgmt)))
return NULL;
/* Create space to import data into */
import_data.keymgmt = keymgmt;
import_data.selection = OSSL_KEYMGMT_SELECT_ALL;
- for (j = 0; j < i && pk->pkeys[j].keymgmt != NULL; j++) {
- EVP_KEYMGMT *exp_keymgmt = pk->pkeys[j].keymgmt;
- void *exp_keydata = pk->pkeys[j].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;
-
+ /*
+ * The export function calls the callback (try_import), which does the
+ * import for us. If successful, we're done.
+ */
+ if (!evp_keymgmt_export(pk->keymgmt, pk->keydata, OSSL_KEYMGMT_SELECT_ALL,
+ &try_import, &import_data)) {
/* If there was an error, bail out */
evp_keymgmt_freedata(keymgmt, keydata);
return NULL;
}
- /*
- * TODO(3.0) Right now, we assume we have ample space. We will
- * have to think about a cache aging scheme, though, if |i| indexes
- * outside the array.
- */
- if (!ossl_assert(i < OSSL_NELEM(pk->pkeys)))
+ /* Add the new export to the operation cache */
+ if (!evp_keymgmt_util_cache_keydata(pk, i, keymgmt, keydata)) {
+ evp_keymgmt_freedata(keymgmt, keydata);
return NULL;
-
- evp_keymgmt_util_cache_pkey(pk, i, keymgmt, keydata);
+ }
return keydata;
}
-void evp_keymgmt_util_clear_pkey_cache(EVP_PKEY *pk)
+void evp_keymgmt_util_clear_operation_cache(EVP_PKEY *pk)
{
- size_t i, end = OSSL_NELEM(pk->pkeys);
+ size_t i, end = OSSL_NELEM(pk->operation_cache);
if (pk != NULL) {
- for (i = 0; i < end && pk->pkeys[i].keymgmt != NULL; i++) {
- EVP_KEYMGMT *keymgmt = pk->pkeys[i].keymgmt;
- void *keydata = pk->pkeys[i].keydata;
+ for (i = 0; i < end && pk->operation_cache[i].keymgmt != NULL; i++) {
+ EVP_KEYMGMT *keymgmt = pk->operation_cache[i].keymgmt;
+ void *keydata = pk->operation_cache[i].keydata;
- pk->pkeys[i].keymgmt = NULL;
- pk->pkeys[i].keydata = NULL;
+ pk->operation_cache[i].keymgmt = NULL;
+ pk->operation_cache[i].keydata = NULL;
evp_keymgmt_freedata(keymgmt, keydata);
EVP_KEYMGMT_free(keymgmt);
}
-
- pk->cache.size = 0;
- pk->cache.bits = 0;
- pk->cache.security_bits = 0;
}
}
-size_t evp_keymgmt_util_find_pkey_cache_index(EVP_PKEY *pk,
- EVP_KEYMGMT *keymgmt)
+size_t evp_keymgmt_util_find_operation_cache_index(EVP_PKEY *pk,
+ EVP_KEYMGMT *keymgmt)
{
- size_t i, end = OSSL_NELEM(pk->pkeys);
+ size_t i, end = OSSL_NELEM(pk->operation_cache);
- for (i = 0; i < end && pk->pkeys[i].keymgmt != NULL; i++) {
- if (keymgmt == pk->pkeys[i].keymgmt)
+ for (i = 0; i < end && pk->operation_cache[i].keymgmt != NULL; i++) {
+ if (keymgmt == pk->operation_cache[i].keymgmt)
break;
}
return i;
}
-void evp_keymgmt_util_cache_pkey(EVP_PKEY *pk, size_t index,
- EVP_KEYMGMT *keymgmt, void *keydata)
+int evp_keymgmt_util_cache_keydata(EVP_PKEY *pk, size_t index,
+ EVP_KEYMGMT *keymgmt, void *keydata)
{
if (keydata != NULL) {
- EVP_KEYMGMT_up_ref(keymgmt);
- pk->pkeys[index].keydata = keydata;
- pk->pkeys[index].keymgmt = keymgmt;
-
- /*
- * 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 bits = 0;
- int security_bits = 0;
- int size = 0;
- OSSL_PARAM params[4];
-
- params[0] = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_BITS, &bits);
- params[1] = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_SECURITY_BITS,
- &security_bits);
- params[2] = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_MAX_SIZE,
- &size);
- params[3] = OSSL_PARAM_construct_end();
- if (evp_keymgmt_get_params(keymgmt, keydata, params)) {
- pk->cache.size = size;
- pk->cache.bits = bits;
- pk->cache.security_bits = security_bits;
- }
+ if (!EVP_KEYMGMT_up_ref(keymgmt))
+ return 0;
+ pk->operation_cache[index].keydata = keydata;
+ pk->operation_cache[index].keymgmt = keymgmt;
+ }
+ return 1;
+}
+
+void evp_keymgmt_util_cache_keyinfo(EVP_PKEY *pk)
+{
+ /*
+ * Cache information about the provider "origin" key.
+ *
+ * This services functions like EVP_PKEY_size, EVP_PKEY_bits, etc
+ */
+ if (pk->keymgmt != NULL) {
+ int bits = 0;
+ int security_bits = 0;
+ int size = 0;
+ OSSL_PARAM params[4];
+
+ params[0] = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_BITS, &bits);
+ params[1] = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_SECURITY_BITS,
+ &security_bits);
+ params[2] = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_MAX_SIZE, &size);
+ params[3] = OSSL_PARAM_construct_end();
+ if (evp_keymgmt_get_params(pk->keymgmt, pk->keydata, params)) {
+ pk->cache.size = size;
+ pk->cache.bits = bits;
+ pk->cache.security_bits = security_bits;
}
}
}
void *keydata = evp_keymgmt_newdata(keymgmt);
if (keydata != NULL) {
- if (!evp_keymgmt_import(keymgmt, keydata, selection, params)) {
+ if (!evp_keymgmt_import(keymgmt, keydata, selection, params)
+ || !EVP_KEYMGMT_up_ref(keymgmt)) {
evp_keymgmt_freedata(keymgmt, keydata);
return NULL;
}
-
- evp_keymgmt_util_clear_pkey_cache(target);
- evp_keymgmt_util_cache_pkey(target, 0, keymgmt, keydata);
+ evp_keymgmt_util_clear_operation_cache(target);
+ target->keymgmt = keymgmt;
+ target->keydata = keydata;
+ evp_keymgmt_util_cache_keyinfo(target);
}
return keydata;
if (locpctx->keytype == NULL)
goto legacy;
- /* Ensure that the key is provided. If not, go legacy */
+ /*
+ * Ensure that the key is provided, either natively, or as a cached export.
+ * If not, go legacy
+ */
tmp_keymgmt = locpctx->keymgmt;
- provkey = evp_pkey_make_provided(locpctx->pkey, locpctx->libctx,
- &tmp_keymgmt, locpctx->propquery);
+ provkey = evp_pkey_export_to_provider(locpctx->pkey, locpctx->libctx,
+ &tmp_keymgmt, locpctx->propquery);
if (provkey == NULL)
goto legacy;
if (!EVP_KEYMGMT_up_ref(tmp_keymgmt)) {
static int legacy_asn1_ctrl_to_param(EVP_PKEY *pkey, int op,
int arg1, void *arg2)
{
- if (pkey->pkeys[0].keymgmt == NULL)
+ if (pkey->keymgmt == NULL)
return 0;
switch (op) {
case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
mdmandatory,
sizeof(mdmandatory));
params[2] = OSSL_PARAM_construct_end();
- if (!evp_keymgmt_get_params(pkey->pkeys[0].keymgmt,
- pkey->pkeys[0].keydata,
- params))
+ if (!evp_keymgmt_get_params(pkey->keymgmt, pkey->keydata, params))
return 0;
if (mdmandatory[0] != '\0') {
OPENSSL_strlcpy(mdname, mdmandatory, mdname_sz);
{
/* internal function; x is never NULL */
- evp_keymgmt_util_clear_pkey_cache(x);
+ evp_keymgmt_util_clear_operation_cache(x);
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;
return 0;
}
-void *evp_pkey_make_provided(EVP_PKEY *pk, OPENSSL_CTX *libctx,
- EVP_KEYMGMT **keymgmt, const char *propquery)
+void *evp_pkey_export_to_provider(EVP_PKEY *pk, OPENSSL_CTX *libctx,
+ EVP_KEYMGMT **keymgmt,
+ const char *propquery)
{
EVP_KEYMGMT *allocated_keymgmt = NULL;
EVP_KEYMGMT *tmp_keymgmt = NULL;
if (pk == NULL)
return NULL;
- if (keymgmt != NULL) {
- tmp_keymgmt = *keymgmt;
- *keymgmt = NULL;
- }
-
#ifndef FIPS_MODE
- /*
- * If there is an underlying legacy key and it has changed, invalidate
- * the cache of provider keys.
- */
if (pk->pkey.ptr != NULL) {
- EVP_KEYMGMT *legacy_keymgmt = NULL;
-
- /*
- * If there is no dirty counter, this key can't be used with
- * providers.
- */
- if (pk->ameth->dirty_cnt == NULL)
- goto end;
-
- /*
- * If no keymgmt was given by the caller, we set it to the first
- * that's cached, to become the keymgmt to re-export to if needed,
- * or to have a token keymgmt to return on success. Further checks
- * are done further down.
- *
- * We need to carefully save the pointer somewhere other than in
- * tmp_keymgmt, so the EVP_KEYMGMT_up_ref() below doesn't mistakenly
- * increment the reference counter of a keymgmt given by the caller.
- */
- if (tmp_keymgmt == NULL)
- legacy_keymgmt = pk->pkeys[0].keymgmt;
-
- /*
- * If the dirty counter changed since last time, we make sure to
- * hold on to the keymgmt we just got (if we got one), then clear
- * the cache.
- */
- if (pk->ameth->dirty_cnt(pk) != pk->dirty_cnt_copy) {
- if (legacy_keymgmt != NULL && !EVP_KEYMGMT_up_ref(legacy_keymgmt))
- goto end;
- evp_keymgmt_util_clear_pkey_cache(pk);
- }
-
/*
- * |legacy_keymgmt| was only given a value if |tmp_keymgmt| is
- * NULL.
+ * If the legacy key doesn't have an dirty counter or export function,
+ * give up
*/
- if (legacy_keymgmt != NULL)
- tmp_keymgmt = legacy_keymgmt;
+ if (pk->ameth->dirty_cnt == NULL || pk->ameth->export_to == NULL)
+ return NULL;
}
#endif
+ if (keymgmt != NULL) {
+ tmp_keymgmt = *keymgmt;
+ *keymgmt = NULL;
+ }
+
/* If no keymgmt was given or found, get a default keymgmt */
if (tmp_keymgmt == NULL) {
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pk, propquery);
EVP_PKEY_CTX_free(ctx);
}
+ /* If there's still no keymgmt to be had, give up */
if (tmp_keymgmt == NULL)
goto end;
#ifndef FIPS_MODE
if (pk->pkey.ptr != NULL) {
- size_t i;
+ size_t i = 0;
/*
- * Find our keymgmt in the cache. If it's present, it means that
- * export has already been done. We take token copies of the
- * cached pointers, to have token success values to return.
- *
- * TODO(3.0) Right now, we assume we have ample space. We will
- * have to think about a cache aging scheme, though, if |i| indexes
- * outside the array.
+ * If the legacy "origin" hasn't changed since last time, we try
+ * to find our keymgmt in the operation cache. If it has changed,
+ * |i| remains zero, and we will clear the cache further down.
*/
- i = evp_keymgmt_util_find_pkey_cache_index(pk, tmp_keymgmt);
- if (!ossl_assert(i < OSSL_NELEM(pk->pkeys)))
- goto end;
- if (pk->pkeys[i].keymgmt != NULL) {
- keydata = pk->pkeys[i].keydata;
- goto end;
+ if (pk->ameth->dirty_cnt(pk) == pk->dirty_cnt_copy) {
+ i = evp_keymgmt_util_find_operation_cache_index(pk, tmp_keymgmt);
+
+ /*
+ * If |tmp_keymgmt| is present in the operation cache, it means
+ * that export doesn't need to be redone. In that case, we take
+ * token copies of the cached pointers, to have token success
+ * values to return.
+ */
+ if (i < OSSL_NELEM(pk->operation_cache)
+ && pk->operation_cache[i].keymgmt != NULL) {
+ keydata = pk->operation_cache[i].keydata;
+ goto end;
+ }
}
/*
- * If we still don't have a keymgmt at this point, or the legacy
- * key doesn't have an export function, just bail out.
+ * TODO(3.0) Right now, we assume we have ample space. We will have
+ * to think about a cache aging scheme, though, if |i| indexes outside
+ * the array.
*/
- if (pk->ameth->export_to == NULL)
+ if (!ossl_assert(i < OSSL_NELEM(pk->operation_cache)))
goto end;
/* Make sure that the keymgmt key type matches the legacy NID */
goto end;
}
- evp_keymgmt_util_cache_pkey(pk, i, tmp_keymgmt, keydata);
+ /*
+ * If the dirty counter changed since last time, then clear the
+ * operation cache. In that case, we know that |i| is zero. Just
+ * in case this is a re-export, we increment then decrement the
+ * keymgmt reference counter.
+ */
+ if (!EVP_KEYMGMT_up_ref(tmp_keymgmt)) { /* refcnt++ */
+ evp_keymgmt_freedata(tmp_keymgmt, keydata);
+ keydata = NULL;
+ goto end;
+ }
+ if (pk->ameth->dirty_cnt(pk) != pk->dirty_cnt_copy)
+ evp_keymgmt_util_clear_operation_cache(pk);
+ EVP_KEYMGMT_free(tmp_keymgmt); /* refcnt-- */
+
+ /* Add the new export to the operation cache */
+ if (!evp_keymgmt_util_cache_keydata(pk, i, tmp_keymgmt, keydata)) {
+ evp_keymgmt_freedata(tmp_keymgmt, keydata);
+ keydata = NULL;
+ goto end;
+ }
/* Synchronize the dirty count */
pk->dirty_cnt_copy = pk->ameth->dirty_cnt(pk);
return 0;
}
- keymgmt = pkey->pkeys[0].keymgmt;
- key = pkey->pkeys[0].keydata;
+ keymgmt = pkey->keymgmt;
+ key = pkey->keydata;
if (key != NULL && keymgmt != NULL)
return evp_keymgmt_validate(keymgmt, key,
return 0;
}
- keymgmt = pkey->pkeys[0].keymgmt;
- key = pkey->pkeys[0].keydata;
+ keymgmt = pkey->keymgmt;
+ key = pkey->keydata;
if (key != NULL && keymgmt != NULL)
return evp_keymgmt_validate(keymgmt, key,
return 0;
}
- keymgmt = pkey->pkeys[0].keymgmt;
- key = pkey->pkeys[0].keydata;
+ keymgmt = pkey->keymgmt;
+ key = pkey->keydata;
if (key != NULL && keymgmt != NULL)
return evp_keymgmt_validate(keymgmt, key,
return 0;
}
- keymgmt = pkey->pkeys[0].keymgmt;
- key = pkey->pkeys[0].keydata;
+ keymgmt = pkey->keymgmt;
+ key = pkey->keydata;
if (key != NULL && keymgmt != NULL)
return evp_keymgmt_validate(keymgmt, key, OSSL_KEYMGMT_SELECT_KEYPAIR);
return 0;
}
- keymgmt = pkey->pkeys[0].keymgmt;
- key = pkey->pkeys[0].keydata;
+ keymgmt = pkey->keymgmt;
+ key = pkey->keydata;
if (key != NULL && keymgmt != NULL)
return evp_keymgmt_validate(keymgmt, key, OSSL_KEYMGMT_SELECT_ALL);
if (ctx->keytype == NULL || ctx->engine != NULL)
goto legacy;
- /* Ensure that the key is provided. If not, go legacy */
+ /*
+ * Ensure that the key is provided, either natively, or as a cached export.
+ * If not, go legacy
+ */
tmp_keymgmt = ctx->keymgmt;
- provkey = evp_pkey_make_provided(ctx->pkey, ctx->libctx,
- &tmp_keymgmt, ctx->propquery);
+ provkey = evp_pkey_export_to_provider(ctx->pkey, ctx->libctx,
+ &tmp_keymgmt, ctx->propquery);
if (provkey == NULL)
goto legacy;
if (!EVP_KEYMGMT_up_ref(tmp_keymgmt)) {
/* If we have an engine, something went wrong somewhere... */
if (!ossl_assert(e == NULL))
return NULL;
- name = evp_first_name(pkey->pkeys[0].keymgmt->prov,
- pkey->pkeys[0].keymgmt->name_id);
+ name = evp_first_name(pkey->keymgmt->prov, pkey->keymgmt->name_id);
/*
* TODO: I wonder if the EVP_PKEY should have the name and propquery
* that were used when building it.... /RL
if (ctx->keytype == NULL)
goto legacy;
- /* Ensure that the key is provided. If not, go legacy */
+ /*
+ * Ensure that the key is provided, either natively, or as a cached export.
+ * If not, go legacy
+ */
tmp_keymgmt = ctx->keymgmt;
- provkey = evp_pkey_make_provided(ctx->pkey, ctx->libctx,
- &tmp_keymgmt, ctx->propquery);
+ provkey = evp_pkey_export_to_provider(ctx->pkey, ctx->libctx,
+ &tmp_keymgmt, ctx->propquery);
if (provkey == NULL)
goto legacy;
if (!EVP_KEYMGMT_up_ref(tmp_keymgmt)) {
static int serializer_EVP_PKEY_to_bio(OSSL_SERIALIZER_CTX *ctx, BIO *out)
{
const EVP_PKEY *pkey = ctx->object;
- void *keydata = pkey->pkeys[0].keydata;
- EVP_KEYMGMT *keymgmt = pkey->pkeys[0].keymgmt;
+ void *keydata = pkey->keydata;
+ EVP_KEYMGMT *keymgmt = pkey->keymgmt;
/*
* OSSL_SERIALIZER_CTX_new() creates a context, even when the
{
OSSL_SERIALIZER_CTX *ctx = NULL;
OSSL_SERIALIZER *ser = NULL;
- EVP_KEYMGMT *keymgmt = pkey->pkeys[0].keymgmt;
+ EVP_KEYMGMT *keymgmt = pkey->keymgmt;
int selection = OSSL_KEYMGMT_SELECT_ALL;
if (!ossl_assert(pkey != NULL && propquery != NULL)) {
X509err(X509_F_X509_PUBKEY_SET, X509_R_METHOD_NOT_SUPPORTED);
goto error;
}
- } else if (pkey->pkeys[0].keymgmt != NULL) {
+ } else if (pkey->keymgmt != NULL) {
BIO *bmem = BIO_new(BIO_s_mem());
const char *serprop = OSSL_SERIALIZER_PUBKEY_TO_DER_PQ;
OSSL_SERIALIZER_CTX *sctx =
xpk->pkey = NULL;
}
X509_PUBKEY_free(xpk);
- } else if (a->pkeys[0].keymgmt != NULL) {
+ } else if (a->keymgmt != NULL) {
const char *serprop = OSSL_SERIALIZER_PUBKEY_TO_DER_PQ;
OSSL_SERIALIZER_CTX *ctx =
OSSL_SERIALIZER_CTX_new_by_EVP_PKEY(a, serprop);
/* == Legacy attributes == */
int type;
int save_type;
+
+ /*
+ * Legacy key "origin" is composed of a pointer to an EVP_PKEY_ASN1_METHOD,
+ * a pointer to a low level key and possibly a pointer to an engine.
+ */
const EVP_PKEY_ASN1_METHOD *ameth;
ENGINE *engine;
ENGINE *pmeth_engine; /* If not NULL public key ENGINE to use */
int save_parameters;
/* == Provider attributes == */
+
+ /*
+ * Provider keydata "origin" is composed of a pointer to an EVP_KEYMGMT
+ * and a pointer to the provider side key data. This is never used at
+ * the same time as the legacy key data above.
+ */
+ EVP_KEYMGMT *keymgmt;
+ void *keydata;
+ /*
+ * If any libcrypto code does anything that may modify the keydata
+ * contents, this dirty counter must be incremented.
+ */
+ size_t dirty_cnt;
+
/*
- * To support transparent export/import between providers that support
- * the methods for it, and still not having to do the export/import
- * every time a key object is changed, we maintain a cache of imported
- * key objects, indexed by keymgmt address. pkeys[0] is *always* the
- * "original" data unless we have a legacy key attached.
+ * To support transparent execution of operation in backends other
+ * than the "origin" key, we support transparent export/import to
+ * those providers, and maintain a cache of the imported keydata,
+ * so we don't need to redo the export/import every time we perform
+ * the same operation in that same provider.
+ * This requires that the "origin" backend (whether it's a legacy or a
+ * provider "origin") implements exports, and that the target provider
+ * has an EVP_KEYMGMT that implements import.
+ *
+ * The cache limit is set at 10 different providers using the same
+ * "origin". It's probably over the top, but is preferable to too
+ * few.
*/
struct {
EVP_KEYMGMT *keymgmt;
void *keydata;
- } pkeys[10];
+ } operation_cache[10];
/*
- * If there is a legacy key assigned to this structure, we keep
- * a copy of that key's dirty count.
+ * We keep a copy of that "origin"'s dirty count, so we know if the
+ * operation cache needs flushing.
*/
size_t dirty_cnt_copy;
void openssl_add_all_digests_int(void);
void evp_cleanup_int(void);
void evp_app_cleanup_int(void);
-void *evp_pkey_make_provided(EVP_PKEY *pk, OPENSSL_CTX *libctx,
- EVP_KEYMGMT **keymgmt, const char *propquery);
+void *evp_pkey_export_to_provider(EVP_PKEY *pk, OPENSSL_CTX *libctx,
+ EVP_KEYMGMT **keymgmt,
+ const char *propquery);
/*
* KEYMGMT utility functions
*/
void *evp_keymgmt_util_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt);
-size_t evp_keymgmt_util_find_pkey_cache_index(EVP_PKEY *pk,
- EVP_KEYMGMT *keymgmt);
-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 *keydata);
+size_t evp_keymgmt_util_find_operation_cache_index(EVP_PKEY *pk,
+ EVP_KEYMGMT *keymgmt);
+void evp_keymgmt_util_clear_operation_cache(EVP_PKEY *pk);
+int evp_keymgmt_util_cache_keydata(EVP_PKEY *pk, size_t index,
+ EVP_KEYMGMT *keymgmt, void *keydata);
+void evp_keymgmt_util_cache_keyinfo(EVP_PKEY *pk);
void *evp_keymgmt_util_fromdata(EVP_PKEY *target, EVP_KEYMGMT *keymgmt,
int selection, const OSSL_PARAM params[]);