CMS question on encrypting and signing

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

CMS question on encrypting and signing

Philip Prindeville
Hi.

I’m working on an application that requires datagrams of ASN.1 PDU’s to be exchanged.

The application data needs to be first encrypted, then signed.  I will not be using streams, but rather memory BIO’s.

I could use the CMS_encrypt() into one BIO, then reset that and pass it as input to CMS_sign() placing its output into a 3rd BIO.

But I’m wondering if there’s an easier way to do this.  I could use chained BIO’s and a stream, but I want to avoid using streams because they place indeterminate lengths as the OCTET STRINGs followed by EOCs, which some of the implementations that I need to interact with have a hard time parsing.

If there’s a flexible way to do this, I might contribute to the library a convenience function to handle this, e.g. CMS_encrypt_sign().  Speaking of convenience functions, when do you know if you need to use CMS_dataInit(), for instance? It’s not documented...

Can someone point me in the right direction to do this efficiently?  Even though I’m not passing a lot of data in these messages, I do need to keep the latency from processing down.

Thanks,

-Philip

P.S. Back in May it sounded like Kevin Le Gouguec was trying to do something similar, so putting it into a convenience function in the library sounds like the right thing to do.


______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    [hidden email]
Automated List Manager                           [hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: CMS question on encrypting and signing

Kevin Le Gouguec
Hi,

Just chiming in to confirm your idea of using CMS_encrypt() on a BIO, then CMS_sign(). That's what I ended up doing (cf. code I posted on StackOverflow at the time[1]). If someone else knows a better approach though, I'm interested too. Hopefully the overhead from BIO/CMS juggling will not increase latency too much...

I don't know anything about CMS_dataInit(). A quick look at 1.0.1j's sources shows that it's only called in a couple of files in crypto/cms/ (notably at the beginning of CMS_final()), so maybe it's not even supposed to be part of the public API? The doc for CMS_encrypt() and CMS_sign() says that they "create and return" a new CMS structure, so I have no idea what the purpose of CMS_dataInit() is. Hopefully someone on this list will know.

Not a terribly useful answer I'm afraid :/ I hope someone else will contribute.


[1]
/* Make EnvelopedData structure */
BIO* in = BIO_new_file(in_path, "rb");

int flags = CMS_BINARY | CMS_USE_KEYID | CMS_PARTIAL | CMS_KEY_PARAM;

CMS_ContentInfo* edata = CMS_encrypt(NULL, NULL, cipher, flags);

CMS_RecipientInfo* r_info = CMS_add1_recipient_cert(edata, r_cert, flags);
EVP_PKEY_CTX* wrap_ctx = CMS_RecipientInfo_get0_pkey_ctx(r_info);

EVP_PKEY_CTX_set_rsa_padding(wrap_ctx, RSA_PKCS1_OAEP_PADDING);
EVP_PKEY_CTX_set_rsa_oaep_md(wrap_ctx, EVP_sha256());
EVP_PKEY_CTX_set_rsa_mgf1_md(wrap_ctx, EVP_sha256());
EVP_PKEY_CTX_set0_rsa_oaep_label(wrap_ctx, oaep_label, oaep_label_l);
/* NB: oaep_label must be heap-allocated, and will be freed by OSSL */

CMS_final(edata, in, NULL, flags);

BIO* tmp = BIO_new(BIO_s_mem());
i2d_CMS_bio(tmp, edata);

/* Make SignedData structure */

flags|= CMS_NOSMIMECAP | CMS_NOCERTS;
flags&= ~(CMS_KEY_PARAM);

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);


----- Original Message -----
From: "Philip Prindeville" <[hidden email]>
To: [hidden email]
Sent: Saturday, November 15, 2014 7:25:41 AM
Subject: CMS question on encrypting and signing

Hi.

I’m working on an application that requires datagrams of ASN.1 PDU’s to be exchanged.

The application data needs to be first encrypted, then signed.  I will not be using streams, but rather memory BIO’s.

I could use the CMS_encrypt() into one BIO, then reset that and pass it as input to CMS_sign() placing its output into a 3rd BIO.

But I’m wondering if there’s an easier way to do this.  I could use chained BIO’s and a stream, but I want to avoid using streams because they place indeterminate lengths as the OCTET STRINGs followed by EOCs, which some of the implementations that I need to interact with have a hard time parsing.

If there’s a flexible way to do this, I might contribute to the library a convenience function to handle this, e.g. CMS_encrypt_sign().  Speaking of convenience functions, when do you know if you need to use CMS_dataInit(), for instance? It’s not documented...

Can someone point me in the right direction to do this efficiently?  Even though I’m not passing a lot of data in these messages, I do need to keep the latency from processing down.

Thanks,

-Philip

P.S. Back in May it sounded like Kevin Le Gouguec was trying to do something similar, so putting it into a convenience function in the library sounds like the right thing to do.


______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    [hidden email]
Automated List Manager                           [hidden email]
______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    [hidden email]
Automated List Manager                           [hidden email]