diff --git a/src/imp/openssl.rs b/src/imp/openssl.rs index 389caa5e..5ade71ce 100644 --- a/src/imp/openssl.rs +++ b/src/imp/openssl.rs @@ -200,6 +200,11 @@ impl Certificate { Ok(Certificate(cert)) } + pub fn stack_from_pem(buf: &[u8]) -> Result, Error> { + let mut certs = X509::stack_from_pem(buf)?; + Ok(certs.drain(..).map(Certificate).collect()) + } + pub fn to_der(&self) -> Result, Error> { let der = self.0.to_der()?; Ok(der) diff --git a/src/imp/schannel.rs b/src/imp/schannel.rs index 62e5042f..92f5e0d2 100644 --- a/src/imp/schannel.rs +++ b/src/imp/schannel.rs @@ -172,6 +172,13 @@ impl Certificate { } } + pub fn stack_from_pem(buf: &[u8]) -> Result, Error> { + pem::PemBlock::new(buf) + .iter() + .map(|pem| CertContext::from_pem(pem).map(Certificate)) + .collect() + } + pub fn to_der(&self) -> Result, Error> { Ok(self.0.to_der().to_vec()) } diff --git a/src/imp/security_framework.rs b/src/imp/security_framework.rs index 5a89dfa8..2ad06870 100644 --- a/src/imp/security_framework.rs +++ b/src/imp/security_framework.rs @@ -219,6 +219,22 @@ impl Certificate { panic!("Not implemented on iOS"); } + #[cfg(not(target_os = "ios"))] + pub fn stack_from_pem(buf: &[u8]) -> Result, Error> { + let mut items = SecItems::default(); + ImportOptions::new().items(&mut items).import(buf)?; + if items.identities.is_empty() && items.keys.is_empty() { + Ok(items.certificates.drain(..).map(Certificate).collect()) + } else { + Err(Error(base::Error::from(errSecParam))) + } + } + + #[cfg(target_os = "ios")] + pub fn stack_from_pem(buf: &[u8]) -> Result, Error> { + panic!("Not implemented on iOS"); + } + pub fn to_der(&self) -> Result, Error> { Ok(self.0.to_der()) } diff --git a/src/lib.rs b/src/lib.rs index 14dabb7b..92c45b32 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -209,6 +209,12 @@ impl Certificate { Ok(Certificate(cert)) } + /// Parses some PEM-formatted X509 certificates. + pub fn stack_from_pem(buf: &[u8]) -> Result> { + let mut certs = imp::Certificate::stack_from_pem(buf)?; + Ok(certs.drain(..).map(Certificate).collect()) + } + /// Returns the DER-encoded representation of this certificate. pub fn to_der(&self) -> Result> { let der = self.0.to_der()?;