(tl;dr : see questions at the end)

I'm trying to build nested CMS structures, as in, having a file F, a signer S 
and a recipient R, I want to build a CMS-compliant message M which looks like:

M = SignedData(ECI, SignerInfo(S))

ECI = EncapsulatedContentInfo( EnvelopedData( RecipientInfo(R) )

Where RecipientInfo(R) contains:
[ F ] = encrypted file, [ K ] = file-encryption key, encrypted with R's public 
key.

Now the code compiles, I figure I can parse that back, but when I run `openssl 
cms` or `openssl asn1parse` on the generated DER file, the whole EnvelopedData 
show up as one big OctetString. Is that normal?

Here's my code (all error checking has been left out for brevity):

    /* Make EnvelopedData structure */

    BIO* in = BIO_new_file(in_path, "rb");
        
    int flags = CMS_BINARY | CMS_USE_KEYID | CMS_PARTIAL;
        
    CMS_ContentInfo* edata = CMS_encrypt(NULL, NULL, cipher, flags);
        
    CMS_RecipientInfo* r_info = CMS_add1_recipient_cert(edata, r_cert, flags);
        
    CMS_final(edata, in, NULL, flags);
        
    BIO* tmp = BIO_new(BIO_s_mem());
    i2d_CMS_bio(tmp, edata);            /* [1] */
        
    /* Make SignedData structure */
        
    flags|= CMS_NOSMIMECAP | CMS_NOCERTS;
        
    CMS_ContentInfo* sdata = CMS_sign(NULL, NULL, NULL, NULL, flags);
        
    ASN1_OBJECT* ectype_edata = OBJ_nid2obj(NID_pkcs7_enveloped);

    CMS_set1_eContentType(sdata, ectype_edata);

    CMS_SignerInfo* s_info =
      CMS_add1_signer(sdata, s_cert, s_key, NULL, flags);

    CMS_SignerInfo_sign(s_info);

    CMS_final(sdata, tmp, NULL, flags);

    BIO* out = BIO_new_file(out_path, "wb");

    i2d_CMS_bio(out, sdata);

    BIO_flush(out);

Now, here's the output from cms:

CMS_ContentInfo: 
  contentType: pkcs7-signedData (1.2.840.113549.1.7.2)
  d.signedData: 
    version: 3
    digestAlgorithms:
        algorithm: sha1 (1.3.14.3.2.26)
        parameter: <ABSENT>
    encapContentInfo: 
      eContentType: pkcs7-envelopedData (1.2.840.113549.1.7.3)
      eContent: 
        < LARGE OCTET STRING, A BIT LARGER THAN THE FILE >
    certificates:
      <EMPTY>
    crls:
      <EMPTY>
    signerInfos:
        version: 3
        d.subjectKeyIdentifier: 
          < KEY ID IS HERE >
        digestAlgorithm: 
          algorithm: sha1 (1.3.14.3.2.26)
          parameter: <ABSENT>
        signedAttrs:
            object: contentType (1.2.840.113549.1.9.3)
            value.set:
              OBJECT:pkcs7-envelopedData (1.2.840.113549.1.7.3)

            < ALSO UTC TIME WHATEVER >

            object: messageDigest (1.2.840.113549.1.9.4)
            value.set:
              OCTET STRING:
                < HASH GOES HERE >
        signatureAlgorithm: 
          algorithm: ecdsa-with-SHA1 (1.2.840.10045.4.1)
          parameter: <ABSENT>
        signature: 
          < SIG GOES HERE >
        unsignedAttrs:
          <EMPTY>

If I output what the BIO at [1] contains, I see this:

CMS_ContentInfo: 
  contentType: pkcs7-envelopedData (1.2.840.113549.1.7.3)
  d.envelopedData: 
    version: <ABSENT>
    originatorInfo: <ABSENT>
    recipientInfos:
      d.ktri: 
        version: 2
        d.subjectKeyIdentifier: 
          < KEY ID IS HERE >
        keyEncryptionAlgorithm: 
          algorithm: rsaEncryption (1.2.840.113549.1.1.1)
          parameter: NULL
        encryptedKey: 
          < 256-BYTES LONG OCTET STRING, SINCE RSA-2048 >
    encryptedContentInfo: 
      contentType: pkcs7-data (1.2.840.113549.1.7.1)
      contentEncryptionAlgorithm: 
        algorithm: aes-256-cbc (2.16.840.1.101.3.4.1.42)
        parameter: OCTET STRING:
          < 16 BYTES IV >
      encryptedContent: 
          < LARGE OCTET STRING, ABOUT THE SIZE OF MY FILE PLUS AES PADDING I 
FIGURE >
    unprotectedAttrs:
      <EMPTY>


So I guess my questions are:

- Does the code look OK to people who regularly use the API?
- Should I be worried the EnvelopedData show up as one big OctetString when 
cms/asn1parse parse the SignedData?
- Should I be worried the "version" field in the EnvelopedData shows <ABSENT>?

Bonus points for anyone who can tell, on the spot, me how to recover:

- the signature;
- the bytes this signature actually signs;
- the encrypted key;
- the encrypted file.

... So that I may process them by some other, non-OpenSSL means on the 
receiving end.

(I'm giving bonus points for this since OpenSSL implements all CMS types as 
opaque structures, and I haven't digged enough yet to see how to recover those 
fields. I'm starting to think maybe I should not use OpenSSL on the receiving 
end...)

Thanks in advance!
______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    openssl-users@openssl.org
Automated List Manager                           majord...@openssl.org

Reply via email to