summaryrefslogtreecommitdiff
path: root/crypto/evp/keymgmt_lib.c
diff options
context:
space:
mode:
authorRichard Levitte <levitte@openssl.org>2020-02-05 16:30:21 +0100
committerRichard Levitte <levitte@openssl.org>2020-03-02 03:27:03 +0100
commitff3b59e1705a40f7cfc6df8d788d08b0a525aa58 (patch)
treeff934479411cb20f3a2491b172023afbbca94795 /crypto/evp/keymgmt_lib.c
parent13697f1c62e98a4c1365fd85cb39ada0f47dce5f (diff)
downloadopenssl-new-ff3b59e1705a40f7cfc6df8d788d08b0a525aa58.tar.gz
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@oracle.com> (Merged from https://github.com/openssl/openssl/pull/11158)
Diffstat (limited to 'crypto/evp/keymgmt_lib.c')
-rw-r--r--crypto/evp/keymgmt_lib.c57
1 files changed, 57 insertions, 0 deletions
diff --git a/crypto/evp/keymgmt_lib.c b/crypto/evp/keymgmt_lib.c
index 6bbf28aa34..68ccdbb8ee 100644
--- a/crypto/evp/keymgmt_lib.c
+++ b/crypto/evp/keymgmt_lib.c
@@ -293,3 +293,60 @@ int evp_keymgmt_util_match(EVP_PKEY *pk1, EVP_PKEY *pk2, int selection)
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;
+}