[openssl-users] How to produce a nested CMS / PKCS#7 structure?

Dr. Stephen Henson steve at openssl.org
Fri Nov 25 20:43:56 UTC 2016


On Tue, Nov 22, 2016, Wim Lewis wrote:

> I'm trying to produce nested structures, like signed-enveloped-signed data. This is explicitly described in the various RFCs, but I can't figure out how to get OpenSSL to produce valid output, and I can't find any code examples of doing this.
> 
> What I'm doing (which doesn't quite work) is this: first I create the inner content using (e.g.) CMS_encrypt(), getting a CMS_ContentInfo structure. This works correctly and if I write it out I get what I expect. Then I want to create another CMS_ContentInfo, e.g. using CMS_sign(), which envelops the first one. How do I cause the ContentInfo of the SignedData structure to be the ContentInfo I obtained from CMS_encrypt()? The closest I can come is code like this:
> 
> 
>     CMS_ContentInfo *innerCms = ....;        // Create the inner CMS content.
>     BIO *inbetween = BIO_new(BIO_s_mem());   // Write it to a buffer.
>     i2d_CMS_bio(inbetween, innerCms);
>     CMS_ContentInfo *outerCms = CMS_sign(cert, key, NULL, inbetween, CMS_BINARY|CMS_PARTIAL|CMS_NOSMIMECAP);
>     CMS_set1_eContentType(outerCms, OBJ_nid2obj(NID of innerCms));   // Set the content-type
>     CMS_final(outerCms, inbetween, NULL, CMS_BINARY|CMS_NOSMIMECAP); // Finalize the CMS structure
> 
> (My actual code checks all the return values, but I left those off for clarity.)
> 
> Unfortunately, this produces output like this:
> 
>    ContentInfo {
>       contentType = :pkcs7-signedData;
>       content = SignedData {
>          ... various ...
>          contentInfo = ContentInfo {
>             contentType = :pkcs7-envelopedData;
>             content = [0] EXPLICIT OctetString{...}
>          }
>       }
>     }
>  
> where the inner OCTET STRING contains *another* ContentInfo, which then contains the nested object.
> 
> But from my understanding, the correct syntax for a nested CMS structure is this:
> 
>    ContentInfo {
>       contentType = :pkcs7-signedData;
>       content = SignedData {
>          ... various ...
>          contentInfo = ContentInfo {
>             contentType = :pkcs7-envelopedData;
>             content = [0] EXPLICIT EnvelopedData {
>                 ...fields of the EnvelopedData structure...
>             }
>          }
>       }
>     }
> 
> In other words, I have two extra, incorrect levels of encapsulation: the OCTET STRING and the extra ContentInfo.
> 

Something like that did happen for PKCS#7 but the  OCTET STRING encapsulation
is correct for CMS.

If you look in RFC5652:

SignedData ::= SEQUENCE {
        version CMSVersion,
        digestAlgorithms DigestAlgorithmIdentifiers,
        encapContentInfo EncapsulatedContentInfo,
        certificates [0] IMPLICIT CertificateSet OPTIONAL,
        crls [1] IMPLICIT RevocationInfoChoices OPTIONAL,
        signerInfos SignerInfos }

The content is of type Encapsulated ConentInfo:

    EncapsulatedContentInfo ::= SEQUENCE {
        eContentType ContentType,
        eContent [0] EXPLICIT OCTET STRING OPTIONAL }

      ContentType ::= OBJECT IDENTIFIER

Here eContent is always an OCTET STRING if it is present.

It also says:

     eContent is the content itself, carried as an octet string.  The
     eContent need not be DER encoded.

Steve.
--
Dr Stephen N. Henson. OpenSSL project core developer.
Commercial tech support now available see: http://www.openssl.org


More information about the openssl-users mailing list