Skip to main content

openssl/ssl/
mod.rs

1//! SSL/TLS support.
2//!
3//! `SslConnector` and `SslAcceptor` should be used in most cases - they handle
4//! configuration of the OpenSSL primitives for you.
5//!
6//! # Examples
7//!
8//! To connect as a client to a remote server:
9//!
10//! ```no_run
11//! use openssl::ssl::{SslMethod, SslConnector};
12//! use std::io::{Read, Write};
13//! use std::net::TcpStream;
14//!
15//! let connector = SslConnector::builder(SslMethod::tls()).unwrap().build();
16//!
17//! let stream = TcpStream::connect("google.com:443").unwrap();
18//! let mut stream = connector.connect("google.com", stream).unwrap();
19//!
20//! stream.write_all(b"GET / HTTP/1.0\r\n\r\n").unwrap();
21//! let mut res = vec![];
22//! stream.read_to_end(&mut res).unwrap();
23//! println!("{}", String::from_utf8_lossy(&res));
24//! ```
25//!
26//! To accept connections as a server from remote clients:
27//!
28//! ```no_run
29//! use openssl::ssl::{SslMethod, SslAcceptor, SslStream, SslFiletype};
30//! use std::net::{TcpListener, TcpStream};
31//! use std::sync::Arc;
32//! use std::thread;
33//!
34//!
35//! let mut acceptor = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap();
36//! acceptor.set_private_key_file("key.pem", SslFiletype::PEM).unwrap();
37//! acceptor.set_certificate_chain_file("certs.pem").unwrap();
38//! acceptor.check_private_key().unwrap();
39//! let acceptor = Arc::new(acceptor.build());
40//!
41//! let listener = TcpListener::bind("0.0.0.0:8443").unwrap();
42//!
43//! fn handle_client(stream: SslStream<TcpStream>) {
44//!     // ...
45//! }
46//!
47//! for stream in listener.incoming() {
48//!     match stream {
49//!         Ok(stream) => {
50//!             let acceptor = acceptor.clone();
51//!             thread::spawn(move || {
52//!                 let stream = acceptor.accept(stream).unwrap();
53//!                 handle_client(stream);
54//!             });
55//!         }
56//!         Err(e) => { /* connection failed */ }
57//!     }
58//! }
59//! ```
60#[cfg(ossl300)]
61use crate::cvt_long;
62use crate::dh::{Dh, DhRef};
63use crate::ec::EcKeyRef;
64use crate::error::ErrorStack;
65use crate::ex_data::Index;
66#[cfg(ossl111)]
67use crate::hash::MessageDigest;
68#[cfg(any(ossl110, libressl))]
69use crate::nid::Nid;
70use crate::pkey::{HasPrivate, PKeyRef, Params, Private};
71#[cfg(ossl300)]
72use crate::pkey::{PKey, Public};
73#[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
74use crate::srtp::{SrtpProtectionProfile, SrtpProtectionProfileRef};
75use crate::ssl::bio::BioMethod;
76use crate::ssl::callbacks::*;
77use crate::ssl::error::InnerError;
78use crate::stack::{Stack, StackRef, Stackable};
79use crate::util;
80use crate::util::{ForeignTypeExt, ForeignTypeRefExt};
81use crate::x509::store::{X509Store, X509StoreBuilderRef, X509StoreRef};
82use crate::x509::verify::X509VerifyParamRef;
83use crate::x509::{X509Name, X509Ref, X509StoreContextRef, X509VerifyResult, X509};
84use crate::{cvt, cvt_n, cvt_p, init};
85use bitflags::bitflags;
86use cfg_if::cfg_if;
87use foreign_types::{ForeignType, ForeignTypeRef, Opaque};
88use libc::{c_char, c_int, c_long, c_uchar, c_uint, c_void};
89use openssl_macros::corresponds;
90use std::any::TypeId;
91use std::collections::HashMap;
92use std::ffi::{CStr, CString};
93use std::fmt;
94use std::io;
95use std::io::prelude::*;
96use std::marker::PhantomData;
97use std::mem::{self, ManuallyDrop, MaybeUninit};
98use std::ops::{Deref, DerefMut};
99use std::panic::resume_unwind;
100use std::path::Path;
101use std::ptr;
102use std::str;
103use std::sync::{Arc, LazyLock, Mutex, OnceLock};
104
105pub use crate::ssl::connector::{
106    ConnectConfiguration, SslAcceptor, SslAcceptorBuilder, SslConnector, SslConnectorBuilder,
107};
108pub use crate::ssl::error::{Error, ErrorCode, HandshakeError};
109
110mod bio;
111mod callbacks;
112mod connector;
113mod error;
114#[cfg(test)]
115mod test;
116
117/// Returns the OpenSSL name of a cipher corresponding to an RFC-standard cipher name.
118///
119/// If the cipher has no corresponding OpenSSL name, the string `(NONE)` is returned.
120///
121/// Requires OpenSSL 1.1.1 or newer.
122#[corresponds(OPENSSL_cipher_name)]
123#[cfg(ossl111)]
124pub fn cipher_name(std_name: &str) -> &'static str {
125    unsafe {
126        ffi::init();
127
128        let s = CString::new(std_name).unwrap();
129        let ptr = ffi::OPENSSL_cipher_name(s.as_ptr());
130        CStr::from_ptr(ptr).to_str().unwrap()
131    }
132}
133
134cfg_if! {
135    if #[cfg(ossl300)] {
136        type SslOptionsRepr = u64;
137    } else if #[cfg(any(boringssl, awslc))] {
138        type SslOptionsRepr = u32;
139    } else {
140        type SslOptionsRepr = libc::c_ulong;
141    }
142}
143
144bitflags! {
145    /// Options controlling the behavior of an `SslContext`.
146    #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
147    #[repr(transparent)]
148    pub struct SslOptions: SslOptionsRepr {
149        /// Disables a countermeasure against an SSLv3/TLSv1.0 vulnerability affecting CBC ciphers.
150        const DONT_INSERT_EMPTY_FRAGMENTS = ffi::SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS as SslOptionsRepr;
151
152        /// If set, a peer closing the connection without sending a close_notify alert is
153        /// treated as a normal EOF rather than an error.
154        #[cfg(ossl300)]
155        const IGNORE_UNEXPECTED_EOF = ffi::SSL_OP_IGNORE_UNEXPECTED_EOF as SslOptionsRepr;
156
157        /// A "reasonable default" set of options which enables compatibility flags.
158        #[cfg(not(any(boringssl, awslc)))]
159        const ALL = ffi::SSL_OP_ALL as SslOptionsRepr;
160
161        /// Do not query the MTU.
162        ///
163        /// Only affects DTLS connections.
164        const NO_QUERY_MTU = ffi::SSL_OP_NO_QUERY_MTU as SslOptionsRepr;
165
166        /// Enables Cookie Exchange as described in [RFC 4347 Section 4.2.1].
167        ///
168        /// Only affects DTLS connections.
169        ///
170        /// [RFC 4347 Section 4.2.1]: https://tools.ietf.org/html/rfc4347#section-4.2.1
171        #[cfg(not(any(boringssl, awslc)))]
172        const COOKIE_EXCHANGE = ffi::SSL_OP_COOKIE_EXCHANGE as SslOptionsRepr;
173
174        /// Disables the use of session tickets for session resumption.
175        const NO_TICKET = ffi::SSL_OP_NO_TICKET as SslOptionsRepr;
176
177        /// Always start a new session when performing a renegotiation on the server side.
178        #[cfg(not(any(boringssl, awslc)))]
179        const NO_SESSION_RESUMPTION_ON_RENEGOTIATION =
180            ffi::SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION as SslOptionsRepr;
181
182        /// Disables the use of TLS compression.
183        #[cfg(not(any(boringssl, awslc)))]
184        const NO_COMPRESSION = ffi::SSL_OP_NO_COMPRESSION as SslOptionsRepr;
185
186        /// Allow legacy insecure renegotiation with servers or clients that do not support secure
187        /// renegotiation.
188        const ALLOW_UNSAFE_LEGACY_RENEGOTIATION =
189            ffi::SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION as SslOptionsRepr;
190
191        /// Creates a new key for each session when using ECDHE.
192        ///
193        /// This is always enabled in OpenSSL 1.1.0.
194        const SINGLE_ECDH_USE = ffi::SSL_OP_SINGLE_ECDH_USE as SslOptionsRepr;
195
196        /// Creates a new key for each session when using DHE.
197        ///
198        /// This is always enabled in OpenSSL 1.1.0.
199        const SINGLE_DH_USE = ffi::SSL_OP_SINGLE_DH_USE as SslOptionsRepr;
200
201        /// Use the server's preferences rather than the client's when selecting a cipher.
202        ///
203        /// This has no effect on the client side.
204        const CIPHER_SERVER_PREFERENCE = ffi::SSL_OP_CIPHER_SERVER_PREFERENCE as SslOptionsRepr;
205
206        /// Disables version rollback attach detection.
207        const TLS_ROLLBACK_BUG = ffi::SSL_OP_TLS_ROLLBACK_BUG as SslOptionsRepr;
208
209        /// Disables the use of SSLv2.
210        const NO_SSLV2 = ffi::SSL_OP_NO_SSLv2 as SslOptionsRepr;
211
212        /// Disables the use of SSLv3.
213        const NO_SSLV3 = ffi::SSL_OP_NO_SSLv3 as SslOptionsRepr;
214
215        /// Disables the use of TLSv1.0.
216        const NO_TLSV1 = ffi::SSL_OP_NO_TLSv1 as SslOptionsRepr;
217
218        /// Disables the use of TLSv1.1.
219        const NO_TLSV1_1 = ffi::SSL_OP_NO_TLSv1_1 as SslOptionsRepr;
220
221        /// Disables the use of TLSv1.2.
222        const NO_TLSV1_2 = ffi::SSL_OP_NO_TLSv1_2 as SslOptionsRepr;
223
224        /// Disables the use of TLSv1.3.
225        ///
226        /// Requires AWS-LC or BoringSSL or OpenSSL 1.1.1 or newer or LibreSSL.
227        #[cfg(any(ossl111, boringssl, libressl, awslc))]
228        const NO_TLSV1_3 = ffi::SSL_OP_NO_TLSv1_3 as SslOptionsRepr;
229
230        /// Disables the use of DTLSv1.0
231        const NO_DTLSV1 = ffi::SSL_OP_NO_DTLSv1 as SslOptionsRepr;
232
233        /// Disables the use of DTLSv1.2.
234        const NO_DTLSV1_2 = ffi::SSL_OP_NO_DTLSv1_2 as SslOptionsRepr;
235
236        /// Disables the use of all (D)TLS protocol versions.
237        ///
238        /// This can be used as a mask when whitelisting protocol versions.
239        ///
240        /// Requires OpenSSL 1.0.2 or newer.
241        ///
242        /// # Examples
243        ///
244        /// Only support TLSv1.2:
245        ///
246        /// ```rust
247        /// use openssl::ssl::SslOptions;
248        ///
249        /// let options = SslOptions::NO_SSL_MASK & !SslOptions::NO_TLSV1_2;
250        /// ```
251        #[cfg(ossl110)]
252        const NO_SSL_MASK = ffi::SSL_OP_NO_SSL_MASK as SslOptionsRepr;
253
254        /// Disallow all renegotiation in TLSv1.2 and earlier.
255        ///
256        /// Requires OpenSSL 1.1.0h or newer.
257        #[cfg(any(boringssl, ossl110h, awslc))]
258        const NO_RENEGOTIATION = ffi::SSL_OP_NO_RENEGOTIATION as SslOptionsRepr;
259
260        /// Enable TLSv1.3 Compatibility mode.
261        ///
262        /// Requires OpenSSL 1.1.1 or newer. This is on by default in 1.1.1, but a future version
263        /// may have this disabled by default.
264        #[cfg(ossl111)]
265        const ENABLE_MIDDLEBOX_COMPAT = ffi::SSL_OP_ENABLE_MIDDLEBOX_COMPAT as SslOptionsRepr;
266
267        /// Prioritize ChaCha ciphers when preferred by clients.
268        ///
269        /// Temporarily reprioritize ChaCha20-Poly1305 ciphers to the top of the server cipher list
270        /// if a ChaCha20-Poly1305 cipher is at the top of the client cipher list. This helps those
271        /// clients (e.g. mobile) use ChaCha20-Poly1305 if that cipher is anywhere in the server
272        /// cipher list; but still allows other clients to use AES and other ciphers.
273        ///
274        /// Requires enable [`SslOptions::CIPHER_SERVER_PREFERENCE`].
275        /// Requires OpenSSL 1.1.1 or newer.
276        ///
277        /// [`SslOptions::CIPHER_SERVER_PREFERENCE`]: struct.SslOptions.html#associatedconstant.CIPHER_SERVER_PREFERENCE
278        #[cfg(ossl111)]
279        const PRIORITIZE_CHACHA = ffi::SSL_OP_PRIORITIZE_CHACHA as SslOptionsRepr;
280    }
281}
282
283bitflags! {
284    /// Options controlling the behavior of an `SslContext`.
285    #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
286    #[repr(transparent)]
287    pub struct SslMode: SslBitType {
288        /// Enables "short writes".
289        ///
290        /// Normally, a write in OpenSSL will always write out all of the requested data, even if it
291        /// requires more than one TLS record or write to the underlying stream. This option will
292        /// cause a write to return after writing a single TLS record instead.
293        const ENABLE_PARTIAL_WRITE = ffi::SSL_MODE_ENABLE_PARTIAL_WRITE;
294
295        /// Disables a check that the data buffer has not moved between calls when operating in a
296        /// non-blocking context.
297        const ACCEPT_MOVING_WRITE_BUFFER = ffi::SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER;
298
299        /// Enables automatic retries after TLS session events such as renegotiations or heartbeats.
300        ///
301        /// By default, OpenSSL will return a `WantRead` error after a renegotiation or heartbeat.
302        /// This option will cause OpenSSL to automatically continue processing the requested
303        /// operation instead.
304        ///
305        /// Note that `SslStream::read` and `SslStream::write` will automatically retry regardless
306        /// of the state of this option. It only affects `SslStream::ssl_read` and
307        /// `SslStream::ssl_write`.
308        const AUTO_RETRY = ffi::SSL_MODE_AUTO_RETRY;
309
310        /// Disables automatic chain building when verifying a peer's certificate.
311        ///
312        /// TLS peers are responsible for sending the entire certificate chain from the leaf to a
313        /// trusted root, but some will incorrectly not do so. OpenSSL will try to build the chain
314        /// out of certificates it knows of, and this option will disable that behavior.
315        const NO_AUTO_CHAIN = ffi::SSL_MODE_NO_AUTO_CHAIN;
316
317        /// Release memory buffers when the session does not need them.
318        ///
319        /// This saves ~34 KiB of memory for idle streams.
320        const RELEASE_BUFFERS = ffi::SSL_MODE_RELEASE_BUFFERS;
321
322        /// Sends the fake `TLS_FALLBACK_SCSV` cipher suite in the ClientHello message of a
323        /// handshake.
324        ///
325        /// This should only be enabled if a client has failed to connect to a server which
326        /// attempted to downgrade the protocol version of the session.
327        ///
328        /// Do not use this unless you know what you're doing!
329        #[cfg(not(libressl))]
330        const SEND_FALLBACK_SCSV = ffi::SSL_MODE_SEND_FALLBACK_SCSV;
331    }
332}
333
334/// A type specifying the kind of protocol an `SslContext` will speak.
335#[derive(Copy, Clone)]
336pub struct SslMethod(*const ffi::SSL_METHOD);
337
338impl SslMethod {
339    /// Support all versions of the TLS protocol.
340    #[corresponds(TLS_method)]
341    pub fn tls() -> SslMethod {
342        unsafe { SslMethod(TLS_method()) }
343    }
344
345    /// Support all versions of the DTLS protocol.
346    #[corresponds(DTLS_method)]
347    pub fn dtls() -> SslMethod {
348        unsafe { SslMethod(DTLS_method()) }
349    }
350
351    /// Support all versions of the TLS protocol, explicitly as a client.
352    #[corresponds(TLS_client_method)]
353    pub fn tls_client() -> SslMethod {
354        unsafe { SslMethod(TLS_client_method()) }
355    }
356
357    /// Support all versions of the TLS protocol, explicitly as a server.
358    #[corresponds(TLS_server_method)]
359    pub fn tls_server() -> SslMethod {
360        unsafe { SslMethod(TLS_server_method()) }
361    }
362
363    /// Support all versions of the DTLS protocol, explicitly as a client.
364    #[corresponds(DTLS_client_method)]
365    pub fn dtls_client() -> SslMethod {
366        unsafe { SslMethod(DTLS_client_method()) }
367    }
368
369    /// Support all versions of the DTLS protocol, explicitly as a server.
370    #[corresponds(DTLS_server_method)]
371    pub fn dtls_server() -> SslMethod {
372        unsafe { SslMethod(DTLS_server_method()) }
373    }
374
375    /// Constructs an `SslMethod` from a pointer to the underlying OpenSSL value.
376    ///
377    /// # Safety
378    ///
379    /// The caller must ensure the pointer is valid.
380    pub unsafe fn from_ptr(ptr: *const ffi::SSL_METHOD) -> SslMethod {
381        SslMethod(ptr)
382    }
383
384    /// Returns a pointer to the underlying OpenSSL value.
385    #[allow(clippy::trivially_copy_pass_by_ref)]
386    pub fn as_ptr(&self) -> *const ffi::SSL_METHOD {
387        self.0
388    }
389}
390
391unsafe impl Sync for SslMethod {}
392unsafe impl Send for SslMethod {}
393
394bitflags! {
395    /// Options controlling the behavior of certificate verification.
396    #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
397    #[repr(transparent)]
398    pub struct SslVerifyMode: i32 {
399        /// Verifies that the peer's certificate is trusted.
400        ///
401        /// On the server side, this will cause OpenSSL to request a certificate from the client.
402        const PEER = ffi::SSL_VERIFY_PEER;
403
404        /// Disables verification of the peer's certificate.
405        ///
406        /// On the server side, this will cause OpenSSL to not request a certificate from the
407        /// client. On the client side, the certificate will be checked for validity, but the
408        /// negotiation will continue regardless of the result of that check.
409        const NONE = ffi::SSL_VERIFY_NONE;
410
411        /// On the server side, abort the handshake if the client did not send a certificate.
412        ///
413        /// This should be paired with `SSL_VERIFY_PEER`. It has no effect on the client side.
414        const FAIL_IF_NO_PEER_CERT = ffi::SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
415
416        /// On the server side, only request a certificate from the client during the initial
417        /// handshake, and not during renegotiations.
418        ///
419        /// This should be paired with `SSL_VERIFY_PEER`. It has no effect on the client side.
420        #[cfg(not(any(boringssl, awslc)))]
421        const CLIENT_ONCE = ffi::SSL_VERIFY_CLIENT_ONCE;
422
423        /// On the server side, request a certificate from the client via a TLSv1.3
424        /// post-handshake authentication request rather than during the initial handshake.
425        ///
426        /// This should be paired with `SSL_VERIFY_PEER`. It has no effect on the client side.
427        ///
428        /// Requires OpenSSL 1.1.1 or newer.
429        #[cfg(ossl111)]
430        const POST_HANDSHAKE = ffi::SSL_VERIFY_POST_HANDSHAKE;
431    }
432}
433
434#[cfg(any(boringssl, awslc))]
435type SslBitType = c_int;
436#[cfg(not(any(boringssl, awslc)))]
437type SslBitType = c_long;
438
439#[cfg(any(boringssl, awslc))]
440type SslTimeTy = u64;
441#[cfg(not(any(boringssl, awslc)))]
442type SslTimeTy = c_long;
443
444bitflags! {
445    /// Options controlling the behavior of session caching.
446    #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
447    #[repr(transparent)]
448    pub struct SslSessionCacheMode: SslBitType {
449        /// No session caching for the client or server takes place.
450        const OFF = ffi::SSL_SESS_CACHE_OFF;
451
452        /// Enable session caching on the client side.
453        ///
454        /// OpenSSL has no way of identifying the proper session to reuse automatically, so the
455        /// application is responsible for setting it explicitly via [`SslRef::set_session`].
456        ///
457        /// [`SslRef::set_session`]: struct.SslRef.html#method.set_session
458        const CLIENT = ffi::SSL_SESS_CACHE_CLIENT;
459
460        /// Enable session caching on the server side.
461        ///
462        /// This is the default mode.
463        const SERVER = ffi::SSL_SESS_CACHE_SERVER;
464
465        /// Enable session caching on both the client and server side.
466        const BOTH = ffi::SSL_SESS_CACHE_BOTH;
467
468        /// Disable automatic removal of expired sessions from the session cache.
469        const NO_AUTO_CLEAR = ffi::SSL_SESS_CACHE_NO_AUTO_CLEAR;
470
471        /// Disable use of the internal session cache for session lookups.
472        const NO_INTERNAL_LOOKUP = ffi::SSL_SESS_CACHE_NO_INTERNAL_LOOKUP;
473
474        /// Disable use of the internal session cache for session storage.
475        const NO_INTERNAL_STORE = ffi::SSL_SESS_CACHE_NO_INTERNAL_STORE;
476
477        /// Disable use of the internal session cache for storage and lookup.
478        const NO_INTERNAL = ffi::SSL_SESS_CACHE_NO_INTERNAL;
479    }
480}
481
482#[cfg(ossl111)]
483bitflags! {
484    /// Which messages and under which conditions an extension should be added or expected.
485    #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
486    #[repr(transparent)]
487    pub struct ExtensionContext: c_uint {
488        /// This extension is only allowed in TLS
489        const TLS_ONLY = ffi::SSL_EXT_TLS_ONLY;
490        /// This extension is only allowed in DTLS
491        const DTLS_ONLY = ffi::SSL_EXT_DTLS_ONLY;
492        /// Some extensions may be allowed in DTLS but we don't implement them for it
493        const TLS_IMPLEMENTATION_ONLY = ffi::SSL_EXT_TLS_IMPLEMENTATION_ONLY;
494        /// Most extensions are not defined for SSLv3 but EXT_TYPE_renegotiate is
495        const SSL3_ALLOWED = ffi::SSL_EXT_SSL3_ALLOWED;
496        /// Extension is only defined for TLS1.2 and below
497        const TLS1_2_AND_BELOW_ONLY = ffi::SSL_EXT_TLS1_2_AND_BELOW_ONLY;
498        /// Extension is only defined for TLS1.3 and above
499        const TLS1_3_ONLY = ffi::SSL_EXT_TLS1_3_ONLY;
500        /// Ignore this extension during parsing if we are resuming
501        const IGNORE_ON_RESUMPTION = ffi::SSL_EXT_IGNORE_ON_RESUMPTION;
502        const CLIENT_HELLO = ffi::SSL_EXT_CLIENT_HELLO;
503        /// Really means TLS1.2 or below
504        const TLS1_2_SERVER_HELLO = ffi::SSL_EXT_TLS1_2_SERVER_HELLO;
505        const TLS1_3_SERVER_HELLO = ffi::SSL_EXT_TLS1_3_SERVER_HELLO;
506        const TLS1_3_ENCRYPTED_EXTENSIONS = ffi::SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS;
507        const TLS1_3_HELLO_RETRY_REQUEST = ffi::SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST;
508        const TLS1_3_CERTIFICATE = ffi::SSL_EXT_TLS1_3_CERTIFICATE;
509        const TLS1_3_NEW_SESSION_TICKET = ffi::SSL_EXT_TLS1_3_NEW_SESSION_TICKET;
510        const TLS1_3_CERTIFICATE_REQUEST = ffi::SSL_EXT_TLS1_3_CERTIFICATE_REQUEST;
511    }
512}
513
514/// An identifier of the format of a certificate or key file.
515#[derive(Copy, Clone)]
516pub struct SslFiletype(c_int);
517
518impl SslFiletype {
519    /// The PEM format.
520    ///
521    /// This corresponds to `SSL_FILETYPE_PEM`.
522    pub const PEM: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_PEM);
523
524    /// The ASN1 format.
525    ///
526    /// This corresponds to `SSL_FILETYPE_ASN1`.
527    pub const ASN1: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_ASN1);
528
529    /// Constructs an `SslFiletype` from a raw OpenSSL value.
530    pub fn from_raw(raw: c_int) -> SslFiletype {
531        SslFiletype(raw)
532    }
533
534    /// Returns the raw OpenSSL value represented by this type.
535    #[allow(clippy::trivially_copy_pass_by_ref)]
536    pub fn as_raw(&self) -> c_int {
537        self.0
538    }
539}
540
541/// An identifier of a certificate status type.
542#[derive(Copy, Clone)]
543pub struct StatusType(c_int);
544
545impl StatusType {
546    /// An OSCP status.
547    pub const OCSP: StatusType = StatusType(ffi::TLSEXT_STATUSTYPE_ocsp);
548
549    /// Constructs a `StatusType` from a raw OpenSSL value.
550    pub fn from_raw(raw: c_int) -> StatusType {
551        StatusType(raw)
552    }
553
554    /// Returns the raw OpenSSL value represented by this type.
555    #[allow(clippy::trivially_copy_pass_by_ref)]
556    pub fn as_raw(&self) -> c_int {
557        self.0
558    }
559}
560
561/// An identifier of a session name type.
562#[derive(Copy, Clone)]
563pub struct NameType(c_int);
564
565impl NameType {
566    /// A host name.
567    pub const HOST_NAME: NameType = NameType(ffi::TLSEXT_NAMETYPE_host_name);
568
569    /// Constructs a `StatusType` from a raw OpenSSL value.
570    pub fn from_raw(raw: c_int) -> StatusType {
571        StatusType(raw)
572    }
573
574    /// Returns the raw OpenSSL value represented by this type.
575    #[allow(clippy::trivially_copy_pass_by_ref)]
576    pub fn as_raw(&self) -> c_int {
577        self.0
578    }
579}
580
581static INDEXES: LazyLock<Mutex<HashMap<TypeId, c_int>>> =
582    LazyLock::new(|| Mutex::new(HashMap::new()));
583static SSL_INDEXES: LazyLock<Mutex<HashMap<TypeId, c_int>>> =
584    LazyLock::new(|| Mutex::new(HashMap::new()));
585static SESSION_CTX_INDEX: OnceLock<Index<Ssl, SslContext>> = OnceLock::new();
586
587fn try_get_session_ctx_index() -> Result<&'static Index<Ssl, SslContext>, ErrorStack> {
588    // Once `OnceLock::get_or_try_init` (rust-lang/rust#109737) is stable, this
589    // can collapse to `SESSION_CTX_INDEX.get_or_try_init(Ssl::new_ex_index)`.
590    if let Some(idx) = SESSION_CTX_INDEX.get() {
591        return Ok(idx);
592    }
593    let new = Ssl::new_ex_index::<SslContext>()?;
594    Ok(SESSION_CTX_INDEX.get_or_init(|| new))
595}
596
597unsafe extern "C" fn free_data_box<T>(
598    _parent: *mut c_void,
599    ptr: *mut c_void,
600    _ad: *mut ffi::CRYPTO_EX_DATA,
601    _idx: c_int,
602    _argl: c_long,
603    _argp: *mut c_void,
604) {
605    if !ptr.is_null() {
606        let _ = Box::<T>::from_raw(ptr as *mut T);
607    }
608}
609
610/// An error returned from the SNI callback.
611#[derive(Debug, Copy, Clone, PartialEq, Eq)]
612pub struct SniError(c_int);
613
614impl SniError {
615    /// Abort the handshake with a fatal alert.
616    pub const ALERT_FATAL: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
617
618    /// Send a warning alert to the client and continue the handshake.
619    pub const ALERT_WARNING: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_WARNING);
620
621    pub const NOACK: SniError = SniError(ffi::SSL_TLSEXT_ERR_NOACK);
622}
623
624/// An SSL/TLS alert.
625#[derive(Debug, Copy, Clone, PartialEq, Eq)]
626pub struct SslAlert(c_int);
627
628impl SslAlert {
629    /// Alert 112 - `unrecognized_name`.
630    pub const UNRECOGNIZED_NAME: SslAlert = SslAlert(ffi::SSL_AD_UNRECOGNIZED_NAME);
631    pub const ILLEGAL_PARAMETER: SslAlert = SslAlert(ffi::SSL_AD_ILLEGAL_PARAMETER);
632    pub const DECODE_ERROR: SslAlert = SslAlert(ffi::SSL_AD_DECODE_ERROR);
633}
634
635/// An error returned from an ALPN selection callback.
636///
637/// Requires AWS-LC or BoringSSL or LibreSSL or OpenSSL 1.0.2 or newer.
638#[derive(Debug, Copy, Clone, PartialEq, Eq)]
639pub struct AlpnError(c_int);
640
641impl AlpnError {
642    /// Terminate the handshake with a fatal alert.
643    pub const ALERT_FATAL: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
644
645    /// Do not select a protocol, but continue the handshake.
646    pub const NOACK: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_NOACK);
647}
648
649/// The result of a client hello callback.
650///
651/// Requires OpenSSL 1.1.1 or newer.
652#[cfg(ossl111)]
653#[derive(Debug, Copy, Clone, PartialEq, Eq)]
654pub struct ClientHelloResponse(c_int);
655
656#[cfg(ossl111)]
657impl ClientHelloResponse {
658    /// Continue the handshake.
659    pub const SUCCESS: ClientHelloResponse = ClientHelloResponse(ffi::SSL_CLIENT_HELLO_SUCCESS);
660
661    /// Return from the handshake with an `ErrorCode::WANT_CLIENT_HELLO_CB` error.
662    pub const RETRY: ClientHelloResponse = ClientHelloResponse(ffi::SSL_CLIENT_HELLO_RETRY);
663}
664
665/// An SSL/TLS protocol version.
666#[derive(Debug, Copy, Clone, PartialEq, Eq)]
667pub struct SslVersion(c_int);
668
669impl SslVersion {
670    /// SSLv3
671    pub const SSL3: SslVersion = SslVersion(ffi::SSL3_VERSION);
672
673    /// TLSv1.0
674    pub const TLS1: SslVersion = SslVersion(ffi::TLS1_VERSION);
675
676    /// TLSv1.1
677    pub const TLS1_1: SslVersion = SslVersion(ffi::TLS1_1_VERSION);
678
679    /// TLSv1.2
680    pub const TLS1_2: SslVersion = SslVersion(ffi::TLS1_2_VERSION);
681
682    /// TLSv1.3
683    ///
684    /// Requires AWS-LC or BoringSSL or OpenSSL 1.1.1 or newer or LibreSSL.
685    #[cfg(any(ossl111, libressl, boringssl, awslc))]
686    pub const TLS1_3: SslVersion = SslVersion(ffi::TLS1_3_VERSION);
687
688    /// DTLSv1.0
689    ///
690    /// DTLS 1.0 corresponds to TLS 1.1.
691    pub const DTLS1: SslVersion = SslVersion(ffi::DTLS1_VERSION);
692
693    /// DTLSv1.2
694    ///
695    /// DTLS 1.2 corresponds to TLS 1.2 to harmonize versions. There was never a DTLS 1.1.
696    pub const DTLS1_2: SslVersion = SslVersion(ffi::DTLS1_2_VERSION);
697}
698
699cfg_if! {
700    if #[cfg(any(boringssl, awslc))] {
701        type SslCacheTy = i64;
702        type SslCacheSize = libc::c_ulong;
703        type MtuTy = u32;
704        type SizeTy = usize;
705    } else {
706        type SslCacheTy = i64;
707        type SslCacheSize = c_long;
708        type MtuTy = c_long;
709        type SizeTy = u32;
710    }
711}
712
713/// A standard implementation of protocol selection for Application Layer Protocol Negotiation
714/// (ALPN).
715///
716/// `server` should contain the server's list of supported protocols and `client` the client's. They
717/// must both be in the ALPN wire format. See the documentation for
718/// [`SslContextBuilder::set_alpn_protos`] for details.
719///
720/// It will select the first protocol supported by the server which is also supported by the client.
721///
722/// [`SslContextBuilder::set_alpn_protos`]: struct.SslContextBuilder.html#method.set_alpn_protos
723#[corresponds(SSL_select_next_proto)]
724pub fn select_next_proto<'a>(server: &'a [u8], client: &'a [u8]) -> Option<&'a [u8]> {
725    unsafe {
726        let mut out = ptr::null_mut();
727        let mut outlen = 0;
728        let r = ffi::SSL_select_next_proto(
729            &mut out,
730            &mut outlen,
731            server.as_ptr(),
732            server.len() as c_uint,
733            client.as_ptr(),
734            client.len() as c_uint,
735        );
736        if r == ffi::OPENSSL_NPN_NEGOTIATED {
737            Some(util::from_raw_parts(out as *const u8, outlen as usize))
738        } else {
739            None
740        }
741    }
742}
743
744/// A builder for `SslContext`s.
745pub struct SslContextBuilder(SslContext);
746
747impl SslContextBuilder {
748    /// Creates a new `SslContextBuilder`.
749    #[corresponds(SSL_CTX_new)]
750    pub fn new(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
751        unsafe {
752            init();
753            let ctx = cvt_p(ffi::SSL_CTX_new(method.as_ptr()))?;
754
755            Ok(SslContextBuilder::from_ptr(ctx))
756        }
757    }
758
759    /// Creates an `SslContextBuilder` from a pointer to a raw OpenSSL value.
760    ///
761    /// # Safety
762    ///
763    /// The caller must ensure that the pointer is valid and uniquely owned by the builder.
764    pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX) -> SslContextBuilder {
765        SslContextBuilder(SslContext::from_ptr(ctx))
766    }
767
768    /// Returns a pointer to the raw OpenSSL value.
769    pub fn as_ptr(&self) -> *mut ffi::SSL_CTX {
770        self.0.as_ptr()
771    }
772
773    /// Configures the certificate verification method for new connections.
774    #[corresponds(SSL_CTX_set_verify)]
775    pub fn set_verify(&mut self, mode: SslVerifyMode) {
776        unsafe {
777            ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, None);
778        }
779    }
780
781    /// Configures the certificate verification method for new connections and
782    /// registers a verification callback.
783    ///
784    /// The callback is passed a boolean indicating if OpenSSL's internal verification succeeded as
785    /// well as a reference to the `X509StoreContext` which can be used to examine the certificate
786    /// chain. It should return a boolean indicating if verification succeeded.
787    #[corresponds(SSL_CTX_set_verify)]
788    pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
789    where
790        F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
791    {
792        unsafe {
793            self.set_ex_data(SslContext::cached_ex_index::<F>(), verify);
794            ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, Some(raw_verify::<F>));
795        }
796    }
797
798    /// Configures the server name indication (SNI) callback for new connections.
799    ///
800    /// SNI is used to allow a single server to handle requests for multiple domains, each of which
801    /// has its own certificate chain and configuration.
802    ///
803    /// Obtain the server name with the `servername` method and then set the corresponding context
804    /// with `set_ssl_context`
805    #[corresponds(SSL_CTX_set_tlsext_servername_callback)]
806    // FIXME tlsext prefix?
807    pub fn set_servername_callback<F>(&mut self, callback: F)
808    where
809        F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), SniError> + 'static + Sync + Send,
810    {
811        unsafe {
812            // The SNI callback is somewhat unique in that the callback associated with the original
813            // context associated with an SSL can be used even if the SSL's context has been swapped
814            // out. When that happens, we wouldn't be able to look up the callback's state in the
815            // context's ex data. Instead, pass the pointer directly as the servername arg. It's
816            // still stored in ex data to manage the lifetime.
817            let arg = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
818            ffi::SSL_CTX_set_tlsext_servername_arg(self.as_ptr(), arg);
819            #[cfg(any(boringssl, awslc))]
820            ffi::SSL_CTX_set_tlsext_servername_callback(self.as_ptr(), Some(raw_sni::<F>));
821            #[cfg(not(any(boringssl, awslc)))]
822            ffi::SSL_CTX_set_tlsext_servername_callback__fixed_rust(
823                self.as_ptr(),
824                Some(raw_sni::<F>),
825            );
826        }
827    }
828
829    /// Sets the certificate verification depth.
830    ///
831    /// If the peer's certificate chain is longer than this value, verification will fail.
832    #[corresponds(SSL_CTX_set_verify_depth)]
833    pub fn set_verify_depth(&mut self, depth: u32) {
834        unsafe {
835            ffi::SSL_CTX_set_verify_depth(self.as_ptr(), depth as c_int);
836        }
837    }
838
839    /// Sets a custom certificate store for verifying peer certificates.
840    ///
841    /// Requires OpenSSL 1.1.0 or newer.
842    #[corresponds(SSL_CTX_set0_verify_cert_store)]
843    #[cfg(ossl110)]
844    pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
845        unsafe {
846            let ptr = cert_store.as_ptr();
847            cvt(ffi::SSL_CTX_set0_verify_cert_store(self.as_ptr(), ptr) as c_int)?;
848            mem::forget(cert_store);
849
850            Ok(())
851        }
852    }
853
854    /// Replaces the context's certificate store.
855    #[corresponds(SSL_CTX_set_cert_store)]
856    pub fn set_cert_store(&mut self, cert_store: X509Store) {
857        unsafe {
858            ffi::SSL_CTX_set_cert_store(self.as_ptr(), cert_store.as_ptr());
859            mem::forget(cert_store);
860        }
861    }
862
863    /// Controls read ahead behavior.
864    ///
865    /// If enabled, OpenSSL will read as much data as is available from the underlying stream,
866    /// instead of a single record at a time.
867    ///
868    /// It has no effect when used with DTLS.
869    #[corresponds(SSL_CTX_set_read_ahead)]
870    pub fn set_read_ahead(&mut self, read_ahead: bool) {
871        unsafe {
872            ffi::SSL_CTX_set_read_ahead(self.as_ptr(), read_ahead as SslBitType);
873        }
874    }
875
876    /// Sets the mode used by the context, returning the previous mode.
877    #[corresponds(SSL_CTX_set_mode)]
878    pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
879        unsafe {
880            let bits = ffi::SSL_CTX_set_mode(self.as_ptr(), mode.bits() as MtuTy) as SslBitType;
881            SslMode::from_bits_retain(bits)
882        }
883    }
884
885    /// Sets the parameters to be used during ephemeral Diffie-Hellman key exchange.
886    #[corresponds(SSL_CTX_set_tmp_dh)]
887    pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
888        unsafe { cvt(ffi::SSL_CTX_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
889    }
890
891    /// Sets the callback which will generate parameters to be used during ephemeral Diffie-Hellman
892    /// key exchange.
893    ///
894    /// The callback is provided with a reference to the `Ssl` for the session, as well as a boolean
895    /// indicating if the selected cipher is export-grade, and the key length. The export and key
896    /// length options are archaic and should be ignored in almost all cases.
897    #[corresponds(SSL_CTX_set_tmp_dh_callback)]
898    pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
899    where
900        F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
901    {
902        unsafe {
903            self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
904
905            #[cfg(not(any(boringssl, awslc)))]
906            ffi::SSL_CTX_set_tmp_dh_callback__fixed_rust(self.as_ptr(), Some(raw_tmp_dh::<F>));
907            #[cfg(any(boringssl, awslc))]
908            ffi::SSL_CTX_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh::<F>));
909        }
910    }
911
912    /// Sets the parameters to be used during ephemeral elliptic curve Diffie-Hellman key exchange.
913    #[corresponds(SSL_CTX_set_tmp_ecdh)]
914    pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
915        unsafe { cvt(ffi::SSL_CTX_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
916    }
917
918    /// Use the default locations of trusted certificates for verification.
919    ///
920    /// These locations are read from the `SSL_CERT_FILE` and `SSL_CERT_DIR` environment variables
921    /// if present, or defaults specified at OpenSSL build time otherwise.
922    #[corresponds(SSL_CTX_set_default_verify_paths)]
923    pub fn set_default_verify_paths(&mut self) -> Result<(), ErrorStack> {
924        unsafe { cvt(ffi::SSL_CTX_set_default_verify_paths(self.as_ptr())).map(|_| ()) }
925    }
926
927    /// Loads trusted root certificates from a file.
928    ///
929    /// The file should contain a sequence of PEM-formatted CA certificates.
930    #[corresponds(SSL_CTX_load_verify_locations)]
931    pub fn set_ca_file<P: AsRef<Path>>(&mut self, file: P) -> Result<(), ErrorStack> {
932        self.load_verify_locations(Some(file.as_ref()), None)
933    }
934
935    /// Loads trusted root certificates from a file and/or a directory.
936    #[corresponds(SSL_CTX_load_verify_locations)]
937    pub fn load_verify_locations(
938        &mut self,
939        ca_file: Option<&Path>,
940        ca_path: Option<&Path>,
941    ) -> Result<(), ErrorStack> {
942        let ca_file = ca_file.map(|p| CString::new(p.as_os_str().to_str().unwrap()).unwrap());
943        let ca_path = ca_path.map(|p| CString::new(p.as_os_str().to_str().unwrap()).unwrap());
944        unsafe {
945            cvt(ffi::SSL_CTX_load_verify_locations(
946                self.as_ptr(),
947                ca_file.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
948                ca_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
949            ))
950            .map(|_| ())
951        }
952    }
953
954    /// Sets the list of CA names sent to the client.
955    ///
956    /// The CA certificates must still be added to the trust root - they are not automatically set
957    /// as trusted by this method.
958    #[corresponds(SSL_CTX_set_client_CA_list)]
959    pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
960        unsafe {
961            ffi::SSL_CTX_set_client_CA_list(self.as_ptr(), list.as_ptr());
962            mem::forget(list);
963        }
964    }
965
966    /// Add the provided CA certificate to the list sent by the server to the client when
967    /// requesting client-side TLS authentication.
968    #[corresponds(SSL_CTX_add_client_CA)]
969    pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
970        unsafe { cvt(ffi::SSL_CTX_add_client_CA(self.as_ptr(), cacert.as_ptr())).map(|_| ()) }
971    }
972
973    /// Set the context identifier for sessions.
974    ///
975    /// This value identifies the server's session cache to clients, telling them when they're
976    /// able to reuse sessions. It should be set to a unique value per server, unless multiple
977    /// servers share a session cache.
978    ///
979    /// This value should be set when using client certificates, or each request will fail its
980    /// handshake and need to be restarted.
981    #[corresponds(SSL_CTX_set_session_id_context)]
982    pub fn set_session_id_context(&mut self, sid_ctx: &[u8]) -> Result<(), ErrorStack> {
983        unsafe {
984            assert!(sid_ctx.len() <= c_uint::MAX as usize);
985            cvt(ffi::SSL_CTX_set_session_id_context(
986                self.as_ptr(),
987                sid_ctx.as_ptr(),
988                sid_ctx.len() as SizeTy,
989            ))
990            .map(|_| ())
991        }
992    }
993
994    /// Loads a leaf certificate from a file.
995    ///
996    /// Only a single certificate will be loaded - use `add_extra_chain_cert` to add the remainder
997    /// of the certificate chain, or `set_certificate_chain_file` to load the entire chain from a
998    /// single file.
999    #[corresponds(SSL_CTX_use_certificate_file)]
1000    pub fn set_certificate_file<P: AsRef<Path>>(
1001        &mut self,
1002        file: P,
1003        file_type: SslFiletype,
1004    ) -> Result<(), ErrorStack> {
1005        let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1006        unsafe {
1007            cvt(ffi::SSL_CTX_use_certificate_file(
1008                self.as_ptr(),
1009                file.as_ptr() as *const _,
1010                file_type.as_raw(),
1011            ))
1012            .map(|_| ())
1013        }
1014    }
1015
1016    /// Loads a certificate chain from a file.
1017    ///
1018    /// The file should contain a sequence of PEM-formatted certificates, the first being the leaf
1019    /// certificate, and the remainder forming the chain of certificates up to and including the
1020    /// trusted root certificate.
1021    #[corresponds(SSL_CTX_use_certificate_chain_file)]
1022    pub fn set_certificate_chain_file<P: AsRef<Path>>(
1023        &mut self,
1024        file: P,
1025    ) -> Result<(), ErrorStack> {
1026        let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1027        unsafe {
1028            cvt(ffi::SSL_CTX_use_certificate_chain_file(
1029                self.as_ptr(),
1030                file.as_ptr() as *const _,
1031            ))
1032            .map(|_| ())
1033        }
1034    }
1035
1036    /// Sets the leaf certificate.
1037    ///
1038    /// Use `add_extra_chain_cert` to add the remainder of the certificate chain.
1039    #[corresponds(SSL_CTX_use_certificate)]
1040    pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1041        unsafe { cvt(ffi::SSL_CTX_use_certificate(self.as_ptr(), cert.as_ptr())).map(|_| ()) }
1042    }
1043
1044    /// Appends a certificate to the certificate chain.
1045    ///
1046    /// This chain should contain all certificates necessary to go from the certificate specified by
1047    /// `set_certificate` to a trusted root.
1048    #[corresponds(SSL_CTX_add_extra_chain_cert)]
1049    pub fn add_extra_chain_cert(&mut self, cert: X509) -> Result<(), ErrorStack> {
1050        unsafe {
1051            cvt(ffi::SSL_CTX_add_extra_chain_cert(self.as_ptr(), cert.as_ptr()) as c_int)?;
1052            mem::forget(cert);
1053            Ok(())
1054        }
1055    }
1056
1057    /// Loads the private key from a file.
1058    #[corresponds(SSL_CTX_use_PrivateKey_file)]
1059    pub fn set_private_key_file<P: AsRef<Path>>(
1060        &mut self,
1061        file: P,
1062        file_type: SslFiletype,
1063    ) -> Result<(), ErrorStack> {
1064        let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1065        unsafe {
1066            cvt(ffi::SSL_CTX_use_PrivateKey_file(
1067                self.as_ptr(),
1068                file.as_ptr() as *const _,
1069                file_type.as_raw(),
1070            ))
1071            .map(|_| ())
1072        }
1073    }
1074
1075    /// Sets the private key.
1076    #[corresponds(SSL_CTX_use_PrivateKey)]
1077    pub fn set_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1078    where
1079        T: HasPrivate,
1080    {
1081        unsafe { cvt(ffi::SSL_CTX_use_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) }
1082    }
1083
1084    /// Sets the list of supported ciphers for protocols before TLSv1.3.
1085    ///
1086    /// The `set_ciphersuites` method controls the cipher suites for TLSv1.3.
1087    ///
1088    /// See [`ciphers`] for details on the format.
1089    ///
1090    /// [`ciphers`]: https://docs.openssl.org/master/man1/ciphers/
1091    #[corresponds(SSL_CTX_set_cipher_list)]
1092    pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1093        let cipher_list = CString::new(cipher_list).unwrap();
1094        unsafe {
1095            cvt(ffi::SSL_CTX_set_cipher_list(
1096                self.as_ptr(),
1097                cipher_list.as_ptr() as *const _,
1098            ))
1099            .map(|_| ())
1100        }
1101    }
1102
1103    /// Sets the list of supported ciphers for the TLSv1.3 protocol.
1104    ///
1105    /// The `set_cipher_list` method controls the cipher suites for protocols before TLSv1.3.
1106    ///
1107    /// The format consists of TLSv1.3 cipher suite names separated by `:` characters in order of
1108    /// preference.
1109    ///
1110    /// Requires OpenSSL 1.1.1 or newer or LibreSSL.
1111    #[corresponds(SSL_CTX_set_ciphersuites)]
1112    #[cfg(any(ossl111, libressl))]
1113    pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1114        let cipher_list = CString::new(cipher_list).unwrap();
1115        unsafe {
1116            cvt(ffi::SSL_CTX_set_ciphersuites(
1117                self.as_ptr(),
1118                cipher_list.as_ptr() as *const _,
1119            ))
1120            .map(|_| ())
1121        }
1122    }
1123
1124    /// Enables ECDHE key exchange with an automatically chosen curve list.
1125    ///
1126    /// Requires LibreSSL.
1127    #[corresponds(SSL_CTX_set_ecdh_auto)]
1128    #[cfg(libressl)]
1129    pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
1130        unsafe { cvt(ffi::SSL_CTX_set_ecdh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) }
1131    }
1132
1133    /// Sets the options used by the context, returning the old set.
1134    ///
1135    /// # Note
1136    ///
1137    /// This *enables* the specified options, but does not disable unspecified options. Use
1138    /// `clear_options` for that.
1139    #[corresponds(SSL_CTX_set_options)]
1140    pub fn set_options(&mut self, option: SslOptions) -> SslOptions {
1141        let bits =
1142            unsafe { ffi::SSL_CTX_set_options(self.as_ptr(), option.bits()) } as SslOptionsRepr;
1143        SslOptions::from_bits_retain(bits)
1144    }
1145
1146    /// Returns the options used by the context.
1147    #[corresponds(SSL_CTX_get_options)]
1148    pub fn options(&self) -> SslOptions {
1149        let bits = unsafe { ffi::SSL_CTX_get_options(self.as_ptr()) } as SslOptionsRepr;
1150        SslOptions::from_bits_retain(bits)
1151    }
1152
1153    /// Clears the options used by the context, returning the old set.
1154    #[corresponds(SSL_CTX_clear_options)]
1155    pub fn clear_options(&mut self, option: SslOptions) -> SslOptions {
1156        let bits =
1157            unsafe { ffi::SSL_CTX_clear_options(self.as_ptr(), option.bits()) } as SslOptionsRepr;
1158        SslOptions::from_bits_retain(bits)
1159    }
1160
1161    /// Sets the minimum supported protocol version.
1162    ///
1163    /// A value of `None` will enable protocol versions down to the lowest version supported by
1164    /// OpenSSL.
1165    #[corresponds(SSL_CTX_set_min_proto_version)]
1166    pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1167        unsafe {
1168            cvt(ffi::SSL_CTX_set_min_proto_version(
1169                self.as_ptr(),
1170                version.map_or(0, |v| v.0 as _),
1171            ))
1172            .map(|_| ())
1173        }
1174    }
1175
1176    /// Sets the maximum supported protocol version.
1177    ///
1178    /// A value of `None` will enable protocol versions up to the highest version supported by
1179    /// OpenSSL.
1180    #[corresponds(SSL_CTX_set_max_proto_version)]
1181    pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1182        unsafe {
1183            cvt(ffi::SSL_CTX_set_max_proto_version(
1184                self.as_ptr(),
1185                version.map_or(0, |v| v.0 as _),
1186            ))
1187            .map(|_| ())
1188        }
1189    }
1190
1191    /// Gets the minimum supported protocol version.
1192    ///
1193    /// A value of `None` indicates that all versions down to the lowest version supported by
1194    /// OpenSSL are enabled.
1195    ///
1196    /// Requires LibreSSL or OpenSSL 1.1.0g or newer.
1197    #[corresponds(SSL_CTX_get_min_proto_version)]
1198    #[cfg(any(ossl110g, libressl))]
1199    pub fn min_proto_version(&mut self) -> Option<SslVersion> {
1200        unsafe {
1201            let r = ffi::SSL_CTX_get_min_proto_version(self.as_ptr());
1202            if r == 0 {
1203                None
1204            } else {
1205                Some(SslVersion(r))
1206            }
1207        }
1208    }
1209
1210    /// Gets the maximum supported protocol version.
1211    ///
1212    /// A value of `None` indicates that all versions up to the highest version supported by
1213    /// OpenSSL are enabled.
1214    ///
1215    /// Requires LibreSSL or OpenSSL 1.1.0g or newer.
1216    #[corresponds(SSL_CTX_get_max_proto_version)]
1217    #[cfg(any(ossl110g, libressl))]
1218    pub fn max_proto_version(&mut self) -> Option<SslVersion> {
1219        unsafe {
1220            let r = ffi::SSL_CTX_get_max_proto_version(self.as_ptr());
1221            if r == 0 {
1222                None
1223            } else {
1224                Some(SslVersion(r))
1225            }
1226        }
1227    }
1228
1229    /// Sets the protocols to sent to the server for Application Layer Protocol Negotiation (ALPN).
1230    ///
1231    /// The input must be in ALPN "wire format". It consists of a sequence of supported protocol
1232    /// names prefixed by their byte length. For example, the protocol list consisting of `spdy/1`
1233    /// and `http/1.1` is encoded as `b"\x06spdy/1\x08http/1.1"`. The protocols are ordered by
1234    /// preference.
1235    ///
1236    /// Requires AWS-LC or BoringSSL or LibreSSL or OpenSSL 1.0.2 or newer.
1237    #[corresponds(SSL_CTX_set_alpn_protos)]
1238    pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
1239        unsafe {
1240            assert!(protocols.len() <= c_uint::MAX as usize);
1241            let r = ffi::SSL_CTX_set_alpn_protos(
1242                self.as_ptr(),
1243                protocols.as_ptr(),
1244                protocols.len() as _,
1245            );
1246            // fun fact, SSL_CTX_set_alpn_protos has a reversed return code D:
1247            if r == 0 {
1248                Ok(())
1249            } else {
1250                Err(ErrorStack::get())
1251            }
1252        }
1253    }
1254
1255    /// Enables the DTLS extension "use_srtp" as defined in RFC5764.
1256    #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
1257    #[corresponds(SSL_CTX_set_tlsext_use_srtp)]
1258    pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
1259        unsafe {
1260            let cstr = CString::new(protocols).unwrap();
1261
1262            let r = ffi::SSL_CTX_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
1263            // fun fact, set_tlsext_use_srtp has a reversed return code D:
1264            if r == 0 {
1265                Ok(())
1266            } else {
1267                Err(ErrorStack::get())
1268            }
1269        }
1270    }
1271
1272    /// Sets the callback used by a server to select a protocol for Application Layer Protocol
1273    /// Negotiation (ALPN).
1274    ///
1275    /// The callback is provided with the client's protocol list in ALPN wire format. See the
1276    /// documentation for [`SslContextBuilder::set_alpn_protos`] for details. It should return one
1277    /// of those protocols on success. The [`select_next_proto`] function implements the standard
1278    /// protocol selection algorithm.
1279    ///
1280    /// Requires AWS-LC or BoringSSL or LibreSSL or OpenSSL 1.0.2 or newer.
1281    ///
1282    /// [`SslContextBuilder::set_alpn_protos`]: struct.SslContextBuilder.html#method.set_alpn_protos
1283    /// [`select_next_proto`]: fn.select_next_proto.html
1284    #[corresponds(SSL_CTX_set_alpn_select_cb)]
1285    pub fn set_alpn_select_callback<F>(&mut self, callback: F)
1286    where
1287        F: for<'a> Fn(&mut SslRef, &'a [u8]) -> Result<&'a [u8], AlpnError> + 'static + Sync + Send,
1288    {
1289        unsafe {
1290            self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1291            #[cfg(not(any(boringssl, awslc)))]
1292            ffi::SSL_CTX_set_alpn_select_cb__fixed_rust(
1293                self.as_ptr(),
1294                Some(callbacks::raw_alpn_select::<F>),
1295                ptr::null_mut(),
1296            );
1297            #[cfg(any(boringssl, awslc))]
1298            ffi::SSL_CTX_set_alpn_select_cb(
1299                self.as_ptr(),
1300                Some(callbacks::raw_alpn_select::<F>),
1301                ptr::null_mut(),
1302            );
1303        }
1304    }
1305
1306    /// Checks for consistency between the private key and certificate.
1307    #[corresponds(SSL_CTX_check_private_key)]
1308    pub fn check_private_key(&self) -> Result<(), ErrorStack> {
1309        unsafe { cvt(ffi::SSL_CTX_check_private_key(self.as_ptr())).map(|_| ()) }
1310    }
1311
1312    /// Returns a shared reference to the context's certificate store.
1313    #[corresponds(SSL_CTX_get_cert_store)]
1314    pub fn cert_store(&self) -> &X509StoreBuilderRef {
1315        unsafe { X509StoreBuilderRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1316    }
1317
1318    /// Returns a mutable reference to the context's certificate store.
1319    #[corresponds(SSL_CTX_get_cert_store)]
1320    pub fn cert_store_mut(&mut self) -> &mut X509StoreBuilderRef {
1321        unsafe { X509StoreBuilderRef::from_ptr_mut(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1322    }
1323
1324    /// Returns a reference to the X509 verification configuration.
1325    ///
1326    /// Requires AWS-LC or BoringSSL or LibreSSL or OpenSSL 1.0.2 or newer.
1327    #[corresponds(SSL_CTX_get0_param)]
1328    pub fn verify_param(&self) -> &X509VerifyParamRef {
1329        unsafe { X509VerifyParamRef::from_ptr(ffi::SSL_CTX_get0_param(self.as_ptr())) }
1330    }
1331
1332    /// Returns a mutable reference to the X509 verification configuration.
1333    ///
1334    /// Requires AWS-LC or BoringSSL or LibreSSL or OpenSSL 1.0.2 or newer.
1335    #[corresponds(SSL_CTX_get0_param)]
1336    pub fn verify_param_mut(&mut self) -> &mut X509VerifyParamRef {
1337        unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_CTX_get0_param(self.as_ptr())) }
1338    }
1339
1340    /// Sets the callback dealing with OCSP stapling.
1341    ///
1342    /// On the client side, this callback is responsible for validating the OCSP status response
1343    /// returned by the server. The status may be retrieved with the `SslRef::ocsp_status` method.
1344    /// A response of `Ok(true)` indicates that the OCSP status is valid, and a response of
1345    /// `Ok(false)` indicates that the OCSP status is invalid and the handshake should be
1346    /// terminated.
1347    ///
1348    /// On the server side, this callback is responsible for setting the OCSP status response to be
1349    /// returned to clients. The status may be set with the `SslRef::set_ocsp_status` method. A
1350    /// response of `Ok(true)` indicates that the OCSP status should be returned to the client, and
1351    /// `Ok(false)` indicates that the status should not be returned to the client.
1352    #[corresponds(SSL_CTX_set_tlsext_status_cb)]
1353    pub fn set_status_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1354    where
1355        F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + 'static + Sync + Send,
1356    {
1357        unsafe {
1358            self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1359            cvt(
1360                ffi::SSL_CTX_set_tlsext_status_cb(self.as_ptr(), Some(raw_tlsext_status::<F>))
1361                    as c_int,
1362            )
1363            .map(|_| ())
1364        }
1365    }
1366
1367    /// Sets the callback for providing an identity and pre-shared key for a TLS-PSK client.
1368    ///
1369    /// The callback will be called with the SSL context, an identity hint if one was provided
1370    /// by the server, a mutable slice for each of the identity and pre-shared key bytes. The
1371    /// identity must be written as a null-terminated C string.
1372    #[corresponds(SSL_CTX_set_psk_client_callback)]
1373    #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1374    pub fn set_psk_client_callback<F>(&mut self, callback: F)
1375    where
1376        F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
1377            + 'static
1378            + Sync
1379            + Send,
1380    {
1381        unsafe {
1382            self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1383            ffi::SSL_CTX_set_psk_client_callback(self.as_ptr(), Some(raw_client_psk::<F>));
1384        }
1385    }
1386
1387    #[deprecated(since = "0.10.10", note = "renamed to `set_psk_client_callback`")]
1388    #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1389    pub fn set_psk_callback<F>(&mut self, callback: F)
1390    where
1391        F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
1392            + 'static
1393            + Sync
1394            + Send,
1395    {
1396        self.set_psk_client_callback(callback)
1397    }
1398
1399    /// Sets the callback for providing an identity and pre-shared key for a TLS-PSK server.
1400    ///
1401    /// The callback will be called with the SSL context, an identity provided by the client,
1402    /// and, a mutable slice for the pre-shared key bytes. The callback returns the number of
1403    /// bytes in the pre-shared key.
1404    #[corresponds(SSL_CTX_set_psk_server_callback)]
1405    #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1406    pub fn set_psk_server_callback<F>(&mut self, callback: F)
1407    where
1408        F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8]) -> Result<usize, ErrorStack>
1409            + 'static
1410            + Sync
1411            + Send,
1412    {
1413        unsafe {
1414            self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1415            ffi::SSL_CTX_set_psk_server_callback(self.as_ptr(), Some(raw_server_psk::<F>));
1416        }
1417    }
1418
1419    /// Sets the callback which is called when new sessions are negotiated.
1420    ///
1421    /// This can be used by clients to implement session caching. While in TLSv1.2 the session is
1422    /// available to access via [`SslRef::session`] immediately after the handshake completes, this
1423    /// is not the case for TLSv1.3. There, a session is not generally available immediately, and
1424    /// the server may provide multiple session tokens to the client over a single session. The new
1425    /// session callback is a portable way to deal with both cases.
1426    ///
1427    /// Note that session caching must be enabled for the callback to be invoked, and it defaults
1428    /// off for clients. [`set_session_cache_mode`] controls that behavior.
1429    ///
1430    /// [`SslRef::session`]: struct.SslRef.html#method.session
1431    /// [`set_session_cache_mode`]: #method.set_session_cache_mode
1432    #[corresponds(SSL_CTX_sess_set_new_cb)]
1433    pub fn set_new_session_callback<F>(&mut self, callback: F)
1434    where
1435        F: Fn(&mut SslRef, SslSession) + 'static + Sync + Send,
1436    {
1437        unsafe {
1438            self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1439            ffi::SSL_CTX_sess_set_new_cb(self.as_ptr(), Some(callbacks::raw_new_session::<F>));
1440        }
1441    }
1442
1443    /// Sets the callback which is called when sessions are removed from the context.
1444    ///
1445    /// Sessions can be removed because they have timed out or because they are considered faulty.
1446    #[corresponds(SSL_CTX_sess_set_remove_cb)]
1447    pub fn set_remove_session_callback<F>(&mut self, callback: F)
1448    where
1449        F: Fn(&SslContextRef, &SslSessionRef) + 'static + Sync + Send,
1450    {
1451        unsafe {
1452            self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1453            ffi::SSL_CTX_sess_set_remove_cb(
1454                self.as_ptr(),
1455                Some(callbacks::raw_remove_session::<F>),
1456            );
1457        }
1458    }
1459
1460    /// Sets the callback which is called when a client proposed to resume a session but it was not
1461    /// found in the internal cache.
1462    ///
1463    /// The callback is passed a reference to the session ID provided by the client. It should
1464    /// return the session corresponding to that ID if available. This is only used for servers, not
1465    /// clients.
1466    ///
1467    /// # Safety
1468    ///
1469    /// The returned `SslSession` must not be associated with a different `SslContext`.
1470    #[corresponds(SSL_CTX_sess_set_get_cb)]
1471    pub unsafe fn set_get_session_callback<F>(&mut self, callback: F)
1472    where
1473        F: Fn(&mut SslRef, &[u8]) -> Option<SslSession> + 'static + Sync + Send,
1474    {
1475        self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1476        ffi::SSL_CTX_sess_set_get_cb(self.as_ptr(), Some(callbacks::raw_get_session::<F>));
1477    }
1478
1479    /// Sets the TLS key logging callback.
1480    ///
1481    /// The callback is invoked whenever TLS key material is generated, and is passed a line of NSS
1482    /// SSLKEYLOGFILE-formatted text. This can be used by tools like Wireshark to decrypt message
1483    /// traffic. The line does not contain a trailing newline.
1484    ///
1485    /// Requires OpenSSL 1.1.1 or newer.
1486    #[corresponds(SSL_CTX_set_keylog_callback)]
1487    #[cfg(any(ossl111, boringssl, awslc))]
1488    pub fn set_keylog_callback<F>(&mut self, callback: F)
1489    where
1490        F: Fn(&SslRef, &str) + 'static + Sync + Send,
1491    {
1492        unsafe {
1493            self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1494            ffi::SSL_CTX_set_keylog_callback(self.as_ptr(), Some(callbacks::raw_keylog::<F>));
1495        }
1496    }
1497
1498    /// Sets the session caching mode use for connections made with the context.
1499    ///
1500    /// Returns the previous session caching mode.
1501    #[corresponds(SSL_CTX_set_session_cache_mode)]
1502    pub fn set_session_cache_mode(&mut self, mode: SslSessionCacheMode) -> SslSessionCacheMode {
1503        unsafe {
1504            let bits = ffi::SSL_CTX_set_session_cache_mode(self.as_ptr(), mode.bits());
1505            SslSessionCacheMode::from_bits_retain(bits)
1506        }
1507    }
1508
1509    /// Sets the callback for generating an application cookie for TLS1.3
1510    /// stateless handshakes.
1511    ///
1512    /// The callback will be called with the SSL context and a slice into which the cookie
1513    /// should be written. The callback should return the number of bytes written.
1514    #[corresponds(SSL_CTX_set_stateless_cookie_generate_cb)]
1515    #[cfg(ossl111)]
1516    pub fn set_stateless_cookie_generate_cb<F>(&mut self, callback: F)
1517    where
1518        F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
1519    {
1520        unsafe {
1521            self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1522            ffi::SSL_CTX_set_stateless_cookie_generate_cb(
1523                self.as_ptr(),
1524                Some(raw_stateless_cookie_generate::<F>),
1525            );
1526        }
1527    }
1528
1529    /// Sets the callback for verifying an application cookie for TLS1.3
1530    /// stateless handshakes.
1531    ///
1532    /// The callback will be called with the SSL context and the cookie supplied by the
1533    /// client. It should return true if and only if the cookie is valid.
1534    ///
1535    /// Note that the OpenSSL implementation independently verifies the integrity of
1536    /// application cookies using an HMAC before invoking the supplied callback.
1537    #[corresponds(SSL_CTX_set_stateless_cookie_verify_cb)]
1538    #[cfg(ossl111)]
1539    pub fn set_stateless_cookie_verify_cb<F>(&mut self, callback: F)
1540    where
1541        F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
1542    {
1543        unsafe {
1544            self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1545            ffi::SSL_CTX_set_stateless_cookie_verify_cb(
1546                self.as_ptr(),
1547                Some(raw_stateless_cookie_verify::<F>),
1548            )
1549        }
1550    }
1551
1552    /// Sets the callback for generating a DTLSv1 cookie
1553    ///
1554    /// The callback will be called with the SSL context and a slice into which the cookie
1555    /// should be written. The callback should return the number of bytes written.
1556    #[corresponds(SSL_CTX_set_cookie_generate_cb)]
1557    #[cfg(not(any(boringssl, awslc)))]
1558    pub fn set_cookie_generate_cb<F>(&mut self, callback: F)
1559    where
1560        F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
1561    {
1562        unsafe {
1563            self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1564            ffi::SSL_CTX_set_cookie_generate_cb(self.as_ptr(), Some(raw_cookie_generate::<F>));
1565        }
1566    }
1567
1568    /// Sets the callback for verifying a DTLSv1 cookie
1569    ///
1570    /// The callback will be called with the SSL context and the cookie supplied by the
1571    /// client. It should return true if and only if the cookie is valid.
1572    #[corresponds(SSL_CTX_set_cookie_verify_cb)]
1573    #[cfg(not(any(boringssl, awslc)))]
1574    pub fn set_cookie_verify_cb<F>(&mut self, callback: F)
1575    where
1576        F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
1577    {
1578        unsafe {
1579            self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1580            ffi::SSL_CTX_set_cookie_verify_cb(self.as_ptr(), Some(raw_cookie_verify::<F>));
1581        }
1582    }
1583
1584    /// Sets the extra data at the specified index.
1585    ///
1586    /// This can be used to provide data to callbacks registered with the context. Use the
1587    /// `SslContext::new_ex_index` method to create an `Index`.
1588    // FIXME should return a result
1589    #[corresponds(SSL_CTX_set_ex_data)]
1590    pub fn set_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) {
1591        self.set_ex_data_inner(index, data);
1592    }
1593
1594    fn set_ex_data_inner<T>(&mut self, index: Index<SslContext, T>, data: T) -> *mut c_void {
1595        match self.ex_data_mut(index) {
1596            Some(v) => {
1597                *v = data;
1598                (v as *mut T).cast()
1599            }
1600            _ => unsafe {
1601                let data = Box::into_raw(Box::new(data)) as *mut c_void;
1602                ffi::SSL_CTX_set_ex_data(self.as_ptr(), index.as_raw(), data);
1603                data
1604            },
1605        }
1606    }
1607
1608    fn ex_data_mut<T>(&mut self, index: Index<SslContext, T>) -> Option<&mut T> {
1609        unsafe {
1610            let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
1611            if data.is_null() {
1612                None
1613            } else {
1614                Some(&mut *data.cast())
1615            }
1616        }
1617    }
1618
1619    /// Adds a custom extension for a TLS/DTLS client or server for all supported protocol versions.
1620    ///
1621    /// Requires OpenSSL 1.1.1 or newer.
1622    #[corresponds(SSL_CTX_add_custom_ext)]
1623    #[cfg(ossl111)]
1624    pub fn add_custom_ext<AddFn, ParseFn, T>(
1625        &mut self,
1626        ext_type: u16,
1627        context: ExtensionContext,
1628        add_cb: AddFn,
1629        parse_cb: ParseFn,
1630    ) -> Result<(), ErrorStack>
1631    where
1632        AddFn: Fn(
1633                &mut SslRef,
1634                ExtensionContext,
1635                Option<(usize, &X509Ref)>,
1636            ) -> Result<Option<T>, SslAlert>
1637            + 'static
1638            + Sync
1639            + Send,
1640        T: AsRef<[u8]> + 'static + Sync + Send,
1641        ParseFn: Fn(
1642                &mut SslRef,
1643                ExtensionContext,
1644                &[u8],
1645                Option<(usize, &X509Ref)>,
1646            ) -> Result<(), SslAlert>
1647            + 'static
1648            + Sync
1649            + Send,
1650    {
1651        let ret = unsafe {
1652            self.set_ex_data(SslContext::cached_ex_index::<AddFn>(), add_cb);
1653            self.set_ex_data(SslContext::cached_ex_index::<ParseFn>(), parse_cb);
1654
1655            ffi::SSL_CTX_add_custom_ext(
1656                self.as_ptr(),
1657                ext_type as c_uint,
1658                context.bits(),
1659                Some(raw_custom_ext_add::<AddFn, T>),
1660                Some(raw_custom_ext_free::<T>),
1661                ptr::null_mut(),
1662                Some(raw_custom_ext_parse::<ParseFn>),
1663                ptr::null_mut(),
1664            )
1665        };
1666        if ret == 1 {
1667            Ok(())
1668        } else {
1669            Err(ErrorStack::get())
1670        }
1671    }
1672
1673    /// Sets the maximum amount of early data that will be accepted on incoming connections.
1674    ///
1675    /// Defaults to 0.
1676    ///
1677    /// Requires OpenSSL 1.1.1 or newer or LibreSSL.
1678    #[corresponds(SSL_CTX_set_max_early_data)]
1679    #[cfg(any(ossl111, libressl))]
1680    pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
1681        if unsafe { ffi::SSL_CTX_set_max_early_data(self.as_ptr(), bytes) } == 1 {
1682            Ok(())
1683        } else {
1684            Err(ErrorStack::get())
1685        }
1686    }
1687
1688    /// Sets a callback which will be invoked just after the client's hello message is received.
1689    ///
1690    /// Requires OpenSSL 1.1.1 or newer.
1691    #[corresponds(SSL_CTX_set_client_hello_cb)]
1692    #[cfg(ossl111)]
1693    pub fn set_client_hello_callback<F>(&mut self, callback: F)
1694    where
1695        F: Fn(&mut SslRef, &mut SslAlert) -> Result<ClientHelloResponse, ErrorStack>
1696            + 'static
1697            + Sync
1698            + Send,
1699    {
1700        unsafe {
1701            let ptr = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
1702            ffi::SSL_CTX_set_client_hello_cb(
1703                self.as_ptr(),
1704                Some(callbacks::raw_client_hello::<F>),
1705                ptr,
1706            );
1707        }
1708    }
1709
1710    /// Sets the context's session cache size limit, returning the previous limit.
1711    ///
1712    /// A value of 0 means that the cache size is unbounded.
1713    #[corresponds(SSL_CTX_sess_set_cache_size)]
1714    #[allow(clippy::useless_conversion)]
1715    pub fn set_session_cache_size(&mut self, size: i32) -> i64 {
1716        unsafe {
1717            ffi::SSL_CTX_sess_set_cache_size(self.as_ptr(), size as SslCacheSize) as SslCacheTy
1718        }
1719    }
1720
1721    /// Sets the context's supported signature algorithms.
1722    ///
1723    /// Requires OpenSSL 1.1.0 or newer.
1724    #[corresponds(SSL_CTX_set1_sigalgs_list)]
1725    #[cfg(ossl110)]
1726    pub fn set_sigalgs_list(&mut self, sigalgs: &str) -> Result<(), ErrorStack> {
1727        let sigalgs = CString::new(sigalgs).unwrap();
1728        unsafe {
1729            cvt(ffi::SSL_CTX_set1_sigalgs_list(self.as_ptr(), sigalgs.as_ptr()) as c_int)
1730                .map(|_| ())
1731        }
1732    }
1733
1734    /// Sets the context's supported elliptic curve groups.
1735    ///
1736    /// Requires AWS-LC or BoringSSL or LibreSSL or OpenSSL 1.1.1 or newer.
1737    #[corresponds(SSL_CTX_set1_groups_list)]
1738    #[cfg(any(ossl111, boringssl, libressl, awslc))]
1739    pub fn set_groups_list(&mut self, groups: &str) -> Result<(), ErrorStack> {
1740        let groups = CString::new(groups).unwrap();
1741        unsafe {
1742            cvt(ffi::SSL_CTX_set1_groups_list(self.as_ptr(), groups.as_ptr()) as c_int).map(|_| ())
1743        }
1744    }
1745
1746    /// Sets the number of TLS 1.3 session tickets that will be sent to a client after a full
1747    /// handshake.
1748    ///
1749    /// Requires OpenSSL 1.1.1 or newer.
1750    #[corresponds(SSL_CTX_set_num_tickets)]
1751    #[cfg(ossl111)]
1752    pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
1753        unsafe { cvt(ffi::SSL_CTX_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
1754    }
1755
1756    /// Set the context's security level to a value between 0 and 5, inclusive.
1757    /// A security value of 0 allows allows all parameters and algorithms.
1758    ///
1759    /// Requires OpenSSL 1.1.0 or newer.
1760    #[corresponds(SSL_CTX_set_security_level)]
1761    #[cfg(any(ossl110, libressl360))]
1762    pub fn set_security_level(&mut self, level: u32) {
1763        unsafe { ffi::SSL_CTX_set_security_level(self.as_ptr(), level as c_int) }
1764    }
1765
1766    /// Consumes the builder, returning a new `SslContext`.
1767    pub fn build(self) -> SslContext {
1768        self.0
1769    }
1770}
1771
1772foreign_type_and_impl_send_sync! {
1773    type CType = ffi::SSL_CTX;
1774    fn drop = ffi::SSL_CTX_free;
1775
1776    /// A context object for TLS streams.
1777    ///
1778    /// Applications commonly configure a single `SslContext` that is shared by all of its
1779    /// `SslStreams`.
1780    pub struct SslContext;
1781
1782    /// Reference to [`SslContext`]
1783    ///
1784    /// [`SslContext`]: struct.SslContext.html
1785    pub struct SslContextRef;
1786}
1787
1788impl Clone for SslContext {
1789    fn clone(&self) -> Self {
1790        (**self).to_owned()
1791    }
1792}
1793
1794impl ToOwned for SslContextRef {
1795    type Owned = SslContext;
1796
1797    fn to_owned(&self) -> Self::Owned {
1798        unsafe {
1799            SSL_CTX_up_ref(self.as_ptr());
1800            SslContext::from_ptr(self.as_ptr())
1801        }
1802    }
1803}
1804
1805// TODO: add useful info here
1806impl fmt::Debug for SslContext {
1807    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1808        write!(fmt, "SslContext")
1809    }
1810}
1811
1812impl SslContext {
1813    /// Creates a new builder object for an `SslContext`.
1814    pub fn builder(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
1815        SslContextBuilder::new(method)
1816    }
1817
1818    /// Returns a new extra data index.
1819    ///
1820    /// Each invocation of this function is guaranteed to return a distinct index. These can be used
1821    /// to store data in the context that can be retrieved later by callbacks, for example.
1822    #[corresponds(SSL_CTX_get_ex_new_index)]
1823    pub fn new_ex_index<T>() -> Result<Index<SslContext, T>, ErrorStack>
1824    where
1825        T: 'static + Sync + Send,
1826    {
1827        unsafe {
1828            ffi::init();
1829            #[cfg(any(boringssl, awslc))]
1830            let idx = cvt_n(get_new_idx(Some(free_data_box::<T>)))?;
1831            #[cfg(not(any(boringssl, awslc)))]
1832            let idx = cvt_n(get_new_idx(free_data_box::<T>))?;
1833            Ok(Index::from_raw(idx))
1834        }
1835    }
1836
1837    // FIXME should return a result?
1838    fn cached_ex_index<T>() -> Index<SslContext, T>
1839    where
1840        T: 'static + Sync + Send,
1841    {
1842        unsafe {
1843            let idx = *INDEXES
1844                .lock()
1845                .unwrap_or_else(|e| e.into_inner())
1846                .entry(TypeId::of::<T>())
1847                .or_insert_with(|| SslContext::new_ex_index::<T>().unwrap().as_raw());
1848            Index::from_raw(idx)
1849        }
1850    }
1851}
1852
1853impl SslContextRef {
1854    /// Returns the certificate associated with this `SslContext`, if present.
1855    ///
1856    /// Requires LibreSSL or OpenSSL 1.1.0 or newer.
1857    #[corresponds(SSL_CTX_get0_certificate)]
1858    #[cfg(any(ossl110, libressl))]
1859    pub fn certificate(&self) -> Option<&X509Ref> {
1860        unsafe {
1861            let ptr = ffi::SSL_CTX_get0_certificate(self.as_ptr());
1862            X509Ref::from_const_ptr_opt(ptr)
1863        }
1864    }
1865
1866    /// Returns the private key associated with this `SslContext`, if present.
1867    ///
1868    /// Requires OpenSSL 1.1.0 or newer or LibreSSL.
1869    #[corresponds(SSL_CTX_get0_privatekey)]
1870    #[cfg(any(ossl110, libressl))]
1871    pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
1872        unsafe {
1873            let ptr = ffi::SSL_CTX_get0_privatekey(self.as_ptr());
1874            PKeyRef::from_const_ptr_opt(ptr)
1875        }
1876    }
1877
1878    /// Returns a shared reference to the certificate store used for verification.
1879    #[corresponds(SSL_CTX_get_cert_store)]
1880    pub fn cert_store(&self) -> &X509StoreRef {
1881        unsafe { X509StoreRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1882    }
1883
1884    /// Returns a shared reference to the stack of certificates making up the chain from the leaf.
1885    #[corresponds(SSL_CTX_get_extra_chain_certs)]
1886    pub fn extra_chain_certs(&self) -> &StackRef<X509> {
1887        unsafe {
1888            let mut chain = ptr::null_mut();
1889            ffi::SSL_CTX_get_extra_chain_certs(self.as_ptr(), &mut chain);
1890            StackRef::from_const_ptr_opt(chain).expect("extra chain certs must not be null")
1891        }
1892    }
1893
1894    /// Returns a reference to the extra data at the specified index.
1895    #[corresponds(SSL_CTX_get_ex_data)]
1896    pub fn ex_data<T>(&self, index: Index<SslContext, T>) -> Option<&T> {
1897        unsafe {
1898            let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
1899            if data.is_null() {
1900                None
1901            } else {
1902                Some(&*(data as *const T))
1903            }
1904        }
1905    }
1906
1907    /// Gets the maximum amount of early data that will be accepted on incoming connections.
1908    ///
1909    /// Requires OpenSSL 1.1.1 or newer or LibreSSL.
1910    #[corresponds(SSL_CTX_get_max_early_data)]
1911    #[cfg(any(ossl111, libressl))]
1912    pub fn max_early_data(&self) -> u32 {
1913        unsafe { ffi::SSL_CTX_get_max_early_data(self.as_ptr()) }
1914    }
1915
1916    /// Adds a session to the context's cache.
1917    ///
1918    /// Returns `true` if the session was successfully added to the cache, and `false` if it was already present.
1919    ///
1920    /// # Safety
1921    ///
1922    /// The caller of this method is responsible for ensuring that the session has never been used with another
1923    /// `SslContext` than this one.
1924    #[corresponds(SSL_CTX_add_session)]
1925    pub unsafe fn add_session(&self, session: &SslSessionRef) -> bool {
1926        ffi::SSL_CTX_add_session(self.as_ptr(), session.as_ptr()) != 0
1927    }
1928
1929    /// Removes a session from the context's cache and marks it as non-resumable.
1930    ///
1931    /// Returns `true` if the session was successfully found and removed, and `false` otherwise.
1932    ///
1933    /// # Safety
1934    ///
1935    /// The caller of this method is responsible for ensuring that the session has never been used with another
1936    /// `SslContext` than this one.
1937    #[corresponds(SSL_CTX_remove_session)]
1938    pub unsafe fn remove_session(&self, session: &SslSessionRef) -> bool {
1939        ffi::SSL_CTX_remove_session(self.as_ptr(), session.as_ptr()) != 0
1940    }
1941
1942    /// Returns the context's session cache size limit.
1943    ///
1944    /// A value of 0 means that the cache size is unbounded.
1945    #[corresponds(SSL_CTX_sess_get_cache_size)]
1946    #[allow(clippy::unnecessary_cast)]
1947    pub fn session_cache_size(&self) -> i64 {
1948        unsafe { ffi::SSL_CTX_sess_get_cache_size(self.as_ptr()) as i64 }
1949    }
1950
1951    /// Returns the verify mode that was set on this context from [`SslContextBuilder::set_verify`].
1952    ///
1953    /// [`SslContextBuilder::set_verify`]: struct.SslContextBuilder.html#method.set_verify
1954    #[corresponds(SSL_CTX_get_verify_mode)]
1955    pub fn verify_mode(&self) -> SslVerifyMode {
1956        let mode = unsafe { ffi::SSL_CTX_get_verify_mode(self.as_ptr()) };
1957        SslVerifyMode::from_bits_retain(mode)
1958    }
1959
1960    /// Gets the number of TLS 1.3 session tickets that will be sent to a client after a full
1961    /// handshake.
1962    ///
1963    /// Requires OpenSSL 1.1.1 or newer.
1964    #[corresponds(SSL_CTX_get_num_tickets)]
1965    #[cfg(ossl111)]
1966    pub fn num_tickets(&self) -> usize {
1967        unsafe { ffi::SSL_CTX_get_num_tickets(self.as_ptr()) }
1968    }
1969
1970    /// Get the context's security level, which controls the allowed parameters
1971    /// and algorithms.
1972    ///
1973    /// Requires OpenSSL 1.1.0 or newer.
1974    #[corresponds(SSL_CTX_get_security_level)]
1975    #[cfg(any(ossl110, libressl360))]
1976    pub fn security_level(&self) -> u32 {
1977        unsafe { ffi::SSL_CTX_get_security_level(self.as_ptr()) as u32 }
1978    }
1979}
1980
1981/// Information about the state of a cipher.
1982pub struct CipherBits {
1983    /// The number of secret bits used for the cipher.
1984    pub secret: i32,
1985
1986    /// The number of bits processed by the chosen algorithm.
1987    pub algorithm: i32,
1988}
1989
1990/// Information about a cipher.
1991pub struct SslCipher(*mut ffi::SSL_CIPHER);
1992
1993impl ForeignType for SslCipher {
1994    type CType = ffi::SSL_CIPHER;
1995    type Ref = SslCipherRef;
1996
1997    #[inline]
1998    unsafe fn from_ptr(ptr: *mut ffi::SSL_CIPHER) -> SslCipher {
1999        SslCipher(ptr)
2000    }
2001
2002    #[inline]
2003    fn as_ptr(&self) -> *mut ffi::SSL_CIPHER {
2004        self.0
2005    }
2006}
2007
2008impl Stackable for SslCipher {
2009    type StackType = ffi::stack_st_SSL_CIPHER;
2010}
2011
2012impl Deref for SslCipher {
2013    type Target = SslCipherRef;
2014
2015    fn deref(&self) -> &SslCipherRef {
2016        unsafe { SslCipherRef::from_ptr(self.0) }
2017    }
2018}
2019
2020impl DerefMut for SslCipher {
2021    fn deref_mut(&mut self) -> &mut SslCipherRef {
2022        unsafe { SslCipherRef::from_ptr_mut(self.0) }
2023    }
2024}
2025
2026/// Reference to an [`SslCipher`].
2027///
2028/// [`SslCipher`]: struct.SslCipher.html
2029pub struct SslCipherRef(Opaque);
2030
2031impl ForeignTypeRef for SslCipherRef {
2032    type CType = ffi::SSL_CIPHER;
2033}
2034
2035impl SslCipherRef {
2036    /// Returns the name of the cipher.
2037    #[corresponds(SSL_CIPHER_get_name)]
2038    pub fn name(&self) -> &'static str {
2039        unsafe {
2040            let ptr = ffi::SSL_CIPHER_get_name(self.as_ptr());
2041            CStr::from_ptr(ptr).to_str().unwrap()
2042        }
2043    }
2044
2045    /// Returns the RFC-standard name of the cipher, if one exists.
2046    ///
2047    /// Requires OpenSSL 1.1.1 or newer.
2048    #[corresponds(SSL_CIPHER_standard_name)]
2049    #[cfg(ossl111)]
2050    pub fn standard_name(&self) -> Option<&'static str> {
2051        unsafe {
2052            let ptr = ffi::SSL_CIPHER_standard_name(self.as_ptr());
2053            if ptr.is_null() {
2054                None
2055            } else {
2056                Some(CStr::from_ptr(ptr).to_str().unwrap())
2057            }
2058        }
2059    }
2060
2061    /// Returns the SSL/TLS protocol version that first defined the cipher.
2062    #[corresponds(SSL_CIPHER_get_version)]
2063    pub fn version(&self) -> &'static str {
2064        let version = unsafe {
2065            let ptr = ffi::SSL_CIPHER_get_version(self.as_ptr());
2066            CStr::from_ptr(ptr as *const _)
2067        };
2068
2069        str::from_utf8(version.to_bytes()).unwrap()
2070    }
2071
2072    /// Returns the number of bits used for the cipher.
2073    #[corresponds(SSL_CIPHER_get_bits)]
2074    #[allow(clippy::useless_conversion)]
2075    pub fn bits(&self) -> CipherBits {
2076        unsafe {
2077            let mut algo_bits = 0;
2078            let secret_bits = ffi::SSL_CIPHER_get_bits(self.as_ptr(), &mut algo_bits);
2079            CipherBits {
2080                secret: secret_bits.into(),
2081                algorithm: algo_bits.into(),
2082            }
2083        }
2084    }
2085
2086    /// Returns a textual description of the cipher.
2087    #[corresponds(SSL_CIPHER_description)]
2088    pub fn description(&self) -> String {
2089        unsafe {
2090            // SSL_CIPHER_description requires a buffer of at least 128 bytes.
2091            let mut buf = [0; 128];
2092            let ptr = ffi::SSL_CIPHER_description(self.as_ptr(), buf.as_mut_ptr(), 128);
2093            String::from_utf8(CStr::from_ptr(ptr as *const _).to_bytes().to_vec()).unwrap()
2094        }
2095    }
2096
2097    /// Returns the handshake digest of the cipher.
2098    ///
2099    /// Requires OpenSSL 1.1.1 or newer.
2100    #[corresponds(SSL_CIPHER_get_handshake_digest)]
2101    #[cfg(ossl111)]
2102    pub fn handshake_digest(&self) -> Option<MessageDigest> {
2103        unsafe {
2104            let ptr = ffi::SSL_CIPHER_get_handshake_digest(self.as_ptr());
2105            if ptr.is_null() {
2106                None
2107            } else {
2108                Some(MessageDigest::from_ptr(ptr))
2109            }
2110        }
2111    }
2112
2113    /// Returns the NID corresponding to the cipher.
2114    ///
2115    /// Requires LibreSSL or OpenSSL 1.1.0 or newer.
2116    #[corresponds(SSL_CIPHER_get_cipher_nid)]
2117    #[cfg(any(ossl110, libressl))]
2118    pub fn cipher_nid(&self) -> Option<Nid> {
2119        let n = unsafe { ffi::SSL_CIPHER_get_cipher_nid(self.as_ptr()) };
2120        if n == 0 {
2121            None
2122        } else {
2123            Some(Nid::from_raw(n))
2124        }
2125    }
2126
2127    /// Returns the two-byte ID of the cipher
2128    ///
2129    /// Requires OpenSSL 1.1.1 or newer.
2130    #[corresponds(SSL_CIPHER_get_protocol_id)]
2131    #[cfg(ossl111)]
2132    pub fn protocol_id(&self) -> [u8; 2] {
2133        unsafe {
2134            let id = ffi::SSL_CIPHER_get_protocol_id(self.as_ptr());
2135            id.to_be_bytes()
2136        }
2137    }
2138}
2139
2140impl fmt::Debug for SslCipherRef {
2141    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2142        write!(fmt, "{}", self.name())
2143    }
2144}
2145
2146/// A stack of selected ciphers, and a stack of selected signalling cipher suites
2147#[derive(Debug)]
2148pub struct CipherLists {
2149    pub suites: Stack<SslCipher>,
2150    pub signalling_suites: Stack<SslCipher>,
2151}
2152
2153foreign_type_and_impl_send_sync! {
2154    type CType = ffi::SSL_SESSION;
2155    fn drop = ffi::SSL_SESSION_free;
2156
2157    /// An encoded SSL session.
2158    ///
2159    /// These can be cached to share sessions across connections.
2160    pub struct SslSession;
2161
2162    /// Reference to [`SslSession`].
2163    ///
2164    /// [`SslSession`]: struct.SslSession.html
2165    pub struct SslSessionRef;
2166}
2167
2168impl Clone for SslSession {
2169    fn clone(&self) -> SslSession {
2170        SslSessionRef::to_owned(self)
2171    }
2172}
2173
2174impl SslSession {
2175    from_der! {
2176        /// Deserializes a DER-encoded session structure.
2177        #[corresponds(d2i_SSL_SESSION)]
2178        from_der,
2179        SslSession,
2180        ffi::d2i_SSL_SESSION
2181    }
2182}
2183
2184impl ToOwned for SslSessionRef {
2185    type Owned = SslSession;
2186
2187    fn to_owned(&self) -> SslSession {
2188        unsafe {
2189            SSL_SESSION_up_ref(self.as_ptr());
2190            SslSession(self.as_ptr())
2191        }
2192    }
2193}
2194
2195impl SslSessionRef {
2196    /// Returns the SSL session ID.
2197    #[corresponds(SSL_SESSION_get_id)]
2198    pub fn id(&self) -> &[u8] {
2199        unsafe {
2200            let mut len = 0;
2201            let p = ffi::SSL_SESSION_get_id(self.as_ptr(), &mut len);
2202            #[allow(clippy::unnecessary_cast)]
2203            util::from_raw_parts(p as *const u8, len as usize)
2204        }
2205    }
2206
2207    /// Returns the length of the master key.
2208    #[corresponds(SSL_SESSION_get_master_key)]
2209    pub fn master_key_len(&self) -> usize {
2210        unsafe { SSL_SESSION_get_master_key(self.as_ptr(), ptr::null_mut(), 0) }
2211    }
2212
2213    /// Copies the master key into the provided buffer.
2214    ///
2215    /// Returns the number of bytes written, or the size of the master key if the buffer is empty.
2216    #[corresponds(SSL_SESSION_get_master_key)]
2217    pub fn master_key(&self, buf: &mut [u8]) -> usize {
2218        unsafe { SSL_SESSION_get_master_key(self.as_ptr(), buf.as_mut_ptr(), buf.len()) }
2219    }
2220
2221    /// Gets the maximum amount of early data that can be sent on this session.
2222    ///
2223    /// Requires OpenSSL 1.1.1 or newer or LibreSSL.
2224    #[corresponds(SSL_SESSION_get_max_early_data)]
2225    #[cfg(any(ossl111, libressl))]
2226    pub fn max_early_data(&self) -> u32 {
2227        unsafe { ffi::SSL_SESSION_get_max_early_data(self.as_ptr()) }
2228    }
2229
2230    /// Returns the time at which the session was established, in seconds since the Unix epoch.
2231    #[corresponds(SSL_SESSION_get_time)]
2232    #[allow(clippy::useless_conversion)]
2233    pub fn time(&self) -> SslTimeTy {
2234        unsafe { ffi::SSL_SESSION_get_time(self.as_ptr()) }
2235    }
2236
2237    /// Returns the sessions timeout, in seconds.
2238    ///
2239    /// A session older than this time should not be used for session resumption.
2240    #[corresponds(SSL_SESSION_get_timeout)]
2241    #[allow(clippy::useless_conversion)]
2242    pub fn timeout(&self) -> i64 {
2243        unsafe { ffi::SSL_SESSION_get_timeout(self.as_ptr()).into() }
2244    }
2245
2246    /// Returns the session's TLS protocol version.
2247    ///
2248    /// Requires LibreSSL or OpenSSL 1.1.0 or newer.
2249    #[corresponds(SSL_SESSION_get_protocol_version)]
2250    #[cfg(any(ossl110, libressl))]
2251    pub fn protocol_version(&self) -> SslVersion {
2252        unsafe {
2253            let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr());
2254            SslVersion(version)
2255        }
2256    }
2257
2258    to_der! {
2259        /// Serializes the session into a DER-encoded structure.
2260        #[corresponds(i2d_SSL_SESSION)]
2261        to_der,
2262        ffi::i2d_SSL_SESSION
2263    }
2264}
2265
2266foreign_type_and_impl_send_sync! {
2267    type CType = ffi::SSL;
2268    fn drop = ffi::SSL_free;
2269
2270    /// The state of an SSL/TLS session.
2271    ///
2272    /// `Ssl` objects are created from an [`SslContext`], which provides configuration defaults.
2273    /// These defaults can be overridden on a per-`Ssl` basis, however.
2274    ///
2275    /// [`SslContext`]: struct.SslContext.html
2276    pub struct Ssl;
2277
2278    /// Reference to an [`Ssl`].
2279    ///
2280    /// [`Ssl`]: struct.Ssl.html
2281    pub struct SslRef;
2282}
2283
2284impl fmt::Debug for Ssl {
2285    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2286        fmt::Debug::fmt(&**self, fmt)
2287    }
2288}
2289
2290impl Ssl {
2291    /// Returns a new extra data index.
2292    ///
2293    /// Each invocation of this function is guaranteed to return a distinct index. These can be used
2294    /// to store data in the context that can be retrieved later by callbacks, for example.
2295    #[corresponds(SSL_get_ex_new_index)]
2296    pub fn new_ex_index<T>() -> Result<Index<Ssl, T>, ErrorStack>
2297    where
2298        T: 'static + Sync + Send,
2299    {
2300        unsafe {
2301            ffi::init();
2302            #[cfg(any(boringssl, awslc))]
2303            let idx = cvt_n(get_new_ssl_idx(Some(free_data_box::<T>)))?;
2304            #[cfg(not(any(boringssl, awslc)))]
2305            let idx = cvt_n(get_new_ssl_idx(free_data_box::<T>))?;
2306            Ok(Index::from_raw(idx))
2307        }
2308    }
2309
2310    // FIXME should return a result?
2311    fn cached_ex_index<T>() -> Index<Ssl, T>
2312    where
2313        T: 'static + Sync + Send,
2314    {
2315        unsafe {
2316            let idx = *SSL_INDEXES
2317                .lock()
2318                .unwrap_or_else(|e| e.into_inner())
2319                .entry(TypeId::of::<T>())
2320                .or_insert_with(|| Ssl::new_ex_index::<T>().unwrap().as_raw());
2321            Index::from_raw(idx)
2322        }
2323    }
2324
2325    /// Creates a new `Ssl`.
2326    #[corresponds(SSL_new)]
2327    pub fn new(ctx: &SslContextRef) -> Result<Ssl, ErrorStack> {
2328        let session_ctx_index = try_get_session_ctx_index()?;
2329        unsafe {
2330            let ptr = cvt_p(ffi::SSL_new(ctx.as_ptr()))?;
2331            let mut ssl = Ssl::from_ptr(ptr);
2332            ssl.set_ex_data(*session_ctx_index, ctx.to_owned());
2333
2334            Ok(ssl)
2335        }
2336    }
2337
2338    /// Initiates a client-side TLS handshake.
2339    /// # Warning
2340    ///
2341    /// OpenSSL's default configuration is insecure. It is highly recommended to use
2342    /// `SslConnector` rather than `Ssl` directly, as it manages that configuration.
2343    #[corresponds(SSL_connect)]
2344    #[allow(deprecated)]
2345    pub fn connect<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2346    where
2347        S: Read + Write,
2348    {
2349        SslStreamBuilder::new(self, stream).connect()
2350    }
2351
2352    /// Initiates a server-side TLS handshake.
2353    ///
2354    /// # Warning
2355    ///
2356    /// OpenSSL's default configuration is insecure. It is highly recommended to use
2357    /// `SslAcceptor` rather than `Ssl` directly, as it manages that configuration.
2358    #[corresponds(SSL_accept)]
2359    #[allow(deprecated)]
2360    pub fn accept<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2361    where
2362        S: Read + Write,
2363    {
2364        SslStreamBuilder::new(self, stream).accept()
2365    }
2366}
2367
2368impl fmt::Debug for SslRef {
2369    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2370        fmt.debug_struct("Ssl")
2371            .field("state", &self.state_string_long())
2372            .field("verify_result", &self.verify_result())
2373            .finish()
2374    }
2375}
2376
2377impl SslRef {
2378    fn get_raw_rbio(&self) -> *mut ffi::BIO {
2379        unsafe { ffi::SSL_get_rbio(self.as_ptr()) }
2380    }
2381
2382    fn get_error(&self, ret: c_int) -> ErrorCode {
2383        unsafe { ErrorCode::from_raw(ffi::SSL_get_error(self.as_ptr(), ret)) }
2384    }
2385
2386    /// Configure as an outgoing stream from a client.
2387    #[corresponds(SSL_set_connect_state)]
2388    pub fn set_connect_state(&mut self) {
2389        unsafe { ffi::SSL_set_connect_state(self.as_ptr()) }
2390    }
2391
2392    /// Configure as an incoming stream to a server.
2393    #[corresponds(SSL_set_accept_state)]
2394    pub fn set_accept_state(&mut self) {
2395        unsafe { ffi::SSL_set_accept_state(self.as_ptr()) }
2396    }
2397
2398    /// Like [`SslContextBuilder::set_verify`].
2399    ///
2400    /// [`SslContextBuilder::set_verify`]: struct.SslContextBuilder.html#method.set_verify
2401    #[corresponds(SSL_set_verify)]
2402    pub fn set_verify(&mut self, mode: SslVerifyMode) {
2403        unsafe { ffi::SSL_set_verify(self.as_ptr(), mode.bits() as c_int, None) }
2404    }
2405
2406    /// Returns the verify mode that was set using `set_verify`.
2407    #[corresponds(SSL_set_verify_mode)]
2408    pub fn verify_mode(&self) -> SslVerifyMode {
2409        let mode = unsafe { ffi::SSL_get_verify_mode(self.as_ptr()) };
2410        SslVerifyMode::from_bits_retain(mode)
2411    }
2412
2413    /// Like [`SslContextBuilder::set_verify_callback`].
2414    ///
2415    /// [`SslContextBuilder::set_verify_callback`]: struct.SslContextBuilder.html#method.set_verify_callback
2416    #[corresponds(SSL_set_verify)]
2417    pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
2418    where
2419        F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
2420    {
2421        unsafe {
2422            // this needs to be in an Arc since the callback can register a new callback!
2423            self.set_ex_data(Ssl::cached_ex_index(), Arc::new(verify));
2424            ffi::SSL_set_verify(
2425                self.as_ptr(),
2426                mode.bits() as c_int,
2427                Some(ssl_raw_verify::<F>),
2428            );
2429        }
2430    }
2431
2432    /// Like [`SslContextBuilder::set_tmp_dh`].
2433    ///
2434    /// [`SslContextBuilder::set_tmp_dh`]: struct.SslContextBuilder.html#method.set_tmp_dh
2435    #[corresponds(SSL_set_tmp_dh)]
2436    pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
2437        unsafe { cvt(ffi::SSL_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
2438    }
2439
2440    /// Like [`SslContextBuilder::set_tmp_dh_callback`].
2441    ///
2442    /// [`SslContextBuilder::set_tmp_dh_callback`]: struct.SslContextBuilder.html#method.set_tmp_dh_callback
2443    #[corresponds(SSL_set_tmp_dh_callback)]
2444    pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
2445    where
2446        F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
2447    {
2448        unsafe {
2449            // this needs to be in an Arc since the callback can register a new callback!
2450            self.set_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
2451            #[cfg(any(boringssl, awslc))]
2452            ffi::SSL_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh_ssl::<F>));
2453            #[cfg(not(any(boringssl, awslc)))]
2454            ffi::SSL_set_tmp_dh_callback__fixed_rust(self.as_ptr(), Some(raw_tmp_dh_ssl::<F>));
2455        }
2456    }
2457
2458    /// Like [`SslContextBuilder::set_tmp_ecdh`].
2459    ///
2460    /// [`SslContextBuilder::set_tmp_ecdh`]: struct.SslContextBuilder.html#method.set_tmp_ecdh
2461    #[corresponds(SSL_set_tmp_ecdh)]
2462    pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
2463        unsafe { cvt(ffi::SSL_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
2464    }
2465
2466    /// Like [`SslContextBuilder::set_ecdh_auto`].
2467    ///
2468    /// Requires LibreSSL.
2469    ///
2470    /// [`SslContextBuilder::set_tmp_ecdh`]: struct.SslContextBuilder.html#method.set_tmp_ecdh
2471    #[corresponds(SSL_set_ecdh_auto)]
2472    #[cfg(libressl)]
2473    pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
2474        unsafe { cvt(ffi::SSL_set_ecdh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) }
2475    }
2476
2477    /// Like [`SslContextBuilder::set_alpn_protos`].
2478    ///
2479    /// Requires AWS-LC or BoringSSL or LibreSSL or OpenSSL 1.0.2 or newer.
2480    ///
2481    /// [`SslContextBuilder::set_alpn_protos`]: struct.SslContextBuilder.html#method.set_alpn_protos
2482    #[corresponds(SSL_set_alpn_protos)]
2483    pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
2484        unsafe {
2485            assert!(protocols.len() <= c_uint::MAX as usize);
2486            let r =
2487                ffi::SSL_set_alpn_protos(self.as_ptr(), protocols.as_ptr(), protocols.len() as _);
2488            // fun fact, SSL_set_alpn_protos has a reversed return code D:
2489            if r == 0 {
2490                Ok(())
2491            } else {
2492                Err(ErrorStack::get())
2493            }
2494        }
2495    }
2496
2497    /// Returns the current cipher if the session is active.
2498    #[corresponds(SSL_get_current_cipher)]
2499    pub fn current_cipher(&self) -> Option<&SslCipherRef> {
2500        unsafe {
2501            let ptr = ffi::SSL_get_current_cipher(self.as_ptr());
2502
2503            SslCipherRef::from_const_ptr_opt(ptr)
2504        }
2505    }
2506
2507    /// Returns a short string describing the state of the session.
2508    #[corresponds(SSL_state_string)]
2509    pub fn state_string(&self) -> &'static str {
2510        let state = unsafe {
2511            let ptr = ffi::SSL_state_string(self.as_ptr());
2512            CStr::from_ptr(ptr as *const _)
2513        };
2514
2515        str::from_utf8(state.to_bytes()).unwrap()
2516    }
2517
2518    /// Returns a longer string describing the state of the session.
2519    #[corresponds(SSL_state_string_long)]
2520    pub fn state_string_long(&self) -> &'static str {
2521        let state = unsafe {
2522            let ptr = ffi::SSL_state_string_long(self.as_ptr());
2523            CStr::from_ptr(ptr as *const _)
2524        };
2525
2526        str::from_utf8(state.to_bytes()).unwrap()
2527    }
2528
2529    /// Sets the host name to be sent to the server for Server Name Indication (SNI).
2530    ///
2531    /// It has no effect for a server-side connection.
2532    #[corresponds(SSL_set_tlsext_host_name)]
2533    pub fn set_hostname(&mut self, hostname: &str) -> Result<(), ErrorStack> {
2534        let cstr = CString::new(hostname).unwrap();
2535        unsafe {
2536            cvt(ffi::SSL_set_tlsext_host_name(self.as_ptr(), cstr.as_ptr() as *mut _) as c_int)
2537                .map(|_| ())
2538        }
2539    }
2540
2541    /// Returns the peer's certificate, if present.
2542    #[corresponds(SSL_get_peer_certificate)]
2543    pub fn peer_certificate(&self) -> Option<X509> {
2544        unsafe {
2545            let ptr = SSL_get1_peer_certificate(self.as_ptr());
2546            X509::from_ptr_opt(ptr)
2547        }
2548    }
2549
2550    /// Returns the certificate chain of the peer, if present.
2551    ///
2552    /// On the client side, the chain includes the leaf certificate, but on the server side it does
2553    /// not. Fun!
2554    #[corresponds(SSL_get_peer_cert_chain)]
2555    pub fn peer_cert_chain(&self) -> Option<&StackRef<X509>> {
2556        unsafe {
2557            let ptr = ffi::SSL_get_peer_cert_chain(self.as_ptr());
2558            StackRef::from_const_ptr_opt(ptr)
2559        }
2560    }
2561
2562    /// Returns the verified certificate chain of the peer, including the leaf certificate.
2563    ///
2564    /// If verification was not successful (i.e. [`verify_result`] does not return
2565    /// [`X509VerifyResult::OK`]), this chain may be incomplete or invalid.
2566    ///
2567    /// Requires OpenSSL 1.1.0 or newer.
2568    ///
2569    /// [`verify_result`]: #method.verify_result
2570    /// [`X509VerifyResult::OK`]: ../x509/struct.X509VerifyResult.html#associatedconstant.OK
2571    #[corresponds(SSL_get0_verified_chain)]
2572    #[cfg(ossl110)]
2573    pub fn verified_chain(&self) -> Option<&StackRef<X509>> {
2574        unsafe {
2575            let ptr = ffi::SSL_get0_verified_chain(self.as_ptr());
2576            StackRef::from_const_ptr_opt(ptr)
2577        }
2578    }
2579
2580    /// Like [`SslContext::certificate`].
2581    #[corresponds(SSL_get_certificate)]
2582    pub fn certificate(&self) -> Option<&X509Ref> {
2583        unsafe {
2584            let ptr = ffi::SSL_get_certificate(self.as_ptr());
2585            X509Ref::from_const_ptr_opt(ptr)
2586        }
2587    }
2588
2589    /// Like [`SslContext::private_key`].
2590    ///
2591    /// [`SslContext::private_key`]: struct.SslContext.html#method.private_key
2592    #[corresponds(SSL_get_privatekey)]
2593    pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
2594        unsafe {
2595            let ptr = ffi::SSL_get_privatekey(self.as_ptr());
2596            PKeyRef::from_const_ptr_opt(ptr)
2597        }
2598    }
2599
2600    #[deprecated(since = "0.10.5", note = "renamed to `version_str`")]
2601    pub fn version(&self) -> &str {
2602        self.version_str()
2603    }
2604
2605    /// Returns the protocol version of the session.
2606    #[corresponds(SSL_version)]
2607    pub fn version2(&self) -> Option<SslVersion> {
2608        unsafe {
2609            let r = ffi::SSL_version(self.as_ptr());
2610            if r == 0 {
2611                None
2612            } else {
2613                Some(SslVersion(r))
2614            }
2615        }
2616    }
2617
2618    /// Returns a string describing the protocol version of the session.
2619    #[corresponds(SSL_get_version)]
2620    pub fn version_str(&self) -> &'static str {
2621        let version = unsafe {
2622            let ptr = ffi::SSL_get_version(self.as_ptr());
2623            CStr::from_ptr(ptr as *const _)
2624        };
2625
2626        str::from_utf8(version.to_bytes()).unwrap()
2627    }
2628
2629    /// Returns the protocol selected via Application Layer Protocol Negotiation (ALPN).
2630    ///
2631    /// The protocol's name is returned is an opaque sequence of bytes. It is up to the client
2632    /// to interpret it.
2633    ///
2634    /// Requires AWS-LC or BoringSSL or LibreSSL or OpenSSL 1.0.2 or newer.
2635    #[corresponds(SSL_get0_alpn_selected)]
2636    pub fn selected_alpn_protocol(&self) -> Option<&[u8]> {
2637        unsafe {
2638            let mut data: *const c_uchar = ptr::null();
2639            let mut len: c_uint = 0;
2640            // Get the negotiated protocol from the SSL instance.
2641            // `data` will point at a `c_uchar` array; `len` will contain the length of this array.
2642            ffi::SSL_get0_alpn_selected(self.as_ptr(), &mut data, &mut len);
2643
2644            if data.is_null() {
2645                None
2646            } else {
2647                Some(util::from_raw_parts(data, len as usize))
2648            }
2649        }
2650    }
2651
2652    /// Enables the DTLS extension "use_srtp" as defined in RFC5764.
2653    #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
2654    #[corresponds(SSL_set_tlsext_use_srtp)]
2655    pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
2656        unsafe {
2657            let cstr = CString::new(protocols).unwrap();
2658
2659            let r = ffi::SSL_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
2660            // fun fact, set_tlsext_use_srtp has a reversed return code D:
2661            if r == 0 {
2662                Ok(())
2663            } else {
2664                Err(ErrorStack::get())
2665            }
2666        }
2667    }
2668
2669    /// Gets all SRTP profiles that are enabled for handshake via set_tlsext_use_srtp
2670    ///
2671    /// DTLS extension "use_srtp" as defined in RFC5764 has to be enabled.
2672    #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
2673    #[corresponds(SSL_get_srtp_profiles)]
2674    pub fn srtp_profiles(&self) -> Option<&StackRef<SrtpProtectionProfile>> {
2675        unsafe {
2676            let chain = ffi::SSL_get_srtp_profiles(self.as_ptr());
2677
2678            StackRef::from_const_ptr_opt(chain)
2679        }
2680    }
2681
2682    /// Gets the SRTP profile selected by handshake.
2683    ///
2684    /// DTLS extension "use_srtp" as defined in RFC5764 has to be enabled.
2685    #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
2686    #[corresponds(SSL_get_selected_srtp_profile)]
2687    pub fn selected_srtp_profile(&self) -> Option<&SrtpProtectionProfileRef> {
2688        unsafe {
2689            let profile = ffi::SSL_get_selected_srtp_profile(self.as_ptr());
2690
2691            SrtpProtectionProfileRef::from_const_ptr_opt(profile)
2692        }
2693    }
2694
2695    /// Returns the number of bytes remaining in the currently processed TLS record.
2696    ///
2697    /// If this is greater than 0, the next call to `read` will not call down to the underlying
2698    /// stream.
2699    #[corresponds(SSL_pending)]
2700    pub fn pending(&self) -> usize {
2701        unsafe { ffi::SSL_pending(self.as_ptr()) as usize }
2702    }
2703
2704    /// Returns the servername sent by the client via Server Name Indication (SNI).
2705    ///
2706    /// It is only useful on the server side.
2707    ///
2708    /// # Note
2709    ///
2710    /// While the SNI specification requires that servernames be valid domain names (and therefore
2711    /// ASCII), OpenSSL does not enforce this restriction. If the servername provided by the client
2712    /// is not valid UTF-8, this function will return `None`. The `servername_raw` method returns
2713    /// the raw bytes and does not have this restriction.
2714    ///
2715    /// [`SSL_get_servername`]: https://docs.openssl.org/master/man3/SSL_get_servername/
2716    #[corresponds(SSL_get_servername)]
2717    // FIXME maybe rethink in 0.11?
2718    pub fn servername(&self, type_: NameType) -> Option<&str> {
2719        self.servername_raw(type_)
2720            .and_then(|b| str::from_utf8(b).ok())
2721    }
2722
2723    /// Returns the servername sent by the client via Server Name Indication (SNI).
2724    ///
2725    /// It is only useful on the server side.
2726    ///
2727    /// # Note
2728    ///
2729    /// Unlike `servername`, this method does not require the name be valid UTF-8.
2730    #[corresponds(SSL_get_servername)]
2731    pub fn servername_raw(&self, type_: NameType) -> Option<&[u8]> {
2732        unsafe {
2733            let name = ffi::SSL_get_servername(self.as_ptr(), type_.0);
2734            if name.is_null() {
2735                None
2736            } else {
2737                Some(CStr::from_ptr(name as *const _).to_bytes())
2738            }
2739        }
2740    }
2741
2742    /// Changes the context corresponding to the current connection.
2743    ///
2744    /// It is most commonly used in the Server Name Indication (SNI) callback.
2745    #[corresponds(SSL_set_SSL_CTX)]
2746    pub fn set_ssl_context(&mut self, ctx: &SslContextRef) -> Result<(), ErrorStack> {
2747        unsafe { cvt_p(ffi::SSL_set_SSL_CTX(self.as_ptr(), ctx.as_ptr())).map(|_| ()) }
2748    }
2749
2750    /// Returns the context corresponding to the current connection.
2751    #[corresponds(SSL_get_SSL_CTX)]
2752    pub fn ssl_context(&self) -> &SslContextRef {
2753        unsafe {
2754            let ssl_ctx = ffi::SSL_get_SSL_CTX(self.as_ptr());
2755            SslContextRef::from_ptr(ssl_ctx)
2756        }
2757    }
2758
2759    /// Returns a mutable reference to the X509 verification configuration.
2760    ///
2761    /// Requires AWS-LC or BoringSSL or LibreSSL or OpenSSL 1.0.2 or newer.
2762    #[corresponds(SSL_get0_param)]
2763    pub fn param_mut(&mut self) -> &mut X509VerifyParamRef {
2764        unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_get0_param(self.as_ptr())) }
2765    }
2766
2767    /// Returns the certificate verification result.
2768    #[corresponds(SSL_get_verify_result)]
2769    pub fn verify_result(&self) -> X509VerifyResult {
2770        unsafe { X509VerifyResult::from_raw(ffi::SSL_get_verify_result(self.as_ptr()) as c_int) }
2771    }
2772
2773    /// Returns a shared reference to the SSL session.
2774    #[corresponds(SSL_get_session)]
2775    pub fn session(&self) -> Option<&SslSessionRef> {
2776        unsafe {
2777            let p = ffi::SSL_get_session(self.as_ptr());
2778            SslSessionRef::from_const_ptr_opt(p)
2779        }
2780    }
2781
2782    /// Copies the `client_random` value sent by the client in the TLS handshake into a buffer.
2783    ///
2784    /// Returns the number of bytes copied, or if the buffer is empty, the size of the `client_random`
2785    /// value.
2786    ///
2787    /// Requires LibreSSL or OpenSSL 1.1.0 or newer.
2788    #[corresponds(SSL_get_client_random)]
2789    #[cfg(any(ossl110, libressl))]
2790    pub fn client_random(&self, buf: &mut [u8]) -> usize {
2791        unsafe {
2792            ffi::SSL_get_client_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
2793        }
2794    }
2795
2796    /// Copies the `server_random` value sent by the server in the TLS handshake into a buffer.
2797    ///
2798    /// Returns the number of bytes copied, or if the buffer is empty, the size of the `server_random`
2799    /// value.
2800    ///
2801    /// Requires LibreSSL or OpenSSL 1.1.0 or newer.
2802    #[corresponds(SSL_get_server_random)]
2803    #[cfg(any(ossl110, libressl))]
2804    pub fn server_random(&self, buf: &mut [u8]) -> usize {
2805        unsafe {
2806            ffi::SSL_get_server_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
2807        }
2808    }
2809
2810    /// Derives keying material for application use in accordance to RFC 5705.
2811    #[corresponds(SSL_export_keying_material)]
2812    pub fn export_keying_material(
2813        &self,
2814        out: &mut [u8],
2815        label: &str,
2816        context: Option<&[u8]>,
2817    ) -> Result<(), ErrorStack> {
2818        unsafe {
2819            let (context, contextlen, use_context) = match context {
2820                Some(context) => (context.as_ptr() as *const c_uchar, context.len(), 1),
2821                None => (ptr::null(), 0, 0),
2822            };
2823            cvt(ffi::SSL_export_keying_material(
2824                self.as_ptr(),
2825                out.as_mut_ptr() as *mut c_uchar,
2826                out.len(),
2827                label.as_ptr() as *const c_char,
2828                label.len(),
2829                context,
2830                contextlen,
2831                use_context,
2832            ))
2833            .map(|_| ())
2834        }
2835    }
2836
2837    /// Derives keying material for application use in accordance to RFC 5705.
2838    ///
2839    /// This function is only usable with TLSv1.3, wherein there is no distinction between an empty context and no
2840    /// context. Therefore, unlike `export_keying_material`, `context` must always be supplied.
2841    ///
2842    /// Requires OpenSSL 1.1.1 or newer.
2843    #[corresponds(SSL_export_keying_material_early)]
2844    #[cfg(ossl111)]
2845    pub fn export_keying_material_early(
2846        &self,
2847        out: &mut [u8],
2848        label: &str,
2849        context: &[u8],
2850    ) -> Result<(), ErrorStack> {
2851        unsafe {
2852            cvt(ffi::SSL_export_keying_material_early(
2853                self.as_ptr(),
2854                out.as_mut_ptr() as *mut c_uchar,
2855                out.len(),
2856                label.as_ptr() as *const c_char,
2857                label.len(),
2858                context.as_ptr() as *const c_uchar,
2859                context.len(),
2860            ))
2861            .map(|_| ())
2862        }
2863    }
2864
2865    /// Sets the session to be used.
2866    ///
2867    /// This should be called before the handshake to attempt to reuse a previously established
2868    /// session. If the server is not willing to reuse the session, a new one will be transparently
2869    /// negotiated.
2870    ///
2871    /// # Safety
2872    ///
2873    /// The caller of this method is responsible for ensuring that the session is associated
2874    /// with the same `SslContext` as this `Ssl`.
2875    #[corresponds(SSL_set_session)]
2876    pub unsafe fn set_session(&mut self, session: &SslSessionRef) -> Result<(), ErrorStack> {
2877        cvt(ffi::SSL_set_session(self.as_ptr(), session.as_ptr())).map(|_| ())
2878    }
2879
2880    /// Determines if the session provided to `set_session` was successfully reused.
2881    #[corresponds(SSL_session_reused)]
2882    pub fn session_reused(&self) -> bool {
2883        unsafe { ffi::SSL_session_reused(self.as_ptr()) != 0 }
2884    }
2885
2886    /// Sets the status response a client wishes the server to reply with.
2887    #[corresponds(SSL_set_tlsext_status_type)]
2888    pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> {
2889        unsafe {
2890            cvt(ffi::SSL_set_tlsext_status_type(self.as_ptr(), type_.as_raw()) as c_int).map(|_| ())
2891        }
2892    }
2893
2894    /// Determines if current session used Extended Master Secret
2895    ///
2896    /// Returns `None` if the handshake is still in-progress.
2897    #[corresponds(SSL_get_extms_support)]
2898    #[cfg(ossl110)]
2899    pub fn extms_support(&self) -> Option<bool> {
2900        unsafe {
2901            match ffi::SSL_get_extms_support(self.as_ptr()) {
2902                -1 => None,
2903                ret => Some(ret != 0),
2904            }
2905        }
2906    }
2907
2908    /// Returns the server's OCSP response, if present.
2909    #[corresponds(SSL_get_tlsext_status_ocsp_resp)]
2910    #[cfg(not(any(boringssl, awslc)))]
2911    pub fn ocsp_status(&self) -> Option<&[u8]> {
2912        unsafe {
2913            let mut p = ptr::null_mut();
2914            let len = ffi::SSL_get_tlsext_status_ocsp_resp(self.as_ptr(), &mut p);
2915
2916            if len < 0 {
2917                None
2918            } else {
2919                Some(util::from_raw_parts(p as *const u8, len as usize))
2920            }
2921        }
2922    }
2923
2924    /// Sets the OCSP response to be returned to the client.
2925    #[corresponds(SSL_set_tlsext_status_oscp_resp)]
2926    #[cfg(not(any(boringssl, awslc)))]
2927    pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> {
2928        unsafe {
2929            assert!(response.len() <= c_int::MAX as usize);
2930            let p = cvt_p(ffi::OPENSSL_malloc(response.len() as _))?;
2931            ptr::copy_nonoverlapping(response.as_ptr(), p as *mut u8, response.len());
2932            cvt(ffi::SSL_set_tlsext_status_ocsp_resp(
2933                self.as_ptr(),
2934                p as *mut c_uchar,
2935                response.len() as c_long,
2936            ) as c_int)
2937            .map(|_| ())
2938            .inspect_err(|_| {
2939                ffi::OPENSSL_free(p);
2940            })
2941        }
2942    }
2943
2944    /// Determines if this `Ssl` is configured for server-side or client-side use.
2945    #[corresponds(SSL_is_server)]
2946    pub fn is_server(&self) -> bool {
2947        unsafe { SSL_is_server(self.as_ptr()) != 0 }
2948    }
2949
2950    /// Sets the extra data at the specified index.
2951    ///
2952    /// This can be used to provide data to callbacks registered with the context. Use the
2953    /// `Ssl::new_ex_index` method to create an `Index`.
2954    // FIXME should return a result
2955    #[corresponds(SSL_set_ex_data)]
2956    pub fn set_ex_data<T>(&mut self, index: Index<Ssl, T>, data: T) {
2957        match self.ex_data_mut(index) {
2958            Some(v) => *v = data,
2959            None => unsafe {
2960                let data = Box::new(data);
2961                ffi::SSL_set_ex_data(
2962                    self.as_ptr(),
2963                    index.as_raw(),
2964                    Box::into_raw(data) as *mut c_void,
2965                );
2966            },
2967        }
2968    }
2969
2970    /// Returns a reference to the extra data at the specified index.
2971    #[corresponds(SSL_get_ex_data)]
2972    pub fn ex_data<T>(&self, index: Index<Ssl, T>) -> Option<&T> {
2973        unsafe {
2974            let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
2975            if data.is_null() {
2976                None
2977            } else {
2978                Some(&*(data as *const T))
2979            }
2980        }
2981    }
2982
2983    /// Returns a mutable reference to the extra data at the specified index.
2984    #[corresponds(SSL_get_ex_data)]
2985    pub fn ex_data_mut<T>(&mut self, index: Index<Ssl, T>) -> Option<&mut T> {
2986        unsafe {
2987            let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
2988            if data.is_null() {
2989                None
2990            } else {
2991                Some(&mut *(data as *mut T))
2992            }
2993        }
2994    }
2995
2996    /// Sets the maximum amount of early data that will be accepted on this connection.
2997    ///
2998    /// Requires OpenSSL 1.1.1 or newer or LibreSSL.
2999    #[corresponds(SSL_set_max_early_data)]
3000    #[cfg(any(ossl111, libressl))]
3001    pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
3002        if unsafe { ffi::SSL_set_max_early_data(self.as_ptr(), bytes) } == 1 {
3003            Ok(())
3004        } else {
3005            Err(ErrorStack::get())
3006        }
3007    }
3008
3009    /// Gets the maximum amount of early data that can be sent on this connection.
3010    ///
3011    /// Requires OpenSSL 1.1.1 or newer or LibreSSL.
3012    #[corresponds(SSL_get_max_early_data)]
3013    #[cfg(any(ossl111, libressl))]
3014    pub fn max_early_data(&self) -> u32 {
3015        unsafe { ffi::SSL_get_max_early_data(self.as_ptr()) }
3016    }
3017
3018    /// Copies the contents of the last Finished message sent to the peer into the provided buffer.
3019    ///
3020    /// The total size of the message is returned, so this can be used to determine the size of the
3021    /// buffer required.
3022    #[corresponds(SSL_get_finished)]
3023    pub fn finished(&self, buf: &mut [u8]) -> usize {
3024        unsafe { ffi::SSL_get_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len()) }
3025    }
3026
3027    /// Copies the contents of the last Finished message received from the peer into the provided
3028    /// buffer.
3029    ///
3030    /// The total size of the message is returned, so this can be used to determine the size of the
3031    /// buffer required.
3032    #[corresponds(SSL_get_peer_finished)]
3033    pub fn peer_finished(&self, buf: &mut [u8]) -> usize {
3034        unsafe {
3035            ffi::SSL_get_peer_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len())
3036        }
3037    }
3038
3039    /// Determines if the initial handshake has been completed.
3040    #[corresponds(SSL_is_init_finished)]
3041    #[cfg(ossl110)]
3042    pub fn is_init_finished(&self) -> bool {
3043        unsafe { ffi::SSL_is_init_finished(self.as_ptr()) != 0 }
3044    }
3045
3046    /// Determines if the client's hello message is in the SSLv2 format.
3047    ///
3048    /// This can only be used inside of the client hello callback. Otherwise, `false` is returned.
3049    ///
3050    /// Requires OpenSSL 1.1.1 or newer.
3051    #[corresponds(SSL_client_hello_isv2)]
3052    #[cfg(ossl111)]
3053    pub fn client_hello_isv2(&self) -> bool {
3054        unsafe { ffi::SSL_client_hello_isv2(self.as_ptr()) != 0 }
3055    }
3056
3057    /// Returns the legacy version field of the client's hello message.
3058    ///
3059    /// This can only be used inside of the client hello callback. Otherwise, `None` is returned.
3060    ///
3061    /// Requires OpenSSL 1.1.1 or newer.
3062    #[corresponds(SSL_client_hello_get0_legacy_version)]
3063    #[cfg(ossl111)]
3064    pub fn client_hello_legacy_version(&self) -> Option<SslVersion> {
3065        unsafe {
3066            let version = ffi::SSL_client_hello_get0_legacy_version(self.as_ptr());
3067            if version == 0 {
3068                None
3069            } else {
3070                Some(SslVersion(version as c_int))
3071            }
3072        }
3073    }
3074
3075    /// Returns the random field of the client's hello message.
3076    ///
3077    /// This can only be used inside of the client hello callback. Otherwise, `None` is returned.
3078    ///
3079    /// Requires OpenSSL 1.1.1 or newer.
3080    #[corresponds(SSL_client_hello_get0_random)]
3081    #[cfg(ossl111)]
3082    pub fn client_hello_random(&self) -> Option<&[u8]> {
3083        unsafe {
3084            let mut ptr = ptr::null();
3085            let len = ffi::SSL_client_hello_get0_random(self.as_ptr(), &mut ptr);
3086            if len == 0 {
3087                None
3088            } else {
3089                Some(util::from_raw_parts(ptr, len))
3090            }
3091        }
3092    }
3093
3094    /// Returns the session ID field of the client's hello message.
3095    ///
3096    /// This can only be used inside of the client hello callback. Otherwise, `None` is returned.
3097    ///
3098    /// Requires OpenSSL 1.1.1 or newer.
3099    #[corresponds(SSL_client_hello_get0_session_id)]
3100    #[cfg(ossl111)]
3101    pub fn client_hello_session_id(&self) -> Option<&[u8]> {
3102        unsafe {
3103            let mut ptr = ptr::null();
3104            let len = ffi::SSL_client_hello_get0_session_id(self.as_ptr(), &mut ptr);
3105            if len == 0 {
3106                None
3107            } else {
3108                Some(util::from_raw_parts(ptr, len))
3109            }
3110        }
3111    }
3112
3113    /// Returns the ciphers field of the client's hello message.
3114    ///
3115    /// This can only be used inside of the client hello callback. Otherwise, `None` is returned.
3116    ///
3117    /// Requires OpenSSL 1.1.1 or newer.
3118    #[corresponds(SSL_client_hello_get0_ciphers)]
3119    #[cfg(ossl111)]
3120    pub fn client_hello_ciphers(&self) -> Option<&[u8]> {
3121        unsafe {
3122            let mut ptr = ptr::null();
3123            let len = ffi::SSL_client_hello_get0_ciphers(self.as_ptr(), &mut ptr);
3124            if len == 0 {
3125                None
3126            } else {
3127                Some(util::from_raw_parts(ptr, len))
3128            }
3129        }
3130    }
3131
3132    /// Decodes a slice of wire-format cipher suite specification bytes. Unsupported cipher suites
3133    /// are ignored.
3134    ///
3135    /// Requires OpenSSL 1.1.1 or newer.
3136    #[corresponds(SSL_bytes_to_cipher_list)]
3137    #[cfg(ossl111)]
3138    pub fn bytes_to_cipher_list(
3139        &self,
3140        bytes: &[u8],
3141        isv2format: bool,
3142    ) -> Result<CipherLists, ErrorStack> {
3143        unsafe {
3144            let ptr = bytes.as_ptr();
3145            let len = bytes.len();
3146            let mut sk = ptr::null_mut();
3147            let mut scsvs = ptr::null_mut();
3148            let res = ffi::SSL_bytes_to_cipher_list(
3149                self.as_ptr(),
3150                ptr,
3151                len,
3152                isv2format as c_int,
3153                &mut sk,
3154                &mut scsvs,
3155            );
3156            if res == 1 {
3157                Ok(CipherLists {
3158                    suites: Stack::from_ptr(sk),
3159                    signalling_suites: Stack::from_ptr(scsvs),
3160                })
3161            } else {
3162                Err(ErrorStack::get())
3163            }
3164        }
3165    }
3166
3167    /// Returns the compression methods field of the client's hello message.
3168    ///
3169    /// This can only be used inside of the client hello callback. Otherwise, `None` is returned.
3170    ///
3171    /// Requires OpenSSL 1.1.1 or newer.
3172    #[corresponds(SSL_client_hello_get0_compression_methods)]
3173    #[cfg(ossl111)]
3174    pub fn client_hello_compression_methods(&self) -> Option<&[u8]> {
3175        unsafe {
3176            let mut ptr = ptr::null();
3177            let len = ffi::SSL_client_hello_get0_compression_methods(self.as_ptr(), &mut ptr);
3178            if len == 0 {
3179                None
3180            } else {
3181                Some(util::from_raw_parts(ptr, len))
3182            }
3183        }
3184    }
3185
3186    /// Sets the MTU used for DTLS connections.
3187    #[corresponds(SSL_set_mtu)]
3188    pub fn set_mtu(&mut self, mtu: u32) -> Result<(), ErrorStack> {
3189        unsafe { cvt(ffi::SSL_set_mtu(self.as_ptr(), mtu as MtuTy) as c_int).map(|_| ()) }
3190    }
3191
3192    /// Returns the PSK identity hint used during connection setup.
3193    ///
3194    /// May return `None` if no PSK identity hint was used during the connection setup.
3195    #[corresponds(SSL_get_psk_identity_hint)]
3196    #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
3197    pub fn psk_identity_hint(&self) -> Option<&[u8]> {
3198        unsafe {
3199            let ptr = ffi::SSL_get_psk_identity_hint(self.as_ptr());
3200            if ptr.is_null() {
3201                None
3202            } else {
3203                Some(CStr::from_ptr(ptr).to_bytes())
3204            }
3205        }
3206    }
3207
3208    /// Returns the PSK identity used during connection setup.
3209    #[corresponds(SSL_get_psk_identity)]
3210    #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
3211    pub fn psk_identity(&self) -> Option<&[u8]> {
3212        unsafe {
3213            let ptr = ffi::SSL_get_psk_identity(self.as_ptr());
3214            if ptr.is_null() {
3215                None
3216            } else {
3217                Some(CStr::from_ptr(ptr).to_bytes())
3218            }
3219        }
3220    }
3221
3222    #[corresponds(SSL_add0_chain_cert)]
3223    #[cfg(ossl110)]
3224    pub fn add_chain_cert(&mut self, chain: X509) -> Result<(), ErrorStack> {
3225        unsafe {
3226            cvt(ffi::SSL_add0_chain_cert(self.as_ptr(), chain.as_ptr()) as c_int).map(|_| ())?;
3227            mem::forget(chain);
3228        }
3229        Ok(())
3230    }
3231
3232    /// Sets a new default TLS/SSL method for SSL objects
3233    #[cfg(not(any(boringssl, awslc)))]
3234    pub fn set_method(&mut self, method: SslMethod) -> Result<(), ErrorStack> {
3235        unsafe {
3236            cvt(ffi::SSL_set_ssl_method(self.as_ptr(), method.as_ptr()))?;
3237        };
3238        Ok(())
3239    }
3240
3241    /// Loads the private key from a file.
3242    #[corresponds(SSL_use_Private_Key_file)]
3243    pub fn set_private_key_file<P: AsRef<Path>>(
3244        &mut self,
3245        path: P,
3246        ssl_file_type: SslFiletype,
3247    ) -> Result<(), ErrorStack> {
3248        let p = path.as_ref().as_os_str().to_str().unwrap();
3249        let key_file = CString::new(p).unwrap();
3250        unsafe {
3251            cvt(ffi::SSL_use_PrivateKey_file(
3252                self.as_ptr(),
3253                key_file.as_ptr(),
3254                ssl_file_type.as_raw(),
3255            ))?;
3256        };
3257        Ok(())
3258    }
3259
3260    /// Sets the private key.
3261    #[corresponds(SSL_use_PrivateKey)]
3262    pub fn set_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3263        unsafe {
3264            cvt(ffi::SSL_use_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
3265        };
3266        Ok(())
3267    }
3268
3269    /// Sets the certificate
3270    #[corresponds(SSL_use_certificate)]
3271    pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
3272        unsafe {
3273            cvt(ffi::SSL_use_certificate(self.as_ptr(), cert.as_ptr()))?;
3274        };
3275        Ok(())
3276    }
3277
3278    /// Loads a certificate chain from a file.
3279    ///
3280    /// The file should contain a sequence of PEM-formatted certificates, the first being the leaf
3281    /// certificate, and the remainder forming the chain of certificates up to and including the
3282    /// trusted root certificate.
3283    #[corresponds(SSL_use_certificate_chain_file)]
3284    #[cfg(any(ossl110, libressl))]
3285    pub fn set_certificate_chain_file<P: AsRef<Path>>(
3286        &mut self,
3287        path: P,
3288    ) -> Result<(), ErrorStack> {
3289        let p = path.as_ref().as_os_str().to_str().unwrap();
3290        let cert_file = CString::new(p).unwrap();
3291        unsafe {
3292            cvt(ffi::SSL_use_certificate_chain_file(
3293                self.as_ptr(),
3294                cert_file.as_ptr(),
3295            ))?;
3296        };
3297        Ok(())
3298    }
3299
3300    /// Sets ca certificate that client trusted
3301    #[corresponds(SSL_add_client_CA)]
3302    pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
3303        unsafe {
3304            cvt(ffi::SSL_add_client_CA(self.as_ptr(), cacert.as_ptr()))?;
3305        };
3306        Ok(())
3307    }
3308
3309    // Sets the list of CAs sent to the client when requesting a client certificate for the chosen ssl
3310    #[corresponds(SSL_set_client_CA_list)]
3311    pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
3312        unsafe { ffi::SSL_set_client_CA_list(self.as_ptr(), list.as_ptr()) }
3313        mem::forget(list);
3314    }
3315
3316    /// Sets the minimum supported protocol version.
3317    ///
3318    /// A value of `None` will enable protocol versions down to the lowest version supported by
3319    /// OpenSSL.
3320    #[corresponds(SSL_set_min_proto_version)]
3321    pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
3322        unsafe {
3323            cvt(ffi::SSL_set_min_proto_version(
3324                self.as_ptr(),
3325                version.map_or(0, |v| v.0 as _),
3326            ))
3327            .map(|_| ())
3328        }
3329    }
3330
3331    /// Sets the maximum supported protocol version.
3332    ///
3333    /// A value of `None` will enable protocol versions up to the highest version supported by
3334    /// OpenSSL.
3335    #[corresponds(SSL_set_max_proto_version)]
3336    pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
3337        unsafe {
3338            cvt(ffi::SSL_set_max_proto_version(
3339                self.as_ptr(),
3340                version.map_or(0, |v| v.0 as _),
3341            ))
3342            .map(|_| ())
3343        }
3344    }
3345
3346    /// Sets the list of supported ciphers for the TLSv1.3 protocol.
3347    ///
3348    /// The `set_cipher_list` method controls the cipher suites for protocols before TLSv1.3.
3349    ///
3350    /// The format consists of TLSv1.3 cipher suite names separated by `:` characters in order of
3351    /// preference.
3352    ///
3353    /// Requires OpenSSL 1.1.1 or newer or LibreSSL.
3354    #[corresponds(SSL_set_ciphersuites)]
3355    #[cfg(any(ossl111, libressl))]
3356    pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
3357        let cipher_list = CString::new(cipher_list).unwrap();
3358        unsafe {
3359            cvt(ffi::SSL_set_ciphersuites(
3360                self.as_ptr(),
3361                cipher_list.as_ptr() as *const _,
3362            ))
3363            .map(|_| ())
3364        }
3365    }
3366
3367    /// Sets the list of supported ciphers for protocols before TLSv1.3.
3368    ///
3369    /// The `set_ciphersuites` method controls the cipher suites for TLSv1.3.
3370    ///
3371    /// See [`ciphers`] for details on the format.
3372    ///
3373    /// [`ciphers`]: https://docs.openssl.org/master/man1/ciphers/
3374    #[corresponds(SSL_set_cipher_list)]
3375    pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
3376        let cipher_list = CString::new(cipher_list).unwrap();
3377        unsafe {
3378            cvt(ffi::SSL_set_cipher_list(
3379                self.as_ptr(),
3380                cipher_list.as_ptr() as *const _,
3381            ))
3382            .map(|_| ())
3383        }
3384    }
3385
3386    /// Set the certificate store used for certificate verification
3387    #[corresponds(SSL_set_cert_store)]
3388    #[cfg(ossl110)]
3389    pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
3390        unsafe {
3391            cvt(ffi::SSL_set0_verify_cert_store(self.as_ptr(), cert_store.as_ptr()) as c_int)?;
3392            mem::forget(cert_store);
3393            Ok(())
3394        }
3395    }
3396
3397    /// Sets the number of TLS 1.3 session tickets that will be sent to a client after a full
3398    /// handshake.
3399    ///
3400    /// Requires OpenSSL 1.1.1 or newer.
3401    #[corresponds(SSL_set_num_tickets)]
3402    #[cfg(ossl111)]
3403    pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
3404        unsafe { cvt(ffi::SSL_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
3405    }
3406
3407    /// Gets the number of TLS 1.3 session tickets that will be sent to a client after a full
3408    /// handshake.
3409    ///
3410    /// Requires OpenSSL 1.1.1 or newer.
3411    #[corresponds(SSL_get_num_tickets)]
3412    #[cfg(ossl111)]
3413    pub fn num_tickets(&self) -> usize {
3414        unsafe { ffi::SSL_get_num_tickets(self.as_ptr()) }
3415    }
3416
3417    /// Set the context's security level to a value between 0 and 5, inclusive.
3418    /// A security value of 0 allows allows all parameters and algorithms.
3419    ///
3420    /// Requires OpenSSL 1.1.0 or newer.
3421    #[corresponds(SSL_set_security_level)]
3422    #[cfg(any(ossl110, libressl360))]
3423    pub fn set_security_level(&mut self, level: u32) {
3424        unsafe { ffi::SSL_set_security_level(self.as_ptr(), level as c_int) }
3425    }
3426
3427    /// Get the connection's security level, which controls the allowed parameters
3428    /// and algorithms.
3429    ///
3430    /// Requires OpenSSL 1.1.0 or newer.
3431    #[corresponds(SSL_get_security_level)]
3432    #[cfg(any(ossl110, libressl360))]
3433    pub fn security_level(&self) -> u32 {
3434        unsafe { ffi::SSL_get_security_level(self.as_ptr()) as u32 }
3435    }
3436
3437    /// Get the temporary key provided by the peer that is used during key
3438    /// exchange.
3439    // We use an owned value because EVP_KEY free need to be called when it is
3440    // dropped
3441    #[corresponds(SSL_get_peer_tmp_key)]
3442    #[cfg(ossl300)]
3443    pub fn peer_tmp_key(&self) -> Result<PKey<Public>, ErrorStack> {
3444        unsafe {
3445            let mut key = ptr::null_mut();
3446            match cvt_long(ffi::SSL_get_peer_tmp_key(self.as_ptr(), &mut key)) {
3447                Ok(_) => Ok(PKey::<Public>::from_ptr(key)),
3448                Err(e) => Err(e),
3449            }
3450        }
3451    }
3452
3453    /// Returns the temporary key from the local end of the connection that is
3454    /// used during key exchange.
3455    // We use an owned value because EVP_KEY free need to be called when it is
3456    // dropped
3457    #[corresponds(SSL_get_tmp_key)]
3458    #[cfg(ossl300)]
3459    pub fn tmp_key(&self) -> Result<PKey<Private>, ErrorStack> {
3460        unsafe {
3461            let mut key = ptr::null_mut();
3462            match cvt_long(ffi::SSL_get_tmp_key(self.as_ptr(), &mut key)) {
3463                Ok(_) => Ok(PKey::<Private>::from_ptr(key)),
3464                Err(e) => Err(e),
3465            }
3466        }
3467    }
3468}
3469
3470/// An SSL stream midway through the handshake process.
3471#[derive(Debug)]
3472pub struct MidHandshakeSslStream<S> {
3473    stream: SslStream<S>,
3474    error: Error,
3475}
3476
3477impl<S> MidHandshakeSslStream<S> {
3478    /// Returns a shared reference to the inner stream.
3479    pub fn get_ref(&self) -> &S {
3480        self.stream.get_ref()
3481    }
3482
3483    /// Returns a mutable reference to the inner stream.
3484    pub fn get_mut(&mut self) -> &mut S {
3485        self.stream.get_mut()
3486    }
3487
3488    /// Returns a shared reference to the `Ssl` of the stream.
3489    pub fn ssl(&self) -> &SslRef {
3490        self.stream.ssl()
3491    }
3492
3493    /// Returns the underlying error which interrupted this handshake.
3494    pub fn error(&self) -> &Error {
3495        &self.error
3496    }
3497
3498    /// Consumes `self`, returning its error.
3499    pub fn into_error(self) -> Error {
3500        self.error
3501    }
3502}
3503
3504impl<S> MidHandshakeSslStream<S>
3505where
3506    S: Read + Write,
3507{
3508    /// Restarts the handshake process.
3509    ///
3510    #[corresponds(SSL_do_handshake)]
3511    pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
3512        match self.stream.do_handshake() {
3513            Ok(()) => Ok(self.stream),
3514            Err(error) => {
3515                self.error = error;
3516                match self.error.code() {
3517                    ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
3518                        Err(HandshakeError::WouldBlock(self))
3519                    }
3520                    _ => Err(HandshakeError::Failure(self)),
3521                }
3522            }
3523        }
3524    }
3525}
3526
3527/// A TLS session over a stream.
3528pub struct SslStream<S> {
3529    ssl: ManuallyDrop<Ssl>,
3530    method: ManuallyDrop<BioMethod>,
3531    _p: PhantomData<S>,
3532}
3533
3534impl<S> Drop for SslStream<S> {
3535    fn drop(&mut self) {
3536        // ssl holds a reference to method internally so it has to drop first
3537        unsafe {
3538            ManuallyDrop::drop(&mut self.ssl);
3539            ManuallyDrop::drop(&mut self.method);
3540        }
3541    }
3542}
3543
3544impl<S> fmt::Debug for SslStream<S>
3545where
3546    S: fmt::Debug,
3547{
3548    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
3549        fmt.debug_struct("SslStream")
3550            .field("stream", &self.get_ref())
3551            .field("ssl", &self.ssl())
3552            .finish()
3553    }
3554}
3555
3556impl<S: Read + Write> SslStream<S> {
3557    /// Creates a new `SslStream`.
3558    ///
3559    /// This function performs no IO; the stream will not have performed any part of the handshake
3560    /// with the peer. If the `Ssl` was configured with [`SslRef::set_connect_state`] or
3561    /// [`SslRef::set_accept_state`], the handshake can be performed automatically during the first
3562    /// call to read or write. Otherwise the `connect` and `accept` methods can be used to
3563    /// explicitly perform the handshake.
3564    #[corresponds(SSL_set_bio)]
3565    pub fn new(ssl: Ssl, stream: S) -> Result<Self, ErrorStack> {
3566        let (bio, method) = bio::new(stream)?;
3567        unsafe {
3568            ffi::SSL_set_bio(ssl.as_ptr(), bio, bio);
3569        }
3570
3571        Ok(SslStream {
3572            ssl: ManuallyDrop::new(ssl),
3573            method: ManuallyDrop::new(method),
3574            _p: PhantomData,
3575        })
3576    }
3577
3578    /// Constructs an `SslStream` from a pointer to the underlying OpenSSL `SSL` struct.
3579    ///
3580    /// This is useful if the handshake has already been completed elsewhere.
3581    ///
3582    /// # Safety
3583    ///
3584    /// The caller must ensure the pointer is valid.
3585    #[deprecated(
3586        since = "0.10.32",
3587        note = "use Ssl::from_ptr and SslStream::new instead"
3588    )]
3589    pub unsafe fn from_raw_parts(ssl: *mut ffi::SSL, stream: S) -> Self {
3590        let ssl = Ssl::from_ptr(ssl);
3591        Self::new(ssl, stream).unwrap()
3592    }
3593
3594    /// Read application data transmitted by a client before handshake completion.
3595    ///
3596    /// Useful for reducing latency, but vulnerable to replay attacks. Call
3597    /// [`SslRef::set_accept_state`] first.
3598    ///
3599    /// Returns `Ok(0)` if all early data has been read.
3600    ///
3601    /// Requires OpenSSL 1.1.1 or newer or LibreSSL.
3602    #[corresponds(SSL_read_early_data)]
3603    #[cfg(any(ossl111, libressl))]
3604    pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
3605        let mut read = 0;
3606        let ret = unsafe {
3607            ffi::SSL_read_early_data(
3608                self.ssl.as_ptr(),
3609                buf.as_ptr() as *mut c_void,
3610                buf.len(),
3611                &mut read,
3612            )
3613        };
3614        match ret {
3615            ffi::SSL_READ_EARLY_DATA_ERROR => Err(self.make_error(ret)),
3616            ffi::SSL_READ_EARLY_DATA_SUCCESS => Ok(read),
3617            ffi::SSL_READ_EARLY_DATA_FINISH => Ok(0),
3618            _ => unreachable!(),
3619        }
3620    }
3621
3622    /// Send data to the server without blocking on handshake completion.
3623    ///
3624    /// Useful for reducing latency, but vulnerable to replay attacks. Call
3625    /// [`SslRef::set_connect_state`] first.
3626    ///
3627    /// Requires OpenSSL 1.1.1 or newer or LibreSSL.
3628    #[corresponds(SSL_write_early_data)]
3629    #[cfg(any(ossl111, libressl))]
3630    pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
3631        let mut written = 0;
3632        let ret = unsafe {
3633            ffi::SSL_write_early_data(
3634                self.ssl.as_ptr(),
3635                buf.as_ptr() as *const c_void,
3636                buf.len(),
3637                &mut written,
3638            )
3639        };
3640        if ret > 0 {
3641            Ok(written)
3642        } else {
3643            Err(self.make_error(ret))
3644        }
3645    }
3646
3647    /// Initiates a client-side TLS handshake.
3648    ///
3649    /// # Warning
3650    ///
3651    /// OpenSSL's default configuration is insecure. It is highly recommended to use
3652    /// `SslConnector` rather than `Ssl` directly, as it manages that configuration.
3653    #[corresponds(SSL_connect)]
3654    pub fn connect(&mut self) -> Result<(), Error> {
3655        let ret = unsafe { ffi::SSL_connect(self.ssl.as_ptr()) };
3656        if ret > 0 {
3657            Ok(())
3658        } else {
3659            Err(self.make_error(ret))
3660        }
3661    }
3662
3663    /// Initiates a server-side TLS handshake.
3664    ///
3665    /// # Warning
3666    ///
3667    /// OpenSSL's default configuration is insecure. It is highly recommended to use
3668    /// `SslAcceptor` rather than `Ssl` directly, as it manages that configuration.
3669    #[corresponds(SSL_accept)]
3670    pub fn accept(&mut self) -> Result<(), Error> {
3671        let ret = unsafe { ffi::SSL_accept(self.ssl.as_ptr()) };
3672        if ret > 0 {
3673            Ok(())
3674        } else {
3675            Err(self.make_error(ret))
3676        }
3677    }
3678
3679    /// Initiates the handshake.
3680    ///
3681    /// This will fail if `set_accept_state` or `set_connect_state` was not called first.
3682    #[corresponds(SSL_do_handshake)]
3683    pub fn do_handshake(&mut self) -> Result<(), Error> {
3684        let ret = unsafe { ffi::SSL_do_handshake(self.ssl.as_ptr()) };
3685        if ret > 0 {
3686            Ok(())
3687        } else {
3688            Err(self.make_error(ret))
3689        }
3690    }
3691
3692    /// Perform a stateless server-side handshake.
3693    ///
3694    /// Requires that cookie generation and verification callbacks were
3695    /// set on the SSL context.
3696    ///
3697    /// Returns `Ok(true)` if a complete ClientHello containing a valid cookie
3698    /// was read, in which case the handshake should be continued via
3699    /// `accept`. If a HelloRetryRequest containing a fresh cookie was
3700    /// transmitted, `Ok(false)` is returned instead. If the handshake cannot
3701    /// proceed at all, `Err` is returned.
3702    #[corresponds(SSL_stateless)]
3703    #[cfg(ossl111)]
3704    pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
3705        match unsafe { ffi::SSL_stateless(self.ssl.as_ptr()) } {
3706            1 => Ok(true),
3707            0 => Ok(false),
3708            -1 => Err(ErrorStack::get()),
3709            _ => unreachable!(),
3710        }
3711    }
3712
3713    /// Like `read`, but takes a possibly-uninitialized slice.
3714    ///
3715    /// # Safety
3716    ///
3717    /// No portion of `buf` will be de-initialized by this method. If the method returns `Ok(n)`,
3718    /// then the first `n` bytes of `buf` are guaranteed to be initialized.
3719    #[corresponds(SSL_read_ex)]
3720    pub fn read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
3721        loop {
3722            match self.ssl_read_uninit(buf) {
3723                Ok(n) => return Ok(n),
3724                Err(ref e) if e.code() == ErrorCode::ZERO_RETURN => return Ok(0),
3725                Err(ref e) if e.code() == ErrorCode::SYSCALL && e.io_error().is_none() => {
3726                    return Ok(0);
3727                }
3728                Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
3729                Err(e) => {
3730                    return Err(e.into_io_error().unwrap_or_else(io::Error::other));
3731                }
3732            }
3733        }
3734    }
3735
3736    /// Like `read`, but returns an `ssl::Error` rather than an `io::Error`.
3737    ///
3738    /// It is particularly useful with a non-blocking socket, where the error value will identify if
3739    /// OpenSSL is waiting on read or write readiness.
3740    #[corresponds(SSL_read_ex)]
3741    pub fn ssl_read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
3742        // SAFETY: `ssl_read_uninit` does not de-initialize the buffer.
3743        unsafe {
3744            self.ssl_read_uninit(util::from_raw_parts_mut(
3745                buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
3746                buf.len(),
3747            ))
3748        }
3749    }
3750
3751    /// Like `read_ssl`, but takes a possibly-uninitialized slice.
3752    ///
3753    /// # Safety
3754    ///
3755    /// No portion of `buf` will be de-initialized by this method. If the method returns `Ok(n)`,
3756    /// then the first `n` bytes of `buf` are guaranteed to be initialized.
3757    #[corresponds(SSL_read_ex)]
3758    pub fn ssl_read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize, Error> {
3759        if buf.is_empty() {
3760            return Ok(0);
3761        }
3762
3763        cfg_if! {
3764            if #[cfg(any(ossl111, libressl))] {
3765                let mut readbytes = 0;
3766                let ret = unsafe {
3767                    ffi::SSL_read_ex(
3768                        self.ssl().as_ptr(),
3769                        buf.as_mut_ptr().cast(),
3770                        buf.len(),
3771                        &mut readbytes,
3772                    )
3773                };
3774
3775                if ret > 0 {
3776                    Ok(readbytes)
3777                } else {
3778                    Err(self.make_error(ret))
3779                }
3780            } else {
3781                let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
3782                let ret = unsafe {
3783                    ffi::SSL_read(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len)
3784                };
3785                if ret > 0 {
3786                    Ok(ret as usize)
3787                } else {
3788                    Err(self.make_error(ret))
3789                }
3790            }
3791        }
3792    }
3793
3794    /// Like `write`, but returns an `ssl::Error` rather than an `io::Error`.
3795    ///
3796    /// It is particularly useful with a non-blocking socket, where the error value will identify if
3797    /// OpenSSL is waiting on read or write readiness.
3798    #[corresponds(SSL_write_ex)]
3799    pub fn ssl_write(&mut self, buf: &[u8]) -> Result<usize, Error> {
3800        if buf.is_empty() {
3801            return Ok(0);
3802        }
3803
3804        cfg_if! {
3805            if #[cfg(any(ossl111, libressl))] {
3806                let mut written = 0;
3807                let ret = unsafe {
3808                    ffi::SSL_write_ex(
3809                        self.ssl().as_ptr(),
3810                        buf.as_ptr().cast(),
3811                        buf.len(),
3812                        &mut written,
3813                    )
3814                };
3815
3816                if ret > 0 {
3817                    Ok(written)
3818                } else {
3819                    Err(self.make_error(ret))
3820                }
3821            } else {
3822                let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
3823                let ret = unsafe {
3824                    ffi::SSL_write(self.ssl().as_ptr(), buf.as_ptr().cast(), len)
3825                };
3826                if ret > 0 {
3827                    Ok(ret as usize)
3828                } else {
3829                    Err(self.make_error(ret))
3830                }
3831            }
3832        }
3833    }
3834
3835    /// Reads data from the stream, without removing it from the queue.
3836    #[corresponds(SSL_peek_ex)]
3837    pub fn ssl_peek(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
3838        cfg_if! {
3839            if #[cfg(any(ossl111, libressl))] {
3840                let mut readbytes = 0;
3841                let ret = unsafe {
3842                    ffi::SSL_peek_ex(
3843                        self.ssl().as_ptr(),
3844                        buf.as_mut_ptr().cast(),
3845                        buf.len(),
3846                        &mut readbytes,
3847                    )
3848                };
3849
3850                if ret > 0 {
3851                    Ok(readbytes)
3852                } else {
3853                    Err(self.make_error(ret))
3854                }
3855            } else {
3856                if buf.is_empty() {
3857                    return Ok(0);
3858                }
3859
3860                let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
3861                let ret = unsafe {
3862                    ffi::SSL_peek(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len)
3863                };
3864                if ret > 0 {
3865                    Ok(ret as usize)
3866                } else {
3867                    Err(self.make_error(ret))
3868                }
3869            }
3870        }
3871    }
3872
3873    /// Shuts down the session.
3874    ///
3875    /// The shutdown process consists of two steps. The first step sends a close notify message to
3876    /// the peer, after which `ShutdownResult::Sent` is returned. The second step awaits the receipt
3877    /// of a close notify message from the peer, after which `ShutdownResult::Received` is returned.
3878    ///
3879    /// While the connection may be closed after the first step, it is recommended to fully shut the
3880    /// session down. In particular, it must be fully shut down if the connection is to be used for
3881    /// further communication in the future.
3882    #[corresponds(SSL_shutdown)]
3883    pub fn shutdown(&mut self) -> Result<ShutdownResult, Error> {
3884        match unsafe { ffi::SSL_shutdown(self.ssl.as_ptr()) } {
3885            0 => Ok(ShutdownResult::Sent),
3886            1 => Ok(ShutdownResult::Received),
3887            n => Err(self.make_error(n)),
3888        }
3889    }
3890
3891    /// Returns the session's shutdown state.
3892    #[corresponds(SSL_get_shutdown)]
3893    pub fn get_shutdown(&mut self) -> ShutdownState {
3894        unsafe {
3895            let bits = ffi::SSL_get_shutdown(self.ssl.as_ptr());
3896            ShutdownState::from_bits_retain(bits)
3897        }
3898    }
3899
3900    /// Sets the session's shutdown state.
3901    ///
3902    /// This can be used to tell OpenSSL that the session should be cached even if a full two-way
3903    /// shutdown was not completed.
3904    #[corresponds(SSL_set_shutdown)]
3905    pub fn set_shutdown(&mut self, state: ShutdownState) {
3906        unsafe { ffi::SSL_set_shutdown(self.ssl.as_ptr(), state.bits()) }
3907    }
3908}
3909
3910impl<S> SslStream<S> {
3911    fn make_error(&mut self, ret: c_int) -> Error {
3912        self.check_panic();
3913
3914        let code = self.ssl.get_error(ret);
3915
3916        let cause = match code {
3917            ErrorCode::SSL => Some(InnerError::Ssl(ErrorStack::get())),
3918            ErrorCode::SYSCALL => {
3919                let errs = ErrorStack::get();
3920                if errs.errors().is_empty() {
3921                    self.get_bio_error().map(InnerError::Io)
3922                } else {
3923                    Some(InnerError::Ssl(errs))
3924                }
3925            }
3926            ErrorCode::ZERO_RETURN => None,
3927            ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
3928                self.get_bio_error().map(InnerError::Io)
3929            }
3930            _ => None,
3931        };
3932
3933        Error { code, cause }
3934    }
3935
3936    fn check_panic(&mut self) {
3937        if let Some(err) = unsafe { bio::take_panic::<S>(self.ssl.get_raw_rbio()) } {
3938            resume_unwind(err)
3939        }
3940    }
3941
3942    fn get_bio_error(&mut self) -> Option<io::Error> {
3943        unsafe { bio::take_error::<S>(self.ssl.get_raw_rbio()) }
3944    }
3945
3946    /// Returns a shared reference to the underlying stream.
3947    pub fn get_ref(&self) -> &S {
3948        unsafe {
3949            let bio = self.ssl.get_raw_rbio();
3950            bio::get_ref(bio)
3951        }
3952    }
3953
3954    /// Returns a mutable reference to the underlying stream.
3955    ///
3956    /// # Warning
3957    ///
3958    /// It is inadvisable to read from or write to the underlying stream as it
3959    /// will most likely corrupt the SSL session.
3960    pub fn get_mut(&mut self) -> &mut S {
3961        unsafe {
3962            let bio = self.ssl.get_raw_rbio();
3963            bio::get_mut(bio)
3964        }
3965    }
3966
3967    /// Returns a shared reference to the `Ssl` object associated with this stream.
3968    pub fn ssl(&self) -> &SslRef {
3969        &self.ssl
3970    }
3971}
3972
3973impl<S: Read + Write> Read for SslStream<S> {
3974    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
3975        // SAFETY: `read_uninit` does not de-initialize the buffer
3976        unsafe {
3977            self.read_uninit(util::from_raw_parts_mut(
3978                buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
3979                buf.len(),
3980            ))
3981        }
3982    }
3983}
3984
3985impl<S: Read + Write> Write for SslStream<S> {
3986    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
3987        loop {
3988            match self.ssl_write(buf) {
3989                Ok(n) => return Ok(n),
3990                Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
3991                Err(e) => {
3992                    return Err(e.into_io_error().unwrap_or_else(io::Error::other));
3993                }
3994            }
3995        }
3996    }
3997
3998    fn flush(&mut self) -> io::Result<()> {
3999        self.get_mut().flush()
4000    }
4001}
4002
4003/// A partially constructed `SslStream`, useful for unusual handshakes.
4004#[deprecated(
4005    since = "0.10.32",
4006    note = "use the methods directly on Ssl/SslStream instead"
4007)]
4008pub struct SslStreamBuilder<S> {
4009    inner: SslStream<S>,
4010}
4011
4012#[allow(deprecated)]
4013impl<S> SslStreamBuilder<S>
4014where
4015    S: Read + Write,
4016{
4017    /// Begin creating an `SslStream` atop `stream`
4018    pub fn new(ssl: Ssl, stream: S) -> Self {
4019        Self {
4020            inner: SslStream::new(ssl, stream).unwrap(),
4021        }
4022    }
4023
4024    /// Perform a stateless server-side handshake
4025    ///
4026    /// Requires that cookie generation and verification callbacks were
4027    /// set on the SSL context.
4028    ///
4029    /// Returns `Ok(true)` if a complete ClientHello containing a valid cookie
4030    /// was read, in which case the handshake should be continued via
4031    /// `accept`. If a HelloRetryRequest containing a fresh cookie was
4032    /// transmitted, `Ok(false)` is returned instead. If the handshake cannot
4033    /// proceed at all, `Err` is returned.
4034    #[corresponds(SSL_stateless)]
4035    #[cfg(ossl111)]
4036    pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
4037        match unsafe { ffi::SSL_stateless(self.inner.ssl.as_ptr()) } {
4038            1 => Ok(true),
4039            0 => Ok(false),
4040            -1 => Err(ErrorStack::get()),
4041            _ => unreachable!(),
4042        }
4043    }
4044
4045    /// Configure as an outgoing stream from a client.
4046    #[corresponds(SSL_set_connect_state)]
4047    pub fn set_connect_state(&mut self) {
4048        unsafe { ffi::SSL_set_connect_state(self.inner.ssl.as_ptr()) }
4049    }
4050
4051    /// Configure as an incoming stream to a server.
4052    #[corresponds(SSL_set_accept_state)]
4053    pub fn set_accept_state(&mut self) {
4054        unsafe { ffi::SSL_set_accept_state(self.inner.ssl.as_ptr()) }
4055    }
4056
4057    /// See `Ssl::connect`
4058    pub fn connect(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4059        match self.inner.connect() {
4060            Ok(()) => Ok(self.inner),
4061            Err(error) => match error.code() {
4062                ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4063                    Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4064                        stream: self.inner,
4065                        error,
4066                    }))
4067                }
4068                _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4069                    stream: self.inner,
4070                    error,
4071                })),
4072            },
4073        }
4074    }
4075
4076    /// See `Ssl::accept`
4077    pub fn accept(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4078        match self.inner.accept() {
4079            Ok(()) => Ok(self.inner),
4080            Err(error) => match error.code() {
4081                ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4082                    Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4083                        stream: self.inner,
4084                        error,
4085                    }))
4086                }
4087                _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4088                    stream: self.inner,
4089                    error,
4090                })),
4091            },
4092        }
4093    }
4094
4095    /// Initiates the handshake.
4096    ///
4097    /// This will fail if `set_accept_state` or `set_connect_state` was not called first.
4098    #[corresponds(SSL_do_handshake)]
4099    pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4100        match self.inner.do_handshake() {
4101            Ok(()) => Ok(self.inner),
4102            Err(error) => match error.code() {
4103                ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4104                    Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4105                        stream: self.inner,
4106                        error,
4107                    }))
4108                }
4109                _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4110                    stream: self.inner,
4111                    error,
4112                })),
4113            },
4114        }
4115    }
4116
4117    /// Read application data transmitted by a client before handshake
4118    /// completion.
4119    ///
4120    /// Useful for reducing latency, but vulnerable to replay attacks. Call
4121    /// `set_accept_state` first.
4122    ///
4123    /// Returns `Ok(0)` if all early data has been read.
4124    ///
4125    /// Requires OpenSSL 1.1.1 or newer or LibreSSL.
4126    #[corresponds(SSL_read_early_data)]
4127    #[cfg(any(ossl111, libressl))]
4128    pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4129        self.inner.read_early_data(buf)
4130    }
4131
4132    /// Send data to the server without blocking on handshake completion.
4133    ///
4134    /// Useful for reducing latency, but vulnerable to replay attacks. Call
4135    /// `set_connect_state` first.
4136    ///
4137    /// Requires OpenSSL 1.1.1 or newer or LibreSSL.
4138    #[corresponds(SSL_write_early_data)]
4139    #[cfg(any(ossl111, libressl))]
4140    pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
4141        self.inner.write_early_data(buf)
4142    }
4143}
4144
4145#[allow(deprecated)]
4146impl<S> SslStreamBuilder<S> {
4147    /// Returns a shared reference to the underlying stream.
4148    pub fn get_ref(&self) -> &S {
4149        unsafe {
4150            let bio = self.inner.ssl.get_raw_rbio();
4151            bio::get_ref(bio)
4152        }
4153    }
4154
4155    /// Returns a mutable reference to the underlying stream.
4156    ///
4157    /// # Warning
4158    ///
4159    /// It is inadvisable to read from or write to the underlying stream as it
4160    /// will most likely corrupt the SSL session.
4161    pub fn get_mut(&mut self) -> &mut S {
4162        unsafe {
4163            let bio = self.inner.ssl.get_raw_rbio();
4164            bio::get_mut(bio)
4165        }
4166    }
4167
4168    /// Returns a shared reference to the `Ssl` object associated with this builder.
4169    pub fn ssl(&self) -> &SslRef {
4170        &self.inner.ssl
4171    }
4172
4173    /// Set the DTLS MTU size.
4174    ///
4175    /// It will be ignored if the value is smaller than the minimum packet size
4176    /// the DTLS protocol requires.
4177    ///
4178    /// # Panics
4179    /// This function panics if the given mtu size can't be represented in a positive `c_long` range
4180    #[deprecated(note = "Use SslRef::set_mtu instead", since = "0.10.30")]
4181    pub fn set_dtls_mtu_size(&mut self, mtu_size: usize) {
4182        unsafe {
4183            let bio = self.inner.ssl.get_raw_rbio();
4184            bio::set_dtls_mtu_size::<S>(bio, mtu_size);
4185        }
4186    }
4187}
4188
4189/// The result of a shutdown request.
4190#[derive(Copy, Clone, Debug, PartialEq, Eq)]
4191pub enum ShutdownResult {
4192    /// A close notify message has been sent to the peer.
4193    Sent,
4194
4195    /// A close notify response message has been received from the peer.
4196    Received,
4197}
4198
4199bitflags! {
4200    /// The shutdown state of a session.
4201    #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
4202    #[repr(transparent)]
4203    pub struct ShutdownState: c_int {
4204        /// A close notify message has been sent to the peer.
4205        const SENT = ffi::SSL_SENT_SHUTDOWN;
4206        /// A close notify message has been received from the peer.
4207        const RECEIVED = ffi::SSL_RECEIVED_SHUTDOWN;
4208    }
4209}
4210
4211use ffi::{SSL_CTX_up_ref, SSL_SESSION_get_master_key, SSL_SESSION_up_ref, SSL_is_server};
4212cfg_if! {
4213    if #[cfg(ossl300)] {
4214        use ffi::SSL_get1_peer_certificate;
4215    } else {
4216        use ffi::SSL_get_peer_certificate as SSL_get1_peer_certificate;
4217    }
4218}
4219use ffi::{
4220    DTLS_client_method, DTLS_method, DTLS_server_method, TLS_client_method, TLS_method,
4221    TLS_server_method,
4222};
4223cfg_if! {
4224    if #[cfg(ossl110)] {
4225        unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4226            ffi::CRYPTO_get_ex_new_index(
4227                ffi::CRYPTO_EX_INDEX_SSL_CTX,
4228                0,
4229                ptr::null_mut(),
4230                None,
4231                None,
4232                Some(f),
4233            )
4234        }
4235
4236        unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4237            ffi::CRYPTO_get_ex_new_index(
4238                ffi::CRYPTO_EX_INDEX_SSL,
4239                0,
4240                ptr::null_mut(),
4241                None,
4242                None,
4243                Some(f),
4244            )
4245        }
4246    } else {
4247        use std::sync::Once;
4248
4249        unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4250            // hack around https://rt.openssl.org/Ticket/Display.html?id=3710&user=guest&pass=guest
4251            static ONCE: Once = Once::new();
4252            ONCE.call_once(|| {
4253                cfg_if! {
4254                    if #[cfg(not(any(boringssl, awslc)))] {
4255                        ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, None);
4256                    } else {
4257                        ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
4258                    }
4259                }
4260            });
4261
4262            cfg_if! {
4263                if #[cfg(not(any(boringssl, awslc)))] {
4264                    ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, Some(f))
4265                } else {
4266                    ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f)
4267                }
4268            }
4269        }
4270
4271        unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4272            // hack around https://rt.openssl.org/Ticket/Display.html?id=3710&user=guest&pass=guest
4273            static ONCE: Once = Once::new();
4274            ONCE.call_once(|| {
4275                #[cfg(not(any(boringssl, awslc)))]
4276                ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, None);
4277                #[cfg(any(boringssl, awslc))]
4278                ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
4279            });
4280
4281            #[cfg(not(any(boringssl, awslc)))]
4282            return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, Some(f));
4283            #[cfg(any(boringssl, awslc))]
4284            return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f);
4285        }
4286    }
4287}