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