From: Tomas Mraz Date: Wed, 7 Apr 2021 17:35:13 +0000 (+0200) Subject: Implement provider-side keymgmt_dup function X-Git-Tag: openssl-3.0.0-alpha15~97 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4a9fe33c8e12f4fefae0471c0834f8e674dc7e4e;p=thirdparty%2Fopenssl.git Implement provider-side keymgmt_dup function To avoid mutating key data add OSSL_FUNC_KEYMGMT_DUP function to the provider API and implement it for all asym-key key managements. Use it when copying everything to an empty EVP_PKEY which is the case with EVP_PKEY_dup(). Fixes #14658 Reviewed-by: Shane Lontis (Merged from https://github.com/openssl/openssl/pull/14793) --- diff --git a/crypto/dh/dh_ameth.c b/crypto/dh/dh_ameth.c index 907a867eca..1e72561d25 100644 --- a/crypto/dh/dh_ameth.c +++ b/crypto/dh/dh_ameth.c @@ -536,46 +536,6 @@ static int dhx_pkey_import_from(const OSSL_PARAM params[], void *vpctx) return dh_pkey_import_from_type(params, vpctx, EVP_PKEY_DHX); } -static ossl_inline int dh_bn_dup_check(BIGNUM **out, const BIGNUM *f) -{ - if (f != NULL && (*out = BN_dup(f)) == NULL) - return 0; - return 1; -} - -static DH *dh_dup(const DH *dh) -{ - DH *dupkey = NULL; - - /* Do not try to duplicate foreign DH keys */ - if (ossl_dh_get_method(dh) != DH_OpenSSL()) - return NULL; - - if ((dupkey = ossl_dh_new_ex(dh->libctx)) == NULL) - return NULL; - - dupkey->length = DH_get_length(dh); - if (!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)) - goto err; - if (!dh_bn_dup_check(&dupkey->priv_key, dh->priv_key)) - goto err; - - if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_DH, - &dupkey->ex_data, &dh->ex_data)) - goto err; - - return dupkey; - - err: - DH_free(dupkey); - return NULL; -} - static int dh_pkey_copy(EVP_PKEY *to, EVP_PKEY *from) { DH *dh = from->pkey.dh; @@ -583,7 +543,7 @@ static int dh_pkey_copy(EVP_PKEY *to, EVP_PKEY *from) int ret; if (dh != NULL) { - dupkey = dh_dup(dh); + dupkey = ossl_dh_dup(dh); if (dupkey == NULL) return 0; } diff --git a/crypto/dh/dh_backend.c b/crypto/dh/dh_backend.c index 97f5271a5a..aebb38d1c9 100644 --- a/crypto/dh/dh_backend.c +++ b/crypto/dh/dh_backend.c @@ -17,6 +17,7 @@ #include #include "internal/param_build_set.h" #include "crypto/dh.h" +#include "dh_local.h" /* * The intention with the "backend" source file is to offer backend functions @@ -117,6 +118,49 @@ int ossl_dh_key_todata(DH *dh, OSSL_PARAM_BLD *bld, OSSL_PARAM params[]) return 1; } +static ossl_inline int dh_bn_dup_check(BIGNUM **out, const BIGNUM *f) +{ + if (f != NULL && (*out = BN_dup(f)) == NULL) + return 0; + return 1; +} + +DH *ossl_dh_dup(const DH *dh) +{ + DH *dupkey = NULL; + +#ifndef FIPS_MODULE + /* Do not try to duplicate foreign DH keys */ + if (ossl_dh_get_method(dh) != DH_OpenSSL()) + return NULL; +#endif + + if ((dupkey = ossl_dh_new_ex(dh->libctx)) == NULL) + return NULL; + + dupkey->length = DH_get_length(dh); + if (!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)) + goto err; + if (!dh_bn_dup_check(&dupkey->priv_key, dh->priv_key)) + goto err; + +#ifndef FIPS_MODULE + if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_DH, + &dupkey->ex_data, &dh->ex_data)) + goto err; +#endif + + return dupkey; + + err: + 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/dh/dh_lib.c b/crypto/dh/dh_lib.c index f5e0f893c1..92767a94c2 100644 --- a/crypto/dh/dh_lib.c +++ b/crypto/dh/dh_lib.c @@ -325,3 +325,5 @@ int ossl_dh_get0_nid(const DH *dh) { return dh->params.nid; } + + diff --git a/crypto/dsa/dsa_ameth.c b/crypto/dsa/dsa_ameth.c index 69964c053c..0844e9be09 100644 --- a/crypto/dsa/dsa_ameth.c +++ b/crypto/dsa/dsa_ameth.c @@ -500,45 +500,6 @@ static int dsa_pkey_import_from(const OSSL_PARAM params[], void *vpctx) return 1; } -static ossl_inline int dsa_bn_dup_check(BIGNUM **out, const BIGNUM *f) -{ - if (f != NULL && (*out = BN_dup(f)) == NULL) - return 0; - return 1; -} - -static DSA *dsa_dup(const DSA *dsa) -{ - DSA *dupkey = NULL; - - /* Do not try to duplicate foreign DSA keys */ - if (DSA_get_method((DSA *)dsa) != DSA_OpenSSL()) - return NULL; - - if ((dupkey = ossl_dsa_new(dsa->libctx)) == NULL) - return NULL; - - if (!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)) - goto err; - if (!dsa_bn_dup_check(&dupkey->priv_key, dsa->priv_key)) - goto err; - - if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_DSA, - &dupkey->ex_data, &dsa->ex_data)) - goto err; - - return dupkey; - - err: - DSA_free(dupkey); - return NULL; -} - static int dsa_pkey_copy(EVP_PKEY *to, EVP_PKEY *from) { DSA *dsa = from->pkey.dsa; @@ -546,7 +507,7 @@ static int dsa_pkey_copy(EVP_PKEY *to, EVP_PKEY *from) int ret; if (dsa != NULL) { - dupkey = dsa_dup(dsa); + dupkey = ossl_dsa_dup(dsa); if (dupkey == NULL) return 0; } diff --git a/crypto/dsa/dsa_backend.c b/crypto/dsa/dsa_backend.c index f3e54aeb13..856203a200 100644 --- a/crypto/dsa/dsa_backend.c +++ b/crypto/dsa/dsa_backend.c @@ -16,6 +16,7 @@ #include #include #include "crypto/dsa.h" +#include "dsa_local.h" /* * The intention with the "backend" source file is to offer backend support @@ -56,6 +57,49 @@ int ossl_dsa_key_fromdata(DSA *dsa, const OSSL_PARAM params[]) return 0; } +static ossl_inline int dsa_bn_dup_check(BIGNUM **out, const BIGNUM *f) +{ + if (f != NULL && (*out = BN_dup(f)) == NULL) + return 0; + return 1; +} + +DSA *ossl_dsa_dup(const DSA *dsa) +{ + DSA *dupkey = NULL; + +#ifndef FIPS_MODULE + /* Do not try to duplicate foreign DSA keys */ + if (DSA_get_method((DSA *)dsa) != DSA_OpenSSL()) + return NULL; +#endif + + if ((dupkey = ossl_dsa_new(dsa->libctx)) == NULL) + return NULL; + + if (!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)) + goto err; + if (!dsa_bn_dup_check(&dupkey->priv_key, dsa->priv_key)) + goto err; + +#ifndef FIPS_MODULE + if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_DSA, + &dupkey->ex_data, &dsa->ex_data)) + goto err; +#endif + + return dupkey; + + err: + DSA_free(dupkey); + return NULL; +} + #ifndef FIPS_MODULE DSA *ossl_dsa_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf, OSSL_LIB_CTX *libctx, const char *propq) diff --git a/crypto/dsa/dsa_lib.c b/crypto/dsa/dsa_lib.c index 5512b99ef1..f39c2aa21a 100644 --- a/crypto/dsa/dsa_lib.c +++ b/crypto/dsa/dsa_lib.c @@ -358,3 +358,4 @@ int ossl_dsa_ffc_params_fromdata(DSA *dsa, const OSSL_PARAM params[]) dsa->dirty_cnt++; return ret; } + diff --git a/crypto/ec/ecx_backend.c b/crypto/ec/ecx_backend.c index 8f8fdc7705..d3ffb13916 100644 --- a/crypto/ec/ecx_backend.c +++ b/crypto/ec/ecx_backend.c @@ -92,6 +92,49 @@ 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 *ret = OPENSSL_zalloc(sizeof(*ret)); + + if (ret == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + return NULL; + } + + ret->lock = CRYPTO_THREAD_lock_new(); + if (ret->lock == NULL) { + OPENSSL_free(ret); + return NULL; + } + + ret->libctx = key->libctx; + ret->haspubkey = key->haspubkey; + ret->keylen = key->keylen; + ret->type = key->type; + ret->references = 1; + + if (key->propq != NULL) { + ret->propq = OPENSSL_strdup(key->propq); + if (ret->propq == NULL) + goto err; + } + + memcpy(ret->pubkey, key->pubkey, sizeof(ret->pubkey)); + + if (key->privkey != NULL) { + if (ossl_ecx_key_allocate_privkey(ret) == NULL) + goto err; + memcpy(ret->privkey, key->privkey, ret->keylen); + } + + return ret; + +err: + ossl_ecx_key_free(ret); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + return NULL; +} + #ifndef FIPS_MODULE ECX_KEY *ossl_ecx_key_op(const X509_ALGOR *palg, const unsigned char *p, int plen, diff --git a/crypto/ec/ecx_key.c b/crypto/ec/ecx_key.c index 60d9f3cc9f..90253372ce 100644 --- a/crypto/ec/ecx_key.c +++ b/crypto/ec/ecx_key.c @@ -7,6 +7,7 @@ * https://www.openssl.org/source/license.html */ +#include #include #include "crypto/ecx.h" @@ -39,7 +40,6 @@ ECX_KEY *ossl_ecx_key_new(OSSL_LIB_CTX *libctx, ECX_KEY_TYPE type, int haspubkey if (propq != NULL) { ret->propq = OPENSSL_strdup(propq); - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); if (ret->propq == NULL) goto err; } @@ -96,3 +96,4 @@ unsigned char *ossl_ecx_key_allocate_privkey(ECX_KEY *key) return key->privkey; } + diff --git a/crypto/ec/ecx_meth.c b/crypto/ec/ecx_meth.c index 609d8609ea..df4b620829 100644 --- a/crypto/ec/ecx_meth.c +++ b/crypto/ec/ecx_meth.c @@ -406,16 +406,18 @@ static int ecx_generic_import_from(const OSSL_PARAM params[], void *vpctx, static int ecx_pkey_copy(EVP_PKEY *to, EVP_PKEY *from) { - ECX_KEY *ecx = from->pkey.ecx; + ECX_KEY *ecx = from->pkey.ecx, *dupkey = NULL; int ret; - /* We can do just up-ref as ECX keys are immutable */ - if (ecx != NULL && !ossl_ecx_key_up_ref(ecx)) - return 0; + if (ecx != NULL) { + dupkey = ossl_ecx_key_dup(ecx); + if (dupkey == NULL) + return 0; + } - ret = EVP_PKEY_assign(to, from->type, ecx); + ret = EVP_PKEY_assign(to, from->type, dupkey); if (!ret) - ossl_ecx_key_free(ecx); + ossl_ecx_key_free(dupkey); return ret; } diff --git a/crypto/evp/evp_local.h b/crypto/evp/evp_local.h index 72caf86aaf..1b92668a20 100644 --- a/crypto/evp/evp_local.h +++ b/crypto/evp/evp_local.h @@ -113,6 +113,7 @@ struct evp_keymgmt_st { OSSL_FUNC_keymgmt_export_fn *export; OSSL_FUNC_keymgmt_export_types_fn *export_types; OSSL_FUNC_keymgmt_copy_fn *copy; + OSSL_FUNC_keymgmt_dup_fn *dup; } /* EVP_KEYMGMT */ ; struct evp_keyexch_st { diff --git a/crypto/evp/keymgmt_lib.c b/crypto/evp/keymgmt_lib.c index 872a63ae47..ed9fb0db03 100644 --- a/crypto/evp/keymgmt_lib.c +++ b/crypto/evp/keymgmt_lib.c @@ -459,6 +459,12 @@ int evp_keymgmt_util_copy(EVP_PKEY *to, EVP_PKEY *from, int selection) evp_keymgmt_freedata(to_keymgmt, alloc_keydata); 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); + if (to_keydata == NULL) + return 0; } else if (match_type(to_keymgmt, from->keymgmt)) { struct evp_keymgmt_util_try_import_data_st import_data; diff --git a/crypto/evp/keymgmt_meth.c b/crypto/evp/keymgmt_meth.c index cdd7c70ed9..a1629bc37f 100644 --- a/crypto/evp/keymgmt_meth.c +++ b/crypto/evp/keymgmt_meth.c @@ -133,6 +133,10 @@ static void *keymgmt_from_algorithm(int name_id, if (keymgmt->copy == NULL) keymgmt->copy = OSSL_FUNC_keymgmt_copy(fns); break; + case OSSL_FUNC_KEYMGMT_DUP: + if (keymgmt->dup == NULL) + keymgmt->dup = OSSL_FUNC_keymgmt_dup(fns); + break; case OSSL_FUNC_KEYMGMT_VALIDATE: if (keymgmt->validate == NULL) keymgmt->validate = OSSL_FUNC_keymgmt_validate(fns); @@ -472,3 +476,11 @@ int evp_keymgmt_copy(const EVP_KEYMGMT *keymgmt, return 0; return keymgmt->copy(keydata_to, keydata_from, selection); } + +void *evp_keymgmt_dup(const EVP_KEYMGMT *keymgmt, const void *keydata_from) +{ + /* We assume no dup if the implementation doesn't have a function */ + if (keymgmt->dup == NULL) + return NULL; + return keymgmt->dup(keydata_from); +} diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c index 0fc3af494f..04d9c80bd3 100644 --- a/crypto/evp/p_lib.c +++ b/crypto/evp/p_lib.c @@ -1857,7 +1857,7 @@ void *evp_pkey_export_to_provider(EVP_PKEY *pk, OSSL_LIB_CTX *libctx, /* Synchronize the dirty count */ pk->dirty_cnt_copy = pk->ameth->dirty_cnt(pk); - + CRYPTO_THREAD_unlock(pk->lock); goto end; } diff --git a/crypto/rsa/rsa_ameth.c b/crypto/rsa/rsa_ameth.c index e633fa5c93..45e0000117 100644 --- a/crypto/rsa/rsa_ameth.c +++ b/crypto/rsa/rsa_ameth.c @@ -884,98 +884,6 @@ static int rsa_pss_pkey_import_from(const OSSL_PARAM params[], void *vpctx) return rsa_int_import_from(params, vpctx, RSA_FLAG_TYPE_RSASSAPSS); } -static ossl_inline int rsa_bn_dup_check(BIGNUM **out, const BIGNUM *f) -{ - if (f != NULL && (*out = BN_dup(f)) == NULL) - return 0; - return 1; -} - -static RSA *rsa_dup(const RSA *rsa) -{ - RSA *dupkey = NULL; - int pnum, i; - - /* Do not try to duplicate foreign RSA keys */ - if (RSA_get_method(rsa) != RSA_PKCS1_OpenSSL()) - return NULL; - - 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; - - /* 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; - - /* multiprime */ - pnum = sk_RSA_PRIME_INFO_num(rsa->prime_infos); - if (pnum > 0) { - dupkey->prime_infos = sk_RSA_PRIME_INFO_new_reserve(NULL, pnum); - for (i = 0; i < pnum; i++) { - const RSA_PRIME_INFO *pinfo = NULL; - RSA_PRIME_INFO *duppinfo = NULL; - - if ((duppinfo = OPENSSL_zalloc(sizeof(*duppinfo))) == NULL) { - ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE); - goto err; - } - /* push first so cleanup in error case works */ - (void)sk_RSA_PRIME_INFO_push(dupkey->prime_infos, duppinfo); - - pinfo = sk_RSA_PRIME_INFO_value(rsa->prime_infos, i); - if (!rsa_bn_dup_check(&duppinfo->r, pinfo->r)) - goto err; - if (!rsa_bn_dup_check(&duppinfo->d, pinfo->d)) - goto err; - if (!rsa_bn_dup_check(&duppinfo->t, pinfo->t)) - goto err; - } - if (!ossl_rsa_multip_calc_product(dupkey)) - goto err; - } - - dupkey->version = rsa->version; - dupkey->flags = rsa->flags; - - dupkey->pss_params = rsa->pss_params; - - if (rsa->pss != NULL) { - dupkey->pss = RSA_PSS_PARAMS_dup(rsa->pss); - if (rsa->pss->maskGenAlgorithm != NULL - && dupkey->pss->maskGenAlgorithm == NULL) { - dupkey->pss->maskHash = ossl_x509_algor_mgf1_decode(rsa->pss->maskGenAlgorithm); - if (dupkey->pss->maskHash == NULL) - goto err; - } - } - - if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_RSA, - &dupkey->ex_data, &rsa->ex_data)) - goto err; - - return dupkey; - - err: - RSA_free(dupkey); - return NULL; -} - static int rsa_pkey_copy(EVP_PKEY *to, EVP_PKEY *from) { RSA *rsa = from->pkey.rsa; @@ -983,7 +891,7 @@ static int rsa_pkey_copy(EVP_PKEY *to, EVP_PKEY *from) int ret; if (rsa != NULL) { - dupkey = rsa_dup(rsa); + dupkey = ossl_rsa_dup(rsa); if (dupkey == NULL) return 0; } diff --git a/crypto/rsa/rsa_backend.c b/crypto/rsa/rsa_backend.c index 01ee875058..92be5f610a 100644 --- a/crypto/rsa/rsa_backend.c +++ b/crypto/rsa/rsa_backend.c @@ -22,6 +22,7 @@ #include "internal/param_build_set.h" #include "crypto/asn1.h" #include "crypto/rsa.h" +#include "rsa_local.h" #include "e_os.h" /* strcasecmp for Windows() */ @@ -322,6 +323,100 @@ int ossl_rsa_pss_params_30_fromdata(RSA_PSS_PARAMS_30 *pss_params, return ret; } +static ossl_inline int rsa_bn_dup_check(BIGNUM **out, const BIGNUM *f) +{ + if (f != NULL && (*out = BN_dup(f)) == NULL) + return 0; + return 1; +} + +RSA *ossl_rsa_dup(const RSA *rsa) +{ + RSA *dupkey = NULL; +#ifndef FIPS_MODULE + int pnum, i; + + /* Do not try to duplicate foreign RSA keys */ + if (RSA_get_method(rsa) != RSA_PKCS1_OpenSSL()) + return NULL; +#endif + + 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; + + /* 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; + dupkey->pss_params = rsa->pss_params; + +#ifndef FIPS_MODULE + /* multiprime */ + pnum = sk_RSA_PRIME_INFO_num(rsa->prime_infos); + if (pnum > 0) { + dupkey->prime_infos = sk_RSA_PRIME_INFO_new_reserve(NULL, pnum); + for (i = 0; i < pnum; i++) { + const RSA_PRIME_INFO *pinfo = NULL; + RSA_PRIME_INFO *duppinfo = NULL; + + if ((duppinfo = OPENSSL_zalloc(sizeof(*duppinfo))) == NULL) { + ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE); + goto err; + } + /* push first so cleanup in error case works */ + (void)sk_RSA_PRIME_INFO_push(dupkey->prime_infos, duppinfo); + + pinfo = sk_RSA_PRIME_INFO_value(rsa->prime_infos, i); + if (!rsa_bn_dup_check(&duppinfo->r, pinfo->r)) + goto err; + if (!rsa_bn_dup_check(&duppinfo->d, pinfo->d)) + goto err; + if (!rsa_bn_dup_check(&duppinfo->t, pinfo->t)) + goto err; + } + if (!ossl_rsa_multip_calc_product(dupkey)) + goto err; + } + + if (rsa->pss != NULL) { + dupkey->pss = RSA_PSS_PARAMS_dup(rsa->pss); + if (rsa->pss->maskGenAlgorithm != NULL + && dupkey->pss->maskGenAlgorithm == NULL) { + dupkey->pss->maskHash = ossl_x509_algor_mgf1_decode(rsa->pss->maskGenAlgorithm); + if (dupkey->pss->maskHash == NULL) + goto err; + } + } + if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_RSA, + &dupkey->ex_data, &rsa->ex_data)) + goto err; +#endif + + return dupkey; + + err: + RSA_free(dupkey); + return NULL; +} + #ifndef FIPS_MODULE RSA_PSS_PARAMS *ossl_rsa_pss_decode(const X509_ALGOR *alg) { diff --git a/doc/man7/provider-keymgmt.pod b/doc/man7/provider-keymgmt.pod index 9a11b316c2..2937d915b9 100644 --- a/doc/man7/provider-keymgmt.pod +++ b/doc/man7/provider-keymgmt.pod @@ -55,6 +55,9 @@ provider-keymgmt - The KEYMGMT library E-E provider functions /* Key object copy */ int OSSL_FUNC_keymgmt_copy(void *keydata_to, const void *keydata_from, int selection); + /* Key object duplication, a constructor */ + void *OSSL_FUNC_keymgmt_dup(const void *keydata_from); + /* Key object validation */ int OSSL_FUNC_keymgmt_validate(const void *keydata, int selection, int checktype); @@ -119,6 +122,7 @@ macros in L, as follows: OSSL_FUNC_keymgmt_export_types OSSL_FUNC_KEYMGMT_EXPORT_TYPES OSSL_FUNC_keymgmt_copy OSSL_FUNC_KEYMGMT_COPY + OSSL_FUNC_keymgmt_dup OSSL_FUNC_KEYMGMT_DUP =head2 Key Objects @@ -342,6 +346,9 @@ from I to I. It is assumed that the caller has ensured that I and I are both owned by the implementation of this function. +OSSL_FUNC_keymgmt_dup() should duplicate the key data I and +create a new provider side key object with the data. + =head2 Common Information Parameters See L for further details on the parameters structure. @@ -379,8 +386,8 @@ Bits of security is defined in SP800-57. =head1 RETURN VALUES -OSSL_FUNC_keymgmt_new() should return a valid reference to the newly created provider -side key object, or NULL on failure. +OSSL_FUNC_keymgmt_new() and OSSL_FUNC_keymgmt_dup() should return a valid +reference to the newly created provider side key object, or NULL on failure. OSSL_FUNC_keymgmt_import(), OSSL_FUNC_keymgmt_export(), OSSL_FUNC_keymgmt_get_params() and OSSL_FUNC_keymgmt_set_params() should return 1 for success or 0 on error. diff --git a/include/crypto/dh.h b/include/crypto/dh.h index ab6115d986..8d5908549b 100644 --- a/include/crypto/dh.h +++ b/include/crypto/dh.h @@ -56,5 +56,6 @@ int ossl_dh_kdf_X9_42_asn1(unsigned char *out, size_t outlen, const unsigned char *ukm, size_t ukmlen, const EVP_MD *md, OSSL_LIB_CTX *libctx, const char *propq); +DH *ossl_dh_dup(const DH *dh); #endif /* OSSL_CRYPTO_DH_H */ diff --git a/include/crypto/dsa.h b/include/crypto/dsa.h index 38c49c3295..4fad9ab73e 100644 --- a/include/crypto/dsa.h +++ b/include/crypto/dsa.h @@ -43,5 +43,6 @@ int ossl_dsa_check_pub_key_partial(const DSA *dsa, const BIGNUM *pub_key, int *ret); int ossl_dsa_check_priv_key(const DSA *dsa, const BIGNUM *priv_key, int *ret); int ossl_dsa_check_pairwise(const DSA *dsa); +DSA *ossl_dsa_dup(const DSA *dsa); #endif diff --git a/include/crypto/ecx.h b/include/crypto/ecx.h index 656ee94f09..fcb0bbde0f 100644 --- a/include/crypto/ecx.h +++ b/include/crypto/ecx.h @@ -83,6 +83,7 @@ void ossl_ecx_key_set0_libctx(ECX_KEY *key, OSSL_LIB_CTX *libctx); unsigned char *ossl_ecx_key_allocate_privkey(ECX_KEY *key); void ossl_ecx_key_free(ECX_KEY *key); int ossl_ecx_key_up_ref(ECX_KEY *key); +ECX_KEY *ossl_ecx_key_dup(const ECX_KEY *key); int ossl_x25519(uint8_t out_shared_key[32], const uint8_t private_key[32], const uint8_t peer_public_value[32]); diff --git a/include/crypto/evp.h b/include/crypto/evp.h index 8ea5a2bf35..5f48d38f98 100644 --- a/include/crypto/evp.h +++ b/include/crypto/evp.h @@ -813,6 +813,8 @@ const OSSL_PARAM *evp_keymgmt_export_types(const EVP_KEYMGMT *keymgmt, int evp_keymgmt_copy(const EVP_KEYMGMT *keymgmt, void *keydata_to, const void *keydata_from, int selection); +void *evp_keymgmt_dup(const EVP_KEYMGMT *keymgmt, + const void *keydata_from); /* Pulling defines out of C source files */ diff --git a/include/crypto/rsa.h b/include/crypto/rsa.h index 73bf03f615..8c6ce49a7d 100644 --- a/include/crypto/rsa.h +++ b/include/crypto/rsa.h @@ -63,6 +63,7 @@ int ossl_rsa_set0_all_params(RSA *r, const STACK_OF(BIGNUM) *primes, int ossl_rsa_get0_all_params(RSA *r, STACK_OF(BIGNUM_const) *primes, STACK_OF(BIGNUM_const) *exps, STACK_OF(BIGNUM_const) *coeffs); +RSA *ossl_rsa_dup(const RSA *rsa); int ossl_rsa_todata(RSA *rsa, OSSL_PARAM_BLD *bld, OSSL_PARAM params[]); int ossl_rsa_fromdata(RSA *rsa, const OSSL_PARAM params[]); diff --git a/include/openssl/core_dispatch.h b/include/openssl/core_dispatch.h index 1cc2ebcc57..46278b4af6 100644 --- a/include/openssl/core_dispatch.h +++ b/include/openssl/core_dispatch.h @@ -598,8 +598,12 @@ OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, keymgmt_export_types, /* Copy function, only works for matching keymgmt */ # define OSSL_FUNC_KEYMGMT_COPY 44 OSSL_CORE_MAKE_FUNC(int, keymgmt_copy, - ( void *keydata_to, const void *keydata_from, + (void *keydata_to, const void *keydata_from, int selection)) +/* Dup function, constructor */ +# define OSSL_FUNC_KEYMGMT_DUP 45 +OSSL_CORE_MAKE_FUNC(void *, keymgmt_dup, + (const void *keydata_from)) /* Key Exchange */ diff --git a/providers/implementations/keymgmt/dh_kmgmt.c b/providers/implementations/keymgmt/dh_kmgmt.c index ba56abe04a..f7b10a1d00 100644 --- a/providers/implementations/keymgmt/dh_kmgmt.c +++ b/providers/implementations/keymgmt/dh_kmgmt.c @@ -45,6 +45,7 @@ static OSSL_FUNC_keymgmt_import_fn dh_import; static OSSL_FUNC_keymgmt_import_types_fn dh_import_types; static OSSL_FUNC_keymgmt_export_fn dh_export; static OSSL_FUNC_keymgmt_export_types_fn dh_export_types; +static OSSL_FUNC_keymgmt_dup_fn dh_dup; #define DH_POSSIBLE_SELECTIONS \ (OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) @@ -707,7 +708,7 @@ static void dh_gen_cleanup(void *genctx) OPENSSL_free(gctx); } -void *dh_load(const void *reference, size_t reference_sz) +static void *dh_load(const void *reference, size_t reference_sz) { DH *dh = NULL; @@ -721,6 +722,13 @@ void *dh_load(const void *reference, size_t reference_sz) return NULL; } +static void *dh_dup(const void *keydata_from) +{ + if (ossl_prov_is_running()) + return ossl_dh_dup(keydata_from); + return NULL; +} + const OSSL_DISPATCH ossl_dh_keymgmt_functions[] = { { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))dh_newdata }, { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))dh_gen_init }, @@ -743,6 +751,7 @@ const OSSL_DISPATCH ossl_dh_keymgmt_functions[] = { { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))dh_import_types }, { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))dh_export }, { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))dh_export_types }, + { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))dh_dup }, { 0, NULL } }; @@ -776,5 +785,6 @@ const OSSL_DISPATCH ossl_dhx_keymgmt_functions[] = { { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))dh_export_types }, { OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME, (void (*)(void))dhx_query_operation_name }, + { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))dh_dup }, { 0, NULL } }; diff --git a/providers/implementations/keymgmt/dsa_kmgmt.c b/providers/implementations/keymgmt/dsa_kmgmt.c index 15a40df260..0d3b6ae36c 100644 --- a/providers/implementations/keymgmt/dsa_kmgmt.c +++ b/providers/implementations/keymgmt/dsa_kmgmt.c @@ -44,6 +44,7 @@ static OSSL_FUNC_keymgmt_import_fn dsa_import; static OSSL_FUNC_keymgmt_import_types_fn dsa_import_types; static OSSL_FUNC_keymgmt_export_fn dsa_export; static OSSL_FUNC_keymgmt_export_types_fn dsa_export_types; +static OSSL_FUNC_keymgmt_dup_fn dsa_dup; #define DSA_DEFAULT_MD "SHA256" #define DSA_POSSIBLE_SELECTIONS \ @@ -597,7 +598,7 @@ static void dsa_gen_cleanup(void *genctx) OPENSSL_free(gctx); } -void *dsa_load(const void *reference, size_t reference_sz) +static void *dsa_load(const void *reference, size_t reference_sz) { DSA *dsa = NULL; @@ -611,6 +612,13 @@ void *dsa_load(const void *reference, size_t reference_sz) return NULL; } +static void *dsa_dup(const void *keydata_from) +{ + if (ossl_prov_is_running()) + return ossl_dsa_dup(keydata_from); + return NULL; +} + const OSSL_DISPATCH ossl_dsa_keymgmt_functions[] = { { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))dsa_newdata }, { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))dsa_gen_init }, @@ -631,5 +639,6 @@ const OSSL_DISPATCH ossl_dsa_keymgmt_functions[] = { { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))dsa_import_types }, { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))dsa_export }, { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))dsa_export_types }, + { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))dsa_dup }, { 0, NULL } }; diff --git a/providers/implementations/keymgmt/ec_kmgmt.c b/providers/implementations/keymgmt/ec_kmgmt.c index fe5bd7a28a..c525ffc81a 100644 --- a/providers/implementations/keymgmt/ec_kmgmt.c +++ b/providers/implementations/keymgmt/ec_kmgmt.c @@ -55,6 +55,7 @@ static OSSL_FUNC_keymgmt_import_types_fn ec_import_types; static OSSL_FUNC_keymgmt_export_fn ec_export; static OSSL_FUNC_keymgmt_export_types_fn ec_export_types; static OSSL_FUNC_keymgmt_query_operation_name_fn ec_query_operation_name; +static OSSL_FUNC_keymgmt_dup_fn ec_dup; #ifndef FIPS_MODULE # ifndef OPENSSL_NO_SM2 static OSSL_FUNC_keymgmt_new_fn sm2_newdata; @@ -1361,6 +1362,13 @@ static void *sm2_load(const void *reference, size_t reference_sz) # endif #endif +static void *ec_dup(const void *keydata_from) +{ + if (ossl_prov_is_running()) + return EC_KEY_dup(keydata_from); + return NULL; +} + const OSSL_DISPATCH ossl_ec_keymgmt_functions[] = { { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))ec_newdata }, { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))ec_gen_init }, @@ -1386,6 +1394,7 @@ const OSSL_DISPATCH ossl_ec_keymgmt_functions[] = { { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ec_export_types }, { OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME, (void (*)(void))ec_query_operation_name }, + { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))ec_dup }, { 0, NULL } }; @@ -1416,6 +1425,7 @@ const OSSL_DISPATCH ossl_sm2_keymgmt_functions[] = { { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ec_export_types }, { OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME, (void (*)(void))sm2_query_operation_name }, + { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))ec_dup }, { 0, NULL } }; # endif diff --git a/providers/implementations/keymgmt/ecx_kmgmt.c b/providers/implementations/keymgmt/ecx_kmgmt.c index a0284325cc..e072cdc851 100644 --- a/providers/implementations/keymgmt/ecx_kmgmt.c +++ b/providers/implementations/keymgmt/ecx_kmgmt.c @@ -71,6 +71,7 @@ static OSSL_FUNC_keymgmt_import_fn ecx_import; static OSSL_FUNC_keymgmt_import_types_fn ecx_imexport_types; static OSSL_FUNC_keymgmt_export_fn ecx_export; static OSSL_FUNC_keymgmt_export_types_fn ecx_imexport_types; +static OSSL_FUNC_keymgmt_dup_fn ecx_dup; #define ECX_POSSIBLE_SELECTIONS (OSSL_KEYMGMT_SELECT_KEYPAIR) @@ -691,6 +692,13 @@ void *ecx_load(const void *reference, size_t reference_sz) return NULL; } +static void *ecx_dup(const void *keydata_from) +{ + if (ossl_prov_is_running()) + return ossl_ecx_key_dup(keydata_from); + return NULL; +} + static int ecx_key_pairwise_check(const ECX_KEY *ecx, int type) { uint8_t pub[64]; @@ -788,6 +796,7 @@ static int ed448_validate(const void *keydata, int selection, int checktype) { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))alg##_gen }, \ { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ecx_gen_cleanup }, \ { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))ecx_load }, \ + { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))ecx_dup }, \ { 0, NULL } \ }; diff --git a/providers/implementations/keymgmt/rsa_kmgmt.c b/providers/implementations/keymgmt/rsa_kmgmt.c index fbd99e3dc8..5760d7650f 100644 --- a/providers/implementations/keymgmt/rsa_kmgmt.c +++ b/providers/implementations/keymgmt/rsa_kmgmt.c @@ -49,6 +49,7 @@ static OSSL_FUNC_keymgmt_import_types_fn rsa_import_types; static OSSL_FUNC_keymgmt_export_fn rsa_export; static OSSL_FUNC_keymgmt_export_types_fn rsa_export_types; static OSSL_FUNC_keymgmt_query_operation_name_fn rsa_query_operation_name; +static OSSL_FUNC_keymgmt_dup_fn rsa_dup; #define RSA_DEFAULT_MD "SHA256" #define RSA_PSS_DEFAULT_MD OSSL_DIGEST_NAME_SHA1 @@ -645,6 +646,13 @@ static void *rsapss_load(const void *reference, size_t reference_sz) return common_load(reference, reference_sz, RSA_FLAG_TYPE_RSASSAPSS); } +static void *rsa_dup(const void *keydata_from) +{ + if (ossl_prov_is_running()) + return ossl_rsa_dup(keydata_from); + return NULL; +} + /* For any RSA key, we use the "RSA" algorithms regardless of sub-type. */ static const char *rsa_query_operation_name(int operation_id) { @@ -671,6 +679,7 @@ const OSSL_DISPATCH ossl_rsa_keymgmt_functions[] = { { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))rsa_import_types }, { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))rsa_export }, { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))rsa_export_types }, + { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))rsa_dup }, { 0, NULL } }; @@ -695,5 +704,6 @@ const OSSL_DISPATCH ossl_rsapss_keymgmt_functions[] = { { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))rsa_export_types }, { OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME, (void (*)(void))rsa_query_operation_name }, + { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))rsa_dup }, { 0, NULL } };