Skip to content

Commit

Permalink
CMS: add encrypt, from_der
Browse files Browse the repository at this point in the history
  • Loading branch information
tgbit committed Mar 1, 2019
1 parent 7602aed commit 546eb4d
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 0 deletions.
12 changes: 12 additions & 0 deletions openssl-sys/src/cms.rs
@@ -1,4 +1,5 @@
use libc::*;
use *;

pub enum CMS_ContentInfo {}

Expand All @@ -7,6 +8,9 @@ extern "C" {
pub fn CMS_ContentInfo_free(cms: *mut ::CMS_ContentInfo);
#[cfg(ossl101)]
pub fn i2d_CMS_ContentInfo(a: *mut ::CMS_ContentInfo, pp: *mut *mut c_uchar) -> c_int;

#[cfg(ossl101)]
pub fn d2i_CMS_ContentInfo(a: *mut *mut ::CMS_ContentInfo, pp: *mut *const c_uchar, length: c_long) -> *mut ::CMS_ContentInfo;
}

#[cfg(ossl101)]
Expand Down Expand Up @@ -67,6 +71,14 @@ extern "C" {
flags: c_uint,
) -> *mut ::CMS_ContentInfo;

#[cfg(ossl101)]
pub fn CMS_encrypt(
certs: *mut stack_st_X509,
data: *mut ::BIO,
cipher: *const EVP_CIPHER,
flags: c_uint
) -> *mut ::CMS_ContentInfo;

#[cfg(ossl101)]
pub fn CMS_decrypt(
cms: *mut ::CMS_ContentInfo,
Expand Down
75 changes: 75 additions & 0 deletions openssl/src/cms.rs
Expand Up @@ -15,6 +15,7 @@ use libc::c_uint;
use pkey::{HasPrivate, PKeyRef};
use stack::StackRef;
use x509::{X509Ref, X509};
use symm::Cipher;
use {cvt, cvt_p};

bitflags! {
Expand Down Expand Up @@ -122,6 +123,17 @@ impl CmsContentInfo {
}
}

from_der! {
/// Deserializes a DER-encoded ContentInfo structure.
///
/// This corresponds to [`d2i_CMS_ContentInfo`].
///
/// [`d2i_CMS_ContentInfo`]: https://www.openssl.org/docs/manmaster/man3/d2i_X509.html
from_der,
CmsContentInfo,
ffi::d2i_CMS_ContentInfo
}

/// Given a signing cert `signcert`, private key `pkey`, a certificate stack `certs`,
/// data `data` and flags `flags`, create a CmsContentInfo struct.
///
Expand Down Expand Up @@ -161,4 +173,67 @@ impl CmsContentInfo {
Ok(CmsContentInfo::from_ptr(cms))
}
}

/// Given a certificate stack `certs`, data `data`, cipher `cipher` and flags `flags`,
/// create a CmsContentInfo struct.
///
/// OpenSSL documentation at [`CMS_encrypt`]
///
/// [`CMS_encrypt`]: https://www.openssl.org/docs/manmaster/man3/CMS_encrypt.html
pub fn encrypt(
certs: &StackRef<X509>,
data: &[u8],
cipher: Cipher,
flags: CMSOptions,
) -> Result<CmsContentInfo, ErrorStack>
{
unsafe {
let data_bio = MemBioSlice::new(data)?;

let cms = cvt_p(ffi::CMS_encrypt(
certs.as_ptr(),
data_bio.as_ptr(),
cipher.as_ptr(),
flags.bits(),
))?;

Ok(CmsContentInfo::from_ptr(cms))
}
}
}

#[cfg(test)]
mod test {
use super::*;
use stack::Stack;
use x509::X509;
use pkcs12::Pkcs12;

#[test]
fn cms_encrypt_decrypt() {
// load cert with public key only
let pub_cert_bytes = include_bytes!("../test/cms_pubkey.der");
let pub_cert = X509::from_der(pub_cert_bytes).expect("failed to load pub cert");

// load cert with private key
let priv_cert_bytes = include_bytes!("../test/cms.p12");
let priv_cert = Pkcs12::from_der(priv_cert_bytes).expect("failed to load priv cert");
let priv_cert = priv_cert.parse("mypass").expect("failed to parse priv cert");

// encrypt cms message using public key cert
let input = String::from("My Message");
let mut cert_stack = Stack::new().expect("failed to create stack");
cert_stack.push(pub_cert).expect("failed to add pub cert to stack");

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

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

assert_eq!(input, decrypt);
}
}
Binary file added openssl/test/cms.p12
Binary file not shown.
Binary file added openssl/test/cms_pubkey.der
Binary file not shown.

0 comments on commit 546eb4d

Please sign in to comment.