diff options
Diffstat (limited to 'crypto')
-rw-r--r-- | crypto/dh/dh_ameth.c | 60 | ||||
-rw-r--r-- | crypto/dsa/dsa_ameth.c | 62 | ||||
-rw-r--r-- | crypto/ec/ec_ameth.c | 22 | ||||
-rw-r--r-- | crypto/ec/ecx_meth.c | 19 | ||||
-rw-r--r-- | crypto/evp/p_lib.c | 55 | ||||
-rw-r--r-- | crypto/ffc/ffc_params.c | 1 | ||||
-rw-r--r-- | crypto/rsa/rsa_ameth.c | 116 | ||||
-rw-r--r-- | crypto/rsa/rsa_asn1.c | 1 | ||||
-rw-r--r-- | crypto/x509/x509_att.c | 24 |
9 files changed, 354 insertions, 6 deletions
diff --git a/crypto/dh/dh_ameth.c b/crypto/dh/dh_ameth.c index ffaf41d802..0ed057dd8d 100644 --- a/crypto/dh/dh_ameth.c +++ b/crypto/dh/dh_ameth.c @@ -536,6 +536,64 @@ 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; + DH *dupkey = NULL; + int ret; + + if (dh != NULL) { + dupkey = dh_dup(dh); + if (dupkey == NULL) + return 0; + } + + ret = EVP_PKEY_assign(to, from->type, dupkey); + if (!ret) + DH_free(dupkey); + return ret; +} + const EVP_PKEY_ASN1_METHOD ossl_dh_asn1_meth = { EVP_PKEY_DH, EVP_PKEY_DH, @@ -579,6 +637,7 @@ const EVP_PKEY_ASN1_METHOD ossl_dh_asn1_meth = { dh_pkey_dirty_cnt, dh_pkey_export_to, dh_pkey_import_from, + dh_pkey_copy }; const EVP_PKEY_ASN1_METHOD ossl_dhx_asn1_meth = { @@ -622,4 +681,5 @@ const EVP_PKEY_ASN1_METHOD ossl_dhx_asn1_meth = { dh_pkey_dirty_cnt, dh_pkey_export_to, dhx_pkey_import_from, + dh_pkey_copy }; diff --git a/crypto/dsa/dsa_ameth.c b/crypto/dsa/dsa_ameth.c index e4c739daf9..1009f1a5c7 100644 --- a/crypto/dsa/dsa_ameth.c +++ b/crypto/dsa/dsa_ameth.c @@ -475,7 +475,7 @@ static int dsa_pkey_export_to(const EVP_PKEY *from, void *to_keydata, rv = evp_keymgmt_import(to_keymgmt, to_keydata, selection, params); OSSL_PARAM_BLD_free_params(params); -err: + err: OSSL_PARAM_BLD_free(tmpl); return rv; } @@ -500,6 +500,63 @@ 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; + DSA *dupkey = NULL; + int ret; + + if (dsa != NULL) { + dupkey = dsa_dup(dsa); + if (dupkey == NULL) + return 0; + } + + ret = EVP_PKEY_assign_DSA(to, dupkey); + if (!ret) + DSA_free(dupkey); + return ret; +} + /* NB these are sorted in pkey_id order, lowest first */ const EVP_PKEY_ASN1_METHOD ossl_dsa_asn1_meths[5] = { @@ -564,6 +621,7 @@ const EVP_PKEY_ASN1_METHOD ossl_dsa_asn1_meths[5] = { dsa_pkey_dirty_cnt, dsa_pkey_export_to, - dsa_pkey_import_from + dsa_pkey_import_from, + dsa_pkey_copy } }; diff --git a/crypto/ec/ec_ameth.c b/crypto/ec/ec_ameth.c index 69370d6bc1..273663d89e 100644 --- a/crypto/ec/ec_ameth.c +++ b/crypto/ec/ec_ameth.c @@ -640,6 +640,27 @@ static int ec_pkey_import_from(const OSSL_PARAM params[], void *vpctx) return 1; } +static int ec_pkey_copy(EVP_PKEY *to, EVP_PKEY *from) +{ + EC_KEY *eckey = from->pkey.ec; + EC_KEY *dupkey = NULL; + int ret; + + if (eckey != NULL) { + dupkey = EC_KEY_dup(eckey); + if (dupkey == NULL) + return 0; + } else { + /* necessary to properly copy empty SM2 keys */ + return EVP_PKEY_set_type(to, from->type); + } + + ret = EVP_PKEY_assign_EC_KEY(to, dupkey); + if (!ret) + EC_KEY_free(dupkey); + return ret; +} + const EVP_PKEY_ASN1_METHOD ossl_eckey_asn1_meth = { EVP_PKEY_EC, EVP_PKEY_EC, @@ -687,6 +708,7 @@ const EVP_PKEY_ASN1_METHOD ossl_eckey_asn1_meth = { ec_pkey_dirty_cnt, ec_pkey_export_to, ec_pkey_import_from, + ec_pkey_copy, eckey_priv_decode_ex }; diff --git a/crypto/ec/ecx_meth.c b/crypto/ec/ecx_meth.c index 00896f4186..c4d534e48c 100644 --- a/crypto/ec/ecx_meth.c +++ b/crypto/ec/ecx_meth.c @@ -404,6 +404,21 @@ static int ecx_generic_import_from(const OSSL_PARAM params[], void *vpctx, return 1; } +static int ecx_pkey_copy(EVP_PKEY *to, EVP_PKEY *from) +{ + ECX_KEY *ecx = from->pkey.ecx; + int ret; + + /* We can do just up-ref as ECX keys are immutable */ + if (ecx != NULL && !ossl_ecx_key_up_ref(ecx)) + return 0; + + ret = EVP_PKEY_assign(to, from->type, ecx); + if (!ret) + ossl_ecx_key_free(ecx); + return ret; +} + static int x25519_import_from(const OSSL_PARAM params[], void *vpctx) { return ecx_generic_import_from(params, vpctx, EVP_PKEY_X25519); @@ -453,6 +468,7 @@ const EVP_PKEY_ASN1_METHOD ossl_ecx25519_asn1_meth = { ecx_pkey_dirty_cnt, ecx_pkey_export_to, x25519_import_from, + ecx_pkey_copy, ecx_priv_decode_ex }; @@ -506,6 +522,7 @@ const EVP_PKEY_ASN1_METHOD ossl_ecx448_asn1_meth = { ecx_pkey_dirty_cnt, ecx_pkey_export_to, x448_import_from, + ecx_pkey_copy, ecx_priv_decode_ex }; @@ -632,6 +649,7 @@ const EVP_PKEY_ASN1_METHOD ossl_ed25519_asn1_meth = { ecx_pkey_dirty_cnt, ecx_pkey_export_to, ed25519_import_from, + ecx_pkey_copy, ecx_priv_decode_ex }; @@ -684,6 +702,7 @@ const EVP_PKEY_ASN1_METHOD ossl_ed448_asn1_meth = { ecx_pkey_dirty_cnt, ecx_pkey_export_to, ed448_import_from, + ecx_pkey_copy, ecx_priv_decode_ex }; diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c index 94a83c4804..d424106360 100644 --- a/crypto/evp/p_lib.c +++ b/crypto/evp/p_lib.c @@ -39,6 +39,7 @@ #include "crypto/evp.h" #include "crypto/ec.h" #include "crypto/ecx.h" +#include "crypto/x509.h" #include "internal/provider.h" #include "evp_local.h" @@ -1578,6 +1579,60 @@ int EVP_PKEY_up_ref(EVP_PKEY *pkey) } #ifndef FIPS_MODULE +EVP_PKEY *EVP_PKEY_dup(EVP_PKEY *pkey) +{ + EVP_PKEY *dup_pk; + + if (pkey == NULL) { + ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + + if ((dup_pk = EVP_PKEY_new()) == NULL) + return NULL; + + if (evp_pkey_is_blank(pkey)) + goto done; + + if (evp_pkey_is_provided(pkey)) { + if (!evp_keymgmt_util_copy(dup_pk, pkey, + OSSL_KEYMGMT_SELECT_ALL)) + goto err; + goto done; + } + + if (evp_pkey_is_legacy(pkey)) { + const EVP_PKEY_ASN1_METHOD *ameth = pkey->ameth; + + if (ameth == NULL || ameth->copy == NULL) { + if (pkey->pkey.ptr == NULL /* empty key, just set type */ + && EVP_PKEY_set_type(dup_pk, pkey->type) != 0) + goto done; + ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_KEY_TYPE); + goto err; + } + if (!ameth->copy(dup_pk, pkey)) + goto err; + goto done; + } + + goto err; +done: + /* copy auxiliary data */ + if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_EVP_PKEY, + &dup_pk->ex_data, &pkey->ex_data)) + goto err; + + if (pkey->attributes != NULL) { + if ((dup_pk->attributes = ossl_x509at_dup(pkey->attributes)) == NULL) + goto err; + } + return dup_pk; +err: + EVP_PKEY_free(dup_pk); + return NULL; +} + void evp_pkey_free_legacy(EVP_PKEY *x) { const EVP_PKEY_ASN1_METHOD *ameth = x->ameth; diff --git a/crypto/ffc/ffc_params.c b/crypto/ffc/ffc_params.c index 43064c0222..1bdee0bb6b 100644 --- a/crypto/ffc/ffc_params.c +++ b/crypto/ffc/ffc_params.c @@ -196,6 +196,7 @@ int ossl_ffc_params_copy(FFC_PARAMS *dst, const FFC_PARAMS *src) dst->pcounter = src->pcounter; dst->h = src->h; dst->gindex = src->gindex; + dst->flags = src->flags; return 1; } diff --git a/crypto/rsa/rsa_ameth.c b/crypto/rsa/rsa_ameth.c index 7a747a33ef..2155eaccd6 100644 --- a/crypto/rsa/rsa_ameth.c +++ b/crypto/rsa/rsa_ameth.c @@ -884,6 +884,116 @@ 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; + RSA *dupkey = NULL; + int ret; + + if (rsa != NULL) { + dupkey = rsa_dup(rsa); + if (dupkey == NULL) + return 0; + } + + ret = EVP_PKEY_assign(to, from->type, dupkey); + if (!ret) + RSA_free(dupkey); + return ret; +} + const EVP_PKEY_ASN1_METHOD ossl_rsa_asn1_meths[2] = { { EVP_PKEY_RSA, @@ -923,7 +1033,8 @@ const EVP_PKEY_ASN1_METHOD ossl_rsa_asn1_meths[2] = { rsa_pkey_dirty_cnt, rsa_pkey_export_to, - rsa_pkey_import_from + rsa_pkey_import_from, + rsa_pkey_copy }, { @@ -969,5 +1080,6 @@ const EVP_PKEY_ASN1_METHOD ossl_rsa_pss_asn1_meth = { rsa_pkey_dirty_cnt, rsa_pss_pkey_export_to, - rsa_pss_pkey_import_from + rsa_pss_pkey_import_from, + rsa_pkey_copy }; diff --git a/crypto/rsa/rsa_asn1.c b/crypto/rsa/rsa_asn1.c index c5799d8e4d..42fa20b6f0 100644 --- a/crypto/rsa/rsa_asn1.c +++ b/crypto/rsa/rsa_asn1.c @@ -92,6 +92,7 @@ ASN1_SEQUENCE_cb(RSA_PSS_PARAMS, rsa_pss_cb) = { } ASN1_SEQUENCE_END_cb(RSA_PSS_PARAMS, RSA_PSS_PARAMS) IMPLEMENT_ASN1_FUNCTIONS(RSA_PSS_PARAMS) +IMPLEMENT_ASN1_DUP_FUNCTION(RSA_PSS_PARAMS) /* Free up maskHash */ static int rsa_oaep_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, diff --git a/crypto/x509/x509_att.c b/crypto/x509/x509_att.c index 6a949f190e..52cad9a047 100644 --- a/crypto/x509/x509_att.c +++ b/crypto/x509/x509_att.c @@ -15,6 +15,7 @@ #include <openssl/evp.h> #include <openssl/x509.h> #include <openssl/x509v3.h> +#include "crypto/x509.h" #include "x509_local.h" int X509at_get_attr_count(const STACK_OF(X509_ATTRIBUTE) *x) @@ -84,8 +85,9 @@ STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr(STACK_OF(X509_ATTRIBUTE) **x, if (*x == NULL) { if ((sk = sk_X509_ATTRIBUTE_new_null()) == NULL) goto err; - } else + } else { sk = *x; + } if ((new_attr = X509_ATTRIBUTE_dup(attr)) == NULL) goto err2; @@ -98,7 +100,8 @@ STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr(STACK_OF(X509_ATTRIBUTE) **x, ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); err2: X509_ATTRIBUTE_free(new_attr); - sk_X509_ATTRIBUTE_free(sk); + if (*x == NULL) + sk_X509_ATTRIBUTE_free(sk); return NULL; } @@ -165,6 +168,23 @@ void *X509at_get0_data_by_OBJ(const STACK_OF(X509_ATTRIBUTE) *x, return X509_ATTRIBUTE_get0_data(at, 0, type, NULL); } +STACK_OF(X509_ATTRIBUTE) *ossl_x509at_dup(const STACK_OF(X509_ATTRIBUTE) *x) +{ + int i, n; + STACK_OF(X509_ATTRIBUTE) *sk = NULL; + + n = sk_X509_ATTRIBUTE_num(x); + for (i = 0; i < n; ++i) { + X509_ATTRIBUTE *attr = sk_X509_ATTRIBUTE_value(x, i); + + if (X509at_add1_attr(&sk, attr) == NULL) { + sk_X509_ATTRIBUTE_pop_free(sk, X509_ATTRIBUTE_free); + return NULL; + } + } + return sk; +} + X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID(X509_ATTRIBUTE **attr, int nid, int atrtype, const void *data, int len) |