Add function CMS_RecipientInfo_encrypt
[oweals/openssl.git] / crypto / cms / cms_sd.c
index 4483593f8638eafe6291a2868637a2a3187b6704..77fbd1359679fd9504b9256e85e8d806fed8a2f7 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;
@@ -608,7 +616,8 @@ void CMS_SignerInfo_get0_algs(CMS_SignerInfo *si, EVP_PKEY **pk, X509 **signer,
                *psig = si->signatureAlgorithm;
        }
 
-static 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,13 +637,20 @@ static 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);
+               if (!EVP_DigestFinal_ex(&mctx, md, &mdlen))
+                       goto err;
                if (!CMS_signed_add1_attr_by_NID(si, NID_pkcs9_messageDigest,
                                                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 +692,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;
        }
 
@@ -783,7 +800,7 @@ int CMS_SignerInfo_verify(CMS_SignerInfo *si)
                }
        r = EVP_DigestVerifyFinal(&mctx,
                        si->signature->data, si->signature->length);
-       if (!r)
+       if (r <= 0)
                CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY, CMS_R_VERIFICATION_FAILURE);
        err:
        EVP_MD_CTX_cleanup(&mctx);
@@ -800,7 +817,8 @@ BIO *cms_SignedData_init_bio(CMS_ContentInfo *cms)
        sd = cms_get0_signed(cms);
        if (!sd)
                return NULL;
-       cms_sd_set_version(sd);
+       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;