Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 36 additions & 13 deletions boring/src/pkcs12.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use std::ptr;
use crate::error::ErrorStack;
use crate::nid::Nid;
use crate::pkey::{HasPrivate, PKey, PKeyRef, Private};
use crate::stack::Stack;
use crate::stack::{Stack, StackRef};
use crate::x509::{X509Ref, X509};
use crate::{cvt_0i, cvt_p};

Expand All @@ -31,33 +31,43 @@ impl Pkcs12Ref {
ffi::i2d_PKCS12
}

/// Extracts the contents of the `Pkcs12`.
/// Extracts the contents of the `Pkcs12` with `pkey` and `cert` required.
pub fn parse(&self, pass: &str) -> Result<ParsedPkcs12, ErrorStack> {
let p2 = self.parse2(pass)?;
Ok(ParsedPkcs12 {
pkey: p2
.pkey
.ok_or_else(|| ErrorStack::internal_error_str("missing pkey"))?,
cert: p2
.cert
.ok_or_else(|| ErrorStack::internal_error_str("missing cert"))?,
chain: p2.ca,
})
}

/// Extracts the contents of the `Pkcs12` with `pkey` and `cert` optional.
#[corresponds(PKCS12_parse)]
pub fn parse2(&self, pass: &str) -> Result<ParsedPkcs12_2, ErrorStack> {
unsafe {
let pass = CString::new(pass.as_bytes()).map_err(ErrorStack::internal_error)?;

let mut pkey = ptr::null_mut();
let mut cert = ptr::null_mut();
let mut chain = ptr::null_mut();
let mut ca = ptr::null_mut();

cvt_0i(ffi::PKCS12_parse(
self.as_ptr(),
pass.as_ptr(),
&mut pkey,
&mut cert,
&mut chain,
&mut ca,
))?;

let pkey = PKey::from_ptr(pkey);
let cert = X509::from_ptr(cert);
let pkey = (!pkey.is_null()).then(|| PKey::from_ptr(pkey));
let cert = (!cert.is_null()).then(|| X509::from_ptr(cert));
let ca = (!ca.is_null()).then(|| Stack::from_ptr(ca));

let chain = if chain.is_null() {
None
} else {
Some(Stack::from_ptr(chain))
};

Ok(ParsedPkcs12 { pkey, cert, chain })
Ok(ParsedPkcs12_2 { pkey, cert, ca })
}
}
}
Expand Down Expand Up @@ -100,6 +110,19 @@ pub struct ParsedPkcs12 {
pub chain: Option<Stack<X509>>,
}

/// [`ParsedPkcs12`] with optional fields
pub struct ParsedPkcs12_2 {
pub pkey: Option<PKey<Private>>,
pub cert: Option<X509>,
pub ca: Option<Stack<X509>>,
}

impl ParsedPkcs12_2 {
pub fn chain(&self) -> Option<&StackRef<X509>> {
self.ca.as_deref()
}
}

pub struct Pkcs12Builder {
nid_key: Nid,
nid_cert: Nid,
Expand Down
32 changes: 22 additions & 10 deletions boring/src/ssl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1272,15 +1272,26 @@ impl SslContextBuilder {
/// The file should contain a sequence of PEM-formatted CA certificates.
#[corresponds(SSL_CTX_load_verify_locations)]
pub fn set_ca_file<P: AsRef<Path>>(&mut self, file: P) -> Result<(), ErrorStack> {
self.load_verify_locations(Some(file.as_ref()), None)
}

/// Loads trusted root certificates from a file and/or a directory.
#[corresponds(SSL_CTX_load_verify_locations)]
pub fn load_verify_locations(
&mut self,
ca_file: Option<&Path>,
ca_path: Option<&Path>,
) -> Result<(), ErrorStack> {
self.ctx.check_x509();

let file = CString::new(file.as_ref().as_os_str().as_encoded_bytes())
.map_err(ErrorStack::internal_error)?;
let ca_file = ca_file.map(path_to_cstring).transpose()?;
let ca_path = ca_path.map(path_to_cstring).transpose()?;

unsafe {
cvt(ffi::SSL_CTX_load_verify_locations(
self.as_ptr(),
file.as_ptr(),
ptr::null(),
ca_file.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
ca_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
))
}
}
Expand Down Expand Up @@ -1341,8 +1352,7 @@ impl SslContextBuilder {
) -> Result<(), ErrorStack> {
self.ctx.check_x509();

let file = CString::new(file.as_ref().as_os_str().as_encoded_bytes())
.map_err(ErrorStack::internal_error)?;
let file = path_to_cstring(file.as_ref())?;
unsafe {
cvt(ffi::SSL_CTX_use_certificate_file(
self.as_ptr(),
Expand All @@ -1362,8 +1372,7 @@ impl SslContextBuilder {
&mut self,
file: P,
) -> Result<(), ErrorStack> {
let file = CString::new(file.as_ref().as_os_str().as_encoded_bytes())
.map_err(ErrorStack::internal_error)?;
let file = path_to_cstring(file.as_ref())?;
unsafe {
cvt(ffi::SSL_CTX_use_certificate_chain_file(
self.as_ptr(),
Expand Down Expand Up @@ -1403,8 +1412,7 @@ impl SslContextBuilder {
file: P,
file_type: SslFiletype,
) -> Result<(), ErrorStack> {
let file = CString::new(file.as_ref().as_os_str().as_encoded_bytes())
.map_err(ErrorStack::internal_error)?;
let file = path_to_cstring(file.as_ref())?;
unsafe {
cvt(ffi::SSL_CTX_use_PrivateKey_file(
self.as_ptr(),
Expand Down Expand Up @@ -4574,3 +4582,7 @@ unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f)
}

fn path_to_cstring(path: &Path) -> Result<CString, ErrorStack> {
CString::new(path.as_os_str().as_encoded_bytes()).map_err(ErrorStack::internal_error)
}
Loading