diff options
author | Richard Levitte <levitte@openssl.org> | 2020-02-05 16:30:21 +0100 |
---|---|---|
committer | Richard Levitte <levitte@openssl.org> | 2020-03-02 03:27:03 +0100 |
commit | ff3b59e1705a40f7cfc6df8d788d08b0a525aa58 (patch) | |
tree | ff934479411cb20f3a2491b172023afbbca94795 /crypto/evp/keymgmt_lib.c | |
parent | 13697f1c62e98a4c1365fd85cb39ada0f47dce5f (diff) | |
download | openssl-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.c | 57 |
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; +} |