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