Latest update.
This commit is contained in:
@@ -534,17 +534,12 @@ static long b64_ctrl(BIO *b, int cmd, long num, void *ptr)
|
||||
|
||||
static long b64_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
|
||||
{
|
||||
long ret = 1;
|
||||
BIO *next = BIO_next(b);
|
||||
|
||||
if (next == NULL)
|
||||
return 0;
|
||||
switch (cmd) {
|
||||
default:
|
||||
ret = BIO_callback_ctrl(next, cmd, fp);
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
|
||||
return BIO_callback_ctrl(next, cmd, fp);
|
||||
}
|
||||
|
||||
static int b64_puts(BIO *b, const char *str)
|
||||
|
||||
@@ -388,17 +388,12 @@ static long enc_ctrl(BIO *b, int cmd, long num, void *ptr)
|
||||
|
||||
static long enc_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
|
||||
{
|
||||
long ret = 1;
|
||||
BIO *next = BIO_next(b);
|
||||
|
||||
if (next == NULL)
|
||||
return 0;
|
||||
switch (cmd) {
|
||||
default:
|
||||
ret = BIO_callback_ctrl(next, cmd, fp);
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
|
||||
return BIO_callback_ctrl(next, cmd, fp);
|
||||
}
|
||||
|
||||
int BIO_set_cipher(BIO *b, const EVP_CIPHER *c, const unsigned char *k,
|
||||
|
||||
+1
-7
@@ -197,7 +197,6 @@ static long md_ctrl(BIO *b, int cmd, long num, void *ptr)
|
||||
|
||||
static long md_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
|
||||
{
|
||||
long ret = 1;
|
||||
BIO *next;
|
||||
|
||||
next = BIO_next(b);
|
||||
@@ -205,12 +204,7 @@ static long md_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
|
||||
if (next == NULL)
|
||||
return 0;
|
||||
|
||||
switch (cmd) {
|
||||
default:
|
||||
ret = BIO_callback_ctrl(next, cmd, fp);
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
return BIO_callback_ctrl(next, cmd, fp);
|
||||
}
|
||||
|
||||
static int md_gets(BIO *bp, char *buf, int size)
|
||||
|
||||
+1
-8
@@ -406,7 +406,6 @@ static long ok_ctrl(BIO *b, int cmd, long num, void *ptr)
|
||||
|
||||
static long ok_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
|
||||
{
|
||||
long ret = 1;
|
||||
BIO *next;
|
||||
|
||||
next = BIO_next(b);
|
||||
@@ -414,13 +413,7 @@ static long ok_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
|
||||
if (next == NULL)
|
||||
return 0;
|
||||
|
||||
switch (cmd) {
|
||||
default:
|
||||
ret = BIO_callback_ctrl(next, cmd, fp);
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return BIO_callback_ctrl(next, cmd, fp);
|
||||
}
|
||||
|
||||
static void longswap(void *_ptr, size_t len)
|
||||
|
||||
@@ -373,7 +373,7 @@ void evp_generic_do_all(OPENSSL_CTX *libctx, int operation_id,
|
||||
ossl_algorithm_do_all(libctx, operation_id, NULL, do_one, &data);
|
||||
}
|
||||
|
||||
const char *evp_first_name(OSSL_PROVIDER *prov, int name_id)
|
||||
const char *evp_first_name(const OSSL_PROVIDER *prov, int name_id)
|
||||
{
|
||||
OPENSSL_CTX *libctx = ossl_provider_library_context(prov);
|
||||
OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
|
||||
|
||||
@@ -78,17 +78,21 @@ struct evp_keymgmt_st {
|
||||
OSSL_OP_keymgmt_free_fn *free;
|
||||
OSSL_OP_keymgmt_get_params_fn *get_params;
|
||||
OSSL_OP_keymgmt_gettable_params_fn *gettable_params;
|
||||
OSSL_OP_keymgmt_set_params_fn *set_params;
|
||||
OSSL_OP_keymgmt_settable_params_fn *settable_params;
|
||||
|
||||
/* Key object checking */
|
||||
OSSL_OP_keymgmt_query_operation_name_fn *query_operation_name;
|
||||
OSSL_OP_keymgmt_has_fn *has;
|
||||
OSSL_OP_keymgmt_validate_fn *validate;
|
||||
OSSL_OP_keymgmt_match_fn *match;
|
||||
|
||||
/* 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;
|
||||
OSSL_OP_keymgmt_copy_fn *copy;
|
||||
} /* EVP_KEYMGMT */ ;
|
||||
|
||||
struct evp_keyexch_st {
|
||||
@@ -105,6 +109,8 @@ struct evp_keyexch_st {
|
||||
OSSL_OP_keyexch_dupctx_fn *dupctx;
|
||||
OSSL_OP_keyexch_set_ctx_params_fn *set_ctx_params;
|
||||
OSSL_OP_keyexch_settable_ctx_params_fn *settable_ctx_params;
|
||||
OSSL_OP_keyexch_get_ctx_params_fn *get_ctx_params;
|
||||
OSSL_OP_keyexch_gettable_ctx_params_fn *gettable_ctx_params;
|
||||
} /* EVP_KEYEXCH */;
|
||||
|
||||
struct evp_signature_st {
|
||||
@@ -263,12 +269,10 @@ OSSL_PARAM *evp_pkey_to_param(EVP_PKEY *pkey, size_t *sz);
|
||||
void evp_pkey_ctx_free_old_ops(EVP_PKEY_CTX *ctx);
|
||||
|
||||
/* OSSL_PROVIDER * is only used to get the library context */
|
||||
const char *evp_first_name(OSSL_PROVIDER *prov, int name_id);
|
||||
const char *evp_first_name(const OSSL_PROVIDER *prov, int name_id);
|
||||
int evp_is_a(OSSL_PROVIDER *prov, int number,
|
||||
const char *legacy_name, const char *name);
|
||||
void evp_names_do_all(OSSL_PROVIDER *prov, int number,
|
||||
void (*fn)(const char *name, void *data),
|
||||
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);
|
||||
+37
-10
@@ -43,7 +43,7 @@ static void *evp_keyexch_from_dispatch(int name_id,
|
||||
OSSL_PROVIDER *prov)
|
||||
{
|
||||
EVP_KEYEXCH *exchange = NULL;
|
||||
int fncnt = 0, paramfncnt = 0;
|
||||
int fncnt = 0, sparamfncnt = 0, gparamfncnt = 0;
|
||||
|
||||
if ((exchange = evp_keyexch_new(prov)) == NULL) {
|
||||
ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
|
||||
@@ -88,28 +88,44 @@ static void *evp_keyexch_from_dispatch(int name_id,
|
||||
break;
|
||||
exchange->dupctx = OSSL_get_OP_keyexch_dupctx(fns);
|
||||
break;
|
||||
case OSSL_FUNC_KEYEXCH_GET_CTX_PARAMS:
|
||||
if (exchange->get_ctx_params != NULL)
|
||||
break;
|
||||
exchange->get_ctx_params = OSSL_get_OP_keyexch_get_ctx_params(fns);
|
||||
gparamfncnt++;
|
||||
break;
|
||||
case OSSL_FUNC_KEYEXCH_GETTABLE_CTX_PARAMS:
|
||||
if (exchange->gettable_ctx_params != NULL)
|
||||
break;
|
||||
exchange->gettable_ctx_params
|
||||
= OSSL_get_OP_keyexch_gettable_ctx_params(fns);
|
||||
gparamfncnt++;
|
||||
break;
|
||||
case OSSL_FUNC_KEYEXCH_SET_CTX_PARAMS:
|
||||
if (exchange->set_ctx_params != NULL)
|
||||
break;
|
||||
exchange->set_ctx_params = OSSL_get_OP_keyexch_set_ctx_params(fns);
|
||||
paramfncnt++;
|
||||
sparamfncnt++;
|
||||
break;
|
||||
case OSSL_FUNC_KEYEXCH_SETTABLE_CTX_PARAMS:
|
||||
if (exchange->settable_ctx_params != NULL)
|
||||
break;
|
||||
exchange->settable_ctx_params
|
||||
= OSSL_get_OP_keyexch_settable_ctx_params(fns);
|
||||
paramfncnt++;
|
||||
sparamfncnt++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (fncnt != 4 || (paramfncnt != 0 && paramfncnt != 2)) {
|
||||
if (fncnt != 4
|
||||
|| (gparamfncnt != 0 && gparamfncnt != 2)
|
||||
|| (sparamfncnt != 0 && sparamfncnt != 2)) {
|
||||
/*
|
||||
* In order to be a consistent set of functions we must have at least
|
||||
* a complete set of "exchange" functions: init, derive, newctx,
|
||||
* and freectx. The set_ctx_params and settable_ctx_params functions are
|
||||
* optional, but if one of them is present then the other one must also
|
||||
* be present. The dupctx and set_peer functions are optional.
|
||||
* be present. Same goes for get_ctx_params and gettable_ctx_params.
|
||||
* The dupctx and set_peer functions are optional.
|
||||
*/
|
||||
EVPerr(EVP_F_EVP_KEYEXCH_FROM_DISPATCH,
|
||||
EVP_R_INVALID_PROVIDER_FUNCTIONS);
|
||||
@@ -184,10 +200,13 @@ int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx)
|
||||
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)) {
|
||||
@@ -293,8 +312,12 @@ 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);
|
||||
/* If export failed, legacy may be able to pick it up */
|
||||
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
|
||||
*/
|
||||
if (provkey == NULL)
|
||||
goto legacy;
|
||||
return ctx->op.kex.exchange->set_peer(ctx->op.kex.exchprovctx, provkey);
|
||||
@@ -303,6 +326,10 @@ int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer)
|
||||
#ifdef FIPS_MODE
|
||||
return ret;
|
||||
#else
|
||||
/*
|
||||
* TODO(3.0) investigate the case where the operation is deemed legacy,
|
||||
* but the given peer key is provider only.
|
||||
*/
|
||||
if (ctx->pmeth == NULL
|
||||
|| !(ctx->pmeth->derive != NULL
|
||||
|| ctx->pmeth->encrypt != NULL
|
||||
|
||||
+267
-128
@@ -16,6 +16,18 @@
|
||||
#include "internal/provider.h"
|
||||
#include "evp_local.h"
|
||||
|
||||
/*
|
||||
* match_type() checks if two EVP_KEYMGMT are matching key types. This
|
||||
* function assumes that the caller has made all the necessary NULL checks.
|
||||
*/
|
||||
static int match_type(const EVP_KEYMGMT *keymgmt1, const EVP_KEYMGMT *keymgmt2)
|
||||
{
|
||||
const OSSL_PROVIDER *prov2 = EVP_KEYMGMT_provider(keymgmt2);
|
||||
const char *name2 = evp_first_name(prov2, EVP_KEYMGMT_number(keymgmt2));
|
||||
|
||||
return EVP_KEYMGMT_is_a(keymgmt1, name2);
|
||||
}
|
||||
|
||||
struct import_data_st {
|
||||
EVP_KEYMGMT *keymgmt;
|
||||
void *keydata;
|
||||
@@ -34,161 +46,150 @@ static int try_import(const OSSL_PARAM params[], void *arg)
|
||||
void *evp_keymgmt_util_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt)
|
||||
{
|
||||
void *keydata = NULL;
|
||||
size_t i, j;
|
||||
struct import_data_st import_data;
|
||||
size_t i = 0;
|
||||
|
||||
/* Export to where? */
|
||||
if (keymgmt == NULL)
|
||||
return NULL;
|
||||
|
||||
/* If we have an unassigned key, give up */
|
||||
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 */
|
||||
/*
|
||||
* TODO(3.0) consider an evp_keymgmt_export() return value that indicates
|
||||
* that the method is unsupported.
|
||||
*/
|
||||
if (pk->keymgmt->export == NULL)
|
||||
return NULL;
|
||||
|
||||
/* 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;
|
||||
|
||||
/*
|
||||
* If there is an underlying legacy key and it has changed, invalidate
|
||||
* the cache of provider keys.
|
||||
* Make sure that the type of the keymgmt to export to matches the type
|
||||
* of the "origin"
|
||||
*/
|
||||
if (pk->pkey.ptr != NULL) {
|
||||
/*
|
||||
* If there is no dirty counter, this key can't be used with
|
||||
* providers.
|
||||
*/
|
||||
if (pk->ameth->dirty_cnt == NULL)
|
||||
return NULL;
|
||||
|
||||
if (pk->ameth->dirty_cnt(pk) != pk->dirty_cnt_copy)
|
||||
evp_keymgmt_util_clear_pkey_cache(pk);
|
||||
}
|
||||
|
||||
/*
|
||||
* See if we have exported to this provider already.
|
||||
* If we have, return immediately.
|
||||
*/
|
||||
for (i = 0;
|
||||
i < OSSL_NELEM(pk->pkeys) && pk->pkeys[i].keymgmt != NULL;
|
||||
i++) {
|
||||
if (keymgmt == pk->pkeys[i].keymgmt)
|
||||
return pk->pkeys[i].keydata;
|
||||
}
|
||||
if (!ossl_assert(match_type(pk->keymgmt, keymgmt)))
|
||||
return NULL;
|
||||
|
||||
/* Create space to import data into */
|
||||
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 */
|
||||
/*
|
||||
* We look at the already cached provider keys, and import from the
|
||||
* first that supports it (i.e. use its export function), and export
|
||||
* the imported data to the new provider.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
/* 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
|
||||
* provider keys, and import from the first that supports it
|
||||
* (i.e. use its export function), and export the imported data to
|
||||
* the new provider.
|
||||
*/
|
||||
|
||||
/* Setup for the export callback */
|
||||
struct import_data_st import_data;
|
||||
|
||||
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++) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
/* Setup for the export callback */
|
||||
import_data.keydata = keydata;
|
||||
import_data.keymgmt = keymgmt;
|
||||
import_data.selection = OSSL_KEYMGMT_SELECT_ALL;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* The export function calls the callback (try_import), which does the
|
||||
* import for us. If successful, we're done.
|
||||
*/
|
||||
if (!ossl_assert(i < OSSL_NELEM(pk->pkeys)))
|
||||
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;
|
||||
}
|
||||
|
||||
evp_keymgmt_util_cache_pkey(pk, i, keymgmt, keydata);
|
||||
/* 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;
|
||||
}
|
||||
|
||||
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;
|
||||
size_t i, end = OSSL_NELEM(pk->operation_cache);
|
||||
|
||||
if (pk != NULL) {
|
||||
for (i = 0;
|
||||
i < OSSL_NELEM(pk->pkeys) && 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;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
size_t i, end = OSSL_NELEM(pk->operation_cache);
|
||||
|
||||
for (i = 0; i < end && pk->operation_cache[i].keymgmt != NULL; i++) {
|
||||
if (keymgmt == pk->operation_cache[i].keymgmt)
|
||||
break;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
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;
|
||||
if (!EVP_KEYMGMT_up_ref(keymgmt))
|
||||
return 0;
|
||||
pk->operation_cache[index].keydata = keydata;
|
||||
pk->operation_cache[index].keymgmt = keymgmt;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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];
|
||||
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(keymgmt, keydata, params)) {
|
||||
pk->cache.size = size;
|
||||
pk->cache.bits = bits;
|
||||
pk->cache.security_bits = security_bits;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -199,15 +200,153 @@ void *evp_keymgmt_util_fromdata(EVP_PKEY *target, EVP_KEYMGMT *keymgmt,
|
||||
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;
|
||||
}
|
||||
|
||||
int evp_keymgmt_util_has(EVP_PKEY *pk, int selection)
|
||||
{
|
||||
/* Check if key is even assigned */
|
||||
if (pk->keymgmt == NULL)
|
||||
return 0;
|
||||
|
||||
return evp_keymgmt_has(pk->keymgmt, pk->keydata, selection);
|
||||
}
|
||||
|
||||
/*
|
||||
* evp_keymgmt_util_match() doesn't just look at the provider side "origin",
|
||||
* but also in the operation cache to see if there's any common keymgmt that
|
||||
* supplies OP_keymgmt_match.
|
||||
*
|
||||
* evp_keymgmt_util_match() adheres to the return values that EVP_PKEY_cmp()
|
||||
* and EVP_PKEY_cmp_parameters() return, i.e.:
|
||||
*
|
||||
* 1 same key
|
||||
* 0 not same key
|
||||
* -1 not same key type
|
||||
* -2 unsupported operation
|
||||
*/
|
||||
int evp_keymgmt_util_match(EVP_PKEY *pk1, EVP_PKEY *pk2, int selection)
|
||||
{
|
||||
EVP_KEYMGMT *keymgmt1 = NULL, *keymgmt2 = NULL;
|
||||
void *keydata1 = NULL, *keydata2 = NULL;
|
||||
|
||||
if (pk1 == NULL || pk2 == NULL) {
|
||||
if (pk1 == NULL && pk2 == NULL)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
keymgmt1 = pk1->keymgmt;
|
||||
keydata1 = pk1->keydata;
|
||||
keymgmt2 = pk2->keymgmt;
|
||||
keydata2 = pk2->keydata;
|
||||
|
||||
if (keymgmt1 != keymgmt2) {
|
||||
void *tmp_keydata = NULL;
|
||||
|
||||
/* Complex case, where the keymgmt differ */
|
||||
if (keymgmt1 != NULL
|
||||
&& keymgmt2 != NULL
|
||||
&& !match_type(keymgmt1, keymgmt2)) {
|
||||
ERR_raise(ERR_LIB_EVP, EVP_R_DIFFERENT_KEY_TYPES);
|
||||
return -1; /* Not the same type */
|
||||
}
|
||||
|
||||
/*
|
||||
* The key types are determined to match, so we try cross export,
|
||||
* but only to keymgmt's that supply a matching function.
|
||||
*/
|
||||
if (keymgmt2 != NULL
|
||||
&& keymgmt2->match != NULL) {
|
||||
tmp_keydata = evp_keymgmt_util_export_to_provider(pk1, keymgmt2);
|
||||
if (tmp_keydata != NULL) {
|
||||
keymgmt1 = keymgmt2;
|
||||
keydata1 = tmp_keydata;
|
||||
}
|
||||
}
|
||||
if (tmp_keydata == NULL
|
||||
&& keymgmt1 != NULL
|
||||
&& keymgmt1->match != NULL) {
|
||||
tmp_keydata = evp_keymgmt_util_export_to_provider(pk2, keymgmt1);
|
||||
if (tmp_keydata != NULL) {
|
||||
keymgmt2 = keymgmt1;
|
||||
keydata2 = tmp_keydata;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If we still don't have matching keymgmt implementations, we give up */
|
||||
if (keymgmt1 != keymgmt2)
|
||||
return -2;
|
||||
|
||||
return evp_keymgmt_match(keymgmt1, keydata1, keydata2, selection);
|
||||
}
|
||||
|
||||
int evp_keymgmt_util_copy(EVP_PKEY *to, EVP_PKEY *from, int selection)
|
||||
{
|
||||
/* Save copies of pointers we want to play with without affecting |to| */
|
||||
EVP_KEYMGMT *to_keymgmt = to->keymgmt;
|
||||
void *to_keydata = to->keydata, *alloc_keydata = NULL;
|
||||
|
||||
/* An unassigned key can't be copied */
|
||||
if (from == NULL || from->keymgmt == NULL)
|
||||
return 0;
|
||||
|
||||
/* If |from| doesn't support copying, we fail */
|
||||
if (from->keymgmt->copy == NULL)
|
||||
return 0;
|
||||
|
||||
/* If |to| doesn't have a provider side "origin" yet, create one */
|
||||
if (to_keymgmt == NULL) {
|
||||
to_keydata = alloc_keydata = evp_keymgmt_newdata(from->keymgmt);
|
||||
if (to_keydata == NULL)
|
||||
return 0;
|
||||
to_keymgmt = from->keymgmt;
|
||||
}
|
||||
|
||||
if (to_keymgmt == from->keymgmt) {
|
||||
/* |to| and |from| have the same keymgmt, just copy and be done */
|
||||
if (!evp_keymgmt_copy(to_keymgmt, to_keydata, from->keydata,
|
||||
selection))
|
||||
return 0;
|
||||
} else if (match_type(to_keymgmt, from->keymgmt)) {
|
||||
struct import_data_st import_data;
|
||||
|
||||
import_data.keymgmt = to_keymgmt;
|
||||
import_data.keydata = to_keydata;
|
||||
import_data.selection = selection;
|
||||
|
||||
if (!evp_keymgmt_export(from->keymgmt, from->keydata, selection,
|
||||
&try_import, &import_data)) {
|
||||
evp_keymgmt_freedata(to_keymgmt, alloc_keydata);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
ERR_raise(ERR_LIB_EVP, EVP_R_DIFFERENT_KEY_TYPES);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (to->keymgmt == NULL
|
||||
&& !EVP_KEYMGMT_up_ref(to_keymgmt)) {
|
||||
evp_keymgmt_freedata(to_keymgmt, alloc_keydata);
|
||||
return 0;
|
||||
}
|
||||
evp_keymgmt_util_clear_operation_cache(to);
|
||||
to->keymgmt = to_keymgmt;
|
||||
to->keydata = to_keydata;
|
||||
evp_keymgmt_util_cache_keyinfo(to);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -38,7 +38,7 @@ static void *keymgmt_from_dispatch(int name_id,
|
||||
OSSL_PROVIDER *prov)
|
||||
{
|
||||
EVP_KEYMGMT *keymgmt = NULL;
|
||||
int paramfncnt = 0, importfncnt = 0, exportfncnt = 0;
|
||||
int setparamfncnt = 0, getparamfncnt = 0, importfncnt = 0, exportfncnt = 0;
|
||||
|
||||
if ((keymgmt = keymgmt_new()) == NULL) {
|
||||
EVP_KEYMGMT_free(keymgmt);
|
||||
@@ -58,17 +58,30 @@ static void *keymgmt_from_dispatch(int name_id,
|
||||
break;
|
||||
case OSSL_FUNC_KEYMGMT_GET_PARAMS:
|
||||
if (keymgmt->get_params == NULL) {
|
||||
paramfncnt++;
|
||||
getparamfncnt++;
|
||||
keymgmt->get_params = OSSL_get_OP_keymgmt_get_params(fns);
|
||||
}
|
||||
break;
|
||||
case OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS:
|
||||
if (keymgmt->gettable_params == NULL) {
|
||||
paramfncnt++;
|
||||
getparamfncnt++;
|
||||
keymgmt->gettable_params =
|
||||
OSSL_get_OP_keymgmt_gettable_params(fns);
|
||||
}
|
||||
break;
|
||||
case OSSL_FUNC_KEYMGMT_SET_PARAMS:
|
||||
if (keymgmt->set_params == NULL) {
|
||||
setparamfncnt++;
|
||||
keymgmt->set_params = OSSL_get_OP_keymgmt_set_params(fns);
|
||||
}
|
||||
break;
|
||||
case OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS:
|
||||
if (keymgmt->settable_params == NULL) {
|
||||
setparamfncnt++;
|
||||
keymgmt->settable_params =
|
||||
OSSL_get_OP_keymgmt_settable_params(fns);
|
||||
}
|
||||
break;
|
||||
case OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME:
|
||||
if (keymgmt->query_operation_name == NULL)
|
||||
keymgmt->query_operation_name =
|
||||
@@ -82,6 +95,10 @@ static void *keymgmt_from_dispatch(int name_id,
|
||||
if (keymgmt->validate == NULL)
|
||||
keymgmt->validate = OSSL_get_OP_keymgmt_validate(fns);
|
||||
break;
|
||||
case OSSL_FUNC_KEYMGMT_MATCH:
|
||||
if (keymgmt->match == NULL)
|
||||
keymgmt->match = OSSL_get_OP_keymgmt_match(fns);
|
||||
break;
|
||||
case OSSL_FUNC_KEYMGMT_IMPORT:
|
||||
if (keymgmt->import == NULL) {
|
||||
importfncnt++;
|
||||
@@ -119,7 +136,8 @@ static void *keymgmt_from_dispatch(int name_id,
|
||||
if (keymgmt->free == NULL
|
||||
|| keymgmt->new == NULL
|
||||
|| keymgmt->has == NULL
|
||||
|| (paramfncnt != 0 && paramfncnt != 2)
|
||||
|| (getparamfncnt != 0 && getparamfncnt != 2)
|
||||
|| (setparamfncnt != 0 && setparamfncnt != 2)
|
||||
|| (importfncnt != 0 && importfncnt != 2)
|
||||
|| (exportfncnt != 0 && exportfncnt != 2)) {
|
||||
EVP_KEYMGMT_free(keymgmt);
|
||||
@@ -246,6 +264,21 @@ const OSSL_PARAM *evp_keymgmt_gettable_params(const EVP_KEYMGMT *keymgmt)
|
||||
return keymgmt->gettable_params();
|
||||
}
|
||||
|
||||
int evp_keymgmt_set_params(const EVP_KEYMGMT *keymgmt, void *keydata,
|
||||
const OSSL_PARAM params[])
|
||||
{
|
||||
if (keymgmt->set_params == NULL)
|
||||
return 1;
|
||||
return keymgmt->set_params(keydata, params);
|
||||
}
|
||||
|
||||
const OSSL_PARAM *evp_keymgmt_settable_params(const EVP_KEYMGMT *keymgmt)
|
||||
{
|
||||
if (keymgmt->settable_params == NULL)
|
||||
return NULL;
|
||||
return keymgmt->settable_params();
|
||||
}
|
||||
|
||||
int evp_keymgmt_has(const EVP_KEYMGMT *keymgmt, void *keydata, int selection)
|
||||
{
|
||||
/* This is mandatory, no need to check for its presence */
|
||||
@@ -261,6 +294,16 @@ int evp_keymgmt_validate(const EVP_KEYMGMT *keymgmt, void *keydata,
|
||||
return keymgmt->validate(keydata, selection);
|
||||
}
|
||||
|
||||
int evp_keymgmt_match(const EVP_KEYMGMT *keymgmt,
|
||||
const void *keydata1, const void *keydata2,
|
||||
int selection)
|
||||
{
|
||||
/* We assume no match if the implementation doesn't have a function */
|
||||
if (keymgmt->match == NULL)
|
||||
return 0;
|
||||
return keymgmt->match(keydata1, keydata2, selection);
|
||||
}
|
||||
|
||||
int evp_keymgmt_import(const EVP_KEYMGMT *keymgmt, void *keydata,
|
||||
int selection, const OSSL_PARAM params[])
|
||||
{
|
||||
@@ -292,3 +335,13 @@ const OSSL_PARAM *evp_keymgmt_export_types(const EVP_KEYMGMT *keymgmt,
|
||||
return NULL;
|
||||
return keymgmt->export_types(selection);
|
||||
}
|
||||
|
||||
int evp_keymgmt_copy(const EVP_KEYMGMT *keymgmt,
|
||||
void *keydata_to, const void *keydata_from,
|
||||
int selection)
|
||||
{
|
||||
/* We assume no copy if the implementation doesn't have a function */
|
||||
if (keymgmt->copy == NULL)
|
||||
return 0;
|
||||
return keymgmt->copy(keydata_to, keydata_from, selection);
|
||||
}
|
||||
@@ -64,10 +64,13 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
|
||||
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)) {
|
||||
|
||||
+378
-30
@@ -86,12 +86,25 @@ int EVP_PKEY_save_parameters(EVP_PKEY *pkey, int mode)
|
||||
|
||||
int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
|
||||
{
|
||||
if (to->type == EVP_PKEY_NONE) {
|
||||
if (EVP_PKEY_set_type(to, from->type) == 0)
|
||||
return 0;
|
||||
} else if (to->type != from->type) {
|
||||
EVPerr(EVP_F_EVP_PKEY_COPY_PARAMETERS, EVP_R_DIFFERENT_KEY_TYPES);
|
||||
goto err;
|
||||
/*
|
||||
* TODO: clean up legacy stuff from this function when legacy support
|
||||
* is gone.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Only check that type match this early when both keys are legacy.
|
||||
* If either of them is provided, we let evp_keymgmt_util_copy()
|
||||
* do this check, after having exported either of them that isn't
|
||||
* provided.
|
||||
*/
|
||||
if (to->keymgmt == NULL && from->keymgmt == NULL) {
|
||||
if (to->type == EVP_PKEY_NONE) {
|
||||
if (EVP_PKEY_set_type(to, from->type) == 0)
|
||||
return 0;
|
||||
} else if (to->type != from->type) {
|
||||
EVPerr(EVP_F_EVP_PKEY_COPY_PARAMETERS, EVP_R_DIFFERENT_KEY_TYPES);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (EVP_PKEY_missing_parameters(from)) {
|
||||
@@ -106,7 +119,56 @@ int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (from->ameth && from->ameth->param_copy)
|
||||
/*
|
||||
* If |from| is provided, we upgrade |to| to be provided as well.
|
||||
* This drops the legacy key from |to|.
|
||||
* evp_pkey_upgrade_to_provider() checks if |to| is already provided,
|
||||
* we don't need to do that here.
|
||||
*
|
||||
* TODO(3.0) We should investigate if that's too aggressive and make
|
||||
* this scenario unsupported instead.
|
||||
*/
|
||||
if (from->keymgmt != NULL) {
|
||||
EVP_KEYMGMT *tmp_keymgmt = from->keymgmt;
|
||||
|
||||
/*
|
||||
* The returned pointer is known to be cached, so we don't have to
|
||||
* save it. However, if it's NULL, something went wrong and we can't
|
||||
* copy.
|
||||
*/
|
||||
if (evp_pkey_upgrade_to_provider(to, NULL,
|
||||
&tmp_keymgmt, NULL) == NULL) {
|
||||
ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* For purely provided keys, we just call the keymgmt utility */
|
||||
if (to->keymgmt != NULL && from->keymgmt != NULL)
|
||||
return evp_keymgmt_util_copy(to, (EVP_PKEY *)from,
|
||||
OSSL_KEYMGMT_SELECT_ALL_PARAMETERS);
|
||||
|
||||
/*
|
||||
* If |to| is provided, we know that |from| is legacy at this point.
|
||||
* Try exporting |from| to |to|'s keymgmt, then use evp_keymgmt_copy()
|
||||
* to copy the appropriate data to |to|'s keydata.
|
||||
*/
|
||||
if (to->keymgmt != NULL) {
|
||||
EVP_KEYMGMT *to_keymgmt = to->keymgmt;
|
||||
void *from_keydata =
|
||||
evp_pkey_export_to_provider((EVP_PKEY *)from, NULL, &to_keymgmt,
|
||||
NULL);
|
||||
|
||||
if (from_keydata == NULL) {
|
||||
ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
return evp_keymgmt_copy(to->keymgmt, to->keydata, from_keydata,
|
||||
OSSL_KEYMGMT_SELECT_ALL_PARAMETERS);
|
||||
}
|
||||
|
||||
/* Both keys are legacy */
|
||||
if (from->ameth != NULL && from->ameth->param_copy != NULL)
|
||||
return from->ameth->param_copy(to, from);
|
||||
err:
|
||||
return 0;
|
||||
@@ -114,35 +176,118 @@ int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
|
||||
|
||||
int EVP_PKEY_missing_parameters(const EVP_PKEY *pkey)
|
||||
{
|
||||
if (pkey != NULL && pkey->ameth && pkey->ameth->param_missing)
|
||||
return pkey->ameth->param_missing(pkey);
|
||||
if (pkey != NULL) {
|
||||
if (pkey->keymgmt != NULL)
|
||||
return !evp_keymgmt_util_has((EVP_PKEY *)pkey,
|
||||
OSSL_KEYMGMT_SELECT_ALL_PARAMETERS);
|
||||
else if (pkey->ameth != NULL && pkey->ameth->param_missing != NULL)
|
||||
return pkey->ameth->param_missing(pkey);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called for any mixture of keys except pure legacy pair.
|
||||
* TODO When legacy keys are gone, we replace a call to this functions with
|
||||
* a call to evp_keymgmt_util_match().
|
||||
*/
|
||||
static int evp_pkey_cmp_any(const EVP_PKEY *a, const EVP_PKEY *b,
|
||||
int selection)
|
||||
{
|
||||
EVP_KEYMGMT *keymgmt1 = NULL, *keymgmt2 = NULL;
|
||||
void *keydata1 = NULL, *keydata2 = NULL, *tmp_keydata = NULL;
|
||||
|
||||
/* If none of them are provided, this function shouldn't have been called */
|
||||
if (!ossl_assert(a->keymgmt != NULL || b->keymgmt != NULL))
|
||||
return -2;
|
||||
|
||||
/* For purely provided keys, we just call the keymgmt utility */
|
||||
if (a->keymgmt != NULL && b->keymgmt != NULL)
|
||||
return evp_keymgmt_util_match((EVP_PKEY *)a, (EVP_PKEY *)b, selection);
|
||||
|
||||
/*
|
||||
* Here, we know that we have a mixture of legacy and provided keys.
|
||||
* Try cross export and compare the resulting key data.
|
||||
*/
|
||||
keymgmt1 = a->keymgmt;
|
||||
keydata1 = a->keydata;
|
||||
keymgmt2 = b->keymgmt;
|
||||
keydata2 = b->keydata;
|
||||
|
||||
if ((keymgmt1 == NULL
|
||||
&& !EVP_KEYMGMT_is_a(keymgmt2, OBJ_nid2sn(a->type)))
|
||||
|| (keymgmt2 == NULL
|
||||
&& !EVP_KEYMGMT_is_a(keymgmt1, OBJ_nid2sn(b->type))))
|
||||
return -1; /* not the same key type */
|
||||
|
||||
if (keymgmt2 != NULL && keymgmt2->match != NULL) {
|
||||
tmp_keydata =
|
||||
evp_pkey_export_to_provider((EVP_PKEY *)a, NULL, &keymgmt2, NULL);
|
||||
if (tmp_keydata != NULL) {
|
||||
keymgmt1 = keymgmt2;
|
||||
keydata1 = tmp_keydata;
|
||||
}
|
||||
}
|
||||
if (tmp_keydata == NULL && keymgmt1 != NULL && keymgmt1->match != NULL) {
|
||||
tmp_keydata =
|
||||
evp_pkey_export_to_provider((EVP_PKEY *)b, NULL, &keymgmt1, NULL);
|
||||
if (tmp_keydata != NULL) {
|
||||
keymgmt2 = keymgmt1;
|
||||
keydata2 = tmp_keydata;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we still don't have matching keymgmt implementations, we give up */
|
||||
if (keymgmt1 != keymgmt2)
|
||||
return -2;
|
||||
|
||||
return evp_keymgmt_match(keymgmt1, keydata1, keydata2, selection);
|
||||
}
|
||||
|
||||
int EVP_PKEY_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
|
||||
{
|
||||
/*
|
||||
* TODO: clean up legacy stuff from this function when legacy support
|
||||
* is gone.
|
||||
*/
|
||||
|
||||
if (a->keymgmt != NULL || b->keymgmt != NULL)
|
||||
return evp_pkey_cmp_any(a, b, OSSL_KEYMGMT_SELECT_ALL_PARAMETERS);
|
||||
|
||||
/* All legacy keys */
|
||||
if (a->type != b->type)
|
||||
return -1;
|
||||
if (a->ameth && a->ameth->param_cmp)
|
||||
if (a->ameth != NULL && a->ameth->param_cmp != NULL)
|
||||
return a->ameth->param_cmp(a, b);
|
||||
return -2;
|
||||
}
|
||||
|
||||
int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
|
||||
{
|
||||
/*
|
||||
* TODO: clean up legacy stuff from this function when legacy support
|
||||
* is gone.
|
||||
*/
|
||||
|
||||
if (a->keymgmt != NULL || b->keymgmt != NULL)
|
||||
return evp_pkey_cmp_any(a, b,
|
||||
OSSL_KEYMGMT_SELECT_ALL_PARAMETERS
|
||||
| OSSL_KEYMGMT_SELECT_PUBLIC_KEY);
|
||||
|
||||
/* All legacy keys */
|
||||
if (a->type != b->type)
|
||||
return -1;
|
||||
|
||||
if (a->ameth) {
|
||||
if (a->ameth != NULL) {
|
||||
int ret;
|
||||
/* Compare parameters if the algorithm has them */
|
||||
if (a->ameth->param_cmp) {
|
||||
if (a->ameth->param_cmp != NULL) {
|
||||
ret = a->ameth->param_cmp(a, b);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (a->ameth->pub_cmp)
|
||||
if (a->ameth->pub_cmp != NULL)
|
||||
return a->ameth->pub_cmp(a, b);
|
||||
}
|
||||
|
||||
@@ -713,7 +858,7 @@ int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey,
|
||||
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:
|
||||
@@ -768,9 +913,7 @@ int EVP_PKEY_get_default_digest_name(EVP_PKEY *pkey,
|
||||
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);
|
||||
@@ -868,22 +1011,40 @@ int EVP_PKEY_up_ref(EVP_PKEY *pkey)
|
||||
return ((i > 1) ? 1 : 0);
|
||||
}
|
||||
|
||||
static void evp_pkey_free_it(EVP_PKEY *x)
|
||||
#ifndef FIPS_MODE
|
||||
static void evp_pkey_free_legacy(EVP_PKEY *x)
|
||||
{
|
||||
/* internal function; x is never NULL */
|
||||
|
||||
evp_keymgmt_util_clear_pkey_cache(x);
|
||||
|
||||
if (x->ameth && x->ameth->pkey_free) {
|
||||
x->ameth->pkey_free(x);
|
||||
if (x->ameth != NULL) {
|
||||
if (x->ameth->pkey_free != NULL)
|
||||
x->ameth->pkey_free(x);
|
||||
x->pkey.ptr = NULL;
|
||||
x->ameth = NULL;
|
||||
}
|
||||
#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
|
||||
# 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->keymgmt != NULL) {
|
||||
evp_keymgmt_freedata(x->keymgmt, x->keydata);
|
||||
EVP_KEYMGMT_free(x->keymgmt);
|
||||
x->keymgmt = NULL;
|
||||
x->keydata = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void EVP_PKEY_free(EVP_PKEY *x)
|
||||
@@ -917,8 +1078,9 @@ int EVP_PKEY_size(const EVP_PKEY *pkey)
|
||||
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;
|
||||
@@ -927,11 +1089,23 @@ void *evp_pkey_make_provided(EVP_PKEY *pk, OPENSSL_CTX *libctx,
|
||||
if (pk == NULL)
|
||||
return NULL;
|
||||
|
||||
#ifndef FIPS_MODE
|
||||
if (pk->pkey.ptr != NULL) {
|
||||
/*
|
||||
* If the legacy key doesn't have an dirty counter or export function,
|
||||
* give up
|
||||
*/
|
||||
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);
|
||||
|
||||
@@ -941,10 +1115,87 @@ void *evp_pkey_make_provided(EVP_PKEY *pk, OPENSSL_CTX *libctx,
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
}
|
||||
|
||||
if (tmp_keymgmt != NULL)
|
||||
keydata =
|
||||
evp_keymgmt_util_export_to_provider(pk, tmp_keymgmt);
|
||||
/* 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 = 0;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)))
|
||||
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_freedata(tmp_keymgmt, keydata);
|
||||
keydata = NULL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
goto end;
|
||||
}
|
||||
#endif /* FIPS_MODE */
|
||||
|
||||
keydata = evp_keymgmt_util_export_to_provider(pk, tmp_keymgmt);
|
||||
|
||||
end:
|
||||
/*
|
||||
* 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
|
||||
@@ -959,3 +1210,100 @@ void *evp_pkey_make_provided(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 */
|
||||
@@ -224,7 +224,7 @@ static int pkey_kdf_ctrl_str(EVP_PKEY_CTX *ctx, const char *type,
|
||||
type = OSSL_KDF_PARAM_SCRYPT_N;
|
||||
|
||||
if (!OSSL_PARAM_allocate_from_text(¶ms[0], defs, type,
|
||||
value, strlen(value)))
|
||||
value, strlen(value), NULL))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
|
||||
@@ -453,7 +453,7 @@ static int pkey_mac_ctrl_str(EVP_PKEY_CTX *ctx,
|
||||
|
||||
if (!OSSL_PARAM_allocate_from_text(¶ms[0],
|
||||
EVP_MAC_settable_ctx_params(mac),
|
||||
type, value, strlen(value) + 1))
|
||||
type, value, strlen(value) + 1, NULL))
|
||||
return 0;
|
||||
params[1] = OSSL_PARAM_construct_end();
|
||||
ok = EVP_MAC_CTX_set_params(hctx->ctx, params);
|
||||
|
||||
+10
-10
@@ -28,8 +28,8 @@ int EVP_PKEY_public_check(EVP_PKEY_CTX *ctx)
|
||||
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,
|
||||
@@ -61,8 +61,8 @@ int EVP_PKEY_param_check(EVP_PKEY_CTX *ctx)
|
||||
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,
|
||||
@@ -94,8 +94,8 @@ int EVP_PKEY_private_check(EVP_PKEY_CTX *ctx)
|
||||
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,
|
||||
@@ -115,8 +115,8 @@ int EVP_PKEY_pairwise_check(EVP_PKEY_CTX *ctx)
|
||||
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);
|
||||
@@ -135,8 +135,8 @@ int EVP_PKEY_check(EVP_PKEY_CTX *ctx)
|
||||
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);
|
||||
|
||||
@@ -41,10 +41,13 @@ static int evp_pkey_asym_cipher_init(EVP_PKEY_CTX *ctx, int operation)
|
||||
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)) {
|
||||
|
||||
+153
-35
@@ -8,6 +8,12 @@
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/*
|
||||
* DH low level APIs are deprecated for public use, but still ok for
|
||||
* internal use.
|
||||
*/
|
||||
#include "internal/deprecated.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <openssl/engine.h>
|
||||
@@ -154,8 +160,7 @@ static EVP_PKEY_CTX *int_ctx_new(OPENSSL_CTX *libctx,
|
||||
/* 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
|
||||
@@ -570,6 +575,12 @@ int EVP_PKEY_CTX_set_params(EVP_PKEY_CTX *ctx, OSSL_PARAM *params)
|
||||
#ifndef FIPS_MODE
|
||||
int EVP_PKEY_CTX_get_params(EVP_PKEY_CTX *ctx, OSSL_PARAM *params)
|
||||
{
|
||||
if (EVP_PKEY_CTX_IS_DERIVE_OP(ctx)
|
||||
&& ctx->op.kex.exchprovctx != NULL
|
||||
&& ctx->op.kex.exchange != NULL
|
||||
&& ctx->op.kex.exchange->get_ctx_params != NULL)
|
||||
return ctx->op.kex.exchange->get_ctx_params(ctx->op.kex.exchprovctx,
|
||||
params);
|
||||
if (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)
|
||||
&& ctx->op.sig.sigprovctx != NULL
|
||||
&& ctx->op.sig.signature != NULL
|
||||
@@ -587,6 +598,10 @@ int EVP_PKEY_CTX_get_params(EVP_PKEY_CTX *ctx, OSSL_PARAM *params)
|
||||
|
||||
const OSSL_PARAM *EVP_PKEY_CTX_gettable_params(EVP_PKEY_CTX *ctx)
|
||||
{
|
||||
if (EVP_PKEY_CTX_IS_DERIVE_OP(ctx)
|
||||
&& ctx->op.kex.exchange != NULL
|
||||
&& ctx->op.kex.exchange->gettable_ctx_params != NULL)
|
||||
return ctx->op.kex.exchange->gettable_ctx_params();
|
||||
if (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)
|
||||
&& ctx->op.sig.signature != NULL
|
||||
&& ctx->op.sig.signature->gettable_ctx_params != NULL)
|
||||
@@ -618,6 +633,52 @@ const OSSL_PARAM *EVP_PKEY_CTX_settable_params(EVP_PKEY_CTX *ctx)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Internal helpers for stricter EVP_PKEY_CTX_{set,get}_params().
|
||||
*
|
||||
* Return 1 on success, 0 or negative for errors.
|
||||
*
|
||||
* In particular they return -2 if any of the params is not supported.
|
||||
*
|
||||
* They are not available in FIPS_MODE as they depend on
|
||||
* - EVP_PKEY_CTX_{get,set}_params()
|
||||
* - EVP_PKEY_CTX_{gettable,settable}_params()
|
||||
*
|
||||
*/
|
||||
int evp_pkey_ctx_set_params_strict(EVP_PKEY_CTX *ctx, OSSL_PARAM *params)
|
||||
{
|
||||
const OSSL_PARAM *p;
|
||||
|
||||
if (ctx == NULL || params == NULL)
|
||||
return 0;
|
||||
|
||||
for (p = params; p->key != NULL; p++) {
|
||||
/* Check the ctx actually understands this parameter */
|
||||
if (OSSL_PARAM_locate_const(EVP_PKEY_CTX_settable_params(ctx),
|
||||
p->key) == NULL )
|
||||
return -2;
|
||||
}
|
||||
|
||||
return EVP_PKEY_CTX_set_params(ctx, params);
|
||||
}
|
||||
|
||||
int evp_pkey_ctx_get_params_strict(EVP_PKEY_CTX *ctx, OSSL_PARAM *params)
|
||||
{
|
||||
const OSSL_PARAM *p;
|
||||
|
||||
if (ctx == NULL || params == NULL)
|
||||
return 0;
|
||||
|
||||
for (p = params; p->key != NULL; p++ ) {
|
||||
/* Check the ctx actually understands this parameter */
|
||||
if (OSSL_PARAM_locate_const(EVP_PKEY_CTX_gettable_params(ctx),
|
||||
p->key) == NULL )
|
||||
return -2;
|
||||
}
|
||||
|
||||
return EVP_PKEY_CTX_get_params(ctx, params);
|
||||
}
|
||||
|
||||
# ifndef OPENSSL_NO_DH
|
||||
int EVP_PKEY_CTX_set_dh_pad(EVP_PKEY_CTX *ctx, int pad)
|
||||
{
|
||||
@@ -713,42 +774,85 @@ int EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD *md)
|
||||
static int legacy_ctrl_to_param(EVP_PKEY_CTX *ctx, int keytype, int optype,
|
||||
int cmd, int p1, void *p2)
|
||||
{
|
||||
switch (cmd) {
|
||||
# ifndef OPENSSL_NO_DH
|
||||
case EVP_PKEY_CTRL_DH_PAD:
|
||||
return EVP_PKEY_CTX_set_dh_pad(ctx, p1);
|
||||
if (keytype == EVP_PKEY_DH) {
|
||||
switch (cmd) {
|
||||
case EVP_PKEY_CTRL_DH_PAD:
|
||||
return EVP_PKEY_CTX_set_dh_pad(ctx, p1);
|
||||
}
|
||||
}
|
||||
# endif
|
||||
case EVP_PKEY_CTRL_MD:
|
||||
return EVP_PKEY_CTX_set_signature_md(ctx, p2);
|
||||
case EVP_PKEY_CTRL_GET_MD:
|
||||
return EVP_PKEY_CTX_get_signature_md(ctx, p2);
|
||||
case EVP_PKEY_CTRL_RSA_PADDING:
|
||||
return EVP_PKEY_CTX_set_rsa_padding(ctx, p1);
|
||||
case EVP_PKEY_CTRL_GET_RSA_PADDING:
|
||||
return EVP_PKEY_CTX_get_rsa_padding(ctx, p2);
|
||||
case EVP_PKEY_CTRL_RSA_OAEP_MD:
|
||||
return EVP_PKEY_CTX_set_rsa_oaep_md(ctx, p2);
|
||||
case EVP_PKEY_CTRL_GET_RSA_OAEP_MD:
|
||||
return EVP_PKEY_CTX_get_rsa_oaep_md(ctx, p2);
|
||||
case EVP_PKEY_CTRL_RSA_MGF1_MD:
|
||||
return EVP_PKEY_CTX_set_rsa_oaep_md(ctx, p2);
|
||||
case EVP_PKEY_CTRL_GET_RSA_MGF1_MD:
|
||||
return EVP_PKEY_CTX_get_rsa_oaep_md(ctx, p2);
|
||||
case EVP_PKEY_CTRL_RSA_OAEP_LABEL:
|
||||
return EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, p2, p1);
|
||||
case EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL:
|
||||
return EVP_PKEY_CTX_get0_rsa_oaep_label(ctx, (unsigned char **)p2);
|
||||
case EVP_PKEY_CTRL_PKCS7_ENCRYPT:
|
||||
case EVP_PKEY_CTRL_PKCS7_DECRYPT:
|
||||
# ifndef OPENSSL_NO_EC
|
||||
if (keytype == EVP_PKEY_EC) {
|
||||
switch (cmd) {
|
||||
case EVP_PKEY_CTRL_EC_ECDH_COFACTOR:
|
||||
if (p1 == -2) {
|
||||
return EVP_PKEY_CTX_get_ecdh_cofactor_mode(ctx);
|
||||
} else if (p1 < -1 || p1 > 1) {
|
||||
/* Uses the same return values as EVP_PKEY_CTX_ctrl */
|
||||
return -2;
|
||||
} else {
|
||||
return EVP_PKEY_CTX_set_ecdh_cofactor_mode(ctx, p1);
|
||||
}
|
||||
case EVP_PKEY_CTRL_EC_KDF_TYPE:
|
||||
if (p1 == -2) {
|
||||
return EVP_PKEY_CTX_get_ecdh_kdf_type(ctx);
|
||||
} else {
|
||||
return EVP_PKEY_CTX_set_ecdh_kdf_type(ctx, p1);
|
||||
}
|
||||
case EVP_PKEY_CTRL_GET_EC_KDF_MD:
|
||||
return EVP_PKEY_CTX_get_ecdh_kdf_md(ctx, p2);
|
||||
case EVP_PKEY_CTRL_EC_KDF_MD:
|
||||
return EVP_PKEY_CTX_set_ecdh_kdf_md(ctx, p2);
|
||||
case EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN:
|
||||
return EVP_PKEY_CTX_get_ecdh_kdf_outlen(ctx, p2);
|
||||
case EVP_PKEY_CTRL_EC_KDF_OUTLEN:
|
||||
return EVP_PKEY_CTX_set_ecdh_kdf_outlen(ctx, p1);
|
||||
case EVP_PKEY_CTRL_GET_EC_KDF_UKM:
|
||||
return EVP_PKEY_CTX_get0_ecdh_kdf_ukm(ctx, p2);
|
||||
case EVP_PKEY_CTRL_EC_KDF_UKM:
|
||||
return EVP_PKEY_CTX_set0_ecdh_kdf_ukm(ctx, p2, p1);
|
||||
}
|
||||
}
|
||||
# endif
|
||||
if (keytype == -1) {
|
||||
switch (cmd) {
|
||||
case EVP_PKEY_CTRL_MD:
|
||||
return EVP_PKEY_CTX_set_signature_md(ctx, p2);
|
||||
case EVP_PKEY_CTRL_GET_MD:
|
||||
return EVP_PKEY_CTX_get_signature_md(ctx, p2);
|
||||
case EVP_PKEY_CTRL_RSA_PADDING:
|
||||
return EVP_PKEY_CTX_set_rsa_padding(ctx, p1);
|
||||
case EVP_PKEY_CTRL_GET_RSA_PADDING:
|
||||
return EVP_PKEY_CTX_get_rsa_padding(ctx, p2);
|
||||
case EVP_PKEY_CTRL_RSA_OAEP_MD:
|
||||
return EVP_PKEY_CTX_set_rsa_oaep_md(ctx, p2);
|
||||
case EVP_PKEY_CTRL_GET_RSA_OAEP_MD:
|
||||
return EVP_PKEY_CTX_get_rsa_oaep_md(ctx, p2);
|
||||
case EVP_PKEY_CTRL_RSA_MGF1_MD:
|
||||
return EVP_PKEY_CTX_set_rsa_oaep_md(ctx, p2);
|
||||
case EVP_PKEY_CTRL_GET_RSA_MGF1_MD:
|
||||
return EVP_PKEY_CTX_get_rsa_oaep_md(ctx, p2);
|
||||
case EVP_PKEY_CTRL_RSA_OAEP_LABEL:
|
||||
return EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, p2, p1);
|
||||
case EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL:
|
||||
return EVP_PKEY_CTX_get0_rsa_oaep_label(ctx, (unsigned char **)p2);
|
||||
case EVP_PKEY_CTRL_RSA_PSS_SALTLEN:
|
||||
return EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, p1);
|
||||
case EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN:
|
||||
return EVP_PKEY_CTX_get_rsa_pss_saltlen(ctx, p2);
|
||||
case EVP_PKEY_CTRL_PKCS7_ENCRYPT:
|
||||
case EVP_PKEY_CTRL_PKCS7_DECRYPT:
|
||||
# ifndef OPENSSL_NO_CMS
|
||||
case EVP_PKEY_CTRL_CMS_DECRYPT:
|
||||
case EVP_PKEY_CTRL_CMS_ENCRYPT:
|
||||
case EVP_PKEY_CTRL_CMS_DECRYPT:
|
||||
case EVP_PKEY_CTRL_CMS_ENCRYPT:
|
||||
# endif
|
||||
if (ctx->pmeth->pkey_id != EVP_PKEY_RSA_PSS)
|
||||
return 1;
|
||||
ERR_raise(ERR_LIB_EVP,
|
||||
EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
|
||||
return -2;
|
||||
if (ctx->pmeth->pkey_id != EVP_PKEY_RSA_PSS)
|
||||
return 1;
|
||||
ERR_raise(ERR_LIB_EVP,
|
||||
EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -817,10 +921,18 @@ static int legacy_ctrl_str_to_param(EVP_PKEY_CTX *ctx, const char *name,
|
||||
name = OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST;
|
||||
else if (strcmp(name, "rsa_oaep_label") == 0)
|
||||
name = OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL;
|
||||
else if (strcmp(name, "rsa_pss_saltlen") == 0)
|
||||
name = OSSL_SIGNATURE_PARAM_PSS_SALTLEN;
|
||||
# ifndef OPENSSL_NO_DH
|
||||
else if (strcmp(name, "dh_pad") == 0)
|
||||
name = OSSL_EXCHANGE_PARAM_PAD;
|
||||
# endif
|
||||
# ifndef OPENSSL_NO_EC
|
||||
else if (strcmp(name, "ecdh_cofactor_mode") == 0)
|
||||
name = OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE;
|
||||
else if (strcmp(name, "ecdh_kdf_md") == 0)
|
||||
name = OSSL_EXCHANGE_PARAM_KDF_TYPE;
|
||||
# endif
|
||||
|
||||
{
|
||||
/*
|
||||
@@ -831,10 +943,16 @@ static int legacy_ctrl_str_to_param(EVP_PKEY_CTX *ctx, const char *name,
|
||||
const OSSL_PARAM *settable = EVP_PKEY_CTX_settable_params(ctx);
|
||||
OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
|
||||
int rv = 0;
|
||||
int exists = 0;
|
||||
|
||||
if (!OSSL_PARAM_allocate_from_text(¶ms[0], settable, name, value,
|
||||
strlen(value)))
|
||||
strlen(value), &exists)) {
|
||||
if (!exists) {
|
||||
ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
|
||||
return -2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (EVP_PKEY_CTX_set_params(ctx, params))
|
||||
rv = 1;
|
||||
OPENSSL_free(params[0].data);
|
||||
|
||||
@@ -342,10 +342,13 @@ static int evp_pkey_signature_init(EVP_PKEY_CTX *ctx, int operation)
|
||||
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)) {
|
||||
|
||||
Reference in New Issue
Block a user