[openssl] master update
Richard Levitte
levitte at openssl.org
Mon Mar 2 02:28:55 UTC 2020
The branch master has been updated
via 2888fc1590ad31633be7a99e7288dcecd35e800c (commit)
via ff3b59e1705a40f7cfc6df8d788d08b0a525aa58 (commit)
via 13697f1c62e98a4c1365fd85cb39ada0f47dce5f (commit)
via 1e9101c404b92b1fd32e8f0308ddc20742285135 (commit)
via bee5d6cd3fa2f8bcc7e1153e4dc26aa26144bee0 (commit)
via 157ded39ee68c1c00814165f79f9b2f000996884 (commit)
from ccceeb48000d5fae95f38d2c4dd02cdd89ca1ee1 (commit)
- Log -----------------------------------------------------------------
commit 2888fc1590ad31633be7a99e7288dcecd35e800c
Author: Richard Levitte <levitte at openssl.org>
Date: Thu Feb 6 09:53:15 2020 +0100
PROV: Add a OP_keymgmt_match() function to our DH, DSA, RSA and EC_KEY impl
Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
(Merged from https://github.com/openssl/openssl/pull/11158)
commit ff3b59e1705a40f7cfc6df8d788d08b0a525aa58
Author: Richard Levitte <levitte at openssl.org>
Date: Wed Feb 5 16:30:21 2020 +0100
EVP: Add support for copying provided EVP_PKEYs
This adds evp_keymgmt_util_copy() and affects EVP_PKEY_copy_parameters()
Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
(Merged from https://github.com/openssl/openssl/pull/11158)
commit 13697f1c62e98a4c1365fd85cb39ada0f47dce5f
Author: Richard Levitte <levitte at openssl.org>
Date: Wed Feb 5 15:41:58 2020 +0100
KEYMGMT: Add a keydata copy function
Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
(Merged from https://github.com/openssl/openssl/pull/11158)
commit 1e9101c404b92b1fd32e8f0308ddc20742285135
Author: Richard Levitte <levitte at openssl.org>
Date: Wed Feb 5 12:55:43 2020 +0100
EVP: Add support for comparing provided EVP_PKEYs
This adds evp_keymgmt_util_match() and affects EVP_PKEY_cmp() and
EVP_PKEY_cmp_parameters().
The word 'match' was used for the new routines because many associate
'cmp' with comparison functions that allows sorting, i.e. return -1, 0
or 1 depending on the order in which the two compared elements should
be sorted. EVP_PKEY_cmp() and EVP_PKEY_cmp_parameters() don't quite
do that.
Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
(Merged from https://github.com/openssl/openssl/pull/11158)
commit bee5d6cd3fa2f8bcc7e1153e4dc26aa26144bee0
Author: Richard Levitte <levitte at openssl.org>
Date: Wed Feb 5 12:53:14 2020 +0100
KEYMGMT: Add a keydata matching function
Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
(Merged from https://github.com/openssl/openssl/pull/11158)
commit 157ded39ee68c1c00814165f79f9b2f000996884
Author: Richard Levitte <levitte at openssl.org>
Date: Wed Feb 5 10:18:51 2020 +0100
EVP: Adapt EVP_PKEY_missing_parameters() for provider keys
Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
(Merged from https://github.com/openssl/openssl/pull/11158)
-----------------------------------------------------------------------
Summary of changes:
crypto/dsa/dsa_lib.c | 5 +
crypto/evp/evp_local.h | 2 +
crypto/evp/keymgmt_lib.c | 136 ++++++++++++++++++++
crypto/evp/keymgmt_meth.c | 24 ++++
crypto/evp/p_lib.c | 173 +++++++++++++++++++++++---
doc/man7/provider-keymgmt.pod | 19 ++-
include/crypto/dsa.h | 4 +
include/crypto/evp.h | 9 ++
include/openssl/core_numbers.h | 14 ++-
providers/implementations/keymgmt/dh_kmgmt.c | 21 ++++
providers/implementations/keymgmt/dsa_kmgmt.c | 23 ++++
providers/implementations/keymgmt/ec_kmgmt.c | 28 +++++
providers/implementations/keymgmt/rsa_kmgmt.c | 17 +++
13 files changed, 459 insertions(+), 16 deletions(-)
diff --git a/crypto/dsa/dsa_lib.c b/crypto/dsa/dsa_lib.c
index 4b048d48c5..154048a3a3 100644
--- a/crypto/dsa/dsa_lib.c
+++ b/crypto/dsa/dsa_lib.c
@@ -337,3 +337,8 @@ int DSA_bits(const DSA *dsa)
{
return BN_num_bits(dsa->params.p);
}
+
+FFC_PARAMS *dsa_get0_params(DSA *dsa)
+{
+ return &dsa->params;
+}
diff --git a/crypto/evp/evp_local.h b/crypto/evp/evp_local.h
index 9b4ab29fda..774db4da8f 100644
--- a/crypto/evp/evp_local.h
+++ b/crypto/evp/evp_local.h
@@ -85,12 +85,14 @@ struct evp_keymgmt_st {
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 {
diff --git a/crypto/evp/keymgmt_lib.c b/crypto/evp/keymgmt_lib.c
index a88d65dc5e..68ccdbb8ee 100644
--- a/crypto/evp/keymgmt_lib.c
+++ b/crypto/evp/keymgmt_lib.c
@@ -214,3 +214,139 @@ void *evp_keymgmt_util_fromdata(EVP_PKEY *target, EVP_KEYMGMT *keymgmt,
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;
+}
diff --git a/crypto/evp/keymgmt_meth.c b/crypto/evp/keymgmt_meth.c
index 3fcc073a5a..f80e6e29b5 100644
--- a/crypto/evp/keymgmt_meth.c
+++ b/crypto/evp/keymgmt_meth.c
@@ -95,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++;
@@ -290,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[])
{
@@ -321,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);
+}
diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c
index 621d99d171..586ffaf041 100644
--- a/crypto/evp/p_lib.c
+++ b/crypto/evp/p_lib.c
@@ -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);
}
@@ -870,7 +1015,7 @@ int EVP_PKEY_up_ref(EVP_PKEY *pkey)
static void evp_pkey_free_legacy(EVP_PKEY *x)
{
if (x->ameth != NULL) {
- if (x->ameth->pkey_free)
+ if (x->ameth->pkey_free != NULL)
x->ameth->pkey_free(x);
x->pkey.ptr = NULL;
x->ameth = NULL;
diff --git a/doc/man7/provider-keymgmt.pod b/doc/man7/provider-keymgmt.pod
index 5141ffdebc..91b87cecdc 100644
--- a/doc/man7/provider-keymgmt.pod
+++ b/doc/man7/provider-keymgmt.pod
@@ -26,6 +26,8 @@ provider-keymgmt - The KEYMGMT library E<lt>-E<gt> provider functions
/* Key object content checks */
int OP_keymgmt_has(void *keydata, int selection);
+ int OP_keymgmt_match(const void *keydata1, const void *keydata2,
+ int selection);
/* Discovery of supported operations */
const char *OP_keymgmt_query_operation_name(int operation_id);
@@ -37,6 +39,9 @@ provider-keymgmt - The KEYMGMT library E<lt>-E<gt> provider functions
OSSL_CALLBACK *param_cb, void *cbarg);
const OSSL_PARAM *OP_keymgmt_export_types(int selection);
+ /* Key object copy */
+ int OP_keymgmt_copy(void *keydata_to, const void *keydata_from, int selection);
+
/* Key object validation */
int OP_keymgmt_validate(void *keydata, int selection);
@@ -84,12 +89,14 @@ macros in L<openssl-core_numbers.h(7)>, as follows:
OP_keymgmt_has OSSL_FUNC_KEYMGMT_HAS
OP_keymgmt_validate OSSL_FUNC_KEYMGMT_VALIDATE
+ OP_keymgmt_match OSSL_FUNC_KEYMGMT_MATCH
OP_keymgmt_import OSSL_FUNC_KEYMGMT_IMPORT
OP_keymgmt_import_types OSSL_FUNC_KEYMGMT_IMPORT_TYPES
OP_keymgmt_export OSSL_FUNC_KEYMGMT_EXPORT
OP_keymgmt_export_types OSSL_FUNC_KEYMGMT_EXPORT_TYPES
+ OP_keymgmt_copy OSSL_FUNC_KEYMGMT_COPY
=head2 Key Objects
@@ -239,7 +246,12 @@ B<OSSL_KEYMGMT_SELECT_PUBLIC_KEY> (or B<OSSL_KEYMGMT_SELECT_KEYPAIR>
for short) is expected to check that the pairwise consistency of
I<keydata> is valid.
-=head2 Key Object Import and Export Functions
+OP_keymgmt_match() should check if the data subset indicated by
+I<selection> in I<keydata1> and I<keydata2> match. It is assumed that
+the caller has ensured that I<keydata1> and I<keydata2> are both owned
+by the implementation of this function.
+
+=head2 Key Object Import, Export and Copy Functions
OP_keymgmt_import() should import data indicated by I<selection> into
I<keydata> with values taken from the B<OSSL_PARAM> array I<params>.
@@ -256,6 +268,11 @@ OP_keymgmt_export_types() should return a constant array of descriptor
B<OSSL_PARAM> for data indicated by I<selection>, that the
OP_keymgmt_export() callback can expect to receive.
+OP_keymgmt_copy() should copy data subsets indicated by I<selection>
+from I<keydata_from> to I<keydata_to>. It is assumed that the caller
+has ensured that I<keydata_to> and I<keydata_from> are both owned by
+the implementation of this function.
+
=head2 Built-in RSA Import/Export Types
The following Import/Export types are available for the built-in RSA algorithm:
diff --git a/include/crypto/dsa.h b/include/crypto/dsa.h
index 1da23a8a7b..eab5d44603 100644
--- a/include/crypto/dsa.h
+++ b/include/crypto/dsa.h
@@ -8,6 +8,7 @@
*/
#include <openssl/dsa.h>
+#include "internal/ffc.h"
#define DSA_PARAMGEN_TYPE_FIPS_186_2 1 /* Use legacy FIPS186-2 standard */
#define DSA_PARAMGEN_TYPE_FIPS_186_4 2 /* Use FIPS186-4 standard */
@@ -21,6 +22,9 @@ int dsa_generate_ffc_parameters(DSA *dsa, int type,
int dsa_sign_int(int type, const unsigned char *dgst,
int dlen, unsigned char *sig, unsigned int *siglen, DSA *dsa);
const unsigned char *dsa_algorithmidentifier_encoding(int md_nid, size_t *len);
+
+FFC_PARAMS *dsa_get0_params(DSA *dsa);
+
int dsa_generate_public_key(BN_CTX *ctx, const DSA *dsa, const BIGNUM *priv_key,
BIGNUM *pub_key);
int dsa_check_params(const DSA *dsa, int *ret);
diff --git a/include/crypto/evp.h b/include/crypto/evp.h
index ddba4083e9..7da0258279 100644
--- a/include/crypto/evp.h
+++ b/include/crypto/evp.h
@@ -619,6 +619,9 @@ int evp_keymgmt_util_cache_keydata(EVP_PKEY *pk, size_t index,
void evp_keymgmt_util_cache_keyinfo(EVP_PKEY *pk);
void *evp_keymgmt_util_fromdata(EVP_PKEY *target, EVP_KEYMGMT *keymgmt,
int selection, const OSSL_PARAM params[]);
+int evp_keymgmt_util_has(EVP_PKEY *pk, int selection);
+int evp_keymgmt_util_match(EVP_PKEY *pk1, EVP_PKEY *pk2, int selection);
+int evp_keymgmt_util_copy(EVP_PKEY *to, EVP_PKEY *from, int selection);
/*
@@ -637,6 +640,9 @@ const OSSL_PARAM *evp_keymgmt_settable_params(const EVP_KEYMGMT *keymgmt);
int evp_keymgmt_has(const EVP_KEYMGMT *keymgmt, void *keyddata, int selection);
int evp_keymgmt_validate(const EVP_KEYMGMT *keymgmt, void *keydata,
int selection);
+int evp_keymgmt_match(const EVP_KEYMGMT *keymgmt,
+ const void *keydata1, const void *keydata2,
+ int selection);
int evp_keymgmt_import(const EVP_KEYMGMT *keymgmt, void *keydata,
int selection, const OSSL_PARAM params[]);
@@ -646,6 +652,9 @@ int evp_keymgmt_export(const EVP_KEYMGMT *keymgmt, void *keydata,
int selection, OSSL_CALLBACK *param_cb, void *cbarg);
const OSSL_PARAM *evp_keymgmt_export_types(const EVP_KEYMGMT *keymgmt,
int selection);
+int evp_keymgmt_copy(const EVP_KEYMGMT *keymgmt,
+ void *keydata_to, const void *keydata_from,
+ int selection);
/* Pulling defines out of C source files */
diff --git a/include/openssl/core_numbers.h b/include/openssl/core_numbers.h
index 3fd462a8d6..3314a0f665 100644
--- a/include/openssl/core_numbers.h
+++ b/include/openssl/core_numbers.h
@@ -412,7 +412,13 @@ OSSL_CORE_MAKE_FUNC(int, OP_keymgmt_has, (void *keydata, int selection))
# define OSSL_FUNC_KEYMGMT_VALIDATE 22
OSSL_CORE_MAKE_FUNC(int, OP_keymgmt_validate, (void *keydata, int selection))
-/* Import and export functions, with ddiscovery */
+/* Key checks - matching */
+# define OSSL_FUNC_KEYMGMT_MATCH 23
+OSSL_CORE_MAKE_FUNC(int, OP_keymgmt_match,
+ (const void *keydata1, const void *keydata2,
+ int selection))
+
+/* Import and export functions, with discovery */
# define OSSL_FUNC_KEYMGMT_IMPORT 40
# define OSSL_FUNC_KEYMGMT_IMPORT_TYPES 41
# define OSSL_FUNC_KEYMGMT_EXPORT 42
@@ -427,6 +433,12 @@ OSSL_CORE_MAKE_FUNC(int, OP_keymgmt_export,
OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, OP_keymgmt_export_types,
(int selection))
+/* Copy function, only works for matching keymgmt */
+# define OSSL_FUNC_KEYMGMT_COPY 44
+OSSL_CORE_MAKE_FUNC(int, OP_keymgmt_copy,
+ ( void *keydata_to, const void *keydata_from,
+ int selection))
+
/* Key Exchange */
# define OSSL_FUNC_KEYEXCH_NEWCTX 1
diff --git a/providers/implementations/keymgmt/dh_kmgmt.c b/providers/implementations/keymgmt/dh_kmgmt.c
index f4f04eeab8..90a583e7db 100644
--- a/providers/implementations/keymgmt/dh_kmgmt.c
+++ b/providers/implementations/keymgmt/dh_kmgmt.c
@@ -29,6 +29,7 @@ static OSSL_OP_keymgmt_free_fn dh_freedata;
static OSSL_OP_keymgmt_get_params_fn dh_get_params;
static OSSL_OP_keymgmt_gettable_params_fn dh_gettable_params;
static OSSL_OP_keymgmt_has_fn dh_has;
+static OSSL_OP_keymgmt_match_fn dh_match;
static OSSL_OP_keymgmt_import_fn dh_import;
static OSSL_OP_keymgmt_import_types_fn dh_import_types;
static OSSL_OP_keymgmt_export_fn dh_export;
@@ -169,6 +170,25 @@ static int dh_has(void *keydata, int selection)
return ok;
}
+static int dh_match(const void *keydata1, const void *keydata2, int selection)
+{
+ const DH *dh1 = keydata1;
+ const DH *dh2 = keydata2;
+ int ok = 1;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
+ ok = ok && BN_cmp(DH_get0_pub_key(dh1), DH_get0_pub_key(dh2)) == 0;
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
+ ok = ok && BN_cmp(DH_get0_priv_key(dh1), DH_get0_priv_key(dh2)) == 0;
+ if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
+ FFC_PARAMS *dhparams1 = dh_get0_params((DH *)dh1);
+ FFC_PARAMS *dhparams2 = dh_get0_params((DH *)dh2);
+
+ ok = ok && ffc_params_cmp(dhparams1, dhparams2, 1);
+ }
+ return ok;
+}
+
static int dh_import(void *keydata, int selection, const OSSL_PARAM params[])
{
DH *dh = keydata;
@@ -302,6 +322,7 @@ const OSSL_DISPATCH dh_keymgmt_functions[] = {
{ OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))dh_get_params },
{ OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))dh_gettable_params },
{ OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))dh_has },
+ { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))dh_match },
{ OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))dh_import },
{ OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))dh_import_types },
{ OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))dh_export },
diff --git a/providers/implementations/keymgmt/dsa_kmgmt.c b/providers/implementations/keymgmt/dsa_kmgmt.c
index 0781f13760..494f284111 100644
--- a/providers/implementations/keymgmt/dsa_kmgmt.c
+++ b/providers/implementations/keymgmt/dsa_kmgmt.c
@@ -29,6 +29,7 @@ static OSSL_OP_keymgmt_free_fn dsa_freedata;
static OSSL_OP_keymgmt_get_params_fn dsa_get_params;
static OSSL_OP_keymgmt_gettable_params_fn dsa_gettable_params;
static OSSL_OP_keymgmt_has_fn dsa_has;
+static OSSL_OP_keymgmt_match_fn dsa_match;
static OSSL_OP_keymgmt_import_fn dsa_import;
static OSSL_OP_keymgmt_import_types_fn dsa_import_types;
static OSSL_OP_keymgmt_export_fn dsa_export;
@@ -175,6 +176,27 @@ static int dsa_has(void *keydata, int selection)
return ok;
}
+static int dsa_match(const void *keydata1, const void *keydata2, int selection)
+{
+ const DSA *dsa1 = keydata1;
+ const DSA *dsa2 = keydata2;
+ int ok = 1;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
+ ok = ok
+ && BN_cmp(DSA_get0_pub_key(dsa1), DSA_get0_pub_key(dsa2)) == 0;
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
+ ok = ok
+ && BN_cmp(DSA_get0_priv_key(dsa1), DSA_get0_priv_key(dsa2)) == 0;
+ if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
+ FFC_PARAMS *dsaparams1 = dsa_get0_params((DSA *)dsa1);
+ FFC_PARAMS *dsaparams2 = dsa_get0_params((DSA *)dsa2);
+
+ ok = ok && ffc_params_cmp(dsaparams1, dsaparams2, 1);
+ }
+ return ok;
+}
+
static int dsa_import(void *keydata, int selection, const OSSL_PARAM params[])
{
DSA *dsa = keydata;
@@ -313,6 +335,7 @@ const OSSL_DISPATCH dsa_keymgmt_functions[] = {
{ OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))dsa_get_params },
{ OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))dsa_gettable_params },
{ OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))dsa_has },
+ { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))dsa_match },
{ OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))dsa_import },
{ OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))dsa_import_types },
{ OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))dsa_export },
diff --git a/providers/implementations/keymgmt/ec_kmgmt.c b/providers/implementations/keymgmt/ec_kmgmt.c
index 794dd92499..6a358aa93b 100644
--- a/providers/implementations/keymgmt/ec_kmgmt.c
+++ b/providers/implementations/keymgmt/ec_kmgmt.c
@@ -31,6 +31,7 @@ static OSSL_OP_keymgmt_gettable_params_fn ec_gettable_params;
static OSSL_OP_keymgmt_set_params_fn ec_set_params;
static OSSL_OP_keymgmt_settable_params_fn ec_settable_params;
static OSSL_OP_keymgmt_has_fn ec_has;
+static OSSL_OP_keymgmt_match_fn ec_match;
static OSSL_OP_keymgmt_import_fn ec_import;
static OSSL_OP_keymgmt_import_types_fn ec_import_types;
static OSSL_OP_keymgmt_export_fn ec_export;
@@ -442,6 +443,32 @@ int ec_has(void *keydata, int selection)
return ok;
}
+static int ec_match(const void *keydata1, const void *keydata2, int selection)
+{
+ const EC_KEY *ec1 = keydata1;
+ const EC_KEY *ec2 = keydata2;
+ const EC_GROUP *group_a = EC_KEY_get0_group(ec1);
+ const EC_GROUP *group_b = EC_KEY_get0_group(ec2);
+ int ok = 1;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
+ ok = ok && group_a != NULL && group_b != NULL
+ && EC_GROUP_cmp(group_a, group_b, NULL) == 0;
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
+ const BIGNUM *pa = EC_KEY_get0_private_key(ec1);
+ const BIGNUM *pb = EC_KEY_get0_private_key(ec2);
+
+ ok = ok && BN_cmp(pa, pb) == 0;
+ }
+ if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
+ const EC_POINT *pa = EC_KEY_get0_public_key(ec1);
+ const EC_POINT *pb = EC_KEY_get0_public_key(ec2);
+
+ ok = ok && EC_POINT_cmp(group_b, pa, pb, NULL);
+ }
+ return ok;
+}
+
static
int ec_import(void *keydata, int selection, const OSSL_PARAM params[])
{
@@ -711,6 +738,7 @@ const OSSL_DISPATCH ec_keymgmt_functions[] = {
{ OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))ec_set_params },
{ OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))ec_settable_params },
{ OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ec_has },
+ { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ec_match },
{ OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))ec_import },
{ OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ec_import_types },
{ OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ec_export },
diff --git a/providers/implementations/keymgmt/rsa_kmgmt.c b/providers/implementations/keymgmt/rsa_kmgmt.c
index 8f3f25eb60..8c7673ad49 100644
--- a/providers/implementations/keymgmt/rsa_kmgmt.c
+++ b/providers/implementations/keymgmt/rsa_kmgmt.c
@@ -32,6 +32,7 @@ static OSSL_OP_keymgmt_free_fn rsa_freedata;
static OSSL_OP_keymgmt_get_params_fn rsa_get_params;
static OSSL_OP_keymgmt_gettable_params_fn rsa_gettable_params;
static OSSL_OP_keymgmt_has_fn rsa_has;
+static OSSL_OP_keymgmt_match_fn rsa_match;
static OSSL_OP_keymgmt_validate_fn rsa_validate;
static OSSL_OP_keymgmt_import_fn rsa_import;
static OSSL_OP_keymgmt_import_types_fn rsa_import_types;
@@ -203,6 +204,21 @@ static int rsa_has(void *keydata, int selection)
return ok;
}
+static int rsa_match(const void *keydata1, const void *keydata2, int selection)
+{
+ const RSA *rsa1 = keydata1;
+ const RSA *rsa2 = keydata2;
+ int ok = 1;
+
+ /* There is always an |e| */
+ ok = ok && BN_cmp(RSA_get0_e(rsa1), RSA_get0_e(rsa2)) == 0;
+ if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
+ ok = ok && BN_cmp(RSA_get0_n(rsa1), RSA_get0_n(rsa2)) == 0;
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
+ ok = ok && BN_cmp(RSA_get0_d(rsa1), RSA_get0_d(rsa2)) == 0;
+ return ok;
+}
+
static int rsa_import(void *keydata, int selection, const OSSL_PARAM params[])
{
RSA *rsa = keydata;
@@ -399,6 +415,7 @@ const OSSL_DISPATCH rsa_keymgmt_functions[] = {
{ OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))rsa_get_params },
{ OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))rsa_gettable_params },
{ OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))rsa_has },
+ { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))rsa_match },
{ OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))rsa_validate },
{ OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))rsa_import },
{ OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))rsa_import_types },
More information about the openssl-commits
mailing list