[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