diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index f0e3e18a..664cf58d 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -32,6 +32,7 @@ pub enum ASN1_TYPE {} pub enum ASN1_OBJECT {} pub enum BN_CTX {} pub enum BN_GENCB {} +pub enum CMS_ContentInfo {} pub enum CONF {} pub enum CONF_METHOD {} pub enum COMP_METHOD {} @@ -2576,4 +2577,21 @@ extern "C" { ) -> c_int; pub fn HMAC_Update(ctx: *mut HMAC_CTX, data: *const c_uchar, len: size_t) -> c_int; pub fn HMAC_Final(ctx: *mut HMAC_CTX, md: *mut c_uchar, len: *mut c_uint) -> c_int; + + #[cfg(not(libressl))] + pub fn CMS_decrypt( + cms: *mut CMS_ContentInfo, + pkey: *mut EVP_PKEY, + cert: *mut X509, + dcont: *mut BIO, + out: *mut BIO, + flags: c_uint, + ) -> c_int; + #[cfg(not(libressl))] + pub fn SMIME_read_CMS( + bio: *mut BIO, + bcont: *mut *mut BIO, + ) -> *mut CMS_ContentInfo; + #[cfg(not(libressl))] + pub fn CMS_ContentInfo_free(cms: *mut CMS_ContentInfo); } diff --git a/openssl/src/cms.rs b/openssl/src/cms.rs new file mode 100644 index 00000000..9619d0b8 --- /dev/null +++ b/openssl/src/cms.rs @@ -0,0 +1,60 @@ +//! CMS archive + +use ffi; +use foreign_types::{ForeignType, ForeignTypeRef}; +use std::ptr; +use error::ErrorStack; + +use bio::{MemBio, MemBioSlice}; + +use x509::X509; +use pkey::PKeyRef; + +use cvt; +use cvt_p; + +foreign_type! { + type CType = ffi::CMS_ContentInfo; + fn drop = ffi::CMS_ContentInfo_free; + + pub struct CmsContentInfo; + pub struct CmsContentInfoRef; +} + +impl CmsContentInfoRef { + pub fn decrypt(&self, pkey: &PKeyRef, cert: &X509) -> Result, ErrorStack> { + unsafe { + let pkey = pkey.as_ptr(); + let cert = cert.as_ptr(); + let out = try!(MemBio::new()); + let flags: u32 = 0; + + try!(cvt(ffi::CMS_decrypt( + self.as_ptr(), + pkey, + cert, + ptr::null_mut(), + out.as_ptr(), + flags.into(), + ))); + + Ok(out.get_buf().to_owned()) + } + } + +} + +impl CmsContentInfo { + pub fn smime_read_cms(smime: &[u8]) -> Result { + unsafe { + let bio = try!(MemBioSlice::new(smime)); + + let cms = try!(cvt_p(ffi::SMIME_read_CMS( + bio.as_ptr(), + ptr::null_mut(), + ))); + + Ok(CmsContentInfo::from_ptr(cms)) + } + } +} diff --git a/openssl/src/lib.rs b/openssl/src/lib.rs index a6d5e6a0..d71d8d9d 100644 --- a/openssl/src/lib.rs +++ b/openssl/src/lib.rs @@ -31,6 +31,8 @@ mod util; pub mod aes; pub mod asn1; pub mod bn; +#[cfg(not(libressl))] +pub mod cms; pub mod conf; pub mod crypto; pub mod dh; diff --git a/systest/build.rs b/systest/build.rs index 5244ea11..700d8565 100644 --- a/systest/build.rs +++ b/systest/build.rs @@ -56,7 +56,8 @@ fn main() { .header("openssl/pkcs12.h") .header("openssl/bn.h") .header("openssl/aes.h") - .header("openssl/ocsp.h"); + .header("openssl/ocsp.h") + .header("openssl/cms.h"); cfg.type_name(|s, is_struct| { // Add some `*` on some callback parameters to get function pointer to // typecheck in C, especially on MSVC.