summaryrefslogtreecommitdiff
path: root/openssl/src/pkcs7.rs
diff options
context:
space:
mode:
authorSam Scott <sam.scott89@gmail.com>2018-10-02 22:51:49 -0400
committerSam Scott <sam.scott89@gmail.com>2018-10-02 22:53:03 -0400
commit8ae761063cc93d14e60725c2bb1b8efa374de85e (patch)
treeb9d8d7b1aed5dbf14c751b94271ced7e41fa0020 /openssl/src/pkcs7.rs
parent2dd3736444781d0326ceb61a8aa8ea24deb3794d (diff)
downloadrust-openssl-8ae761063cc93d14e60725c2bb1b8efa374de85e.zip
Address comments.
Diffstat (limited to 'openssl/src/pkcs7.rs')
-rw-r--r--openssl/src/pkcs7.rs256
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)
}