summaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorTomas Mraz <tomas@openssl.org>2021-04-08 18:25:26 +0200
committerTomas Mraz <tomas@openssl.org>2021-04-15 09:19:39 +0200
commitb4f447c038c05260491eb880e4a9c420b476c119 (patch)
tree1f77cb414be14032b47264c1c98356c9398b4516 /crypto
parent4a9fe33c8e12f4fefae0471c0834f8e674dc7e4e (diff)
Add selection support to the provider keymgmt_dup function
Reviewed-by: Shane Lontis <shane.lontis@oracle.com> (Merged from https://github.com/openssl/openssl/pull/14793)
Diffstat (limited to 'crypto')
-rw-r--r--crypto/dh/dh_ameth.c2
-rw-r--r--crypto/dh/dh_backend.c15
-rw-r--r--crypto/dsa/dsa_ameth.c2
-rw-r--r--crypto/dsa/dsa_backend.c14
-rw-r--r--crypto/ec/ec_backend.c88
-rw-r--r--crypto/ec/ec_key.c12
-rw-r--r--crypto/ec/ecx_backend.c8
-rw-r--r--crypto/ec/ecx_meth.c2
-rw-r--r--crypto/evp/keymgmt_lib.c7
-rw-r--r--crypto/evp/keymgmt_meth.c5
-rw-r--r--crypto/rsa/rsa_ameth.c2
-rw-r--r--crypto/rsa/rsa_backend.c50
12 files changed, 155 insertions, 52 deletions
diff --git a/crypto/dh/dh_ameth.c b/crypto/dh/dh_ameth.c
index 1e72561d25..d96b54285b 100644
--- a/crypto/dh/dh_ameth.c
+++ b/crypto/dh/dh_ameth.c
@@ -543,7 +543,7 @@ static int dh_pkey_copy(EVP_PKEY *to, EVP_PKEY *from)
int ret;
if (dh != NULL) {
- dupkey = ossl_dh_dup(dh);
+ dupkey = ossl_dh_dup(dh, OSSL_KEYMGMT_SELECT_ALL);
if (dupkey == NULL)
return 0;
}
diff --git a/crypto/dh/dh_backend.c b/crypto/dh/dh_backend.c
index aebb38d1c9..18cf3f5992 100644
--- a/crypto/dh/dh_backend.c
+++ b/crypto/dh/dh_backend.c
@@ -125,7 +125,7 @@ static ossl_inline int dh_bn_dup_check(BIGNUM **out, const BIGNUM *f)
return 1;
}
-DH *ossl_dh_dup(const DH *dh)
+DH *ossl_dh_dup(const DH *dh, int selection)
{
DH *dupkey = NULL;
@@ -139,14 +139,20 @@ DH *ossl_dh_dup(const DH *dh)
return NULL;
dupkey->length = DH_get_length(dh);
- if (!ossl_ffc_params_copy(&dupkey->params, &dh->params))
+ if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0
+ && !ossl_ffc_params_copy(&dupkey->params, &dh->params))
goto err;
dupkey->flags = dh->flags;
- if (!dh_bn_dup_check(&dupkey->pub_key, dh->pub_key))
+ if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0
+ && ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0
+ || !dh_bn_dup_check(&dupkey->pub_key, dh->pub_key)))
goto err;
- if (!dh_bn_dup_check(&dupkey->priv_key, dh->priv_key))
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0
+ && ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0
+ || !dh_bn_dup_check(&dupkey->priv_key, dh->priv_key)))
goto err;
#ifndef FIPS_MODULE
@@ -161,6 +167,7 @@ DH *ossl_dh_dup(const DH *dh)
DH_free(dupkey);
return NULL;
}
+
#ifndef FIPS_MODULE
DH *ossl_dh_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf,
OSSL_LIB_CTX *libctx, const char *propq)
diff --git a/crypto/dsa/dsa_ameth.c b/crypto/dsa/dsa_ameth.c
index 0844e9be09..2e1ad081dc 100644
--- a/crypto/dsa/dsa_ameth.c
+++ b/crypto/dsa/dsa_ameth.c
@@ -507,7 +507,7 @@ static int dsa_pkey_copy(EVP_PKEY *to, EVP_PKEY *from)
int ret;
if (dsa != NULL) {
- dupkey = ossl_dsa_dup(dsa);
+ dupkey = ossl_dsa_dup(dsa, OSSL_KEYMGMT_SELECT_ALL);
if (dupkey == NULL)
return 0;
}
diff --git a/crypto/dsa/dsa_backend.c b/crypto/dsa/dsa_backend.c
index 856203a200..2ef8cbc9f3 100644
--- a/crypto/dsa/dsa_backend.c
+++ b/crypto/dsa/dsa_backend.c
@@ -64,7 +64,7 @@ static ossl_inline int dsa_bn_dup_check(BIGNUM **out, const BIGNUM *f)
return 1;
}
-DSA *ossl_dsa_dup(const DSA *dsa)
+DSA *ossl_dsa_dup(const DSA *dsa, int selection)
{
DSA *dupkey = NULL;
@@ -77,14 +77,20 @@ DSA *ossl_dsa_dup(const DSA *dsa)
if ((dupkey = ossl_dsa_new(dsa->libctx)) == NULL)
return NULL;
- if (!ossl_ffc_params_copy(&dupkey->params, &dsa->params))
+ if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0
+ && !ossl_ffc_params_copy(&dupkey->params, &dsa->params))
goto err;
dupkey->flags = dsa->flags;
- if (!dsa_bn_dup_check(&dupkey->pub_key, dsa->pub_key))
+ if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0
+ && ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0
+ || !dsa_bn_dup_check(&dupkey->pub_key, dsa->pub_key)))
goto err;
- if (!dsa_bn_dup_check(&dupkey->priv_key, dsa->priv_key))
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0
+ && ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0
+ || !dsa_bn_dup_check(&dupkey->priv_key, dsa->priv_key)))
goto err;
#ifndef FIPS_MODULE
diff --git a/crypto/ec/ec_backend.c b/crypto/ec/ec_backend.c
index 9716ffc2f2..0189a33a91 100644
--- a/crypto/ec/ec_backend.c
+++ b/crypto/ec/ec_backend.c
@@ -17,6 +17,7 @@
#include <openssl/objects.h>
#include <openssl/params.h>
#include <openssl/err.h>
+#include <openssl/engine.h>
#include "crypto/bn.h"
#include "crypto/ec.h"
#include "ec_local.h"
@@ -519,6 +520,93 @@ int ossl_ec_key_otherparams_fromdata(EC_KEY *ec, const OSSL_PARAM params[])
return 1;
}
+EC_KEY *ossl_ec_key_dup(const EC_KEY *src, int selection)
+{
+ EC_KEY *ret = ossl_ec_key_new_method_int(src->libctx, src->propq,
+ src->engine);
+
+ if (ret == NULL)
+ return NULL;
+
+ if (src == NULL) {
+ ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
+ goto err;
+ }
+
+ /* copy the parameters */
+ if (src->group != NULL
+ && (selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
+ ret->group = ossl_ec_group_new_ex(src->libctx, src->propq,
+ src->group->meth);
+ if (ret->group == NULL
+ || !EC_GROUP_copy(ret->group, src->group))
+ goto err;
+
+ if (src->meth != NULL) {
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
+ if (src->engine != NULL && ENGINE_init(src->engine) == 0)
+ goto err;
+ ret->engine = src->engine;
+#endif
+ ret->meth = src->meth;
+ }
+ }
+
+ /* copy the public key */
+ if (src->pub_key != NULL
+ && (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
+ if (ret->group == NULL)
+ /* no parameter-less keys allowed */
+ goto err;
+ ret->pub_key = EC_POINT_new(ret->group);
+ if (ret->pub_key == NULL
+ || !EC_POINT_copy(ret->pub_key, src->pub_key))
+ goto err;
+ }
+
+ /* copy the private key */
+ if (src->priv_key != NULL
+ && (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
+ if (ret->group == NULL)
+ /* no parameter-less keys allowed */
+ goto err;
+ ret->priv_key = BN_new();
+ if (ret->priv_key == NULL || !BN_copy(ret->priv_key, src->priv_key))
+ goto err;
+ if (ret->group->meth->keycopy
+ && ret->group->meth->keycopy(ret, src) == 0)
+ goto err;
+ }
+
+ /* copy the rest */
+ if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0) {
+ ret->enc_flag = src->enc_flag;
+ ret->conv_form = src->conv_form;
+ }
+
+ ret->version = src->version;
+ ret->flags = src->flags;
+
+#ifndef FIPS_MODULE
+ if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_EC_KEY,
+ &ret->ex_data, &src->ex_data))
+ goto err;
+#endif
+
+ if (ret->meth != NULL && ret->meth->copy != NULL) {
+ if ((selection
+ & OSSL_KEYMGMT_SELECT_KEYPAIR) != OSSL_KEYMGMT_SELECT_KEYPAIR)
+ goto err;
+ if (ret->meth->copy(ret, src) == 0)
+ goto err;
+ }
+
+ return ret;
+ err:
+ EC_KEY_free(ret);
+ return NULL;
+}
+
int ossl_ec_encoding_param2id(const OSSL_PARAM *p, int *id)
{
const char *name = NULL;
diff --git a/crypto/ec/ec_key.c b/crypto/ec/ec_key.c
index 50b53f97ed..f06715fa6b 100644
--- a/crypto/ec/ec_key.c
+++ b/crypto/ec/ec_key.c
@@ -184,17 +184,7 @@ EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src)
EC_KEY *EC_KEY_dup(const EC_KEY *ec_key)
{
- EC_KEY *ret = ossl_ec_key_new_method_int(ec_key->libctx, ec_key->propq,
- ec_key->engine);
-
- if (ret == NULL)
- return NULL;
-
- if (EC_KEY_copy(ret, ec_key) == NULL) {
- EC_KEY_free(ret);
- return NULL;
- }
- return ret;
+ return ossl_ec_key_dup(ec_key, OSSL_KEYMGMT_SELECT_ALL);
}
int EC_KEY_up_ref(EC_KEY *r)
diff --git a/crypto/ec/ecx_backend.c b/crypto/ec/ecx_backend.c
index d3ffb13916..3a1314626b 100644
--- a/crypto/ec/ecx_backend.c
+++ b/crypto/ec/ecx_backend.c
@@ -92,7 +92,7 @@ int ossl_ecx_key_fromdata(ECX_KEY *ecx, const OSSL_PARAM params[],
return 1;
}
-ECX_KEY *ossl_ecx_key_dup(const ECX_KEY *key)
+ECX_KEY *ossl_ecx_key_dup(const ECX_KEY *key, int selection)
{
ECX_KEY *ret = OPENSSL_zalloc(sizeof(*ret));
@@ -119,9 +119,11 @@ ECX_KEY *ossl_ecx_key_dup(const ECX_KEY *key)
goto err;
}
- memcpy(ret->pubkey, key->pubkey, sizeof(ret->pubkey));
+ if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
+ memcpy(ret->pubkey, key->pubkey, sizeof(ret->pubkey));
- if (key->privkey != NULL) {
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0
+ && key->privkey != NULL) {
if (ossl_ecx_key_allocate_privkey(ret) == NULL)
goto err;
memcpy(ret->privkey, key->privkey, ret->keylen);
diff --git a/crypto/ec/ecx_meth.c b/crypto/ec/ecx_meth.c
index df4b620829..61f062a2f8 100644
--- a/crypto/ec/ecx_meth.c
+++ b/crypto/ec/ecx_meth.c
@@ -410,7 +410,7 @@ static int ecx_pkey_copy(EVP_PKEY *to, EVP_PKEY *from)
int ret;
if (ecx != NULL) {
- dupkey = ossl_ecx_key_dup(ecx);
+ dupkey = ossl_ecx_key_dup(ecx, OSSL_KEYMGMT_SELECT_ALL);
if (dupkey == NULL)
return 0;
}
diff --git a/crypto/evp/keymgmt_lib.c b/crypto/evp/keymgmt_lib.c
index ed9fb0db03..4300daa1f3 100644
--- a/crypto/evp/keymgmt_lib.c
+++ b/crypto/evp/keymgmt_lib.c
@@ -460,9 +460,10 @@ int evp_keymgmt_util_copy(EVP_PKEY *to, EVP_PKEY *from, int selection)
return 0;
}
} else if (to_keymgmt == from->keymgmt && to_keymgmt->dup != NULL
- && to_keydata == NULL
- && selection == OSSL_KEYMGMT_SELECT_ALL) {
- to_keydata = alloc_keydata = evp_keymgmt_dup(to_keymgmt, from->keydata);
+ && 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)) {
diff --git a/crypto/evp/keymgmt_meth.c b/crypto/evp/keymgmt_meth.c
index a1629bc37f..1a7945af09 100644
--- a/crypto/evp/keymgmt_meth.c
+++ b/crypto/evp/keymgmt_meth.c
@@ -477,10 +477,11 @@ int evp_keymgmt_copy(const EVP_KEYMGMT *keymgmt,
return keymgmt->copy(keydata_to, keydata_from, selection);
}
-void *evp_keymgmt_dup(const EVP_KEYMGMT *keymgmt, const void *keydata_from)
+void *evp_keymgmt_dup(const EVP_KEYMGMT *keymgmt, const void *keydata_from,
+ int selection)
{
/* We assume no dup if the implementation doesn't have a function */
if (keymgmt->dup == NULL)
return NULL;
- return keymgmt->dup(keydata_from);
+ return keymgmt->dup(keydata_from, selection);
}
diff --git a/crypto/rsa/rsa_ameth.c b/crypto/rsa/rsa_ameth.c
index 45e0000117..2f9d60a7b3 100644
--- a/crypto/rsa/rsa_ameth.c
+++ b/crypto/rsa/rsa_ameth.c
@@ -891,7 +891,7 @@ static int rsa_pkey_copy(EVP_PKEY *to, EVP_PKEY *from)
int ret;
if (rsa != NULL) {
- dupkey = ossl_rsa_dup(rsa);
+ dupkey = ossl_rsa_dup(rsa, OSSL_KEYMGMT_SELECT_ALL);
if (dupkey == NULL)
return 0;
}
diff --git a/crypto/rsa/rsa_backend.c b/crypto/rsa/rsa_backend.c
index 92be5f610a..192b3fdbf7 100644
--- a/crypto/rsa/rsa_backend.c
+++ b/crypto/rsa/rsa_backend.c
@@ -330,7 +330,7 @@ static ossl_inline int rsa_bn_dup_check(BIGNUM **out, const BIGNUM *f)
return 1;
}
-RSA *ossl_rsa_dup(const RSA *rsa)
+RSA *ossl_rsa_dup(const RSA *rsa, int selection)
{
RSA *dupkey = NULL;
#ifndef FIPS_MODULE
@@ -344,34 +344,42 @@ RSA *ossl_rsa_dup(const RSA *rsa)
if ((dupkey = ossl_rsa_new_with_ctx(rsa->libctx)) == NULL)
return NULL;
- /* private and public key */
- if (!rsa_bn_dup_check(&dupkey->n, rsa->n))
- goto err;
- if (!rsa_bn_dup_check(&dupkey->e, rsa->e))
- goto err;
- if (!rsa_bn_dup_check(&dupkey->d, rsa->d))
- goto err;
+ /* public key */
+ if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
+ if (!rsa_bn_dup_check(&dupkey->n, rsa->n))
+ goto err;
+ if (!rsa_bn_dup_check(&dupkey->e, rsa->e))
+ goto err;
+ }
- /* factors and crt params */
- if (!rsa_bn_dup_check(&dupkey->p, rsa->p))
- goto err;
- if (!rsa_bn_dup_check(&dupkey->q, rsa->q))
- goto err;
- if (!rsa_bn_dup_check(&dupkey->dmp1, rsa->dmp1))
- goto err;
- if (!rsa_bn_dup_check(&dupkey->dmq1, rsa->dmq1))
- goto err;
- if (!rsa_bn_dup_check(&dupkey->iqmp, rsa->iqmp))
- goto err;
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
+
+ /* private key */
+ if (!rsa_bn_dup_check(&dupkey->d, rsa->d))
+ goto err;
+
+ /* factors and crt params */
+ if (!rsa_bn_dup_check(&dupkey->p, rsa->p))
+ goto err;
+ if (!rsa_bn_dup_check(&dupkey->q, rsa->q))
+ goto err;
+ if (!rsa_bn_dup_check(&dupkey->dmp1, rsa->dmp1))
+ goto err;
+ if (!rsa_bn_dup_check(&dupkey->dmq1, rsa->dmq1))
+ goto err;
+ if (!rsa_bn_dup_check(&dupkey->iqmp, rsa->iqmp))
+ goto err;
+ }
dupkey->version = rsa->version;
dupkey->flags = rsa->flags;
+ /* we always copy the PSS parameters regardless of selection */
dupkey->pss_params = rsa->pss_params;
#ifndef FIPS_MODULE
/* multiprime */
- pnum = sk_RSA_PRIME_INFO_num(rsa->prime_infos);
- if (pnum > 0) {
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0
+ && (pnum = sk_RSA_PRIME_INFO_num(rsa->prime_infos)) > 0) {
dupkey->prime_infos = sk_RSA_PRIME_INFO_new_reserve(NULL, pnum);
for (i = 0; i < pnum; i++) {
const RSA_PRIME_INFO *pinfo = NULL;