Skip to content

Commit 8aaab8e

Browse files
committed
Add client certificate auth
1 parent 04bd29c commit 8aaab8e

File tree

1 file changed

+45
-13
lines changed

1 file changed

+45
-13
lines changed

src/imp/mbedtls.rs

Lines changed: 45 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -244,17 +244,14 @@ pub struct TlsConnector {
244244
min_protocol: Option<Protocol>,
245245
max_protocol: Option<Protocol>,
246246
root_certificates: Vec<::Certificate>,
247+
identity: Option<::Identity>,
247248
accept_invalid_certs: bool,
248249
accept_invalid_hostnames: bool,
249250
use_sni: bool,
250251
}
251252

252253
impl TlsConnector {
253254
pub fn new(builder: &TlsConnectorBuilder) -> Result<TlsConnector, Error> {
254-
if builder.identity.is_some() {
255-
return Err(Error::Custom("Client authentication not supported".to_owned()));
256-
}
257-
258255
let trust_roots = if builder.root_certificates.len() > 0 {
259256
builder.root_certificates.clone()
260257
} else {
@@ -265,6 +262,7 @@ impl TlsConnector {
265262
min_protocol: builder.min_protocol,
266263
max_protocol: builder.max_protocol,
267264
root_certificates: trust_roots,
265+
identity: builder.identity.clone(),
268266
accept_invalid_certs: builder.accept_invalid_certs,
269267
accept_invalid_hostnames: builder.accept_invalid_hostnames,
270268
use_sni: builder.use_sni
@@ -277,6 +275,33 @@ impl TlsConnector {
277275
{
278276
// If any of the ? fail then memory leaks ...
279277

278+
let identity = if let Some(identity) = &self.identity {
279+
let mut keys = (identity.0).0.private_keys().collect::<Vec<_>>();
280+
let certificates = (identity.0).0.certificates().collect::<Vec<_>>();
281+
282+
if keys.len() != 1 {
283+
return Err(HandshakeError::Failure(Error::Custom("Unexpected number of keys in PKCS12 file".to_owned())))
284+
}
285+
if certificates.len() == 0 {
286+
return Err(HandshakeError::Failure(Error::Custom("PKCS12 file is missing certificate chain".to_owned())))
287+
}
288+
289+
let mut cert_chain = vec![];
290+
for cert in certificates {
291+
cert_chain.push(cert.0?);
292+
}
293+
294+
fn pk_clone(pk: &mut Pk) -> TlsResult<Pk> {
295+
let der = pk.write_private_der_vec()?;
296+
Pk::from_private_key(&der, None)
297+
}
298+
let key = Box::new(keys.pop().unwrap().0.map_err(|_| TlsError::PkInvalidAlg)?);
299+
300+
Some((cert_chain, key))
301+
} else {
302+
None
303+
};
304+
280305
unsafe {
281306
let ca_vec = Box::into_raw(Box::new(cert_to_vec(&self.root_certificates)));
282307
let ca_list = Box::into_raw(Box::new(CertList::from_vec(&mut *ca_vec).ok_or(TlsError::AesInvalidKeyLength)?));
@@ -286,6 +311,17 @@ impl TlsConnector {
286311
(*config).set_rng(Some(&mut *rng));
287312
(*config).set_ca_list(Some(&mut *ca_list), None);
288313

314+
let mut cred_certs = ::std::ptr::null_mut();
315+
let mut cred_cert_list = ::std::ptr::null_mut();
316+
let mut cred_pk = ::std::ptr::null_mut();
317+
318+
if let Some((certificates,mut pk)) = identity {
319+
cred_certs = Box::into_raw(Box::new(certificates.to_vec()));
320+
cred_cert_list = Box::into_raw(Box::new(CertList::from_vec(&mut *cred_certs).ok_or(TlsError::CamelliaInvalidInputLength)?));
321+
cred_pk = Box::into_raw(Box::new(Pk::from_private_key(&pk.write_private_der_vec()?, None)?));
322+
(*config).push_cert(&mut *cred_cert_list, &mut *cred_pk)?;
323+
}
324+
289325
if self.accept_invalid_certs {
290326
(*config).set_authmode(mbedtls::ssl::config::AuthMode::None);
291327
}
@@ -309,9 +345,9 @@ impl TlsConnector {
309345
role: ProtocolRole::Client,
310346
ca_certs: ca_vec,
311347
ca_cert_list: ca_list,
312-
cred_pk: ::std::ptr::null_mut(),
313-
cred_certs: ::std::ptr::null_mut(),
314-
cred_cert_list: ::std::ptr::null_mut(),
348+
cred_pk: cred_pk,
349+
cred_certs: cred_certs,
350+
cred_cert_list: cred_cert_list,
315351
entropy: entropy,
316352
rng: rng,
317353
config: config,
@@ -358,14 +394,10 @@ impl TlsAcceptor {
358394
cert_chain.push(cert.0?);
359395
}
360396

361-
fn pk_clone(pk: &mut Pk) -> TlsResult<Pk> {
362-
let der = pk.write_private_der_vec()?;
363-
Pk::from_private_key(&der, None)
364-
}
397+
let key : &mut Pk = &mut keys.pop().unwrap().0.map_err(|_| TlsError::PkInvalidAlg)?;
365398

366399
unsafe {
367-
let key : &mut Pk = &mut keys.pop().unwrap().0.map_err(|_| TlsError::PkInvalidAlg)?;
368-
let pk = Box::into_raw(Box::new(pk_clone(key)?));
400+
let pk = Box::into_raw(Box::new(Pk::from_private_key(&key.write_private_der_vec()?, None)?));
369401
let cert_chain = Box::into_raw(Box::new(cert_chain.to_vec()));
370402
let cert_list = Box::into_raw(Box::new(CertList::from_vec(&mut *cert_chain).ok_or(TlsError::CamelliaInvalidInputLength)?));
371403
let entropy = Box::into_raw(Box::new(OsEntropy::new()));

0 commit comments

Comments
 (0)