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

Wim Lewis wiml at omnigroup.com
Wed Nov 23 01:09:55 UTC 2016


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.

In order to get the right output, I think I would need both a way to tell the CMS structure to use the correct data type *and* the correct contentType OID, and also a way to get to the EnvelopedData structure inside of the innerCms structure. But neither of those things seems to be accessible using the OpenSSL API.

Any hints? Surely someone has used OpenSSL to create nested structures in the past?




More information about the openssl-users mailing list