tcp_stream/
openssl_impl.rs

1use crate::{
2    HandshakeError, HandshakeResult, Identity, MidHandshakeTlsStream, TLSConfig, TcpStream,
3};
4
5#[cfg(feature = "openssl-futures")]
6use crate::AsyncTcpStream;
7
8use openssl::x509::X509;
9use std::io;
10
11/// Reexport openssl's `TlsConnector`
12pub use openssl::ssl::{SslConnector as OpenSslConnector, SslMethod as OpenSslMethod};
13
14/// A `TcpStream` wrapped by openssl
15pub type OpenSslStream = openssl::ssl::SslStream<TcpStream>;
16
17/// A `MidHandshakeTlsStream` from openssl
18pub type OpenSslMidHandshakeTlsStream = openssl::ssl::MidHandshakeSslStream<TcpStream>;
19
20/// A `HandshakeError` from openssl
21pub type OpenSslHandshakeError = openssl::ssl::HandshakeError<TcpStream>;
22
23/// An `ErrorStack` from openssl
24pub type OpenSslErrorStack = openssl::error::ErrorStack;
25
26fn openssl_connector(config: TLSConfig<'_, '_, '_>) -> io::Result<OpenSslConnector> {
27    let mut builder = OpenSslConnector::builder(OpenSslMethod::tls())?;
28    if let Some(identity) = config.identity {
29        let (cert, pkey, chain) = match identity {
30            Identity::PKCS8 { pem, key } => {
31                let pkey = openssl::pkey::PKey::private_key_from_pem(key)?;
32                let mut chain = openssl::x509::X509::stack_from_pem(pem)?.into_iter();
33                let cert = chain.next();
34                (cert, Some(pkey), Some(chain.collect()))
35            }
36            Identity::PKCS12 { der, password } => {
37                let mut openssl_identity =
38                    openssl::pkcs12::Pkcs12::from_der(der)?.parse2(password)?;
39                (
40                    openssl_identity.cert,
41                    openssl_identity.pkey,
42                    openssl_identity
43                        .ca
44                        .take()
45                        .map(|stack| stack.into_iter().collect::<Vec<_>>()),
46                )
47            }
48        };
49        if let Some(cert) = cert.as_ref() {
50            builder.set_certificate(cert)?;
51        }
52        if let Some(pkey) = pkey.as_ref() {
53            builder.set_private_key(pkey)?;
54        }
55        if let Some(chain) = chain.as_ref() {
56            for cert in chain.iter().rev() {
57                builder.add_extra_chain_cert(cert.to_owned())?;
58            }
59        }
60    }
61    if let Some(cert_chain) = config.cert_chain.as_ref() {
62        for cert in X509::stack_from_pem(cert_chain.as_bytes())?.drain(..).rev() {
63            builder.cert_store_mut().add_cert(cert)?;
64        }
65    }
66    Ok(builder.build())
67}
68
69#[allow(dead_code)]
70pub(crate) fn into_openssl_impl(
71    s: TcpStream,
72    domain: &str,
73    config: TLSConfig<'_, '_, '_>,
74) -> HandshakeResult {
75    s.into_openssl(&openssl_connector(config)?, domain)
76}
77
78#[cfg(feature = "openssl-futures")]
79#[allow(dead_code)]
80pub(crate) async fn into_openssl_impl_async(
81    s: AsyncTcpStream,
82    domain: &str,
83    config: TLSConfig<'_, '_, '_>,
84) -> io::Result<AsyncTcpStream> {
85    s.into_openssl(&openssl_connector(config)?, domain).await
86}
87
88impl From<OpenSslStream> for TcpStream {
89    fn from(s: OpenSslStream) -> Self {
90        TcpStream::OpenSsl(Box::new(s))
91    }
92}
93
94impl From<OpenSslMidHandshakeTlsStream> for MidHandshakeTlsStream {
95    fn from(mid: OpenSslMidHandshakeTlsStream) -> Self {
96        MidHandshakeTlsStream::Openssl(mid)
97    }
98}
99
100impl From<OpenSslHandshakeError> for HandshakeError {
101    fn from(error: OpenSslHandshakeError) -> Self {
102        match error {
103            openssl::ssl::HandshakeError::WouldBlock(mid) => HandshakeError::WouldBlock(mid.into()),
104            openssl::ssl::HandshakeError::Failure(failure) => {
105                HandshakeError::Failure(io::Error::other(failure.into_error()))
106            }
107            openssl::ssl::HandshakeError::SetupFailure(failure) => failure.into(),
108        }
109    }
110}
111
112impl From<OpenSslErrorStack> for HandshakeError {
113    fn from(error: OpenSslErrorStack) -> Self {
114        Self::Failure(error.into())
115    }
116}