PKCS #12 support
This commit is contained in:
parent
ad4a8cc140
commit
6b12a0cdde
|
|
@ -1086,6 +1086,10 @@ extern "C" {
|
||||||
-> c_int;
|
-> c_int;
|
||||||
pub fn PKCS12_free(p12: *mut PKCS12);
|
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() -> c_long;
|
||||||
pub fn SSLeay_version(key: c_int) -> *const c_char;
|
pub fn SSLeay_version(key: c_int) -> *const c_char;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,11 @@ use ffi;
|
||||||
use libc::{c_long, c_uchar};
|
use libc::{c_long, c_uchar};
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
use std::ffi::CString;
|
||||||
|
|
||||||
|
use crypto::pkey::PKey;
|
||||||
use error::ErrorStack;
|
use error::ErrorStack;
|
||||||
|
use x509::X509;
|
||||||
|
|
||||||
/// A PKCS #12 archive.
|
/// A PKCS #12 archive.
|
||||||
pub struct Pkcs12(*mut ffi::PKCS12);
|
pub struct Pkcs12(*mut ffi::PKCS12);
|
||||||
|
|
@ -19,21 +22,69 @@ impl Drop for Pkcs12 {
|
||||||
impl Pkcs12 {
|
impl Pkcs12 {
|
||||||
pub fn from_der(der: &[u8]) -> Result<Pkcs12, ErrorStack> {
|
pub fn from_der(der: &[u8]) -> Result<Pkcs12, ErrorStack> {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
ffi::init();
|
||||||
let mut ptr = der.as_ptr() as *const c_uchar;
|
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 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));
|
let p12 = try_ssl_null!(ffi::d2i_PKCS12(ptr::null_mut(), &mut ptr, length));
|
||||||
Ok(Pkcs12(p12))
|
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)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
|
use crypto::hash::Type::SHA1;
|
||||||
|
use serialize::hex::ToHex;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn from_der() {
|
fn parse() {
|
||||||
let der = include_bytes!("../../test/identity.p12");
|
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() {
|
if ptr.is_null() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(X509::new(ptr))
|
Some(X509::from_ptr(ptr))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@ impl X509StoreContext {
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(X509Ref::new(ptr))
|
Some(X509Ref::from_ptr(ptr))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -298,7 +298,7 @@ impl X509Generator {
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let x509 = try_ssl_null!(ffi::X509_new());
|
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::X509_set_version(x509.as_ptr(), 2));
|
||||||
try_ssl!(ffi::ASN1_INTEGER_set(ffi::X509_get_serialNumber(x509.as_ptr()),
|
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> {
|
impl<'a> X509Ref<'a> {
|
||||||
/// Creates a new `X509Ref` wrapping the provided handle.
|
/// Creates a new `X509Ref` wrapping the provided handle.
|
||||||
pub unsafe fn new(handle: *mut ffi::X509) -> X509Ref<'a> {
|
pub unsafe fn from_ptr(x509: *mut ffi::X509) -> X509Ref<'a> {
|
||||||
X509Ref(handle, PhantomData)
|
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 {
|
pub fn as_ptr(&self) -> *mut ffi::X509 {
|
||||||
|
|
@ -451,8 +457,14 @@ pub struct X509(X509Ref<'static>);
|
||||||
|
|
||||||
impl X509 {
|
impl X509 {
|
||||||
/// Returns a new `X509`, taking ownership of the handle.
|
/// 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 {
|
pub unsafe fn new(x509: *mut ffi::X509) -> X509 {
|
||||||
X509(X509Ref::new(x509))
|
X509::from_ptr(x509)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads a certificate from PEM.
|
/// Reads a certificate from PEM.
|
||||||
|
|
@ -463,7 +475,7 @@ impl X509 {
|
||||||
ptr::null_mut(),
|
ptr::null_mut(),
|
||||||
None,
|
None,
|
||||||
ptr::null_mut()));
|
ptr::null_mut()));
|
||||||
Ok(X509::new(handle))
|
Ok(X509::from_ptr(handle))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue