+ /* An unassigned key can't be copied */
+ if (from == NULL || from->keydata == NULL)
+ return 0;
+
+ /*
+ * If |to| is unassigned, ensure it gets the same KEYMGMT as |from|,
+ * Note that the final setting of KEYMGMT is done further down, with
+ * EVP_PKEY_set_type_by_keymgmt(); we don't want to do that prematurely.
+ */
+ if (to_keymgmt == NULL)
+ to_keymgmt = from->keymgmt;
+
+ if (to_keymgmt == from->keymgmt && to_keymgmt->dup != NULL
+ && to_keydata == NULL) {
+ to_keydata = alloc_keydata = evp_keymgmt_dup(to_keymgmt,
+ from->keydata,
+ selection);
+ if (to_keydata == NULL)
+ return 0;
+ } else if (match_type(to_keymgmt, from->keymgmt)) {
+ struct evp_keymgmt_util_try_import_data_st import_data;
+
+ import_data.keymgmt = to_keymgmt;
+ import_data.keydata = to_keydata;
+ import_data.selection = selection;
+
+ if (!evp_keymgmt_util_export(from, selection,
+ &evp_keymgmt_util_try_import,
+ &import_data))
+ return 0;
+
+ /*
+ * In case to_keydata was previously unallocated,
+ * evp_keymgmt_util_try_import() may have created it for us.
+ */
+ if (to_keydata == NULL)
+ to_keydata = alloc_keydata = import_data.keydata;
+ } else {
+ ERR_raise(ERR_LIB_EVP, EVP_R_DIFFERENT_KEY_TYPES);
+ return 0;
+ }
+
+ /*
+ * We only need to set the |to| type when its |keymgmt| isn't set.
+ * We can then just set its |keydata| to what we have, which might
+ * be exactly what it had when entering this function.
+ * This is a bit different from using evp_keymgmt_util_assign_pkey(),
+ * which isn't as careful with |to|'s original |keymgmt|, since it's
+ * meant to forcibly reassign an EVP_PKEY no matter what, which is
+ * why we don't use that one here.
+ */
+ if (to->keymgmt == NULL
+ && !EVP_PKEY_set_type_by_keymgmt(to, to_keymgmt)) {
+ evp_keymgmt_freedata(to_keymgmt, alloc_keydata);
+ return 0;
+ }
+ to->keydata = to_keydata;
+ evp_keymgmt_util_cache_keyinfo(to);
+
+ return 1;
+}