diff options
author | Sam Scott <sam.scott89@gmail.com> | 2018-10-02 22:51:49 -0400 |
---|---|---|
committer | Sam Scott <sam.scott89@gmail.com> | 2018-10-02 22:53:03 -0400 |
commit | 8ae761063cc93d14e60725c2bb1b8efa374de85e (patch) | |
tree | b9d8d7b1aed5dbf14c751b94271ced7e41fa0020 /openssl/src/pkcs7.rs | |
parent | 2dd3736444781d0326ceb61a8aa8ea24deb3794d (diff) | |
download | rust-openssl-8ae761063cc93d14e60725c2bb1b8efa374de85e.zip |
Address comments.
Diffstat (limited to 'openssl/src/pkcs7.rs')
-rw-r--r-- | openssl/src/pkcs7.rs | 256 |
1 files changed, 126 insertions, 130 deletions
diff --git a/openssl/src/pkcs7.rs b/openssl/src/pkcs7.rs index 40569eaf..54c1638c 100644 --- a/openssl/src/pkcs7.rs +++ b/openssl/src/pkcs7.rs @@ -6,112 +6,49 @@ use error::ErrorStack; use stack::Stack; use foreign_types::ForeignType; use symm::Cipher; -use pkey::{HasPrivate, Public, PKeyRef}; +use pkey::{HasPrivate, PKeyRef}; use libc::c_int; use std::ptr::null_mut; use foreign_types::ForeignTypeRef; use {cvt, cvt_p}; -generic_foreign_type_and_impl_send_sync! { +foreign_type_and_impl_send_sync! { type CType = ffi::PKCS7; fn drop = ffi::PKCS7_free; /// A PKCS#7 structure. /// /// Contains signed and/or encrypted data. - pub struct Pkcs7<T>; + pub struct Pkcs7; /// Reference to `Pkcs7` - pub struct Pkcs7Ref<T>; + pub struct Pkcs7Ref; } bitflags! { - pub struct PKCS7Flags: c_int { - const PKCS7_TEXT = ffi::PKCS7_TEXT; - const PKCS7_NOCERTS = ffi::PKCS7_NOCERTS; - const PKCS7_NOSIGS = ffi::PKCS7_NOSIGS; - const PKCS7_NOCHAIN = ffi::PKCS7_NOCHAIN; - const PKCS7_NOINTERN = ffi::PKCS7_NOINTERN; - const PKCS7_NOVERIFY = ffi::PKCS7_NOVERIFY; - const PKCS7_DETACHED = ffi::PKCS7_DETACHED; - const PKCS7_BINARY = ffi::PKCS7_BINARY; - const PKCS7_NOATTR = ffi::PKCS7_NOATTR; - const PKCS7_NOSMIMECAP = ffi::PKCS7_NOSMIMECAP; - const PKCS7_NOOLDMIMETYPE = ffi::PKCS7_NOOLDMIMETYPE; - const PKCS7_CRLFEOL = ffi::PKCS7_CRLFEOL; - const PKCS7_STREAM = ffi::PKCS7_STREAM; - const PKCS7_NOCRL = ffi::PKCS7_NOCRL; - const PKCS7_PARTIAL = ffi::PKCS7_PARTIAL; - const PKCS7_REUSE_DIGEST = ffi::PKCS7_REUSE_DIGEST; + pub struct Pkcs7Flags: c_int { + const TEXT = ffi::PKCS7_TEXT; + const NOCERTS = ffi::PKCS7_NOCERTS; + const NOSIGS = ffi::PKCS7_NOSIGS; + const NOCHAIN = ffi::PKCS7_NOCHAIN; + const NOINTERN = ffi::PKCS7_NOINTERN; + const NOVERIFY = ffi::PKCS7_NOVERIFY; + const DETACHED = ffi::PKCS7_DETACHED; + const BINARY = ffi::PKCS7_BINARY; + const NOATTR = ffi::PKCS7_NOATTR; + const NOSMIMECAP = ffi::PKCS7_NOSMIMECAP; + const NOOLDMIMETYPE = ffi::PKCS7_NOOLDMIMETYPE; + const CRLFEOL = ffi::PKCS7_CRLFEOL; + const STREAM = ffi::PKCS7_STREAM; + const NOCRL = ffi::PKCS7_NOCRL; + const PARTIAL = ffi::PKCS7_PARTIAL; + const REUSE_DIGEST = ffi::PKCS7_REUSE_DIGEST; #[cfg(not(any(ossl101, ossl102, libressl)))] - const PKCS7_NO_DUAL_CONTENT = ffi::PKCS7_NO_DUAL_CONTENT; + const NO_DUAL_CONTENT = ffi::PKCS7_NO_DUAL_CONTENT; } } -impl Pkcs7<Public> { - /// Converts PKCS#7 structure to S/MIME format - /// - /// This corresponds to [`SMIME_write_PKCS7`]. - /// - /// [`SMIME_write_PKCS7`]: https://www.openssl.org/docs/man1.1.0/crypto/SMIME_write_PKCS7.html - pub fn to_smime( - &self, - input: &[u8], - flags: PKCS7Flags - ) -> Result<Vec<u8>, ErrorStack> - { - ffi::init(); - - let input_bio = MemBioSlice::new(input)?; - let output = MemBio::new()?; - unsafe { - cvt( - ffi::SMIME_write_PKCS7( - output.as_ptr(), - self.0, - input_bio.as_ptr(), - flags.bits) - ).and( - Ok(output.get_buf().to_owned()) - ) - } - } - - /// Parses a message in S/MIME format. - /// - /// This corresponds to [`SMIME_read_PKCS7`]. - /// - /// [`SMIME_read_PKCS7`]: https://www.openssl.org/docs/man1.1.0/crypto/SMIME_read_PKCS7.html - pub fn from_smime(input: &[u8], bcont: &mut Vec<u8>) -> Result<Self, ErrorStack> { - ffi::init(); - - let input_bio = MemBioSlice::new(input)?; - let mut bcount_bio = null_mut(); - let pkcs7 = unsafe { - cvt_p(ffi::SMIME_read_PKCS7(input_bio.as_ptr(), &mut bcount_bio))? - }; - bcont.clear(); - if !bcount_bio.is_null() { - let bcount_bio = MemBio::from_ptr(bcount_bio); - bcont.append(&mut bcount_bio.get_buf().to_vec()); - } - unsafe { - Ok(Pkcs7::from_ptr(pkcs7)) - } - } - - to_pem! { - /// Serializes the data into a PEM-encoded PKCS#7 structure. - /// - /// The output will have a header of `-----BEGIN PKCS7-----`. - /// - /// This corresponds to [`PEM_write_bio_PKCS7`]. - /// - /// [`PEM_write_bio_PKCS7`]: https://www.openssl.org/docs/man1.0.2/crypto/PEM_write_bio_PKCS7.html - to_pem, - ffi::PEM_write_bio_PKCS7 - } - +impl Pkcs7 { from_pem! { /// Deserializes a PEM-encoded PKCS#7 signature /// @@ -121,31 +58,32 @@ impl Pkcs7<Public> { /// /// [`PEM_read_bio_PKCS7`]: https://www.openssl.org/docs/man1.0.2/crypto/PEM_read_bio_PKCS7.html from_pem, - Pkcs7<Public>, + Pkcs7, ffi::PEM_read_bio_PKCS7 } - /// Decrypts data using the provided private key. - /// - /// `pkey` is the recipient's private key, and `cert` is the recipient's - /// certificate. - /// - /// Returns the decrypted message. + /// Parses a message in S/MIME format. + /// + /// Returns the loaded signature, along with the cleartext message (if + /// available). /// - /// This corresponds to [`PKCS7_decrypt`]. + /// This corresponds to [`SMIME_read_PKCS7`]. /// - /// [`PKCS7_decrypt`]: https://www.openssl.org/docs/man1.0.2/crypto/PKCS7_decrypt.html - pub fn decrypt<PT>(&self, pkey: &PKeyRef<PT>, cert: &X509Ref) -> Result<Vec<u8>, ErrorStack> - where - PT: HasPrivate - { + /// [`SMIME_read_PKCS7`]: https://www.openssl.org/docs/man1.1.0/crypto/SMIME_read_PKCS7.html + pub fn from_smime(input: &[u8]) -> Result<(Self, Option<Vec<u8>>), ErrorStack> { ffi::init(); - let output = MemBio::new()?; - + let input_bio = MemBioSlice::new(input)?; + let mut bcont_bio = null_mut(); unsafe { - cvt(ffi::PKCS7_decrypt(self.0, pkey.as_ptr(), cert.as_ptr(), output.as_ptr(), 0)) - .and(Ok(output.get_buf().to_owned())) + let pkcs7= cvt_p(ffi::SMIME_read_PKCS7(input_bio.as_ptr(), &mut bcont_bio))?; + let out = if !bcont_bio.is_null() { + let bcont_bio = MemBio::from_ptr(bcont_bio); + Some(bcont_bio.get_buf().to_vec()) + } else { + None + }; + Ok((Pkcs7::from_ptr(pkcs7), out)) } } @@ -158,7 +96,7 @@ impl Pkcs7<Public> { /// This corresponds to [`PKCS7_encrypt`]. /// /// [`PKCS7_encrypt`]: https://www.openssl.org/docs/man1.0.2/crypto/PKCS7_encrypt.html - pub fn encrypt(certs: &Stack<X509>, input: &[u8], cipher: Cipher, flags: PKCS7Flags) -> Result<Self, ErrorStack> { + pub fn encrypt(certs: &Stack<X509>, input: &[u8], cipher: Cipher, flags: Pkcs7Flags) -> Result<Self, ErrorStack> { ffi::init(); let input_bio = MemBioSlice::new(input)?; @@ -188,7 +126,7 @@ impl Pkcs7<Public> { pkey: &PKeyRef<PT>, certs: &Stack<X509>, input: &[u8], - flags: PKCS7Flags + flags: Pkcs7Flags ) -> Result<Self, ErrorStack> where PT: HasPrivate @@ -206,6 +144,72 @@ impl Pkcs7<Public> { ).map(|p| Pkcs7::from_ptr(p)) } } +} + +impl Pkcs7Ref { + /// Converts PKCS#7 structure to S/MIME format + /// + /// This corresponds to [`SMIME_write_PKCS7`]. + /// + /// [`SMIME_write_PKCS7`]: https://www.openssl.org/docs/man1.1.0/crypto/SMIME_write_PKCS7.html + pub fn to_smime( + &self, + input: &[u8], + flags: Pkcs7Flags + ) -> Result<Vec<u8>, ErrorStack> + { + ffi::init(); + + let input_bio = MemBioSlice::new(input)?; + let output = MemBio::new()?; + unsafe { + cvt( + ffi::SMIME_write_PKCS7( + output.as_ptr(), + self.as_ptr(), + input_bio.as_ptr(), + flags.bits) + ).and( + Ok(output.get_buf().to_owned()) + ) + } + } + + to_pem! { + /// Serializes the data into a PEM-encoded PKCS#7 structure. + /// + /// The output will have a header of `-----BEGIN PKCS7-----`. + /// + /// This corresponds to [`PEM_write_bio_PKCS7`]. + /// + /// [`PEM_write_bio_PKCS7`]: https://www.openssl.org/docs/man1.0.2/crypto/PEM_write_bio_PKCS7.html + to_pem, + ffi::PEM_write_bio_PKCS7 + } + + /// Decrypts data using the provided private key. + /// + /// `pkey` is the recipient's private key, and `cert` is the recipient's + /// certificate. + /// + /// Returns the decrypted message. + /// + /// This corresponds to [`PKCS7_decrypt`]. + /// + /// [`PKCS7_decrypt`]: https://www.openssl.org/docs/man1.0.2/crypto/PKCS7_decrypt.html + pub fn decrypt<PT>(&self, pkey: &PKeyRef<PT>, cert: &X509Ref) -> Result<Vec<u8>, ErrorStack> + where + PT: HasPrivate + { + ffi::init(); + + let output = MemBio::new()?; + + unsafe { + cvt(ffi::PKCS7_decrypt(self.as_ptr(), pkey.as_ptr(), cert.as_ptr(), output.as_ptr(), 0)) + .and(Ok(output.get_buf().to_owned())) + } + } /// Verifies the PKCS#7 `signedData` structure contained by `&self`. /// @@ -223,8 +227,8 @@ impl Pkcs7<Public> { store: &X509Store, indata: Option<&[u8]>, out: Option<&mut Vec<u8>>, - flags: PKCS7Flags - ) -> Result<bool, ErrorStack> { + flags: Pkcs7Flags + ) -> Result<(), ErrorStack> { ffi::init(); let out_bio = MemBio::new()?; @@ -237,13 +241,13 @@ impl Pkcs7<Public> { let result = unsafe { cvt(ffi::PKCS7_verify( - self.0, + self.as_ptr(), certs.as_ptr(), store.as_ptr(), indata_bio_ptr, out_bio.as_ptr(), flags.bits)) - .map(|r| r == 1) + .map(|_r| ()) }; if let Some(data) = out { @@ -260,8 +264,8 @@ mod tests { use x509::X509; use x509::store::X509StoreBuilder; use symm::Cipher; - use pkcs7::{Pkcs7, PKCS7Flags}; - use pkey::{PKey, Public}; + use pkcs7::{Pkcs7, Pkcs7Flags}; + use pkey::PKey; use stack::Stack; #[test] @@ -272,7 +276,7 @@ mod tests { certs.push(cert.clone()).unwrap(); let message: String = String::from("foo"); let cypher = Cipher::des_ede3_cbc(); - let flags = PKCS7Flags::PKCS7_STREAM; + let flags = Pkcs7Flags::STREAM; let pkey = include_bytes!("../test/key.pem"); let pkey = PKey::private_key_from_pem(pkey).unwrap(); @@ -280,8 +284,7 @@ mod tests { let encrypted = pkcs7.to_smime(message.as_bytes(), flags).expect("should succeed"); - let mut bcount = Vec::new(); - let pkcs7_decoded = Pkcs7::from_smime(encrypted.as_slice(), &mut bcount).expect("should succeed"); + let (pkcs7_decoded, _) = Pkcs7::from_smime(encrypted.as_slice()).expect("should succeed"); let decoded = pkcs7_decoded.decrypt(&pkey, &cert).expect("should succeed"); @@ -294,7 +297,7 @@ mod tests { let cert = X509::from_pem(cert).unwrap(); let certs = Stack::new().unwrap(); let message: String = String::from("foo"); - let flags = PKCS7Flags::PKCS7_STREAM | PKCS7Flags::PKCS7_DETACHED; + let flags = Pkcs7Flags::STREAM | Pkcs7Flags::DETACHED; let pkey = include_bytes!("../test/key.pem"); let pkey = PKey::private_key_from_pem(pkey).unwrap(); let mut store_builder = X509StoreBuilder::new().expect("should succeed"); @@ -309,16 +312,14 @@ mod tests { let signed = pkcs7.to_smime(message.as_bytes(), flags).expect("should succeed"); println!("{:?}", String::from_utf8(signed.clone()).unwrap()); - let mut bcount = Vec::new(); - let pkcs7_decoded = Pkcs7::from_smime(signed.as_slice(), &mut bcount).expect("should succeed"); + let (pkcs7_decoded, content) = Pkcs7::from_smime(signed.as_slice()).expect("should succeed"); let mut output = Vec::new(); - let result = pkcs7_decoded.verify(&certs, &store, Some(message.as_bytes()), Some(&mut output), flags) + pkcs7_decoded.verify(&certs, &store, Some(message.as_bytes()), Some(&mut output), flags) .expect("should succeed"); - assert!(result); assert_eq!(message.clone().into_bytes(), output); - assert_eq!(message.clone().into_bytes(), bcount); + assert_eq!(message.clone().into_bytes(), content.expect("should be non-empty")); } #[test] @@ -327,7 +328,7 @@ mod tests { let cert = X509::from_pem(cert).unwrap(); let certs = Stack::new().unwrap(); let message: String = String::from("foo"); - let flags = PKCS7Flags::PKCS7_STREAM; + let flags = Pkcs7Flags::STREAM; let pkey = include_bytes!("../test/key.pem"); let pkey = PKey::private_key_from_pem(pkey).unwrap(); let mut store_builder = X509StoreBuilder::new().expect("should succeed"); @@ -342,24 +343,19 @@ mod tests { let signed = pkcs7.to_smime(message.as_bytes(), flags).expect("should succeed"); - let mut bcount = Vec::new(); - let pkcs7_decoded = Pkcs7::<Public>::from_smime(signed.as_slice(), &mut bcount).expect("should succeed"); + let (pkcs7_decoded, content) = Pkcs7::from_smime(signed.as_slice()).expect("should succeed"); let mut output = Vec::new(); - let result = pkcs7_decoded.verify(&certs, &store, None, Some(&mut output), flags).expect("should succeed"); + pkcs7_decoded.verify(&certs, &store, None, Some(&mut output), flags).expect("should succeed"); - assert!(result); assert_eq!(message.clone().into_bytes(), output); - let empty: Vec<u8> = Vec::new(); - assert_eq!(empty, bcount); + assert!(content.is_none()); } #[test] fn invalid_from_smime() { let input = String::from("Invalid SMIME Message"); - let mut bcount = Vec::new(); - - let result = Pkcs7::from_smime(input.as_bytes(), &mut bcount); + let result = Pkcs7::from_smime(input.as_bytes()); assert_eq!(result.is_err(), true) } |