Set contentType attribute just before signing to allow encapsulated content
[openssl.git] / crypto / cms / cms_sd.c
index 52860975f6086ea44e0cda67228ee205f4750a71..e862872f398943b2e3c1c42f938786c83f13e906 100644 (file)
@@ -87,6 +87,7 @@ static CMS_SignedData *cms_signed_data_init(CMS_ContentInfo *cms)
                cms->d.signedData->version = 1;
                cms->d.signedData->encapContentInfo->eContentType =
                                                OBJ_nid2obj(NID_pkcs7_data);
+               cms->d.signedData->encapContentInfo->partial = 1;
                ASN1_OBJECT_free(cms->contentType);
                cms->contentType = OBJ_nid2obj(NID_pkcs7_signed);
                return cms->d.signedData;
@@ -225,6 +226,12 @@ int cms_set1_SignerIdentifier(CMS_SignerIdentifier *sid, X509 *cert, int type)
                break;
 
                case CMS_SIGNERINFO_KEYIDENTIFIER:
+               if (!cert->skid)
+                       {
+                       CMSerr(CMS_F_CMS_SET1_SIGNERIDENTIFIER,
+                                       CMS_R_CERTIFICATE_HAS_NO_KEYID);
+                       return 0;
+                       }
                sid->d.subjectKeyIdentifier = ASN1_STRING_dup(cert->skid);
                if (!sid->d.subjectKeyIdentifier)
                        goto merr;
@@ -397,16 +404,17 @@ CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms,
 
        if (!(flags & CMS_NOATTR))
                {
-               /* Copy content type across */
-               ASN1_OBJECT *ctype =
-                               OBJ_dup(sd->encapContentInfo->eContentType); 
-               if (!ctype)
-                       goto merr;
-               i = CMS_signed_add1_attr_by_NID(si, NID_pkcs9_contentType,
-                                               V_ASN1_OBJECT, ctype, -1);
-               ASN1_OBJECT_free(ctype);
-               if (i <= 0)
-                       goto merr;
+               /* Initialialize signed attributes strutucture so other
+                * attributes such as signing time etc are added later
+                * even if we add none here.
+                */
+               if (!si->signedAttrs)
+                       {
+                       si->signedAttrs = sk_X509_ATTRIBUTE_new_null();
+                       if (!si->signedAttrs)
+                               goto merr;
+                       }
+
                if (!(flags & CMS_NOSMIMECAP))
                        {
                        STACK_OF(X509_ALGOR) *smcap = NULL;
@@ -451,7 +459,7 @@ CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms,
 
        }
 
-int CMS_add1_signingTime(CMS_SignerInfo *si, ASN1_TIME *t)
+static int cms_add1_signingTime(CMS_SignerInfo *si, ASN1_TIME *t)
        {
        ASN1_TIME *tt;
        int r = 0;
@@ -608,7 +616,8 @@ void CMS_SignerInfo_get0_algs(CMS_SignerInfo *si, EVP_PKEY **pk, X509 **signer,
                *psig = si->signatureAlgorithm;
        }
 
-int cms_SignerInfo_content_sign(CMS_SignerInfo *si, BIO *chain)
+static int cms_SignerInfo_content_sign(CMS_ContentInfo *cms,
+                                       CMS_SignerInfo *si, BIO *chain)
        {
        EVP_MD_CTX mctx;
        int r = 0;
@@ -628,6 +637,8 @@ int cms_SignerInfo_content_sign(CMS_SignerInfo *si, BIO *chain)
 
        if (CMS_signed_get_attr_count(si) >= 0)
                {
+               ASN1_OBJECT *ctype =
+                       cms->d.signedData->encapContentInfo->eContentType; 
                unsigned char md[EVP_MAX_MD_SIZE];
                unsigned int mdlen;
                EVP_DigestFinal_ex(&mctx, md, &mdlen);
@@ -635,6 +646,10 @@ int cms_SignerInfo_content_sign(CMS_SignerInfo *si, BIO *chain)
                                                V_ASN1_OCTET_STRING,
                                                md, mdlen))
                        goto err;
+               /* Copy content type across */
+               if (CMS_signed_add1_attr_by_NID(si, NID_pkcs9_contentType,
+                                       V_ASN1_OBJECT, ctype, -1) <= 0)
+                       goto err;
                if (!CMS_SignerInfo_sign(si))
                        goto err;
                }
@@ -676,9 +691,10 @@ int cms_SignedData_final(CMS_ContentInfo *cms, BIO *chain)
        for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++)
                {
                si = sk_CMS_SignerInfo_value(sinfos, i);
-               if (!cms_SignerInfo_content_sign(si, chain))
+               if (!cms_SignerInfo_content_sign(cms, si, chain))
                        return 0;
                }
+       cms->d.signedData->encapContentInfo->partial = 0;
        return 1;
        }
 
@@ -699,7 +715,7 @@ int CMS_SignerInfo_sign(CMS_SignerInfo *si)
 
        if (CMS_signed_get_attr_by_NID(si, NID_pkcs9_signingTime, -1) < 0)
                {
-               if (!CMS_add1_signingTime(si, NULL))
+               if (!cms_add1_signingTime(si, NULL))
                        goto err;
                }
 
@@ -798,9 +814,10 @@ BIO *cms_SignedData_init_bio(CMS_ContentInfo *cms)
        CMS_SignedData *sd;
        BIO *chain = NULL;
        sd = cms_get0_signed(cms);
-       cms_sd_set_version(sd);
        if (!sd)
                return NULL;
+       if (cms->d.signedData->encapContentInfo->partial)
+               cms_sd_set_version(sd);
        for (i = 0; i < sk_X509_ALGOR_num(sd->digestAlgorithms); i++)
                {
                X509_ALGOR *digestAlgorithm;
@@ -856,7 +873,7 @@ int CMS_SignerInfo_verify_content(CMS_SignerInfo *si, BIO *chain)
                                CMS_R_UNABLE_TO_FINALIZE_CONTEXT);
                        goto err;
                        }
-               if (mlen != os->length)
+               if (mlen != (unsigned int)os->length)
                        {
                        CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT,
                                CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH);