From 124c05d0580852a2ab89678f31c84cc56b17c2e4 Mon Sep 17 00:00:00 2001 From: Daniel Abramov Date: Wed, 12 Jun 2019 10:23:48 +0200 Subject: [PATCH 1/4] Add `CmsContentInfo` <-> PEM bindings --- openssl-sys/src/pem.rs | 8 ++++++++ openssl/src/cms.rs | 21 +++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/openssl-sys/src/pem.rs b/openssl-sys/src/pem.rs index dce6e0b3..6bc2eca3 100644 --- a/openssl-sys/src/pem.rs +++ b/openssl-sys/src/pem.rs @@ -146,6 +146,14 @@ extern "C" { ) -> *mut PKCS7; pub fn PEM_write_bio_PKCS7(bp: *mut BIO, x: *mut PKCS7) -> c_int; + + pub fn PEM_read_bio_CMS( + bio: *mut BIO, + out: *mut *mut CMS_ContentInfo, + callback: pem_password_cb, + user_data: *mut c_void, + ) -> *mut CMS_ContentInfo; + pub fn PEM_write_bio_CMS(bio: *mut BIO, cms: *const CMS_ContentInfo) -> c_int; } pub const PEM_R_NO_START_LINE: c_int = 108; diff --git a/openssl/src/cms.rs b/openssl/src/cms.rs index 45f4dd65..e6370e4b 100644 --- a/openssl/src/cms.rs +++ b/openssl/src/cms.rs @@ -105,6 +105,16 @@ impl CmsContentInfoRef { to_der, ffi::i2d_CMS_ContentInfo } + + to_pem! { + /// Serializes this CmsContentInfo using DER. + /// + /// OpenSSL documentation at [`PEM_write_bio_CMS`] + /// + /// [`PEM_write_bio_CMS`]: https://www.openssl.org/docs/man1.1.0/man3/PEM_write_bio_CMS.html + to_pem, + ffi::PEM_write_bio_CMS + } } impl CmsContentInfo { @@ -134,6 +144,17 @@ impl CmsContentInfo { ffi::d2i_CMS_ContentInfo } + from_pem! { + /// Deserializes a PEM-encoded ContentInfo structure. + /// + /// This corresponds to [`PEM_read_bio_CMS`]. + /// + /// [`PEM_read_bio_CMS`]: https://www.openssl.org/docs/man1.1.0/man3/PEM_read_bio_CMS.html + from_pem, + CmsContentInfo, + ffi::PEM_read_bio_CMS + } + /// Given a signing cert `signcert`, private key `pkey`, a certificate stack `certs`, /// data `data` and flags `flags`, create a CmsContentInfo struct. /// From 69ee79d435b229441dac57a824dc064734e8b4cd Mon Sep 17 00:00:00 2001 From: Daniel Abramov Date: Wed, 12 Jun 2019 10:24:53 +0200 Subject: [PATCH 2/4] Fix formatting in cms `to_der` implementation --- openssl/src/cms.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/openssl/src/cms.rs b/openssl/src/cms.rs index e6370e4b..6aacbf51 100644 --- a/openssl/src/cms.rs +++ b/openssl/src/cms.rs @@ -97,13 +97,13 @@ impl CmsContentInfoRef { } to_der! { - /// Serializes this CmsContentInfo using DER. - /// - /// OpenSSL documentation at [`i2d_CMS_ContentInfo`] - /// - /// [`i2d_CMS_ContentInfo`]: https://www.openssl.org/docs/man1.0.2/crypto/i2d_CMS_ContentInfo.html - to_der, - ffi::i2d_CMS_ContentInfo + /// Serializes this CmsContentInfo using DER. + /// + /// OpenSSL documentation at [`i2d_CMS_ContentInfo`] + /// + /// [`i2d_CMS_ContentInfo`]: https://www.openssl.org/docs/man1.0.2/crypto/i2d_CMS_ContentInfo.html + to_der, + ffi::i2d_CMS_ContentInfo } to_pem! { From ed966a09ac723c0437f7ab1e6a1a7527b1461307 Mon Sep 17 00:00:00 2001 From: Daniel Abramov Date: Wed, 12 Jun 2019 10:36:44 +0200 Subject: [PATCH 3/4] Extend CMS unit tests (pem/der conversions) --- openssl/src/cms.rs | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/openssl/src/cms.rs b/openssl/src/cms.rs index 6aacbf51..fb5d627b 100644 --- a/openssl/src/cms.rs +++ b/openssl/src/cms.rs @@ -248,13 +248,23 @@ mod test { let encrypt = CmsContentInfo::encrypt(&cert_stack, &input.as_bytes(), Cipher::des_ede3_cbc(), CMSOptions::empty()) .expect("failed create encrypted cms"); - let encrypt = encrypt.to_der().expect("failed to create der from cms"); + let encrypted_der = encrypt.to_der().expect("failed to create der from cms"); + let encrypted_pem = encrypt.to_pem().expect("failed to create pem from cms"); - // decrypt cms message using private key cert - let decrypt = CmsContentInfo::from_der(&encrypt).expect("failed read cms from der"); - let decrypt = decrypt.decrypt(&priv_cert.pkey, &priv_cert.cert).expect("failed to decrypt cms"); - let decrypt = String::from_utf8(decrypt).expect("failed to create string from cms content"); + // decrypt cms message using private key cert (DER) + { + let decrypt = CmsContentInfo::from_der(&encrypted_der).expect("failed read cms from der"); + let decrypt = decrypt.decrypt(&priv_cert.pkey, &priv_cert.cert).expect("failed to decrypt cms"); + let decrypt = String::from_utf8(decrypt).expect("failed to create string from cms content"); + assert_eq!(input, decrypt); + } - assert_eq!(input, decrypt); + // decrypt cms message using private key cert (PEM) + { + let decrypt = CmsContentInfo::from_pem(&encrypted_pem).expect("failed read cms from pem"); + let decrypt = decrypt.decrypt(&priv_cert.pkey, &priv_cert.cert).expect("failed to decrypt cms"); + let decrypt = String::from_utf8(decrypt).expect("failed to create string from cms content"); + assert_eq!(input, decrypt); + } } } From fab6ea4727dd70c36989f21d41ef21793eaa4006 Mon Sep 17 00:00:00 2001 From: Daniel Abramov Date: Wed, 12 Jun 2019 15:10:05 +0200 Subject: [PATCH 4/4] Conditionally compile PEM functions for CMS Apparently libressl does not quite support all CMS functions (well, at least the bindings for CMS are currently compile-time guarded), so CI checks inside the systest fail during the verification on libressl. This is an attempt to fix it. --- openssl-sys/src/pem.rs | 2 ++ openssl/src/cms.rs | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/openssl-sys/src/pem.rs b/openssl-sys/src/pem.rs index 6bc2eca3..64703377 100644 --- a/openssl-sys/src/pem.rs +++ b/openssl-sys/src/pem.rs @@ -147,12 +147,14 @@ extern "C" { pub fn PEM_write_bio_PKCS7(bp: *mut BIO, x: *mut PKCS7) -> c_int; + #[cfg(ossl101)] pub fn PEM_read_bio_CMS( bio: *mut BIO, out: *mut *mut CMS_ContentInfo, callback: pem_password_cb, user_data: *mut c_void, ) -> *mut CMS_ContentInfo; + #[cfg(ossl101)] pub fn PEM_write_bio_CMS(bio: *mut BIO, cms: *const CMS_ContentInfo) -> c_int; } diff --git a/openssl/src/cms.rs b/openssl/src/cms.rs index fb5d627b..21af2a80 100644 --- a/openssl/src/cms.rs +++ b/openssl/src/cms.rs @@ -248,11 +248,10 @@ mod test { let encrypt = CmsContentInfo::encrypt(&cert_stack, &input.as_bytes(), Cipher::des_ede3_cbc(), CMSOptions::empty()) .expect("failed create encrypted cms"); - let encrypted_der = encrypt.to_der().expect("failed to create der from cms"); - let encrypted_pem = encrypt.to_pem().expect("failed to create pem from cms"); // decrypt cms message using private key cert (DER) { + let encrypted_der = encrypt.to_der().expect("failed to create der from cms"); let decrypt = CmsContentInfo::from_der(&encrypted_der).expect("failed read cms from der"); let decrypt = decrypt.decrypt(&priv_cert.pkey, &priv_cert.cert).expect("failed to decrypt cms"); let decrypt = String::from_utf8(decrypt).expect("failed to create string from cms content"); @@ -261,6 +260,7 @@ mod test { // decrypt cms message using private key cert (PEM) { + let encrypted_pem = encrypt.to_pem().expect("failed to create pem from cms"); let decrypt = CmsContentInfo::from_pem(&encrypted_pem).expect("failed read cms from pem"); let decrypt = decrypt.decrypt(&priv_cert.pkey, &priv_cert.cert).expect("failed to decrypt cms"); let decrypt = String::from_utf8(decrypt).expect("failed to create string from cms content");