192f3ab15Sopenharmony_ci//! SSL/TLS support.
292f3ab15Sopenharmony_ci//!
392f3ab15Sopenharmony_ci//! `SslConnector` and `SslAcceptor` should be used in most cases - they handle
492f3ab15Sopenharmony_ci//! configuration of the OpenSSL primitives for you.
592f3ab15Sopenharmony_ci//!
692f3ab15Sopenharmony_ci//! # Examples
792f3ab15Sopenharmony_ci//!
892f3ab15Sopenharmony_ci//! To connect as a client to a remote server:
992f3ab15Sopenharmony_ci//!
1092f3ab15Sopenharmony_ci//! ```no_run
1192f3ab15Sopenharmony_ci//! use openssl::ssl::{SslMethod, SslConnector};
1292f3ab15Sopenharmony_ci//! use std::io::{Read, Write};
1392f3ab15Sopenharmony_ci//! use std::net::TcpStream;
1492f3ab15Sopenharmony_ci//!
1592f3ab15Sopenharmony_ci//! let connector = SslConnector::builder(SslMethod::tls()).unwrap().build();
1692f3ab15Sopenharmony_ci//!
1792f3ab15Sopenharmony_ci//! let stream = TcpStream::connect("google.com:443").unwrap();
1892f3ab15Sopenharmony_ci//! let mut stream = connector.connect("google.com", stream).unwrap();
1992f3ab15Sopenharmony_ci//!
2092f3ab15Sopenharmony_ci//! stream.write_all(b"GET / HTTP/1.0\r\n\r\n").unwrap();
2192f3ab15Sopenharmony_ci//! let mut res = vec![];
2292f3ab15Sopenharmony_ci//! stream.read_to_end(&mut res).unwrap();
2392f3ab15Sopenharmony_ci//! println!("{}", String::from_utf8_lossy(&res));
2492f3ab15Sopenharmony_ci//! ```
2592f3ab15Sopenharmony_ci//!
2692f3ab15Sopenharmony_ci//! To accept connections as a server from remote clients:
2792f3ab15Sopenharmony_ci//!
2892f3ab15Sopenharmony_ci//! ```no_run
2992f3ab15Sopenharmony_ci//! use openssl::ssl::{SslMethod, SslAcceptor, SslStream, SslFiletype};
3092f3ab15Sopenharmony_ci//! use std::net::{TcpListener, TcpStream};
3192f3ab15Sopenharmony_ci//! use std::sync::Arc;
3292f3ab15Sopenharmony_ci//! use std::thread;
3392f3ab15Sopenharmony_ci//!
3492f3ab15Sopenharmony_ci//!
3592f3ab15Sopenharmony_ci//! let mut acceptor = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap();
3692f3ab15Sopenharmony_ci//! acceptor.set_private_key_file("key.pem", SslFiletype::PEM).unwrap();
3792f3ab15Sopenharmony_ci//! acceptor.set_certificate_chain_file("certs.pem").unwrap();
3892f3ab15Sopenharmony_ci//! acceptor.check_private_key().unwrap();
3992f3ab15Sopenharmony_ci//! let acceptor = Arc::new(acceptor.build());
4092f3ab15Sopenharmony_ci//!
4192f3ab15Sopenharmony_ci//! let listener = TcpListener::bind("0.0.0.0:8443").unwrap();
4292f3ab15Sopenharmony_ci//!
4392f3ab15Sopenharmony_ci//! fn handle_client(stream: SslStream<TcpStream>) {
4492f3ab15Sopenharmony_ci//!     // ...
4592f3ab15Sopenharmony_ci//! }
4692f3ab15Sopenharmony_ci//!
4792f3ab15Sopenharmony_ci//! for stream in listener.incoming() {
4892f3ab15Sopenharmony_ci//!     match stream {
4992f3ab15Sopenharmony_ci//!         Ok(stream) => {
5092f3ab15Sopenharmony_ci//!             let acceptor = acceptor.clone();
5192f3ab15Sopenharmony_ci//!             thread::spawn(move || {
5292f3ab15Sopenharmony_ci//!                 let stream = acceptor.accept(stream).unwrap();
5392f3ab15Sopenharmony_ci//!                 handle_client(stream);
5492f3ab15Sopenharmony_ci//!             });
5592f3ab15Sopenharmony_ci//!         }
5692f3ab15Sopenharmony_ci//!         Err(e) => { /* connection failed */ }
5792f3ab15Sopenharmony_ci//!     }
5892f3ab15Sopenharmony_ci//! }
5992f3ab15Sopenharmony_ci//! ```
6092f3ab15Sopenharmony_ciuse crate::dh::{Dh, DhRef};
6192f3ab15Sopenharmony_ci#[cfg(all(ossl101, not(ossl110)))]
6292f3ab15Sopenharmony_ciuse crate::ec::EcKey;
6392f3ab15Sopenharmony_ciuse crate::ec::EcKeyRef;
6492f3ab15Sopenharmony_ciuse crate::error::ErrorStack;
6592f3ab15Sopenharmony_ciuse crate::ex_data::Index;
6692f3ab15Sopenharmony_ci#[cfg(ossl111)]
6792f3ab15Sopenharmony_ciuse crate::hash::MessageDigest;
6892f3ab15Sopenharmony_ci#[cfg(any(ossl110, libressl270))]
6992f3ab15Sopenharmony_ciuse crate::nid::Nid;
7092f3ab15Sopenharmony_ciuse crate::pkey::{HasPrivate, PKeyRef, Params, Private};
7192f3ab15Sopenharmony_ciuse crate::srtp::{SrtpProtectionProfile, SrtpProtectionProfileRef};
7292f3ab15Sopenharmony_ciuse crate::ssl::bio::BioMethod;
7392f3ab15Sopenharmony_ciuse crate::ssl::callbacks::*;
7492f3ab15Sopenharmony_ciuse crate::ssl::error::InnerError;
7592f3ab15Sopenharmony_ciuse crate::stack::{Stack, StackRef, Stackable};
7692f3ab15Sopenharmony_ciuse crate::util::{ForeignTypeExt, ForeignTypeRefExt};
7792f3ab15Sopenharmony_ciuse crate::x509::store::{X509Store, X509StoreBuilderRef, X509StoreRef};
7892f3ab15Sopenharmony_ci#[cfg(any(ossl102, libressl261))]
7992f3ab15Sopenharmony_ciuse crate::x509::verify::X509VerifyParamRef;
8092f3ab15Sopenharmony_ciuse crate::x509::{X509Name, X509Ref, X509StoreContextRef, X509VerifyResult, X509};
8192f3ab15Sopenharmony_ciuse crate::{cvt, cvt_n, cvt_p, init};
8292f3ab15Sopenharmony_ciuse bitflags::bitflags;
8392f3ab15Sopenharmony_ciuse cfg_if::cfg_if;
8492f3ab15Sopenharmony_ciuse foreign_types::{ForeignType, ForeignTypeRef, Opaque};
8592f3ab15Sopenharmony_ciuse libc::{c_char, c_int, c_long, c_uchar, c_uint, c_void};
8692f3ab15Sopenharmony_ciuse once_cell::sync::{Lazy, OnceCell};
8792f3ab15Sopenharmony_ciuse openssl_macros::corresponds;
8892f3ab15Sopenharmony_ciuse std::any::TypeId;
8992f3ab15Sopenharmony_ciuse std::cmp;
9092f3ab15Sopenharmony_ciuse std::collections::HashMap;
9192f3ab15Sopenharmony_ciuse std::ffi::{CStr, CString};
9292f3ab15Sopenharmony_ciuse std::fmt;
9392f3ab15Sopenharmony_ciuse std::io;
9492f3ab15Sopenharmony_ciuse std::io::prelude::*;
9592f3ab15Sopenharmony_ciuse std::marker::PhantomData;
9692f3ab15Sopenharmony_ciuse std::mem::{self, ManuallyDrop};
9792f3ab15Sopenharmony_ciuse std::ops::{Deref, DerefMut};
9892f3ab15Sopenharmony_ciuse std::panic::resume_unwind;
9992f3ab15Sopenharmony_ciuse std::path::Path;
10092f3ab15Sopenharmony_ciuse std::ptr;
10192f3ab15Sopenharmony_ciuse std::slice;
10292f3ab15Sopenharmony_ciuse std::str;
10392f3ab15Sopenharmony_ciuse std::sync::{Arc, Mutex};
10492f3ab15Sopenharmony_ci
10592f3ab15Sopenharmony_cipub use crate::ssl::connector::{
10692f3ab15Sopenharmony_ci    ConnectConfiguration, SslAcceptor, SslAcceptorBuilder, SslConnector, SslConnectorBuilder,
10792f3ab15Sopenharmony_ci};
10892f3ab15Sopenharmony_cipub use crate::ssl::error::{Error, ErrorCode, HandshakeError};
10992f3ab15Sopenharmony_ci
11092f3ab15Sopenharmony_cimod bio;
11192f3ab15Sopenharmony_cimod callbacks;
11292f3ab15Sopenharmony_cimod connector;
11392f3ab15Sopenharmony_cimod error;
11492f3ab15Sopenharmony_ci#[cfg(test)]
11592f3ab15Sopenharmony_cimod test;
11692f3ab15Sopenharmony_ci
11792f3ab15Sopenharmony_ci/// Returns the OpenSSL name of a cipher corresponding to an RFC-standard cipher name.
11892f3ab15Sopenharmony_ci///
11992f3ab15Sopenharmony_ci/// If the cipher has no corresponding OpenSSL name, the string `(NONE)` is returned.
12092f3ab15Sopenharmony_ci///
12192f3ab15Sopenharmony_ci/// Requires OpenSSL 1.1.1 or newer.
12292f3ab15Sopenharmony_ci#[corresponds(OPENSSL_cipher_name)]
12392f3ab15Sopenharmony_ci#[cfg(ossl111)]
12492f3ab15Sopenharmony_cipub fn cipher_name(std_name: &str) -> &'static str {
12592f3ab15Sopenharmony_ci    unsafe {
12692f3ab15Sopenharmony_ci        ffi::init();
12792f3ab15Sopenharmony_ci
12892f3ab15Sopenharmony_ci        let s = CString::new(std_name).unwrap();
12992f3ab15Sopenharmony_ci        let ptr = ffi::OPENSSL_cipher_name(s.as_ptr());
13092f3ab15Sopenharmony_ci        CStr::from_ptr(ptr).to_str().unwrap()
13192f3ab15Sopenharmony_ci    }
13292f3ab15Sopenharmony_ci}
13392f3ab15Sopenharmony_ci
13492f3ab15Sopenharmony_cicfg_if! {
13592f3ab15Sopenharmony_ci    if #[cfg(ossl300)] {
13692f3ab15Sopenharmony_ci        type SslOptionsRepr = u64;
13792f3ab15Sopenharmony_ci    } else if #[cfg(boringssl)] {
13892f3ab15Sopenharmony_ci        type SslOptionsRepr = u32;
13992f3ab15Sopenharmony_ci    } else {
14092f3ab15Sopenharmony_ci        type SslOptionsRepr = libc::c_ulong;
14192f3ab15Sopenharmony_ci    }
14292f3ab15Sopenharmony_ci}
14392f3ab15Sopenharmony_ci
14492f3ab15Sopenharmony_cibitflags! {
14592f3ab15Sopenharmony_ci    /// Options controlling the behavior of an `SslContext`.
14692f3ab15Sopenharmony_ci    pub struct SslOptions: SslOptionsRepr {
14792f3ab15Sopenharmony_ci        /// Disables a countermeasure against an SSLv3/TLSv1.0 vulnerability affecting CBC ciphers.
14892f3ab15Sopenharmony_ci        const DONT_INSERT_EMPTY_FRAGMENTS = ffi::SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS as SslOptionsRepr;
14992f3ab15Sopenharmony_ci
15092f3ab15Sopenharmony_ci        /// A "reasonable default" set of options which enables compatibility flags.
15192f3ab15Sopenharmony_ci        #[cfg(not(boringssl))]
15292f3ab15Sopenharmony_ci        const ALL = ffi::SSL_OP_ALL as SslOptionsRepr;
15392f3ab15Sopenharmony_ci
15492f3ab15Sopenharmony_ci        /// Do not query the MTU.
15592f3ab15Sopenharmony_ci        ///
15692f3ab15Sopenharmony_ci        /// Only affects DTLS connections.
15792f3ab15Sopenharmony_ci        const NO_QUERY_MTU = ffi::SSL_OP_NO_QUERY_MTU as SslOptionsRepr;
15892f3ab15Sopenharmony_ci
15992f3ab15Sopenharmony_ci        /// Enables Cookie Exchange as described in [RFC 4347 Section 4.2.1].
16092f3ab15Sopenharmony_ci        ///
16192f3ab15Sopenharmony_ci        /// Only affects DTLS connections.
16292f3ab15Sopenharmony_ci        ///
16392f3ab15Sopenharmony_ci        /// [RFC 4347 Section 4.2.1]: https://tools.ietf.org/html/rfc4347#section-4.2.1
16492f3ab15Sopenharmony_ci        #[cfg(not(boringssl))]
16592f3ab15Sopenharmony_ci        const COOKIE_EXCHANGE = ffi::SSL_OP_COOKIE_EXCHANGE as SslOptionsRepr;
16692f3ab15Sopenharmony_ci
16792f3ab15Sopenharmony_ci        /// Disables the use of session tickets for session resumption.
16892f3ab15Sopenharmony_ci        const NO_TICKET = ffi::SSL_OP_NO_TICKET as SslOptionsRepr;
16992f3ab15Sopenharmony_ci
17092f3ab15Sopenharmony_ci        /// Always start a new session when performing a renegotiation on the server side.
17192f3ab15Sopenharmony_ci        #[cfg(not(boringssl))]
17292f3ab15Sopenharmony_ci        const NO_SESSION_RESUMPTION_ON_RENEGOTIATION =
17392f3ab15Sopenharmony_ci            ffi::SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION as SslOptionsRepr;
17492f3ab15Sopenharmony_ci
17592f3ab15Sopenharmony_ci        /// Disables the use of TLS compression.
17692f3ab15Sopenharmony_ci        #[cfg(not(boringssl))]
17792f3ab15Sopenharmony_ci        const NO_COMPRESSION = ffi::SSL_OP_NO_COMPRESSION as SslOptionsRepr;
17892f3ab15Sopenharmony_ci
17992f3ab15Sopenharmony_ci        /// Allow legacy insecure renegotiation with servers or clients that do not support secure
18092f3ab15Sopenharmony_ci        /// renegotiation.
18192f3ab15Sopenharmony_ci        const ALLOW_UNSAFE_LEGACY_RENEGOTIATION =
18292f3ab15Sopenharmony_ci            ffi::SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION as SslOptionsRepr;
18392f3ab15Sopenharmony_ci
18492f3ab15Sopenharmony_ci        /// Creates a new key for each session when using ECDHE.
18592f3ab15Sopenharmony_ci        ///
18692f3ab15Sopenharmony_ci        /// This is always enabled in OpenSSL 1.1.0.
18792f3ab15Sopenharmony_ci        const SINGLE_ECDH_USE = ffi::SSL_OP_SINGLE_ECDH_USE as SslOptionsRepr;
18892f3ab15Sopenharmony_ci
18992f3ab15Sopenharmony_ci        /// Creates a new key for each session when using DHE.
19092f3ab15Sopenharmony_ci        ///
19192f3ab15Sopenharmony_ci        /// This is always enabled in OpenSSL 1.1.0.
19292f3ab15Sopenharmony_ci        const SINGLE_DH_USE = ffi::SSL_OP_SINGLE_DH_USE as SslOptionsRepr;
19392f3ab15Sopenharmony_ci
19492f3ab15Sopenharmony_ci        /// Use the server's preferences rather than the client's when selecting a cipher.
19592f3ab15Sopenharmony_ci        ///
19692f3ab15Sopenharmony_ci        /// This has no effect on the client side.
19792f3ab15Sopenharmony_ci        const CIPHER_SERVER_PREFERENCE = ffi::SSL_OP_CIPHER_SERVER_PREFERENCE as SslOptionsRepr;
19892f3ab15Sopenharmony_ci
19992f3ab15Sopenharmony_ci        /// Disables version rollback attach detection.
20092f3ab15Sopenharmony_ci        const TLS_ROLLBACK_BUG = ffi::SSL_OP_TLS_ROLLBACK_BUG as SslOptionsRepr;
20192f3ab15Sopenharmony_ci
20292f3ab15Sopenharmony_ci        /// Disables the use of SSLv2.
20392f3ab15Sopenharmony_ci        const NO_SSLV2 = ffi::SSL_OP_NO_SSLv2 as SslOptionsRepr;
20492f3ab15Sopenharmony_ci
20592f3ab15Sopenharmony_ci        /// Disables the use of SSLv3.
20692f3ab15Sopenharmony_ci        const NO_SSLV3 = ffi::SSL_OP_NO_SSLv3 as SslOptionsRepr;
20792f3ab15Sopenharmony_ci
20892f3ab15Sopenharmony_ci        /// Disables the use of TLSv1.0.
20992f3ab15Sopenharmony_ci        const NO_TLSV1 = ffi::SSL_OP_NO_TLSv1 as SslOptionsRepr;
21092f3ab15Sopenharmony_ci
21192f3ab15Sopenharmony_ci        /// Disables the use of TLSv1.1.
21292f3ab15Sopenharmony_ci        const NO_TLSV1_1 = ffi::SSL_OP_NO_TLSv1_1 as SslOptionsRepr;
21392f3ab15Sopenharmony_ci
21492f3ab15Sopenharmony_ci        /// Disables the use of TLSv1.2.
21592f3ab15Sopenharmony_ci        const NO_TLSV1_2 = ffi::SSL_OP_NO_TLSv1_2 as SslOptionsRepr;
21692f3ab15Sopenharmony_ci
21792f3ab15Sopenharmony_ci        /// Disables the use of TLSv1.3.
21892f3ab15Sopenharmony_ci        ///
21992f3ab15Sopenharmony_ci        /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer.
22092f3ab15Sopenharmony_ci        #[cfg(any(boringssl, ossl111, libressl340))]
22192f3ab15Sopenharmony_ci        const NO_TLSV1_3 = ffi::SSL_OP_NO_TLSv1_3 as SslOptionsRepr;
22292f3ab15Sopenharmony_ci
22392f3ab15Sopenharmony_ci        /// Disables the use of DTLSv1.0
22492f3ab15Sopenharmony_ci        ///
22592f3ab15Sopenharmony_ci        /// Requires OpenSSL 1.0.2 or LibreSSL 3.3.2 or newer.
22692f3ab15Sopenharmony_ci        #[cfg(any(boringssl, ossl102, ossl110, libressl332))]
22792f3ab15Sopenharmony_ci        const NO_DTLSV1 = ffi::SSL_OP_NO_DTLSv1 as SslOptionsRepr;
22892f3ab15Sopenharmony_ci
22992f3ab15Sopenharmony_ci        /// Disables the use of DTLSv1.2.
23092f3ab15Sopenharmony_ci        ///
23192f3ab15Sopenharmony_ci        /// Requires OpenSSL 1.0.2 or LibreSSL 3.3.2 or newer.
23292f3ab15Sopenharmony_ci        #[cfg(any(boringssl, ossl102, ossl110, libressl332))]
23392f3ab15Sopenharmony_ci        const NO_DTLSV1_2 = ffi::SSL_OP_NO_DTLSv1_2 as SslOptionsRepr;
23492f3ab15Sopenharmony_ci
23592f3ab15Sopenharmony_ci        /// Disables the use of all (D)TLS protocol versions.
23692f3ab15Sopenharmony_ci        ///
23792f3ab15Sopenharmony_ci        /// This can be used as a mask when whitelisting protocol versions.
23892f3ab15Sopenharmony_ci        ///
23992f3ab15Sopenharmony_ci        /// Requires OpenSSL 1.0.2 or newer.
24092f3ab15Sopenharmony_ci        ///
24192f3ab15Sopenharmony_ci        /// # Examples
24292f3ab15Sopenharmony_ci        ///
24392f3ab15Sopenharmony_ci        /// Only support TLSv1.2:
24492f3ab15Sopenharmony_ci        ///
24592f3ab15Sopenharmony_ci        /// ```rust
24692f3ab15Sopenharmony_ci        /// use openssl::ssl::SslOptions;
24792f3ab15Sopenharmony_ci        ///
24892f3ab15Sopenharmony_ci        /// let options = SslOptions::NO_SSL_MASK & !SslOptions::NO_TLSV1_2;
24992f3ab15Sopenharmony_ci        /// ```
25092f3ab15Sopenharmony_ci        #[cfg(any(ossl102, ossl110))]
25192f3ab15Sopenharmony_ci        const NO_SSL_MASK = ffi::SSL_OP_NO_SSL_MASK as SslOptionsRepr;
25292f3ab15Sopenharmony_ci
25392f3ab15Sopenharmony_ci        /// Disallow all renegotiation in TLSv1.2 and earlier.
25492f3ab15Sopenharmony_ci        ///
25592f3ab15Sopenharmony_ci        /// Requires OpenSSL 1.1.0h or newer.
25692f3ab15Sopenharmony_ci        #[cfg(any(boringssl, ossl110h))]
25792f3ab15Sopenharmony_ci        const NO_RENEGOTIATION = ffi::SSL_OP_NO_RENEGOTIATION as SslOptionsRepr;
25892f3ab15Sopenharmony_ci
25992f3ab15Sopenharmony_ci        /// Enable TLSv1.3 Compatibility mode.
26092f3ab15Sopenharmony_ci        ///
26192f3ab15Sopenharmony_ci        /// Requires OpenSSL 1.1.1 or newer. This is on by default in 1.1.1, but a future version
26292f3ab15Sopenharmony_ci        /// may have this disabled by default.
26392f3ab15Sopenharmony_ci        #[cfg(ossl111)]
26492f3ab15Sopenharmony_ci        const ENABLE_MIDDLEBOX_COMPAT = ffi::SSL_OP_ENABLE_MIDDLEBOX_COMPAT as SslOptionsRepr;
26592f3ab15Sopenharmony_ci
26692f3ab15Sopenharmony_ci        /// Prioritize ChaCha ciphers when preferred by clients.
26792f3ab15Sopenharmony_ci        ///
26892f3ab15Sopenharmony_ci        /// Temporarily reprioritize ChaCha20-Poly1305 ciphers to the top of the server cipher list
26992f3ab15Sopenharmony_ci        /// if a ChaCha20-Poly1305 cipher is at the top of the client cipher list. This helps those
27092f3ab15Sopenharmony_ci        /// clients (e.g. mobile) use ChaCha20-Poly1305 if that cipher is anywhere in the server
27192f3ab15Sopenharmony_ci        /// cipher list; but still allows other clients to use AES and other ciphers.
27292f3ab15Sopenharmony_ci        ///
27392f3ab15Sopenharmony_ci        /// Requires enable [`SslOptions::CIPHER_SERVER_PREFERENCE`].
27492f3ab15Sopenharmony_ci        /// Requires OpenSSL 1.1.1 or newer.
27592f3ab15Sopenharmony_ci        ///
27692f3ab15Sopenharmony_ci        /// [`SslOptions::CIPHER_SERVER_PREFERENCE`]: struct.SslOptions.html#associatedconstant.CIPHER_SERVER_PREFERENCE
27792f3ab15Sopenharmony_ci        #[cfg(ossl111)]
27892f3ab15Sopenharmony_ci        const PRIORITIZE_CHACHA = ffi::SSL_OP_PRIORITIZE_CHACHA as SslOptionsRepr;
27992f3ab15Sopenharmony_ci    }
28092f3ab15Sopenharmony_ci}
28192f3ab15Sopenharmony_ci
28292f3ab15Sopenharmony_cibitflags! {
28392f3ab15Sopenharmony_ci    /// Options controlling the behavior of an `SslContext`.
28492f3ab15Sopenharmony_ci    pub struct SslMode: SslBitType {
28592f3ab15Sopenharmony_ci        /// Enables "short writes".
28692f3ab15Sopenharmony_ci        ///
28792f3ab15Sopenharmony_ci        /// Normally, a write in OpenSSL will always write out all of the requested data, even if it
28892f3ab15Sopenharmony_ci        /// requires more than one TLS record or write to the underlying stream. This option will
28992f3ab15Sopenharmony_ci        /// cause a write to return after writing a single TLS record instead.
29092f3ab15Sopenharmony_ci        const ENABLE_PARTIAL_WRITE = ffi::SSL_MODE_ENABLE_PARTIAL_WRITE;
29192f3ab15Sopenharmony_ci
29292f3ab15Sopenharmony_ci        /// Disables a check that the data buffer has not moved between calls when operating in a
29392f3ab15Sopenharmony_ci        /// non-blocking context.
29492f3ab15Sopenharmony_ci        const ACCEPT_MOVING_WRITE_BUFFER = ffi::SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER;
29592f3ab15Sopenharmony_ci
29692f3ab15Sopenharmony_ci        /// Enables automatic retries after TLS session events such as renegotiations or heartbeats.
29792f3ab15Sopenharmony_ci        ///
29892f3ab15Sopenharmony_ci        /// By default, OpenSSL will return a `WantRead` error after a renegotiation or heartbeat.
29992f3ab15Sopenharmony_ci        /// This option will cause OpenSSL to automatically continue processing the requested
30092f3ab15Sopenharmony_ci        /// operation instead.
30192f3ab15Sopenharmony_ci        ///
30292f3ab15Sopenharmony_ci        /// Note that `SslStream::read` and `SslStream::write` will automatically retry regardless
30392f3ab15Sopenharmony_ci        /// of the state of this option. It only affects `SslStream::ssl_read` and
30492f3ab15Sopenharmony_ci        /// `SslStream::ssl_write`.
30592f3ab15Sopenharmony_ci        const AUTO_RETRY = ffi::SSL_MODE_AUTO_RETRY;
30692f3ab15Sopenharmony_ci
30792f3ab15Sopenharmony_ci        /// Disables automatic chain building when verifying a peer's certificate.
30892f3ab15Sopenharmony_ci        ///
30992f3ab15Sopenharmony_ci        /// TLS peers are responsible for sending the entire certificate chain from the leaf to a
31092f3ab15Sopenharmony_ci        /// trusted root, but some will incorrectly not do so. OpenSSL will try to build the chain
31192f3ab15Sopenharmony_ci        /// out of certificates it knows of, and this option will disable that behavior.
31292f3ab15Sopenharmony_ci        const NO_AUTO_CHAIN = ffi::SSL_MODE_NO_AUTO_CHAIN;
31392f3ab15Sopenharmony_ci
31492f3ab15Sopenharmony_ci        /// Release memory buffers when the session does not need them.
31592f3ab15Sopenharmony_ci        ///
31692f3ab15Sopenharmony_ci        /// This saves ~34 KiB of memory for idle streams.
31792f3ab15Sopenharmony_ci        const RELEASE_BUFFERS = ffi::SSL_MODE_RELEASE_BUFFERS;
31892f3ab15Sopenharmony_ci
31992f3ab15Sopenharmony_ci        /// Sends the fake `TLS_FALLBACK_SCSV` cipher suite in the ClientHello message of a
32092f3ab15Sopenharmony_ci        /// handshake.
32192f3ab15Sopenharmony_ci        ///
32292f3ab15Sopenharmony_ci        /// This should only be enabled if a client has failed to connect to a server which
32392f3ab15Sopenharmony_ci        /// attempted to downgrade the protocol version of the session.
32492f3ab15Sopenharmony_ci        ///
32592f3ab15Sopenharmony_ci        /// Do not use this unless you know what you're doing!
32692f3ab15Sopenharmony_ci        #[cfg(not(libressl))]
32792f3ab15Sopenharmony_ci        const SEND_FALLBACK_SCSV = ffi::SSL_MODE_SEND_FALLBACK_SCSV;
32892f3ab15Sopenharmony_ci    }
32992f3ab15Sopenharmony_ci}
33092f3ab15Sopenharmony_ci
33192f3ab15Sopenharmony_ci/// A type specifying the kind of protocol an `SslContext` will speak.
33292f3ab15Sopenharmony_ci#[derive(Copy, Clone)]
33392f3ab15Sopenharmony_cipub struct SslMethod(*const ffi::SSL_METHOD);
33492f3ab15Sopenharmony_ci
33592f3ab15Sopenharmony_ciimpl SslMethod {
33692f3ab15Sopenharmony_ci    /// Support all versions of the TLS protocol.
33792f3ab15Sopenharmony_ci    #[corresponds(TLS_method)]
33892f3ab15Sopenharmony_ci    pub fn tls() -> SslMethod {
33992f3ab15Sopenharmony_ci        unsafe { SslMethod(TLS_method()) }
34092f3ab15Sopenharmony_ci    }
34192f3ab15Sopenharmony_ci
34292f3ab15Sopenharmony_ci    /// Support all versions of the DTLS protocol.
34392f3ab15Sopenharmony_ci    #[corresponds(DTLS_method)]
34492f3ab15Sopenharmony_ci    pub fn dtls() -> SslMethod {
34592f3ab15Sopenharmony_ci        unsafe { SslMethod(DTLS_method()) }
34692f3ab15Sopenharmony_ci    }
34792f3ab15Sopenharmony_ci
34892f3ab15Sopenharmony_ci    /// Support all versions of the TLS protocol, explicitly as a client.
34992f3ab15Sopenharmony_ci    #[corresponds(TLS_client_method)]
35092f3ab15Sopenharmony_ci    pub fn tls_client() -> SslMethod {
35192f3ab15Sopenharmony_ci        unsafe { SslMethod(TLS_client_method()) }
35292f3ab15Sopenharmony_ci    }
35392f3ab15Sopenharmony_ci
35492f3ab15Sopenharmony_ci    /// Support all versions of the TLS protocol, explicitly as a server.
35592f3ab15Sopenharmony_ci    #[corresponds(TLS_server_method)]
35692f3ab15Sopenharmony_ci    pub fn tls_server() -> SslMethod {
35792f3ab15Sopenharmony_ci        unsafe { SslMethod(TLS_server_method()) }
35892f3ab15Sopenharmony_ci    }
35992f3ab15Sopenharmony_ci
36092f3ab15Sopenharmony_ci    /// Constructs an `SslMethod` from a pointer to the underlying OpenSSL value.
36192f3ab15Sopenharmony_ci    ///
36292f3ab15Sopenharmony_ci    /// # Safety
36392f3ab15Sopenharmony_ci    ///
36492f3ab15Sopenharmony_ci    /// The caller must ensure the pointer is valid.
36592f3ab15Sopenharmony_ci    pub unsafe fn from_ptr(ptr: *const ffi::SSL_METHOD) -> SslMethod {
36692f3ab15Sopenharmony_ci        SslMethod(ptr)
36792f3ab15Sopenharmony_ci    }
36892f3ab15Sopenharmony_ci
36992f3ab15Sopenharmony_ci    /// Returns a pointer to the underlying OpenSSL value.
37092f3ab15Sopenharmony_ci    #[allow(clippy::trivially_copy_pass_by_ref)]
37192f3ab15Sopenharmony_ci    pub fn as_ptr(&self) -> *const ffi::SSL_METHOD {
37292f3ab15Sopenharmony_ci        self.0
37392f3ab15Sopenharmony_ci    }
37492f3ab15Sopenharmony_ci}
37592f3ab15Sopenharmony_ci
37692f3ab15Sopenharmony_ciunsafe impl Sync for SslMethod {}
37792f3ab15Sopenharmony_ciunsafe impl Send for SslMethod {}
37892f3ab15Sopenharmony_ci
37992f3ab15Sopenharmony_cibitflags! {
38092f3ab15Sopenharmony_ci    /// Options controlling the behavior of certificate verification.
38192f3ab15Sopenharmony_ci    pub struct SslVerifyMode: i32 {
38292f3ab15Sopenharmony_ci        /// Verifies that the peer's certificate is trusted.
38392f3ab15Sopenharmony_ci        ///
38492f3ab15Sopenharmony_ci        /// On the server side, this will cause OpenSSL to request a certificate from the client.
38592f3ab15Sopenharmony_ci        const PEER = ffi::SSL_VERIFY_PEER;
38692f3ab15Sopenharmony_ci
38792f3ab15Sopenharmony_ci        /// Disables verification of the peer's certificate.
38892f3ab15Sopenharmony_ci        ///
38992f3ab15Sopenharmony_ci        /// On the server side, this will cause OpenSSL to not request a certificate from the
39092f3ab15Sopenharmony_ci        /// client. On the client side, the certificate will be checked for validity, but the
39192f3ab15Sopenharmony_ci        /// negotiation will continue regardless of the result of that check.
39292f3ab15Sopenharmony_ci        const NONE = ffi::SSL_VERIFY_NONE;
39392f3ab15Sopenharmony_ci
39492f3ab15Sopenharmony_ci        /// On the server side, abort the handshake if the client did not send a certificate.
39592f3ab15Sopenharmony_ci        ///
39692f3ab15Sopenharmony_ci        /// This should be paired with `SSL_VERIFY_PEER`. It has no effect on the client side.
39792f3ab15Sopenharmony_ci        const FAIL_IF_NO_PEER_CERT = ffi::SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
39892f3ab15Sopenharmony_ci    }
39992f3ab15Sopenharmony_ci}
40092f3ab15Sopenharmony_ci
40192f3ab15Sopenharmony_ci#[cfg(boringssl)]
40292f3ab15Sopenharmony_citype SslBitType = c_int;
40392f3ab15Sopenharmony_ci#[cfg(not(boringssl))]
40492f3ab15Sopenharmony_citype SslBitType = c_long;
40592f3ab15Sopenharmony_ci
40692f3ab15Sopenharmony_ci#[cfg(boringssl)]
40792f3ab15Sopenharmony_citype SslTimeTy = u64;
40892f3ab15Sopenharmony_ci#[cfg(not(boringssl))]
40992f3ab15Sopenharmony_citype SslTimeTy = c_long;
41092f3ab15Sopenharmony_ci
41192f3ab15Sopenharmony_cibitflags! {
41292f3ab15Sopenharmony_ci    /// Options controlling the behavior of session caching.
41392f3ab15Sopenharmony_ci    pub struct SslSessionCacheMode: SslBitType {
41492f3ab15Sopenharmony_ci        /// No session caching for the client or server takes place.
41592f3ab15Sopenharmony_ci        const OFF = ffi::SSL_SESS_CACHE_OFF;
41692f3ab15Sopenharmony_ci
41792f3ab15Sopenharmony_ci        /// Enable session caching on the client side.
41892f3ab15Sopenharmony_ci        ///
41992f3ab15Sopenharmony_ci        /// OpenSSL has no way of identifying the proper session to reuse automatically, so the
42092f3ab15Sopenharmony_ci        /// application is responsible for setting it explicitly via [`SslRef::set_session`].
42192f3ab15Sopenharmony_ci        ///
42292f3ab15Sopenharmony_ci        /// [`SslRef::set_session`]: struct.SslRef.html#method.set_session
42392f3ab15Sopenharmony_ci        const CLIENT = ffi::SSL_SESS_CACHE_CLIENT;
42492f3ab15Sopenharmony_ci
42592f3ab15Sopenharmony_ci        /// Enable session caching on the server side.
42692f3ab15Sopenharmony_ci        ///
42792f3ab15Sopenharmony_ci        /// This is the default mode.
42892f3ab15Sopenharmony_ci        const SERVER = ffi::SSL_SESS_CACHE_SERVER;
42992f3ab15Sopenharmony_ci
43092f3ab15Sopenharmony_ci        /// Enable session caching on both the client and server side.
43192f3ab15Sopenharmony_ci        const BOTH = ffi::SSL_SESS_CACHE_BOTH;
43292f3ab15Sopenharmony_ci
43392f3ab15Sopenharmony_ci        /// Disable automatic removal of expired sessions from the session cache.
43492f3ab15Sopenharmony_ci        const NO_AUTO_CLEAR = ffi::SSL_SESS_CACHE_NO_AUTO_CLEAR;
43592f3ab15Sopenharmony_ci
43692f3ab15Sopenharmony_ci        /// Disable use of the internal session cache for session lookups.
43792f3ab15Sopenharmony_ci        const NO_INTERNAL_LOOKUP = ffi::SSL_SESS_CACHE_NO_INTERNAL_LOOKUP;
43892f3ab15Sopenharmony_ci
43992f3ab15Sopenharmony_ci        /// Disable use of the internal session cache for session storage.
44092f3ab15Sopenharmony_ci        const NO_INTERNAL_STORE = ffi::SSL_SESS_CACHE_NO_INTERNAL_STORE;
44192f3ab15Sopenharmony_ci
44292f3ab15Sopenharmony_ci        /// Disable use of the internal session cache for storage and lookup.
44392f3ab15Sopenharmony_ci        const NO_INTERNAL = ffi::SSL_SESS_CACHE_NO_INTERNAL;
44492f3ab15Sopenharmony_ci    }
44592f3ab15Sopenharmony_ci}
44692f3ab15Sopenharmony_ci
44792f3ab15Sopenharmony_ci#[cfg(ossl111)]
44892f3ab15Sopenharmony_cibitflags! {
44992f3ab15Sopenharmony_ci    /// Which messages and under which conditions an extension should be added or expected.
45092f3ab15Sopenharmony_ci    pub struct ExtensionContext: c_uint {
45192f3ab15Sopenharmony_ci        /// This extension is only allowed in TLS
45292f3ab15Sopenharmony_ci        const TLS_ONLY = ffi::SSL_EXT_TLS_ONLY;
45392f3ab15Sopenharmony_ci        /// This extension is only allowed in DTLS
45492f3ab15Sopenharmony_ci        const DTLS_ONLY = ffi::SSL_EXT_DTLS_ONLY;
45592f3ab15Sopenharmony_ci        /// Some extensions may be allowed in DTLS but we don't implement them for it
45692f3ab15Sopenharmony_ci        const TLS_IMPLEMENTATION_ONLY = ffi::SSL_EXT_TLS_IMPLEMENTATION_ONLY;
45792f3ab15Sopenharmony_ci        /// Most extensions are not defined for SSLv3 but EXT_TYPE_renegotiate is
45892f3ab15Sopenharmony_ci        const SSL3_ALLOWED = ffi::SSL_EXT_SSL3_ALLOWED;
45992f3ab15Sopenharmony_ci        /// Extension is only defined for TLS1.2 and below
46092f3ab15Sopenharmony_ci        const TLS1_2_AND_BELOW_ONLY = ffi::SSL_EXT_TLS1_2_AND_BELOW_ONLY;
46192f3ab15Sopenharmony_ci        /// Extension is only defined for TLS1.3 and above
46292f3ab15Sopenharmony_ci        const TLS1_3_ONLY = ffi::SSL_EXT_TLS1_3_ONLY;
46392f3ab15Sopenharmony_ci        /// Ignore this extension during parsing if we are resuming
46492f3ab15Sopenharmony_ci        const IGNORE_ON_RESUMPTION = ffi::SSL_EXT_IGNORE_ON_RESUMPTION;
46592f3ab15Sopenharmony_ci        const CLIENT_HELLO = ffi::SSL_EXT_CLIENT_HELLO;
46692f3ab15Sopenharmony_ci        /// Really means TLS1.2 or below
46792f3ab15Sopenharmony_ci        const TLS1_2_SERVER_HELLO = ffi::SSL_EXT_TLS1_2_SERVER_HELLO;
46892f3ab15Sopenharmony_ci        const TLS1_3_SERVER_HELLO = ffi::SSL_EXT_TLS1_3_SERVER_HELLO;
46992f3ab15Sopenharmony_ci        const TLS1_3_ENCRYPTED_EXTENSIONS = ffi::SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS;
47092f3ab15Sopenharmony_ci        const TLS1_3_HELLO_RETRY_REQUEST = ffi::SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST;
47192f3ab15Sopenharmony_ci        const TLS1_3_CERTIFICATE = ffi::SSL_EXT_TLS1_3_CERTIFICATE;
47292f3ab15Sopenharmony_ci        const TLS1_3_NEW_SESSION_TICKET = ffi::SSL_EXT_TLS1_3_NEW_SESSION_TICKET;
47392f3ab15Sopenharmony_ci        const TLS1_3_CERTIFICATE_REQUEST = ffi::SSL_EXT_TLS1_3_CERTIFICATE_REQUEST;
47492f3ab15Sopenharmony_ci    }
47592f3ab15Sopenharmony_ci}
47692f3ab15Sopenharmony_ci
47792f3ab15Sopenharmony_ci/// An identifier of the format of a certificate or key file.
47892f3ab15Sopenharmony_ci#[derive(Copy, Clone)]
47992f3ab15Sopenharmony_cipub struct SslFiletype(c_int);
48092f3ab15Sopenharmony_ci
48192f3ab15Sopenharmony_ciimpl SslFiletype {
48292f3ab15Sopenharmony_ci    /// The PEM format.
48392f3ab15Sopenharmony_ci    ///
48492f3ab15Sopenharmony_ci    /// This corresponds to `SSL_FILETYPE_PEM`.
48592f3ab15Sopenharmony_ci    pub const PEM: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_PEM);
48692f3ab15Sopenharmony_ci
48792f3ab15Sopenharmony_ci    /// The ASN1 format.
48892f3ab15Sopenharmony_ci    ///
48992f3ab15Sopenharmony_ci    /// This corresponds to `SSL_FILETYPE_ASN1`.
49092f3ab15Sopenharmony_ci    pub const ASN1: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_ASN1);
49192f3ab15Sopenharmony_ci
49292f3ab15Sopenharmony_ci    /// Constructs an `SslFiletype` from a raw OpenSSL value.
49392f3ab15Sopenharmony_ci    pub fn from_raw(raw: c_int) -> SslFiletype {
49492f3ab15Sopenharmony_ci        SslFiletype(raw)
49592f3ab15Sopenharmony_ci    }
49692f3ab15Sopenharmony_ci
49792f3ab15Sopenharmony_ci    /// Returns the raw OpenSSL value represented by this type.
49892f3ab15Sopenharmony_ci    #[allow(clippy::trivially_copy_pass_by_ref)]
49992f3ab15Sopenharmony_ci    pub fn as_raw(&self) -> c_int {
50092f3ab15Sopenharmony_ci        self.0
50192f3ab15Sopenharmony_ci    }
50292f3ab15Sopenharmony_ci}
50392f3ab15Sopenharmony_ci
50492f3ab15Sopenharmony_ci/// An identifier of a certificate status type.
50592f3ab15Sopenharmony_ci#[derive(Copy, Clone)]
50692f3ab15Sopenharmony_cipub struct StatusType(c_int);
50792f3ab15Sopenharmony_ci
50892f3ab15Sopenharmony_ciimpl StatusType {
50992f3ab15Sopenharmony_ci    /// An OSCP status.
51092f3ab15Sopenharmony_ci    pub const OCSP: StatusType = StatusType(ffi::TLSEXT_STATUSTYPE_ocsp);
51192f3ab15Sopenharmony_ci
51292f3ab15Sopenharmony_ci    /// Constructs a `StatusType` from a raw OpenSSL value.
51392f3ab15Sopenharmony_ci    pub fn from_raw(raw: c_int) -> StatusType {
51492f3ab15Sopenharmony_ci        StatusType(raw)
51592f3ab15Sopenharmony_ci    }
51692f3ab15Sopenharmony_ci
51792f3ab15Sopenharmony_ci    /// Returns the raw OpenSSL value represented by this type.
51892f3ab15Sopenharmony_ci    #[allow(clippy::trivially_copy_pass_by_ref)]
51992f3ab15Sopenharmony_ci    pub fn as_raw(&self) -> c_int {
52092f3ab15Sopenharmony_ci        self.0
52192f3ab15Sopenharmony_ci    }
52292f3ab15Sopenharmony_ci}
52392f3ab15Sopenharmony_ci
52492f3ab15Sopenharmony_ci/// An identifier of a session name type.
52592f3ab15Sopenharmony_ci#[derive(Copy, Clone)]
52692f3ab15Sopenharmony_cipub struct NameType(c_int);
52792f3ab15Sopenharmony_ci
52892f3ab15Sopenharmony_ciimpl NameType {
52992f3ab15Sopenharmony_ci    /// A host name.
53092f3ab15Sopenharmony_ci    pub const HOST_NAME: NameType = NameType(ffi::TLSEXT_NAMETYPE_host_name);
53192f3ab15Sopenharmony_ci
53292f3ab15Sopenharmony_ci    /// Constructs a `StatusType` from a raw OpenSSL value.
53392f3ab15Sopenharmony_ci    pub fn from_raw(raw: c_int) -> StatusType {
53492f3ab15Sopenharmony_ci        StatusType(raw)
53592f3ab15Sopenharmony_ci    }
53692f3ab15Sopenharmony_ci
53792f3ab15Sopenharmony_ci    /// Returns the raw OpenSSL value represented by this type.
53892f3ab15Sopenharmony_ci    #[allow(clippy::trivially_copy_pass_by_ref)]
53992f3ab15Sopenharmony_ci    pub fn as_raw(&self) -> c_int {
54092f3ab15Sopenharmony_ci        self.0
54192f3ab15Sopenharmony_ci    }
54292f3ab15Sopenharmony_ci}
54392f3ab15Sopenharmony_ci
54492f3ab15Sopenharmony_cistatic INDEXES: Lazy<Mutex<HashMap<TypeId, c_int>>> = Lazy::new(|| Mutex::new(HashMap::new()));
54592f3ab15Sopenharmony_cistatic SSL_INDEXES: Lazy<Mutex<HashMap<TypeId, c_int>>> = Lazy::new(|| Mutex::new(HashMap::new()));
54692f3ab15Sopenharmony_cistatic SESSION_CTX_INDEX: OnceCell<Index<Ssl, SslContext>> = OnceCell::new();
54792f3ab15Sopenharmony_ci
54892f3ab15Sopenharmony_cifn try_get_session_ctx_index() -> Result<&'static Index<Ssl, SslContext>, ErrorStack> {
54992f3ab15Sopenharmony_ci    SESSION_CTX_INDEX.get_or_try_init(Ssl::new_ex_index)
55092f3ab15Sopenharmony_ci}
55192f3ab15Sopenharmony_ci
55292f3ab15Sopenharmony_ciunsafe extern "C" fn free_data_box<T>(
55392f3ab15Sopenharmony_ci    _parent: *mut c_void,
55492f3ab15Sopenharmony_ci    ptr: *mut c_void,
55592f3ab15Sopenharmony_ci    _ad: *mut ffi::CRYPTO_EX_DATA,
55692f3ab15Sopenharmony_ci    _idx: c_int,
55792f3ab15Sopenharmony_ci    _argl: c_long,
55892f3ab15Sopenharmony_ci    _argp: *mut c_void,
55992f3ab15Sopenharmony_ci) {
56092f3ab15Sopenharmony_ci    if !ptr.is_null() {
56192f3ab15Sopenharmony_ci        let _ = Box::<T>::from_raw(ptr as *mut T);
56292f3ab15Sopenharmony_ci    }
56392f3ab15Sopenharmony_ci}
56492f3ab15Sopenharmony_ci
56592f3ab15Sopenharmony_ci/// An error returned from the SNI callback.
56692f3ab15Sopenharmony_ci#[derive(Debug, Copy, Clone, PartialEq, Eq)]
56792f3ab15Sopenharmony_cipub struct SniError(c_int);
56892f3ab15Sopenharmony_ci
56992f3ab15Sopenharmony_ciimpl SniError {
57092f3ab15Sopenharmony_ci    /// Abort the handshake with a fatal alert.
57192f3ab15Sopenharmony_ci    pub const ALERT_FATAL: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
57292f3ab15Sopenharmony_ci
57392f3ab15Sopenharmony_ci    /// Send a warning alert to the client and continue the handshake.
57492f3ab15Sopenharmony_ci    pub const ALERT_WARNING: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_WARNING);
57592f3ab15Sopenharmony_ci
57692f3ab15Sopenharmony_ci    pub const NOACK: SniError = SniError(ffi::SSL_TLSEXT_ERR_NOACK);
57792f3ab15Sopenharmony_ci}
57892f3ab15Sopenharmony_ci
57992f3ab15Sopenharmony_ci/// An SSL/TLS alert.
58092f3ab15Sopenharmony_ci#[derive(Debug, Copy, Clone, PartialEq, Eq)]
58192f3ab15Sopenharmony_cipub struct SslAlert(c_int);
58292f3ab15Sopenharmony_ci
58392f3ab15Sopenharmony_ciimpl SslAlert {
58492f3ab15Sopenharmony_ci    /// Alert 112 - `unrecognized_name`.
58592f3ab15Sopenharmony_ci    pub const UNRECOGNIZED_NAME: SslAlert = SslAlert(ffi::SSL_AD_UNRECOGNIZED_NAME);
58692f3ab15Sopenharmony_ci    pub const ILLEGAL_PARAMETER: SslAlert = SslAlert(ffi::SSL_AD_ILLEGAL_PARAMETER);
58792f3ab15Sopenharmony_ci    pub const DECODE_ERROR: SslAlert = SslAlert(ffi::SSL_AD_DECODE_ERROR);
58892f3ab15Sopenharmony_ci}
58992f3ab15Sopenharmony_ci
59092f3ab15Sopenharmony_ci/// An error returned from an ALPN selection callback.
59192f3ab15Sopenharmony_ci///
59292f3ab15Sopenharmony_ci/// Requires OpenSSL 1.0.2 or LibreSSL 2.6.1 or newer.
59392f3ab15Sopenharmony_ci#[cfg(any(ossl102, libressl261))]
59492f3ab15Sopenharmony_ci#[derive(Debug, Copy, Clone, PartialEq, Eq)]
59592f3ab15Sopenharmony_cipub struct AlpnError(c_int);
59692f3ab15Sopenharmony_ci
59792f3ab15Sopenharmony_ci#[cfg(any(ossl102, libressl261))]
59892f3ab15Sopenharmony_ciimpl AlpnError {
59992f3ab15Sopenharmony_ci    /// Terminate the handshake with a fatal alert.
60092f3ab15Sopenharmony_ci    ///
60192f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.1.0 or newer.
60292f3ab15Sopenharmony_ci    #[cfg(ossl110)]
60392f3ab15Sopenharmony_ci    pub const ALERT_FATAL: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
60492f3ab15Sopenharmony_ci
60592f3ab15Sopenharmony_ci    /// Do not select a protocol, but continue the handshake.
60692f3ab15Sopenharmony_ci    pub const NOACK: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_NOACK);
60792f3ab15Sopenharmony_ci}
60892f3ab15Sopenharmony_ci
60992f3ab15Sopenharmony_ci/// The result of a client hello callback.
61092f3ab15Sopenharmony_ci///
61192f3ab15Sopenharmony_ci/// Requires OpenSSL 1.1.1 or newer.
61292f3ab15Sopenharmony_ci#[cfg(ossl111)]
61392f3ab15Sopenharmony_ci#[derive(Debug, Copy, Clone, PartialEq, Eq)]
61492f3ab15Sopenharmony_cipub struct ClientHelloResponse(c_int);
61592f3ab15Sopenharmony_ci
61692f3ab15Sopenharmony_ci#[cfg(ossl111)]
61792f3ab15Sopenharmony_ciimpl ClientHelloResponse {
61892f3ab15Sopenharmony_ci    /// Continue the handshake.
61992f3ab15Sopenharmony_ci    pub const SUCCESS: ClientHelloResponse = ClientHelloResponse(ffi::SSL_CLIENT_HELLO_SUCCESS);
62092f3ab15Sopenharmony_ci
62192f3ab15Sopenharmony_ci    /// Return from the handshake with an `ErrorCode::WANT_CLIENT_HELLO_CB` error.
62292f3ab15Sopenharmony_ci    pub const RETRY: ClientHelloResponse = ClientHelloResponse(ffi::SSL_CLIENT_HELLO_RETRY);
62392f3ab15Sopenharmony_ci}
62492f3ab15Sopenharmony_ci
62592f3ab15Sopenharmony_ci/// An SSL/TLS protocol version.
62692f3ab15Sopenharmony_ci#[derive(Debug, Copy, Clone, PartialEq, Eq)]
62792f3ab15Sopenharmony_cipub struct SslVersion(c_int);
62892f3ab15Sopenharmony_ci
62992f3ab15Sopenharmony_ciimpl SslVersion {
63092f3ab15Sopenharmony_ci    /// SSLv3
63192f3ab15Sopenharmony_ci    pub const SSL3: SslVersion = SslVersion(ffi::SSL3_VERSION);
63292f3ab15Sopenharmony_ci
63392f3ab15Sopenharmony_ci    /// TLSv1.0
63492f3ab15Sopenharmony_ci    pub const TLS1: SslVersion = SslVersion(ffi::TLS1_VERSION);
63592f3ab15Sopenharmony_ci
63692f3ab15Sopenharmony_ci    /// TLSv1.1
63792f3ab15Sopenharmony_ci    pub const TLS1_1: SslVersion = SslVersion(ffi::TLS1_1_VERSION);
63892f3ab15Sopenharmony_ci
63992f3ab15Sopenharmony_ci    /// TLSv1.2
64092f3ab15Sopenharmony_ci    pub const TLS1_2: SslVersion = SslVersion(ffi::TLS1_2_VERSION);
64192f3ab15Sopenharmony_ci
64292f3ab15Sopenharmony_ci    /// TLSv1.3
64392f3ab15Sopenharmony_ci    ///
64492f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer.
64592f3ab15Sopenharmony_ci    #[cfg(any(ossl111, libressl340))]
64692f3ab15Sopenharmony_ci    pub const TLS1_3: SslVersion = SslVersion(ffi::TLS1_3_VERSION);
64792f3ab15Sopenharmony_ci
64892f3ab15Sopenharmony_ci    /// DTLSv1.0
64992f3ab15Sopenharmony_ci    ///
65092f3ab15Sopenharmony_ci    /// DTLS 1.0 corresponds to TLS 1.1.
65192f3ab15Sopenharmony_ci    pub const DTLS1: SslVersion = SslVersion(ffi::DTLS1_VERSION);
65292f3ab15Sopenharmony_ci
65392f3ab15Sopenharmony_ci    /// DTLSv1.2
65492f3ab15Sopenharmony_ci    ///
65592f3ab15Sopenharmony_ci    /// DTLS 1.2 corresponds to TLS 1.2 to harmonize versions. There was never a DTLS 1.1.
65692f3ab15Sopenharmony_ci    #[cfg(any(ossl102, libressl332))]
65792f3ab15Sopenharmony_ci    pub const DTLS1_2: SslVersion = SslVersion(ffi::DTLS1_2_VERSION);
65892f3ab15Sopenharmony_ci}
65992f3ab15Sopenharmony_ci
66092f3ab15Sopenharmony_cicfg_if! {
66192f3ab15Sopenharmony_ci    if #[cfg(boringssl)] {
66292f3ab15Sopenharmony_ci        type SslCacheTy = i64;
66392f3ab15Sopenharmony_ci        type SslCacheSize = libc::c_ulong;
66492f3ab15Sopenharmony_ci        type MtuTy = u32;
66592f3ab15Sopenharmony_ci        type SizeTy = usize;
66692f3ab15Sopenharmony_ci    } else {
66792f3ab15Sopenharmony_ci        type SslCacheTy = i64;
66892f3ab15Sopenharmony_ci        type SslCacheSize = c_long;
66992f3ab15Sopenharmony_ci        type MtuTy = c_long;
67092f3ab15Sopenharmony_ci        type SizeTy = u32;
67192f3ab15Sopenharmony_ci    }
67292f3ab15Sopenharmony_ci}
67392f3ab15Sopenharmony_ci
67492f3ab15Sopenharmony_ci/// A standard implementation of protocol selection for Application Layer Protocol Negotiation
67592f3ab15Sopenharmony_ci/// (ALPN).
67692f3ab15Sopenharmony_ci///
67792f3ab15Sopenharmony_ci/// `server` should contain the server's list of supported protocols and `client` the client's. They
67892f3ab15Sopenharmony_ci/// must both be in the ALPN wire format. See the documentation for
67992f3ab15Sopenharmony_ci/// [`SslContextBuilder::set_alpn_protos`] for details.
68092f3ab15Sopenharmony_ci///
68192f3ab15Sopenharmony_ci/// It will select the first protocol supported by the server which is also supported by the client.
68292f3ab15Sopenharmony_ci///
68392f3ab15Sopenharmony_ci/// [`SslContextBuilder::set_alpn_protos`]: struct.SslContextBuilder.html#method.set_alpn_protos
68492f3ab15Sopenharmony_ci#[corresponds(SSL_select_next_proto)]
68592f3ab15Sopenharmony_cipub fn select_next_proto<'a>(server: &[u8], client: &'a [u8]) -> Option<&'a [u8]> {
68692f3ab15Sopenharmony_ci    unsafe {
68792f3ab15Sopenharmony_ci        let mut out = ptr::null_mut();
68892f3ab15Sopenharmony_ci        let mut outlen = 0;
68992f3ab15Sopenharmony_ci        let r = ffi::SSL_select_next_proto(
69092f3ab15Sopenharmony_ci            &mut out,
69192f3ab15Sopenharmony_ci            &mut outlen,
69292f3ab15Sopenharmony_ci            server.as_ptr(),
69392f3ab15Sopenharmony_ci            server.len() as c_uint,
69492f3ab15Sopenharmony_ci            client.as_ptr(),
69592f3ab15Sopenharmony_ci            client.len() as c_uint,
69692f3ab15Sopenharmony_ci        );
69792f3ab15Sopenharmony_ci        if r == ffi::OPENSSL_NPN_NEGOTIATED {
69892f3ab15Sopenharmony_ci            Some(slice::from_raw_parts(out as *const u8, outlen as usize))
69992f3ab15Sopenharmony_ci        } else {
70092f3ab15Sopenharmony_ci            None
70192f3ab15Sopenharmony_ci        }
70292f3ab15Sopenharmony_ci    }
70392f3ab15Sopenharmony_ci}
70492f3ab15Sopenharmony_ci
70592f3ab15Sopenharmony_ci/// A builder for `SslContext`s.
70692f3ab15Sopenharmony_cipub struct SslContextBuilder(SslContext);
70792f3ab15Sopenharmony_ci
70892f3ab15Sopenharmony_ciimpl SslContextBuilder {
70992f3ab15Sopenharmony_ci    /// Creates a new `SslContextBuilder`.
71092f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_new)]
71192f3ab15Sopenharmony_ci    pub fn new(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
71292f3ab15Sopenharmony_ci        unsafe {
71392f3ab15Sopenharmony_ci            init();
71492f3ab15Sopenharmony_ci            let ctx = cvt_p(ffi::SSL_CTX_new(method.as_ptr()))?;
71592f3ab15Sopenharmony_ci
71692f3ab15Sopenharmony_ci            Ok(SslContextBuilder::from_ptr(ctx))
71792f3ab15Sopenharmony_ci        }
71892f3ab15Sopenharmony_ci    }
71992f3ab15Sopenharmony_ci
72092f3ab15Sopenharmony_ci    /// Creates an `SslContextBuilder` from a pointer to a raw OpenSSL value.
72192f3ab15Sopenharmony_ci    ///
72292f3ab15Sopenharmony_ci    /// # Safety
72392f3ab15Sopenharmony_ci    ///
72492f3ab15Sopenharmony_ci    /// The caller must ensure that the pointer is valid and uniquely owned by the builder.
72592f3ab15Sopenharmony_ci    pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX) -> SslContextBuilder {
72692f3ab15Sopenharmony_ci        SslContextBuilder(SslContext::from_ptr(ctx))
72792f3ab15Sopenharmony_ci    }
72892f3ab15Sopenharmony_ci
72992f3ab15Sopenharmony_ci    /// Returns a pointer to the raw OpenSSL value.
73092f3ab15Sopenharmony_ci    pub fn as_ptr(&self) -> *mut ffi::SSL_CTX {
73192f3ab15Sopenharmony_ci        self.0.as_ptr()
73292f3ab15Sopenharmony_ci    }
73392f3ab15Sopenharmony_ci
73492f3ab15Sopenharmony_ci    /// Configures the certificate verification method for new connections.
73592f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_set_verify)]
73692f3ab15Sopenharmony_ci    pub fn set_verify(&mut self, mode: SslVerifyMode) {
73792f3ab15Sopenharmony_ci        unsafe {
73892f3ab15Sopenharmony_ci            ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits as c_int, None);
73992f3ab15Sopenharmony_ci        }
74092f3ab15Sopenharmony_ci    }
74192f3ab15Sopenharmony_ci
74292f3ab15Sopenharmony_ci    /// Configures the certificate verification method for new connections and
74392f3ab15Sopenharmony_ci    /// registers a verification callback.
74492f3ab15Sopenharmony_ci    ///
74592f3ab15Sopenharmony_ci    /// The callback is passed a boolean indicating if OpenSSL's internal verification succeeded as
74692f3ab15Sopenharmony_ci    /// well as a reference to the `X509StoreContext` which can be used to examine the certificate
74792f3ab15Sopenharmony_ci    /// chain. It should return a boolean indicating if verification succeeded.
74892f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_set_verify)]
74992f3ab15Sopenharmony_ci    pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
75092f3ab15Sopenharmony_ci    where
75192f3ab15Sopenharmony_ci        F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
75292f3ab15Sopenharmony_ci    {
75392f3ab15Sopenharmony_ci        unsafe {
75492f3ab15Sopenharmony_ci            self.set_ex_data(SslContext::cached_ex_index::<F>(), verify);
75592f3ab15Sopenharmony_ci            ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits as c_int, Some(raw_verify::<F>));
75692f3ab15Sopenharmony_ci        }
75792f3ab15Sopenharmony_ci    }
75892f3ab15Sopenharmony_ci
75992f3ab15Sopenharmony_ci    /// Configures the server name indication (SNI) callback for new connections.
76092f3ab15Sopenharmony_ci    ///
76192f3ab15Sopenharmony_ci    /// SNI is used to allow a single server to handle requests for multiple domains, each of which
76292f3ab15Sopenharmony_ci    /// has its own certificate chain and configuration.
76392f3ab15Sopenharmony_ci    ///
76492f3ab15Sopenharmony_ci    /// Obtain the server name with the `servername` method and then set the corresponding context
76592f3ab15Sopenharmony_ci    /// with `set_ssl_context`
76692f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_set_tlsext_servername_callback)]
76792f3ab15Sopenharmony_ci    // FIXME tlsext prefix?
76892f3ab15Sopenharmony_ci    pub fn set_servername_callback<F>(&mut self, callback: F)
76992f3ab15Sopenharmony_ci    where
77092f3ab15Sopenharmony_ci        F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), SniError> + 'static + Sync + Send,
77192f3ab15Sopenharmony_ci    {
77292f3ab15Sopenharmony_ci        unsafe {
77392f3ab15Sopenharmony_ci            // The SNI callback is somewhat unique in that the callback associated with the original
77492f3ab15Sopenharmony_ci            // context associated with an SSL can be used even if the SSL's context has been swapped
77592f3ab15Sopenharmony_ci            // out. When that happens, we wouldn't be able to look up the callback's state in the
77692f3ab15Sopenharmony_ci            // context's ex data. Instead, pass the pointer directly as the servername arg. It's
77792f3ab15Sopenharmony_ci            // still stored in ex data to manage the lifetime.
77892f3ab15Sopenharmony_ci            let arg = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
77992f3ab15Sopenharmony_ci            ffi::SSL_CTX_set_tlsext_servername_arg(self.as_ptr(), arg);
78092f3ab15Sopenharmony_ci            #[cfg(boringssl)]
78192f3ab15Sopenharmony_ci            ffi::SSL_CTX_set_tlsext_servername_callback(self.as_ptr(), Some(raw_sni::<F>));
78292f3ab15Sopenharmony_ci            #[cfg(not(boringssl))]
78392f3ab15Sopenharmony_ci            ffi::SSL_CTX_set_tlsext_servername_callback__fixed_rust(
78492f3ab15Sopenharmony_ci                self.as_ptr(),
78592f3ab15Sopenharmony_ci                Some(raw_sni::<F>),
78692f3ab15Sopenharmony_ci            );
78792f3ab15Sopenharmony_ci        }
78892f3ab15Sopenharmony_ci    }
78992f3ab15Sopenharmony_ci
79092f3ab15Sopenharmony_ci    /// Sets the certificate verification depth.
79192f3ab15Sopenharmony_ci    ///
79292f3ab15Sopenharmony_ci    /// If the peer's certificate chain is longer than this value, verification will fail.
79392f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_set_verify_depth)]
79492f3ab15Sopenharmony_ci    pub fn set_verify_depth(&mut self, depth: u32) {
79592f3ab15Sopenharmony_ci        unsafe {
79692f3ab15Sopenharmony_ci            ffi::SSL_CTX_set_verify_depth(self.as_ptr(), depth as c_int);
79792f3ab15Sopenharmony_ci        }
79892f3ab15Sopenharmony_ci    }
79992f3ab15Sopenharmony_ci
80092f3ab15Sopenharmony_ci    /// Sets a custom certificate store for verifying peer certificates.
80192f3ab15Sopenharmony_ci    ///
80292f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.0.2 or newer.
80392f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_set0_verify_cert_store)]
80492f3ab15Sopenharmony_ci    #[cfg(ossl102)]
80592f3ab15Sopenharmony_ci    pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
80692f3ab15Sopenharmony_ci        unsafe {
80792f3ab15Sopenharmony_ci            let ptr = cert_store.as_ptr();
80892f3ab15Sopenharmony_ci            cvt(ffi::SSL_CTX_set0_verify_cert_store(self.as_ptr(), ptr) as c_int)?;
80992f3ab15Sopenharmony_ci            mem::forget(cert_store);
81092f3ab15Sopenharmony_ci
81192f3ab15Sopenharmony_ci            Ok(())
81292f3ab15Sopenharmony_ci        }
81392f3ab15Sopenharmony_ci    }
81492f3ab15Sopenharmony_ci
81592f3ab15Sopenharmony_ci    /// Replaces the context's certificate store.
81692f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_set_cert_store)]
81792f3ab15Sopenharmony_ci    pub fn set_cert_store(&mut self, cert_store: X509Store) {
81892f3ab15Sopenharmony_ci        unsafe {
81992f3ab15Sopenharmony_ci            ffi::SSL_CTX_set_cert_store(self.as_ptr(), cert_store.as_ptr());
82092f3ab15Sopenharmony_ci            mem::forget(cert_store);
82192f3ab15Sopenharmony_ci        }
82292f3ab15Sopenharmony_ci    }
82392f3ab15Sopenharmony_ci
82492f3ab15Sopenharmony_ci    /// Controls read ahead behavior.
82592f3ab15Sopenharmony_ci    ///
82692f3ab15Sopenharmony_ci    /// If enabled, OpenSSL will read as much data as is available from the underlying stream,
82792f3ab15Sopenharmony_ci    /// instead of a single record at a time.
82892f3ab15Sopenharmony_ci    ///
82992f3ab15Sopenharmony_ci    /// It has no effect when used with DTLS.
83092f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_set_read_ahead)]
83192f3ab15Sopenharmony_ci    pub fn set_read_ahead(&mut self, read_ahead: bool) {
83292f3ab15Sopenharmony_ci        unsafe {
83392f3ab15Sopenharmony_ci            ffi::SSL_CTX_set_read_ahead(self.as_ptr(), read_ahead as SslBitType);
83492f3ab15Sopenharmony_ci        }
83592f3ab15Sopenharmony_ci    }
83692f3ab15Sopenharmony_ci
83792f3ab15Sopenharmony_ci    /// Sets the mode used by the context, returning the previous mode.
83892f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_set_mode)]
83992f3ab15Sopenharmony_ci    pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
84092f3ab15Sopenharmony_ci        unsafe {
84192f3ab15Sopenharmony_ci            let bits = ffi::SSL_CTX_set_mode(self.as_ptr(), mode.bits() as MtuTy) as SslBitType;
84292f3ab15Sopenharmony_ci            SslMode { bits }
84392f3ab15Sopenharmony_ci        }
84492f3ab15Sopenharmony_ci    }
84592f3ab15Sopenharmony_ci
84692f3ab15Sopenharmony_ci    /// Sets the parameters to be used during ephemeral Diffie-Hellman key exchange.
84792f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_set_tmp_dh)]
84892f3ab15Sopenharmony_ci    pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
84992f3ab15Sopenharmony_ci        unsafe { cvt(ffi::SSL_CTX_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
85092f3ab15Sopenharmony_ci    }
85192f3ab15Sopenharmony_ci
85292f3ab15Sopenharmony_ci    /// Sets the callback which will generate parameters to be used during ephemeral Diffie-Hellman
85392f3ab15Sopenharmony_ci    /// key exchange.
85492f3ab15Sopenharmony_ci    ///
85592f3ab15Sopenharmony_ci    /// The callback is provided with a reference to the `Ssl` for the session, as well as a boolean
85692f3ab15Sopenharmony_ci    /// indicating if the selected cipher is export-grade, and the key length. The export and key
85792f3ab15Sopenharmony_ci    /// length options are archaic and should be ignored in almost all cases.
85892f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_set_tmp_dh_callback)]
85992f3ab15Sopenharmony_ci    pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
86092f3ab15Sopenharmony_ci    where
86192f3ab15Sopenharmony_ci        F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
86292f3ab15Sopenharmony_ci    {
86392f3ab15Sopenharmony_ci        unsafe {
86492f3ab15Sopenharmony_ci            self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
86592f3ab15Sopenharmony_ci
86692f3ab15Sopenharmony_ci            #[cfg(not(boringssl))]
86792f3ab15Sopenharmony_ci            ffi::SSL_CTX_set_tmp_dh_callback__fixed_rust(self.as_ptr(), Some(raw_tmp_dh::<F>));
86892f3ab15Sopenharmony_ci            #[cfg(boringssl)]
86992f3ab15Sopenharmony_ci            ffi::SSL_CTX_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh::<F>));
87092f3ab15Sopenharmony_ci        }
87192f3ab15Sopenharmony_ci    }
87292f3ab15Sopenharmony_ci
87392f3ab15Sopenharmony_ci    /// Sets the parameters to be used during ephemeral elliptic curve Diffie-Hellman key exchange.
87492f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_set_tmp_ecdh)]
87592f3ab15Sopenharmony_ci    pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
87692f3ab15Sopenharmony_ci        unsafe { cvt(ffi::SSL_CTX_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
87792f3ab15Sopenharmony_ci    }
87892f3ab15Sopenharmony_ci
87992f3ab15Sopenharmony_ci    /// Sets the callback which will generate parameters to be used during ephemeral elliptic curve
88092f3ab15Sopenharmony_ci    /// Diffie-Hellman key exchange.
88192f3ab15Sopenharmony_ci    ///
88292f3ab15Sopenharmony_ci    /// The callback is provided with a reference to the `Ssl` for the session, as well as a boolean
88392f3ab15Sopenharmony_ci    /// indicating if the selected cipher is export-grade, and the key length. The export and key
88492f3ab15Sopenharmony_ci    /// length options are archaic and should be ignored in almost all cases.
88592f3ab15Sopenharmony_ci    ///
88692f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.0.1 or 1.0.2.
88792f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_set_tmp_ecdh_callback)]
88892f3ab15Sopenharmony_ci    #[cfg(all(ossl101, not(ossl110)))]
88992f3ab15Sopenharmony_ci    #[deprecated(note = "this function leaks memory and does not exist on newer OpenSSL versions")]
89092f3ab15Sopenharmony_ci    pub fn set_tmp_ecdh_callback<F>(&mut self, callback: F)
89192f3ab15Sopenharmony_ci    where
89292f3ab15Sopenharmony_ci        F: Fn(&mut SslRef, bool, u32) -> Result<EcKey<Params>, ErrorStack> + 'static + Sync + Send,
89392f3ab15Sopenharmony_ci    {
89492f3ab15Sopenharmony_ci        unsafe {
89592f3ab15Sopenharmony_ci            self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
89692f3ab15Sopenharmony_ci            ffi::SSL_CTX_set_tmp_ecdh_callback__fixed_rust(self.as_ptr(), Some(raw_tmp_ecdh::<F>));
89792f3ab15Sopenharmony_ci        }
89892f3ab15Sopenharmony_ci    }
89992f3ab15Sopenharmony_ci
90092f3ab15Sopenharmony_ci    /// Use the default locations of trusted certificates for verification.
90192f3ab15Sopenharmony_ci    ///
90292f3ab15Sopenharmony_ci    /// These locations are read from the `SSL_CERT_FILE` and `SSL_CERT_DIR` environment variables
90392f3ab15Sopenharmony_ci    /// if present, or defaults specified at OpenSSL build time otherwise.
90492f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_set_default_verify_paths)]
90592f3ab15Sopenharmony_ci    pub fn set_default_verify_paths(&mut self) -> Result<(), ErrorStack> {
90692f3ab15Sopenharmony_ci        unsafe { cvt(ffi::SSL_CTX_set_default_verify_paths(self.as_ptr())).map(|_| ()) }
90792f3ab15Sopenharmony_ci    }
90892f3ab15Sopenharmony_ci
90992f3ab15Sopenharmony_ci    /// Loads trusted root certificates from a file.
91092f3ab15Sopenharmony_ci    ///
91192f3ab15Sopenharmony_ci    /// The file should contain a sequence of PEM-formatted CA certificates.
91292f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_load_verify_locations)]
91392f3ab15Sopenharmony_ci    pub fn set_ca_file<P: AsRef<Path>>(&mut self, file: P) -> Result<(), ErrorStack> {
91492f3ab15Sopenharmony_ci        let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
91592f3ab15Sopenharmony_ci        unsafe {
91692f3ab15Sopenharmony_ci            cvt(ffi::SSL_CTX_load_verify_locations(
91792f3ab15Sopenharmony_ci                self.as_ptr(),
91892f3ab15Sopenharmony_ci                file.as_ptr() as *const _,
91992f3ab15Sopenharmony_ci                ptr::null(),
92092f3ab15Sopenharmony_ci            ))
92192f3ab15Sopenharmony_ci            .map(|_| ())
92292f3ab15Sopenharmony_ci        }
92392f3ab15Sopenharmony_ci    }
92492f3ab15Sopenharmony_ci
92592f3ab15Sopenharmony_ci    /// Sets the list of CA names sent to the client.
92692f3ab15Sopenharmony_ci    ///
92792f3ab15Sopenharmony_ci    /// The CA certificates must still be added to the trust root - they are not automatically set
92892f3ab15Sopenharmony_ci    /// as trusted by this method.
92992f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_set_client_CA_list)]
93092f3ab15Sopenharmony_ci    pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
93192f3ab15Sopenharmony_ci        unsafe {
93292f3ab15Sopenharmony_ci            ffi::SSL_CTX_set_client_CA_list(self.as_ptr(), list.as_ptr());
93392f3ab15Sopenharmony_ci            mem::forget(list);
93492f3ab15Sopenharmony_ci        }
93592f3ab15Sopenharmony_ci    }
93692f3ab15Sopenharmony_ci
93792f3ab15Sopenharmony_ci    /// Add the provided CA certificate to the list sent by the server to the client when
93892f3ab15Sopenharmony_ci    /// requesting client-side TLS authentication.
93992f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_add_client_CA)]
94092f3ab15Sopenharmony_ci    pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
94192f3ab15Sopenharmony_ci        unsafe { cvt(ffi::SSL_CTX_add_client_CA(self.as_ptr(), cacert.as_ptr())).map(|_| ()) }
94292f3ab15Sopenharmony_ci    }
94392f3ab15Sopenharmony_ci
94492f3ab15Sopenharmony_ci    /// Set the context identifier for sessions.
94592f3ab15Sopenharmony_ci    ///
94692f3ab15Sopenharmony_ci    /// This value identifies the server's session cache to clients, telling them when they're
94792f3ab15Sopenharmony_ci    /// able to reuse sessions. It should be set to a unique value per server, unless multiple
94892f3ab15Sopenharmony_ci    /// servers share a session cache.
94992f3ab15Sopenharmony_ci    ///
95092f3ab15Sopenharmony_ci    /// This value should be set when using client certificates, or each request will fail its
95192f3ab15Sopenharmony_ci    /// handshake and need to be restarted.
95292f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_set_session_id_context)]
95392f3ab15Sopenharmony_ci    pub fn set_session_id_context(&mut self, sid_ctx: &[u8]) -> Result<(), ErrorStack> {
95492f3ab15Sopenharmony_ci        unsafe {
95592f3ab15Sopenharmony_ci            assert!(sid_ctx.len() <= c_uint::max_value() as usize);
95692f3ab15Sopenharmony_ci            cvt(ffi::SSL_CTX_set_session_id_context(
95792f3ab15Sopenharmony_ci                self.as_ptr(),
95892f3ab15Sopenharmony_ci                sid_ctx.as_ptr(),
95992f3ab15Sopenharmony_ci                sid_ctx.len() as SizeTy,
96092f3ab15Sopenharmony_ci            ))
96192f3ab15Sopenharmony_ci            .map(|_| ())
96292f3ab15Sopenharmony_ci        }
96392f3ab15Sopenharmony_ci    }
96492f3ab15Sopenharmony_ci
96592f3ab15Sopenharmony_ci    /// Loads a leaf certificate from a file.
96692f3ab15Sopenharmony_ci    ///
96792f3ab15Sopenharmony_ci    /// Only a single certificate will be loaded - use `add_extra_chain_cert` to add the remainder
96892f3ab15Sopenharmony_ci    /// of the certificate chain, or `set_certificate_chain_file` to load the entire chain from a
96992f3ab15Sopenharmony_ci    /// single file.
97092f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_use_certificate_file)]
97192f3ab15Sopenharmony_ci    pub fn set_certificate_file<P: AsRef<Path>>(
97292f3ab15Sopenharmony_ci        &mut self,
97392f3ab15Sopenharmony_ci        file: P,
97492f3ab15Sopenharmony_ci        file_type: SslFiletype,
97592f3ab15Sopenharmony_ci    ) -> Result<(), ErrorStack> {
97692f3ab15Sopenharmony_ci        let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
97792f3ab15Sopenharmony_ci        unsafe {
97892f3ab15Sopenharmony_ci            cvt(ffi::SSL_CTX_use_certificate_file(
97992f3ab15Sopenharmony_ci                self.as_ptr(),
98092f3ab15Sopenharmony_ci                file.as_ptr() as *const _,
98192f3ab15Sopenharmony_ci                file_type.as_raw(),
98292f3ab15Sopenharmony_ci            ))
98392f3ab15Sopenharmony_ci            .map(|_| ())
98492f3ab15Sopenharmony_ci        }
98592f3ab15Sopenharmony_ci    }
98692f3ab15Sopenharmony_ci
98792f3ab15Sopenharmony_ci    /// Loads a certificate chain from a file.
98892f3ab15Sopenharmony_ci    ///
98992f3ab15Sopenharmony_ci    /// The file should contain a sequence of PEM-formatted certificates, the first being the leaf
99092f3ab15Sopenharmony_ci    /// certificate, and the remainder forming the chain of certificates up to and including the
99192f3ab15Sopenharmony_ci    /// trusted root certificate.
99292f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_use_certificate_chain_file)]
99392f3ab15Sopenharmony_ci    pub fn set_certificate_chain_file<P: AsRef<Path>>(
99492f3ab15Sopenharmony_ci        &mut self,
99592f3ab15Sopenharmony_ci        file: P,
99692f3ab15Sopenharmony_ci    ) -> Result<(), ErrorStack> {
99792f3ab15Sopenharmony_ci        let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
99892f3ab15Sopenharmony_ci        unsafe {
99992f3ab15Sopenharmony_ci            cvt(ffi::SSL_CTX_use_certificate_chain_file(
100092f3ab15Sopenharmony_ci                self.as_ptr(),
100192f3ab15Sopenharmony_ci                file.as_ptr() as *const _,
100292f3ab15Sopenharmony_ci            ))
100392f3ab15Sopenharmony_ci            .map(|_| ())
100492f3ab15Sopenharmony_ci        }
100592f3ab15Sopenharmony_ci    }
100692f3ab15Sopenharmony_ci
100792f3ab15Sopenharmony_ci    /// Sets the leaf certificate.
100892f3ab15Sopenharmony_ci    ///
100992f3ab15Sopenharmony_ci    /// Use `add_extra_chain_cert` to add the remainder of the certificate chain.
101092f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_use_certificate)]
101192f3ab15Sopenharmony_ci    pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
101292f3ab15Sopenharmony_ci        unsafe { cvt(ffi::SSL_CTX_use_certificate(self.as_ptr(), cert.as_ptr())).map(|_| ()) }
101392f3ab15Sopenharmony_ci    }
101492f3ab15Sopenharmony_ci
101592f3ab15Sopenharmony_ci    /// Appends a certificate to the certificate chain.
101692f3ab15Sopenharmony_ci    ///
101792f3ab15Sopenharmony_ci    /// This chain should contain all certificates necessary to go from the certificate specified by
101892f3ab15Sopenharmony_ci    /// `set_certificate` to a trusted root.
101992f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_add_extra_chain_cert)]
102092f3ab15Sopenharmony_ci    pub fn add_extra_chain_cert(&mut self, cert: X509) -> Result<(), ErrorStack> {
102192f3ab15Sopenharmony_ci        unsafe {
102292f3ab15Sopenharmony_ci            cvt(ffi::SSL_CTX_add_extra_chain_cert(self.as_ptr(), cert.as_ptr()) as c_int)?;
102392f3ab15Sopenharmony_ci            mem::forget(cert);
102492f3ab15Sopenharmony_ci            Ok(())
102592f3ab15Sopenharmony_ci        }
102692f3ab15Sopenharmony_ci    }
102792f3ab15Sopenharmony_ci
102892f3ab15Sopenharmony_ci    /// Loads the private key from a file.
102992f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_use_PrivateKey_file)]
103092f3ab15Sopenharmony_ci    pub fn set_private_key_file<P: AsRef<Path>>(
103192f3ab15Sopenharmony_ci        &mut self,
103292f3ab15Sopenharmony_ci        file: P,
103392f3ab15Sopenharmony_ci        file_type: SslFiletype,
103492f3ab15Sopenharmony_ci    ) -> Result<(), ErrorStack> {
103592f3ab15Sopenharmony_ci        let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
103692f3ab15Sopenharmony_ci        unsafe {
103792f3ab15Sopenharmony_ci            cvt(ffi::SSL_CTX_use_PrivateKey_file(
103892f3ab15Sopenharmony_ci                self.as_ptr(),
103992f3ab15Sopenharmony_ci                file.as_ptr() as *const _,
104092f3ab15Sopenharmony_ci                file_type.as_raw(),
104192f3ab15Sopenharmony_ci            ))
104292f3ab15Sopenharmony_ci            .map(|_| ())
104392f3ab15Sopenharmony_ci        }
104492f3ab15Sopenharmony_ci    }
104592f3ab15Sopenharmony_ci
104692f3ab15Sopenharmony_ci    /// Sets the private key.
104792f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_use_PrivateKey)]
104892f3ab15Sopenharmony_ci    pub fn set_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
104992f3ab15Sopenharmony_ci    where
105092f3ab15Sopenharmony_ci        T: HasPrivate,
105192f3ab15Sopenharmony_ci    {
105292f3ab15Sopenharmony_ci        unsafe { cvt(ffi::SSL_CTX_use_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) }
105392f3ab15Sopenharmony_ci    }
105492f3ab15Sopenharmony_ci
105592f3ab15Sopenharmony_ci    /// Sets the list of supported ciphers for protocols before TLSv1.3.
105692f3ab15Sopenharmony_ci    ///
105792f3ab15Sopenharmony_ci    /// The `set_ciphersuites` method controls the cipher suites for TLSv1.3.
105892f3ab15Sopenharmony_ci    ///
105992f3ab15Sopenharmony_ci    /// See [`ciphers`] for details on the format.
106092f3ab15Sopenharmony_ci    ///
106192f3ab15Sopenharmony_ci    /// [`ciphers`]: https://www.openssl.org/docs/manmaster/apps/ciphers.html
106292f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_set_cipher_list)]
106392f3ab15Sopenharmony_ci    pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
106492f3ab15Sopenharmony_ci        let cipher_list = CString::new(cipher_list).unwrap();
106592f3ab15Sopenharmony_ci        unsafe {
106692f3ab15Sopenharmony_ci            cvt(ffi::SSL_CTX_set_cipher_list(
106792f3ab15Sopenharmony_ci                self.as_ptr(),
106892f3ab15Sopenharmony_ci                cipher_list.as_ptr() as *const _,
106992f3ab15Sopenharmony_ci            ))
107092f3ab15Sopenharmony_ci            .map(|_| ())
107192f3ab15Sopenharmony_ci        }
107292f3ab15Sopenharmony_ci    }
107392f3ab15Sopenharmony_ci
107492f3ab15Sopenharmony_ci    /// Sets the list of supported ciphers for the TLSv1.3 protocol.
107592f3ab15Sopenharmony_ci    ///
107692f3ab15Sopenharmony_ci    /// The `set_cipher_list` method controls the cipher suites for protocols before TLSv1.3.
107792f3ab15Sopenharmony_ci    ///
107892f3ab15Sopenharmony_ci    /// The format consists of TLSv1.3 cipher suite names separated by `:` characters in order of
107992f3ab15Sopenharmony_ci    /// preference.
108092f3ab15Sopenharmony_ci    ///
108192f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer.
108292f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_set_ciphersuites)]
108392f3ab15Sopenharmony_ci    #[cfg(any(ossl111, libressl340))]
108492f3ab15Sopenharmony_ci    pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
108592f3ab15Sopenharmony_ci        let cipher_list = CString::new(cipher_list).unwrap();
108692f3ab15Sopenharmony_ci        unsafe {
108792f3ab15Sopenharmony_ci            cvt(ffi::SSL_CTX_set_ciphersuites(
108892f3ab15Sopenharmony_ci                self.as_ptr(),
108992f3ab15Sopenharmony_ci                cipher_list.as_ptr() as *const _,
109092f3ab15Sopenharmony_ci            ))
109192f3ab15Sopenharmony_ci            .map(|_| ())
109292f3ab15Sopenharmony_ci        }
109392f3ab15Sopenharmony_ci    }
109492f3ab15Sopenharmony_ci
109592f3ab15Sopenharmony_ci    /// Enables ECDHE key exchange with an automatically chosen curve list.
109692f3ab15Sopenharmony_ci    ///
109792f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.0.2.
109892f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_set_ecdh_auto)]
109992f3ab15Sopenharmony_ci    #[cfg(any(libressl, all(ossl102, not(ossl110))))]
110092f3ab15Sopenharmony_ci    pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
110192f3ab15Sopenharmony_ci        unsafe { cvt(ffi::SSL_CTX_set_ecdh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) }
110292f3ab15Sopenharmony_ci    }
110392f3ab15Sopenharmony_ci
110492f3ab15Sopenharmony_ci    /// Sets the options used by the context, returning the old set.
110592f3ab15Sopenharmony_ci    ///
110692f3ab15Sopenharmony_ci    /// # Note
110792f3ab15Sopenharmony_ci    ///
110892f3ab15Sopenharmony_ci    /// This *enables* the specified options, but does not disable unspecified options. Use
110992f3ab15Sopenharmony_ci    /// `clear_options` for that.
111092f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_set_options)]
111192f3ab15Sopenharmony_ci    pub fn set_options(&mut self, option: SslOptions) -> SslOptions {
111292f3ab15Sopenharmony_ci        let bits =
111392f3ab15Sopenharmony_ci            unsafe { ffi::SSL_CTX_set_options(self.as_ptr(), option.bits()) } as SslOptionsRepr;
111492f3ab15Sopenharmony_ci        SslOptions { bits }
111592f3ab15Sopenharmony_ci    }
111692f3ab15Sopenharmony_ci
111792f3ab15Sopenharmony_ci    /// Returns the options used by the context.
111892f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_get_options)]
111992f3ab15Sopenharmony_ci    pub fn options(&self) -> SslOptions {
112092f3ab15Sopenharmony_ci        let bits = unsafe { ffi::SSL_CTX_get_options(self.as_ptr()) } as SslOptionsRepr;
112192f3ab15Sopenharmony_ci        SslOptions { bits }
112292f3ab15Sopenharmony_ci    }
112392f3ab15Sopenharmony_ci
112492f3ab15Sopenharmony_ci    /// Clears the options used by the context, returning the old set.
112592f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_clear_options)]
112692f3ab15Sopenharmony_ci    pub fn clear_options(&mut self, option: SslOptions) -> SslOptions {
112792f3ab15Sopenharmony_ci        let bits =
112892f3ab15Sopenharmony_ci            unsafe { ffi::SSL_CTX_clear_options(self.as_ptr(), option.bits()) } as SslOptionsRepr;
112992f3ab15Sopenharmony_ci        SslOptions { bits }
113092f3ab15Sopenharmony_ci    }
113192f3ab15Sopenharmony_ci
113292f3ab15Sopenharmony_ci    /// Sets the minimum supported protocol version.
113392f3ab15Sopenharmony_ci    ///
113492f3ab15Sopenharmony_ci    /// A value of `None` will enable protocol versions down to the lowest version supported by
113592f3ab15Sopenharmony_ci    /// OpenSSL.
113692f3ab15Sopenharmony_ci    ///
113792f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.1.0 or LibreSSL 2.6.1 or newer.
113892f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_set_min_proto_version)]
113992f3ab15Sopenharmony_ci    #[cfg(any(ossl110, libressl261))]
114092f3ab15Sopenharmony_ci    pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
114192f3ab15Sopenharmony_ci        unsafe {
114292f3ab15Sopenharmony_ci            cvt(ffi::SSL_CTX_set_min_proto_version(
114392f3ab15Sopenharmony_ci                self.as_ptr(),
114492f3ab15Sopenharmony_ci                version.map_or(0, |v| v.0 as _),
114592f3ab15Sopenharmony_ci            ))
114692f3ab15Sopenharmony_ci            .map(|_| ())
114792f3ab15Sopenharmony_ci        }
114892f3ab15Sopenharmony_ci    }
114992f3ab15Sopenharmony_ci
115092f3ab15Sopenharmony_ci    /// Sets the maximum supported protocol version.
115192f3ab15Sopenharmony_ci    ///
115292f3ab15Sopenharmony_ci    /// A value of `None` will enable protocol versions up to the highest version supported by
115392f3ab15Sopenharmony_ci    /// OpenSSL.
115492f3ab15Sopenharmony_ci    ///
115592f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.1.0 or or LibreSSL 2.6.1 or newer.
115692f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_set_max_proto_version)]
115792f3ab15Sopenharmony_ci    #[cfg(any(ossl110, libressl261))]
115892f3ab15Sopenharmony_ci    pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
115992f3ab15Sopenharmony_ci        unsafe {
116092f3ab15Sopenharmony_ci            cvt(ffi::SSL_CTX_set_max_proto_version(
116192f3ab15Sopenharmony_ci                self.as_ptr(),
116292f3ab15Sopenharmony_ci                version.map_or(0, |v| v.0 as _),
116392f3ab15Sopenharmony_ci            ))
116492f3ab15Sopenharmony_ci            .map(|_| ())
116592f3ab15Sopenharmony_ci        }
116692f3ab15Sopenharmony_ci    }
116792f3ab15Sopenharmony_ci
116892f3ab15Sopenharmony_ci    /// Gets the minimum supported protocol version.
116992f3ab15Sopenharmony_ci    ///
117092f3ab15Sopenharmony_ci    /// A value of `None` indicates that all versions down to the lowest version supported by
117192f3ab15Sopenharmony_ci    /// OpenSSL are enabled.
117292f3ab15Sopenharmony_ci    ///
117392f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.1.0g or LibreSSL 2.7.0 or newer.
117492f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_get_min_proto_version)]
117592f3ab15Sopenharmony_ci    #[cfg(any(ossl110g, libressl270))]
117692f3ab15Sopenharmony_ci    pub fn min_proto_version(&mut self) -> Option<SslVersion> {
117792f3ab15Sopenharmony_ci        unsafe {
117892f3ab15Sopenharmony_ci            let r = ffi::SSL_CTX_get_min_proto_version(self.as_ptr());
117992f3ab15Sopenharmony_ci            if r == 0 {
118092f3ab15Sopenharmony_ci                None
118192f3ab15Sopenharmony_ci            } else {
118292f3ab15Sopenharmony_ci                Some(SslVersion(r))
118392f3ab15Sopenharmony_ci            }
118492f3ab15Sopenharmony_ci        }
118592f3ab15Sopenharmony_ci    }
118692f3ab15Sopenharmony_ci
118792f3ab15Sopenharmony_ci    /// Gets the maximum supported protocol version.
118892f3ab15Sopenharmony_ci    ///
118992f3ab15Sopenharmony_ci    /// A value of `None` indicates that all versions up to the highest version supported by
119092f3ab15Sopenharmony_ci    /// OpenSSL are enabled.
119192f3ab15Sopenharmony_ci    ///
119292f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.1.0g or LibreSSL 2.7.0 or newer.
119392f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_get_max_proto_version)]
119492f3ab15Sopenharmony_ci    #[cfg(any(ossl110g, libressl270))]
119592f3ab15Sopenharmony_ci    pub fn max_proto_version(&mut self) -> Option<SslVersion> {
119692f3ab15Sopenharmony_ci        unsafe {
119792f3ab15Sopenharmony_ci            let r = ffi::SSL_CTX_get_max_proto_version(self.as_ptr());
119892f3ab15Sopenharmony_ci            if r == 0 {
119992f3ab15Sopenharmony_ci                None
120092f3ab15Sopenharmony_ci            } else {
120192f3ab15Sopenharmony_ci                Some(SslVersion(r))
120292f3ab15Sopenharmony_ci            }
120392f3ab15Sopenharmony_ci        }
120492f3ab15Sopenharmony_ci    }
120592f3ab15Sopenharmony_ci
120692f3ab15Sopenharmony_ci    /// Sets the protocols to sent to the server for Application Layer Protocol Negotiation (ALPN).
120792f3ab15Sopenharmony_ci    ///
120892f3ab15Sopenharmony_ci    /// The input must be in ALPN "wire format". It consists of a sequence of supported protocol
120992f3ab15Sopenharmony_ci    /// names prefixed by their byte length. For example, the protocol list consisting of `spdy/1`
121092f3ab15Sopenharmony_ci    /// and `http/1.1` is encoded as `b"\x06spdy/1\x08http/1.1"`. The protocols are ordered by
121192f3ab15Sopenharmony_ci    /// preference.
121292f3ab15Sopenharmony_ci    ///
121392f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.0.2 or LibreSSL 2.6.1 or newer.
121492f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_set_alpn_protos)]
121592f3ab15Sopenharmony_ci    #[cfg(any(ossl102, libressl261))]
121692f3ab15Sopenharmony_ci    pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
121792f3ab15Sopenharmony_ci        unsafe {
121892f3ab15Sopenharmony_ci            assert!(protocols.len() <= c_uint::max_value() as usize);
121992f3ab15Sopenharmony_ci            let r = ffi::SSL_CTX_set_alpn_protos(
122092f3ab15Sopenharmony_ci                self.as_ptr(),
122192f3ab15Sopenharmony_ci                protocols.as_ptr(),
122292f3ab15Sopenharmony_ci                protocols.len() as c_uint,
122392f3ab15Sopenharmony_ci            );
122492f3ab15Sopenharmony_ci            // fun fact, SSL_CTX_set_alpn_protos has a reversed return code D:
122592f3ab15Sopenharmony_ci            if r == 0 {
122692f3ab15Sopenharmony_ci                Ok(())
122792f3ab15Sopenharmony_ci            } else {
122892f3ab15Sopenharmony_ci                Err(ErrorStack::get())
122992f3ab15Sopenharmony_ci            }
123092f3ab15Sopenharmony_ci        }
123192f3ab15Sopenharmony_ci    }
123292f3ab15Sopenharmony_ci
123392f3ab15Sopenharmony_ci    /// Enables the DTLS extension "use_srtp" as defined in RFC5764.
123492f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_set_tlsext_use_srtp)]
123592f3ab15Sopenharmony_ci    pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
123692f3ab15Sopenharmony_ci        unsafe {
123792f3ab15Sopenharmony_ci            let cstr = CString::new(protocols).unwrap();
123892f3ab15Sopenharmony_ci
123992f3ab15Sopenharmony_ci            let r = ffi::SSL_CTX_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
124092f3ab15Sopenharmony_ci            // fun fact, set_tlsext_use_srtp has a reversed return code D:
124192f3ab15Sopenharmony_ci            if r == 0 {
124292f3ab15Sopenharmony_ci                Ok(())
124392f3ab15Sopenharmony_ci            } else {
124492f3ab15Sopenharmony_ci                Err(ErrorStack::get())
124592f3ab15Sopenharmony_ci            }
124692f3ab15Sopenharmony_ci        }
124792f3ab15Sopenharmony_ci    }
124892f3ab15Sopenharmony_ci
124992f3ab15Sopenharmony_ci    /// Sets the callback used by a server to select a protocol for Application Layer Protocol
125092f3ab15Sopenharmony_ci    /// Negotiation (ALPN).
125192f3ab15Sopenharmony_ci    ///
125292f3ab15Sopenharmony_ci    /// The callback is provided with the client's protocol list in ALPN wire format. See the
125392f3ab15Sopenharmony_ci    /// documentation for [`SslContextBuilder::set_alpn_protos`] for details. It should return one
125492f3ab15Sopenharmony_ci    /// of those protocols on success. The [`select_next_proto`] function implements the standard
125592f3ab15Sopenharmony_ci    /// protocol selection algorithm.
125692f3ab15Sopenharmony_ci    ///
125792f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.0.2 or LibreSSL 2.6.1 or newer.
125892f3ab15Sopenharmony_ci    ///
125992f3ab15Sopenharmony_ci    /// [`SslContextBuilder::set_alpn_protos`]: struct.SslContextBuilder.html#method.set_alpn_protos
126092f3ab15Sopenharmony_ci    /// [`select_next_proto`]: fn.select_next_proto.html
126192f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_set_alpn_select_cb)]
126292f3ab15Sopenharmony_ci    #[cfg(any(ossl102, libressl261))]
126392f3ab15Sopenharmony_ci    pub fn set_alpn_select_callback<F>(&mut self, callback: F)
126492f3ab15Sopenharmony_ci    where
126592f3ab15Sopenharmony_ci        F: for<'a> Fn(&mut SslRef, &'a [u8]) -> Result<&'a [u8], AlpnError> + 'static + Sync + Send,
126692f3ab15Sopenharmony_ci    {
126792f3ab15Sopenharmony_ci        unsafe {
126892f3ab15Sopenharmony_ci            self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
126992f3ab15Sopenharmony_ci            ffi::SSL_CTX_set_alpn_select_cb__fixed_rust(
127092f3ab15Sopenharmony_ci                self.as_ptr(),
127192f3ab15Sopenharmony_ci                Some(callbacks::raw_alpn_select::<F>),
127292f3ab15Sopenharmony_ci                ptr::null_mut(),
127392f3ab15Sopenharmony_ci            );
127492f3ab15Sopenharmony_ci        }
127592f3ab15Sopenharmony_ci    }
127692f3ab15Sopenharmony_ci
127792f3ab15Sopenharmony_ci    /// Checks for consistency between the private key and certificate.
127892f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_check_private_key)]
127992f3ab15Sopenharmony_ci    pub fn check_private_key(&self) -> Result<(), ErrorStack> {
128092f3ab15Sopenharmony_ci        unsafe { cvt(ffi::SSL_CTX_check_private_key(self.as_ptr())).map(|_| ()) }
128192f3ab15Sopenharmony_ci    }
128292f3ab15Sopenharmony_ci
128392f3ab15Sopenharmony_ci    /// Returns a shared reference to the context's certificate store.
128492f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_get_cert_store)]
128592f3ab15Sopenharmony_ci    pub fn cert_store(&self) -> &X509StoreBuilderRef {
128692f3ab15Sopenharmony_ci        unsafe { X509StoreBuilderRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
128792f3ab15Sopenharmony_ci    }
128892f3ab15Sopenharmony_ci
128992f3ab15Sopenharmony_ci    /// Returns a mutable reference to the context's certificate store.
129092f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_get_cert_store)]
129192f3ab15Sopenharmony_ci    pub fn cert_store_mut(&mut self) -> &mut X509StoreBuilderRef {
129292f3ab15Sopenharmony_ci        unsafe { X509StoreBuilderRef::from_ptr_mut(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
129392f3ab15Sopenharmony_ci    }
129492f3ab15Sopenharmony_ci
129592f3ab15Sopenharmony_ci    /// Returns a reference to the X509 verification configuration.
129692f3ab15Sopenharmony_ci    ///
129792f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.0.2 or newer.
129892f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_get0_param)]
129992f3ab15Sopenharmony_ci    #[cfg(any(ossl102, libressl261))]
130092f3ab15Sopenharmony_ci    pub fn verify_param(&self) -> &X509VerifyParamRef {
130192f3ab15Sopenharmony_ci        unsafe { X509VerifyParamRef::from_ptr(ffi::SSL_CTX_get0_param(self.as_ptr())) }
130292f3ab15Sopenharmony_ci    }
130392f3ab15Sopenharmony_ci
130492f3ab15Sopenharmony_ci    /// Returns a mutable reference to the X509 verification configuration.
130592f3ab15Sopenharmony_ci    ///
130692f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.0.2 or newer.
130792f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_get0_param)]
130892f3ab15Sopenharmony_ci    #[cfg(any(ossl102, libressl261))]
130992f3ab15Sopenharmony_ci    pub fn verify_param_mut(&mut self) -> &mut X509VerifyParamRef {
131092f3ab15Sopenharmony_ci        unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_CTX_get0_param(self.as_ptr())) }
131192f3ab15Sopenharmony_ci    }
131292f3ab15Sopenharmony_ci
131392f3ab15Sopenharmony_ci    /// Sets the callback dealing with OCSP stapling.
131492f3ab15Sopenharmony_ci    ///
131592f3ab15Sopenharmony_ci    /// On the client side, this callback is responsible for validating the OCSP status response
131692f3ab15Sopenharmony_ci    /// returned by the server. The status may be retrieved with the `SslRef::ocsp_status` method.
131792f3ab15Sopenharmony_ci    /// A response of `Ok(true)` indicates that the OCSP status is valid, and a response of
131892f3ab15Sopenharmony_ci    /// `Ok(false)` indicates that the OCSP status is invalid and the handshake should be
131992f3ab15Sopenharmony_ci    /// terminated.
132092f3ab15Sopenharmony_ci    ///
132192f3ab15Sopenharmony_ci    /// On the server side, this callback is responsible for setting the OCSP status response to be
132292f3ab15Sopenharmony_ci    /// returned to clients. The status may be set with the `SslRef::set_ocsp_status` method. A
132392f3ab15Sopenharmony_ci    /// response of `Ok(true)` indicates that the OCSP status should be returned to the client, and
132492f3ab15Sopenharmony_ci    /// `Ok(false)` indicates that the status should not be returned to the client.
132592f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_set_tlsext_status_cb)]
132692f3ab15Sopenharmony_ci    pub fn set_status_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
132792f3ab15Sopenharmony_ci    where
132892f3ab15Sopenharmony_ci        F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + 'static + Sync + Send,
132992f3ab15Sopenharmony_ci    {
133092f3ab15Sopenharmony_ci        unsafe {
133192f3ab15Sopenharmony_ci            self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
133292f3ab15Sopenharmony_ci            cvt(
133392f3ab15Sopenharmony_ci                ffi::SSL_CTX_set_tlsext_status_cb(self.as_ptr(), Some(raw_tlsext_status::<F>))
133492f3ab15Sopenharmony_ci                    as c_int,
133592f3ab15Sopenharmony_ci            )
133692f3ab15Sopenharmony_ci            .map(|_| ())
133792f3ab15Sopenharmony_ci        }
133892f3ab15Sopenharmony_ci    }
133992f3ab15Sopenharmony_ci
134092f3ab15Sopenharmony_ci    /// Sets the callback for providing an identity and pre-shared key for a TLS-PSK client.
134192f3ab15Sopenharmony_ci    ///
134292f3ab15Sopenharmony_ci    /// The callback will be called with the SSL context, an identity hint if one was provided
134392f3ab15Sopenharmony_ci    /// by the server, a mutable slice for each of the identity and pre-shared key bytes. The
134492f3ab15Sopenharmony_ci    /// identity must be written as a null-terminated C string.
134592f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_set_psk_client_callback)]
134692f3ab15Sopenharmony_ci    #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
134792f3ab15Sopenharmony_ci    pub fn set_psk_client_callback<F>(&mut self, callback: F)
134892f3ab15Sopenharmony_ci    where
134992f3ab15Sopenharmony_ci        F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
135092f3ab15Sopenharmony_ci            + 'static
135192f3ab15Sopenharmony_ci            + Sync
135292f3ab15Sopenharmony_ci            + Send,
135392f3ab15Sopenharmony_ci    {
135492f3ab15Sopenharmony_ci        unsafe {
135592f3ab15Sopenharmony_ci            self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
135692f3ab15Sopenharmony_ci            ffi::SSL_CTX_set_psk_client_callback(self.as_ptr(), Some(raw_client_psk::<F>));
135792f3ab15Sopenharmony_ci        }
135892f3ab15Sopenharmony_ci    }
135992f3ab15Sopenharmony_ci
136092f3ab15Sopenharmony_ci    #[deprecated(since = "0.10.10", note = "renamed to `set_psk_client_callback`")]
136192f3ab15Sopenharmony_ci    #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
136292f3ab15Sopenharmony_ci    pub fn set_psk_callback<F>(&mut self, callback: F)
136392f3ab15Sopenharmony_ci    where
136492f3ab15Sopenharmony_ci        F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
136592f3ab15Sopenharmony_ci            + 'static
136692f3ab15Sopenharmony_ci            + Sync
136792f3ab15Sopenharmony_ci            + Send,
136892f3ab15Sopenharmony_ci    {
136992f3ab15Sopenharmony_ci        self.set_psk_client_callback(callback)
137092f3ab15Sopenharmony_ci    }
137192f3ab15Sopenharmony_ci
137292f3ab15Sopenharmony_ci    /// Sets the callback for providing an identity and pre-shared key for a TLS-PSK server.
137392f3ab15Sopenharmony_ci    ///
137492f3ab15Sopenharmony_ci    /// The callback will be called with the SSL context, an identity provided by the client,
137592f3ab15Sopenharmony_ci    /// and, a mutable slice for the pre-shared key bytes. The callback returns the number of
137692f3ab15Sopenharmony_ci    /// bytes in the pre-shared key.
137792f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_set_psk_server_callback)]
137892f3ab15Sopenharmony_ci    #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
137992f3ab15Sopenharmony_ci    pub fn set_psk_server_callback<F>(&mut self, callback: F)
138092f3ab15Sopenharmony_ci    where
138192f3ab15Sopenharmony_ci        F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8]) -> Result<usize, ErrorStack>
138292f3ab15Sopenharmony_ci            + 'static
138392f3ab15Sopenharmony_ci            + Sync
138492f3ab15Sopenharmony_ci            + Send,
138592f3ab15Sopenharmony_ci    {
138692f3ab15Sopenharmony_ci        unsafe {
138792f3ab15Sopenharmony_ci            self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
138892f3ab15Sopenharmony_ci            ffi::SSL_CTX_set_psk_server_callback(self.as_ptr(), Some(raw_server_psk::<F>));
138992f3ab15Sopenharmony_ci        }
139092f3ab15Sopenharmony_ci    }
139192f3ab15Sopenharmony_ci
139292f3ab15Sopenharmony_ci    /// Sets the callback which is called when new sessions are negotiated.
139392f3ab15Sopenharmony_ci    ///
139492f3ab15Sopenharmony_ci    /// This can be used by clients to implement session caching. While in TLSv1.2 the session is
139592f3ab15Sopenharmony_ci    /// available to access via [`SslRef::session`] immediately after the handshake completes, this
139692f3ab15Sopenharmony_ci    /// is not the case for TLSv1.3. There, a session is not generally available immediately, and
139792f3ab15Sopenharmony_ci    /// the server may provide multiple session tokens to the client over a single session. The new
139892f3ab15Sopenharmony_ci    /// session callback is a portable way to deal with both cases.
139992f3ab15Sopenharmony_ci    ///
140092f3ab15Sopenharmony_ci    /// Note that session caching must be enabled for the callback to be invoked, and it defaults
140192f3ab15Sopenharmony_ci    /// off for clients. [`set_session_cache_mode`] controls that behavior.
140292f3ab15Sopenharmony_ci    ///
140392f3ab15Sopenharmony_ci    /// [`SslRef::session`]: struct.SslRef.html#method.session
140492f3ab15Sopenharmony_ci    /// [`set_session_cache_mode`]: #method.set_session_cache_mode
140592f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_sess_set_new_cb)]
140692f3ab15Sopenharmony_ci    pub fn set_new_session_callback<F>(&mut self, callback: F)
140792f3ab15Sopenharmony_ci    where
140892f3ab15Sopenharmony_ci        F: Fn(&mut SslRef, SslSession) + 'static + Sync + Send,
140992f3ab15Sopenharmony_ci    {
141092f3ab15Sopenharmony_ci        unsafe {
141192f3ab15Sopenharmony_ci            self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
141292f3ab15Sopenharmony_ci            ffi::SSL_CTX_sess_set_new_cb(self.as_ptr(), Some(callbacks::raw_new_session::<F>));
141392f3ab15Sopenharmony_ci        }
141492f3ab15Sopenharmony_ci    }
141592f3ab15Sopenharmony_ci
141692f3ab15Sopenharmony_ci    /// Sets the callback which is called when sessions are removed from the context.
141792f3ab15Sopenharmony_ci    ///
141892f3ab15Sopenharmony_ci    /// Sessions can be removed because they have timed out or because they are considered faulty.
141992f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_sess_set_remove_cb)]
142092f3ab15Sopenharmony_ci    pub fn set_remove_session_callback<F>(&mut self, callback: F)
142192f3ab15Sopenharmony_ci    where
142292f3ab15Sopenharmony_ci        F: Fn(&SslContextRef, &SslSessionRef) + 'static + Sync + Send,
142392f3ab15Sopenharmony_ci    {
142492f3ab15Sopenharmony_ci        unsafe {
142592f3ab15Sopenharmony_ci            self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
142692f3ab15Sopenharmony_ci            ffi::SSL_CTX_sess_set_remove_cb(
142792f3ab15Sopenharmony_ci                self.as_ptr(),
142892f3ab15Sopenharmony_ci                Some(callbacks::raw_remove_session::<F>),
142992f3ab15Sopenharmony_ci            );
143092f3ab15Sopenharmony_ci        }
143192f3ab15Sopenharmony_ci    }
143292f3ab15Sopenharmony_ci
143392f3ab15Sopenharmony_ci    /// Sets the callback which is called when a client proposed to resume a session but it was not
143492f3ab15Sopenharmony_ci    /// found in the internal cache.
143592f3ab15Sopenharmony_ci    ///
143692f3ab15Sopenharmony_ci    /// The callback is passed a reference to the session ID provided by the client. It should
143792f3ab15Sopenharmony_ci    /// return the session corresponding to that ID if available. This is only used for servers, not
143892f3ab15Sopenharmony_ci    /// clients.
143992f3ab15Sopenharmony_ci    ///
144092f3ab15Sopenharmony_ci    /// # Safety
144192f3ab15Sopenharmony_ci    ///
144292f3ab15Sopenharmony_ci    /// The returned `SslSession` must not be associated with a different `SslContext`.
144392f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_sess_set_get_cb)]
144492f3ab15Sopenharmony_ci    pub unsafe fn set_get_session_callback<F>(&mut self, callback: F)
144592f3ab15Sopenharmony_ci    where
144692f3ab15Sopenharmony_ci        F: Fn(&mut SslRef, &[u8]) -> Option<SslSession> + 'static + Sync + Send,
144792f3ab15Sopenharmony_ci    {
144892f3ab15Sopenharmony_ci        self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
144992f3ab15Sopenharmony_ci        ffi::SSL_CTX_sess_set_get_cb(self.as_ptr(), Some(callbacks::raw_get_session::<F>));
145092f3ab15Sopenharmony_ci    }
145192f3ab15Sopenharmony_ci
145292f3ab15Sopenharmony_ci    /// Sets the TLS key logging callback.
145392f3ab15Sopenharmony_ci    ///
145492f3ab15Sopenharmony_ci    /// The callback is invoked whenever TLS key material is generated, and is passed a line of NSS
145592f3ab15Sopenharmony_ci    /// SSLKEYLOGFILE-formatted text. This can be used by tools like Wireshark to decrypt message
145692f3ab15Sopenharmony_ci    /// traffic. The line does not contain a trailing newline.
145792f3ab15Sopenharmony_ci    ///
145892f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.1.1 or newer.
145992f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_set_keylog_callback)]
146092f3ab15Sopenharmony_ci    #[cfg(ossl111)]
146192f3ab15Sopenharmony_ci    pub fn set_keylog_callback<F>(&mut self, callback: F)
146292f3ab15Sopenharmony_ci    where
146392f3ab15Sopenharmony_ci        F: Fn(&SslRef, &str) + 'static + Sync + Send,
146492f3ab15Sopenharmony_ci    {
146592f3ab15Sopenharmony_ci        unsafe {
146692f3ab15Sopenharmony_ci            self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
146792f3ab15Sopenharmony_ci            ffi::SSL_CTX_set_keylog_callback(self.as_ptr(), Some(callbacks::raw_keylog::<F>));
146892f3ab15Sopenharmony_ci        }
146992f3ab15Sopenharmony_ci    }
147092f3ab15Sopenharmony_ci
147192f3ab15Sopenharmony_ci    /// Sets the session caching mode use for connections made with the context.
147292f3ab15Sopenharmony_ci    ///
147392f3ab15Sopenharmony_ci    /// Returns the previous session caching mode.
147492f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_set_session_cache_mode)]
147592f3ab15Sopenharmony_ci    pub fn set_session_cache_mode(&mut self, mode: SslSessionCacheMode) -> SslSessionCacheMode {
147692f3ab15Sopenharmony_ci        unsafe {
147792f3ab15Sopenharmony_ci            let bits = ffi::SSL_CTX_set_session_cache_mode(self.as_ptr(), mode.bits());
147892f3ab15Sopenharmony_ci            SslSessionCacheMode { bits }
147992f3ab15Sopenharmony_ci        }
148092f3ab15Sopenharmony_ci    }
148192f3ab15Sopenharmony_ci
148292f3ab15Sopenharmony_ci    /// Sets the callback for generating an application cookie for TLS1.3
148392f3ab15Sopenharmony_ci    /// stateless handshakes.
148492f3ab15Sopenharmony_ci    ///
148592f3ab15Sopenharmony_ci    /// The callback will be called with the SSL context and a slice into which the cookie
148692f3ab15Sopenharmony_ci    /// should be written. The callback should return the number of bytes written.
148792f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_set_stateless_cookie_generate_cb)]
148892f3ab15Sopenharmony_ci    #[cfg(ossl111)]
148992f3ab15Sopenharmony_ci    pub fn set_stateless_cookie_generate_cb<F>(&mut self, callback: F)
149092f3ab15Sopenharmony_ci    where
149192f3ab15Sopenharmony_ci        F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
149292f3ab15Sopenharmony_ci    {
149392f3ab15Sopenharmony_ci        unsafe {
149492f3ab15Sopenharmony_ci            self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
149592f3ab15Sopenharmony_ci            ffi::SSL_CTX_set_stateless_cookie_generate_cb(
149692f3ab15Sopenharmony_ci                self.as_ptr(),
149792f3ab15Sopenharmony_ci                Some(raw_stateless_cookie_generate::<F>),
149892f3ab15Sopenharmony_ci            );
149992f3ab15Sopenharmony_ci        }
150092f3ab15Sopenharmony_ci    }
150192f3ab15Sopenharmony_ci
150292f3ab15Sopenharmony_ci    /// Sets the callback for verifying an application cookie for TLS1.3
150392f3ab15Sopenharmony_ci    /// stateless handshakes.
150492f3ab15Sopenharmony_ci    ///
150592f3ab15Sopenharmony_ci    /// The callback will be called with the SSL context and the cookie supplied by the
150692f3ab15Sopenharmony_ci    /// client. It should return true if and only if the cookie is valid.
150792f3ab15Sopenharmony_ci    ///
150892f3ab15Sopenharmony_ci    /// Note that the OpenSSL implementation independently verifies the integrity of
150992f3ab15Sopenharmony_ci    /// application cookies using an HMAC before invoking the supplied callback.
151092f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_set_stateless_cookie_verify_cb)]
151192f3ab15Sopenharmony_ci    #[cfg(ossl111)]
151292f3ab15Sopenharmony_ci    pub fn set_stateless_cookie_verify_cb<F>(&mut self, callback: F)
151392f3ab15Sopenharmony_ci    where
151492f3ab15Sopenharmony_ci        F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
151592f3ab15Sopenharmony_ci    {
151692f3ab15Sopenharmony_ci        unsafe {
151792f3ab15Sopenharmony_ci            self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
151892f3ab15Sopenharmony_ci            ffi::SSL_CTX_set_stateless_cookie_verify_cb(
151992f3ab15Sopenharmony_ci                self.as_ptr(),
152092f3ab15Sopenharmony_ci                Some(raw_stateless_cookie_verify::<F>),
152192f3ab15Sopenharmony_ci            )
152292f3ab15Sopenharmony_ci        }
152392f3ab15Sopenharmony_ci    }
152492f3ab15Sopenharmony_ci
152592f3ab15Sopenharmony_ci    /// Sets the callback for generating a DTLSv1 cookie
152692f3ab15Sopenharmony_ci    ///
152792f3ab15Sopenharmony_ci    /// The callback will be called with the SSL context and a slice into which the cookie
152892f3ab15Sopenharmony_ci    /// should be written. The callback should return the number of bytes written.
152992f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_set_cookie_generate_cb)]
153092f3ab15Sopenharmony_ci    #[cfg(not(boringssl))]
153192f3ab15Sopenharmony_ci    pub fn set_cookie_generate_cb<F>(&mut self, callback: F)
153292f3ab15Sopenharmony_ci    where
153392f3ab15Sopenharmony_ci        F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
153492f3ab15Sopenharmony_ci    {
153592f3ab15Sopenharmony_ci        unsafe {
153692f3ab15Sopenharmony_ci            self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
153792f3ab15Sopenharmony_ci            ffi::SSL_CTX_set_cookie_generate_cb(self.as_ptr(), Some(raw_cookie_generate::<F>));
153892f3ab15Sopenharmony_ci        }
153992f3ab15Sopenharmony_ci    }
154092f3ab15Sopenharmony_ci
154192f3ab15Sopenharmony_ci    /// Sets the callback for verifying a DTLSv1 cookie
154292f3ab15Sopenharmony_ci    ///
154392f3ab15Sopenharmony_ci    /// The callback will be called with the SSL context and the cookie supplied by the
154492f3ab15Sopenharmony_ci    /// client. It should return true if and only if the cookie is valid.
154592f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_set_cookie_verify_cb)]
154692f3ab15Sopenharmony_ci    #[cfg(not(boringssl))]
154792f3ab15Sopenharmony_ci    pub fn set_cookie_verify_cb<F>(&mut self, callback: F)
154892f3ab15Sopenharmony_ci    where
154992f3ab15Sopenharmony_ci        F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
155092f3ab15Sopenharmony_ci    {
155192f3ab15Sopenharmony_ci        unsafe {
155292f3ab15Sopenharmony_ci            self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
155392f3ab15Sopenharmony_ci            ffi::SSL_CTX_set_cookie_verify_cb(self.as_ptr(), Some(raw_cookie_verify::<F>));
155492f3ab15Sopenharmony_ci        }
155592f3ab15Sopenharmony_ci    }
155692f3ab15Sopenharmony_ci
155792f3ab15Sopenharmony_ci    /// Sets the extra data at the specified index.
155892f3ab15Sopenharmony_ci    ///
155992f3ab15Sopenharmony_ci    /// This can be used to provide data to callbacks registered with the context. Use the
156092f3ab15Sopenharmony_ci    /// `SslContext::new_ex_index` method to create an `Index`.
156192f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_set_ex_data)]
156292f3ab15Sopenharmony_ci    pub fn set_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) {
156392f3ab15Sopenharmony_ci        self.set_ex_data_inner(index, data);
156492f3ab15Sopenharmony_ci    }
156592f3ab15Sopenharmony_ci
156692f3ab15Sopenharmony_ci    fn set_ex_data_inner<T>(&mut self, index: Index<SslContext, T>, data: T) -> *mut c_void {
156792f3ab15Sopenharmony_ci        unsafe {
156892f3ab15Sopenharmony_ci            let data = Box::into_raw(Box::new(data)) as *mut c_void;
156992f3ab15Sopenharmony_ci            ffi::SSL_CTX_set_ex_data(self.as_ptr(), index.as_raw(), data);
157092f3ab15Sopenharmony_ci            data
157192f3ab15Sopenharmony_ci        }
157292f3ab15Sopenharmony_ci    }
157392f3ab15Sopenharmony_ci
157492f3ab15Sopenharmony_ci    /// Adds a custom extension for a TLS/DTLS client or server for all supported protocol versions.
157592f3ab15Sopenharmony_ci    ///
157692f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.1.1 or newer.
157792f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_add_custom_ext)]
157892f3ab15Sopenharmony_ci    #[cfg(ossl111)]
157992f3ab15Sopenharmony_ci    pub fn add_custom_ext<AddFn, ParseFn, T>(
158092f3ab15Sopenharmony_ci        &mut self,
158192f3ab15Sopenharmony_ci        ext_type: u16,
158292f3ab15Sopenharmony_ci        context: ExtensionContext,
158392f3ab15Sopenharmony_ci        add_cb: AddFn,
158492f3ab15Sopenharmony_ci        parse_cb: ParseFn,
158592f3ab15Sopenharmony_ci    ) -> Result<(), ErrorStack>
158692f3ab15Sopenharmony_ci    where
158792f3ab15Sopenharmony_ci        AddFn: Fn(
158892f3ab15Sopenharmony_ci                &mut SslRef,
158992f3ab15Sopenharmony_ci                ExtensionContext,
159092f3ab15Sopenharmony_ci                Option<(usize, &X509Ref)>,
159192f3ab15Sopenharmony_ci            ) -> Result<Option<T>, SslAlert>
159292f3ab15Sopenharmony_ci            + 'static
159392f3ab15Sopenharmony_ci            + Sync
159492f3ab15Sopenharmony_ci            + Send,
159592f3ab15Sopenharmony_ci        T: AsRef<[u8]> + 'static + Sync + Send,
159692f3ab15Sopenharmony_ci        ParseFn: Fn(
159792f3ab15Sopenharmony_ci                &mut SslRef,
159892f3ab15Sopenharmony_ci                ExtensionContext,
159992f3ab15Sopenharmony_ci                &[u8],
160092f3ab15Sopenharmony_ci                Option<(usize, &X509Ref)>,
160192f3ab15Sopenharmony_ci            ) -> Result<(), SslAlert>
160292f3ab15Sopenharmony_ci            + 'static
160392f3ab15Sopenharmony_ci            + Sync
160492f3ab15Sopenharmony_ci            + Send,
160592f3ab15Sopenharmony_ci    {
160692f3ab15Sopenharmony_ci        let ret = unsafe {
160792f3ab15Sopenharmony_ci            self.set_ex_data(SslContext::cached_ex_index::<AddFn>(), add_cb);
160892f3ab15Sopenharmony_ci            self.set_ex_data(SslContext::cached_ex_index::<ParseFn>(), parse_cb);
160992f3ab15Sopenharmony_ci
161092f3ab15Sopenharmony_ci            ffi::SSL_CTX_add_custom_ext(
161192f3ab15Sopenharmony_ci                self.as_ptr(),
161292f3ab15Sopenharmony_ci                ext_type as c_uint,
161392f3ab15Sopenharmony_ci                context.bits(),
161492f3ab15Sopenharmony_ci                Some(raw_custom_ext_add::<AddFn, T>),
161592f3ab15Sopenharmony_ci                Some(raw_custom_ext_free::<T>),
161692f3ab15Sopenharmony_ci                ptr::null_mut(),
161792f3ab15Sopenharmony_ci                Some(raw_custom_ext_parse::<ParseFn>),
161892f3ab15Sopenharmony_ci                ptr::null_mut(),
161992f3ab15Sopenharmony_ci            )
162092f3ab15Sopenharmony_ci        };
162192f3ab15Sopenharmony_ci        if ret == 1 {
162292f3ab15Sopenharmony_ci            Ok(())
162392f3ab15Sopenharmony_ci        } else {
162492f3ab15Sopenharmony_ci            Err(ErrorStack::get())
162592f3ab15Sopenharmony_ci        }
162692f3ab15Sopenharmony_ci    }
162792f3ab15Sopenharmony_ci
162892f3ab15Sopenharmony_ci    /// Sets the maximum amount of early data that will be accepted on incoming connections.
162992f3ab15Sopenharmony_ci    ///
163092f3ab15Sopenharmony_ci    /// Defaults to 0.
163192f3ab15Sopenharmony_ci    ///
163292f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer.
163392f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_set_max_early_data)]
163492f3ab15Sopenharmony_ci    #[cfg(any(ossl111, libressl340))]
163592f3ab15Sopenharmony_ci    pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
163692f3ab15Sopenharmony_ci        if unsafe { ffi::SSL_CTX_set_max_early_data(self.as_ptr(), bytes) } == 1 {
163792f3ab15Sopenharmony_ci            Ok(())
163892f3ab15Sopenharmony_ci        } else {
163992f3ab15Sopenharmony_ci            Err(ErrorStack::get())
164092f3ab15Sopenharmony_ci        }
164192f3ab15Sopenharmony_ci    }
164292f3ab15Sopenharmony_ci
164392f3ab15Sopenharmony_ci    /// Sets a callback which will be invoked just after the client's hello message is received.
164492f3ab15Sopenharmony_ci    ///
164592f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.1.1 or newer.
164692f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_set_client_hello_cb)]
164792f3ab15Sopenharmony_ci    #[cfg(ossl111)]
164892f3ab15Sopenharmony_ci    pub fn set_client_hello_callback<F>(&mut self, callback: F)
164992f3ab15Sopenharmony_ci    where
165092f3ab15Sopenharmony_ci        F: Fn(&mut SslRef, &mut SslAlert) -> Result<ClientHelloResponse, ErrorStack>
165192f3ab15Sopenharmony_ci            + 'static
165292f3ab15Sopenharmony_ci            + Sync
165392f3ab15Sopenharmony_ci            + Send,
165492f3ab15Sopenharmony_ci    {
165592f3ab15Sopenharmony_ci        unsafe {
165692f3ab15Sopenharmony_ci            let ptr = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
165792f3ab15Sopenharmony_ci            ffi::SSL_CTX_set_client_hello_cb(
165892f3ab15Sopenharmony_ci                self.as_ptr(),
165992f3ab15Sopenharmony_ci                Some(callbacks::raw_client_hello::<F>),
166092f3ab15Sopenharmony_ci                ptr,
166192f3ab15Sopenharmony_ci            );
166292f3ab15Sopenharmony_ci        }
166392f3ab15Sopenharmony_ci    }
166492f3ab15Sopenharmony_ci
166592f3ab15Sopenharmony_ci    /// Sets the context's session cache size limit, returning the previous limit.
166692f3ab15Sopenharmony_ci    ///
166792f3ab15Sopenharmony_ci    /// A value of 0 means that the cache size is unbounded.
166892f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_sess_set_cache_size)]
166992f3ab15Sopenharmony_ci    #[allow(clippy::useless_conversion)]
167092f3ab15Sopenharmony_ci    pub fn set_session_cache_size(&mut self, size: i32) -> i64 {
167192f3ab15Sopenharmony_ci        unsafe {
167292f3ab15Sopenharmony_ci            ffi::SSL_CTX_sess_set_cache_size(self.as_ptr(), size as SslCacheSize) as SslCacheTy
167392f3ab15Sopenharmony_ci        }
167492f3ab15Sopenharmony_ci    }
167592f3ab15Sopenharmony_ci
167692f3ab15Sopenharmony_ci    /// Sets the context's supported signature algorithms.
167792f3ab15Sopenharmony_ci    ///
167892f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.0.2 or newer.
167992f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_set1_sigalgs_list)]
168092f3ab15Sopenharmony_ci    #[cfg(ossl102)]
168192f3ab15Sopenharmony_ci    pub fn set_sigalgs_list(&mut self, sigalgs: &str) -> Result<(), ErrorStack> {
168292f3ab15Sopenharmony_ci        let sigalgs = CString::new(sigalgs).unwrap();
168392f3ab15Sopenharmony_ci        unsafe {
168492f3ab15Sopenharmony_ci            cvt(ffi::SSL_CTX_set1_sigalgs_list(self.as_ptr(), sigalgs.as_ptr()) as c_int)
168592f3ab15Sopenharmony_ci                .map(|_| ())
168692f3ab15Sopenharmony_ci        }
168792f3ab15Sopenharmony_ci    }
168892f3ab15Sopenharmony_ci
168992f3ab15Sopenharmony_ci    /// Sets the context's supported elliptic curve groups.
169092f3ab15Sopenharmony_ci    ///
169192f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.1.1 or LibreSSL 2.5.1 or newer.
169292f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_set1_groups_list)]
169392f3ab15Sopenharmony_ci    #[cfg(any(ossl111, libressl251))]
169492f3ab15Sopenharmony_ci    pub fn set_groups_list(&mut self, groups: &str) -> Result<(), ErrorStack> {
169592f3ab15Sopenharmony_ci        let groups = CString::new(groups).unwrap();
169692f3ab15Sopenharmony_ci        unsafe {
169792f3ab15Sopenharmony_ci            cvt(ffi::SSL_CTX_set1_groups_list(self.as_ptr(), groups.as_ptr()) as c_int).map(|_| ())
169892f3ab15Sopenharmony_ci        }
169992f3ab15Sopenharmony_ci    }
170092f3ab15Sopenharmony_ci
170192f3ab15Sopenharmony_ci    /// Sets the number of TLS 1.3 session tickets that will be sent to a client after a full
170292f3ab15Sopenharmony_ci    /// handshake.
170392f3ab15Sopenharmony_ci    ///
170492f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.1.1 or newer.
170592f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_set_num_tickets)]
170692f3ab15Sopenharmony_ci    #[cfg(ossl111)]
170792f3ab15Sopenharmony_ci    pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
170892f3ab15Sopenharmony_ci        unsafe { cvt(ffi::SSL_CTX_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
170992f3ab15Sopenharmony_ci    }
171092f3ab15Sopenharmony_ci
171192f3ab15Sopenharmony_ci    /// Consumes the builder, returning a new `SslContext`.
171292f3ab15Sopenharmony_ci    pub fn build(self) -> SslContext {
171392f3ab15Sopenharmony_ci        self.0
171492f3ab15Sopenharmony_ci    }
171592f3ab15Sopenharmony_ci}
171692f3ab15Sopenharmony_ci
171792f3ab15Sopenharmony_ciforeign_type_and_impl_send_sync! {
171892f3ab15Sopenharmony_ci    type CType = ffi::SSL_CTX;
171992f3ab15Sopenharmony_ci    fn drop = ffi::SSL_CTX_free;
172092f3ab15Sopenharmony_ci
172192f3ab15Sopenharmony_ci    /// A context object for TLS streams.
172292f3ab15Sopenharmony_ci    ///
172392f3ab15Sopenharmony_ci    /// Applications commonly configure a single `SslContext` that is shared by all of its
172492f3ab15Sopenharmony_ci    /// `SslStreams`.
172592f3ab15Sopenharmony_ci    pub struct SslContext;
172692f3ab15Sopenharmony_ci
172792f3ab15Sopenharmony_ci    /// Reference to [`SslContext`]
172892f3ab15Sopenharmony_ci    ///
172992f3ab15Sopenharmony_ci    /// [`SslContext`]: struct.SslContext.html
173092f3ab15Sopenharmony_ci    pub struct SslContextRef;
173192f3ab15Sopenharmony_ci}
173292f3ab15Sopenharmony_ci
173392f3ab15Sopenharmony_ciimpl Clone for SslContext {
173492f3ab15Sopenharmony_ci    fn clone(&self) -> Self {
173592f3ab15Sopenharmony_ci        (**self).to_owned()
173692f3ab15Sopenharmony_ci    }
173792f3ab15Sopenharmony_ci}
173892f3ab15Sopenharmony_ci
173992f3ab15Sopenharmony_ciimpl ToOwned for SslContextRef {
174092f3ab15Sopenharmony_ci    type Owned = SslContext;
174192f3ab15Sopenharmony_ci
174292f3ab15Sopenharmony_ci    fn to_owned(&self) -> Self::Owned {
174392f3ab15Sopenharmony_ci        unsafe {
174492f3ab15Sopenharmony_ci            SSL_CTX_up_ref(self.as_ptr());
174592f3ab15Sopenharmony_ci            SslContext::from_ptr(self.as_ptr())
174692f3ab15Sopenharmony_ci        }
174792f3ab15Sopenharmony_ci    }
174892f3ab15Sopenharmony_ci}
174992f3ab15Sopenharmony_ci
175092f3ab15Sopenharmony_ci// TODO: add useful info here
175192f3ab15Sopenharmony_ciimpl fmt::Debug for SslContext {
175292f3ab15Sopenharmony_ci    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
175392f3ab15Sopenharmony_ci        write!(fmt, "SslContext")
175492f3ab15Sopenharmony_ci    }
175592f3ab15Sopenharmony_ci}
175692f3ab15Sopenharmony_ci
175792f3ab15Sopenharmony_ciimpl SslContext {
175892f3ab15Sopenharmony_ci    /// Creates a new builder object for an `SslContext`.
175992f3ab15Sopenharmony_ci    pub fn builder(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
176092f3ab15Sopenharmony_ci        SslContextBuilder::new(method)
176192f3ab15Sopenharmony_ci    }
176292f3ab15Sopenharmony_ci
176392f3ab15Sopenharmony_ci    /// Returns a new extra data index.
176492f3ab15Sopenharmony_ci    ///
176592f3ab15Sopenharmony_ci    /// Each invocation of this function is guaranteed to return a distinct index. These can be used
176692f3ab15Sopenharmony_ci    /// to store data in the context that can be retrieved later by callbacks, for example.
176792f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_get_ex_new_index)]
176892f3ab15Sopenharmony_ci    pub fn new_ex_index<T>() -> Result<Index<SslContext, T>, ErrorStack>
176992f3ab15Sopenharmony_ci    where
177092f3ab15Sopenharmony_ci        T: 'static + Sync + Send,
177192f3ab15Sopenharmony_ci    {
177292f3ab15Sopenharmony_ci        unsafe {
177392f3ab15Sopenharmony_ci            ffi::init();
177492f3ab15Sopenharmony_ci            #[cfg(boringssl)]
177592f3ab15Sopenharmony_ci            let idx = cvt_n(get_new_idx(Some(free_data_box::<T>)))?;
177692f3ab15Sopenharmony_ci            #[cfg(not(boringssl))]
177792f3ab15Sopenharmony_ci            let idx = cvt_n(get_new_idx(free_data_box::<T>))?;
177892f3ab15Sopenharmony_ci            Ok(Index::from_raw(idx))
177992f3ab15Sopenharmony_ci        }
178092f3ab15Sopenharmony_ci    }
178192f3ab15Sopenharmony_ci
178292f3ab15Sopenharmony_ci    // FIXME should return a result?
178392f3ab15Sopenharmony_ci    fn cached_ex_index<T>() -> Index<SslContext, T>
178492f3ab15Sopenharmony_ci    where
178592f3ab15Sopenharmony_ci        T: 'static + Sync + Send,
178692f3ab15Sopenharmony_ci    {
178792f3ab15Sopenharmony_ci        unsafe {
178892f3ab15Sopenharmony_ci            let idx = *INDEXES
178992f3ab15Sopenharmony_ci                .lock()
179092f3ab15Sopenharmony_ci                .unwrap_or_else(|e| e.into_inner())
179192f3ab15Sopenharmony_ci                .entry(TypeId::of::<T>())
179292f3ab15Sopenharmony_ci                .or_insert_with(|| SslContext::new_ex_index::<T>().unwrap().as_raw());
179392f3ab15Sopenharmony_ci            Index::from_raw(idx)
179492f3ab15Sopenharmony_ci        }
179592f3ab15Sopenharmony_ci    }
179692f3ab15Sopenharmony_ci}
179792f3ab15Sopenharmony_ci
179892f3ab15Sopenharmony_ciimpl SslContextRef {
179992f3ab15Sopenharmony_ci    /// Returns the certificate associated with this `SslContext`, if present.
180092f3ab15Sopenharmony_ci    ///
180192f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.0.2 or LibreSSL 2.7.0 or newer.
180292f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_get0_certificate)]
180392f3ab15Sopenharmony_ci    #[cfg(any(ossl102, libressl270))]
180492f3ab15Sopenharmony_ci    pub fn certificate(&self) -> Option<&X509Ref> {
180592f3ab15Sopenharmony_ci        unsafe {
180692f3ab15Sopenharmony_ci            let ptr = ffi::SSL_CTX_get0_certificate(self.as_ptr());
180792f3ab15Sopenharmony_ci            X509Ref::from_const_ptr_opt(ptr)
180892f3ab15Sopenharmony_ci        }
180992f3ab15Sopenharmony_ci    }
181092f3ab15Sopenharmony_ci
181192f3ab15Sopenharmony_ci    /// Returns the private key associated with this `SslContext`, if present.
181292f3ab15Sopenharmony_ci    ///
181392f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.0.2 or LibreSSL 3.4.0 or newer.
181492f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_get0_privatekey)]
181592f3ab15Sopenharmony_ci    #[cfg(any(ossl102, libressl340))]
181692f3ab15Sopenharmony_ci    pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
181792f3ab15Sopenharmony_ci        unsafe {
181892f3ab15Sopenharmony_ci            let ptr = ffi::SSL_CTX_get0_privatekey(self.as_ptr());
181992f3ab15Sopenharmony_ci            PKeyRef::from_const_ptr_opt(ptr)
182092f3ab15Sopenharmony_ci        }
182192f3ab15Sopenharmony_ci    }
182292f3ab15Sopenharmony_ci
182392f3ab15Sopenharmony_ci    /// Returns a shared reference to the certificate store used for verification.
182492f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_get_cert_store)]
182592f3ab15Sopenharmony_ci    pub fn cert_store(&self) -> &X509StoreRef {
182692f3ab15Sopenharmony_ci        unsafe { X509StoreRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
182792f3ab15Sopenharmony_ci    }
182892f3ab15Sopenharmony_ci
182992f3ab15Sopenharmony_ci    /// Returns a shared reference to the stack of certificates making up the chain from the leaf.
183092f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_get_extra_chain_certs)]
183192f3ab15Sopenharmony_ci    pub fn extra_chain_certs(&self) -> &StackRef<X509> {
183292f3ab15Sopenharmony_ci        unsafe {
183392f3ab15Sopenharmony_ci            let mut chain = ptr::null_mut();
183492f3ab15Sopenharmony_ci            ffi::SSL_CTX_get_extra_chain_certs(self.as_ptr(), &mut chain);
183592f3ab15Sopenharmony_ci            StackRef::from_const_ptr_opt(chain).expect("extra chain certs must not be null")
183692f3ab15Sopenharmony_ci        }
183792f3ab15Sopenharmony_ci    }
183892f3ab15Sopenharmony_ci
183992f3ab15Sopenharmony_ci    /// Returns a reference to the extra data at the specified index.
184092f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_get_ex_data)]
184192f3ab15Sopenharmony_ci    pub fn ex_data<T>(&self, index: Index<SslContext, T>) -> Option<&T> {
184292f3ab15Sopenharmony_ci        unsafe {
184392f3ab15Sopenharmony_ci            let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
184492f3ab15Sopenharmony_ci            if data.is_null() {
184592f3ab15Sopenharmony_ci                None
184692f3ab15Sopenharmony_ci            } else {
184792f3ab15Sopenharmony_ci                Some(&*(data as *const T))
184892f3ab15Sopenharmony_ci            }
184992f3ab15Sopenharmony_ci        }
185092f3ab15Sopenharmony_ci    }
185192f3ab15Sopenharmony_ci
185292f3ab15Sopenharmony_ci    /// Gets the maximum amount of early data that will be accepted on incoming connections.
185392f3ab15Sopenharmony_ci    ///
185492f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer.
185592f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_get_max_early_data)]
185692f3ab15Sopenharmony_ci    #[cfg(any(ossl111, libressl340))]
185792f3ab15Sopenharmony_ci    pub fn max_early_data(&self) -> u32 {
185892f3ab15Sopenharmony_ci        unsafe { ffi::SSL_CTX_get_max_early_data(self.as_ptr()) }
185992f3ab15Sopenharmony_ci    }
186092f3ab15Sopenharmony_ci
186192f3ab15Sopenharmony_ci    /// Adds a session to the context's cache.
186292f3ab15Sopenharmony_ci    ///
186392f3ab15Sopenharmony_ci    /// Returns `true` if the session was successfully added to the cache, and `false` if it was already present.
186492f3ab15Sopenharmony_ci    ///
186592f3ab15Sopenharmony_ci    /// # Safety
186692f3ab15Sopenharmony_ci    ///
186792f3ab15Sopenharmony_ci    /// The caller of this method is responsible for ensuring that the session has never been used with another
186892f3ab15Sopenharmony_ci    /// `SslContext` than this one.
186992f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_add_session)]
187092f3ab15Sopenharmony_ci    pub unsafe fn add_session(&self, session: &SslSessionRef) -> bool {
187192f3ab15Sopenharmony_ci        ffi::SSL_CTX_add_session(self.as_ptr(), session.as_ptr()) != 0
187292f3ab15Sopenharmony_ci    }
187392f3ab15Sopenharmony_ci
187492f3ab15Sopenharmony_ci    /// Removes a session from the context's cache and marks it as non-resumable.
187592f3ab15Sopenharmony_ci    ///
187692f3ab15Sopenharmony_ci    /// Returns `true` if the session was successfully found and removed, and `false` otherwise.
187792f3ab15Sopenharmony_ci    ///
187892f3ab15Sopenharmony_ci    /// # Safety
187992f3ab15Sopenharmony_ci    ///
188092f3ab15Sopenharmony_ci    /// The caller of this method is responsible for ensuring that the session has never been used with another
188192f3ab15Sopenharmony_ci    /// `SslContext` than this one.
188292f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_remove_session)]
188392f3ab15Sopenharmony_ci    pub unsafe fn remove_session(&self, session: &SslSessionRef) -> bool {
188492f3ab15Sopenharmony_ci        ffi::SSL_CTX_remove_session(self.as_ptr(), session.as_ptr()) != 0
188592f3ab15Sopenharmony_ci    }
188692f3ab15Sopenharmony_ci
188792f3ab15Sopenharmony_ci    /// Returns the context's session cache size limit.
188892f3ab15Sopenharmony_ci    ///
188992f3ab15Sopenharmony_ci    /// A value of 0 means that the cache size is unbounded.
189092f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_sess_get_cache_size)]
189192f3ab15Sopenharmony_ci    #[allow(clippy::unnecessary_cast)]
189292f3ab15Sopenharmony_ci    pub fn session_cache_size(&self) -> i64 {
189392f3ab15Sopenharmony_ci        unsafe { ffi::SSL_CTX_sess_get_cache_size(self.as_ptr()) as i64 }
189492f3ab15Sopenharmony_ci    }
189592f3ab15Sopenharmony_ci
189692f3ab15Sopenharmony_ci    /// Returns the verify mode that was set on this context from [`SslContextBuilder::set_verify`].
189792f3ab15Sopenharmony_ci    ///
189892f3ab15Sopenharmony_ci    /// [`SslContextBuilder::set_verify`]: struct.SslContextBuilder.html#method.set_verify
189992f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_get_verify_mode)]
190092f3ab15Sopenharmony_ci    pub fn verify_mode(&self) -> SslVerifyMode {
190192f3ab15Sopenharmony_ci        let mode = unsafe { ffi::SSL_CTX_get_verify_mode(self.as_ptr()) };
190292f3ab15Sopenharmony_ci        SslVerifyMode::from_bits(mode).expect("SSL_CTX_get_verify_mode returned invalid mode")
190392f3ab15Sopenharmony_ci    }
190492f3ab15Sopenharmony_ci
190592f3ab15Sopenharmony_ci    /// Gets the number of TLS 1.3 session tickets that will be sent to a client after a full
190692f3ab15Sopenharmony_ci    /// handshake.
190792f3ab15Sopenharmony_ci    ///
190892f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.1.1 or newer.
190992f3ab15Sopenharmony_ci    #[corresponds(SSL_CTX_get_num_tickets)]
191092f3ab15Sopenharmony_ci    #[cfg(ossl111)]
191192f3ab15Sopenharmony_ci    pub fn num_tickets(&self) -> usize {
191292f3ab15Sopenharmony_ci        unsafe { ffi::SSL_CTX_get_num_tickets(self.as_ptr()) }
191392f3ab15Sopenharmony_ci    }
191492f3ab15Sopenharmony_ci}
191592f3ab15Sopenharmony_ci
191692f3ab15Sopenharmony_ci/// Information about the state of a cipher.
191792f3ab15Sopenharmony_cipub struct CipherBits {
191892f3ab15Sopenharmony_ci    /// The number of secret bits used for the cipher.
191992f3ab15Sopenharmony_ci    pub secret: i32,
192092f3ab15Sopenharmony_ci
192192f3ab15Sopenharmony_ci    /// The number of bits processed by the chosen algorithm.
192292f3ab15Sopenharmony_ci    pub algorithm: i32,
192392f3ab15Sopenharmony_ci}
192492f3ab15Sopenharmony_ci
192592f3ab15Sopenharmony_ci/// Information about a cipher.
192692f3ab15Sopenharmony_cipub struct SslCipher(*mut ffi::SSL_CIPHER);
192792f3ab15Sopenharmony_ci
192892f3ab15Sopenharmony_ciimpl ForeignType for SslCipher {
192992f3ab15Sopenharmony_ci    type CType = ffi::SSL_CIPHER;
193092f3ab15Sopenharmony_ci    type Ref = SslCipherRef;
193192f3ab15Sopenharmony_ci
193292f3ab15Sopenharmony_ci    #[inline]
193392f3ab15Sopenharmony_ci    unsafe fn from_ptr(ptr: *mut ffi::SSL_CIPHER) -> SslCipher {
193492f3ab15Sopenharmony_ci        SslCipher(ptr)
193592f3ab15Sopenharmony_ci    }
193692f3ab15Sopenharmony_ci
193792f3ab15Sopenharmony_ci    #[inline]
193892f3ab15Sopenharmony_ci    fn as_ptr(&self) -> *mut ffi::SSL_CIPHER {
193992f3ab15Sopenharmony_ci        self.0
194092f3ab15Sopenharmony_ci    }
194192f3ab15Sopenharmony_ci}
194292f3ab15Sopenharmony_ci
194392f3ab15Sopenharmony_ciimpl Stackable for SslCipher {
194492f3ab15Sopenharmony_ci    type StackType = ffi::stack_st_SSL_CIPHER;
194592f3ab15Sopenharmony_ci}
194692f3ab15Sopenharmony_ci
194792f3ab15Sopenharmony_ciimpl Deref for SslCipher {
194892f3ab15Sopenharmony_ci    type Target = SslCipherRef;
194992f3ab15Sopenharmony_ci
195092f3ab15Sopenharmony_ci    fn deref(&self) -> &SslCipherRef {
195192f3ab15Sopenharmony_ci        unsafe { SslCipherRef::from_ptr(self.0) }
195292f3ab15Sopenharmony_ci    }
195392f3ab15Sopenharmony_ci}
195492f3ab15Sopenharmony_ci
195592f3ab15Sopenharmony_ciimpl DerefMut for SslCipher {
195692f3ab15Sopenharmony_ci    fn deref_mut(&mut self) -> &mut SslCipherRef {
195792f3ab15Sopenharmony_ci        unsafe { SslCipherRef::from_ptr_mut(self.0) }
195892f3ab15Sopenharmony_ci    }
195992f3ab15Sopenharmony_ci}
196092f3ab15Sopenharmony_ci
196192f3ab15Sopenharmony_ci/// Reference to an [`SslCipher`].
196292f3ab15Sopenharmony_ci///
196392f3ab15Sopenharmony_ci/// [`SslCipher`]: struct.SslCipher.html
196492f3ab15Sopenharmony_cipub struct SslCipherRef(Opaque);
196592f3ab15Sopenharmony_ci
196692f3ab15Sopenharmony_ciimpl ForeignTypeRef for SslCipherRef {
196792f3ab15Sopenharmony_ci    type CType = ffi::SSL_CIPHER;
196892f3ab15Sopenharmony_ci}
196992f3ab15Sopenharmony_ci
197092f3ab15Sopenharmony_ciimpl SslCipherRef {
197192f3ab15Sopenharmony_ci    /// Returns the name of the cipher.
197292f3ab15Sopenharmony_ci    #[corresponds(SSL_CIPHER_get_name)]
197392f3ab15Sopenharmony_ci    pub fn name(&self) -> &'static str {
197492f3ab15Sopenharmony_ci        unsafe {
197592f3ab15Sopenharmony_ci            let ptr = ffi::SSL_CIPHER_get_name(self.as_ptr());
197692f3ab15Sopenharmony_ci            CStr::from_ptr(ptr).to_str().unwrap()
197792f3ab15Sopenharmony_ci        }
197892f3ab15Sopenharmony_ci    }
197992f3ab15Sopenharmony_ci
198092f3ab15Sopenharmony_ci    /// Returns the RFC-standard name of the cipher, if one exists.
198192f3ab15Sopenharmony_ci    ///
198292f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.1.1 or newer.
198392f3ab15Sopenharmony_ci    #[corresponds(SSL_CIPHER_standard_name)]
198492f3ab15Sopenharmony_ci    #[cfg(ossl111)]
198592f3ab15Sopenharmony_ci    pub fn standard_name(&self) -> Option<&'static str> {
198692f3ab15Sopenharmony_ci        unsafe {
198792f3ab15Sopenharmony_ci            let ptr = ffi::SSL_CIPHER_standard_name(self.as_ptr());
198892f3ab15Sopenharmony_ci            if ptr.is_null() {
198992f3ab15Sopenharmony_ci                None
199092f3ab15Sopenharmony_ci            } else {
199192f3ab15Sopenharmony_ci                Some(CStr::from_ptr(ptr).to_str().unwrap())
199292f3ab15Sopenharmony_ci            }
199392f3ab15Sopenharmony_ci        }
199492f3ab15Sopenharmony_ci    }
199592f3ab15Sopenharmony_ci
199692f3ab15Sopenharmony_ci    /// Returns the SSL/TLS protocol version that first defined the cipher.
199792f3ab15Sopenharmony_ci    #[corresponds(SSL_CIPHER_get_version)]
199892f3ab15Sopenharmony_ci    pub fn version(&self) -> &'static str {
199992f3ab15Sopenharmony_ci        let version = unsafe {
200092f3ab15Sopenharmony_ci            let ptr = ffi::SSL_CIPHER_get_version(self.as_ptr());
200192f3ab15Sopenharmony_ci            CStr::from_ptr(ptr as *const _)
200292f3ab15Sopenharmony_ci        };
200392f3ab15Sopenharmony_ci
200492f3ab15Sopenharmony_ci        str::from_utf8(version.to_bytes()).unwrap()
200592f3ab15Sopenharmony_ci    }
200692f3ab15Sopenharmony_ci
200792f3ab15Sopenharmony_ci    /// Returns the number of bits used for the cipher.
200892f3ab15Sopenharmony_ci    #[corresponds(SSL_CIPHER_get_bits)]
200992f3ab15Sopenharmony_ci    #[allow(clippy::useless_conversion)]
201092f3ab15Sopenharmony_ci    pub fn bits(&self) -> CipherBits {
201192f3ab15Sopenharmony_ci        unsafe {
201292f3ab15Sopenharmony_ci            let mut algo_bits = 0;
201392f3ab15Sopenharmony_ci            let secret_bits = ffi::SSL_CIPHER_get_bits(self.as_ptr(), &mut algo_bits);
201492f3ab15Sopenharmony_ci            CipherBits {
201592f3ab15Sopenharmony_ci                secret: secret_bits.into(),
201692f3ab15Sopenharmony_ci                algorithm: algo_bits.into(),
201792f3ab15Sopenharmony_ci            }
201892f3ab15Sopenharmony_ci        }
201992f3ab15Sopenharmony_ci    }
202092f3ab15Sopenharmony_ci
202192f3ab15Sopenharmony_ci    /// Returns a textual description of the cipher.
202292f3ab15Sopenharmony_ci    #[corresponds(SSL_CIPHER_description)]
202392f3ab15Sopenharmony_ci    pub fn description(&self) -> String {
202492f3ab15Sopenharmony_ci        unsafe {
202592f3ab15Sopenharmony_ci            // SSL_CIPHER_description requires a buffer of at least 128 bytes.
202692f3ab15Sopenharmony_ci            let mut buf = [0; 128];
202792f3ab15Sopenharmony_ci            let ptr = ffi::SSL_CIPHER_description(self.as_ptr(), buf.as_mut_ptr(), 128);
202892f3ab15Sopenharmony_ci            String::from_utf8(CStr::from_ptr(ptr as *const _).to_bytes().to_vec()).unwrap()
202992f3ab15Sopenharmony_ci        }
203092f3ab15Sopenharmony_ci    }
203192f3ab15Sopenharmony_ci
203292f3ab15Sopenharmony_ci    /// Returns the handshake digest of the cipher.
203392f3ab15Sopenharmony_ci    ///
203492f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.1.1 or newer.
203592f3ab15Sopenharmony_ci    #[corresponds(SSL_CIPHER_get_handshake_digest)]
203692f3ab15Sopenharmony_ci    #[cfg(ossl111)]
203792f3ab15Sopenharmony_ci    pub fn handshake_digest(&self) -> Option<MessageDigest> {
203892f3ab15Sopenharmony_ci        unsafe {
203992f3ab15Sopenharmony_ci            let ptr = ffi::SSL_CIPHER_get_handshake_digest(self.as_ptr());
204092f3ab15Sopenharmony_ci            if ptr.is_null() {
204192f3ab15Sopenharmony_ci                None
204292f3ab15Sopenharmony_ci            } else {
204392f3ab15Sopenharmony_ci                Some(MessageDigest::from_ptr(ptr))
204492f3ab15Sopenharmony_ci            }
204592f3ab15Sopenharmony_ci        }
204692f3ab15Sopenharmony_ci    }
204792f3ab15Sopenharmony_ci
204892f3ab15Sopenharmony_ci    /// Returns the NID corresponding to the cipher.
204992f3ab15Sopenharmony_ci    ///
205092f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.1.0 or LibreSSL 2.7.0 or newer.
205192f3ab15Sopenharmony_ci    #[corresponds(SSL_CIPHER_get_cipher_nid)]
205292f3ab15Sopenharmony_ci    #[cfg(any(ossl110, libressl270))]
205392f3ab15Sopenharmony_ci    pub fn cipher_nid(&self) -> Option<Nid> {
205492f3ab15Sopenharmony_ci        let n = unsafe { ffi::SSL_CIPHER_get_cipher_nid(self.as_ptr()) };
205592f3ab15Sopenharmony_ci        if n == 0 {
205692f3ab15Sopenharmony_ci            None
205792f3ab15Sopenharmony_ci        } else {
205892f3ab15Sopenharmony_ci            Some(Nid::from_raw(n))
205992f3ab15Sopenharmony_ci        }
206092f3ab15Sopenharmony_ci    }
206192f3ab15Sopenharmony_ci}
206292f3ab15Sopenharmony_ci
206392f3ab15Sopenharmony_ciimpl fmt::Debug for SslCipherRef {
206492f3ab15Sopenharmony_ci    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
206592f3ab15Sopenharmony_ci        write!(fmt, "{}", self.name())
206692f3ab15Sopenharmony_ci    }
206792f3ab15Sopenharmony_ci}
206892f3ab15Sopenharmony_ci
206992f3ab15Sopenharmony_ci/// A stack of selected ciphers, and a stack of selected signalling cipher suites
207092f3ab15Sopenharmony_ci#[derive(Debug)]
207192f3ab15Sopenharmony_cipub struct CipherLists {
207292f3ab15Sopenharmony_ci    pub suites: Stack<SslCipher>,
207392f3ab15Sopenharmony_ci    pub signalling_suites: Stack<SslCipher>,
207492f3ab15Sopenharmony_ci}
207592f3ab15Sopenharmony_ci
207692f3ab15Sopenharmony_ciforeign_type_and_impl_send_sync! {
207792f3ab15Sopenharmony_ci    type CType = ffi::SSL_SESSION;
207892f3ab15Sopenharmony_ci    fn drop = ffi::SSL_SESSION_free;
207992f3ab15Sopenharmony_ci
208092f3ab15Sopenharmony_ci    /// An encoded SSL session.
208192f3ab15Sopenharmony_ci    ///
208292f3ab15Sopenharmony_ci    /// These can be cached to share sessions across connections.
208392f3ab15Sopenharmony_ci    pub struct SslSession;
208492f3ab15Sopenharmony_ci
208592f3ab15Sopenharmony_ci    /// Reference to [`SslSession`].
208692f3ab15Sopenharmony_ci    ///
208792f3ab15Sopenharmony_ci    /// [`SslSession`]: struct.SslSession.html
208892f3ab15Sopenharmony_ci    pub struct SslSessionRef;
208992f3ab15Sopenharmony_ci}
209092f3ab15Sopenharmony_ci
209192f3ab15Sopenharmony_ciimpl Clone for SslSession {
209292f3ab15Sopenharmony_ci    fn clone(&self) -> SslSession {
209392f3ab15Sopenharmony_ci        SslSessionRef::to_owned(self)
209492f3ab15Sopenharmony_ci    }
209592f3ab15Sopenharmony_ci}
209692f3ab15Sopenharmony_ci
209792f3ab15Sopenharmony_ciimpl SslSession {
209892f3ab15Sopenharmony_ci    from_der! {
209992f3ab15Sopenharmony_ci        /// Deserializes a DER-encoded session structure.
210092f3ab15Sopenharmony_ci        #[corresponds(d2i_SSL_SESSION)]
210192f3ab15Sopenharmony_ci        from_der,
210292f3ab15Sopenharmony_ci        SslSession,
210392f3ab15Sopenharmony_ci        ffi::d2i_SSL_SESSION
210492f3ab15Sopenharmony_ci    }
210592f3ab15Sopenharmony_ci}
210692f3ab15Sopenharmony_ci
210792f3ab15Sopenharmony_ciimpl ToOwned for SslSessionRef {
210892f3ab15Sopenharmony_ci    type Owned = SslSession;
210992f3ab15Sopenharmony_ci
211092f3ab15Sopenharmony_ci    fn to_owned(&self) -> SslSession {
211192f3ab15Sopenharmony_ci        unsafe {
211292f3ab15Sopenharmony_ci            SSL_SESSION_up_ref(self.as_ptr());
211392f3ab15Sopenharmony_ci            SslSession(self.as_ptr())
211492f3ab15Sopenharmony_ci        }
211592f3ab15Sopenharmony_ci    }
211692f3ab15Sopenharmony_ci}
211792f3ab15Sopenharmony_ci
211892f3ab15Sopenharmony_ciimpl SslSessionRef {
211992f3ab15Sopenharmony_ci    /// Returns the SSL session ID.
212092f3ab15Sopenharmony_ci    #[corresponds(SSL_SESSION_get_id)]
212192f3ab15Sopenharmony_ci    pub fn id(&self) -> &[u8] {
212292f3ab15Sopenharmony_ci        unsafe {
212392f3ab15Sopenharmony_ci            let mut len = 0;
212492f3ab15Sopenharmony_ci            let p = ffi::SSL_SESSION_get_id(self.as_ptr(), &mut len);
212592f3ab15Sopenharmony_ci            slice::from_raw_parts(p as *const u8, len as usize)
212692f3ab15Sopenharmony_ci        }
212792f3ab15Sopenharmony_ci    }
212892f3ab15Sopenharmony_ci
212992f3ab15Sopenharmony_ci    /// Returns the length of the master key.
213092f3ab15Sopenharmony_ci    #[corresponds(SSL_SESSION_get_master_key)]
213192f3ab15Sopenharmony_ci    pub fn master_key_len(&self) -> usize {
213292f3ab15Sopenharmony_ci        unsafe { SSL_SESSION_get_master_key(self.as_ptr(), ptr::null_mut(), 0) }
213392f3ab15Sopenharmony_ci    }
213492f3ab15Sopenharmony_ci
213592f3ab15Sopenharmony_ci    /// Copies the master key into the provided buffer.
213692f3ab15Sopenharmony_ci    ///
213792f3ab15Sopenharmony_ci    /// Returns the number of bytes written, or the size of the master key if the buffer is empty.
213892f3ab15Sopenharmony_ci    #[corresponds(SSL_SESSION_get_master_key)]
213992f3ab15Sopenharmony_ci    pub fn master_key(&self, buf: &mut [u8]) -> usize {
214092f3ab15Sopenharmony_ci        unsafe { SSL_SESSION_get_master_key(self.as_ptr(), buf.as_mut_ptr(), buf.len()) }
214192f3ab15Sopenharmony_ci    }
214292f3ab15Sopenharmony_ci
214392f3ab15Sopenharmony_ci    /// Gets the maximum amount of early data that can be sent on this session.
214492f3ab15Sopenharmony_ci    ///
214592f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer.
214692f3ab15Sopenharmony_ci    #[corresponds(SSL_SESSION_get_max_early_data)]
214792f3ab15Sopenharmony_ci    #[cfg(any(ossl111, libressl340))]
214892f3ab15Sopenharmony_ci    pub fn max_early_data(&self) -> u32 {
214992f3ab15Sopenharmony_ci        unsafe { ffi::SSL_SESSION_get_max_early_data(self.as_ptr()) }
215092f3ab15Sopenharmony_ci    }
215192f3ab15Sopenharmony_ci
215292f3ab15Sopenharmony_ci    /// Returns the time at which the session was established, in seconds since the Unix epoch.
215392f3ab15Sopenharmony_ci    #[corresponds(SSL_SESSION_get_time)]
215492f3ab15Sopenharmony_ci    #[allow(clippy::useless_conversion)]
215592f3ab15Sopenharmony_ci    pub fn time(&self) -> SslTimeTy {
215692f3ab15Sopenharmony_ci        unsafe { ffi::SSL_SESSION_get_time(self.as_ptr()) }
215792f3ab15Sopenharmony_ci    }
215892f3ab15Sopenharmony_ci
215992f3ab15Sopenharmony_ci    /// Returns the sessions timeout, in seconds.
216092f3ab15Sopenharmony_ci    ///
216192f3ab15Sopenharmony_ci    /// A session older than this time should not be used for session resumption.
216292f3ab15Sopenharmony_ci    #[corresponds(SSL_SESSION_get_timeout)]
216392f3ab15Sopenharmony_ci    #[allow(clippy::useless_conversion)]
216492f3ab15Sopenharmony_ci    pub fn timeout(&self) -> i64 {
216592f3ab15Sopenharmony_ci        unsafe { ffi::SSL_SESSION_get_timeout(self.as_ptr()).into() }
216692f3ab15Sopenharmony_ci    }
216792f3ab15Sopenharmony_ci
216892f3ab15Sopenharmony_ci    /// Returns the session's TLS protocol version.
216992f3ab15Sopenharmony_ci    ///
217092f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.1.0 or LibreSSL 2.7.0 or newer.
217192f3ab15Sopenharmony_ci    #[corresponds(SSL_SESSION_get_protocol_version)]
217292f3ab15Sopenharmony_ci    #[cfg(any(ossl110, libressl270))]
217392f3ab15Sopenharmony_ci    pub fn protocol_version(&self) -> SslVersion {
217492f3ab15Sopenharmony_ci        unsafe {
217592f3ab15Sopenharmony_ci            let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr());
217692f3ab15Sopenharmony_ci            SslVersion(version)
217792f3ab15Sopenharmony_ci        }
217892f3ab15Sopenharmony_ci    }
217992f3ab15Sopenharmony_ci
218092f3ab15Sopenharmony_ci    to_der! {
218192f3ab15Sopenharmony_ci        /// Serializes the session into a DER-encoded structure.
218292f3ab15Sopenharmony_ci        #[corresponds(i2d_SSL_SESSION)]
218392f3ab15Sopenharmony_ci        to_der,
218492f3ab15Sopenharmony_ci        ffi::i2d_SSL_SESSION
218592f3ab15Sopenharmony_ci    }
218692f3ab15Sopenharmony_ci}
218792f3ab15Sopenharmony_ci
218892f3ab15Sopenharmony_ciforeign_type_and_impl_send_sync! {
218992f3ab15Sopenharmony_ci    type CType = ffi::SSL;
219092f3ab15Sopenharmony_ci    fn drop = ffi::SSL_free;
219192f3ab15Sopenharmony_ci
219292f3ab15Sopenharmony_ci    /// The state of an SSL/TLS session.
219392f3ab15Sopenharmony_ci    ///
219492f3ab15Sopenharmony_ci    /// `Ssl` objects are created from an [`SslContext`], which provides configuration defaults.
219592f3ab15Sopenharmony_ci    /// These defaults can be overridden on a per-`Ssl` basis, however.
219692f3ab15Sopenharmony_ci    ///
219792f3ab15Sopenharmony_ci    /// [`SslContext`]: struct.SslContext.html
219892f3ab15Sopenharmony_ci    pub struct Ssl;
219992f3ab15Sopenharmony_ci
220092f3ab15Sopenharmony_ci    /// Reference to an [`Ssl`].
220192f3ab15Sopenharmony_ci    ///
220292f3ab15Sopenharmony_ci    /// [`Ssl`]: struct.Ssl.html
220392f3ab15Sopenharmony_ci    pub struct SslRef;
220492f3ab15Sopenharmony_ci}
220592f3ab15Sopenharmony_ci
220692f3ab15Sopenharmony_ciimpl fmt::Debug for Ssl {
220792f3ab15Sopenharmony_ci    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
220892f3ab15Sopenharmony_ci        fmt::Debug::fmt(&**self, fmt)
220992f3ab15Sopenharmony_ci    }
221092f3ab15Sopenharmony_ci}
221192f3ab15Sopenharmony_ci
221292f3ab15Sopenharmony_ciimpl Ssl {
221392f3ab15Sopenharmony_ci    /// Returns a new extra data index.
221492f3ab15Sopenharmony_ci    ///
221592f3ab15Sopenharmony_ci    /// Each invocation of this function is guaranteed to return a distinct index. These can be used
221692f3ab15Sopenharmony_ci    /// to store data in the context that can be retrieved later by callbacks, for example.
221792f3ab15Sopenharmony_ci    #[corresponds(SSL_get_ex_new_index)]
221892f3ab15Sopenharmony_ci    pub fn new_ex_index<T>() -> Result<Index<Ssl, T>, ErrorStack>
221992f3ab15Sopenharmony_ci    where
222092f3ab15Sopenharmony_ci        T: 'static + Sync + Send,
222192f3ab15Sopenharmony_ci    {
222292f3ab15Sopenharmony_ci        unsafe {
222392f3ab15Sopenharmony_ci            ffi::init();
222492f3ab15Sopenharmony_ci            #[cfg(boringssl)]
222592f3ab15Sopenharmony_ci            let idx = cvt_n(get_new_ssl_idx(Some(free_data_box::<T>)))?;
222692f3ab15Sopenharmony_ci            #[cfg(not(boringssl))]
222792f3ab15Sopenharmony_ci            let idx = cvt_n(get_new_ssl_idx(free_data_box::<T>))?;
222892f3ab15Sopenharmony_ci            Ok(Index::from_raw(idx))
222992f3ab15Sopenharmony_ci        }
223092f3ab15Sopenharmony_ci    }
223192f3ab15Sopenharmony_ci
223292f3ab15Sopenharmony_ci    // FIXME should return a result?
223392f3ab15Sopenharmony_ci    fn cached_ex_index<T>() -> Index<Ssl, T>
223492f3ab15Sopenharmony_ci    where
223592f3ab15Sopenharmony_ci        T: 'static + Sync + Send,
223692f3ab15Sopenharmony_ci    {
223792f3ab15Sopenharmony_ci        unsafe {
223892f3ab15Sopenharmony_ci            let idx = *SSL_INDEXES
223992f3ab15Sopenharmony_ci                .lock()
224092f3ab15Sopenharmony_ci                .unwrap_or_else(|e| e.into_inner())
224192f3ab15Sopenharmony_ci                .entry(TypeId::of::<T>())
224292f3ab15Sopenharmony_ci                .or_insert_with(|| Ssl::new_ex_index::<T>().unwrap().as_raw());
224392f3ab15Sopenharmony_ci            Index::from_raw(idx)
224492f3ab15Sopenharmony_ci        }
224592f3ab15Sopenharmony_ci    }
224692f3ab15Sopenharmony_ci
224792f3ab15Sopenharmony_ci    /// Creates a new `Ssl`.
224892f3ab15Sopenharmony_ci    ///
224992f3ab15Sopenharmony_ci    /// This corresponds to [`SSL_new`].
225092f3ab15Sopenharmony_ci    ///
225192f3ab15Sopenharmony_ci    /// [`SSL_new`]: https://www.openssl.org/docs/manmaster/ssl/SSL_new.html
225292f3ab15Sopenharmony_ci    #[corresponds(SSL_new)]
225392f3ab15Sopenharmony_ci    pub fn new(ctx: &SslContextRef) -> Result<Ssl, ErrorStack> {
225492f3ab15Sopenharmony_ci        let session_ctx_index = try_get_session_ctx_index()?;
225592f3ab15Sopenharmony_ci        unsafe {
225692f3ab15Sopenharmony_ci            let ptr = cvt_p(ffi::SSL_new(ctx.as_ptr()))?;
225792f3ab15Sopenharmony_ci            let mut ssl = Ssl::from_ptr(ptr);
225892f3ab15Sopenharmony_ci            ssl.set_ex_data(*session_ctx_index, ctx.to_owned());
225992f3ab15Sopenharmony_ci
226092f3ab15Sopenharmony_ci            Ok(ssl)
226192f3ab15Sopenharmony_ci        }
226292f3ab15Sopenharmony_ci    }
226392f3ab15Sopenharmony_ci
226492f3ab15Sopenharmony_ci    /// Initiates a client-side TLS handshake.
226592f3ab15Sopenharmony_ci    ///
226692f3ab15Sopenharmony_ci    /// This corresponds to [`SSL_connect`].
226792f3ab15Sopenharmony_ci    ///
226892f3ab15Sopenharmony_ci    /// # Warning
226992f3ab15Sopenharmony_ci    ///
227092f3ab15Sopenharmony_ci    /// OpenSSL's default configuration is insecure. It is highly recommended to use
227192f3ab15Sopenharmony_ci    /// `SslConnector` rather than `Ssl` directly, as it manages that configuration.
227292f3ab15Sopenharmony_ci    ///
227392f3ab15Sopenharmony_ci    /// [`SSL_connect`]: https://www.openssl.org/docs/manmaster/man3/SSL_connect.html
227492f3ab15Sopenharmony_ci    #[corresponds(SSL_connect)]
227592f3ab15Sopenharmony_ci    #[allow(deprecated)]
227692f3ab15Sopenharmony_ci    pub fn connect<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
227792f3ab15Sopenharmony_ci    where
227892f3ab15Sopenharmony_ci        S: Read + Write,
227992f3ab15Sopenharmony_ci    {
228092f3ab15Sopenharmony_ci        SslStreamBuilder::new(self, stream).connect()
228192f3ab15Sopenharmony_ci    }
228292f3ab15Sopenharmony_ci
228392f3ab15Sopenharmony_ci    /// Initiates a server-side TLS handshake.
228492f3ab15Sopenharmony_ci    ///
228592f3ab15Sopenharmony_ci    /// This corresponds to [`SSL_accept`].
228692f3ab15Sopenharmony_ci    ///
228792f3ab15Sopenharmony_ci    /// # Warning
228892f3ab15Sopenharmony_ci    ///
228992f3ab15Sopenharmony_ci    /// OpenSSL's default configuration is insecure. It is highly recommended to use
229092f3ab15Sopenharmony_ci    /// `SslAcceptor` rather than `Ssl` directly, as it manages that configuration.
229192f3ab15Sopenharmony_ci    ///
229292f3ab15Sopenharmony_ci    /// [`SSL_accept`]: https://www.openssl.org/docs/manmaster/man3/SSL_accept.html
229392f3ab15Sopenharmony_ci    #[corresponds(SSL_accept)]
229492f3ab15Sopenharmony_ci    #[allow(deprecated)]
229592f3ab15Sopenharmony_ci    pub fn accept<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
229692f3ab15Sopenharmony_ci    where
229792f3ab15Sopenharmony_ci        S: Read + Write,
229892f3ab15Sopenharmony_ci    {
229992f3ab15Sopenharmony_ci        SslStreamBuilder::new(self, stream).accept()
230092f3ab15Sopenharmony_ci    }
230192f3ab15Sopenharmony_ci}
230292f3ab15Sopenharmony_ci
230392f3ab15Sopenharmony_ciimpl fmt::Debug for SslRef {
230492f3ab15Sopenharmony_ci    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
230592f3ab15Sopenharmony_ci        fmt.debug_struct("Ssl")
230692f3ab15Sopenharmony_ci            .field("state", &self.state_string_long())
230792f3ab15Sopenharmony_ci            .field("verify_result", &self.verify_result())
230892f3ab15Sopenharmony_ci            .finish()
230992f3ab15Sopenharmony_ci    }
231092f3ab15Sopenharmony_ci}
231192f3ab15Sopenharmony_ci
231292f3ab15Sopenharmony_ciimpl SslRef {
231392f3ab15Sopenharmony_ci    fn get_raw_rbio(&self) -> *mut ffi::BIO {
231492f3ab15Sopenharmony_ci        unsafe { ffi::SSL_get_rbio(self.as_ptr()) }
231592f3ab15Sopenharmony_ci    }
231692f3ab15Sopenharmony_ci
231792f3ab15Sopenharmony_ci    fn read(&mut self, buf: &mut [u8]) -> c_int {
231892f3ab15Sopenharmony_ci        let len = cmp::min(c_int::max_value() as usize, buf.len()) as c_int;
231992f3ab15Sopenharmony_ci        unsafe { ffi::SSL_read(self.as_ptr(), buf.as_ptr() as *mut c_void, len) }
232092f3ab15Sopenharmony_ci    }
232192f3ab15Sopenharmony_ci
232292f3ab15Sopenharmony_ci    fn peek(&mut self, buf: &mut [u8]) -> c_int {
232392f3ab15Sopenharmony_ci        let len = cmp::min(c_int::max_value() as usize, buf.len()) as c_int;
232492f3ab15Sopenharmony_ci        unsafe { ffi::SSL_peek(self.as_ptr(), buf.as_ptr() as *mut c_void, len) }
232592f3ab15Sopenharmony_ci    }
232692f3ab15Sopenharmony_ci
232792f3ab15Sopenharmony_ci    fn write(&mut self, buf: &[u8]) -> c_int {
232892f3ab15Sopenharmony_ci        let len = cmp::min(c_int::max_value() as usize, buf.len()) as c_int;
232992f3ab15Sopenharmony_ci        unsafe { ffi::SSL_write(self.as_ptr(), buf.as_ptr() as *const c_void, len) }
233092f3ab15Sopenharmony_ci    }
233192f3ab15Sopenharmony_ci
233292f3ab15Sopenharmony_ci    fn get_error(&self, ret: c_int) -> ErrorCode {
233392f3ab15Sopenharmony_ci        unsafe { ErrorCode::from_raw(ffi::SSL_get_error(self.as_ptr(), ret)) }
233492f3ab15Sopenharmony_ci    }
233592f3ab15Sopenharmony_ci
233692f3ab15Sopenharmony_ci    /// Configure as an outgoing stream from a client.
233792f3ab15Sopenharmony_ci    #[corresponds(SSL_set_connect_state)]
233892f3ab15Sopenharmony_ci    pub fn set_connect_state(&mut self) {
233992f3ab15Sopenharmony_ci        unsafe { ffi::SSL_set_connect_state(self.as_ptr()) }
234092f3ab15Sopenharmony_ci    }
234192f3ab15Sopenharmony_ci
234292f3ab15Sopenharmony_ci    /// Configure as an incoming stream to a server.
234392f3ab15Sopenharmony_ci    #[corresponds(SSL_set_accept_state)]
234492f3ab15Sopenharmony_ci    pub fn set_accept_state(&mut self) {
234592f3ab15Sopenharmony_ci        unsafe { ffi::SSL_set_accept_state(self.as_ptr()) }
234692f3ab15Sopenharmony_ci    }
234792f3ab15Sopenharmony_ci
234892f3ab15Sopenharmony_ci    /// Like [`SslContextBuilder::set_verify`].
234992f3ab15Sopenharmony_ci    ///
235092f3ab15Sopenharmony_ci    /// [`SslContextBuilder::set_verify`]: struct.SslContextBuilder.html#method.set_verify
235192f3ab15Sopenharmony_ci    #[corresponds(SSL_set_verify)]
235292f3ab15Sopenharmony_ci    pub fn set_verify(&mut self, mode: SslVerifyMode) {
235392f3ab15Sopenharmony_ci        unsafe { ffi::SSL_set_verify(self.as_ptr(), mode.bits as c_int, None) }
235492f3ab15Sopenharmony_ci    }
235592f3ab15Sopenharmony_ci
235692f3ab15Sopenharmony_ci    /// Returns the verify mode that was set using `set_verify`.
235792f3ab15Sopenharmony_ci    #[corresponds(SSL_set_verify_mode)]
235892f3ab15Sopenharmony_ci    pub fn verify_mode(&self) -> SslVerifyMode {
235992f3ab15Sopenharmony_ci        let mode = unsafe { ffi::SSL_get_verify_mode(self.as_ptr()) };
236092f3ab15Sopenharmony_ci        SslVerifyMode::from_bits(mode).expect("SSL_get_verify_mode returned invalid mode")
236192f3ab15Sopenharmony_ci    }
236292f3ab15Sopenharmony_ci
236392f3ab15Sopenharmony_ci    /// Like [`SslContextBuilder::set_verify_callback`].
236492f3ab15Sopenharmony_ci    ///
236592f3ab15Sopenharmony_ci    /// [`SslContextBuilder::set_verify_callback`]: struct.SslContextBuilder.html#method.set_verify_callback
236692f3ab15Sopenharmony_ci    #[corresponds(SSL_set_verify)]
236792f3ab15Sopenharmony_ci    pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
236892f3ab15Sopenharmony_ci    where
236992f3ab15Sopenharmony_ci        F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
237092f3ab15Sopenharmony_ci    {
237192f3ab15Sopenharmony_ci        unsafe {
237292f3ab15Sopenharmony_ci            // this needs to be in an Arc since the callback can register a new callback!
237392f3ab15Sopenharmony_ci            self.set_ex_data(Ssl::cached_ex_index(), Arc::new(verify));
237492f3ab15Sopenharmony_ci            ffi::SSL_set_verify(self.as_ptr(), mode.bits as c_int, Some(ssl_raw_verify::<F>));
237592f3ab15Sopenharmony_ci        }
237692f3ab15Sopenharmony_ci    }
237792f3ab15Sopenharmony_ci
237892f3ab15Sopenharmony_ci    /// Like [`SslContextBuilder::set_tmp_dh`].
237992f3ab15Sopenharmony_ci    ///
238092f3ab15Sopenharmony_ci    /// [`SslContextBuilder::set_tmp_dh`]: struct.SslContextBuilder.html#method.set_tmp_dh
238192f3ab15Sopenharmony_ci    #[corresponds(SSL_set_tmp_dh)]
238292f3ab15Sopenharmony_ci    pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
238392f3ab15Sopenharmony_ci        unsafe { cvt(ffi::SSL_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
238492f3ab15Sopenharmony_ci    }
238592f3ab15Sopenharmony_ci
238692f3ab15Sopenharmony_ci    /// Like [`SslContextBuilder::set_tmp_dh_callback`].
238792f3ab15Sopenharmony_ci    ///
238892f3ab15Sopenharmony_ci    /// [`SslContextBuilder::set_tmp_dh_callback`]: struct.SslContextBuilder.html#method.set_tmp_dh_callback
238992f3ab15Sopenharmony_ci    #[corresponds(SSL_set_tmp_dh_callback)]
239092f3ab15Sopenharmony_ci    pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
239192f3ab15Sopenharmony_ci    where
239292f3ab15Sopenharmony_ci        F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
239392f3ab15Sopenharmony_ci    {
239492f3ab15Sopenharmony_ci        unsafe {
239592f3ab15Sopenharmony_ci            // this needs to be in an Arc since the callback can register a new callback!
239692f3ab15Sopenharmony_ci            self.set_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
239792f3ab15Sopenharmony_ci            #[cfg(boringssl)]
239892f3ab15Sopenharmony_ci            ffi::SSL_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh_ssl::<F>));
239992f3ab15Sopenharmony_ci            #[cfg(not(boringssl))]
240092f3ab15Sopenharmony_ci            ffi::SSL_set_tmp_dh_callback__fixed_rust(self.as_ptr(), Some(raw_tmp_dh_ssl::<F>));
240192f3ab15Sopenharmony_ci        }
240292f3ab15Sopenharmony_ci    }
240392f3ab15Sopenharmony_ci
240492f3ab15Sopenharmony_ci    /// Like [`SslContextBuilder::set_tmp_ecdh`].
240592f3ab15Sopenharmony_ci    ///
240692f3ab15Sopenharmony_ci    /// [`SslContextBuilder::set_tmp_ecdh`]: struct.SslContextBuilder.html#method.set_tmp_ecdh
240792f3ab15Sopenharmony_ci    #[corresponds(SSL_set_tmp_ecdh)]
240892f3ab15Sopenharmony_ci    pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
240992f3ab15Sopenharmony_ci        unsafe { cvt(ffi::SSL_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
241092f3ab15Sopenharmony_ci    }
241192f3ab15Sopenharmony_ci
241292f3ab15Sopenharmony_ci    /// Like [`SslContextBuilder::set_tmp_ecdh_callback`].
241392f3ab15Sopenharmony_ci    ///
241492f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.0.1 or 1.0.2.
241592f3ab15Sopenharmony_ci    #[corresponds(SSL_set_tmp_ecdh_callback)]
241692f3ab15Sopenharmony_ci    #[cfg(all(ossl101, not(ossl110)))]
241792f3ab15Sopenharmony_ci    #[deprecated(note = "this function leaks memory and does not exist on newer OpenSSL versions")]
241892f3ab15Sopenharmony_ci    pub fn set_tmp_ecdh_callback<F>(&mut self, callback: F)
241992f3ab15Sopenharmony_ci    where
242092f3ab15Sopenharmony_ci        F: Fn(&mut SslRef, bool, u32) -> Result<EcKey<Params>, ErrorStack> + 'static + Sync + Send,
242192f3ab15Sopenharmony_ci    {
242292f3ab15Sopenharmony_ci        unsafe {
242392f3ab15Sopenharmony_ci            // this needs to be in an Arc since the callback can register a new callback!
242492f3ab15Sopenharmony_ci            self.set_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
242592f3ab15Sopenharmony_ci            ffi::SSL_set_tmp_ecdh_callback__fixed_rust(self.as_ptr(), Some(raw_tmp_ecdh_ssl::<F>));
242692f3ab15Sopenharmony_ci        }
242792f3ab15Sopenharmony_ci    }
242892f3ab15Sopenharmony_ci
242992f3ab15Sopenharmony_ci    /// Like [`SslContextBuilder::set_ecdh_auto`].
243092f3ab15Sopenharmony_ci    ///
243192f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.0.2 or LibreSSL.
243292f3ab15Sopenharmony_ci    ///
243392f3ab15Sopenharmony_ci    /// [`SslContextBuilder::set_tmp_ecdh`]: struct.SslContextBuilder.html#method.set_tmp_ecdh
243492f3ab15Sopenharmony_ci    #[corresponds(SSL_set_ecdh_auto)]
243592f3ab15Sopenharmony_ci    #[cfg(any(all(ossl102, not(ossl110)), libressl))]
243692f3ab15Sopenharmony_ci    pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
243792f3ab15Sopenharmony_ci        unsafe { cvt(ffi::SSL_set_ecdh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) }
243892f3ab15Sopenharmony_ci    }
243992f3ab15Sopenharmony_ci
244092f3ab15Sopenharmony_ci    /// Like [`SslContextBuilder::set_alpn_protos`].
244192f3ab15Sopenharmony_ci    ///
244292f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.0.2 or LibreSSL 2.6.1 or newer.
244392f3ab15Sopenharmony_ci    ///
244492f3ab15Sopenharmony_ci    /// [`SslContextBuilder::set_alpn_protos`]: struct.SslContextBuilder.html#method.set_alpn_protos
244592f3ab15Sopenharmony_ci    #[corresponds(SSL_set_alpn_protos)]
244692f3ab15Sopenharmony_ci    #[cfg(any(ossl102, libressl261))]
244792f3ab15Sopenharmony_ci    pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
244892f3ab15Sopenharmony_ci        unsafe {
244992f3ab15Sopenharmony_ci            assert!(protocols.len() <= c_uint::max_value() as usize);
245092f3ab15Sopenharmony_ci            let r = ffi::SSL_set_alpn_protos(
245192f3ab15Sopenharmony_ci                self.as_ptr(),
245292f3ab15Sopenharmony_ci                protocols.as_ptr(),
245392f3ab15Sopenharmony_ci                protocols.len() as c_uint,
245492f3ab15Sopenharmony_ci            );
245592f3ab15Sopenharmony_ci            // fun fact, SSL_set_alpn_protos has a reversed return code D:
245692f3ab15Sopenharmony_ci            if r == 0 {
245792f3ab15Sopenharmony_ci                Ok(())
245892f3ab15Sopenharmony_ci            } else {
245992f3ab15Sopenharmony_ci                Err(ErrorStack::get())
246092f3ab15Sopenharmony_ci            }
246192f3ab15Sopenharmony_ci        }
246292f3ab15Sopenharmony_ci    }
246392f3ab15Sopenharmony_ci
246492f3ab15Sopenharmony_ci    /// Returns the current cipher if the session is active.
246592f3ab15Sopenharmony_ci    #[corresponds(SSL_get_current_cipher)]
246692f3ab15Sopenharmony_ci    pub fn current_cipher(&self) -> Option<&SslCipherRef> {
246792f3ab15Sopenharmony_ci        unsafe {
246892f3ab15Sopenharmony_ci            let ptr = ffi::SSL_get_current_cipher(self.as_ptr());
246992f3ab15Sopenharmony_ci
247092f3ab15Sopenharmony_ci            SslCipherRef::from_const_ptr_opt(ptr)
247192f3ab15Sopenharmony_ci        }
247292f3ab15Sopenharmony_ci    }
247392f3ab15Sopenharmony_ci
247492f3ab15Sopenharmony_ci    /// Returns a short string describing the state of the session.
247592f3ab15Sopenharmony_ci    #[corresponds(SSL_state_string)]
247692f3ab15Sopenharmony_ci    pub fn state_string(&self) -> &'static str {
247792f3ab15Sopenharmony_ci        let state = unsafe {
247892f3ab15Sopenharmony_ci            let ptr = ffi::SSL_state_string(self.as_ptr());
247992f3ab15Sopenharmony_ci            CStr::from_ptr(ptr as *const _)
248092f3ab15Sopenharmony_ci        };
248192f3ab15Sopenharmony_ci
248292f3ab15Sopenharmony_ci        str::from_utf8(state.to_bytes()).unwrap()
248392f3ab15Sopenharmony_ci    }
248492f3ab15Sopenharmony_ci
248592f3ab15Sopenharmony_ci    /// Returns a longer string describing the state of the session.
248692f3ab15Sopenharmony_ci    #[corresponds(SSL_state_string_long)]
248792f3ab15Sopenharmony_ci    pub fn state_string_long(&self) -> &'static str {
248892f3ab15Sopenharmony_ci        let state = unsafe {
248992f3ab15Sopenharmony_ci            let ptr = ffi::SSL_state_string_long(self.as_ptr());
249092f3ab15Sopenharmony_ci            CStr::from_ptr(ptr as *const _)
249192f3ab15Sopenharmony_ci        };
249292f3ab15Sopenharmony_ci
249392f3ab15Sopenharmony_ci        str::from_utf8(state.to_bytes()).unwrap()
249492f3ab15Sopenharmony_ci    }
249592f3ab15Sopenharmony_ci
249692f3ab15Sopenharmony_ci    /// Sets the host name to be sent to the server for Server Name Indication (SNI).
249792f3ab15Sopenharmony_ci    ///
249892f3ab15Sopenharmony_ci    /// It has no effect for a server-side connection.
249992f3ab15Sopenharmony_ci    #[corresponds(SSL_set_tlsext_host_name)]
250092f3ab15Sopenharmony_ci    pub fn set_hostname(&mut self, hostname: &str) -> Result<(), ErrorStack> {
250192f3ab15Sopenharmony_ci        let cstr = CString::new(hostname).unwrap();
250292f3ab15Sopenharmony_ci        unsafe {
250392f3ab15Sopenharmony_ci            cvt(ffi::SSL_set_tlsext_host_name(self.as_ptr(), cstr.as_ptr() as *mut _) as c_int)
250492f3ab15Sopenharmony_ci                .map(|_| ())
250592f3ab15Sopenharmony_ci        }
250692f3ab15Sopenharmony_ci    }
250792f3ab15Sopenharmony_ci
250892f3ab15Sopenharmony_ci    /// Returns the peer's certificate, if present.
250992f3ab15Sopenharmony_ci    #[corresponds(SSL_get_peer_certificate)]
251092f3ab15Sopenharmony_ci    pub fn peer_certificate(&self) -> Option<X509> {
251192f3ab15Sopenharmony_ci        unsafe {
251292f3ab15Sopenharmony_ci            let ptr = SSL_get1_peer_certificate(self.as_ptr());
251392f3ab15Sopenharmony_ci            X509::from_ptr_opt(ptr)
251492f3ab15Sopenharmony_ci        }
251592f3ab15Sopenharmony_ci    }
251692f3ab15Sopenharmony_ci
251792f3ab15Sopenharmony_ci    /// Returns the certificate chain of the peer, if present.
251892f3ab15Sopenharmony_ci    ///
251992f3ab15Sopenharmony_ci    /// On the client side, the chain includes the leaf certificate, but on the server side it does
252092f3ab15Sopenharmony_ci    /// not. Fun!
252192f3ab15Sopenharmony_ci    #[corresponds(SSL_get_peer_cert_chain)]
252292f3ab15Sopenharmony_ci    pub fn peer_cert_chain(&self) -> Option<&StackRef<X509>> {
252392f3ab15Sopenharmony_ci        unsafe {
252492f3ab15Sopenharmony_ci            let ptr = ffi::SSL_get_peer_cert_chain(self.as_ptr());
252592f3ab15Sopenharmony_ci            StackRef::from_const_ptr_opt(ptr)
252692f3ab15Sopenharmony_ci        }
252792f3ab15Sopenharmony_ci    }
252892f3ab15Sopenharmony_ci
252992f3ab15Sopenharmony_ci    /// Returns the verified certificate chain of the peer, including the leaf certificate.
253092f3ab15Sopenharmony_ci    ///
253192f3ab15Sopenharmony_ci    /// If verification was not successful (i.e. [`verify_result`] does not return
253292f3ab15Sopenharmony_ci    /// [`X509VerifyResult::OK`]), this chain may be incomplete or invalid.
253392f3ab15Sopenharmony_ci    ///
253492f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.1.0 or newer.
253592f3ab15Sopenharmony_ci    ///
253692f3ab15Sopenharmony_ci    /// [`verify_result`]: #method.verify_result
253792f3ab15Sopenharmony_ci    /// [`X509VerifyResult::OK`]: ../x509/struct.X509VerifyResult.html#associatedconstant.OK
253892f3ab15Sopenharmony_ci    #[corresponds(SSL_get0_verified_chain)]
253992f3ab15Sopenharmony_ci    #[cfg(ossl110)]
254092f3ab15Sopenharmony_ci    pub fn verified_chain(&self) -> Option<&StackRef<X509>> {
254192f3ab15Sopenharmony_ci        unsafe {
254292f3ab15Sopenharmony_ci            let ptr = ffi::SSL_get0_verified_chain(self.as_ptr());
254392f3ab15Sopenharmony_ci            StackRef::from_const_ptr_opt(ptr)
254492f3ab15Sopenharmony_ci        }
254592f3ab15Sopenharmony_ci    }
254692f3ab15Sopenharmony_ci
254792f3ab15Sopenharmony_ci    /// Like [`SslContext::certificate`].
254892f3ab15Sopenharmony_ci    #[corresponds(SSL_get_certificate)]
254992f3ab15Sopenharmony_ci    pub fn certificate(&self) -> Option<&X509Ref> {
255092f3ab15Sopenharmony_ci        unsafe {
255192f3ab15Sopenharmony_ci            let ptr = ffi::SSL_get_certificate(self.as_ptr());
255292f3ab15Sopenharmony_ci            X509Ref::from_const_ptr_opt(ptr)
255392f3ab15Sopenharmony_ci        }
255492f3ab15Sopenharmony_ci    }
255592f3ab15Sopenharmony_ci
255692f3ab15Sopenharmony_ci    /// Like [`SslContext::private_key`].
255792f3ab15Sopenharmony_ci    ///
255892f3ab15Sopenharmony_ci    /// [`SslContext::private_key`]: struct.SslContext.html#method.private_key
255992f3ab15Sopenharmony_ci    #[corresponds(SSL_get_privatekey)]
256092f3ab15Sopenharmony_ci    pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
256192f3ab15Sopenharmony_ci        unsafe {
256292f3ab15Sopenharmony_ci            let ptr = ffi::SSL_get_privatekey(self.as_ptr());
256392f3ab15Sopenharmony_ci            PKeyRef::from_const_ptr_opt(ptr)
256492f3ab15Sopenharmony_ci        }
256592f3ab15Sopenharmony_ci    }
256692f3ab15Sopenharmony_ci
256792f3ab15Sopenharmony_ci    #[deprecated(since = "0.10.5", note = "renamed to `version_str`")]
256892f3ab15Sopenharmony_ci    pub fn version(&self) -> &str {
256992f3ab15Sopenharmony_ci        self.version_str()
257092f3ab15Sopenharmony_ci    }
257192f3ab15Sopenharmony_ci
257292f3ab15Sopenharmony_ci    /// Returns the protocol version of the session.
257392f3ab15Sopenharmony_ci    #[corresponds(SSL_version)]
257492f3ab15Sopenharmony_ci    pub fn version2(&self) -> Option<SslVersion> {
257592f3ab15Sopenharmony_ci        unsafe {
257692f3ab15Sopenharmony_ci            let r = ffi::SSL_version(self.as_ptr());
257792f3ab15Sopenharmony_ci            if r == 0 {
257892f3ab15Sopenharmony_ci                None
257992f3ab15Sopenharmony_ci            } else {
258092f3ab15Sopenharmony_ci                Some(SslVersion(r))
258192f3ab15Sopenharmony_ci            }
258292f3ab15Sopenharmony_ci        }
258392f3ab15Sopenharmony_ci    }
258492f3ab15Sopenharmony_ci
258592f3ab15Sopenharmony_ci    /// Returns a string describing the protocol version of the session.
258692f3ab15Sopenharmony_ci    #[corresponds(SSL_get_version)]
258792f3ab15Sopenharmony_ci    pub fn version_str(&self) -> &'static str {
258892f3ab15Sopenharmony_ci        let version = unsafe {
258992f3ab15Sopenharmony_ci            let ptr = ffi::SSL_get_version(self.as_ptr());
259092f3ab15Sopenharmony_ci            CStr::from_ptr(ptr as *const _)
259192f3ab15Sopenharmony_ci        };
259292f3ab15Sopenharmony_ci
259392f3ab15Sopenharmony_ci        str::from_utf8(version.to_bytes()).unwrap()
259492f3ab15Sopenharmony_ci    }
259592f3ab15Sopenharmony_ci
259692f3ab15Sopenharmony_ci    /// Returns the protocol selected via Application Layer Protocol Negotiation (ALPN).
259792f3ab15Sopenharmony_ci    ///
259892f3ab15Sopenharmony_ci    /// The protocol's name is returned is an opaque sequence of bytes. It is up to the client
259992f3ab15Sopenharmony_ci    /// to interpret it.
260092f3ab15Sopenharmony_ci    ///
260192f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.0.2 or LibreSSL 2.6.1 or newer.
260292f3ab15Sopenharmony_ci    #[corresponds(SSL_get0_alpn_selected)]
260392f3ab15Sopenharmony_ci    #[cfg(any(ossl102, libressl261))]
260492f3ab15Sopenharmony_ci    pub fn selected_alpn_protocol(&self) -> Option<&[u8]> {
260592f3ab15Sopenharmony_ci        unsafe {
260692f3ab15Sopenharmony_ci            let mut data: *const c_uchar = ptr::null();
260792f3ab15Sopenharmony_ci            let mut len: c_uint = 0;
260892f3ab15Sopenharmony_ci            // Get the negotiated protocol from the SSL instance.
260992f3ab15Sopenharmony_ci            // `data` will point at a `c_uchar` array; `len` will contain the length of this array.
261092f3ab15Sopenharmony_ci            ffi::SSL_get0_alpn_selected(self.as_ptr(), &mut data, &mut len);
261192f3ab15Sopenharmony_ci
261292f3ab15Sopenharmony_ci            if data.is_null() {
261392f3ab15Sopenharmony_ci                None
261492f3ab15Sopenharmony_ci            } else {
261592f3ab15Sopenharmony_ci                Some(slice::from_raw_parts(data, len as usize))
261692f3ab15Sopenharmony_ci            }
261792f3ab15Sopenharmony_ci        }
261892f3ab15Sopenharmony_ci    }
261992f3ab15Sopenharmony_ci
262092f3ab15Sopenharmony_ci    /// Enables the DTLS extension "use_srtp" as defined in RFC5764.
262192f3ab15Sopenharmony_ci    ///
262292f3ab15Sopenharmony_ci    /// This corresponds to [`SSL_set_tlsext_use_srtp`].
262392f3ab15Sopenharmony_ci    ///
262492f3ab15Sopenharmony_ci    /// [`SSL_set_tlsext_use_srtp`]: https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_tlsext_use_srtp.html
262592f3ab15Sopenharmony_ci    #[corresponds(SSL_set_tlsext_use_srtp)]
262692f3ab15Sopenharmony_ci    pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
262792f3ab15Sopenharmony_ci        unsafe {
262892f3ab15Sopenharmony_ci            let cstr = CString::new(protocols).unwrap();
262992f3ab15Sopenharmony_ci
263092f3ab15Sopenharmony_ci            let r = ffi::SSL_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
263192f3ab15Sopenharmony_ci            // fun fact, set_tlsext_use_srtp has a reversed return code D:
263292f3ab15Sopenharmony_ci            if r == 0 {
263392f3ab15Sopenharmony_ci                Ok(())
263492f3ab15Sopenharmony_ci            } else {
263592f3ab15Sopenharmony_ci                Err(ErrorStack::get())
263692f3ab15Sopenharmony_ci            }
263792f3ab15Sopenharmony_ci        }
263892f3ab15Sopenharmony_ci    }
263992f3ab15Sopenharmony_ci
264092f3ab15Sopenharmony_ci    /// Gets all SRTP profiles that are enabled for handshake via set_tlsext_use_srtp
264192f3ab15Sopenharmony_ci    ///
264292f3ab15Sopenharmony_ci    /// DTLS extension "use_srtp" as defined in RFC5764 has to be enabled.
264392f3ab15Sopenharmony_ci    ///
264492f3ab15Sopenharmony_ci    /// This corresponds to [`SSL_get_srtp_profiles`].
264592f3ab15Sopenharmony_ci    ///
264692f3ab15Sopenharmony_ci    /// [`SSL_get_srtp_profiles`]: https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_tlsext_use_srtp.html
264792f3ab15Sopenharmony_ci    #[corresponds(SSL_get_srtp_profiles)]
264892f3ab15Sopenharmony_ci    pub fn srtp_profiles(&self) -> Option<&StackRef<SrtpProtectionProfile>> {
264992f3ab15Sopenharmony_ci        unsafe {
265092f3ab15Sopenharmony_ci            let chain = ffi::SSL_get_srtp_profiles(self.as_ptr());
265192f3ab15Sopenharmony_ci
265292f3ab15Sopenharmony_ci            StackRef::from_const_ptr_opt(chain)
265392f3ab15Sopenharmony_ci        }
265492f3ab15Sopenharmony_ci    }
265592f3ab15Sopenharmony_ci
265692f3ab15Sopenharmony_ci    /// Gets the SRTP profile selected by handshake.
265792f3ab15Sopenharmony_ci    ///
265892f3ab15Sopenharmony_ci    /// DTLS extension "use_srtp" as defined in RFC5764 has to be enabled.
265992f3ab15Sopenharmony_ci    #[corresponds(SSL_get_selected_srtp_profile)]
266092f3ab15Sopenharmony_ci    pub fn selected_srtp_profile(&self) -> Option<&SrtpProtectionProfileRef> {
266192f3ab15Sopenharmony_ci        unsafe {
266292f3ab15Sopenharmony_ci            let profile = ffi::SSL_get_selected_srtp_profile(self.as_ptr());
266392f3ab15Sopenharmony_ci
266492f3ab15Sopenharmony_ci            SrtpProtectionProfileRef::from_const_ptr_opt(profile)
266592f3ab15Sopenharmony_ci        }
266692f3ab15Sopenharmony_ci    }
266792f3ab15Sopenharmony_ci
266892f3ab15Sopenharmony_ci    /// Returns the number of bytes remaining in the currently processed TLS record.
266992f3ab15Sopenharmony_ci    ///
267092f3ab15Sopenharmony_ci    /// If this is greater than 0, the next call to `read` will not call down to the underlying
267192f3ab15Sopenharmony_ci    /// stream.
267292f3ab15Sopenharmony_ci    #[corresponds(SSL_pending)]
267392f3ab15Sopenharmony_ci    pub fn pending(&self) -> usize {
267492f3ab15Sopenharmony_ci        unsafe { ffi::SSL_pending(self.as_ptr()) as usize }
267592f3ab15Sopenharmony_ci    }
267692f3ab15Sopenharmony_ci
267792f3ab15Sopenharmony_ci    /// Returns the servername sent by the client via Server Name Indication (SNI).
267892f3ab15Sopenharmony_ci    ///
267992f3ab15Sopenharmony_ci    /// It is only useful on the server side.
268092f3ab15Sopenharmony_ci    ///
268192f3ab15Sopenharmony_ci    /// # Note
268292f3ab15Sopenharmony_ci    ///
268392f3ab15Sopenharmony_ci    /// While the SNI specification requires that servernames be valid domain names (and therefore
268492f3ab15Sopenharmony_ci    /// ASCII), OpenSSL does not enforce this restriction. If the servername provided by the client
268592f3ab15Sopenharmony_ci    /// is not valid UTF-8, this function will return `None`. The `servername_raw` method returns
268692f3ab15Sopenharmony_ci    /// the raw bytes and does not have this restriction.
268792f3ab15Sopenharmony_ci    ///
268892f3ab15Sopenharmony_ci    /// [`SSL_get_servername`]: https://www.openssl.org/docs/manmaster/man3/SSL_get_servername.html
268992f3ab15Sopenharmony_ci    #[corresponds(SSL_get_servername)]
269092f3ab15Sopenharmony_ci    // FIXME maybe rethink in 0.11?
269192f3ab15Sopenharmony_ci    pub fn servername(&self, type_: NameType) -> Option<&str> {
269292f3ab15Sopenharmony_ci        self.servername_raw(type_)
269392f3ab15Sopenharmony_ci            .and_then(|b| str::from_utf8(b).ok())
269492f3ab15Sopenharmony_ci    }
269592f3ab15Sopenharmony_ci
269692f3ab15Sopenharmony_ci    /// Returns the servername sent by the client via Server Name Indication (SNI).
269792f3ab15Sopenharmony_ci    ///
269892f3ab15Sopenharmony_ci    /// It is only useful on the server side.
269992f3ab15Sopenharmony_ci    ///
270092f3ab15Sopenharmony_ci    /// # Note
270192f3ab15Sopenharmony_ci    ///
270292f3ab15Sopenharmony_ci    /// Unlike `servername`, this method does not require the name be valid UTF-8.
270392f3ab15Sopenharmony_ci    #[corresponds(SSL_get_servername)]
270492f3ab15Sopenharmony_ci    pub fn servername_raw(&self, type_: NameType) -> Option<&[u8]> {
270592f3ab15Sopenharmony_ci        unsafe {
270692f3ab15Sopenharmony_ci            let name = ffi::SSL_get_servername(self.as_ptr(), type_.0);
270792f3ab15Sopenharmony_ci            if name.is_null() {
270892f3ab15Sopenharmony_ci                None
270992f3ab15Sopenharmony_ci            } else {
271092f3ab15Sopenharmony_ci                Some(CStr::from_ptr(name as *const _).to_bytes())
271192f3ab15Sopenharmony_ci            }
271292f3ab15Sopenharmony_ci        }
271392f3ab15Sopenharmony_ci    }
271492f3ab15Sopenharmony_ci
271592f3ab15Sopenharmony_ci    /// Changes the context corresponding to the current connection.
271692f3ab15Sopenharmony_ci    ///
271792f3ab15Sopenharmony_ci    /// It is most commonly used in the Server Name Indication (SNI) callback.
271892f3ab15Sopenharmony_ci    #[corresponds(SSL_set_SSL_CTX)]
271992f3ab15Sopenharmony_ci    pub fn set_ssl_context(&mut self, ctx: &SslContextRef) -> Result<(), ErrorStack> {
272092f3ab15Sopenharmony_ci        unsafe { cvt_p(ffi::SSL_set_SSL_CTX(self.as_ptr(), ctx.as_ptr())).map(|_| ()) }
272192f3ab15Sopenharmony_ci    }
272292f3ab15Sopenharmony_ci
272392f3ab15Sopenharmony_ci    /// Returns the context corresponding to the current connection.
272492f3ab15Sopenharmony_ci    #[corresponds(SSL_get_SSL_CTX)]
272592f3ab15Sopenharmony_ci    pub fn ssl_context(&self) -> &SslContextRef {
272692f3ab15Sopenharmony_ci        unsafe {
272792f3ab15Sopenharmony_ci            let ssl_ctx = ffi::SSL_get_SSL_CTX(self.as_ptr());
272892f3ab15Sopenharmony_ci            SslContextRef::from_ptr(ssl_ctx)
272992f3ab15Sopenharmony_ci        }
273092f3ab15Sopenharmony_ci    }
273192f3ab15Sopenharmony_ci
273292f3ab15Sopenharmony_ci    /// Returns a mutable reference to the X509 verification configuration.
273392f3ab15Sopenharmony_ci    ///
273492f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.0.2 or newer.
273592f3ab15Sopenharmony_ci    #[corresponds(SSL_get0_param)]
273692f3ab15Sopenharmony_ci    #[cfg(any(ossl102, libressl261))]
273792f3ab15Sopenharmony_ci    pub fn param_mut(&mut self) -> &mut X509VerifyParamRef {
273892f3ab15Sopenharmony_ci        unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_get0_param(self.as_ptr())) }
273992f3ab15Sopenharmony_ci    }
274092f3ab15Sopenharmony_ci
274192f3ab15Sopenharmony_ci    /// Returns the certificate verification result.
274292f3ab15Sopenharmony_ci    #[corresponds(SSL_get_verify_result)]
274392f3ab15Sopenharmony_ci    pub fn verify_result(&self) -> X509VerifyResult {
274492f3ab15Sopenharmony_ci        unsafe { X509VerifyResult::from_raw(ffi::SSL_get_verify_result(self.as_ptr()) as c_int) }
274592f3ab15Sopenharmony_ci    }
274692f3ab15Sopenharmony_ci
274792f3ab15Sopenharmony_ci    /// Returns a shared reference to the SSL session.
274892f3ab15Sopenharmony_ci    #[corresponds(SSL_get_session)]
274992f3ab15Sopenharmony_ci    pub fn session(&self) -> Option<&SslSessionRef> {
275092f3ab15Sopenharmony_ci        unsafe {
275192f3ab15Sopenharmony_ci            let p = ffi::SSL_get_session(self.as_ptr());
275292f3ab15Sopenharmony_ci            SslSessionRef::from_const_ptr_opt(p)
275392f3ab15Sopenharmony_ci        }
275492f3ab15Sopenharmony_ci    }
275592f3ab15Sopenharmony_ci
275692f3ab15Sopenharmony_ci    /// Copies the `client_random` value sent by the client in the TLS handshake into a buffer.
275792f3ab15Sopenharmony_ci    ///
275892f3ab15Sopenharmony_ci    /// Returns the number of bytes copied, or if the buffer is empty, the size of the `client_random`
275992f3ab15Sopenharmony_ci    /// value.
276092f3ab15Sopenharmony_ci    ///
276192f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.1.0 or LibreSSL 2.7.0 or newer.
276292f3ab15Sopenharmony_ci    #[corresponds(SSL_get_client_random)]
276392f3ab15Sopenharmony_ci    #[cfg(any(ossl110, libressl270))]
276492f3ab15Sopenharmony_ci    pub fn client_random(&self, buf: &mut [u8]) -> usize {
276592f3ab15Sopenharmony_ci        unsafe {
276692f3ab15Sopenharmony_ci            ffi::SSL_get_client_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
276792f3ab15Sopenharmony_ci        }
276892f3ab15Sopenharmony_ci    }
276992f3ab15Sopenharmony_ci
277092f3ab15Sopenharmony_ci    /// Copies the `server_random` value sent by the server in the TLS handshake into a buffer.
277192f3ab15Sopenharmony_ci    ///
277292f3ab15Sopenharmony_ci    /// Returns the number of bytes copied, or if the buffer is empty, the size of the `server_random`
277392f3ab15Sopenharmony_ci    /// value.
277492f3ab15Sopenharmony_ci    ///
277592f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.1.0 or LibreSSL 2.7.0 or newer.
277692f3ab15Sopenharmony_ci    #[corresponds(SSL_get_server_random)]
277792f3ab15Sopenharmony_ci    #[cfg(any(ossl110, libressl270))]
277892f3ab15Sopenharmony_ci    pub fn server_random(&self, buf: &mut [u8]) -> usize {
277992f3ab15Sopenharmony_ci        unsafe {
278092f3ab15Sopenharmony_ci            ffi::SSL_get_server_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
278192f3ab15Sopenharmony_ci        }
278292f3ab15Sopenharmony_ci    }
278392f3ab15Sopenharmony_ci
278492f3ab15Sopenharmony_ci    /// Derives keying material for application use in accordance to RFC 5705.
278592f3ab15Sopenharmony_ci    #[corresponds(SSL_export_keying_material)]
278692f3ab15Sopenharmony_ci    pub fn export_keying_material(
278792f3ab15Sopenharmony_ci        &self,
278892f3ab15Sopenharmony_ci        out: &mut [u8],
278992f3ab15Sopenharmony_ci        label: &str,
279092f3ab15Sopenharmony_ci        context: Option<&[u8]>,
279192f3ab15Sopenharmony_ci    ) -> Result<(), ErrorStack> {
279292f3ab15Sopenharmony_ci        unsafe {
279392f3ab15Sopenharmony_ci            let (context, contextlen, use_context) = match context {
279492f3ab15Sopenharmony_ci                Some(context) => (context.as_ptr() as *const c_uchar, context.len(), 1),
279592f3ab15Sopenharmony_ci                None => (ptr::null(), 0, 0),
279692f3ab15Sopenharmony_ci            };
279792f3ab15Sopenharmony_ci            cvt(ffi::SSL_export_keying_material(
279892f3ab15Sopenharmony_ci                self.as_ptr(),
279992f3ab15Sopenharmony_ci                out.as_mut_ptr() as *mut c_uchar,
280092f3ab15Sopenharmony_ci                out.len(),
280192f3ab15Sopenharmony_ci                label.as_ptr() as *const c_char,
280292f3ab15Sopenharmony_ci                label.len(),
280392f3ab15Sopenharmony_ci                context,
280492f3ab15Sopenharmony_ci                contextlen,
280592f3ab15Sopenharmony_ci                use_context,
280692f3ab15Sopenharmony_ci            ))
280792f3ab15Sopenharmony_ci            .map(|_| ())
280892f3ab15Sopenharmony_ci        }
280992f3ab15Sopenharmony_ci    }
281092f3ab15Sopenharmony_ci
281192f3ab15Sopenharmony_ci    /// Derives keying material for application use in accordance to RFC 5705.
281292f3ab15Sopenharmony_ci    ///
281392f3ab15Sopenharmony_ci    /// This function is only usable with TLSv1.3, wherein there is no distinction between an empty context and no
281492f3ab15Sopenharmony_ci    /// context. Therefore, unlike `export_keying_material`, `context` must always be supplied.
281592f3ab15Sopenharmony_ci    ///
281692f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.1.1 or newer.
281792f3ab15Sopenharmony_ci    #[corresponds(SSL_export_keying_material_early)]
281892f3ab15Sopenharmony_ci    #[cfg(ossl111)]
281992f3ab15Sopenharmony_ci    pub fn export_keying_material_early(
282092f3ab15Sopenharmony_ci        &self,
282192f3ab15Sopenharmony_ci        out: &mut [u8],
282292f3ab15Sopenharmony_ci        label: &str,
282392f3ab15Sopenharmony_ci        context: &[u8],
282492f3ab15Sopenharmony_ci    ) -> Result<(), ErrorStack> {
282592f3ab15Sopenharmony_ci        unsafe {
282692f3ab15Sopenharmony_ci            cvt(ffi::SSL_export_keying_material_early(
282792f3ab15Sopenharmony_ci                self.as_ptr(),
282892f3ab15Sopenharmony_ci                out.as_mut_ptr() as *mut c_uchar,
282992f3ab15Sopenharmony_ci                out.len(),
283092f3ab15Sopenharmony_ci                label.as_ptr() as *const c_char,
283192f3ab15Sopenharmony_ci                label.len(),
283292f3ab15Sopenharmony_ci                context.as_ptr() as *const c_uchar,
283392f3ab15Sopenharmony_ci                context.len(),
283492f3ab15Sopenharmony_ci            ))
283592f3ab15Sopenharmony_ci            .map(|_| ())
283692f3ab15Sopenharmony_ci        }
283792f3ab15Sopenharmony_ci    }
283892f3ab15Sopenharmony_ci
283992f3ab15Sopenharmony_ci    /// Sets the session to be used.
284092f3ab15Sopenharmony_ci    ///
284192f3ab15Sopenharmony_ci    /// This should be called before the handshake to attempt to reuse a previously established
284292f3ab15Sopenharmony_ci    /// session. If the server is not willing to reuse the session, a new one will be transparently
284392f3ab15Sopenharmony_ci    /// negotiated.
284492f3ab15Sopenharmony_ci    ///
284592f3ab15Sopenharmony_ci    /// # Safety
284692f3ab15Sopenharmony_ci    ///
284792f3ab15Sopenharmony_ci    /// The caller of this method is responsible for ensuring that the session is associated
284892f3ab15Sopenharmony_ci    /// with the same `SslContext` as this `Ssl`.
284992f3ab15Sopenharmony_ci    #[corresponds(SSL_set_session)]
285092f3ab15Sopenharmony_ci    pub unsafe fn set_session(&mut self, session: &SslSessionRef) -> Result<(), ErrorStack> {
285192f3ab15Sopenharmony_ci        cvt(ffi::SSL_set_session(self.as_ptr(), session.as_ptr())).map(|_| ())
285292f3ab15Sopenharmony_ci    }
285392f3ab15Sopenharmony_ci
285492f3ab15Sopenharmony_ci    /// Determines if the session provided to `set_session` was successfully reused.
285592f3ab15Sopenharmony_ci    #[corresponds(SSL_session_reused)]
285692f3ab15Sopenharmony_ci    pub fn session_reused(&self) -> bool {
285792f3ab15Sopenharmony_ci        unsafe { ffi::SSL_session_reused(self.as_ptr()) != 0 }
285892f3ab15Sopenharmony_ci    }
285992f3ab15Sopenharmony_ci
286092f3ab15Sopenharmony_ci    /// Sets the status response a client wishes the server to reply with.
286192f3ab15Sopenharmony_ci    #[corresponds(SSL_set_tlsext_status_type)]
286292f3ab15Sopenharmony_ci    pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> {
286392f3ab15Sopenharmony_ci        unsafe {
286492f3ab15Sopenharmony_ci            cvt(ffi::SSL_set_tlsext_status_type(self.as_ptr(), type_.as_raw()) as c_int).map(|_| ())
286592f3ab15Sopenharmony_ci        }
286692f3ab15Sopenharmony_ci    }
286792f3ab15Sopenharmony_ci
286892f3ab15Sopenharmony_ci    /// Determines if current session used Extended Master Secret
286992f3ab15Sopenharmony_ci    ///
287092f3ab15Sopenharmony_ci    /// Returns `None` if the handshake is still in-progress.
287192f3ab15Sopenharmony_ci    #[corresponds(SSL_get_extms_support)]
287292f3ab15Sopenharmony_ci    #[cfg(ossl110)]
287392f3ab15Sopenharmony_ci    pub fn extms_support(&self) -> Option<bool> {
287492f3ab15Sopenharmony_ci        unsafe {
287592f3ab15Sopenharmony_ci            match ffi::SSL_get_extms_support(self.as_ptr()) {
287692f3ab15Sopenharmony_ci                -1 => None,
287792f3ab15Sopenharmony_ci                ret => Some(ret != 0),
287892f3ab15Sopenharmony_ci            }
287992f3ab15Sopenharmony_ci        }
288092f3ab15Sopenharmony_ci    }
288192f3ab15Sopenharmony_ci
288292f3ab15Sopenharmony_ci    /// Returns the server's OCSP response, if present.
288392f3ab15Sopenharmony_ci    #[corresponds(SSL_get_tlsext_status_ocsp_resp)]
288492f3ab15Sopenharmony_ci    #[cfg(not(boringssl))]
288592f3ab15Sopenharmony_ci    pub fn ocsp_status(&self) -> Option<&[u8]> {
288692f3ab15Sopenharmony_ci        unsafe {
288792f3ab15Sopenharmony_ci            let mut p = ptr::null_mut();
288892f3ab15Sopenharmony_ci            let len = ffi::SSL_get_tlsext_status_ocsp_resp(self.as_ptr(), &mut p);
288992f3ab15Sopenharmony_ci
289092f3ab15Sopenharmony_ci            if len < 0 {
289192f3ab15Sopenharmony_ci                None
289292f3ab15Sopenharmony_ci            } else {
289392f3ab15Sopenharmony_ci                Some(slice::from_raw_parts(p as *const u8, len as usize))
289492f3ab15Sopenharmony_ci            }
289592f3ab15Sopenharmony_ci        }
289692f3ab15Sopenharmony_ci    }
289792f3ab15Sopenharmony_ci
289892f3ab15Sopenharmony_ci    /// Sets the OCSP response to be returned to the client.
289992f3ab15Sopenharmony_ci    #[corresponds(SSL_set_tlsext_status_oscp_resp)]
290092f3ab15Sopenharmony_ci    #[cfg(not(boringssl))]
290192f3ab15Sopenharmony_ci    pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> {
290292f3ab15Sopenharmony_ci        unsafe {
290392f3ab15Sopenharmony_ci            assert!(response.len() <= c_int::max_value() as usize);
290492f3ab15Sopenharmony_ci            let p = cvt_p(ffi::OPENSSL_malloc(response.len() as _))?;
290592f3ab15Sopenharmony_ci            ptr::copy_nonoverlapping(response.as_ptr(), p as *mut u8, response.len());
290692f3ab15Sopenharmony_ci            cvt(ffi::SSL_set_tlsext_status_ocsp_resp(
290792f3ab15Sopenharmony_ci                self.as_ptr(),
290892f3ab15Sopenharmony_ci                p as *mut c_uchar,
290992f3ab15Sopenharmony_ci                response.len() as c_long,
291092f3ab15Sopenharmony_ci            ) as c_int)
291192f3ab15Sopenharmony_ci            .map(|_| ())
291292f3ab15Sopenharmony_ci            .map_err(|e| {
291392f3ab15Sopenharmony_ci                ffi::OPENSSL_free(p);
291492f3ab15Sopenharmony_ci                e
291592f3ab15Sopenharmony_ci            })
291692f3ab15Sopenharmony_ci        }
291792f3ab15Sopenharmony_ci    }
291892f3ab15Sopenharmony_ci
291992f3ab15Sopenharmony_ci    /// Determines if this `Ssl` is configured for server-side or client-side use.
292092f3ab15Sopenharmony_ci    #[corresponds(SSL_is_server)]
292192f3ab15Sopenharmony_ci    pub fn is_server(&self) -> bool {
292292f3ab15Sopenharmony_ci        unsafe { SSL_is_server(self.as_ptr()) != 0 }
292392f3ab15Sopenharmony_ci    }
292492f3ab15Sopenharmony_ci
292592f3ab15Sopenharmony_ci    /// Sets the extra data at the specified index.
292692f3ab15Sopenharmony_ci    ///
292792f3ab15Sopenharmony_ci    /// This can be used to provide data to callbacks registered with the context. Use the
292892f3ab15Sopenharmony_ci    /// `Ssl::new_ex_index` method to create an `Index`.
292992f3ab15Sopenharmony_ci    #[corresponds(SSL_set_ex_data)]
293092f3ab15Sopenharmony_ci    pub fn set_ex_data<T>(&mut self, index: Index<Ssl, T>, data: T) {
293192f3ab15Sopenharmony_ci        unsafe {
293292f3ab15Sopenharmony_ci            let data = Box::new(data);
293392f3ab15Sopenharmony_ci            ffi::SSL_set_ex_data(
293492f3ab15Sopenharmony_ci                self.as_ptr(),
293592f3ab15Sopenharmony_ci                index.as_raw(),
293692f3ab15Sopenharmony_ci                Box::into_raw(data) as *mut c_void,
293792f3ab15Sopenharmony_ci            );
293892f3ab15Sopenharmony_ci        }
293992f3ab15Sopenharmony_ci    }
294092f3ab15Sopenharmony_ci
294192f3ab15Sopenharmony_ci    /// Returns a reference to the extra data at the specified index.
294292f3ab15Sopenharmony_ci    #[corresponds(SSL_get_ex_data)]
294392f3ab15Sopenharmony_ci    pub fn ex_data<T>(&self, index: Index<Ssl, T>) -> Option<&T> {
294492f3ab15Sopenharmony_ci        unsafe {
294592f3ab15Sopenharmony_ci            let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
294692f3ab15Sopenharmony_ci            if data.is_null() {
294792f3ab15Sopenharmony_ci                None
294892f3ab15Sopenharmony_ci            } else {
294992f3ab15Sopenharmony_ci                Some(&*(data as *const T))
295092f3ab15Sopenharmony_ci            }
295192f3ab15Sopenharmony_ci        }
295292f3ab15Sopenharmony_ci    }
295392f3ab15Sopenharmony_ci
295492f3ab15Sopenharmony_ci    /// Returns a mutable reference to the extra data at the specified index.
295592f3ab15Sopenharmony_ci    #[corresponds(SSL_get_ex_data)]
295692f3ab15Sopenharmony_ci    pub fn ex_data_mut<T>(&mut self, index: Index<Ssl, T>) -> Option<&mut T> {
295792f3ab15Sopenharmony_ci        unsafe {
295892f3ab15Sopenharmony_ci            let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
295992f3ab15Sopenharmony_ci            if data.is_null() {
296092f3ab15Sopenharmony_ci                None
296192f3ab15Sopenharmony_ci            } else {
296292f3ab15Sopenharmony_ci                Some(&mut *(data as *mut T))
296392f3ab15Sopenharmony_ci            }
296492f3ab15Sopenharmony_ci        }
296592f3ab15Sopenharmony_ci    }
296692f3ab15Sopenharmony_ci
296792f3ab15Sopenharmony_ci    /// Sets the maximum amount of early data that will be accepted on this connection.
296892f3ab15Sopenharmony_ci    ///
296992f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer.
297092f3ab15Sopenharmony_ci    #[corresponds(SSL_set_max_early_data)]
297192f3ab15Sopenharmony_ci    #[cfg(any(ossl111, libressl340))]
297292f3ab15Sopenharmony_ci    pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
297392f3ab15Sopenharmony_ci        if unsafe { ffi::SSL_set_max_early_data(self.as_ptr(), bytes) } == 1 {
297492f3ab15Sopenharmony_ci            Ok(())
297592f3ab15Sopenharmony_ci        } else {
297692f3ab15Sopenharmony_ci            Err(ErrorStack::get())
297792f3ab15Sopenharmony_ci        }
297892f3ab15Sopenharmony_ci    }
297992f3ab15Sopenharmony_ci
298092f3ab15Sopenharmony_ci    /// Gets the maximum amount of early data that can be sent on this connection.
298192f3ab15Sopenharmony_ci    ///
298292f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer.
298392f3ab15Sopenharmony_ci    #[corresponds(SSL_get_max_early_data)]
298492f3ab15Sopenharmony_ci    #[cfg(any(ossl111, libressl340))]
298592f3ab15Sopenharmony_ci    pub fn max_early_data(&self) -> u32 {
298692f3ab15Sopenharmony_ci        unsafe { ffi::SSL_get_max_early_data(self.as_ptr()) }
298792f3ab15Sopenharmony_ci    }
298892f3ab15Sopenharmony_ci
298992f3ab15Sopenharmony_ci    /// Copies the contents of the last Finished message sent to the peer into the provided buffer.
299092f3ab15Sopenharmony_ci    ///
299192f3ab15Sopenharmony_ci    /// The total size of the message is returned, so this can be used to determine the size of the
299292f3ab15Sopenharmony_ci    /// buffer required.
299392f3ab15Sopenharmony_ci    #[corresponds(SSL_get_finished)]
299492f3ab15Sopenharmony_ci    pub fn finished(&self, buf: &mut [u8]) -> usize {
299592f3ab15Sopenharmony_ci        unsafe { ffi::SSL_get_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len()) }
299692f3ab15Sopenharmony_ci    }
299792f3ab15Sopenharmony_ci
299892f3ab15Sopenharmony_ci    /// Copies the contents of the last Finished message received from the peer into the provided
299992f3ab15Sopenharmony_ci    /// buffer.
300092f3ab15Sopenharmony_ci    ///
300192f3ab15Sopenharmony_ci    /// The total size of the message is returned, so this can be used to determine the size of the
300292f3ab15Sopenharmony_ci    /// buffer required.
300392f3ab15Sopenharmony_ci    #[corresponds(SSL_get_peer_finished)]
300492f3ab15Sopenharmony_ci    pub fn peer_finished(&self, buf: &mut [u8]) -> usize {
300592f3ab15Sopenharmony_ci        unsafe {
300692f3ab15Sopenharmony_ci            ffi::SSL_get_peer_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len())
300792f3ab15Sopenharmony_ci        }
300892f3ab15Sopenharmony_ci    }
300992f3ab15Sopenharmony_ci
301092f3ab15Sopenharmony_ci    /// Determines if the initial handshake has been completed.
301192f3ab15Sopenharmony_ci    #[corresponds(SSL_is_init_finished)]
301292f3ab15Sopenharmony_ci    #[cfg(ossl110)]
301392f3ab15Sopenharmony_ci    pub fn is_init_finished(&self) -> bool {
301492f3ab15Sopenharmony_ci        unsafe { ffi::SSL_is_init_finished(self.as_ptr()) != 0 }
301592f3ab15Sopenharmony_ci    }
301692f3ab15Sopenharmony_ci
301792f3ab15Sopenharmony_ci    /// Determines if the client's hello message is in the SSLv2 format.
301892f3ab15Sopenharmony_ci    ///
301992f3ab15Sopenharmony_ci    /// This can only be used inside of the client hello callback. Otherwise, `false` is returned.
302092f3ab15Sopenharmony_ci    ///
302192f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.1.1 or newer.
302292f3ab15Sopenharmony_ci    #[corresponds(SSL_client_hello_isv2)]
302392f3ab15Sopenharmony_ci    #[cfg(ossl111)]
302492f3ab15Sopenharmony_ci    pub fn client_hello_isv2(&self) -> bool {
302592f3ab15Sopenharmony_ci        unsafe { ffi::SSL_client_hello_isv2(self.as_ptr()) != 0 }
302692f3ab15Sopenharmony_ci    }
302792f3ab15Sopenharmony_ci
302892f3ab15Sopenharmony_ci    /// Returns the legacy version field of the client's hello message.
302992f3ab15Sopenharmony_ci    ///
303092f3ab15Sopenharmony_ci    /// This can only be used inside of the client hello callback. Otherwise, `None` is returned.
303192f3ab15Sopenharmony_ci    ///
303292f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.1.1 or newer.
303392f3ab15Sopenharmony_ci    #[corresponds(SSL_client_hello_get0_legacy_version)]
303492f3ab15Sopenharmony_ci    #[cfg(ossl111)]
303592f3ab15Sopenharmony_ci    pub fn client_hello_legacy_version(&self) -> Option<SslVersion> {
303692f3ab15Sopenharmony_ci        unsafe {
303792f3ab15Sopenharmony_ci            let version = ffi::SSL_client_hello_get0_legacy_version(self.as_ptr());
303892f3ab15Sopenharmony_ci            if version == 0 {
303992f3ab15Sopenharmony_ci                None
304092f3ab15Sopenharmony_ci            } else {
304192f3ab15Sopenharmony_ci                Some(SslVersion(version as c_int))
304292f3ab15Sopenharmony_ci            }
304392f3ab15Sopenharmony_ci        }
304492f3ab15Sopenharmony_ci    }
304592f3ab15Sopenharmony_ci
304692f3ab15Sopenharmony_ci    /// Returns the random field of the client's hello message.
304792f3ab15Sopenharmony_ci    ///
304892f3ab15Sopenharmony_ci    /// This can only be used inside of the client hello callback. Otherwise, `None` is returned.
304992f3ab15Sopenharmony_ci    ///
305092f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.1.1 or newer.
305192f3ab15Sopenharmony_ci    #[corresponds(SSL_client_hello_get0_random)]
305292f3ab15Sopenharmony_ci    #[cfg(ossl111)]
305392f3ab15Sopenharmony_ci    pub fn client_hello_random(&self) -> Option<&[u8]> {
305492f3ab15Sopenharmony_ci        unsafe {
305592f3ab15Sopenharmony_ci            let mut ptr = ptr::null();
305692f3ab15Sopenharmony_ci            let len = ffi::SSL_client_hello_get0_random(self.as_ptr(), &mut ptr);
305792f3ab15Sopenharmony_ci            if len == 0 {
305892f3ab15Sopenharmony_ci                None
305992f3ab15Sopenharmony_ci            } else {
306092f3ab15Sopenharmony_ci                Some(slice::from_raw_parts(ptr, len))
306192f3ab15Sopenharmony_ci            }
306292f3ab15Sopenharmony_ci        }
306392f3ab15Sopenharmony_ci    }
306492f3ab15Sopenharmony_ci
306592f3ab15Sopenharmony_ci    /// Returns the session ID field of the client's hello message.
306692f3ab15Sopenharmony_ci    ///
306792f3ab15Sopenharmony_ci    /// This can only be used inside of the client hello callback. Otherwise, `None` is returned.
306892f3ab15Sopenharmony_ci    ///
306992f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.1.1 or newer.
307092f3ab15Sopenharmony_ci    #[corresponds(SSL_client_hello_get0_session_id)]
307192f3ab15Sopenharmony_ci    #[cfg(ossl111)]
307292f3ab15Sopenharmony_ci    pub fn client_hello_session_id(&self) -> Option<&[u8]> {
307392f3ab15Sopenharmony_ci        unsafe {
307492f3ab15Sopenharmony_ci            let mut ptr = ptr::null();
307592f3ab15Sopenharmony_ci            let len = ffi::SSL_client_hello_get0_session_id(self.as_ptr(), &mut ptr);
307692f3ab15Sopenharmony_ci            if len == 0 {
307792f3ab15Sopenharmony_ci                None
307892f3ab15Sopenharmony_ci            } else {
307992f3ab15Sopenharmony_ci                Some(slice::from_raw_parts(ptr, len))
308092f3ab15Sopenharmony_ci            }
308192f3ab15Sopenharmony_ci        }
308292f3ab15Sopenharmony_ci    }
308392f3ab15Sopenharmony_ci
308492f3ab15Sopenharmony_ci    /// Returns the ciphers field of the client's hello message.
308592f3ab15Sopenharmony_ci    ///
308692f3ab15Sopenharmony_ci    /// This can only be used inside of the client hello callback. Otherwise, `None` is returned.
308792f3ab15Sopenharmony_ci    ///
308892f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.1.1 or newer.
308992f3ab15Sopenharmony_ci    #[corresponds(SSL_client_hello_get0_ciphers)]
309092f3ab15Sopenharmony_ci    #[cfg(ossl111)]
309192f3ab15Sopenharmony_ci    pub fn client_hello_ciphers(&self) -> Option<&[u8]> {
309292f3ab15Sopenharmony_ci        unsafe {
309392f3ab15Sopenharmony_ci            let mut ptr = ptr::null();
309492f3ab15Sopenharmony_ci            let len = ffi::SSL_client_hello_get0_ciphers(self.as_ptr(), &mut ptr);
309592f3ab15Sopenharmony_ci            if len == 0 {
309692f3ab15Sopenharmony_ci                None
309792f3ab15Sopenharmony_ci            } else {
309892f3ab15Sopenharmony_ci                Some(slice::from_raw_parts(ptr, len))
309992f3ab15Sopenharmony_ci            }
310092f3ab15Sopenharmony_ci        }
310192f3ab15Sopenharmony_ci    }
310292f3ab15Sopenharmony_ci
310392f3ab15Sopenharmony_ci    /// Decodes a slice of wire-format cipher suite specification bytes. Unsupported cipher suites
310492f3ab15Sopenharmony_ci    /// are ignored.
310592f3ab15Sopenharmony_ci    ///
310692f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.1.1 or newer.
310792f3ab15Sopenharmony_ci    #[corresponds(SSL_bytes_to_cipher_list)]
310892f3ab15Sopenharmony_ci    #[cfg(ossl111)]
310992f3ab15Sopenharmony_ci    pub fn bytes_to_cipher_list(
311092f3ab15Sopenharmony_ci        &self,
311192f3ab15Sopenharmony_ci        bytes: &[u8],
311292f3ab15Sopenharmony_ci        isv2format: bool,
311392f3ab15Sopenharmony_ci    ) -> Result<CipherLists, ErrorStack> {
311492f3ab15Sopenharmony_ci        unsafe {
311592f3ab15Sopenharmony_ci            let ptr = bytes.as_ptr();
311692f3ab15Sopenharmony_ci            let len = bytes.len();
311792f3ab15Sopenharmony_ci            let mut sk = ptr::null_mut();
311892f3ab15Sopenharmony_ci            let mut scsvs = ptr::null_mut();
311992f3ab15Sopenharmony_ci            let res = ffi::SSL_bytes_to_cipher_list(
312092f3ab15Sopenharmony_ci                self.as_ptr(),
312192f3ab15Sopenharmony_ci                ptr,
312292f3ab15Sopenharmony_ci                len,
312392f3ab15Sopenharmony_ci                isv2format as c_int,
312492f3ab15Sopenharmony_ci                &mut sk,
312592f3ab15Sopenharmony_ci                &mut scsvs,
312692f3ab15Sopenharmony_ci            );
312792f3ab15Sopenharmony_ci            if res == 1 {
312892f3ab15Sopenharmony_ci                Ok(CipherLists {
312992f3ab15Sopenharmony_ci                    suites: Stack::from_ptr(sk),
313092f3ab15Sopenharmony_ci                    signalling_suites: Stack::from_ptr(scsvs),
313192f3ab15Sopenharmony_ci                })
313292f3ab15Sopenharmony_ci            } else {
313392f3ab15Sopenharmony_ci                Err(ErrorStack::get())
313492f3ab15Sopenharmony_ci            }
313592f3ab15Sopenharmony_ci        }
313692f3ab15Sopenharmony_ci    }
313792f3ab15Sopenharmony_ci
313892f3ab15Sopenharmony_ci    /// Returns the compression methods field of the client's hello message.
313992f3ab15Sopenharmony_ci    ///
314092f3ab15Sopenharmony_ci    /// This can only be used inside of the client hello callback. Otherwise, `None` is returned.
314192f3ab15Sopenharmony_ci    ///
314292f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.1.1 or newer.
314392f3ab15Sopenharmony_ci    #[corresponds(SSL_client_hello_get0_compression_methods)]
314492f3ab15Sopenharmony_ci    #[cfg(ossl111)]
314592f3ab15Sopenharmony_ci    pub fn client_hello_compression_methods(&self) -> Option<&[u8]> {
314692f3ab15Sopenharmony_ci        unsafe {
314792f3ab15Sopenharmony_ci            let mut ptr = ptr::null();
314892f3ab15Sopenharmony_ci            let len = ffi::SSL_client_hello_get0_compression_methods(self.as_ptr(), &mut ptr);
314992f3ab15Sopenharmony_ci            if len == 0 {
315092f3ab15Sopenharmony_ci                None
315192f3ab15Sopenharmony_ci            } else {
315292f3ab15Sopenharmony_ci                Some(slice::from_raw_parts(ptr, len))
315392f3ab15Sopenharmony_ci            }
315492f3ab15Sopenharmony_ci        }
315592f3ab15Sopenharmony_ci    }
315692f3ab15Sopenharmony_ci
315792f3ab15Sopenharmony_ci    /// Sets the MTU used for DTLS connections.
315892f3ab15Sopenharmony_ci    #[corresponds(SSL_set_mtu)]
315992f3ab15Sopenharmony_ci    pub fn set_mtu(&mut self, mtu: u32) -> Result<(), ErrorStack> {
316092f3ab15Sopenharmony_ci        unsafe { cvt(ffi::SSL_set_mtu(self.as_ptr(), mtu as MtuTy) as c_int).map(|_| ()) }
316192f3ab15Sopenharmony_ci    }
316292f3ab15Sopenharmony_ci
316392f3ab15Sopenharmony_ci    /// Returns the PSK identity hint used during connection setup.
316492f3ab15Sopenharmony_ci    ///
316592f3ab15Sopenharmony_ci    /// May return `None` if no PSK identity hint was used during the connection setup.
316692f3ab15Sopenharmony_ci    #[corresponds(SSL_get_psk_identity_hint)]
316792f3ab15Sopenharmony_ci    #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
316892f3ab15Sopenharmony_ci    pub fn psk_identity_hint(&self) -> Option<&[u8]> {
316992f3ab15Sopenharmony_ci        unsafe {
317092f3ab15Sopenharmony_ci            let ptr = ffi::SSL_get_psk_identity_hint(self.as_ptr());
317192f3ab15Sopenharmony_ci            if ptr.is_null() {
317292f3ab15Sopenharmony_ci                None
317392f3ab15Sopenharmony_ci            } else {
317492f3ab15Sopenharmony_ci                Some(CStr::from_ptr(ptr).to_bytes())
317592f3ab15Sopenharmony_ci            }
317692f3ab15Sopenharmony_ci        }
317792f3ab15Sopenharmony_ci    }
317892f3ab15Sopenharmony_ci
317992f3ab15Sopenharmony_ci    /// Returns the PSK identity used during connection setup.
318092f3ab15Sopenharmony_ci    #[corresponds(SSL_get_psk_identity)]
318192f3ab15Sopenharmony_ci    #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
318292f3ab15Sopenharmony_ci    pub fn psk_identity(&self) -> Option<&[u8]> {
318392f3ab15Sopenharmony_ci        unsafe {
318492f3ab15Sopenharmony_ci            let ptr = ffi::SSL_get_psk_identity(self.as_ptr());
318592f3ab15Sopenharmony_ci            if ptr.is_null() {
318692f3ab15Sopenharmony_ci                None
318792f3ab15Sopenharmony_ci            } else {
318892f3ab15Sopenharmony_ci                Some(CStr::from_ptr(ptr).to_bytes())
318992f3ab15Sopenharmony_ci            }
319092f3ab15Sopenharmony_ci        }
319192f3ab15Sopenharmony_ci    }
319292f3ab15Sopenharmony_ci
319392f3ab15Sopenharmony_ci    #[corresponds(SSL_add0_chain_cert)]
319492f3ab15Sopenharmony_ci    #[cfg(ossl102)]
319592f3ab15Sopenharmony_ci    pub fn add_chain_cert(&mut self, chain: X509) -> Result<(), ErrorStack> {
319692f3ab15Sopenharmony_ci        unsafe {
319792f3ab15Sopenharmony_ci            cvt(ffi::SSL_add0_chain_cert(self.as_ptr(), chain.as_ptr()) as c_int).map(|_| ())?;
319892f3ab15Sopenharmony_ci            mem::forget(chain);
319992f3ab15Sopenharmony_ci        }
320092f3ab15Sopenharmony_ci        Ok(())
320192f3ab15Sopenharmony_ci    }
320292f3ab15Sopenharmony_ci
320392f3ab15Sopenharmony_ci    /// Sets a new default TLS/SSL method for SSL objects
320492f3ab15Sopenharmony_ci    #[cfg(not(boringssl))]
320592f3ab15Sopenharmony_ci    pub fn set_method(&mut self, method: SslMethod) -> Result<(), ErrorStack> {
320692f3ab15Sopenharmony_ci        unsafe {
320792f3ab15Sopenharmony_ci            cvt(ffi::SSL_set_ssl_method(self.as_ptr(), method.as_ptr()))?;
320892f3ab15Sopenharmony_ci        };
320992f3ab15Sopenharmony_ci        Ok(())
321092f3ab15Sopenharmony_ci    }
321192f3ab15Sopenharmony_ci
321292f3ab15Sopenharmony_ci    /// Loads the private key from a file.
321392f3ab15Sopenharmony_ci    #[corresponds(SSL_use_Private_Key_file)]
321492f3ab15Sopenharmony_ci    pub fn set_private_key_file<P: AsRef<Path>>(
321592f3ab15Sopenharmony_ci        &mut self,
321692f3ab15Sopenharmony_ci        path: P,
321792f3ab15Sopenharmony_ci        ssl_file_type: SslFiletype,
321892f3ab15Sopenharmony_ci    ) -> Result<(), ErrorStack> {
321992f3ab15Sopenharmony_ci        let p = path.as_ref().as_os_str().to_str().unwrap();
322092f3ab15Sopenharmony_ci        let key_file = CString::new(p).unwrap();
322192f3ab15Sopenharmony_ci        unsafe {
322292f3ab15Sopenharmony_ci            cvt(ffi::SSL_use_PrivateKey_file(
322392f3ab15Sopenharmony_ci                self.as_ptr(),
322492f3ab15Sopenharmony_ci                key_file.as_ptr(),
322592f3ab15Sopenharmony_ci                ssl_file_type.as_raw(),
322692f3ab15Sopenharmony_ci            ))?;
322792f3ab15Sopenharmony_ci        };
322892f3ab15Sopenharmony_ci        Ok(())
322992f3ab15Sopenharmony_ci    }
323092f3ab15Sopenharmony_ci
323192f3ab15Sopenharmony_ci    /// Sets the private key.
323292f3ab15Sopenharmony_ci    #[corresponds(SSL_use_PrivateKey)]
323392f3ab15Sopenharmony_ci    pub fn set_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
323492f3ab15Sopenharmony_ci        unsafe {
323592f3ab15Sopenharmony_ci            cvt(ffi::SSL_use_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
323692f3ab15Sopenharmony_ci        };
323792f3ab15Sopenharmony_ci        Ok(())
323892f3ab15Sopenharmony_ci    }
323992f3ab15Sopenharmony_ci
324092f3ab15Sopenharmony_ci    /// Sets the certificate
324192f3ab15Sopenharmony_ci    #[corresponds(SSL_use_certificate)]
324292f3ab15Sopenharmony_ci    pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
324392f3ab15Sopenharmony_ci        unsafe {
324492f3ab15Sopenharmony_ci            cvt(ffi::SSL_use_certificate(self.as_ptr(), cert.as_ptr()))?;
324592f3ab15Sopenharmony_ci        };
324692f3ab15Sopenharmony_ci        Ok(())
324792f3ab15Sopenharmony_ci    }
324892f3ab15Sopenharmony_ci
324992f3ab15Sopenharmony_ci    /// Loads a certificate chain from a file.
325092f3ab15Sopenharmony_ci    ///
325192f3ab15Sopenharmony_ci    /// The file should contain a sequence of PEM-formatted certificates, the first being the leaf
325292f3ab15Sopenharmony_ci    /// certificate, and the remainder forming the chain of certificates up to and including the
325392f3ab15Sopenharmony_ci    /// trusted root certificate.
325492f3ab15Sopenharmony_ci    #[corresponds(SSL_use_certificate_chain_file)]
325592f3ab15Sopenharmony_ci    #[cfg(any(ossl110, libressl332))]
325692f3ab15Sopenharmony_ci    pub fn set_certificate_chain_file<P: AsRef<Path>>(
325792f3ab15Sopenharmony_ci        &mut self,
325892f3ab15Sopenharmony_ci        path: P,
325992f3ab15Sopenharmony_ci    ) -> Result<(), ErrorStack> {
326092f3ab15Sopenharmony_ci        let p = path.as_ref().as_os_str().to_str().unwrap();
326192f3ab15Sopenharmony_ci        let cert_file = CString::new(p).unwrap();
326292f3ab15Sopenharmony_ci        unsafe {
326392f3ab15Sopenharmony_ci            cvt(ffi::SSL_use_certificate_chain_file(
326492f3ab15Sopenharmony_ci                self.as_ptr(),
326592f3ab15Sopenharmony_ci                cert_file.as_ptr(),
326692f3ab15Sopenharmony_ci            ))?;
326792f3ab15Sopenharmony_ci        };
326892f3ab15Sopenharmony_ci        Ok(())
326992f3ab15Sopenharmony_ci    }
327092f3ab15Sopenharmony_ci
327192f3ab15Sopenharmony_ci    /// Sets ca certificate that client trusted
327292f3ab15Sopenharmony_ci    #[corresponds(SSL_add_client_CA)]
327392f3ab15Sopenharmony_ci    pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
327492f3ab15Sopenharmony_ci        unsafe {
327592f3ab15Sopenharmony_ci            cvt(ffi::SSL_add_client_CA(self.as_ptr(), cacert.as_ptr()))?;
327692f3ab15Sopenharmony_ci        };
327792f3ab15Sopenharmony_ci        Ok(())
327892f3ab15Sopenharmony_ci    }
327992f3ab15Sopenharmony_ci
328092f3ab15Sopenharmony_ci    // Sets the list of CAs sent to the client when requesting a client certificate for the chosen ssl
328192f3ab15Sopenharmony_ci    #[corresponds(SSL_set_client_CA_list)]
328292f3ab15Sopenharmony_ci    pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
328392f3ab15Sopenharmony_ci        unsafe { ffi::SSL_set_client_CA_list(self.as_ptr(), list.as_ptr()) }
328492f3ab15Sopenharmony_ci        mem::forget(list);
328592f3ab15Sopenharmony_ci    }
328692f3ab15Sopenharmony_ci
328792f3ab15Sopenharmony_ci    /// Sets the minimum supported protocol version.
328892f3ab15Sopenharmony_ci    ///
328992f3ab15Sopenharmony_ci    /// A value of `None` will enable protocol versions down to the lowest version supported by
329092f3ab15Sopenharmony_ci    /// OpenSSL.
329192f3ab15Sopenharmony_ci    ///
329292f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.1.0 or LibreSSL 2.6.1 or newer.
329392f3ab15Sopenharmony_ci    #[corresponds(SSL_set_min_proto_version)]
329492f3ab15Sopenharmony_ci    #[cfg(any(ossl110, libressl261))]
329592f3ab15Sopenharmony_ci    pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
329692f3ab15Sopenharmony_ci        unsafe {
329792f3ab15Sopenharmony_ci            cvt(ffi::SSL_set_min_proto_version(
329892f3ab15Sopenharmony_ci                self.as_ptr(),
329992f3ab15Sopenharmony_ci                version.map_or(0, |v| v.0 as _),
330092f3ab15Sopenharmony_ci            ))
330192f3ab15Sopenharmony_ci            .map(|_| ())
330292f3ab15Sopenharmony_ci        }
330392f3ab15Sopenharmony_ci    }
330492f3ab15Sopenharmony_ci
330592f3ab15Sopenharmony_ci    /// Sets the maximum supported protocol version.
330692f3ab15Sopenharmony_ci    ///
330792f3ab15Sopenharmony_ci    /// A value of `None` will enable protocol versions up to the highest version supported by
330892f3ab15Sopenharmony_ci    /// OpenSSL.
330992f3ab15Sopenharmony_ci    ///
331092f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.1.0 or or LibreSSL 2.6.1 or newer.
331192f3ab15Sopenharmony_ci    #[corresponds(SSL_set_max_proto_version)]
331292f3ab15Sopenharmony_ci    #[cfg(any(ossl110, libressl261))]
331392f3ab15Sopenharmony_ci    pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
331492f3ab15Sopenharmony_ci        unsafe {
331592f3ab15Sopenharmony_ci            cvt(ffi::SSL_set_max_proto_version(
331692f3ab15Sopenharmony_ci                self.as_ptr(),
331792f3ab15Sopenharmony_ci                version.map_or(0, |v| v.0 as _),
331892f3ab15Sopenharmony_ci            ))
331992f3ab15Sopenharmony_ci            .map(|_| ())
332092f3ab15Sopenharmony_ci        }
332192f3ab15Sopenharmony_ci    }
332292f3ab15Sopenharmony_ci
332392f3ab15Sopenharmony_ci    /// Sets the list of supported ciphers for the TLSv1.3 protocol.
332492f3ab15Sopenharmony_ci    ///
332592f3ab15Sopenharmony_ci    /// The `set_cipher_list` method controls the cipher suites for protocols before TLSv1.3.
332692f3ab15Sopenharmony_ci    ///
332792f3ab15Sopenharmony_ci    /// The format consists of TLSv1.3 cipher suite names separated by `:` characters in order of
332892f3ab15Sopenharmony_ci    /// preference.
332992f3ab15Sopenharmony_ci    ///
333092f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer.
333192f3ab15Sopenharmony_ci    #[corresponds(SSL_set_ciphersuites)]
333292f3ab15Sopenharmony_ci    #[cfg(any(ossl111, libressl340))]
333392f3ab15Sopenharmony_ci    pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
333492f3ab15Sopenharmony_ci        let cipher_list = CString::new(cipher_list).unwrap();
333592f3ab15Sopenharmony_ci        unsafe {
333692f3ab15Sopenharmony_ci            cvt(ffi::SSL_set_ciphersuites(
333792f3ab15Sopenharmony_ci                self.as_ptr(),
333892f3ab15Sopenharmony_ci                cipher_list.as_ptr() as *const _,
333992f3ab15Sopenharmony_ci            ))
334092f3ab15Sopenharmony_ci            .map(|_| ())
334192f3ab15Sopenharmony_ci        }
334292f3ab15Sopenharmony_ci    }
334392f3ab15Sopenharmony_ci
334492f3ab15Sopenharmony_ci    /// Sets the list of supported ciphers for protocols before TLSv1.3.
334592f3ab15Sopenharmony_ci    ///
334692f3ab15Sopenharmony_ci    /// The `set_ciphersuites` method controls the cipher suites for TLSv1.3.
334792f3ab15Sopenharmony_ci    ///
334892f3ab15Sopenharmony_ci    /// See [`ciphers`] for details on the format.
334992f3ab15Sopenharmony_ci    ///
335092f3ab15Sopenharmony_ci    /// [`ciphers`]: https://www.openssl.org/docs/manmaster/apps/ciphers.html
335192f3ab15Sopenharmony_ci    #[corresponds(SSL_set_cipher_list)]
335292f3ab15Sopenharmony_ci    pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
335392f3ab15Sopenharmony_ci        let cipher_list = CString::new(cipher_list).unwrap();
335492f3ab15Sopenharmony_ci        unsafe {
335592f3ab15Sopenharmony_ci            cvt(ffi::SSL_set_cipher_list(
335692f3ab15Sopenharmony_ci                self.as_ptr(),
335792f3ab15Sopenharmony_ci                cipher_list.as_ptr() as *const _,
335892f3ab15Sopenharmony_ci            ))
335992f3ab15Sopenharmony_ci            .map(|_| ())
336092f3ab15Sopenharmony_ci        }
336192f3ab15Sopenharmony_ci    }
336292f3ab15Sopenharmony_ci
336392f3ab15Sopenharmony_ci    /// Set the certificate store used for certificate verification
336492f3ab15Sopenharmony_ci    #[corresponds(SSL_set_cert_store)]
336592f3ab15Sopenharmony_ci    #[cfg(ossl102)]
336692f3ab15Sopenharmony_ci    pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
336792f3ab15Sopenharmony_ci        unsafe {
336892f3ab15Sopenharmony_ci            cvt(ffi::SSL_set0_verify_cert_store(self.as_ptr(), cert_store.as_ptr()) as c_int)?;
336992f3ab15Sopenharmony_ci            mem::forget(cert_store);
337092f3ab15Sopenharmony_ci            Ok(())
337192f3ab15Sopenharmony_ci        }
337292f3ab15Sopenharmony_ci    }
337392f3ab15Sopenharmony_ci
337492f3ab15Sopenharmony_ci    /// Sets the number of TLS 1.3 session tickets that will be sent to a client after a full
337592f3ab15Sopenharmony_ci    /// handshake.
337692f3ab15Sopenharmony_ci    ///
337792f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.1.1 or newer.
337892f3ab15Sopenharmony_ci    #[corresponds(SSL_set_num_tickets)]
337992f3ab15Sopenharmony_ci    #[cfg(ossl111)]
338092f3ab15Sopenharmony_ci    pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
338192f3ab15Sopenharmony_ci        unsafe { cvt(ffi::SSL_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
338292f3ab15Sopenharmony_ci    }
338392f3ab15Sopenharmony_ci
338492f3ab15Sopenharmony_ci    /// Gets the number of TLS 1.3 session tickets that will be sent to a client after a full
338592f3ab15Sopenharmony_ci    /// handshake.
338692f3ab15Sopenharmony_ci    ///
338792f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.1.1 or newer.
338892f3ab15Sopenharmony_ci    #[corresponds(SSL_get_num_tickets)]
338992f3ab15Sopenharmony_ci    #[cfg(ossl111)]
339092f3ab15Sopenharmony_ci    pub fn num_tickets(&self) -> usize {
339192f3ab15Sopenharmony_ci        unsafe { ffi::SSL_get_num_tickets(self.as_ptr()) }
339292f3ab15Sopenharmony_ci    }
339392f3ab15Sopenharmony_ci}
339492f3ab15Sopenharmony_ci
339592f3ab15Sopenharmony_ci/// An SSL stream midway through the handshake process.
339692f3ab15Sopenharmony_ci#[derive(Debug)]
339792f3ab15Sopenharmony_cipub struct MidHandshakeSslStream<S> {
339892f3ab15Sopenharmony_ci    stream: SslStream<S>,
339992f3ab15Sopenharmony_ci    error: Error,
340092f3ab15Sopenharmony_ci}
340192f3ab15Sopenharmony_ci
340292f3ab15Sopenharmony_ciimpl<S> MidHandshakeSslStream<S> {
340392f3ab15Sopenharmony_ci    /// Returns a shared reference to the inner stream.
340492f3ab15Sopenharmony_ci    pub fn get_ref(&self) -> &S {
340592f3ab15Sopenharmony_ci        self.stream.get_ref()
340692f3ab15Sopenharmony_ci    }
340792f3ab15Sopenharmony_ci
340892f3ab15Sopenharmony_ci    /// Returns a mutable reference to the inner stream.
340992f3ab15Sopenharmony_ci    pub fn get_mut(&mut self) -> &mut S {
341092f3ab15Sopenharmony_ci        self.stream.get_mut()
341192f3ab15Sopenharmony_ci    }
341292f3ab15Sopenharmony_ci
341392f3ab15Sopenharmony_ci    /// Returns a shared reference to the `Ssl` of the stream.
341492f3ab15Sopenharmony_ci    pub fn ssl(&self) -> &SslRef {
341592f3ab15Sopenharmony_ci        self.stream.ssl()
341692f3ab15Sopenharmony_ci    }
341792f3ab15Sopenharmony_ci
341892f3ab15Sopenharmony_ci    /// Returns the underlying error which interrupted this handshake.
341992f3ab15Sopenharmony_ci    pub fn error(&self) -> &Error {
342092f3ab15Sopenharmony_ci        &self.error
342192f3ab15Sopenharmony_ci    }
342292f3ab15Sopenharmony_ci
342392f3ab15Sopenharmony_ci    /// Consumes `self`, returning its error.
342492f3ab15Sopenharmony_ci    pub fn into_error(self) -> Error {
342592f3ab15Sopenharmony_ci        self.error
342692f3ab15Sopenharmony_ci    }
342792f3ab15Sopenharmony_ci}
342892f3ab15Sopenharmony_ci
342992f3ab15Sopenharmony_ciimpl<S> MidHandshakeSslStream<S>
343092f3ab15Sopenharmony_ciwhere
343192f3ab15Sopenharmony_ci    S: Read + Write,
343292f3ab15Sopenharmony_ci{
343392f3ab15Sopenharmony_ci    /// Restarts the handshake process.
343492f3ab15Sopenharmony_ci    ///
343592f3ab15Sopenharmony_ci    /// This corresponds to [`SSL_do_handshake`].
343692f3ab15Sopenharmony_ci    ///
343792f3ab15Sopenharmony_ci    /// [`SSL_do_handshake`]: https://www.openssl.org/docs/manmaster/man3/SSL_do_handshake.html
343892f3ab15Sopenharmony_ci    pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
343992f3ab15Sopenharmony_ci        match self.stream.do_handshake() {
344092f3ab15Sopenharmony_ci            Ok(()) => Ok(self.stream),
344192f3ab15Sopenharmony_ci            Err(error) => {
344292f3ab15Sopenharmony_ci                self.error = error;
344392f3ab15Sopenharmony_ci                match self.error.code() {
344492f3ab15Sopenharmony_ci                    ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
344592f3ab15Sopenharmony_ci                        Err(HandshakeError::WouldBlock(self))
344692f3ab15Sopenharmony_ci                    }
344792f3ab15Sopenharmony_ci                    _ => Err(HandshakeError::Failure(self)),
344892f3ab15Sopenharmony_ci                }
344992f3ab15Sopenharmony_ci            }
345092f3ab15Sopenharmony_ci        }
345192f3ab15Sopenharmony_ci    }
345292f3ab15Sopenharmony_ci}
345392f3ab15Sopenharmony_ci
345492f3ab15Sopenharmony_ci/// A TLS session over a stream.
345592f3ab15Sopenharmony_cipub struct SslStream<S> {
345692f3ab15Sopenharmony_ci    ssl: ManuallyDrop<Ssl>,
345792f3ab15Sopenharmony_ci    method: ManuallyDrop<BioMethod>,
345892f3ab15Sopenharmony_ci    _p: PhantomData<S>,
345992f3ab15Sopenharmony_ci}
346092f3ab15Sopenharmony_ci
346192f3ab15Sopenharmony_ciimpl<S> Drop for SslStream<S> {
346292f3ab15Sopenharmony_ci    fn drop(&mut self) {
346392f3ab15Sopenharmony_ci        // ssl holds a reference to method internally so it has to drop first
346492f3ab15Sopenharmony_ci        unsafe {
346592f3ab15Sopenharmony_ci            ManuallyDrop::drop(&mut self.ssl);
346692f3ab15Sopenharmony_ci            ManuallyDrop::drop(&mut self.method);
346792f3ab15Sopenharmony_ci        }
346892f3ab15Sopenharmony_ci    }
346992f3ab15Sopenharmony_ci}
347092f3ab15Sopenharmony_ci
347192f3ab15Sopenharmony_ciimpl<S> fmt::Debug for SslStream<S>
347292f3ab15Sopenharmony_ciwhere
347392f3ab15Sopenharmony_ci    S: fmt::Debug,
347492f3ab15Sopenharmony_ci{
347592f3ab15Sopenharmony_ci    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
347692f3ab15Sopenharmony_ci        fmt.debug_struct("SslStream")
347792f3ab15Sopenharmony_ci            .field("stream", &self.get_ref())
347892f3ab15Sopenharmony_ci            .field("ssl", &self.ssl())
347992f3ab15Sopenharmony_ci            .finish()
348092f3ab15Sopenharmony_ci    }
348192f3ab15Sopenharmony_ci}
348292f3ab15Sopenharmony_ci
348392f3ab15Sopenharmony_ciimpl<S: Read + Write> SslStream<S> {
348492f3ab15Sopenharmony_ci    /// Creates a new `SslStream`.
348592f3ab15Sopenharmony_ci    ///
348692f3ab15Sopenharmony_ci    /// This function performs no IO; the stream will not have performed any part of the handshake
348792f3ab15Sopenharmony_ci    /// with the peer. If the `Ssl` was configured with [`SslRef::set_connect_state`] or
348892f3ab15Sopenharmony_ci    /// [`SslRef::set_accept_state`], the handshake can be performed automatically during the first
348992f3ab15Sopenharmony_ci    /// call to read or write. Otherwise the `connect` and `accept` methods can be used to
349092f3ab15Sopenharmony_ci    /// explicitly perform the handshake.
349192f3ab15Sopenharmony_ci    #[corresponds(SSL_set_bio)]
349292f3ab15Sopenharmony_ci    pub fn new(ssl: Ssl, stream: S) -> Result<Self, ErrorStack> {
349392f3ab15Sopenharmony_ci        let (bio, method) = bio::new(stream)?;
349492f3ab15Sopenharmony_ci        unsafe {
349592f3ab15Sopenharmony_ci            ffi::SSL_set_bio(ssl.as_ptr(), bio, bio);
349692f3ab15Sopenharmony_ci        }
349792f3ab15Sopenharmony_ci
349892f3ab15Sopenharmony_ci        Ok(SslStream {
349992f3ab15Sopenharmony_ci            ssl: ManuallyDrop::new(ssl),
350092f3ab15Sopenharmony_ci            method: ManuallyDrop::new(method),
350192f3ab15Sopenharmony_ci            _p: PhantomData,
350292f3ab15Sopenharmony_ci        })
350392f3ab15Sopenharmony_ci    }
350492f3ab15Sopenharmony_ci
350592f3ab15Sopenharmony_ci    /// Constructs an `SslStream` from a pointer to the underlying OpenSSL `SSL` struct.
350692f3ab15Sopenharmony_ci    ///
350792f3ab15Sopenharmony_ci    /// This is useful if the handshake has already been completed elsewhere.
350892f3ab15Sopenharmony_ci    ///
350992f3ab15Sopenharmony_ci    /// # Safety
351092f3ab15Sopenharmony_ci    ///
351192f3ab15Sopenharmony_ci    /// The caller must ensure the pointer is valid.
351292f3ab15Sopenharmony_ci    #[deprecated(
351392f3ab15Sopenharmony_ci        since = "0.10.32",
351492f3ab15Sopenharmony_ci        note = "use Ssl::from_ptr and SslStream::new instead"
351592f3ab15Sopenharmony_ci    )]
351692f3ab15Sopenharmony_ci    pub unsafe fn from_raw_parts(ssl: *mut ffi::SSL, stream: S) -> Self {
351792f3ab15Sopenharmony_ci        let ssl = Ssl::from_ptr(ssl);
351892f3ab15Sopenharmony_ci        Self::new(ssl, stream).unwrap()
351992f3ab15Sopenharmony_ci    }
352092f3ab15Sopenharmony_ci
352192f3ab15Sopenharmony_ci    /// Read application data transmitted by a client before handshake completion.
352292f3ab15Sopenharmony_ci    ///
352392f3ab15Sopenharmony_ci    /// Useful for reducing latency, but vulnerable to replay attacks. Call
352492f3ab15Sopenharmony_ci    /// [`SslRef::set_accept_state`] first.
352592f3ab15Sopenharmony_ci    ///
352692f3ab15Sopenharmony_ci    /// Returns `Ok(0)` if all early data has been read.
352792f3ab15Sopenharmony_ci    ///
352892f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer.
352992f3ab15Sopenharmony_ci    #[corresponds(SSL_read_early_data)]
353092f3ab15Sopenharmony_ci    #[cfg(any(ossl111, libressl340))]
353192f3ab15Sopenharmony_ci    pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
353292f3ab15Sopenharmony_ci        let mut read = 0;
353392f3ab15Sopenharmony_ci        let ret = unsafe {
353492f3ab15Sopenharmony_ci            ffi::SSL_read_early_data(
353592f3ab15Sopenharmony_ci                self.ssl.as_ptr(),
353692f3ab15Sopenharmony_ci                buf.as_ptr() as *mut c_void,
353792f3ab15Sopenharmony_ci                buf.len(),
353892f3ab15Sopenharmony_ci                &mut read,
353992f3ab15Sopenharmony_ci            )
354092f3ab15Sopenharmony_ci        };
354192f3ab15Sopenharmony_ci        match ret {
354292f3ab15Sopenharmony_ci            ffi::SSL_READ_EARLY_DATA_ERROR => Err(self.make_error(ret)),
354392f3ab15Sopenharmony_ci            ffi::SSL_READ_EARLY_DATA_SUCCESS => Ok(read),
354492f3ab15Sopenharmony_ci            ffi::SSL_READ_EARLY_DATA_FINISH => Ok(0),
354592f3ab15Sopenharmony_ci            _ => unreachable!(),
354692f3ab15Sopenharmony_ci        }
354792f3ab15Sopenharmony_ci    }
354892f3ab15Sopenharmony_ci
354992f3ab15Sopenharmony_ci    /// Send data to the server without blocking on handshake completion.
355092f3ab15Sopenharmony_ci    ///
355192f3ab15Sopenharmony_ci    /// Useful for reducing latency, but vulnerable to replay attacks. Call
355292f3ab15Sopenharmony_ci    /// [`SslRef::set_connect_state`] first.
355392f3ab15Sopenharmony_ci    ///
355492f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer.
355592f3ab15Sopenharmony_ci    #[corresponds(SSL_write_early_data)]
355692f3ab15Sopenharmony_ci    #[cfg(any(ossl111, libressl340))]
355792f3ab15Sopenharmony_ci    pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
355892f3ab15Sopenharmony_ci        let mut written = 0;
355992f3ab15Sopenharmony_ci        let ret = unsafe {
356092f3ab15Sopenharmony_ci            ffi::SSL_write_early_data(
356192f3ab15Sopenharmony_ci                self.ssl.as_ptr(),
356292f3ab15Sopenharmony_ci                buf.as_ptr() as *const c_void,
356392f3ab15Sopenharmony_ci                buf.len(),
356492f3ab15Sopenharmony_ci                &mut written,
356592f3ab15Sopenharmony_ci            )
356692f3ab15Sopenharmony_ci        };
356792f3ab15Sopenharmony_ci        if ret > 0 {
356892f3ab15Sopenharmony_ci            Ok(written)
356992f3ab15Sopenharmony_ci        } else {
357092f3ab15Sopenharmony_ci            Err(self.make_error(ret))
357192f3ab15Sopenharmony_ci        }
357292f3ab15Sopenharmony_ci    }
357392f3ab15Sopenharmony_ci
357492f3ab15Sopenharmony_ci    /// Initiates a client-side TLS handshake.
357592f3ab15Sopenharmony_ci    ///
357692f3ab15Sopenharmony_ci    /// # Warning
357792f3ab15Sopenharmony_ci    ///
357892f3ab15Sopenharmony_ci    /// OpenSSL's default configuration is insecure. It is highly recommended to use
357992f3ab15Sopenharmony_ci    /// `SslConnector` rather than `Ssl` directly, as it manages that configuration.
358092f3ab15Sopenharmony_ci    #[corresponds(SSL_connect)]
358192f3ab15Sopenharmony_ci    pub fn connect(&mut self) -> Result<(), Error> {
358292f3ab15Sopenharmony_ci        let ret = unsafe { ffi::SSL_connect(self.ssl.as_ptr()) };
358392f3ab15Sopenharmony_ci        if ret > 0 {
358492f3ab15Sopenharmony_ci            Ok(())
358592f3ab15Sopenharmony_ci        } else {
358692f3ab15Sopenharmony_ci            Err(self.make_error(ret))
358792f3ab15Sopenharmony_ci        }
358892f3ab15Sopenharmony_ci    }
358992f3ab15Sopenharmony_ci
359092f3ab15Sopenharmony_ci    /// Initiates a server-side TLS handshake.
359192f3ab15Sopenharmony_ci    ///
359292f3ab15Sopenharmony_ci    /// # Warning
359392f3ab15Sopenharmony_ci    ///
359492f3ab15Sopenharmony_ci    /// OpenSSL's default configuration is insecure. It is highly recommended to use
359592f3ab15Sopenharmony_ci    /// `SslAcceptor` rather than `Ssl` directly, as it manages that configuration.
359692f3ab15Sopenharmony_ci    #[corresponds(SSL_accept)]
359792f3ab15Sopenharmony_ci    pub fn accept(&mut self) -> Result<(), Error> {
359892f3ab15Sopenharmony_ci        let ret = unsafe { ffi::SSL_accept(self.ssl.as_ptr()) };
359992f3ab15Sopenharmony_ci        if ret > 0 {
360092f3ab15Sopenharmony_ci            Ok(())
360192f3ab15Sopenharmony_ci        } else {
360292f3ab15Sopenharmony_ci            Err(self.make_error(ret))
360392f3ab15Sopenharmony_ci        }
360492f3ab15Sopenharmony_ci    }
360592f3ab15Sopenharmony_ci
360692f3ab15Sopenharmony_ci    /// Initiates the handshake.
360792f3ab15Sopenharmony_ci    ///
360892f3ab15Sopenharmony_ci    /// This will fail if `set_accept_state` or `set_connect_state` was not called first.
360992f3ab15Sopenharmony_ci    #[corresponds(SSL_do_handshake)]
361092f3ab15Sopenharmony_ci    pub fn do_handshake(&mut self) -> Result<(), Error> {
361192f3ab15Sopenharmony_ci        let ret = unsafe { ffi::SSL_do_handshake(self.ssl.as_ptr()) };
361292f3ab15Sopenharmony_ci        if ret > 0 {
361392f3ab15Sopenharmony_ci            Ok(())
361492f3ab15Sopenharmony_ci        } else {
361592f3ab15Sopenharmony_ci            Err(self.make_error(ret))
361692f3ab15Sopenharmony_ci        }
361792f3ab15Sopenharmony_ci    }
361892f3ab15Sopenharmony_ci
361992f3ab15Sopenharmony_ci    /// Perform a stateless server-side handshake.
362092f3ab15Sopenharmony_ci    ///
362192f3ab15Sopenharmony_ci    /// Requires that cookie generation and verification callbacks were
362292f3ab15Sopenharmony_ci    /// set on the SSL context.
362392f3ab15Sopenharmony_ci    ///
362492f3ab15Sopenharmony_ci    /// Returns `Ok(true)` if a complete ClientHello containing a valid cookie
362592f3ab15Sopenharmony_ci    /// was read, in which case the handshake should be continued via
362692f3ab15Sopenharmony_ci    /// `accept`. If a HelloRetryRequest containing a fresh cookie was
362792f3ab15Sopenharmony_ci    /// transmitted, `Ok(false)` is returned instead. If the handshake cannot
362892f3ab15Sopenharmony_ci    /// proceed at all, `Err` is returned.
362992f3ab15Sopenharmony_ci    #[corresponds(SSL_stateless)]
363092f3ab15Sopenharmony_ci    #[cfg(ossl111)]
363192f3ab15Sopenharmony_ci    pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
363292f3ab15Sopenharmony_ci        match unsafe { ffi::SSL_stateless(self.ssl.as_ptr()) } {
363392f3ab15Sopenharmony_ci            1 => Ok(true),
363492f3ab15Sopenharmony_ci            0 => Ok(false),
363592f3ab15Sopenharmony_ci            -1 => Err(ErrorStack::get()),
363692f3ab15Sopenharmony_ci            _ => unreachable!(),
363792f3ab15Sopenharmony_ci        }
363892f3ab15Sopenharmony_ci    }
363992f3ab15Sopenharmony_ci
364092f3ab15Sopenharmony_ci    /// Like `read`, but returns an `ssl::Error` rather than an `io::Error`.
364192f3ab15Sopenharmony_ci    ///
364292f3ab15Sopenharmony_ci    /// It is particularly useful with a non-blocking socket, where the error value will identify if
364392f3ab15Sopenharmony_ci    /// OpenSSL is waiting on read or write readiness.
364492f3ab15Sopenharmony_ci    #[corresponds(SSL_read)]
364592f3ab15Sopenharmony_ci    pub fn ssl_read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
364692f3ab15Sopenharmony_ci        // The interpretation of the return code here is a little odd with a
364792f3ab15Sopenharmony_ci        // zero-length write. OpenSSL will likely correctly report back to us
364892f3ab15Sopenharmony_ci        // that it read zero bytes, but zero is also the sentinel for "error".
364992f3ab15Sopenharmony_ci        // To avoid that confusion short-circuit that logic and return quickly
365092f3ab15Sopenharmony_ci        // if `buf` has a length of zero.
365192f3ab15Sopenharmony_ci        if buf.is_empty() {
365292f3ab15Sopenharmony_ci            return Ok(0);
365392f3ab15Sopenharmony_ci        }
365492f3ab15Sopenharmony_ci
365592f3ab15Sopenharmony_ci        let ret = self.ssl.read(buf);
365692f3ab15Sopenharmony_ci        if ret > 0 {
365792f3ab15Sopenharmony_ci            Ok(ret as usize)
365892f3ab15Sopenharmony_ci        } else {
365992f3ab15Sopenharmony_ci            Err(self.make_error(ret))
366092f3ab15Sopenharmony_ci        }
366192f3ab15Sopenharmony_ci    }
366292f3ab15Sopenharmony_ci
366392f3ab15Sopenharmony_ci    /// Like `write`, but returns an `ssl::Error` rather than an `io::Error`.
366492f3ab15Sopenharmony_ci    ///
366592f3ab15Sopenharmony_ci    /// It is particularly useful with a non-blocking socket, where the error value will identify if
366692f3ab15Sopenharmony_ci    /// OpenSSL is waiting on read or write readiness.
366792f3ab15Sopenharmony_ci    #[corresponds(SSL_write)]
366892f3ab15Sopenharmony_ci    pub fn ssl_write(&mut self, buf: &[u8]) -> Result<usize, Error> {
366992f3ab15Sopenharmony_ci        // See above for why we short-circuit on zero-length buffers
367092f3ab15Sopenharmony_ci        if buf.is_empty() {
367192f3ab15Sopenharmony_ci            return Ok(0);
367292f3ab15Sopenharmony_ci        }
367392f3ab15Sopenharmony_ci
367492f3ab15Sopenharmony_ci        let ret = self.ssl.write(buf);
367592f3ab15Sopenharmony_ci        if ret > 0 {
367692f3ab15Sopenharmony_ci            Ok(ret as usize)
367792f3ab15Sopenharmony_ci        } else {
367892f3ab15Sopenharmony_ci            Err(self.make_error(ret))
367992f3ab15Sopenharmony_ci        }
368092f3ab15Sopenharmony_ci    }
368192f3ab15Sopenharmony_ci
368292f3ab15Sopenharmony_ci    /// Reads data from the stream, without removing it from the queue.
368392f3ab15Sopenharmony_ci    #[corresponds(SSL_peek)]
368492f3ab15Sopenharmony_ci    pub fn ssl_peek(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
368592f3ab15Sopenharmony_ci        // See above for why we short-circuit on zero-length buffers
368692f3ab15Sopenharmony_ci        if buf.is_empty() {
368792f3ab15Sopenharmony_ci            return Ok(0);
368892f3ab15Sopenharmony_ci        }
368992f3ab15Sopenharmony_ci
369092f3ab15Sopenharmony_ci        let ret = self.ssl.peek(buf);
369192f3ab15Sopenharmony_ci        if ret > 0 {
369292f3ab15Sopenharmony_ci            Ok(ret as usize)
369392f3ab15Sopenharmony_ci        } else {
369492f3ab15Sopenharmony_ci            Err(self.make_error(ret))
369592f3ab15Sopenharmony_ci        }
369692f3ab15Sopenharmony_ci    }
369792f3ab15Sopenharmony_ci
369892f3ab15Sopenharmony_ci    /// Shuts down the session.
369992f3ab15Sopenharmony_ci    ///
370092f3ab15Sopenharmony_ci    /// The shutdown process consists of two steps. The first step sends a close notify message to
370192f3ab15Sopenharmony_ci    /// the peer, after which `ShutdownResult::Sent` is returned. The second step awaits the receipt
370292f3ab15Sopenharmony_ci    /// of a close notify message from the peer, after which `ShutdownResult::Received` is returned.
370392f3ab15Sopenharmony_ci    ///
370492f3ab15Sopenharmony_ci    /// While the connection may be closed after the first step, it is recommended to fully shut the
370592f3ab15Sopenharmony_ci    /// session down. In particular, it must be fully shut down if the connection is to be used for
370692f3ab15Sopenharmony_ci    /// further communication in the future.
370792f3ab15Sopenharmony_ci    #[corresponds(SSL_shutdown)]
370892f3ab15Sopenharmony_ci    pub fn shutdown(&mut self) -> Result<ShutdownResult, Error> {
370992f3ab15Sopenharmony_ci        match unsafe { ffi::SSL_shutdown(self.ssl.as_ptr()) } {
371092f3ab15Sopenharmony_ci            0 => Ok(ShutdownResult::Sent),
371192f3ab15Sopenharmony_ci            1 => Ok(ShutdownResult::Received),
371292f3ab15Sopenharmony_ci            n => Err(self.make_error(n)),
371392f3ab15Sopenharmony_ci        }
371492f3ab15Sopenharmony_ci    }
371592f3ab15Sopenharmony_ci
371692f3ab15Sopenharmony_ci    /// Returns the session's shutdown state.
371792f3ab15Sopenharmony_ci    #[corresponds(SSL_get_shutdown)]
371892f3ab15Sopenharmony_ci    pub fn get_shutdown(&mut self) -> ShutdownState {
371992f3ab15Sopenharmony_ci        unsafe {
372092f3ab15Sopenharmony_ci            let bits = ffi::SSL_get_shutdown(self.ssl.as_ptr());
372192f3ab15Sopenharmony_ci            ShutdownState { bits }
372292f3ab15Sopenharmony_ci        }
372392f3ab15Sopenharmony_ci    }
372492f3ab15Sopenharmony_ci
372592f3ab15Sopenharmony_ci    /// Sets the session's shutdown state.
372692f3ab15Sopenharmony_ci    ///
372792f3ab15Sopenharmony_ci    /// This can be used to tell OpenSSL that the session should be cached even if a full two-way
372892f3ab15Sopenharmony_ci    /// shutdown was not completed.
372992f3ab15Sopenharmony_ci    #[corresponds(SSL_set_shutdown)]
373092f3ab15Sopenharmony_ci    pub fn set_shutdown(&mut self, state: ShutdownState) {
373192f3ab15Sopenharmony_ci        unsafe { ffi::SSL_set_shutdown(self.ssl.as_ptr(), state.bits()) }
373292f3ab15Sopenharmony_ci    }
373392f3ab15Sopenharmony_ci}
373492f3ab15Sopenharmony_ci
373592f3ab15Sopenharmony_ciimpl<S> SslStream<S> {
373692f3ab15Sopenharmony_ci    fn make_error(&mut self, ret: c_int) -> Error {
373792f3ab15Sopenharmony_ci        self.check_panic();
373892f3ab15Sopenharmony_ci
373992f3ab15Sopenharmony_ci        let code = self.ssl.get_error(ret);
374092f3ab15Sopenharmony_ci
374192f3ab15Sopenharmony_ci        let cause = match code {
374292f3ab15Sopenharmony_ci            ErrorCode::SSL => Some(InnerError::Ssl(ErrorStack::get())),
374392f3ab15Sopenharmony_ci            ErrorCode::SYSCALL => {
374492f3ab15Sopenharmony_ci                let errs = ErrorStack::get();
374592f3ab15Sopenharmony_ci                if errs.errors().is_empty() {
374692f3ab15Sopenharmony_ci                    self.get_bio_error().map(InnerError::Io)
374792f3ab15Sopenharmony_ci                } else {
374892f3ab15Sopenharmony_ci                    Some(InnerError::Ssl(errs))
374992f3ab15Sopenharmony_ci                }
375092f3ab15Sopenharmony_ci            }
375192f3ab15Sopenharmony_ci            ErrorCode::ZERO_RETURN => None,
375292f3ab15Sopenharmony_ci            ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
375392f3ab15Sopenharmony_ci                self.get_bio_error().map(InnerError::Io)
375492f3ab15Sopenharmony_ci            }
375592f3ab15Sopenharmony_ci            _ => None,
375692f3ab15Sopenharmony_ci        };
375792f3ab15Sopenharmony_ci
375892f3ab15Sopenharmony_ci        Error { code, cause }
375992f3ab15Sopenharmony_ci    }
376092f3ab15Sopenharmony_ci
376192f3ab15Sopenharmony_ci    fn check_panic(&mut self) {
376292f3ab15Sopenharmony_ci        if let Some(err) = unsafe { bio::take_panic::<S>(self.ssl.get_raw_rbio()) } {
376392f3ab15Sopenharmony_ci            resume_unwind(err)
376492f3ab15Sopenharmony_ci        }
376592f3ab15Sopenharmony_ci    }
376692f3ab15Sopenharmony_ci
376792f3ab15Sopenharmony_ci    fn get_bio_error(&mut self) -> Option<io::Error> {
376892f3ab15Sopenharmony_ci        unsafe { bio::take_error::<S>(self.ssl.get_raw_rbio()) }
376992f3ab15Sopenharmony_ci    }
377092f3ab15Sopenharmony_ci
377192f3ab15Sopenharmony_ci    /// Returns a shared reference to the underlying stream.
377292f3ab15Sopenharmony_ci    pub fn get_ref(&self) -> &S {
377392f3ab15Sopenharmony_ci        unsafe {
377492f3ab15Sopenharmony_ci            let bio = self.ssl.get_raw_rbio();
377592f3ab15Sopenharmony_ci            bio::get_ref(bio)
377692f3ab15Sopenharmony_ci        }
377792f3ab15Sopenharmony_ci    }
377892f3ab15Sopenharmony_ci
377992f3ab15Sopenharmony_ci    /// Returns a mutable reference to the underlying stream.
378092f3ab15Sopenharmony_ci    ///
378192f3ab15Sopenharmony_ci    /// # Warning
378292f3ab15Sopenharmony_ci    ///
378392f3ab15Sopenharmony_ci    /// It is inadvisable to read from or write to the underlying stream as it
378492f3ab15Sopenharmony_ci    /// will most likely corrupt the SSL session.
378592f3ab15Sopenharmony_ci    pub fn get_mut(&mut self) -> &mut S {
378692f3ab15Sopenharmony_ci        unsafe {
378792f3ab15Sopenharmony_ci            let bio = self.ssl.get_raw_rbio();
378892f3ab15Sopenharmony_ci            bio::get_mut(bio)
378992f3ab15Sopenharmony_ci        }
379092f3ab15Sopenharmony_ci    }
379192f3ab15Sopenharmony_ci
379292f3ab15Sopenharmony_ci    /// Returns a shared reference to the `Ssl` object associated with this stream.
379392f3ab15Sopenharmony_ci    pub fn ssl(&self) -> &SslRef {
379492f3ab15Sopenharmony_ci        &self.ssl
379592f3ab15Sopenharmony_ci    }
379692f3ab15Sopenharmony_ci}
379792f3ab15Sopenharmony_ci
379892f3ab15Sopenharmony_ciimpl<S: Read + Write> Read for SslStream<S> {
379992f3ab15Sopenharmony_ci    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
380092f3ab15Sopenharmony_ci        loop {
380192f3ab15Sopenharmony_ci            match self.ssl_read(buf) {
380292f3ab15Sopenharmony_ci                Ok(n) => return Ok(n),
380392f3ab15Sopenharmony_ci                Err(ref e) if e.code() == ErrorCode::ZERO_RETURN => return Ok(0),
380492f3ab15Sopenharmony_ci                Err(ref e) if e.code() == ErrorCode::SYSCALL && e.io_error().is_none() => {
380592f3ab15Sopenharmony_ci                    return Ok(0);
380692f3ab15Sopenharmony_ci                }
380792f3ab15Sopenharmony_ci                Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
380892f3ab15Sopenharmony_ci                Err(e) => {
380992f3ab15Sopenharmony_ci                    return Err(e
381092f3ab15Sopenharmony_ci                        .into_io_error()
381192f3ab15Sopenharmony_ci                        .unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e)));
381292f3ab15Sopenharmony_ci                }
381392f3ab15Sopenharmony_ci            }
381492f3ab15Sopenharmony_ci        }
381592f3ab15Sopenharmony_ci    }
381692f3ab15Sopenharmony_ci}
381792f3ab15Sopenharmony_ci
381892f3ab15Sopenharmony_ciimpl<S: Read + Write> Write for SslStream<S> {
381992f3ab15Sopenharmony_ci    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
382092f3ab15Sopenharmony_ci        loop {
382192f3ab15Sopenharmony_ci            match self.ssl_write(buf) {
382292f3ab15Sopenharmony_ci                Ok(n) => return Ok(n),
382392f3ab15Sopenharmony_ci                Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
382492f3ab15Sopenharmony_ci                Err(e) => {
382592f3ab15Sopenharmony_ci                    return Err(e
382692f3ab15Sopenharmony_ci                        .into_io_error()
382792f3ab15Sopenharmony_ci                        .unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e)));
382892f3ab15Sopenharmony_ci                }
382992f3ab15Sopenharmony_ci            }
383092f3ab15Sopenharmony_ci        }
383192f3ab15Sopenharmony_ci    }
383292f3ab15Sopenharmony_ci
383392f3ab15Sopenharmony_ci    fn flush(&mut self) -> io::Result<()> {
383492f3ab15Sopenharmony_ci        self.get_mut().flush()
383592f3ab15Sopenharmony_ci    }
383692f3ab15Sopenharmony_ci}
383792f3ab15Sopenharmony_ci
383892f3ab15Sopenharmony_ci/// A partially constructed `SslStream`, useful for unusual handshakes.
383992f3ab15Sopenharmony_ci#[deprecated(
384092f3ab15Sopenharmony_ci    since = "0.10.32",
384192f3ab15Sopenharmony_ci    note = "use the methods directly on Ssl/SslStream instead"
384292f3ab15Sopenharmony_ci)]
384392f3ab15Sopenharmony_cipub struct SslStreamBuilder<S> {
384492f3ab15Sopenharmony_ci    inner: SslStream<S>,
384592f3ab15Sopenharmony_ci}
384692f3ab15Sopenharmony_ci
384792f3ab15Sopenharmony_ci#[allow(deprecated)]
384892f3ab15Sopenharmony_ciimpl<S> SslStreamBuilder<S>
384992f3ab15Sopenharmony_ciwhere
385092f3ab15Sopenharmony_ci    S: Read + Write,
385192f3ab15Sopenharmony_ci{
385292f3ab15Sopenharmony_ci    /// Begin creating an `SslStream` atop `stream`
385392f3ab15Sopenharmony_ci    pub fn new(ssl: Ssl, stream: S) -> Self {
385492f3ab15Sopenharmony_ci        Self {
385592f3ab15Sopenharmony_ci            inner: SslStream::new(ssl, stream).unwrap(),
385692f3ab15Sopenharmony_ci        }
385792f3ab15Sopenharmony_ci    }
385892f3ab15Sopenharmony_ci
385992f3ab15Sopenharmony_ci    /// Perform a stateless server-side handshake
386092f3ab15Sopenharmony_ci    ///
386192f3ab15Sopenharmony_ci    /// Requires that cookie generation and verification callbacks were
386292f3ab15Sopenharmony_ci    /// set on the SSL context.
386392f3ab15Sopenharmony_ci    ///
386492f3ab15Sopenharmony_ci    /// Returns `Ok(true)` if a complete ClientHello containing a valid cookie
386592f3ab15Sopenharmony_ci    /// was read, in which case the handshake should be continued via
386692f3ab15Sopenharmony_ci    /// `accept`. If a HelloRetryRequest containing a fresh cookie was
386792f3ab15Sopenharmony_ci    /// transmitted, `Ok(false)` is returned instead. If the handshake cannot
386892f3ab15Sopenharmony_ci    /// proceed at all, `Err` is returned.
386992f3ab15Sopenharmony_ci    ///
387092f3ab15Sopenharmony_ci    /// This corresponds to [`SSL_stateless`]
387192f3ab15Sopenharmony_ci    ///
387292f3ab15Sopenharmony_ci    /// [`SSL_stateless`]: https://www.openssl.org/docs/manmaster/man3/SSL_stateless.html
387392f3ab15Sopenharmony_ci    #[cfg(ossl111)]
387492f3ab15Sopenharmony_ci    pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
387592f3ab15Sopenharmony_ci        match unsafe { ffi::SSL_stateless(self.inner.ssl.as_ptr()) } {
387692f3ab15Sopenharmony_ci            1 => Ok(true),
387792f3ab15Sopenharmony_ci            0 => Ok(false),
387892f3ab15Sopenharmony_ci            -1 => Err(ErrorStack::get()),
387992f3ab15Sopenharmony_ci            _ => unreachable!(),
388092f3ab15Sopenharmony_ci        }
388192f3ab15Sopenharmony_ci    }
388292f3ab15Sopenharmony_ci
388392f3ab15Sopenharmony_ci    /// Configure as an outgoing stream from a client.
388492f3ab15Sopenharmony_ci    ///
388592f3ab15Sopenharmony_ci    /// This corresponds to [`SSL_set_connect_state`].
388692f3ab15Sopenharmony_ci    ///
388792f3ab15Sopenharmony_ci    /// [`SSL_set_connect_state`]: https://www.openssl.org/docs/manmaster/man3/SSL_set_connect_state.html
388892f3ab15Sopenharmony_ci    pub fn set_connect_state(&mut self) {
388992f3ab15Sopenharmony_ci        unsafe { ffi::SSL_set_connect_state(self.inner.ssl.as_ptr()) }
389092f3ab15Sopenharmony_ci    }
389192f3ab15Sopenharmony_ci
389292f3ab15Sopenharmony_ci    /// Configure as an incoming stream to a server.
389392f3ab15Sopenharmony_ci    ///
389492f3ab15Sopenharmony_ci    /// This corresponds to [`SSL_set_accept_state`].
389592f3ab15Sopenharmony_ci    ///
389692f3ab15Sopenharmony_ci    /// [`SSL_set_accept_state`]: https://www.openssl.org/docs/manmaster/man3/SSL_set_accept_state.html
389792f3ab15Sopenharmony_ci    pub fn set_accept_state(&mut self) {
389892f3ab15Sopenharmony_ci        unsafe { ffi::SSL_set_accept_state(self.inner.ssl.as_ptr()) }
389992f3ab15Sopenharmony_ci    }
390092f3ab15Sopenharmony_ci
390192f3ab15Sopenharmony_ci    /// See `Ssl::connect`
390292f3ab15Sopenharmony_ci    pub fn connect(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
390392f3ab15Sopenharmony_ci        match self.inner.connect() {
390492f3ab15Sopenharmony_ci            Ok(()) => Ok(self.inner),
390592f3ab15Sopenharmony_ci            Err(error) => match error.code() {
390692f3ab15Sopenharmony_ci                ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
390792f3ab15Sopenharmony_ci                    Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
390892f3ab15Sopenharmony_ci                        stream: self.inner,
390992f3ab15Sopenharmony_ci                        error,
391092f3ab15Sopenharmony_ci                    }))
391192f3ab15Sopenharmony_ci                }
391292f3ab15Sopenharmony_ci                _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
391392f3ab15Sopenharmony_ci                    stream: self.inner,
391492f3ab15Sopenharmony_ci                    error,
391592f3ab15Sopenharmony_ci                })),
391692f3ab15Sopenharmony_ci            },
391792f3ab15Sopenharmony_ci        }
391892f3ab15Sopenharmony_ci    }
391992f3ab15Sopenharmony_ci
392092f3ab15Sopenharmony_ci    /// See `Ssl::accept`
392192f3ab15Sopenharmony_ci    pub fn accept(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
392292f3ab15Sopenharmony_ci        match self.inner.accept() {
392392f3ab15Sopenharmony_ci            Ok(()) => Ok(self.inner),
392492f3ab15Sopenharmony_ci            Err(error) => match error.code() {
392592f3ab15Sopenharmony_ci                ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
392692f3ab15Sopenharmony_ci                    Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
392792f3ab15Sopenharmony_ci                        stream: self.inner,
392892f3ab15Sopenharmony_ci                        error,
392992f3ab15Sopenharmony_ci                    }))
393092f3ab15Sopenharmony_ci                }
393192f3ab15Sopenharmony_ci                _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
393292f3ab15Sopenharmony_ci                    stream: self.inner,
393392f3ab15Sopenharmony_ci                    error,
393492f3ab15Sopenharmony_ci                })),
393592f3ab15Sopenharmony_ci            },
393692f3ab15Sopenharmony_ci        }
393792f3ab15Sopenharmony_ci    }
393892f3ab15Sopenharmony_ci
393992f3ab15Sopenharmony_ci    /// Initiates the handshake.
394092f3ab15Sopenharmony_ci    ///
394192f3ab15Sopenharmony_ci    /// This will fail if `set_accept_state` or `set_connect_state` was not called first.
394292f3ab15Sopenharmony_ci    ///
394392f3ab15Sopenharmony_ci    /// This corresponds to [`SSL_do_handshake`].
394492f3ab15Sopenharmony_ci    ///
394592f3ab15Sopenharmony_ci    /// [`SSL_do_handshake`]: https://www.openssl.org/docs/manmaster/man3/SSL_do_handshake.html
394692f3ab15Sopenharmony_ci    pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
394792f3ab15Sopenharmony_ci        match self.inner.do_handshake() {
394892f3ab15Sopenharmony_ci            Ok(()) => Ok(self.inner),
394992f3ab15Sopenharmony_ci            Err(error) => match error.code() {
395092f3ab15Sopenharmony_ci                ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
395192f3ab15Sopenharmony_ci                    Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
395292f3ab15Sopenharmony_ci                        stream: self.inner,
395392f3ab15Sopenharmony_ci                        error,
395492f3ab15Sopenharmony_ci                    }))
395592f3ab15Sopenharmony_ci                }
395692f3ab15Sopenharmony_ci                _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
395792f3ab15Sopenharmony_ci                    stream: self.inner,
395892f3ab15Sopenharmony_ci                    error,
395992f3ab15Sopenharmony_ci                })),
396092f3ab15Sopenharmony_ci            },
396192f3ab15Sopenharmony_ci        }
396292f3ab15Sopenharmony_ci    }
396392f3ab15Sopenharmony_ci
396492f3ab15Sopenharmony_ci    /// Read application data transmitted by a client before handshake
396592f3ab15Sopenharmony_ci    /// completion.
396692f3ab15Sopenharmony_ci    ///
396792f3ab15Sopenharmony_ci    /// Useful for reducing latency, but vulnerable to replay attacks. Call
396892f3ab15Sopenharmony_ci    /// `set_accept_state` first.
396992f3ab15Sopenharmony_ci    ///
397092f3ab15Sopenharmony_ci    /// Returns `Ok(0)` if all early data has been read.
397192f3ab15Sopenharmony_ci    ///
397292f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer.
397392f3ab15Sopenharmony_ci    ///
397492f3ab15Sopenharmony_ci    /// This corresponds to [`SSL_read_early_data`].
397592f3ab15Sopenharmony_ci    ///
397692f3ab15Sopenharmony_ci    /// [`SSL_read_early_data`]: https://www.openssl.org/docs/manmaster/man3/SSL_read_early_data.html
397792f3ab15Sopenharmony_ci    #[cfg(any(ossl111, libressl340))]
397892f3ab15Sopenharmony_ci    pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
397992f3ab15Sopenharmony_ci        self.inner.read_early_data(buf)
398092f3ab15Sopenharmony_ci    }
398192f3ab15Sopenharmony_ci
398292f3ab15Sopenharmony_ci    /// Send data to the server without blocking on handshake completion.
398392f3ab15Sopenharmony_ci    ///
398492f3ab15Sopenharmony_ci    /// Useful for reducing latency, but vulnerable to replay attacks. Call
398592f3ab15Sopenharmony_ci    /// `set_connect_state` first.
398692f3ab15Sopenharmony_ci    ///
398792f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer.
398892f3ab15Sopenharmony_ci    ///
398992f3ab15Sopenharmony_ci    /// This corresponds to [`SSL_write_early_data`].
399092f3ab15Sopenharmony_ci    ///
399192f3ab15Sopenharmony_ci    /// [`SSL_write_early_data`]: https://www.openssl.org/docs/manmaster/man3/SSL_write_early_data.html
399292f3ab15Sopenharmony_ci    #[cfg(any(ossl111, libressl340))]
399392f3ab15Sopenharmony_ci    pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
399492f3ab15Sopenharmony_ci        self.inner.write_early_data(buf)
399592f3ab15Sopenharmony_ci    }
399692f3ab15Sopenharmony_ci}
399792f3ab15Sopenharmony_ci
399892f3ab15Sopenharmony_ci#[allow(deprecated)]
399992f3ab15Sopenharmony_ciimpl<S> SslStreamBuilder<S> {
400092f3ab15Sopenharmony_ci    /// Returns a shared reference to the underlying stream.
400192f3ab15Sopenharmony_ci    pub fn get_ref(&self) -> &S {
400292f3ab15Sopenharmony_ci        unsafe {
400392f3ab15Sopenharmony_ci            let bio = self.inner.ssl.get_raw_rbio();
400492f3ab15Sopenharmony_ci            bio::get_ref(bio)
400592f3ab15Sopenharmony_ci        }
400692f3ab15Sopenharmony_ci    }
400792f3ab15Sopenharmony_ci
400892f3ab15Sopenharmony_ci    /// Returns a mutable reference to the underlying stream.
400992f3ab15Sopenharmony_ci    ///
401092f3ab15Sopenharmony_ci    /// # Warning
401192f3ab15Sopenharmony_ci    ///
401292f3ab15Sopenharmony_ci    /// It is inadvisable to read from or write to the underlying stream as it
401392f3ab15Sopenharmony_ci    /// will most likely corrupt the SSL session.
401492f3ab15Sopenharmony_ci    pub fn get_mut(&mut self) -> &mut S {
401592f3ab15Sopenharmony_ci        unsafe {
401692f3ab15Sopenharmony_ci            let bio = self.inner.ssl.get_raw_rbio();
401792f3ab15Sopenharmony_ci            bio::get_mut(bio)
401892f3ab15Sopenharmony_ci        }
401992f3ab15Sopenharmony_ci    }
402092f3ab15Sopenharmony_ci
402192f3ab15Sopenharmony_ci    /// Returns a shared reference to the `Ssl` object associated with this builder.
402292f3ab15Sopenharmony_ci    pub fn ssl(&self) -> &SslRef {
402392f3ab15Sopenharmony_ci        &self.inner.ssl
402492f3ab15Sopenharmony_ci    }
402592f3ab15Sopenharmony_ci
402692f3ab15Sopenharmony_ci    /// Set the DTLS MTU size.
402792f3ab15Sopenharmony_ci    ///
402892f3ab15Sopenharmony_ci    /// It will be ignored if the value is smaller than the minimum packet size
402992f3ab15Sopenharmony_ci    /// the DTLS protocol requires.
403092f3ab15Sopenharmony_ci    ///
403192f3ab15Sopenharmony_ci    /// # Panics
403292f3ab15Sopenharmony_ci    /// This function panics if the given mtu size can't be represented in a positive `c_long` range
403392f3ab15Sopenharmony_ci    #[deprecated(note = "Use SslRef::set_mtu instead", since = "0.10.30")]
403492f3ab15Sopenharmony_ci    pub fn set_dtls_mtu_size(&mut self, mtu_size: usize) {
403592f3ab15Sopenharmony_ci        unsafe {
403692f3ab15Sopenharmony_ci            let bio = self.inner.ssl.get_raw_rbio();
403792f3ab15Sopenharmony_ci            bio::set_dtls_mtu_size::<S>(bio, mtu_size);
403892f3ab15Sopenharmony_ci        }
403992f3ab15Sopenharmony_ci    }
404092f3ab15Sopenharmony_ci}
404192f3ab15Sopenharmony_ci
404292f3ab15Sopenharmony_ci/// The result of a shutdown request.
404392f3ab15Sopenharmony_ci#[derive(Copy, Clone, Debug, PartialEq, Eq)]
404492f3ab15Sopenharmony_cipub enum ShutdownResult {
404592f3ab15Sopenharmony_ci    /// A close notify message has been sent to the peer.
404692f3ab15Sopenharmony_ci    Sent,
404792f3ab15Sopenharmony_ci
404892f3ab15Sopenharmony_ci    /// A close notify response message has been received from the peer.
404992f3ab15Sopenharmony_ci    Received,
405092f3ab15Sopenharmony_ci}
405192f3ab15Sopenharmony_ci
405292f3ab15Sopenharmony_cibitflags! {
405392f3ab15Sopenharmony_ci    /// The shutdown state of a session.
405492f3ab15Sopenharmony_ci    pub struct ShutdownState: c_int {
405592f3ab15Sopenharmony_ci        /// A close notify message has been sent to the peer.
405692f3ab15Sopenharmony_ci        const SENT = ffi::SSL_SENT_SHUTDOWN;
405792f3ab15Sopenharmony_ci        /// A close notify message has been received from the peer.
405892f3ab15Sopenharmony_ci        const RECEIVED = ffi::SSL_RECEIVED_SHUTDOWN;
405992f3ab15Sopenharmony_ci    }
406092f3ab15Sopenharmony_ci}
406192f3ab15Sopenharmony_ci
406292f3ab15Sopenharmony_cicfg_if! {
406392f3ab15Sopenharmony_ci    if #[cfg(any(boringssl, ossl110, libressl273))] {
406492f3ab15Sopenharmony_ci        use ffi::{SSL_CTX_up_ref, SSL_SESSION_get_master_key, SSL_SESSION_up_ref, SSL_is_server};
406592f3ab15Sopenharmony_ci    } else {
406692f3ab15Sopenharmony_ci        #[allow(bad_style)]
406792f3ab15Sopenharmony_ci        pub unsafe fn SSL_CTX_up_ref(ssl: *mut ffi::SSL_CTX) -> c_int {
406892f3ab15Sopenharmony_ci            ffi::CRYPTO_add_lock(
406992f3ab15Sopenharmony_ci                &mut (*ssl).references,
407092f3ab15Sopenharmony_ci                1,
407192f3ab15Sopenharmony_ci                ffi::CRYPTO_LOCK_SSL_CTX,
407292f3ab15Sopenharmony_ci                "mod.rs\0".as_ptr() as *const _,
407392f3ab15Sopenharmony_ci                line!() as c_int,
407492f3ab15Sopenharmony_ci            );
407592f3ab15Sopenharmony_ci            0
407692f3ab15Sopenharmony_ci        }
407792f3ab15Sopenharmony_ci
407892f3ab15Sopenharmony_ci        #[allow(bad_style)]
407992f3ab15Sopenharmony_ci        pub unsafe fn SSL_SESSION_get_master_key(
408092f3ab15Sopenharmony_ci            session: *const ffi::SSL_SESSION,
408192f3ab15Sopenharmony_ci            out: *mut c_uchar,
408292f3ab15Sopenharmony_ci            mut outlen: usize,
408392f3ab15Sopenharmony_ci        ) -> usize {
408492f3ab15Sopenharmony_ci            if outlen == 0 {
408592f3ab15Sopenharmony_ci                return (*session).master_key_length as usize;
408692f3ab15Sopenharmony_ci            }
408792f3ab15Sopenharmony_ci            if outlen > (*session).master_key_length as usize {
408892f3ab15Sopenharmony_ci                outlen = (*session).master_key_length as usize;
408992f3ab15Sopenharmony_ci            }
409092f3ab15Sopenharmony_ci            ptr::copy_nonoverlapping((*session).master_key.as_ptr(), out, outlen);
409192f3ab15Sopenharmony_ci            outlen
409292f3ab15Sopenharmony_ci        }
409392f3ab15Sopenharmony_ci
409492f3ab15Sopenharmony_ci        #[allow(bad_style)]
409592f3ab15Sopenharmony_ci        pub unsafe fn SSL_is_server(s: *mut ffi::SSL) -> c_int {
409692f3ab15Sopenharmony_ci            (*s).server
409792f3ab15Sopenharmony_ci        }
409892f3ab15Sopenharmony_ci
409992f3ab15Sopenharmony_ci        #[allow(bad_style)]
410092f3ab15Sopenharmony_ci        pub unsafe fn SSL_SESSION_up_ref(ses: *mut ffi::SSL_SESSION) -> c_int {
410192f3ab15Sopenharmony_ci            ffi::CRYPTO_add_lock(
410292f3ab15Sopenharmony_ci                &mut (*ses).references,
410392f3ab15Sopenharmony_ci                1,
410492f3ab15Sopenharmony_ci                ffi::CRYPTO_LOCK_SSL_CTX,
410592f3ab15Sopenharmony_ci                "mod.rs\0".as_ptr() as *const _,
410692f3ab15Sopenharmony_ci                line!() as c_int,
410792f3ab15Sopenharmony_ci            );
410892f3ab15Sopenharmony_ci            0
410992f3ab15Sopenharmony_ci        }
411092f3ab15Sopenharmony_ci    }
411192f3ab15Sopenharmony_ci}
411292f3ab15Sopenharmony_ci
411392f3ab15Sopenharmony_cicfg_if! {
411492f3ab15Sopenharmony_ci    if #[cfg(ossl300)] {
411592f3ab15Sopenharmony_ci        use ffi::SSL_get1_peer_certificate;
411692f3ab15Sopenharmony_ci    } else {
411792f3ab15Sopenharmony_ci        use ffi::SSL_get_peer_certificate as SSL_get1_peer_certificate;
411892f3ab15Sopenharmony_ci    }
411992f3ab15Sopenharmony_ci}
412092f3ab15Sopenharmony_cicfg_if! {
412192f3ab15Sopenharmony_ci    if #[cfg(any(boringssl, ossl110, libressl291))] {
412292f3ab15Sopenharmony_ci        use ffi::{TLS_method, DTLS_method, TLS_client_method, TLS_server_method};
412392f3ab15Sopenharmony_ci    } else {
412492f3ab15Sopenharmony_ci        use ffi::{
412592f3ab15Sopenharmony_ci            SSLv23_method as TLS_method, DTLSv1_method as DTLS_method, SSLv23_client_method as TLS_client_method,
412692f3ab15Sopenharmony_ci            SSLv23_server_method as TLS_server_method,
412792f3ab15Sopenharmony_ci        };
412892f3ab15Sopenharmony_ci    }
412992f3ab15Sopenharmony_ci}
413092f3ab15Sopenharmony_cicfg_if! {
413192f3ab15Sopenharmony_ci    if #[cfg(ossl110)] {
413292f3ab15Sopenharmony_ci        unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
413392f3ab15Sopenharmony_ci            ffi::CRYPTO_get_ex_new_index(
413492f3ab15Sopenharmony_ci                ffi::CRYPTO_EX_INDEX_SSL_CTX,
413592f3ab15Sopenharmony_ci                0,
413692f3ab15Sopenharmony_ci                ptr::null_mut(),
413792f3ab15Sopenharmony_ci                None,
413892f3ab15Sopenharmony_ci                None,
413992f3ab15Sopenharmony_ci                Some(f),
414092f3ab15Sopenharmony_ci            )
414192f3ab15Sopenharmony_ci        }
414292f3ab15Sopenharmony_ci
414392f3ab15Sopenharmony_ci        unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
414492f3ab15Sopenharmony_ci            ffi::CRYPTO_get_ex_new_index(
414592f3ab15Sopenharmony_ci                ffi::CRYPTO_EX_INDEX_SSL,
414692f3ab15Sopenharmony_ci                0,
414792f3ab15Sopenharmony_ci                ptr::null_mut(),
414892f3ab15Sopenharmony_ci                None,
414992f3ab15Sopenharmony_ci                None,
415092f3ab15Sopenharmony_ci                Some(f),
415192f3ab15Sopenharmony_ci            )
415292f3ab15Sopenharmony_ci        }
415392f3ab15Sopenharmony_ci    } else {
415492f3ab15Sopenharmony_ci        use std::sync::Once;
415592f3ab15Sopenharmony_ci
415692f3ab15Sopenharmony_ci        unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
415792f3ab15Sopenharmony_ci            // hack around https://rt.openssl.org/Ticket/Display.html?id=3710&user=guest&pass=guest
415892f3ab15Sopenharmony_ci            static ONCE: Once = Once::new();
415992f3ab15Sopenharmony_ci            ONCE.call_once(|| {
416092f3ab15Sopenharmony_ci                cfg_if! {
416192f3ab15Sopenharmony_ci                    if #[cfg(not(boringssl))] {
416292f3ab15Sopenharmony_ci                        ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, None);
416392f3ab15Sopenharmony_ci                    } else {
416492f3ab15Sopenharmony_ci                        ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
416592f3ab15Sopenharmony_ci                    }
416692f3ab15Sopenharmony_ci                }
416792f3ab15Sopenharmony_ci            });
416892f3ab15Sopenharmony_ci
416992f3ab15Sopenharmony_ci            cfg_if! {
417092f3ab15Sopenharmony_ci                if #[cfg(not(boringssl))] {
417192f3ab15Sopenharmony_ci                    ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, Some(f))
417292f3ab15Sopenharmony_ci                } else {
417392f3ab15Sopenharmony_ci                    ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f)
417492f3ab15Sopenharmony_ci                }
417592f3ab15Sopenharmony_ci            }
417692f3ab15Sopenharmony_ci        }
417792f3ab15Sopenharmony_ci
417892f3ab15Sopenharmony_ci        unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
417992f3ab15Sopenharmony_ci            // hack around https://rt.openssl.org/Ticket/Display.html?id=3710&user=guest&pass=guest
418092f3ab15Sopenharmony_ci            static ONCE: Once = Once::new();
418192f3ab15Sopenharmony_ci            ONCE.call_once(|| {
418292f3ab15Sopenharmony_ci                #[cfg(not(boringssl))]
418392f3ab15Sopenharmony_ci                ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, None);
418492f3ab15Sopenharmony_ci                #[cfg(boringssl)]
418592f3ab15Sopenharmony_ci                ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
418692f3ab15Sopenharmony_ci            });
418792f3ab15Sopenharmony_ci
418892f3ab15Sopenharmony_ci            #[cfg(not(boringssl))]
418992f3ab15Sopenharmony_ci            return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, Some(f));
419092f3ab15Sopenharmony_ci            #[cfg(boringssl)]
419192f3ab15Sopenharmony_ci            return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f);
419292f3ab15Sopenharmony_ci        }
419392f3ab15Sopenharmony_ci    }
419492f3ab15Sopenharmony_ci}
4195