tolerate broken CMS/PKCS7 implementations using signature OID instead of digest
[openssl.git] / crypto / cms / cms_lib.c
index 24ab0e7ba5ab9dc44574a7dffbf17c38ffa05939..b62d1bfac02b750f59021e74de3d5c2fa81ad772 100644 (file)
@@ -68,12 +68,6 @@ DECLARE_ASN1_ITEM(CMS_RevocationInfoChoice)
 DECLARE_STACK_OF(CMS_CertificateChoices)
 DECLARE_STACK_OF(CMS_RevocationInfoChoice)
 
-#if 0
-IMPLEMENT_ASN1_ALLOC_FUNCTIONS(CMS_CertificateChoices)
-IMPLEMENT_ASN1_ALLOC_FUNCTIONS(CMS_RevocationInfoChoice)
-#endif
-
-
 const ASN1_OBJECT *CMS_get0_type(CMS_ContentInfo *cms)
        {
        return cms->contentType;
@@ -139,6 +133,14 @@ BIO *CMS_dataInit(CMS_ContentInfo *cms, BIO *icont)
                break;
 #endif
 
+               case NID_pkcs7_encrypted:
+               cmsbio = cms_EncryptedData_init_bio(cms);
+               break;
+
+               case NID_pkcs7_enveloped:
+               cmsbio = cms_EnvelopedData_init_bio(cms);
+               break;
+
                default:
                CMSerr(CMS_F_CMS_DATAINIT, CMS_R_UNSUPPORTED_TYPE);
                return NULL;
@@ -152,7 +154,7 @@ BIO *CMS_dataInit(CMS_ContentInfo *cms, BIO *icont)
        return NULL;
 
        }
-               
+
 int CMS_dataFinal(CMS_ContentInfo *cms, BIO *cmsbio)
        {
        ASN1_OCTET_STRING **pos = CMS_get0_content(cms);
@@ -182,6 +184,8 @@ int CMS_dataFinal(CMS_ContentInfo *cms, BIO *cmsbio)
                {
 
                case NID_pkcs7_data:
+               case NID_pkcs7_enveloped:
+               case NID_pkcs7_encrypted:
                case NID_id_smime_ct_compressedData:
                /* Nothing to do */
                return 1;
@@ -402,16 +406,17 @@ int cms_DigestAlgorithm_find_ctx(EVP_MD_CTX *mctx, BIO *chain,
                        return 0;
                        }
                BIO_get_md_ctx(chain, &mtmp);
-               if (EVP_MD_CTX_type(mtmp) == nid)
-                       {
-                       EVP_MD_CTX_copy_ex(mctx, mtmp);
-                       return 1;
-                       }
+               if (EVP_MD_CTX_type(mtmp) == nid
+               /* Workaround for broken implementations that use signature
+                * algorithm  OID instead of digest.
+                */
+                       || EVP_MD_pkey_type(EVP_MD_CTX_md(mtmp)) == nid)
+                       return EVP_MD_CTX_copy_ex(mctx, mtmp);
                chain = BIO_next(chain);
                }
        }
 
-STACK_OF(CMS_CertificateChoices) **cms_get0_certificate_choices(CMS_ContentInfo *cms)
+static STACK_OF(CMS_CertificateChoices) **cms_get0_certificate_choices(CMS_ContentInfo *cms)
        {
        switch (OBJ_obj2nid(cms->contentType))
                {
@@ -468,8 +473,11 @@ int CMS_add0_cert(CMS_ContentInfo *cms, X509 *cert)
                if (cch->type == CMS_CERTCHOICE_CERT)
                        {
                        if (!X509_cmp(cch->d.certificate, cert))
-                               return -1;
-                               
+                               {
+                               CMSerr(CMS_F_CMS_ADD0_CERT, 
+                                       CMS_R_CERTIFICATE_ALREADY_PRESENT);
+                               return 0;
+                               }
                        }
                }
        cch = CMS_add0_CertificateChoices(cms);
@@ -489,7 +497,7 @@ int CMS_add1_cert(CMS_ContentInfo *cms, X509 *cert)
        return r;
        }
 
-STACK_OF(CMS_RevocationInfoChoice) **cms_get0_revocation_choices(CMS_ContentInfo *cms)
+static STACK_OF(CMS_RevocationInfoChoice) **cms_get0_revocation_choices(CMS_ContentInfo *cms)
        {
        switch (OBJ_obj2nid(cms->contentType))
                {
@@ -541,6 +549,15 @@ int CMS_add0_crl(CMS_ContentInfo *cms, X509_CRL *crl)
        return 1;
        }
 
+int CMS_add1_crl(CMS_ContentInfo *cms, X509_CRL *crl)
+       {
+       int r;
+       r = CMS_add0_crl(cms, crl);
+       if (r > 0)
+               CRYPTO_add(&crl->references, 1, CRYPTO_LOCK_X509_CRL);
+       return r;
+       }
+
 STACK_OF(X509) *CMS_get1_certs(CMS_ContentInfo *cms)
        {
        STACK_OF(X509) *certs = NULL;