PKCS #12 support
This commit is contained in:
parent
ad4a8cc140
commit
6b12a0cdde
|
|
@ -1086,6 +1086,10 @@ extern "C" {
|
|||
-> c_int;
|
||||
pub fn PKCS12_free(p12: *mut PKCS12);
|
||||
|
||||
pub fn sk_free(st: *mut _STACK);
|
||||
pub fn sk_pop_free(st: *mut _STACK, free: Option<unsafe extern "C" fn (*mut c_void)>);
|
||||
pub fn sk_pop(st: *mut _STACK) -> *mut c_char;
|
||||
|
||||
pub fn SSLeay() -> c_long;
|
||||
pub fn SSLeay_version(key: c_int) -> *const c_char;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,8 +4,11 @@ use ffi;
|
|||
use libc::{c_long, c_uchar};
|
||||
use std::cmp;
|
||||
use std::ptr;
|
||||
use std::ffi::CString;
|
||||
|
||||
use crypto::pkey::PKey;
|
||||
use error::ErrorStack;
|
||||
use x509::X509;
|
||||
|
||||
/// A PKCS #12 archive.
|
||||
pub struct Pkcs12(*mut ffi::PKCS12);
|
||||
|
|
@ -19,21 +22,69 @@ impl Drop for Pkcs12 {
|
|||
impl Pkcs12 {
|
||||
pub fn from_der(der: &[u8]) -> Result<Pkcs12, ErrorStack> {
|
||||
unsafe {
|
||||
ffi::init();
|
||||
let mut ptr = der.as_ptr() as *const c_uchar;
|
||||
let length = cmp::min(der.len(), c_long::max_value() as usize) as c_long;
|
||||
let p12 = try_ssl_null!(ffi::d2i_PKCS12(ptr::null_mut(), &mut ptr, length));
|
||||
Ok(Pkcs12(p12))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse(&self, pass: &str) -> Result<ParsedPkcs12, ErrorStack> {
|
||||
unsafe {
|
||||
let pass = CString::new(pass).unwrap();
|
||||
|
||||
let mut pkey = ptr::null_mut();
|
||||
let mut cert = ptr::null_mut();
|
||||
let mut chain = ptr::null_mut();
|
||||
|
||||
try_ssl!(ffi::PKCS12_parse(self.0, pass.as_ptr(), &mut pkey, &mut cert, &mut chain));
|
||||
|
||||
let pkey = PKey::from_ptr(pkey);
|
||||
let cert = X509::from_ptr(cert);
|
||||
|
||||
let mut chain_out = vec![];
|
||||
for i in 0..(*chain).stack.num {
|
||||
let x509 = *(*chain).stack.data.offset(i as isize) as *mut _;
|
||||
chain_out.push(X509::from_ptr(x509));
|
||||
}
|
||||
ffi::sk_free(&mut (*chain).stack);
|
||||
|
||||
Ok(ParsedPkcs12 {
|
||||
pkey: pkey,
|
||||
cert: cert,
|
||||
chain: chain_out,
|
||||
_p: (),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ParsedPkcs12 {
|
||||
pub pkey: PKey,
|
||||
pub cert: X509,
|
||||
pub chain: Vec<X509>,
|
||||
_p: (),
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crypto::hash::Type::SHA1;
|
||||
use serialize::hex::ToHex;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn from_der() {
|
||||
fn parse() {
|
||||
let der = include_bytes!("../../test/identity.p12");
|
||||
Pkcs12::from_der(der).unwrap();
|
||||
let pkcs12 = Pkcs12::from_der(der).unwrap();
|
||||
let parsed = pkcs12.parse("mypass").unwrap();
|
||||
|
||||
assert_eq!(parsed.cert.fingerprint(SHA1).unwrap().to_hex(),
|
||||
"59172d9313e84459bcff27f967e79e6e9217e584");
|
||||
|
||||
assert_eq!(parsed.chain.len(), 1);
|
||||
assert_eq!(parsed.chain[0].fingerprint(SHA1).unwrap().to_hex(),
|
||||
"c0cbdf7cdd03c9773e5468e1f6d2da7d5cbb1875");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -933,7 +933,7 @@ impl<'a> SslRef<'a> {
|
|||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(X509::new(ptr))
|
||||
Some(X509::from_ptr(ptr))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ impl X509StoreContext {
|
|||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(X509Ref::new(ptr))
|
||||
Some(X509Ref::from_ptr(ptr))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -298,7 +298,7 @@ impl X509Generator {
|
|||
|
||||
unsafe {
|
||||
let x509 = try_ssl_null!(ffi::X509_new());
|
||||
let x509 = X509::new(x509);
|
||||
let x509 = X509::from_ptr(x509);
|
||||
|
||||
try_ssl!(ffi::X509_set_version(x509.as_ptr(), 2));
|
||||
try_ssl!(ffi::ASN1_INTEGER_set(ffi::X509_get_serialNumber(x509.as_ptr()),
|
||||
|
|
@ -377,8 +377,14 @@ pub struct X509Ref<'a>(*mut ffi::X509, PhantomData<&'a ()>);
|
|||
|
||||
impl<'a> X509Ref<'a> {
|
||||
/// Creates a new `X509Ref` wrapping the provided handle.
|
||||
pub unsafe fn new(handle: *mut ffi::X509) -> X509Ref<'a> {
|
||||
X509Ref(handle, PhantomData)
|
||||
pub unsafe fn from_ptr(x509: *mut ffi::X509) -> X509Ref<'a> {
|
||||
X509Ref(x509, PhantomData)
|
||||
}
|
||||
|
||||
///
|
||||
#[deprecated(note = "renamed to `X509::from_ptr`", since = "0.8.1")]
|
||||
pub unsafe fn new(x509: *mut ffi::X509) -> X509Ref<'a> {
|
||||
X509Ref::from_ptr(x509)
|
||||
}
|
||||
|
||||
pub fn as_ptr(&self) -> *mut ffi::X509 {
|
||||
|
|
@ -451,8 +457,14 @@ pub struct X509(X509Ref<'static>);
|
|||
|
||||
impl X509 {
|
||||
/// Returns a new `X509`, taking ownership of the handle.
|
||||
pub unsafe fn from_ptr(x509: *mut ffi::X509) -> X509 {
|
||||
X509(X509Ref::from_ptr(x509))
|
||||
}
|
||||
|
||||
///
|
||||
#[deprecated(note = "renamed to `X509::from_ptr`", since = "0.8.1")]
|
||||
pub unsafe fn new(x509: *mut ffi::X509) -> X509 {
|
||||
X509(X509Ref::new(x509))
|
||||
X509::from_ptr(x509)
|
||||
}
|
||||
|
||||
/// Reads a certificate from PEM.
|
||||
|
|
@ -463,7 +475,7 @@ impl X509 {
|
|||
ptr::null_mut(),
|
||||
None,
|
||||
ptr::null_mut()));
|
||||
Ok(X509::new(handle))
|
||||
Ok(X509::from_ptr(handle))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue