From: Dr. Stephen Henson Date: Wed, 19 Jun 2013 17:17:14 +0000 (+0100) Subject: CMS public key parameter support. X-Git-Tag: master-pre-reformat~1227 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e365352d6a6368039392fed14a328f8c0bf955c3;p=openssl CMS public key parameter support. Add support for customisation of CMS handling of signed and enveloped data from custom public key parameters. This will provide support for RSA-PSS and RSA-OAEP but could also be applied to other algorithms. --- diff --git a/crypto/cms/cms.h b/crypto/cms/cms.h index 198688e53a..1624b79ebc 100644 --- a/crypto/cms/cms.h +++ b/crypto/cms/cms.h @@ -112,6 +112,7 @@ DECLARE_ASN1_PRINT_FUNCTION(CMS_ContentInfo) #define CMS_REUSE_DIGEST 0x8000 #define CMS_USE_KEYID 0x10000 #define CMS_DEBUG_DECRYPT 0x20000 +#define CMS_KEY_PARAM 0x40000 const ASN1_OBJECT *CMS_get0_type(CMS_ContentInfo *cms); @@ -190,6 +191,7 @@ int CMS_decrypt_set1_password(CMS_ContentInfo *cms, STACK_OF(CMS_RecipientInfo) *CMS_get0_RecipientInfos(CMS_ContentInfo *cms); int CMS_RecipientInfo_type(CMS_RecipientInfo *ri); +EVP_PKEY_CTX *CMS_RecipientInfo_get0_pkey_ctx(CMS_RecipientInfo *ri); CMS_ContentInfo *CMS_EnvelopedData_create(const EVP_CIPHER *cipher); CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms, X509 *recip, unsigned int flags); @@ -256,6 +258,8 @@ int CMS_SignedData_init(CMS_ContentInfo *cms); CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms, X509 *signer, EVP_PKEY *pk, const EVP_MD *md, unsigned int flags); +EVP_PKEY_CTX *CMS_SignerInfo_get0_pkey_ctx(CMS_SignerInfo *si); +EVP_MD_CTX *CMS_SignerInfo_get0_md_ctx(CMS_SignerInfo *si); STACK_OF(CMS_SignerInfo) *CMS_get0_SignerInfos(CMS_ContentInfo *cms); void CMS_SignerInfo_set1_signer_cert(CMS_SignerInfo *si, X509 *signer); @@ -374,6 +378,7 @@ void ERR_load_CMS_strings(void); #define CMS_F_CMS_ENVELOPEDDATA_CREATE 124 #define CMS_F_CMS_ENVELOPEDDATA_INIT_BIO 125 #define CMS_F_CMS_ENVELOPED_DATA_INIT 126 +#define CMS_F_CMS_ENV_ASN1_CTRL 171 #define CMS_F_CMS_FINAL 127 #define CMS_F_CMS_GET0_CERTIFICATE_CHOICES 128 #define CMS_F_CMS_GET0_CONTENT 129 @@ -399,6 +404,7 @@ void ERR_load_CMS_strings(void); #define CMS_F_CMS_RECIPIENTINFO_SET0_KEY 144 #define CMS_F_CMS_RECIPIENTINFO_SET0_PASSWORD 168 #define CMS_F_CMS_RECIPIENTINFO_SET0_PKEY 145 +#define CMS_F_CMS_SD_ASN1_CTRL 170 #define CMS_F_CMS_SET1_SIGNERIDENTIFIER 146 #define CMS_F_CMS_SET_DETACHED 147 #define CMS_F_CMS_SIGN 148 diff --git a/crypto/cms/cms_asn1.c b/crypto/cms/cms_asn1.c index cfe67fb6c1..6a692cdb1d 100644 --- a/crypto/cms/cms_asn1.c +++ b/crypto/cms/cms_asn1.c @@ -97,6 +97,8 @@ static int cms_si_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, EVP_PKEY_free(si->pkey); if (si->signer) X509_free(si->signer); + if (si->pctx) + EVP_MD_CTX_cleanup(&si->mctx); } return 1; } @@ -227,6 +229,8 @@ static int cms_ri_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, EVP_PKEY_free(ktri->pkey); if (ktri->recip) X509_free(ktri->recip); + if (ktri->pctx) + EVP_PKEY_CTX_free(ktri->pctx); } else if (ri->type == CMS_RECIPINFO_KEK) { diff --git a/crypto/cms/cms_env.c b/crypto/cms/cms_env.c index 632dbae760..c26dd59738 100644 --- a/crypto/cms/cms_env.c +++ b/crypto/cms/cms_env.c @@ -103,6 +103,27 @@ static CMS_EnvelopedData *cms_enveloped_data_init(CMS_ContentInfo *cms) return cms_get0_enveloped(cms); } +static int cms_env_asn1_ctrl(CMS_RecipientInfo *ri, int cmd) + { + EVP_PKEY *pkey = ri->d.ktri->pkey; + int i; + if (!pkey->ameth || !pkey->ameth->pkey_ctrl) + return 1; + i = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_CMS_ENVELOPE, cmd, ri); + if (i == -2) + { + CMSerr(CMS_F_CMS_ENV_ASN1_CTRL, + CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); + return 0; + } + if (i <= 0) + { + CMSerr(CMS_F_CMS_ENV_ASN1_CTRL, CMS_R_CTRL_FAILURE); + return 0; + } + return 1; + } + STACK_OF(CMS_RecipientInfo) *CMS_get0_RecipientInfos(CMS_ContentInfo *cms) { CMS_EnvelopedData *env; @@ -117,6 +138,13 @@ int CMS_RecipientInfo_type(CMS_RecipientInfo *ri) return ri->type; } +EVP_PKEY_CTX *CMS_RecipientInfo_get0_pkey_ctx(CMS_RecipientInfo *ri) + { + if (ri->type == CMS_RECIPINFO_TRANS) + return ri->d.ktri->pctx; + return NULL; + } + CMS_ContentInfo *CMS_EnvelopedData_create(const EVP_CIPHER *cipher) { CMS_ContentInfo *cms; @@ -151,7 +179,7 @@ CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms, CMS_KeyTransRecipientInfo *ktri; CMS_EnvelopedData *env; EVP_PKEY *pk = NULL; - int i, type; + int type; env = cms_get0_enveloped(cms); if (!env) goto err; @@ -200,23 +228,16 @@ CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms, if (!cms_set1_SignerIdentifier(ktri->rid, recip, type)) goto err; - if (pk->ameth && pk->ameth->pkey_ctrl) + if (flags & CMS_KEY_PARAM) { - i = pk->ameth->pkey_ctrl(pk, ASN1_PKEY_CTRL_CMS_ENVELOPE, - 0, ri); - if (i == -2) - { - CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, - CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); + ktri->pctx = EVP_PKEY_CTX_new(ktri->pkey, NULL); + if (!ktri->pctx) + return 0; + if (EVP_PKEY_encrypt_init(ktri->pctx) <= 0) goto err; - } - if (i <= 0) - { - CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, - CMS_R_CTRL_FAILURE); - goto err; - } } + else if (!cms_env_asn1_ctrl(ri, 0)) + goto err; if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri)) goto merr; @@ -302,7 +323,7 @@ static int cms_RecipientInfo_ktri_encrypt(CMS_ContentInfo *cms, { CMS_KeyTransRecipientInfo *ktri; CMS_EncryptedContentInfo *ec; - EVP_PKEY_CTX *pctx = NULL; + EVP_PKEY_CTX *pctx; unsigned char *ek = NULL; size_t eklen; @@ -317,12 +338,22 @@ static int cms_RecipientInfo_ktri_encrypt(CMS_ContentInfo *cms, ktri = ri->d.ktri; ec = cms->d.envelopedData->encryptedContentInfo; - pctx = EVP_PKEY_CTX_new(ktri->pkey, NULL); - if (!pctx) - return 0; + pctx = ktri->pctx; - if (EVP_PKEY_encrypt_init(pctx) <= 0) - goto err; + if (pctx) + { + if (!cms_env_asn1_ctrl(ri, 0)) + goto err; + } + else + { + pctx = EVP_PKEY_CTX_new(ktri->pkey, NULL); + if (!pctx) + return 0; + + if (EVP_PKEY_encrypt_init(pctx) <= 0) + goto err; + } if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_ENCRYPT, EVP_PKEY_CTRL_CMS_ENCRYPT, 0, ri) <= 0) @@ -353,7 +384,10 @@ static int cms_RecipientInfo_ktri_encrypt(CMS_ContentInfo *cms, err: if (pctx) + { EVP_PKEY_CTX_free(pctx); + ktri->pctx = NULL; + } if (ek) OPENSSL_free(ek); return ret; @@ -366,7 +400,7 @@ static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri) { CMS_KeyTransRecipientInfo *ktri = ri->d.ktri; - EVP_PKEY_CTX *pctx = NULL; + EVP_PKEY *pkey = ktri->pkey; unsigned char *ek = NULL; size_t eklen; int ret = 0; @@ -380,21 +414,24 @@ static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms, return 0; } - pctx = EVP_PKEY_CTX_new(ktri->pkey, NULL); - if (!pctx) + ktri->pctx = EVP_PKEY_CTX_new(pkey, NULL); + if (!ktri->pctx) return 0; - if (EVP_PKEY_decrypt_init(pctx) <= 0) + if (EVP_PKEY_decrypt_init(ktri->pctx) <= 0) + goto err; + + if (!cms_env_asn1_ctrl(ri, 1)) goto err; - if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DECRYPT, + if (EVP_PKEY_CTX_ctrl(ktri->pctx, -1, EVP_PKEY_OP_DECRYPT, EVP_PKEY_CTRL_CMS_DECRYPT, 0, ri) <= 0) { CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_CTRL_ERROR); goto err; } - if (EVP_PKEY_decrypt(pctx, NULL, &eklen, + if (EVP_PKEY_decrypt(ktri->pctx, NULL, &eklen, ktri->encryptedKey->data, ktri->encryptedKey->length) <= 0) goto err; @@ -408,7 +445,7 @@ static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms, goto err; } - if (EVP_PKEY_decrypt(pctx, ek, &eklen, + if (EVP_PKEY_decrypt(ktri->pctx, ek, &eklen, ktri->encryptedKey->data, ktri->encryptedKey->length) <= 0) { @@ -428,8 +465,11 @@ static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms, ec->keylen = eklen; err: - if (pctx) - EVP_PKEY_CTX_free(pctx); + if (ktri->pctx) + { + EVP_PKEY_CTX_free(ktri->pctx); + ktri->pctx = NULL; + } if (!ret && ek) OPENSSL_free(ek); diff --git a/crypto/cms/cms_err.c b/crypto/cms/cms_err.c index cc58ea5f96..35aca59335 100644 --- a/crypto/cms/cms_err.c +++ b/crypto/cms/cms_err.c @@ -103,6 +103,7 @@ static ERR_STRING_DATA CMS_str_functs[]= {ERR_FUNC(CMS_F_CMS_ENVELOPEDDATA_CREATE), "CMS_EnvelopedData_create"}, {ERR_FUNC(CMS_F_CMS_ENVELOPEDDATA_INIT_BIO), "cms_EnvelopedData_init_bio"}, {ERR_FUNC(CMS_F_CMS_ENVELOPED_DATA_INIT), "CMS_ENVELOPED_DATA_INIT"}, +{ERR_FUNC(CMS_F_CMS_ENV_ASN1_CTRL), "CMS_ENV_ASN1_CTRL"}, {ERR_FUNC(CMS_F_CMS_FINAL), "CMS_final"}, {ERR_FUNC(CMS_F_CMS_GET0_CERTIFICATE_CHOICES), "CMS_GET0_CERTIFICATE_CHOICES"}, {ERR_FUNC(CMS_F_CMS_GET0_CONTENT), "CMS_get0_content"}, @@ -128,6 +129,7 @@ static ERR_STRING_DATA CMS_str_functs[]= {ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_SET0_KEY), "CMS_RecipientInfo_set0_key"}, {ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_SET0_PASSWORD), "CMS_RecipientInfo_set0_password"}, {ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_SET0_PKEY), "CMS_RecipientInfo_set0_pkey"}, +{ERR_FUNC(CMS_F_CMS_SD_ASN1_CTRL), "CMS_SD_ASN1_CTRL"}, {ERR_FUNC(CMS_F_CMS_SET1_SIGNERIDENTIFIER), "cms_set1_SignerIdentifier"}, {ERR_FUNC(CMS_F_CMS_SET_DETACHED), "CMS_set_detached"}, {ERR_FUNC(CMS_F_CMS_SIGN), "CMS_sign"}, diff --git a/crypto/cms/cms_lcl.h b/crypto/cms/cms_lcl.h index d5a70b4665..b62dc72f2f 100644 --- a/crypto/cms/cms_lcl.h +++ b/crypto/cms/cms_lcl.h @@ -140,6 +140,9 @@ struct CMS_SignerInfo_st /* Signing certificate and key */ X509 *signer; EVP_PKEY *pkey; + /* Digest and public key context for alternative parameters */ + EVP_MD_CTX mctx; + EVP_PKEY_CTX *pctx; }; struct CMS_SignerIdentifier_st @@ -202,6 +205,8 @@ struct CMS_KeyTransRecipientInfo_st /* Recipient Key and cert */ X509 *recip; EVP_PKEY *pkey; + /* Public key context for this operation */ + EVP_PKEY_CTX *pctx; }; struct CMS_KeyAgreeRecipientInfo_st diff --git a/crypto/cms/cms_sd.c b/crypto/cms/cms_sd.c index f448a35066..b7dbf52ab1 100644 --- a/crypto/cms/cms_sd.c +++ b/crypto/cms/cms_sd.c @@ -297,6 +297,27 @@ int cms_SignerIdentifier_cert_cmp(CMS_SignerIdentifier *sid, X509 *cert) return -1; } +static int cms_sd_asn1_ctrl(CMS_SignerInfo *si, int cmd) + { + EVP_PKEY *pkey = si->pkey; + int i; + if (!pkey->ameth || !pkey->ameth->pkey_ctrl) + return 1; + i = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_CMS_SIGN, cmd, si); + if (i == -2) + { + CMSerr(CMS_F_CMS_SD_ASN1_CTRL, + CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); + return 0; + } + if (i <= 0) + { + CMSerr(CMS_F_CMS_SD_ASN1_CTRL, CMS_R_CTRL_FAILURE); + return 0; + } + return 1; + } + CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms, X509 *signer, EVP_PKEY *pk, const EVP_MD *md, unsigned int flags) @@ -324,6 +345,8 @@ CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms, si->pkey = pk; si->signer = signer; + EVP_MD_CTX_init(&si->mctx); + si->pctx = NULL; if (flags & CMS_USE_KEYID) { @@ -385,23 +408,8 @@ CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms, } } - if (pk->ameth && pk->ameth->pkey_ctrl) - { - i = pk->ameth->pkey_ctrl(pk, ASN1_PKEY_CTRL_CMS_SIGN, - 0, si); - if (i == -2) - { - CMSerr(CMS_F_CMS_ADD1_SIGNER, - CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); - goto err; - } - if (i <= 0) - { - CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_CTRL_FAILURE); - goto err; - } - } - + if (!(flags & CMS_KEY_PARAM) && !cms_sd_asn1_ctrl(si, 0)) + goto err; if (!(flags & CMS_NOATTR)) { /* Initialialize signed attributes strutucture so other @@ -429,7 +437,7 @@ CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms, { if (!cms_copy_messageDigest(cms, si)) goto err; - if (!(flags & CMS_PARTIAL) && + if (!(flags & (CMS_PARTIAL|CMS_KEY_PARAM)) && !CMS_SignerInfo_sign(si)) goto err; } @@ -442,6 +450,22 @@ CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms, goto merr; } + if (flags & CMS_KEY_PARAM) + { + if (flags & CMS_NOATTR) + { + si->pctx = EVP_PKEY_CTX_new(si->pkey, NULL); + if (!si->pctx) + goto err; + if (EVP_PKEY_sign_init(si->pctx) <= 0) + goto err; + if (EVP_PKEY_CTX_set_signature_md(si->pctx, md) <= 0) + goto err; + } + else if (EVP_DigestSignInit(&si->mctx, &si->pctx, md, NULL, pk) <= 0) + goto err; + } + if (!sd->signerInfos) sd->signerInfos = sk_CMS_SignerInfo_new_null(); if (!sd->signerInfos || @@ -489,6 +513,16 @@ static int cms_add1_signingTime(CMS_SignerInfo *si, ASN1_TIME *t) } +EVP_PKEY_CTX *CMS_SignerInfo_get0_pkey_ctx(CMS_SignerInfo *si) + { + return si->pctx; + } + +EVP_MD_CTX *CMS_SignerInfo_get0_md_ctx(CMS_SignerInfo *si) + { + return &si->mctx; + } + STACK_OF(CMS_SignerInfo) *CMS_get0_SignerInfos(CMS_ContentInfo *cms) { CMS_SignedData *sd; @@ -621,9 +655,9 @@ static int cms_SignerInfo_content_sign(CMS_ContentInfo *cms, { EVP_MD_CTX mctx; int r = 0; + EVP_PKEY_CTX *pctx = NULL; EVP_MD_CTX_init(&mctx); - if (!si->pkey) { CMSerr(CMS_F_CMS_SIGNERINFO_CONTENT_SIGN, CMS_R_NO_PRIVATE_KEY); @@ -632,6 +666,9 @@ static int cms_SignerInfo_content_sign(CMS_ContentInfo *cms, if (!cms_DigestAlgorithm_find_ctx(&mctx, chain, si->digestAlgorithm)) goto err; + /* Set SignerInfo algortihm details if we used custom parametsr */ + if (si->pctx && !cms_sd_asn1_ctrl(si, 0)) + goto err; /* If any signed attributes calculate and add messageDigest attribute */ @@ -654,6 +691,26 @@ static int cms_SignerInfo_content_sign(CMS_ContentInfo *cms, if (!CMS_SignerInfo_sign(si)) goto err; } + else if (si->pctx) + { + unsigned char *sig; + size_t siglen; + unsigned char md[EVP_MAX_MD_SIZE]; + unsigned int mdlen; + pctx = si->pctx; + if (!EVP_DigestFinal_ex(&mctx, md, &mdlen)) + goto err; + sig = OPENSSL_malloc(EVP_PKEY_size(si->pkey)); + if (!sig) + { + CMSerr(CMS_F_CMS_SIGNERINFO_CONTENT_SIGN, + ERR_R_MALLOC_FAILURE); + goto err; + } + if (EVP_PKEY_sign(pctx, sig, &siglen, md, mdlen) <= 0) + goto err; + ASN1_STRING_set0(si->signature, sig, siglen); + } else { unsigned char *sig; @@ -679,6 +736,8 @@ static int cms_SignerInfo_content_sign(CMS_ContentInfo *cms, err: EVP_MD_CTX_cleanup(&mctx); + if (pctx) + EVP_PKEY_CTX_free(pctx); return r; } @@ -701,7 +760,7 @@ int cms_SignedData_final(CMS_ContentInfo *cms, BIO *chain) int CMS_SignerInfo_sign(CMS_SignerInfo *si) { - EVP_MD_CTX mctx; + EVP_MD_CTX *mctx = &si->mctx; EVP_PKEY_CTX *pctx; unsigned char *abuf = NULL; int alen; @@ -712,7 +771,6 @@ int CMS_SignerInfo_sign(CMS_SignerInfo *si) if (md == NULL) return 0; - EVP_MD_CTX_init(&mctx); if (CMS_signed_get_attr_by_NID(si, NID_pkcs9_signingTime, -1) < 0) { @@ -720,8 +778,14 @@ int CMS_SignerInfo_sign(CMS_SignerInfo *si) goto err; } - if (EVP_DigestSignInit(&mctx, &pctx, md, NULL, si->pkey) <= 0) - goto err; + if (si->pctx) + pctx = si->pctx; + else + { + EVP_MD_CTX_init(mctx); + if (EVP_DigestSignInit(mctx, &pctx, md, NULL, si->pkey) <= 0) + goto err; + } if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN, EVP_PKEY_CTRL_CMS_SIGN, 0, si) <= 0) @@ -734,15 +798,15 @@ int CMS_SignerInfo_sign(CMS_SignerInfo *si) ASN1_ITEM_rptr(CMS_Attributes_Sign)); if(!abuf) goto err; - if (EVP_DigestSignUpdate(&mctx, abuf, alen) <= 0) + if (EVP_DigestSignUpdate(mctx, abuf, alen) <= 0) goto err; - if (EVP_DigestSignFinal(&mctx, NULL, &siglen) <= 0) + if (EVP_DigestSignFinal(mctx, NULL, &siglen) <= 0) goto err; OPENSSL_free(abuf); abuf = OPENSSL_malloc(siglen); if(!abuf) goto err; - if (EVP_DigestSignFinal(&mctx, abuf, &siglen) <= 0) + if (EVP_DigestSignFinal(mctx, abuf, &siglen) <= 0) goto err; if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN, @@ -752,7 +816,7 @@ int CMS_SignerInfo_sign(CMS_SignerInfo *si) goto err; } - EVP_MD_CTX_cleanup(&mctx); + EVP_MD_CTX_cleanup(mctx); ASN1_STRING_set0(si->signature, abuf, siglen); @@ -761,15 +825,14 @@ int CMS_SignerInfo_sign(CMS_SignerInfo *si) err: if (abuf) OPENSSL_free(abuf); - EVP_MD_CTX_cleanup(&mctx); + EVP_MD_CTX_cleanup(mctx); return 0; } int CMS_SignerInfo_verify(CMS_SignerInfo *si) { - EVP_MD_CTX mctx; - EVP_PKEY_CTX *pctx; + EVP_MD_CTX *mctx = &si->mctx; unsigned char *abuf = NULL; int alen, r = -1; const EVP_MD *md = NULL; @@ -783,27 +846,30 @@ int CMS_SignerInfo_verify(CMS_SignerInfo *si) md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm); if (md == NULL) return -1; - EVP_MD_CTX_init(&mctx); - if (EVP_DigestVerifyInit(&mctx, &pctx, md, NULL, si->pkey) <= 0) + EVP_MD_CTX_init(mctx); + if (EVP_DigestVerifyInit(mctx, &si->pctx, md, NULL, si->pkey) <= 0) + goto err; + + if (!cms_sd_asn1_ctrl(si, 1)) goto err; alen = ASN1_item_i2d((ASN1_VALUE *)si->signedAttrs,&abuf, ASN1_ITEM_rptr(CMS_Attributes_Verify)); if(!abuf) goto err; - r = EVP_DigestVerifyUpdate(&mctx, abuf, alen); + r = EVP_DigestVerifyUpdate(mctx, abuf, alen); OPENSSL_free(abuf); if (r <= 0) { r = -1; goto err; } - r = EVP_DigestVerifyFinal(&mctx, + r = EVP_DigestVerifyFinal(mctx, si->signature->data, si->signature->length); if (r <= 0) CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY, CMS_R_VERIFICATION_FAILURE); err: - EVP_MD_CTX_cleanup(&mctx); + EVP_MD_CTX_cleanup(mctx); return r; } @@ -843,7 +909,10 @@ int CMS_SignerInfo_verify_content(CMS_SignerInfo *si, BIO *chain) { ASN1_OCTET_STRING *os = NULL; EVP_MD_CTX mctx; + EVP_PKEY_CTX *pkctx = NULL; int r = -1; + unsigned char mval[EVP_MAX_MD_SIZE]; + unsigned int mlen; EVP_MD_CTX_init(&mctx); /* If we have any signed attributes look for messageDigest value */ if (CMS_signed_get_attr_count(si) >= 0) @@ -862,18 +931,17 @@ int CMS_SignerInfo_verify_content(CMS_SignerInfo *si, BIO *chain) if (!cms_DigestAlgorithm_find_ctx(&mctx, chain, si->digestAlgorithm)) goto err; + if (EVP_DigestFinal_ex(&mctx, mval, &mlen) <= 0) + { + CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT, + CMS_R_UNABLE_TO_FINALIZE_CONTEXT); + goto err; + } + /* If messageDigest found compare it */ if (os) { - unsigned char mval[EVP_MAX_MD_SIZE]; - unsigned int mlen; - if (EVP_DigestFinal_ex(&mctx, mval, &mlen) <= 0) - { - CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT, - CMS_R_UNABLE_TO_FINALIZE_CONTEXT); - goto err; - } if (mlen != (unsigned int)os->length) { CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT, @@ -892,8 +960,18 @@ int CMS_SignerInfo_verify_content(CMS_SignerInfo *si, BIO *chain) } else { - r = EVP_VerifyFinal(&mctx, si->signature->data, - si->signature->length, si->pkey); + const EVP_MD *md = EVP_MD_CTX_md(&mctx); + pkctx = EVP_PKEY_CTX_new(si->pkey, NULL); + if (EVP_PKEY_verify_init(pkctx) <= 0) + goto err; + if (EVP_PKEY_CTX_set_signature_md(pkctx, md) <= 0) + goto err; + si->pctx = pkctx; + if (!cms_sd_asn1_ctrl(si, 1)) + goto err; + r = EVP_PKEY_verify(pkctx, si->signature->data, + si->signature->length, + mval, mlen); if (r <= 0) { CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT, @@ -903,6 +981,8 @@ int CMS_SignerInfo_verify_content(CMS_SignerInfo *si, BIO *chain) } err: + if (pkctx) + EVP_PKEY_CTX_free(pkctx); EVP_MD_CTX_cleanup(&mctx); return r;