#include <openssl/err.h>
#include <openssl/cms.h>
#include "cms_lcl.h"
+#include "asn1_locl.h"
static int cms_copy_content(BIO *out, BIO *in, unsigned int flags)
{
CMS_R_STORE_INIT_ERROR);
goto err;
}
- X509_STORE_CTX_set_default(&cert_ctx, "smime_sign");
+ X509_STORE_CTX_set_default(&ctx, "smime_sign");
if (crls)
X509_STORE_CTX_set0_crls(&ctx, crls);
for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++)
{
si = sk_CMS_SignerInfo_value(sinfos, i);
- if (!CMS_SignerInfo_verify_content(si, cmsbio))
+ if (CMS_SignerInfo_verify_content(si, cmsbio) <= 0)
{
CMSerr(CMS_F_CMS_VERIFY,
CMS_R_CONTENT_VERIFY_ERROR);
return NULL;
}
+static int cms_kari_set1_pkey(CMS_ContentInfo *cms, CMS_RecipientInfo *ri,
+ EVP_PKEY *pk, X509 *cert)
+ {
+ int i;
+ STACK_OF(CMS_RecipientEncryptedKey) *reks;
+ CMS_RecipientEncryptedKey *rek;
+ reks = CMS_RecipientInfo_kari_get0_reks(ri);
+ if (!cert)
+ return 0;
+ for (i = 0; i < sk_CMS_RecipientEncryptedKey_num(reks); i++)
+ {
+ int rv;
+ rek = sk_CMS_RecipientEncryptedKey_value(reks, i);
+ if (CMS_RecipientEncryptedKey_cert_cmp(rek, cert))
+ continue;
+ CMS_RecipientInfo_kari_set0_pkey(ri, pk);
+ rv = CMS_RecipientInfo_kari_decrypt(cms, ri, rek);
+ CMS_RecipientInfo_kari_set0_pkey(ri, NULL);
+ if (rv > 0)
+ return 1;
+ return -1;
+ }
+ return 0;
+ }
+
int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert)
{
STACK_OF(CMS_RecipientInfo) *ris;
CMS_RecipientInfo *ri;
- int i, r;
+ int i, r, ri_type;
+ int debug = 0;
ris = CMS_get0_RecipientInfos(cms);
+ if (ris)
+ debug = cms->d.envelopedData->encryptedContentInfo->debug;
+ ri_type = cms_pkey_get_ri_type(pk);
+ if (ri_type == CMS_RECIPINFO_NONE)
+ {
+ CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY,
+ CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
+ return 0;
+ }
+
for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++)
{
ri = sk_CMS_RecipientInfo_value(ris, i);
- if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_TRANS)
+ if (CMS_RecipientInfo_type(ri) != ri_type)
continue;
+ if (ri_type == CMS_RECIPINFO_AGREE)
+ {
+ r = cms_kari_set1_pkey(cms, ri, pk, cert);
+ if (r > 0)
+ return 1;
+ if (r < 0)
+ return 0;
+ }
/* If we have a cert try matching RecipientInfo
* otherwise try them all.
*/
- if (!cert || (CMS_RecipientInfo_ktri_cert_cmp(ri, cert) == 0))
+ else if (!cert || !CMS_RecipientInfo_ktri_cert_cmp(ri, cert))
{
CMS_RecipientInfo_set0_pkey(ri, pk);
r = CMS_RecipientInfo_decrypt(cms, ri);
CMS_RecipientInfo_set0_pkey(ri, NULL);
- if (r > 0)
- return 1;
if (cert)
{
+ /* If not debugging clear any error and
+ * return success to avoid leaking of
+ * information useful to MMA
+ */
+ if (!debug)
+ {
+ ERR_clear_error();
+ return 1;
+ }
+ if (r > 0)
+ return 1;
CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY,
CMS_R_DECRYPT_ERROR);
return 0;
}
- ERR_clear_error();
+ /* If no cert and not debugging don't leave loop
+ * after first successful decrypt. Always attempt
+ * to decrypt all recipients to avoid leaking timing
+ * of a successful decrypt.
+ */
+ else if (r > 0 && debug)
+ return 1;
}
}
+ /* If no cert and not debugging always return success */
+ if (!cert && !debug)
+ {
+ ERR_clear_error();
+ return 1;
+ }
CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY, CMS_R_NO_MATCHING_RECIPIENT);
return 0;
return 0;
}
+
+int CMS_decrypt_set1_password(CMS_ContentInfo *cms,
+ unsigned char *pass, ossl_ssize_t passlen)
+ {
+ STACK_OF(CMS_RecipientInfo) *ris;
+ CMS_RecipientInfo *ri;
+ int i, r;
+ ris = CMS_get0_RecipientInfos(cms);
+ for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++)
+ {
+ ri = sk_CMS_RecipientInfo_value(ris, i);
+ if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_PASS)
+ continue;
+ CMS_RecipientInfo_set0_password(ri, pass, passlen);
+ r = CMS_RecipientInfo_decrypt(cms, ri);
+ CMS_RecipientInfo_set0_password(ri, NULL, 0);
+ if (r > 0)
+ return 1;
+ }
+
+ CMSerr(CMS_F_CMS_DECRYPT_SET1_PASSWORD, CMS_R_NO_MATCHING_RECIPIENT);
+ return 0;
+
+ }
int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert,
BIO *dcont, BIO *out,
}
if (!dcont && !check_content(cms))
return 0;
+ if (flags & CMS_DEBUG_DECRYPT)
+ cms->d.envelopedData->encryptedContentInfo->debug = 1;
+ else
+ cms->d.envelopedData->encryptedContentInfo->debug = 0;
+ if (!pk && !cert && !dcont && !out)
+ return 1;
if (pk && !CMS_decrypt_set1_pkey(cms, pk, cert))
return 0;
-
cont = CMS_dataInit(cms, dcont);
if (!cont)
return 0;