Latest update.

This commit is contained in:
2020-03-03 19:16:19 +09:00
parent f85de4da03
commit b412d79e8b
310 changed files with 32765 additions and 19720 deletions
+2 -7
View File
@@ -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)
+2 -7
View File
@@ -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
View File
@@ -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
View File
@@ -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)
+1 -1
View File
@@ -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);
+7 -3
View File
@@ -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
View File
@@ -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
View File
@@ -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;
}
+57 -4
View File
@@ -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);
}
+6 -3
View File
@@ -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
View File
@@ -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 */
+1 -1
View File
@@ -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(&params[0], defs, type,
value, strlen(value)))
value, strlen(value), NULL))
return 0;
/*
+1 -1
View File
@@ -453,7 +453,7 @@ static int pkey_mac_ctrl_str(EVP_PKEY_CTX *ctx,
if (!OSSL_PARAM_allocate_from_text(&params[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
View File
@@ -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);
+6 -3
View File
@@ -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
View File
@@ -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(&params[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);
+6 -3
View File
@@ -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)) {