Skip to main content

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