Skip to content

Commit e18e17c

Browse files
committed
Rename identity::PEM to Identity::PKCS8
And fix openssl and native-tls integration with it. This is a followup to 0055210
1 parent 0055210 commit e18e17c

File tree

1 file changed

+70
-44
lines changed

1 file changed

+70
-44
lines changed

src/lib.rs

Lines changed: 70 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -125,9 +125,9 @@ pub enum TcpStream {
125125

126126
/// Holds extra TLS configuration
127127
#[derive(Default, Debug, PartialEq)]
128-
pub struct TLSConfig<'der, 'cert, 'pass, 'chain> {
128+
pub struct TLSConfig<'data, 'key, 'chain> {
129129
/// Use for client certificate authentication
130-
pub identity: Option<Identity<'der, 'cert, 'pass>>,
130+
pub identity: Option<Identity<'data, 'key>>,
131131
/// The custom certificates chain in PEM format
132132
pub cert_chain: Option<&'chain str>,
133133
}
@@ -144,7 +144,7 @@ pub struct OwnedTLSConfig {
144144
impl OwnedTLSConfig {
145145
/// Get the ephemeral `TLSConfig` corresponding to the `OwnedTLSConfig`
146146
#[must_use]
147-
pub fn as_ref(&self) -> TLSConfig<'_, '_, '_, '_> {
147+
pub fn as_ref(&self) -> TLSConfig<'_, '_, '_> {
148148
TLSConfig {
149149
identity: self.identity.as_ref().map(OwnedIdentity::as_ref),
150150
cert_chain: self.cert_chain.as_deref(),
@@ -154,28 +154,28 @@ impl OwnedTLSConfig {
154154

155155
/// Holds one of:
156156
/// - PKCS#12 DER-encoded identity and decryption password
157-
/// - PEM-encoded DER identity (without decryption password)
157+
/// - PKCS#8 PEM-encoded certificate and key (without decryption password)
158158
#[derive(Debug, PartialEq)]
159-
pub enum Identity<'der, 'cert, 'pass> {
159+
pub enum Identity<'data, 'key> {
160160
/// PKCS#12 DER-encoded identity with decryption password
161161
PKCS12 {
162162
/// PKCS#12 DER-encoded identity
163-
der: &'der [u8],
163+
der: &'data [u8],
164164
/// Decryption password
165-
password: &'pass str,
165+
password: &'key str,
166166
},
167167
/// PEM encoded DER private key with PEM encoded certificate
168-
PEM {
169-
/// PEM-encoded identity
170-
der: &'der [u8],
168+
PKCS8 {
171169
/// PEM-encoded certificate
172-
cert: &'cert [u8]
173-
}
170+
pem: &'data [u8],
171+
/// PEM-encoded key
172+
key: &'key [u8],
173+
},
174174
}
175175

176176
/// Holds one of:
177177
/// - PKCS#12 DER-encoded identity and decryption password
178-
/// - PEM-encoded DER identity (without decryption password)
178+
/// - PKCS#8 PEM-encoded certificate and key (without decryption password)
179179
#[derive(Debug, PartialEq)]
180180
pub enum OwnedIdentity {
181181
/// PKCS#12 DER-encoded identity with decryption password
@@ -185,22 +185,22 @@ pub enum OwnedIdentity {
185185
/// Decryption password
186186
password: String,
187187
},
188-
/// PEM encoded DER private key with PEM encoded certificate
189-
PEM {
190-
/// PEM-encoded identity
191-
der: Vec<u8>,
188+
/// PKCS#8 encoded DER private key with PEM encoded certificate
189+
PKCS8 {
192190
/// PEM-encoded certificate
193-
cert: Vec<u8>
194-
}
191+
pem: Vec<u8>,
192+
/// PEM-encoded key
193+
key: Vec<u8>,
194+
},
195195
}
196196

197197
impl OwnedIdentity {
198198
/// Get the ephemeral `Identity` corresponding to the `OwnedIdentity`
199199
#[must_use]
200-
pub fn as_ref(&self) -> Identity<'_, '_, '_> {
200+
pub fn as_ref(&self) -> Identity<'_, '_> {
201201
match self {
202-
Self::PEM { der, cert } => Identity::PEM { der, cert },
203-
Self::PKCS12 { der, password } => Identity::PKCS12 { der, password }
202+
Self::PKCS8 { pem, key } => Identity::PKCS8 { pem, key },
203+
Self::PKCS12 { der, password } => Identity::PKCS12 { der, password },
204204
}
205205
}
206206
}
@@ -265,7 +265,7 @@ impl TcpStream {
265265
pub fn into_tls(
266266
self,
267267
domain: &str,
268-
config: TLSConfig<'_, '_, '_, '_>,
268+
config: TLSConfig<'_, '_, '_>,
269269
) -> Result<Self, HandshakeError> {
270270
into_tls_impl(self, domain, config)
271271
}
@@ -349,9 +349,11 @@ fn into_rustls_common(
349349
s: TcpStream,
350350
mut c: RustlsConnectorConfig,
351351
domain: &str,
352-
config: TLSConfig<'_, '_, '_, '_>,
352+
config: TLSConfig<'_, '_, '_>,
353353
) -> HandshakeResult {
354-
use rustls_connector::rustls_pki_types::{pem::PemObject, CertificateDer, PrivateKeyDer, PrivatePkcs8KeyDer};
354+
use rustls_connector::rustls_pki_types::{
355+
pem::PemObject, CertificateDer, PrivateKeyDer, PrivatePkcs8KeyDer,
356+
};
355357

356358
if let Some(cert_chain) = config.cert_chain {
357359
let mut cert_chain = std::io::BufReader::new(cert_chain.as_bytes());
@@ -366,23 +368,32 @@ fn into_rustls_common(
366368
let pfx = p12_keystore::KeyStore::from_pkcs12(der, password)
367369
.map_err(|err| io::Error::new(io::ErrorKind::Other, err))?;
368370
let Some((_, keychain)) = pfx.private_key_chain() else {
369-
return Err(
370-
io::Error::new(io::ErrorKind::Other, "No private key in pkcs12 DER").into(),
371-
);
371+
return Err(io::Error::new(
372+
io::ErrorKind::Other,
373+
"No private key in pkcs12 DER",
374+
)
375+
.into());
372376
};
373377
let certs = keychain
374378
.chain()
375379
.iter()
376380
.map(|cert| CertificateDer::from(cert.as_der().to_vec()))
377381
.collect();
378-
(certs, PrivateKeyDer::from(PrivatePkcs8KeyDer::from(keychain.key().to_vec())))
379-
},
380-
Identity::PEM { der, cert } => {
381-
let mut cert_reader = std::io::BufReader::new(cert);
382+
(
383+
certs,
384+
PrivateKeyDer::from(PrivatePkcs8KeyDer::from(keychain.key().to_vec())),
385+
)
386+
}
387+
Identity::PKCS8 { pem, key } => {
388+
let mut cert_reader = std::io::BufReader::new(pem);
382389
let certs = rustls_pemfile::certs(&mut cert_reader)
383390
.collect::<Result<Vec<_>, _>>()
384391
.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
385-
(certs, PrivateKeyDer::from_pem_slice(der).map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?)
392+
(
393+
certs,
394+
PrivateKeyDer::from_pem_slice(key)
395+
.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?,
396+
)
386397
}
387398
};
388399
c.connector_with_single_cert(certs, key)
@@ -395,31 +406,42 @@ fn into_rustls_common(
395406

396407
cfg_if! {
397408
if #[cfg(feature = "rustls-native-certs")] {
398-
fn into_tls_impl(s: TcpStream, domain: &str, config: TLSConfig<'_, '_, '_, '_>) -> HandshakeResult {
409+
fn into_tls_impl(s: TcpStream, domain: &str, config: TLSConfig<'_, '_, '_>) -> HandshakeResult {
399410
into_rustls_common(s, RustlsConnectorConfig::new_with_native_certs()?, domain, config)
400411
}
401412
} else if #[cfg(feature = "rustls-webpki-roots-certs")] {
402-
fn into_tls_impl(s: TcpStream, domain: &str, config: TLSConfig<'_, '_, '_, '_>) -> HandshakeResult {
413+
fn into_tls_impl(s: TcpStream, domain: &str, config: TLSConfig<'_, '_, '_>) -> HandshakeResult {
403414
into_rustls_common(s, RustlsConnectorConfig::new_with_webpki_roots_certs(), domain, config)
404415
}
405416
} else if #[cfg(feature = "rustls-common")] {
406-
fn into_tls_impl(s: TcpStream, domain: &str, config: TLSConfig<'_, '_, '_, '_>) -> HandshakeResult {
417+
fn into_tls_impl(s: TcpStream, domain: &str, config: TLSConfig<'_, '_, '_>) -> HandshakeResult {
407418
into_rustls_common(s, RustlsConnectorConfig::default(), domain, config)
408419
}
409420
} else if #[cfg(feature = "openssl")] {
410-
fn into_tls_impl(s: TcpStream, domain: &str, config: TLSConfig<'_, '_, '_, '_>) -> HandshakeResult {
421+
fn into_tls_impl(s: TcpStream, domain: &str, config: TLSConfig<'_, '_, '_>) -> HandshakeResult {
411422
use openssl::x509::X509;
412423

413424
let mut builder = OpenSslConnector::builder(OpenSslMethod::tls())?;
414425
if let Some(identity) = config.identity {
415-
let identity = openssl::pkcs12::Pkcs12::from_der(identity.der)?.parse2(identity.password)?;
416-
if let Some(cert) = identity.cert.as_ref() {
426+
let (cert, pkey, chain) = match identity {
427+
Identity::PKCS8 { pem, key } => {
428+
let pkey = openssl::pkey::PKey::private_key_from_pem(key)?;
429+
let mut chain = openssl::x509::X509::stack_from_pem(pem)?.into_iter();
430+
let cert = chain.next();
431+
(cert, Some(pkey), Some(chain.collect()))
432+
}
433+
Identity::PKCS12 { der, password } => {
434+
let mut openssl_identity = openssl::pkcs12::Pkcs12::from_der(der)?.parse2(password)?;
435+
(openssl_identity.cert, openssl_identity.pkey, openssl_identity.ca.take().map(|stack| stack.into_iter().collect::<Vec<_>>()))
436+
},
437+
};
438+
if let Some(cert) = cert.as_ref() {
417439
builder.set_certificate(cert)?;
418440
}
419-
if let Some(pkey) = identity.pkey.as_ref() {
441+
if let Some(pkey) = pkey.as_ref() {
420442
builder.set_private_key(pkey)?;
421443
}
422-
if let Some(chain) = identity.ca.as_ref() {
444+
if let Some(chain) = chain.as_ref() {
423445
for cert in chain.iter().rev() {
424446
builder.add_extra_chain_cert(cert.to_owned())?;
425447
}
@@ -433,12 +455,16 @@ cfg_if! {
433455
s.into_openssl(&builder.build(), domain)
434456
}
435457
} else if #[cfg(feature = "native-tls")] {
436-
fn into_tls_impl(s: TcpStream, domain: &str, config: TLSConfig<'_, '_, '_, '_>) -> HandshakeResult {
458+
fn into_tls_impl(s: TcpStream, domain: &str, config: TLSConfig<'_, '_, '_>) -> HandshakeResult {
437459
use native_tls::Certificate;
438460

439461
let mut builder = NativeTlsConnector::builder();
440462
if let Some(identity) = config.identity {
441-
builder.identity(native_tls::Identity::from_pkcs12(identity.der, identity.password).map_err(|e| io::Error::new(io::ErrorKind::Other, e))?);
463+
let native_identity = match identity {
464+
Identity::PKCS8 { pem, key } => native_tls::Identity::from_pkcs8(pem, key),
465+
Identity::PKCS12 { der, password } => native_tls::Identity::from_pkcs12(der, password),
466+
};
467+
builder.identity(native_identity.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?);
442468
}
443469
if let Some(cert_chain) = config.cert_chain {
444470
let mut cert_chain = std::io::BufReader::new(cert_chain.as_bytes());
@@ -449,7 +475,7 @@ cfg_if! {
449475
s.into_native_tls(&builder.build().map_err(|e| io::Error::new(io::ErrorKind::Other, e))?, domain)
450476
}
451477
} else {
452-
fn into_tls_impl(s: TcpStream, _domain: &str, _: TLSConfig<'_, '_, '_, '_>) -> HandshakeResult {
478+
fn into_tls_impl(s: TcpStream, _domain: &str, _: TLSConfig<'_, '_, '_>) -> HandshakeResult {
453479
Ok(s.into_plain()?)
454480
}
455481
}

0 commit comments

Comments
 (0)