diff options
author | Michael Baentsch <info@baentsch.ch> | 2022-02-18 14:10:04 +0100 |
---|---|---|
committer | Tomas Mraz <tomas@openssl.org> | 2022-03-03 13:30:45 +0100 |
commit | d15d561844d8989e50896724d89681ae7ba81a74 (patch) | |
tree | 1dcd82903c4fb4e85d36d3929a41dc8a77207c16 | |
parent | 13ba91cb02479a91b0743d2bf5f5ec7ce42860d0 (diff) |
enable CMS sign/verify for provider-implemented PKEYs
We need to handle signatures with and without digest algs
and we generalize the ossl_cms_ecdsa_dsa_sign() function
to other algorithms that are handled in the same way.
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/17733)
-rw-r--r-- | crypto/cms/cms_ec.c | 23 | ||||
-rw-r--r-- | crypto/cms/cms_local.h | 1 | ||||
-rw-r--r-- | crypto/cms/cms_sd.c | 37 | ||||
-rw-r--r-- | crypto/objects/obj_xref.c | 9 |
4 files changed, 42 insertions, 28 deletions
diff --git a/crypto/cms/cms_ec.c b/crypto/cms/cms_ec.c index fd6c5d7077..e8d942a812 100644 --- a/crypto/cms/cms_ec.c +++ b/crypto/cms/cms_ec.c @@ -388,26 +388,3 @@ int ossl_cms_ecdh_envelope(CMS_RecipientInfo *ri, int decrypt) ERR_raise(ERR_LIB_CMS, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); return 0; } - -/* ECDSA and DSA implementation is the same */ -int ossl_cms_ecdsa_dsa_sign(CMS_SignerInfo *si, int verify) -{ - assert(verify == 0 || verify == 1); - - if (!verify) { - int snid, hnid; - X509_ALGOR *alg1, *alg2; - EVP_PKEY *pkey = si->pkey; - - CMS_SignerInfo_get0_algs(si, NULL, NULL, &alg1, &alg2); - if (alg1 == NULL || alg1->algorithm == NULL) - return -1; - hnid = OBJ_obj2nid(alg1->algorithm); - if (hnid == NID_undef) - return -1; - if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_get_id(pkey))) - return -1; - return X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, NULL); - } - return 1; -} diff --git a/crypto/cms/cms_local.h b/crypto/cms/cms_local.h index 15b4a29ce0..e9fb43715a 100644 --- a/crypto/cms/cms_local.h +++ b/crypto/cms/cms_local.h @@ -479,7 +479,6 @@ int ossl_cms_check_signing_certs(const CMS_SignerInfo *si, int ossl_cms_dh_envelope(CMS_RecipientInfo *ri, int decrypt); int ossl_cms_ecdh_envelope(CMS_RecipientInfo *ri, int decrypt); int ossl_cms_rsa_envelope(CMS_RecipientInfo *ri, int decrypt); -int ossl_cms_ecdsa_dsa_sign(CMS_SignerInfo *si, int verify); int ossl_cms_rsa_sign(CMS_SignerInfo *si, int verify); DECLARE_ASN1_ITEM(CMS_CertificateChoices) diff --git a/crypto/cms/cms_sd.c b/crypto/cms/cms_sd.c index 8985be4fb4..d1e5ec8b4e 100644 --- a/crypto/cms/cms_sd.c +++ b/crypto/cms/cms_sd.c @@ -227,19 +227,50 @@ int ossl_cms_SignerIdentifier_cert_cmp(CMS_SignerIdentifier *sid, X509 *cert) return -1; } +/* Method to map any, incl. provider-implemented PKEY types to OIDs */ +/* ECDSA and DSA and all provider-delivered signatures implementation is the same */ +static int cms_generic_sign(CMS_SignerInfo *si, int verify) +{ + if (!ossl_assert(verify == 0 || verify == 1)) + return -1; + + if (!verify) { + int snid, hnid, pknid; + X509_ALGOR *alg1, *alg2; + EVP_PKEY *pkey = si->pkey; + pknid = EVP_PKEY_get_id(pkey); + + CMS_SignerInfo_get0_algs(si, NULL, NULL, &alg1, &alg2); + if (alg1 == NULL || alg1->algorithm == NULL) + return -1; + hnid = OBJ_obj2nid(alg1->algorithm); + if (hnid == NID_undef) + return -1; + if (pknid <= 0) { /* check whether a provider registered a NID */ + const char *typename = EVP_PKEY_get0_type_name(pkey); + if (typename != NULL) + pknid = OBJ_txt2nid(typename); + } + if (!OBJ_find_sigid_by_algs(&snid, hnid, pknid)) + return -1; + return X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, NULL); + } + return 1; +} + static int cms_sd_asn1_ctrl(CMS_SignerInfo *si, int cmd) { EVP_PKEY *pkey = si->pkey; int i; if (EVP_PKEY_is_a(pkey, "DSA") || EVP_PKEY_is_a(pkey, "EC")) - return ossl_cms_ecdsa_dsa_sign(si, cmd); + return cms_generic_sign(si, cmd); else if (EVP_PKEY_is_a(pkey, "RSA") || EVP_PKEY_is_a(pkey, "RSA-PSS")) return ossl_cms_rsa_sign(si, cmd); - /* Something else? We'll give engines etc a chance to handle this */ + /* Now give engines, providers, etc a chance to handle this */ if (pkey->ameth == NULL || pkey->ameth->pkey_ctrl == NULL) - return 1; + return cms_generic_sign(si, cmd); i = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_CMS_SIGN, cmd, si); if (i == -2) { ERR_raise(ERR_LIB_CMS, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); diff --git a/crypto/objects/obj_xref.c b/crypto/objects/obj_xref.c index 8b4980d5b5..fc870c5691 100644 --- a/crypto/objects/obj_xref.c +++ b/crypto/objects/obj_xref.c @@ -36,7 +36,14 @@ static int sigx_cmp(const nid_triple *const *a, const nid_triple *const *b) int ret; ret = (*a)->hash_id - (*b)->hash_id; - if (ret != 0) + /* The "b" side of the comparison carries the algorithms already + * registered. A NID_undef for 'hash_id' there means that the + * signature algorithm doesn't need a digest to operate OK. In + * such case, any hash_id/digest algorithm on the test side (a), + * incl. NID_undef, is acceptable. signature algorithm NID + * (pkey_id) must match in any case. + */ + if ((ret != 0) && ((*b)->hash_id != NID_undef)) return ret; return (*a)->pkey_id - (*b)->pkey_id; } |