summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteven Fackler <sfackler@gmail.com>2021-02-28 21:22:14 -0500
committerGitHub <noreply@github.com>2021-02-28 21:22:14 -0500
commitcfbe5d48a0a43a6282eed7da625387b6b059f086 (patch)
treebd8a4cdb643e8066ed9a319d8b7c6c351e793f97
parent9872a5dd7f476170372b9e119b8a6b681396b434 (diff)
parent15863bbf6f8c28de2a57ff0ad8f33449415f7eaa (diff)
downloadrust-openssl-cfbe5d48a0a43a6282eed7da625387b6b059f086.zip
Merge pull request #1420 from cmars/PKCS7_get0_signers
Add PKCS7_get0_signers as pkcs7::Pkcs7::signers.
-rw-r--r--openssl-sys/src/pkcs7.rs6
-rw-r--r--openssl/src/pkcs7.rs70
2 files changed, 74 insertions, 2 deletions
diff --git a/openssl-sys/src/pkcs7.rs b/openssl-sys/src/pkcs7.rs
index 5aa55ff8..53e7e8ab 100644
--- a/openssl-sys/src/pkcs7.rs
+++ b/openssl-sys/src/pkcs7.rs
@@ -49,6 +49,12 @@ extern "C" {
flags: c_int,
) -> c_int;
+ pub fn PKCS7_get0_signers(
+ pkcs7: *mut PKCS7,
+ certs: *mut stack_st_X509,
+ flags: c_int,
+ ) -> *mut stack_st_X509;
+
pub fn PKCS7_sign(
signcert: *mut X509,
pkey: *mut EVP_PKEY,
diff --git a/openssl/src/pkcs7.rs b/openssl/src/pkcs7.rs
index 577ee16b..f314ae18 100644
--- a/openssl/src/pkcs7.rs
+++ b/openssl/src/pkcs7.rs
@@ -1,12 +1,13 @@
use bitflags::bitflags;
-use foreign_types::ForeignTypeRef;
+use foreign_types::{ForeignType, ForeignTypeRef};
use libc::c_int;
+use std::mem;
use std::ptr;
use crate::bio::{MemBio, MemBioSlice};
use crate::error::ErrorStack;
use crate::pkey::{HasPrivate, PKeyRef};
-use crate::stack::StackRef;
+use crate::stack::{Stack, StackRef};
use crate::symm::Cipher;
use crate::x509::store::X509StoreRef;
use crate::x509::{X509Ref, X509};
@@ -281,10 +282,40 @@ impl Pkcs7Ref {
Ok(())
}
+
+ /// Retrieve the signer's certificates from the PKCS#7 structure without verifying them.
+ ///
+ /// This corresponds to [`PKCS7_get0_signers`].
+ ///
+ /// [`PKCS7_get0_signers`]: https://www.openssl.org/docs/man1.0.2/crypto/PKCS7_verify.html
+ pub fn signers(
+ &self,
+ certs: &StackRef<X509>,
+ flags: Pkcs7Flags,
+ ) -> Result<Stack<X509>, ErrorStack> {
+ unsafe {
+ let ptr = cvt_p(ffi::PKCS7_get0_signers(
+ self.as_ptr(),
+ certs.as_ptr(),
+ flags.bits,
+ ))?;
+
+ // The returned stack is owned by the caller, but the certs inside are not! Our stack interface can't deal
+ // with that, so instead we just manually bump the refcount of the certs so that the whole stack is properly
+ // owned.
+ let stack = Stack::<X509>::from_ptr(ptr);
+ for cert in &stack {
+ mem::forget(cert.to_owned());
+ }
+
+ Ok(stack)
+ }
+ }
}
#[cfg(test)]
mod tests {
+ use crate::hash::MessageDigest;
use crate::pkcs7::{Pkcs7, Pkcs7Flags};
use crate::pkey::PKey;
use crate::stack::Stack;
@@ -399,6 +430,41 @@ mod tests {
}
#[test]
+ fn signers() {
+ let cert = include_bytes!("../test/cert.pem");
+ let cert = X509::from_pem(cert).unwrap();
+ let cert_digest = cert.digest(MessageDigest::sha256()).unwrap();
+ let certs = Stack::new().unwrap();
+ let message = "foo";
+ 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");
+
+ let root_ca = include_bytes!("../test/root-ca.pem");
+ let root_ca = X509::from_pem(root_ca).unwrap();
+ store_builder.add_cert(root_ca).expect("should succeed");
+
+ let pkcs7 =
+ Pkcs7::sign(&cert, &pkey, &certs, message.as_bytes(), flags).expect("should succeed");
+
+ let signed = pkcs7
+ .to_smime(message.as_bytes(), flags)
+ .expect("should succeed");
+
+ let (pkcs7_decoded, _) = Pkcs7::from_smime(signed.as_slice()).expect("should succeed");
+
+ let empty_certs = Stack::new().unwrap();
+ let signer_certs = pkcs7_decoded
+ .signers(&empty_certs, flags)
+ .expect("should succeed");
+ assert_eq!(empty_certs.len(), 0);
+ assert_eq!(signer_certs.len(), 1);
+ let signer_digest = signer_certs[0].digest(MessageDigest::sha256()).unwrap();
+ assert_eq!(*cert_digest, *signer_digest);
+ }
+
+ #[test]
fn invalid_from_smime() {
let input = String::from("Invalid SMIME Message");
let result = Pkcs7::from_smime(input.as_bytes());